Red Hat Enterprise Linux 6 上 shell 腳本的 execvp exec 格式錯誤

Red Hat Enterprise Linux 6 上 shell 腳本的 execvp exec 格式錯誤

我們有兩個 RHEL 6 系統,運行相同版本的內核和 glibc (glibc–2.12–1.90.el6_3.6)。根據 POSIX 標準和 Linux 手冊頁,如果核心確定一個可執行檔案不是可執行格式(例如 ELF)且沒有 shebang ( #!) 行,則函數execl, execlp, execle, execv, execvp, 和execvpe(但是not execve) 將嘗試使用POSIX shell 執行該檔案,在Linux 上是/bin/sh.

但是,在其中一個系統上,執行第一行:使用該函數的 shell 腳本execvp會失敗,而在另一台電腦上/bin/sh,則按預期使用 執行腳本。具體來說,我們正在使用這些測試程式;/tmp/test_script可執行:

xc:

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

外部字元**環境;

int 主函數 () {
        char *argv[] = { "/tmp/test_script", NULL };
        char *程式名 = argv[0];
        if (execvp(程式名稱, argv) == -1) {
                錯誤(“execvp”);
                返回-1;
        }
}

/tmp/測試腳本:

:

echo“測試腳本已呼叫”
出口0

我們在來源 RPM 中搜尋了已安裝的 glibc 版本,它確實實作了所需的行為(execvp 是 execvpe 的簡單包裝器):

posix/execvpe.c:

if (strchr(檔案, '/') != NULL)
    {
        /* 當包含斜線時不進行搜尋。 */
        __execve(檔案、argv、envp);

        if (errno == ENOEXEC)
            {
                /* 計算參數。 */
                int argc = 0;
                while (argv[argc++])
                    ;
                size_t len = (argc + 1) * sizeof(char *);
                字元 **script_argv;
                無效 *ptr = NULL;
                如果 (__libc_use_alloca(len))
                    script_argv = alloca(len);
                別的
                    script_argv = ptr = malloc(len);

                如果(script_argv!= NULL)
                    {
                        script_argv(檔案、argv、argc、script_argv);
                        __execve(script_argv[0], script_argv, envp);

                        自由(ptr);
                    }
            }
    }
別的
   ︙

這裡,scripts_argv是一個簡單的函數,它添加/bin/sh到參數列表中,並且與透過 glibc 暴露給用戶空間的函數__execve相同。execve

還有其他人在 Linux 上遇到過這個問題嗎?在我嘗試過的所有其他系統上,該行為都是正確的。

答案1

好吧,我發現了問題所在。編譯x.c可執行檔後,我運行ldd它,發現有一個liboit.so動態連結到可執行檔的庫。該庫是由ObserveIT Unix 審計員,它攔截登入使用者的所有活動,包括系統呼叫。但是,我認為僅攔截系統呼叫不會導致觀察到的行為,因為重新執行/bin/sh是在 glibc 內部完成的。也許 ObserveIT 也模擬 POSIX 函數,但在這種情況下顯然不符合要求。

相關內容