ftpd: do not use nasty tricks for re-execing if we are on MMU machine.

On NOMMU, code is alomost the same, on MMU:

function                                             old     new   delta
handle_dir_common                                    223     390    +167
ftpd_main                                           2306    2231     -75
popen_ls                                             203       -    -203
------------------------------------------------------------------------------
(add/remove: 0/1 grow/shrink: 1/1 up/down: 167/-278)         Total: -111 bytes
This commit is contained in:
Denis Vlasenko 2009-03-18 14:12:22 +00:00
parent 1432cb4bd9
commit 5b492ee876

View File

@ -87,7 +87,9 @@ enum {
struct globals { struct globals {
int pasv_listen_fd; int pasv_listen_fd;
int proc_self_fd; #if !BB_MMU
int root_fd;
#endif
int local_file_fd; int local_file_fd;
unsigned end_time; unsigned end_time;
unsigned timeout; unsigned timeout;
@ -615,7 +617,13 @@ static int
popen_ls(const char *opt) popen_ls(const char *opt)
{ {
char *cwd; char *cwd;
const char *argv[5] = { "ftpd", opt, NULL, G.ftp_arg, NULL }; const char *argv[] = {
"ftpd",
opt,
BB_MMU ? "--" : NULL,
G.ftp_arg,
NULL
};
struct fd_pair outfd; struct fd_pair outfd;
pid_t pid; pid_t pid;
@ -623,25 +631,40 @@ popen_ls(const char *opt)
xpiped_pair(outfd); xpiped_pair(outfd);
/*fflush(NULL); - so far we dont use stdio on output */ /*fflush(NULL); - so far we dont use stdio on output */
pid = vfork(); pid = BB_MMU ? fork() : vfork();
switch (pid) { if (pid < 0)
case -1: /* failure */ bb_perror_msg_and_die(BB_MMU ? "fork" : "vfork");
bb_perror_msg_and_die("vfork");
case 0: /* child */ if (pid == 0) {
/* NB: close _first_, then move fds! */ /* child */
#if !BB_MMU
if (fchdir(G.root_fd) != 0)
_exit(127);
close(G.root_fd);
#endif
/* NB: close _first_, then move fd! */
close(outfd.rd); close(outfd.rd);
xmove_fd(outfd.wr, STDOUT_FILENO); xmove_fd(outfd.wr, STDOUT_FILENO);
/* Opening /dev/null in chroot is hard.
* Just making sure STDIN_FILENO is opened
* to something harmless. Paranoia,
* ls won't read it anyway */
close(STDIN_FILENO); close(STDIN_FILENO);
/* xopen("/dev/null", O_RDONLY); - chroot may lack it! */ dup(STDOUT_FILENO); /* copy will become STDIN_FILENO */
if (fchdir(G.proc_self_fd) == 0) { #if !BB_MMU
close(G.proc_self_fd);
argv[2] = cwd;
/* ftpd ls helper chdirs to argv[2], /* ftpd ls helper chdirs to argv[2],
* preventing peer from seeing /proc/self * preventing peer from seeing real root we are in now
*/ */
execv("exe", (char**) argv); argv[2] = cwd;
} /* + 1: we must use relative path here if in chroot.
* For example, execv("/proc/self/exe") will fail, since
* it looks for "/proc/self/exe" _relative to chroot!_ */
execv(CONFIG_BUSYBOX_EXEC_PATH + 1, (char**) argv);
_exit(127); _exit(127);
#else
memset(&G, 0, sizeof(G));
exit(ls_main(ARRAY_SIZE(argv) - 1, (char**) argv));
#endif
} }
/* parent */ /* parent */
@ -1006,15 +1029,21 @@ enum {
const_TYPE = mk_const4('T', 'Y', 'P', 'E'), const_TYPE = mk_const4('T', 'Y', 'P', 'E'),
const_USER = mk_const4('U', 'S', 'E', 'R'), const_USER = mk_const4('U', 'S', 'E', 'R'),
#if !BB_MMU
OPT_l = (1 << 0), OPT_l = (1 << 0),
OPT_1 = (1 << 1), OPT_1 = (1 << 1),
OPT_v = (1 << 2), #endif
OPT_S = (1 << 3), OPT_v = (1 << ((!BB_MMU) * 2 + 0)),
OPT_w = (1 << 4), OPT_S = (1 << ((!BB_MMU) * 2 + 1)),
OPT_w = (1 << ((!BB_MMU) * 2 + 2)) * ENABLE_FEATURE_FTP_WRITE,
}; };
int ftpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int ftpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
#if !BB_MMU
int ftpd_main(int argc, char **argv) int ftpd_main(int argc, char **argv)
#else
int ftpd_main(int argc UNUSED_PARAM, char **argv)
#endif
{ {
unsigned abs_timeout; unsigned abs_timeout;
smallint opts; smallint opts;
@ -1024,16 +1053,20 @@ int ftpd_main(int argc, char **argv)
abs_timeout = 1 * 60 * 60; abs_timeout = 1 * 60 * 60;
G.timeout = 2 * 60; G.timeout = 2 * 60;
opt_complementary = "t+:T+:vv"; opt_complementary = "t+:T+:vv";
#if BB_MMU
opts = getopt32(argv, "vS" USE_FEATURE_FTP_WRITE("w") "t:T:", &G.timeout, &abs_timeout, &G.verbose);
#else
opts = getopt32(argv, "l1vS" USE_FEATURE_FTP_WRITE("w") "t:T:", &G.timeout, &abs_timeout, &G.verbose); opts = getopt32(argv, "l1vS" USE_FEATURE_FTP_WRITE("w") "t:T:", &G.timeout, &abs_timeout, &G.verbose);
if (opts & (OPT_l|OPT_1)) { if (opts & (OPT_l|OPT_1)) {
/* Our secret backdoor to ls */ /* Our secret backdoor to ls */
memset(&G, 0, sizeof(G));
/* TODO: pass -n too? */ /* TODO: pass -n too? */
/* --group-directories-first would be nice, but ls don't do that yet */ /* --group-directories-first would be nice, but ls don't do that yet */
xchdir(argv[2]); xchdir(argv[2]);
argv[2] = (char*)"--"; argv[2] = (char*)"--";
memset(&G, 0, sizeof(G));
return ls_main(argc, argv); return ls_main(argc, argv);
} }
#endif
if (abs_timeout | G.timeout) { if (abs_timeout | G.timeout) {
if (abs_timeout == 0) if (abs_timeout == 0)
abs_timeout = INT_MAX; abs_timeout = INT_MAX;
@ -1065,7 +1098,9 @@ int ftpd_main(int argc, char **argv)
if (logmode) if (logmode)
applet_name = xasprintf("%s[%u]", applet_name, (int)getpid()); applet_name = xasprintf("%s[%u]", applet_name, (int)getpid());
G.proc_self_fd = xopen("/proc/self", O_RDONLY | O_DIRECTORY); #if !BB_MMU
G.root_fd = xopen("/", O_RDONLY | O_DIRECTORY);
#endif
if (argv[optind]) { if (argv[optind]) {
xchdir(argv[optind]); xchdir(argv[optind]);