diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2009-03-18 14:12:22 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2009-03-18 14:12:22 +0000 |
commit | 5b492ee87614632e7bf5cd68fe0ce87dad30002a (patch) | |
tree | 747b5212fc9428139b29b5fb273772eebf6025da /networking/ftpd.c | |
parent | 1432cb4bd9daf304111dd19e0011f8756c32e327 (diff) | |
download | busybox-w32-5b492ee87614632e7bf5cd68fe0ce87dad30002a.tar.gz busybox-w32-5b492ee87614632e7bf5cd68fe0ce87dad30002a.tar.bz2 busybox-w32-5b492ee87614632e7bf5cd68fe0ce87dad30002a.zip |
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
Diffstat (limited to 'networking/ftpd.c')
-rw-r--r-- | networking/ftpd.c | 79 |
1 files changed, 57 insertions, 22 deletions
diff --git a/networking/ftpd.c b/networking/ftpd.c index b295ddf4f..0a4b185a1 100644 --- a/networking/ftpd.c +++ b/networking/ftpd.c | |||
@@ -87,7 +87,9 @@ enum { | |||
87 | 87 | ||
88 | struct globals { | 88 | struct globals { |
89 | int pasv_listen_fd; | 89 | int pasv_listen_fd; |
90 | int proc_self_fd; | 90 | #if !BB_MMU |
91 | int root_fd; | ||
92 | #endif | ||
91 | int local_file_fd; | 93 | int local_file_fd; |
92 | unsigned end_time; | 94 | unsigned end_time; |
93 | unsigned timeout; | 95 | unsigned timeout; |
@@ -615,7 +617,13 @@ static int | |||
615 | popen_ls(const char *opt) | 617 | popen_ls(const char *opt) |
616 | { | 618 | { |
617 | char *cwd; | 619 | char *cwd; |
618 | const char *argv[5] = { "ftpd", opt, NULL, G.ftp_arg, NULL }; | 620 | const char *argv[] = { |
621 | "ftpd", | ||
622 | opt, | ||
623 | BB_MMU ? "--" : NULL, | ||
624 | G.ftp_arg, | ||
625 | NULL | ||
626 | }; | ||
619 | struct fd_pair outfd; | 627 | struct fd_pair outfd; |
620 | pid_t pid; | 628 | pid_t pid; |
621 | 629 | ||
@@ -623,25 +631,40 @@ popen_ls(const char *opt) | |||
623 | xpiped_pair(outfd); | 631 | xpiped_pair(outfd); |
624 | 632 | ||
625 | /*fflush(NULL); - so far we dont use stdio on output */ | 633 | /*fflush(NULL); - so far we dont use stdio on output */ |
626 | pid = vfork(); | 634 | pid = BB_MMU ? fork() : vfork(); |
627 | switch (pid) { | 635 | if (pid < 0) |
628 | case -1: /* failure */ | 636 | bb_perror_msg_and_die(BB_MMU ? "fork" : "vfork"); |
629 | bb_perror_msg_and_die("vfork"); | 637 | |
630 | case 0: /* child */ | 638 | if (pid == 0) { |
631 | /* NB: close _first_, then move fds! */ | 639 | /* child */ |
640 | #if !BB_MMU | ||
641 | if (fchdir(G.root_fd) != 0) | ||
642 | _exit(127); | ||
643 | close(G.root_fd); | ||
644 | #endif | ||
645 | /* NB: close _first_, then move fd! */ | ||
632 | close(outfd.rd); | 646 | close(outfd.rd); |
633 | xmove_fd(outfd.wr, STDOUT_FILENO); | 647 | xmove_fd(outfd.wr, STDOUT_FILENO); |
648 | /* Opening /dev/null in chroot is hard. | ||
649 | * Just making sure STDIN_FILENO is opened | ||
650 | * to something harmless. Paranoia, | ||
651 | * ls won't read it anyway */ | ||
634 | close(STDIN_FILENO); | 652 | close(STDIN_FILENO); |
635 | /* xopen("/dev/null", O_RDONLY); - chroot may lack it! */ | 653 | dup(STDOUT_FILENO); /* copy will become STDIN_FILENO */ |
636 | if (fchdir(G.proc_self_fd) == 0) { | 654 | #if !BB_MMU |
637 | close(G.proc_self_fd); | 655 | /* ftpd ls helper chdirs to argv[2], |
638 | argv[2] = cwd; | 656 | * preventing peer from seeing real root we are in now |
639 | /* ftpd ls helper chdirs to argv[2], | 657 | */ |
640 | * preventing peer from seeing /proc/self | 658 | argv[2] = cwd; |
641 | */ | 659 | /* + 1: we must use relative path here if in chroot. |
642 | execv("exe", (char**) argv); | 660 | * For example, execv("/proc/self/exe") will fail, since |
643 | } | 661 | * it looks for "/proc/self/exe" _relative to chroot!_ */ |
662 | execv(CONFIG_BUSYBOX_EXEC_PATH + 1, (char**) argv); | ||
644 | _exit(127); | 663 | _exit(127); |
664 | #else | ||
665 | memset(&G, 0, sizeof(G)); | ||
666 | exit(ls_main(ARRAY_SIZE(argv) - 1, (char**) argv)); | ||
667 | #endif | ||
645 | } | 668 | } |
646 | 669 | ||
647 | /* parent */ | 670 | /* parent */ |
@@ -1006,15 +1029,21 @@ enum { | |||
1006 | const_TYPE = mk_const4('T', 'Y', 'P', 'E'), | 1029 | const_TYPE = mk_const4('T', 'Y', 'P', 'E'), |
1007 | const_USER = mk_const4('U', 'S', 'E', 'R'), | 1030 | const_USER = mk_const4('U', 'S', 'E', 'R'), |
1008 | 1031 | ||
1032 | #if !BB_MMU | ||
1009 | OPT_l = (1 << 0), | 1033 | OPT_l = (1 << 0), |
1010 | OPT_1 = (1 << 1), | 1034 | OPT_1 = (1 << 1), |
1011 | OPT_v = (1 << 2), | 1035 | #endif |
1012 | OPT_S = (1 << 3), | 1036 | OPT_v = (1 << ((!BB_MMU) * 2 + 0)), |
1013 | OPT_w = (1 << 4), | 1037 | OPT_S = (1 << ((!BB_MMU) * 2 + 1)), |
1038 | OPT_w = (1 << ((!BB_MMU) * 2 + 2)) * ENABLE_FEATURE_FTP_WRITE, | ||
1014 | }; | 1039 | }; |
1015 | 1040 | ||
1016 | int ftpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 1041 | int ftpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
1042 | #if !BB_MMU | ||
1017 | int ftpd_main(int argc, char **argv) | 1043 | int ftpd_main(int argc, char **argv) |
1044 | #else | ||
1045 | int ftpd_main(int argc UNUSED_PARAM, char **argv) | ||
1046 | #endif | ||
1018 | { | 1047 | { |
1019 | unsigned abs_timeout; | 1048 | unsigned abs_timeout; |
1020 | smallint opts; | 1049 | smallint opts; |
@@ -1024,16 +1053,20 @@ int ftpd_main(int argc, char **argv) | |||
1024 | abs_timeout = 1 * 60 * 60; | 1053 | abs_timeout = 1 * 60 * 60; |
1025 | G.timeout = 2 * 60; | 1054 | G.timeout = 2 * 60; |
1026 | opt_complementary = "t+:T+:vv"; | 1055 | opt_complementary = "t+:T+:vv"; |
1056 | #if BB_MMU | ||
1057 | opts = getopt32(argv, "vS" USE_FEATURE_FTP_WRITE("w") "t:T:", &G.timeout, &abs_timeout, &G.verbose); | ||
1058 | #else | ||
1027 | opts = getopt32(argv, "l1vS" USE_FEATURE_FTP_WRITE("w") "t:T:", &G.timeout, &abs_timeout, &G.verbose); | 1059 | opts = getopt32(argv, "l1vS" USE_FEATURE_FTP_WRITE("w") "t:T:", &G.timeout, &abs_timeout, &G.verbose); |
1028 | if (opts & (OPT_l|OPT_1)) { | 1060 | if (opts & (OPT_l|OPT_1)) { |
1029 | /* Our secret backdoor to ls */ | 1061 | /* Our secret backdoor to ls */ |
1030 | memset(&G, 0, sizeof(G)); | ||
1031 | /* TODO: pass -n too? */ | 1062 | /* TODO: pass -n too? */ |
1032 | /* --group-directories-first would be nice, but ls don't do that yet */ | 1063 | /* --group-directories-first would be nice, but ls don't do that yet */ |
1033 | xchdir(argv[2]); | 1064 | xchdir(argv[2]); |
1034 | argv[2] = (char*)"--"; | 1065 | argv[2] = (char*)"--"; |
1066 | memset(&G, 0, sizeof(G)); | ||
1035 | return ls_main(argc, argv); | 1067 | return ls_main(argc, argv); |
1036 | } | 1068 | } |
1069 | #endif | ||
1037 | if (abs_timeout | G.timeout) { | 1070 | if (abs_timeout | G.timeout) { |
1038 | if (abs_timeout == 0) | 1071 | if (abs_timeout == 0) |
1039 | abs_timeout = INT_MAX; | 1072 | abs_timeout = INT_MAX; |
@@ -1065,7 +1098,9 @@ int ftpd_main(int argc, char **argv) | |||
1065 | if (logmode) | 1098 | if (logmode) |
1066 | applet_name = xasprintf("%s[%u]", applet_name, (int)getpid()); | 1099 | applet_name = xasprintf("%s[%u]", applet_name, (int)getpid()); |
1067 | 1100 | ||
1068 | G.proc_self_fd = xopen("/proc/self", O_RDONLY | O_DIRECTORY); | 1101 | #if !BB_MMU |
1102 | G.root_fd = xopen("/", O_RDONLY | O_DIRECTORY); | ||
1103 | #endif | ||
1069 | 1104 | ||
1070 | if (argv[optind]) { | 1105 | if (argv[optind]) { |
1071 | xchdir(argv[optind]); | 1106 | xchdir(argv[optind]); |