为什么exec()在chroot()之后不起作用?

Zaf*_*ffy 1 c c++ linux exec

我正在玩exec家庭功能,我看到了一个非常奇怪的行为:它们在chroot()系统调用后似乎不起作用.

这是来自联机帮助页的相关报价:

execlp()和execvp()的特殊语义

如果指定的文件名不包含斜杠(/)字符,则execlp(),execvp()和execvpe()函数会复制shell在搜索可执行文件时的操作.在PATH环境变量中指定的以冒号分隔的目录路径名列表中查找该文件.如果未定义此变量,则路径列表默认为当前目录,后跟confstr(_CS_PATH)返回的目录列表.(此confstr(3)调用通常返回值"/ bin:/ usr/bin".)

如果指定的文件名包含斜杠字符,则忽略PATH,并执行指定路径名的文件.

这就是理论,现在让我们看看它的表现如何:

  • 我有prog.c将执行的文件execlp:

    #include <stdio.h>
    
    int main()
    {
        puts("works!");
        return 0;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 我有exec.c文件将尝试执行prog:

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <errno.h>
    #include <dirent.h>
    
    int main(int argc, char* const argv[])
    {
        const char path[] = "/home/zaffy/cool";
    
        if (argc < 2)
            return 1;
    
        if (argc > 2 && (chdir(path) || chroot(path)))
        {
            printf("Cannot chroot(%s): %s\n", path, strerror(errno));
            return 1;
        }
    
        /* Clear our environment, including PATH */
        clearenv();
    
        if (execlp(argv[1], argv[1], NULL))
        {
            printf("Cannot execlp(%s): %s\n", argv[1], strerror(errno));
    
            /* Well, we failed... let's see
               contents of the current root */
            struct dirent* entry;
            DIR* dir = opendir("/");
            while ( (entry = readdir(dir)) )
                printf("%s\n", entry->d_name);
            closedir(dir);
        }
    
        return 0;
    }
    
    Run Code Online (Sandbox Code Playgroud)

测试一:exec没有调用chroot:

# /home/zaffy/cool/exec /home/zaffy/cool/prog
works!
Run Code Online (Sandbox Code Playgroud)

测试二:exec调用chroot:

# /home/zaffy/cool/exec /prog 1
Cannot execlp(/prog): No such file or directory
.
..
prog.c
prog
exec.c
exec
Run Code Online (Sandbox Code Playgroud)

我糊涂了!根据man-pages,如果我已经通过绝对路径execlp它不应该搜索PATH,或者如果PATH没有设置,它应该也设置为当前目录,所以我不能在这里看到问题.

该文件肯定存在并且可用!即使我fopen之前使用execlp,fopen查找并打开文件,但execlp仍然会发出错误没有这样的文件或目录.

你知道为什么会这样吗?为什么exec()在chroot()之后不起作用?

R..*_*R.. 6

您的问题很可能是您尝试执行的程序是动态链接的,并且/libchroot环境中不存在动态链接器.那会导致ENOENT(No such file or directory)错误.然而,仅仅添加它本身无济于事.您需要动态链接程序所依赖的所有其他文件,包括共享库和任何必要的配置/表/等.这些库需要的文件.