Ошибка формата execvp exec для сценария оболочки в Red Hat Enterprise Linux 6

Ошибка формата execvp exec для сценария оболочки в Red Hat Enterprise Linux 6

У нас есть две системы 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, что, по-видимому, не соответствует данной ситуации.

Связанный контент