用 C 语言编写这个程序似乎有点愚蠢,但如果有充分的理由这样做(例如,如果它必须是 setuid),那么你应该更加防御。我会做这样的事情:
#define _XOPEN_SOURCE 700 /* getline */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main(void)
{
char *jobdir = 0;
size_t asize = 0;
ssize_t len;
fputs("Enter job directory: ", stdout);
fflush(stdout);
len = getline(&jobdir, &asize, stdin);
if (len < 0) {
perror("getline");
return 1;
}
jobdir[--len] = '\0'; /* remove trailing \n */
if (len == 0 || !strcmp(jobdir, ".") || !strcmp(jobdir, "..")
|| strchr(jobdir, '/')) {
fputs("job directory name may not be empty, \".\", or \"..\", "
"nor contain a '/'\n", stderr);
return 1;
}
if (chdir("/home/jobs") || chdir(jobdir) || chdir("xxx")) {
perror(jobdir);
return 1;
}
execlp("ls", "ls", "-ltr", (char *)0);
perror("exec");
return 1;
}
这个答案的编辑历史将证明要做到这一点 100% 是多么困难——我不断地回顾它并意识到我忘记了另一个需要防御的案例。