summaryrefslogtreecommitdiff
path: root/networking/ftpd.c
diff options
context:
space:
mode:
Diffstat (limited to 'networking/ftpd.c')
-rw-r--r--networking/ftpd.c51
1 files changed, 30 insertions, 21 deletions
diff --git a/networking/ftpd.c b/networking/ftpd.c
index df8188c..4e9f65c 100644
--- a/networking/ftpd.c
+++ b/networking/ftpd.c
@@ -616,18 +616,22 @@ handle_retr(void)
static int
popen_ls(const char *opt)
{
- char *cwd;
- const char *argv[] = {
- "ftpd",
- opt,
- BB_MMU ? "--" : NULL,
- G.ftp_arg,
- NULL
- };
+ const char *argv[5];
struct fd_pair outfd;
pid_t pid;
- cwd = xrealloc_getcwd_or_warn(NULL);
+ argv[0] = "ftpd";
+ argv[1] = opt; /* "-l" or "-1" */
+#if BB_MMU
+ argv[2] = "--";
+#else
+ /* NOMMU ftpd ls helper chdirs to argv[2],
+ * preventing peer from seeing real root. */
+ argv[2] = xrealloc_getcwd_or_warn(NULL);
+#endif
+ argv[3] = G.ftp_arg;
+ argv[4] = NULL;
+
xpiped_pair(outfd);
/*fflush_all(); - so far we dont use stdio on output */
@@ -638,9 +642,14 @@ popen_ls(const char *opt)
if (pid == 0) {
/* child */
#if !BB_MMU
+ /* On NOMMU, we want to execute a child - copy of ourself.
+ * In chroot we usually can't do it. Thus we chdir
+ * out of the chroot back to original root,
+ * and (see later below) execute bb_busybox_exec_path
+ * relative to current directory */
if (fchdir(G.root_fd) != 0)
_exit(127);
- close(G.root_fd);
+ /*close(G.root_fd); - close_on_exec_on() took care of this */
#endif
/* NB: close _first_, then move fd! */
close(outfd.rd);
@@ -651,25 +660,23 @@ popen_ls(const char *opt)
* ls won't read it anyway */
close(STDIN_FILENO);
dup(STDOUT_FILENO); /* copy will become STDIN_FILENO */
-#if !BB_MMU
- /* ftpd ls helper chdirs to argv[2],
- * preventing peer from seeing real root we are in now
- */
- argv[2] = cwd;
+#if BB_MMU
+ /* memset(&G, 0, sizeof(G)); - ls_main does it */
+ exit(ls_main(ARRAY_SIZE(argv) - 1, (char**) argv));
+#else
/* + 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(bb_busybox_exec_path + 1, (char**) argv);
_exit(127);
-#else
- /* memset(&G, 0, sizeof(G)); - ls_main does it */
- exit(ls_main(ARRAY_SIZE(argv) - 1, (char**) argv));
#endif
}
/* parent */
close(outfd.wr);
- free(cwd);
+#if !BB_MMU
+ free((char*)argv[2]);
+#endif
return outfd.rd;
}
@@ -1108,8 +1115,9 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv)
opts = getopt32(argv, "l1vS" IF_FEATURE_FTP_WRITE("w") "t:T:", &G.timeout, &abs_timeout, &G.verbose, &verbose_S);
if (opts & (OPT_l|OPT_1)) {
/* Our secret backdoor to ls */
-/* TODO: pass -n too? */
-/* --group-directories-first would be nice, but ls don't do that yet */
+/* TODO: pass -n? It prevents user/group resolution, whicj may not work in chroot anyway */
+/* TODO: pass -A? It shows dot files */
+/* TODO: pass --group-directories-first? would be nice, but ls don't do that yet */
xchdir(argv[2]);
argv[2] = (char*)"--";
/* memset(&G, 0, sizeof(G)); - ls_main does it */
@@ -1151,6 +1159,7 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv)
#if !BB_MMU
G.root_fd = xopen("/", O_RDONLY | O_DIRECTORY);
+ close_on_exec_on(G.root_fd);
#endif
if (argv[optind]) {