ftpd: make DIR parameter work for non-root too: chdir to it instead of chroot
authorDenys Vlasenko <vda.linux@googlemail.com>
Tue, 13 Oct 2015 11:49:53 +0000 (13:49 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Tue, 13 Oct 2015 11:49:53 +0000 (13:49 +0200)
Unfortunately, chroot() works only for root user, because of attacks
on setuid binaries (make DIR/lib/ld-linux.so a shell, hardlink to
a setuid binary, chroot to DIR, execute it and get root shell).

function                                             old     new   delta
ftpd_main                                           2160    2180     +20

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
networking/ftpd.c

index 7735b723322bd194f58b78bdd3a4b7147f6d64f3..8345ae67c112ad3c4eb874d2e0af8541a73dc6e0 100644 (file)
@@ -1223,11 +1223,26 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv)
 #endif
        argv += optind;
        if (argv[0]) {
+               const char *basedir = argv[0];
 #if !BB_MMU
                G.root_fd = xopen("/", O_RDONLY | O_DIRECTORY);
                close_on_exec_on(G.root_fd);
 #endif
-               xchroot(argv[0]);
+               if (chroot(basedir) == 0)
+                       basedir = "/";
+#if !BB_MMU
+               else {
+                       close(G.root_fd);
+                       G.root_fd = -1;
+               }
+#endif
+               /*
+                * If chroot failed, assume that we aren't root,
+                * and at least chdir to the specified DIR
+                * (older versions were dying with error message).
+                * If chroot worked, move current dir to new "/":
+                */
+               xchdir(basedir);
        }
 
 #if ENABLE_FEATURE_FTP_AUTHENTICATION