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

时间:2018-09-20 14:13:46

标签: linux linux-kernel executable file-permissions execve

了解Linux内核有关execve()的实现:

  

do_execve( )执行以下操作:

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

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

  4.   
  5. 验证文件是否可以被当前进程执行;另外,通过查看   i_writecount的{​​{1}}字段;在该字段中存储–1禁止   进一步的写访问。

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

  8.   
  9. 调用sched_exec()来检查当前进程是否正在使用自定义的本地描述符表(请参见“ Linux   LDT”)。在这种情况下,该函数分配并填充一个   新程序将使用的新LDT。

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

         

    a。 再次检查文件是否可执行(至少执行一次)   设置访问权限);如果不是,则返回错误代码。 (上一个   检查第3步还不够,因为使用   linux_binprm功能集始终满足检查要求;看到   本节前面的“过程凭证和功能”部分   一章)。

  12.   
     

...

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

他们之间有什么区别和关系?

步骤3a是否没有考虑到步骤3的CAP_DAC_OVERRIDE能力?这是两个步骤之间的唯一区别吗?

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

谢谢。

1 个答案:

答案 0 :(得分:0)

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

所以到更具体的位:

  • 这应该防止什么? =>可能会根错误地执行不可执行的二进制文件
  • 为什么不签入3? =>这将重用更常规的操作-带标志打开-如果有能力,该操作应该会成功
  • 为什么不在6中进行所有检查? => 3是否进行了许多在这里不切实际的检查,例如“我们在使用noexec挂载的fs吗?”

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