
У нас есть две системы RHEL 6, на которых запущены идентичные версии ядра и glibc (glibc–2.12–1.90.el6_3.6). Согласно стандарту POSIX и страницам руководства Linux, если ядро определяет, что исполняемый файл не находится в исполняемом формате, например ELF, и не имеет #!
строки shebang ( ), функции execl
, execlp
, execle
, execv
, execvp
, и execvpe
(но не execve
) попытаются выполнить этот файл с помощью оболочки POSIX, которая в Linux называется /bin/sh
.
Однако на одной из систем выполнение скрипта оболочки, первая строка которого использует :
функцию, execvp
завершается неудачей, тогда как на другой машине скрипт выполняется с использованием /bin/sh
, как и ожидалось. В частности, мы используем эти тестовые программы; /tmp/test_script
становится исполняемым:
хс:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> внешний символ **среда; инт мейн () { char *argv[] = { "/tmp/test_script", NULL }; char *имя_программы = argv[0]; если (execvp(имя_программы, argv) == -1) { perror("execvp"); возврат -1; } }
/tmp/test_script:
: echo "Вызван тестовый скрипт" выход 0
Мы выполнили поиск в исходном RPM-пакете установленной версии glibc, и она определенно реализует желаемое поведение (execvp — это тривиальная оболочка вокруг execvpe):
posix/execvpe.c:
если (strchr(файл, '/') != NULL) { /* Не выполнять поиск, если он содержит косую черту. */ __execve(файл, argv, envp); если (errno == ENOEXEC) { /* Подсчитаем аргументы. */ int argc = 0; пока (argv[argc++]) ; size_t len = (argc + 1) * sizeof(char *); символ **script_argv; void *ptr = NULL; если (__libc_use_alloca(len)) script_argv = alloca(len); еще script_argv = ptr = malloc(len); если (script_argv != NULL) { scripts_argv(файл, argv, argc, script_argv); __execve(script_argv[0], script_argv, envp); бесплатно(ptr); } } } еще ︙
Здесь scripts_argv
представлена простая функция, которая добавляется /bin/sh
к списку аргументов и __execve
идентична той execve
, которая предоставляется пользовательскому пространству через glibc.
Кто-нибудь еще сталкивался с этой проблемой на Linux? Поведение корректное на всех других системах, на которых я это пробовал.
решение1
Хорошо, я обнаружил, что вызывало проблему. После компиляции x.c
исполняемого файла я запустил ldd
его и обнаружил, что к исполняемому файлу динамически подключена библиотека liboit.so
. Эта библиотека была установленаАудитор Unix ObserveIT, который перехватывает всю активность вошедших в систему пользователей, включая системные вызовы. Однако я думаю, что просто перехват системных вызовов не приведет к наблюдаемому поведению, поскольку повторное выполнение /bin/sh
выполняется внутри glibc. Возможно, ObserveIT также эмулирует функции POSIX, что, по-видимому, не соответствует данной ситуации.