使用Bash source
,可以在不设置执行位的情况下执行脚本。这是有据可查的并且是预期的行为,但这不是反对使用执行位吗?
我知道,这source
不会创建子外壳。
cp /sbin/suidexecutable /tmp/mycopy; /tmp/mycopy
使用Bash source
,可以在不设置执行位的情况下执行脚本。这是有据可查的并且是预期的行为,但这不是反对使用执行位吗?
我知道,这source
不会创建子外壳。
cp /sbin/suidexecutable /tmp/mycopy; /tmp/mycopy
Answers:
Bash是一名口译员;它接受输入并做任何想做的事情。不需要注意可执行位。实际上,Bash是可移植的,并且可以在没有可执行位概念的操作系统和文件系统上运行。
关心可执行位的是操作系统内核。exec
例如,当Linux内核执行时,它将检查是否未通过noexec
选项安装文件系统,并检查程序文件的可执行位,并强制执行由安全模块(例如SELinux或AppArmor)施加的任何要求。
请注意,可执行位是一种相当随意的控制类型。例如,在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
这有点类似于在Bash中采购Bash源代码,除了它ld.so
是解释器,并且它执行的代码是ELF格式的机器代码。
ld.so
是进行动态链接。
source
或等效但标准的点.
不执行脚本,而是从脚本文件中读取命令,然后在当前Shell环境中逐行执行它们。
没有什么反对执行位的使用,因为外壳只需要具有读取权限才能读取文件的内容。
只有在运行脚本时才需要执行位。在这里,shell将fork()
新建一个进程,然后使用execve()
函数从脚本创建新的进程映像,该脚本必须是常规的可执行文件。
bash < script
,您得到的结果基本上与相同source script
。执行位检查提供什么保护?
execv
*系列的syscall 是否可与可执行文件一起使用,而不控制解释器是否将其运行。为什么通过破坏约定使人们感到困惑(并破坏评估非文件源流代码的能力)?
bin/activate
没有可执行位。脚本可以完全是库或类似的东西。我想拥有.sh也可能是一个信号,但是拥有最少的步枪还是不错的:很好的是,不可能./bin/activate
偶然发生而不是. bin/activate
nonsetuid和nonsetguid文件上的可执行位(与其余部分不同)不是一种安全机制。您可以读取的任何内容都可以间接运行,Linux可以让您间接读取您可以运行但不能直接读取的任何内容(这足以在非set(g)uid x位概念上打一个洞。安全措施)。
更为方便的是:如果该位置1,则让系统直接为我运行它,否则,我需要间接进行此操作(bash the_script;
或进行某些破解以获取未读取权限的可执行文件的内存映像)。
如果您打算同时在源代码中和执行可采购的产品,则可以将其设置为方便。
但是,显然,许多共享库的实现者会分享您的想法,因此,许多系统的确要求共享库(本质上等同于外壳不可采购产品)必须标记为可执行才能使用。请参阅为什么共享库可执行?。
chmod
则可以自由使用它并使其可执行。它用于对程序中的数据进行排序,因此OP的问题是一个合理的问题。
x
位只是一个额外的地方,它可以读取/写入操作提示。
/tmp$ cp /bin/cat ./cat ; chmod a-rw ./cat ; ./cat & cp /proc/$!/exe /tmp/cat2
->cp: cannot stat ‘/proc/16260/exe’: Permission denied
这是个好问题!Unix使用可执行位来区分程序和数据。OS不需要执行位,因为源脚本不会作为新进程传递给OS来执行。但是外壳程序将源脚本视为程序,并会查找$PATH
您要源文件。因此,shell本身可能需要对源文件的执行权限。但事实并非如此。
这个问题一定是很久以前提出的。Bourne外壳的设计是Bell Labs居民之间“经过长时间的修改,对话,讨论”的结果,多年来,SR Bourne等人讨论了许多设计决策。不幸的是,我的快速浏览没有找到任何有关源功能的讨论(以我的辩护,很难用它来搜索它)。我确实发现的是“。” Bourne自己对Shell的早期介绍中未出现该命令,但在更成熟的Version 7版本中提供了该命令。
没有权限,这是我自己的解释:
的.
命令,又名source
,实际上是文本列入(如#include
在C预处理)到执行脚本或交互式会话的源代码。这样,可以说所包含的文件没有被“执行”。
Unix的哲学一直是给予程序员足够的能力来吊死自己。太多的手动操作和随意的限制只会妨碍您的操作。只是在最近,一些发行版本rm -r /
拒绝执行您的要求。(此命令告诉rm
您删除计算机上的所有内容。 请勿以root用户身份尝试它!或者更好的是,根本不要尝试。)因此,也许是Bourne。刚决定,当您尝试获取文件源时,假定您知道自己在做什么。这也避免了不必要的工作,从那时起周期就变得很重要。
以防万一有人对进一步的研究和/或澄清感兴趣:在不久前实现的与POSIX兼容的外壳中,'exec_program()'和'builtin_source()'函数的内部工作非常具有示范性。在这些函数中,您确切地看到它们之间的区别是什么:
https://github.com/rsenn/shish/blob/master/src/builtin/builtin_source.c
https://github.com/rsenn/shish/blob/master/src/exec/exec_program.c
基本上,源代码可以看作是Shell临时重定向其内部文件描述符,在此它从中解析shell脚本(交互模式下的终端)。因此它与之类的其他重定向非常相似<input_file.txt
,>>append_to_something.list
而这些重定向仅需要打开和关闭文件。
因此执行是由execve()
强制执行位的系统调用来处理的。
我记得曾经看到一些系统允许执行ELF / a.out二进制文件,但是通过执行“ /lib/ld-dynamic-linker.so”并使用二进制程序(无exec位)作为第一个参数来执行。我相信这是在某些DEC Alpha或VAX机器上的(可能是SCO Unix吗?)
另一个角度来看:
源脚本基本上由shell内置程序和程序调用组成。Shell内置程序(source
包括它们)是Shell的一部分,并且该Shell必须首先是可执行的。每个调用的程序(即ELF,带有shebang的另一个脚本,无论如何)都必须设置执行位,否则它将无法运行。
因此,这并不反对使用执行位,因为没有执行位的任何内容都不会运行。整个源脚本都不会进行验证。它是针对每个部分分别执行的,但是确实如此。
chmod
可以让您使用八进制数字设置权限(包括`x)的事实为您提供了它来自哪个时代的线索。从它被发明之前的日子开始,如果它以快速而肮脏的“这是一个可以执行的二进制文件”指示开始,我不会感到惊讶,但是我没有任何证据