Reputation: 17521
I was playing around with exec
-family functions and I've seen a really strange behavior: they don't seem to work after chroot()
system call.
Here's a relevant Quote from manpages:
Special semantics for execlp() and execvp()
The execlp(), execvp(), and execvpe() functions duplicate the actions of the shell in searching for an executable file if the specified filename does not contain a slash (/) character. The file is sought in the colon-separated list of directory pathnames specified in the PATH envi‐ ronment variable. If this variable isn't defined, the path list defaults to the current directory followed by the list of directories returned by confstr(_CS_PATH). (This confstr(3) call typically returns the value "/bin:/usr/bin".)
If the specified filename includes a slash character, then PATH is ignored, and the file at the specified pathname is executed.
That was the theory, now let's see how it behaves:
I have prog.c
file that will be executed by execlp
:
#include <stdio.h>
int main()
{
puts("works!");
return 0;
}
And I have exec.c
file which will attempt to execute 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;
}
all tests are done in /home/zaffy/cool
:
/home/zaffy/cool
├── exec
├── exec.c
├── prog
└── prog.c
# /home/zaffy/cool/exec /home/zaffy/cool/prog
works!
# /home/zaffy/cool/exec /prog 1
Cannot execlp(/prog): No such file or directory
.
..
prog.c
prog
exec.c
exec
I'm confused! According to man-pages, if I have passed absolute path to execlp
it should not search in PATH
, or if the PATH
is not set, it should be set also to the current directory so I'm not able to see the problem here.
The file surely exists and is available! Even if I use fopen
right before execlp
, the fopen
finds and opens the file, but execlp
still emits the error No such file or directory.
Do you have any idea why this happens ? Why doesn't exec() work after chroot() ?
Upvotes: 3
Views: 1408
Reputation: 215447
Your problem is most likely that the program you're trying to exec is dynamic linked, and the dynamic linker is not present in /lib
in the chroot environment. That would cause the ENOENT
(No such file or directory
) error. However just adding it by itself won't help. You'd need all the other files the dynamic-linked program depends on, including shared libraries and any essential configuration/table/etc. files these libraries need.
Upvotes: 11