
동일한 버전의 커널과 glibc(glibc–2.12–1.90.el6_3.6)를 실행하는 두 개의 RHEL 6 시스템이 있습니다. POSIX 표준과 Linux 매뉴얼 페이지에 따르면, 커널이 실행 파일이 ELF와 같은 실행 가능 형식이 아니고 shebang( ) 줄이 없다고 판단하면 #!
함수 execl
, execlp
, execle
, execv
, execvp
및 execvpe
(그러나 not execve
)은 Linux의 POSIX 쉘을 사용하여 해당 파일을 실행하려고 시도합니다 /bin/sh
.
그러나 시스템 중 하나에서는 첫 번째 줄에서 :
함수를 사용 하는 쉘 스크립트를 실행하는 데 execvp
실패하고, 다른 시스템에서는 스크립트가 /bin/sh
예상대로 를 사용하여 실행됩니다. 특히 우리는 이러한 테스트 프로그램을 사용하고 있습니다. /tmp/test_script
실행 가능해졌습니다:
xc:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> 외부 char **환경; 정수 메인 () { char *argv[] = { "/tmp/test_script", NULL }; char *progname = argv[0]; if (execvp(progname, argv) == -1) { perror("execvp"); -1을 반환합니다. } }
/tmp/테스트_스크립트:
: echo "테스트 스크립트 호출됨" 0번 출구
설치된 glibc 버전에 대한 소스 RPM을 검색한 결과 원하는 동작이 확실히 구현되었습니다(execvp는 execvpe를 둘러싼 간단한 래퍼입니다).
posix/execvpe.c:
if (strchr(파일, '/') != NULL) { /* 슬래시가 포함된 경우 검색하지 마세요. */ __execve(파일, argv, envp); if (errno == ENOEXEC) { /* 인수의 개수를 셉니다. */ int 인수 = 0; 동안(argv[argc++]) ; size_t len = (argc + 1) * sizeof(char *); char **script_argv; 무효 *ptr = NULL; if (__libc_use_alloca(len)) script_argv = alloca(len); 또 다른 script_argv = ptr = malloc(len); if (script_argv != NULL) { scripts_argv(파일, argv, argc, script_argv); __execve(script_argv[0], script_argv, envp); 무료(ptr); } } } 또 다른 ︙
여기에 인수 목록 앞에 scripts_argv
추가되는 간단한 함수가 있으며 glibc를 통해 사용자 공간에 노출되는 것과 동일합니다 ./bin/sh
__execve
execve
Linux에서 이 문제를 겪은 사람이 있습니까? 내가 시도한 다른 모든 시스템에서는 동작이 정확했습니다.
답변1
알겠습니다. 문제의 원인을 발견했습니다. x.c
실행 파일을 컴파일한 후 실행해 보니 실행 파일에 동적으로 연결된 ldd
라이브러리가 있다는 것을 발견했습니다 . liboit.so
이 라이브러리는 다음에서 설치했습니다.ObserveIT Unix 감사자, 시스템 호출을 포함하여 로그인한 사용자의 모든 활동을 가로챕니다. 그러나 재실행은 /bin/sh
glibc 내부에서 수행되므로 시스템 호출을 가로채는 것만으로는 관찰된 동작이 발생하지 않을 것이라고 생각합니다. 아마도 ObserveIT는 POSIX 기능도 에뮬레이트하는데, 이는 분명히 이 상황에서는 부적합한 것 같습니다.