Почему нечитаемый ELF на linux может быть запущен? - PullRequest
0 голосов
/ 10 сентября 2018

Я понимаю, что скрипт не может быть запущен, если он не читается (даже если он исполняемый), потому что его должен прочитать читатель.

Но почему на linux можно запустить нечитаемый двоичный файл (я использую gcc, чтобы скомпилировать мой код в ./my_exe и установить для него разрешение 0100)? Выполнение двоичного файла всегда вызывает некоторое чтение, верно? Тогда я читаю это Можно ли прочитать исполняемый файл? , но у меня все еще есть некоторые вопросы.

execve (2) говорит мне, что ядро ​​вызовет /lib/ld-linux.so.2 для запуска программы (я использую readelf для проверки, у него есть сегмент INTERP, который равен /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. Я просто получаю сообщение, что он не может загрузить общий объект. Но когда я запускаю его прямо из bash, например ./my_exe, он запускается успешно.

Мой вопрос: поскольку выполнение ELF включает ld-linux-x86-64.so.2, почему моя скомпилированная программа с разрешением 0100 может быть запущена напрямую? ld-linux-x86-64.so.2 не должен быть в состоянии прочитать его, поэтому он не должен уметь читать GOT и выполнять динамическое связывание. Так почему же я запустил его напрямую?

1 Ответ

0 голосов
/ 10 сентября 2018

ld.so является частью вашего двоичного адресного пространства, оно загружается ядром с целью загрузки других (динамических) библиотек. Почему он должен читать ваш двоичный файл с диска, когда он уже загружен в память ядром? Получается, что ld.so ничего не читает и, следовательно, не проходит проверку безопасности.

Вы имели в виду, что когда ядро ​​выполнит execve, оно выполнит mmap для обоих PT_INTERP и сам эльф с надлежащим разрешением (например, сделать GOT легко читаемый)

Да, вы можете проверить это самостоятельно здесь

 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);  
...