Red Hat Enterprise Linux 6의 쉘 스크립트에 대한 execvp exec 형식 오류

Red Hat Enterprise Linux 6의 쉘 스크립트에 대한 execvp exec 형식 오류

동일한 버전의 커널과 glibc(glibc–2.12–1.90.el6_3.6)를 실행하는 두 개의 RHEL 6 시스템이 있습니다. POSIX 표준과 Linux 매뉴얼 페이지에 따르면, 커널이 실행 파일이 ELF와 같은 실행 가능 형식이 아니고 shebang( ) 줄이 없다고 판단하면 #!함수 execl, execlp, execle, execv, execvpexecvpe(그러나 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__execveexecve

Linux에서 이 문제를 겪은 사람이 있습니까? 내가 시도한 다른 모든 시스템에서는 동작이 정확했습니다.

답변1

알겠습니다. 문제의 원인을 발견했습니다. x.c실행 파일을 컴파일한 후 실행해 보니 실행 파일에 동적으로 연결된 ldd라이브러리가 있다는 것을 발견했습니다 . liboit.so이 라이브러리는 다음에서 설치했습니다.ObserveIT Unix 감사자, 시스템 호출을 포함하여 로그인한 사용자의 모든 활동을 가로챕니다. 그러나 재실행은 /bin/shglibc 내부에서 수행되므로 시스템 호출을 가로채는 것만으로는 관찰된 동작이 발생하지 않을 것이라고 생각합니다. 아마도 ObserveIT는 POSIX 기능도 에뮬레이트하는데, 이는 분명히 이 상황에서는 부적합한 것 같습니다.

관련 정보