
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 execvp
falha, 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_argv
está uma função simples que antecede /bin/sh
a lista de argumentos e __execve
é idêntica àquela execve
que é 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.c
executável, executei ldd
-o e descobri que havia uma biblioteca liboit.so
vinculada 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.