erro de formato execvp exec para script de shell no Red Hat Enterprise Linux 6

erro de formato execvp exec para script de shell no Red Hat Enterprise Linux 6

Temos dois sistemas RHEL 6 que executam versões idênticas do kernel e glibc (glibc–2.12–1.90.el6_3.6). De acordo com o padrão POSIX e as páginas de manual do Linux, se o kernel determinar que um arquivo executável não está em um formato executável como ELF e não possui uma #!linha shebang (), as funções execl, execlp, execle, execv, execvp, e execvpe(mas not execve) tentará executar esse arquivo usando um shell POSIX, que no Linux é /bin/sh.

Porém, em um dos sistemas, a execução de um script de shell cuja primeira linha está :usando a função execvpfalha, enquanto na outra máquina o script é executado usando /bin/sh, conforme esperado. Especificamente, estamos usando estes programas de teste; /tmp/test_scripté tornado executável:

xc:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

char externo **ambiente;

int principal() {
        char *argv[] = { "/tmp/test_script", NULL };
        char *nome do programa = argv[0];
        if (execvp(nome do programa, argv) == -1) {
                perror("execvp");
                retornar -1;
        }
}

/tmp/test_script:

:

echo "Script de teste chamado"
saída 0

Procuramos no RPM de origem a versão instalada do glibc e ele definitivamente implementa o comportamento desejado (execvp é um wrapper trivial em torno do execvpe):

posix/execvpe.c:

if (strchr(arquivo, '/') != NULL)
    {
        /* Não pesquisa quando contém uma barra. */
        __execve(arquivo,argv,envp);

        if (erro == ENOEXEC)
            {
                /* Conta os argumentos. */
                int argc = 0;
                enquanto (argv[argc++])
                    ;
                tamanho_t len ​​= (argc + 1) * sizeof(char *);
                char **script_argv;
                vazio *ptr = NULO;
                if (__libc_use_alloca(len))
                    script_argv = aloca(len);
                outro
                    script_argv = ptr = malloc(len);

                se (script_argv! = NULO)
                    {
                        scripts_argv(arquivo, argv, argc, script_argv);
                        __execve(script_argv[0], script_argv, envp);

                        grátis(ptr);
                    }
            }
    }
outro
   ︙

Aqui scripts_argvestá uma função simples que antecede /bin/sha lista de argumentos e __execveé idêntica àquela execveque é exposta ao espaço do usuário via glibc.

Alguém mais encontrou esse problema no Linux? O comportamento está correto em todos os outros sistemas em que experimentei.

Responder1

Tudo bem, descobri o que estava causando o problema. Depois de compilar o x.cexecutável, executei ldd-o e descobri que havia uma biblioteca liboit.sovinculada dinamicamente ao executável. Esta biblioteca foi instalada peloAuditor Unix ObserveIT, que intercepta todas as atividades dos usuários logados, incluindo chamadas do sistema. Porém, eu acho que apenas interceptar chamadas do sistema não resultaria no comportamento observado, já que a reexecução /bin/shé feita dentro da glibc. Talvez o ObserveIT também emule funções POSIX, aparentemente não conformes nesta situação.

informação relacionada