我正在玩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)所有测试均在/home/zaffy/cool:
/home/zaffy/cool
??? exec
??? exec.c
??? prog
??? prog.c
Run Code Online (Sandbox Code Playgroud)# /home/zaffy/cool/exec /home/zaffy/cool/prog
works!
Run Code Online (Sandbox Code Playgroud)
# /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()之后不起作用?
您的问题很可能是您尝试执行的程序是动态链接的,并且/libchroot环境中不存在动态链接器.那会导致ENOENT(No such file or directory)错误.然而,仅仅添加它本身无济于事.您需要动态链接程序所依赖的所有其他文件,包括共享库和任何必要的配置/表/等.这些库需要的文件.