为什么Linux上的不可读ELF可以运行?

问题描述 投票:1回答:1

我理解如果脚本不可读(即使它是可删除的),也无法运行脚本,因为解释器需要读取它。

但是为什么Linux上可以运行一个不可读的二进制文件(我使用gcc将我的代码编译成./my_exe并将其设置为0100权限)?执行二进制文件总是会读取一些读数,对吗?然后我读了这个Can a file that is executable be read?,但我脑子里仍然有一些问题。

execve(2)告诉我,内核将调用/lib/ld-linux.so.2来运行程序(我使用readelf来检查,它有DOP段,这是/lib64/ld-linux-x86-64.so.2),所以我认为/lib64/ld-linux-x86-64.so.2是用户空间ELF加载器(它做动态链接和mmap ELF)进入记忆)。由于我无法读取ELF,我认为我不应该运行它,因为运行它需要读取它的GOT来进行动态链接。事实证明,我真的不能像/lib64/ld-linux-x86-64.so.2 my_exe那样运行它。我只是得到它无法加载共享对象的消息。但是当我像./my_exe那样直接从bash运行它时,它运行成功。

我的问题是:由于执行ELF涉及ld-linux-x86-64.so.2,为什么我的编译程序具有0100权限可以直接运行? ld-linux-x86-64.so.2应该无法读取它,因此它不应该能够读取GOT并进行动态链接。那我为什么要成功直接运行呢?

linux linux-kernel elf
1个回答
2
投票

ld.so是二进制地址空间的一部分,它由内核加载,目的是加载其他(动态)库。当内核已经将内存加载到内存中时,为什么它应该从磁盘中读取它?因此,ld.so不会读取任何内容,因此不会通过安全检查。

你的意思是,当内核执行时,它会为PT_INTERP和ELF本身做适当的权限mmap(比如使GOT可读地编码)

是的,你可以自己检查here

 static int load_elf_binary(struct linux_binprm *bprm)
    ...
 if (elf_interpreter) {                                                      
         unsigned long interp_map_addr = 0;                                      

         elf_entry = load_elf_interp(&loc->interp_elf_ex,                        
                          interpreter,                                            
                         &interp_map_addr,                                       
                          load_bias, interp_elf_phdata);  
© www.soinside.com 2019 - 2024. All rights reserved.