为什么 Bash 的源代码不需要执行位?

Mot*_*001 63 bash source permissions conventions executable

与 Bash 的 source可以在不设置执行位的情况下执行脚本。这是记录在案的预期行为,但这不是反对使用执行位吗?

我知道,这source不会创建子shell。

cuo*_*glm 57

source或等效但标准的.不执行脚本,而是从脚本文件中读取命令,然后在当前 shell 环境中逐行执行它们。

没有什么反对使用执行位的,因为shell 只需要权限来读取文件的内容。

只有在运行脚本时才需要执行位。在这里,shell 将fork()新进程然后使用execve()函数从脚本创建新的进程映像,该映像需要是常规的可执行文件。

  • @alexis,检查它解释的脚本的权限不是解释器的工作。**没有**这样做——不是 Python,不是 Ruby,不是 Java 虚拟机,不是其他随机 shell。执行位控制操作系统`execv`* 系列系统调用是否可以与可执行文件一起使用,而不是解释器是否会运行它。为什么要通过打破约定来混淆人们(并破坏评估从非文件源流式传输的代码的能力)? (27认同)
  • @alexis,...此外,拥有一个不可执行的 shell 库还有一个很有价值的意义:它说“我是一个库,而不是一个命令——来源我,不要执行我”。否则,您将需要编写代码来检测和修复旨在仅获取源代码的滥用,但通过没有 +x 权限,您可以确保用户不能(不会)以这种方式滥用库。 (14认同)
  • @alexis“这是作者的决定”只是在某种意义上说,未包含的所有其他可能的代码位都是一个决定。shell 打开文件进行读取,从中读取命令。我不希望它检查读取权限,它只是尝试打开文件,如果不能打开就会失败。同样,它不检查写入或执行权限,因为这些检查与读取文件无关。 (6认同)
  • @alexis:我不确定我是否真的遵循。如果你执行 `bash < script`,你会得到与 `source script` 基本相同的结果。执行位检查提供什么保护? (5认同)
  • @alexis 这在实践中使用,例如使用 python 的 virtualenv,激活它的脚本是源代码,而不是执行,因此 `bin/activate` 没有可执行位。脚本完全可以是库或其他类似的东西。我想拥有 .sh 也可能是一个信号,但是拥有最少的足枪是好的:很高兴不可能意外地运行 `./bin/activate` 而不是 `。垃圾箱/激活` (2认同)

200*_*ess 41

Bash 是一个解释器;它接受输入并做任何它想做的事情。它不需要注意可执行位。事实上,Bash 是可移植的,可以在没有任何可执行位概念的操作系统和文件系统上运行。

关心可执行位的是操作系统内核。exec例如,当 Linux 内核执行noexec.

请注意,可执行位是一种相当随意的控制。例如,在 Linux x86-64 系统上,您可以通过显式调用/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2解释器来绕过内核对可执行位的验证:

cp /bin/ls /tmp/
chmod -x /tmp/ls
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 /tmp/ls
Run Code Online (Sandbox Code Playgroud)

这有点类似于在 Bash 中获取 Bash 源代码,不同之处在于它ld.so是解释器,并且它执行的代码是 ELF 格式的机器代码。

  • 使用加载器作为“字节码”的“解释器”,它恰好是一个真正的可执行二进制文件......太棒了。谢谢你。 (4认同)
  • @JFSebastian 是的,我们知道它是本机代码,因此“解释器”用引号引起来。`ld.so` 的工作是做动态链接。 (2认同)

PSk*_*cik 20

nonsetuid 和 nonsetguid 文件上的可执行位(与其余部分不同)并不是什么安全机制。您可以读取的任何内容,都可以间接运行,而 Linux 将让您间接读取您可以运行但不能直接读取的任何内容(这应该足以在 non-set(g)uid x-bit 作为安全措施)。

这更像是一件方便的事情:如果设置了该位,让系统直接为我运行它,否则我需要间接执行(bash the_script;或一些黑客行为以获取无读取权限的可执行文件的内存映像)。

如果您打算在源代码中同时执行您的资源,您可以设置它以方便使用。

然而,显然,许多共享库实现者同意您的想法,因此,许多系统确实要求共享库(本质上是 shell insourcables 的本机等价物)标记为可执行以供使用。请参阅为什么共享库是可执行的?.

  • @Motte001 如果他们真的愿意,他们可以执行这些附件。这是一种方便。 (3认同)
  • 我们*需要*可执行位的原因之一是运行 setuid 程序,特别是那些由 root 拥有的程序。虽然您当然可以自己执行它们,但您需要操作系统来运行它们,以便它们具有必要的权限。在其他一些情况下,它确实只是一种方便。 (3认同)
  • 可执行位不是为了安全:如果我拥有一个文件,我可以自由地对其进行“chmod”并使其可执行。它用于对程序中的数据进行排序,因此 OP 的问题是合理的。 (2认同)
  • _“Linux 可以让你阅读任何你可以通过 /proc 运行的东西”_——好吧,我的 Debian 内核没有:`/tmp$ cp /bin/cat ./cat ; chmod a-rw ./cat ; ./cat & cp /proc/$!/exe /tmp/cat2` -> `cp: cannot stat '/proc/16260/exe': Permission denied` (2认同)

ale*_*xis 9

这是个好问题!Unix 使用可执行位来区分程序和数据。操作系统不需要执行位,因为源脚本不会作为新进程传递给操作系统以执行。但是 shell 将源脚本视为程序,并将查看$PATH您要获取的文件。因此,shell 本身可能需要对源文件的执行权限;但它没有。

这个问题应该是很久以前提出来的。Bourne shell 的设计是贝尔实验室居民“经过长时间的修改、对话、讨论”的结果,多年来,SR Bourne 和其他人讨论了许多设计决策。不幸的是,我的快速浏览没有找到任何关于源功能的讨论(在我的辩护中,很难用谷歌搜索它)。我确实发现了“。” 命令没有出现在Bourne 本人对 shell 的早期介绍中,但它出现在更成熟的Version 7 版本中

没有权威,这是我自己的解释:

  1. .命令,又名source,实际上是将文本包含#include在执行脚本或交互式会话的源代码中(就像在 C 预处理器中一样)。因此,包含的文件可以说没有被“执行”。

  2. Unix 哲学一直是给程序员足够的绳子让他们上吊。太多的牵手和随意的限制只会阻碍。直到最近,一些发行版才rm -r /拒绝执行您的要求。(此命令告诉您rm删除计算机上的所有内容。 不要以 root 身份尝试!或者更好,根本不要。)所以,也许 Bourne 等人。刚刚决定,当您尝试获取文件的来源时,假定您知道自己在做什么。这也避免了不必要的工作,当时周期很重要。