繁体   English   中英

为什么do_execve()分两步而不是一步来执行可执行文件验证检查?

[英]Why does do_execve() perform executable verification check in two steps instead of one?

了解Linux内核说明了execve()的实现:

do_execve( )执行以下操作:

  1. 动态分配linux_binprm数据结构,该结构将填充有关新的可执行文件的数据。

  2. 调用path_lookup(), dentry_open()path_release()以获得与可执行文件关联的dentry对象,文件对象和inode对象。 失败时,它将返回正确的错误代码。

  3. 验证文件当前进程是否可执行 另外,通过查看inodei_writecount字段来检查是否正在写入文件; 在该字段中存储–1以禁止进一步的写访问。

  4. 在多处理器系统中,它调用sched_exec()函数来确定可以执行新程序的负载最小的CPU,并将当前进程迁移到该程序(请参见第7章)。

  5. 调用init_new_context()来检查当前进程是否正在使用自定义的本地描述符表(请参阅第2章中的“ Linux LDT”部分); 在这种情况下,该函数分配并填充新的LDT以供新程序使用。

  6. 调用prepare_binprm( )函数来填充linux_binprm数据结构。 该功能依次执行以下操作:

    一种。 再次检查文件是否可执行(设置了至少一个执行访问权限) 如果不是,则返回错误代码。 步骤3中的上一个检查是不够的,因为设置了CAP_DAC_OVERRIDE功能的进程始终可以满足该检查;请参阅本章前面的“进程凭据和功能”部分)。

...

步骤3和步骤6a是否都执行验证检查,以确保为该进程设置了可执行文件的执行许可位?

他们有什么区别和关系?

第3步没有考虑到进程的CAP_DAC_OVERRIDE容量,而第6a步却考虑了吗? 这是两个步骤之间的唯一区别吗?

为什么我们需要两步检查,而不是通过将所有检查合并到步骤3或步骤6a中来进行单步检查?

谢谢。

您可以并且应该阅读内核源代码本身(位于fs / exec.c中)。 步骤2和3基本上是在调用带有特殊EXEC标志“打算执行的打开文件”的通用打开功能,而第二个检查是一系列检查“新进程应具有的权利”的一部分。

所以到更具体的位:

  • 这应该防止什么? =>可能会以root身份错误地执行不可执行的二进制文件
  • 为什么不检查3? =>这将重用更通用的操作-带标志打开-如果有能力,该操作应会成功
  • 为什么不在6中进行所有检查? => 3还有很多其他的检查在这里是不切实际的,例如“我们在noexec挂载的fs上吗?”

无论如何,您的问题有点太开放了,不确定我的答案会满足您的要求。 请去阅读内核源代码。 :-)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM