login: clear dangerous environment variables if started by non-root
authorDenis Vlasenko <vda.linux@googlemail.com>
Tue, 6 Nov 2007 05:26:51 +0000 (05:26 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Tue, 6 Nov 2007 05:26:51 +0000 (05:26 -0000)
include/libbb.h
libbb/login.c
loginutils/login.c
loginutils/sulogin.c

index 77c678ceef5f9e5fb49a3c715e8a88d063d9873e..f79d80d7fa74aab750fe2bf4eb91fe84e2c8f553 100644 (file)
@@ -623,6 +623,8 @@ enum {
 #endif
 void bb_daemonize_or_rexec(int flags, char **argv);
 void bb_sanitize_stdio(void);
+/* Clear dangerous stuff, set PATH */
+void sanitize_env_for_suid(void);
 
 
 extern const char *opt_complementary;
index 308e1bfed613398aae4062869444a1852c6a16ed..1af3165b94f83fa585e56396216166b1b0bce2b2 100644 (file)
@@ -99,3 +99,29 @@ void print_login_prompt(void)
        fputs(LOGIN, stdout);
        fflush(stdout);
 }
+
+/* Clear dangerous stuff, set PATH */
+static const char forbid[] ALIGN1 =
+       "ENV" "\0"
+       "BASH_ENV" "\0"
+       "HOME" "\0"
+       "IFS" "\0"
+       "SHELL" "\0"
+       "LD_LIBRARY_PATH" "\0"
+       "LD_PRELOAD" "\0"
+       "LD_TRACE_LOADED_OBJECTS" "\0"
+       "LD_BIND_NOW" "\0"
+       "LD_AOUT_LIBRARY_PATH" "\0"
+       "LD_AOUT_PRELOAD" "\0"
+       "LD_NOWARN" "\0"
+       "LD_KEEPDIR" "\0";
+
+void sanitize_env_for_suid(void)
+{
+       const char *p = forbid;
+       do {
+               unsetenv(p);
+               p += strlen(p) + 1;
+       } while (*p);
+       putenv((char*)bb_PATH_root_path);
+}
index bddc0f533886971b2dc62942a462745039c26d77..c05edde36af267c0dde24d70c6883e275d1c8fac 100644 (file)
@@ -201,7 +201,7 @@ static void motd(void)
        int fd;
 
        fd = open(bb_path_motd_file, O_RDONLY);
-       if (fd) {
+       if (fd >= 0) {
                fflush(stdout);
                bb_copyfd_eof(fd, STDOUT_FILENO);
                close(fd);
@@ -216,6 +216,10 @@ static void alarm_handler(int sig ATTRIBUTE_UNUSED)
        ndelay_on(1);
        ndelay_on(2);
        printf("\r\nLogin timed out after %d seconds\r\n", TIMEOUT);
+       /* unix API is brain damaged regarding O_NONBLOCK,
+        * we should undo it, or else we can affect other processes */
+       ndelay_off(1);
+       ndelay_off(2);
        exit(EXIT_SUCCESS);
 }
 
@@ -254,6 +258,11 @@ int login_main(int argc, char **argv)
         * and any extra open fd's are closed.
         * (The name of the function is misleading. Not daemonizing here.) */
        bb_daemonize_or_rexec(DAEMON_ONLY_SANITIZE | DAEMON_CLOSE_EXTRA_FDS, NULL);
+       /* More of suid paranoia if called by non-root */
+       if (!amroot) {
+               /* Clear dangerous stuff, set PATH */
+               sanitize_env_for_suid();
+       }
 
        opt = getopt32(argv, "f:h:p", &opt_user, &opt_host);
        if (opt & LOGIN_OPT_f) {
@@ -411,7 +420,8 @@ int login_main(int argc, char **argv)
        fchown(0, pw->pw_uid, pw->pw_gid);
        fchmod(0, 0600);
 
-       if (ENABLE_LOGIN_SCRIPTS) {
+       /* We trust environment only if we run by root */
+       if (ENABLE_LOGIN_SCRIPTS && amroot) {
                char *t_argv[2];
 
                t_argv[0] = getenv("LOGIN_PRE_SUID_SCRIPT");
index f1545b78fab2be38426de2da502eb9e8c3d38fbe..af457ef1e52b1ea0c0b095a2166fbac1a87b9c09 100644 (file)
@@ -9,22 +9,6 @@
 
 #include "libbb.h"
 
-static const char forbid[] ALIGN1 =
-       "ENV" "\0"
-       "BASH_ENV" "\0"
-       "HOME" "\0"
-       "IFS" "\0"
-       "PATH" "\0"
-       "SHELL" "\0"
-       "LD_LIBRARY_PATH" "\0"
-       "LD_PRELOAD" "\0"
-       "LD_TRACE_LOADED_OBJECTS" "\0"
-       "LD_BIND_NOW" "\0"
-       "LD_AOUT_LIBRARY_PATH" "\0"
-       "LD_AOUT_PRELOAD" "\0"
-       "LD_NOWARN" "\0"
-       "LD_KEEPDIR" "\0";
-
 //static void catchalarm(int ATTRIBUTE_UNUSED junk)
 //{
 //     exit(EXIT_FAILURE);
@@ -37,7 +21,6 @@ int sulogin_main(int argc, char **argv)
        char *cp;
        int timeout = 0;
        char *timeout_arg;
-       const char *p;
        struct passwd *pwd;
        const char *shell;
 #if ENABLE_FEATURE_SHADOWPASSWDS
@@ -66,12 +49,8 @@ int sulogin_main(int argc, char **argv)
                bb_error_msg_and_die("not a tty");
        }
 
-       /* Clear out anything dangerous from the environment */
-       p = forbid;
-       do {
-               unsetenv(p);
-               p += strlen(p) + 1;
-       } while (*p);
+       /* Clear dangerous stuff, set PATH */
+       sanitize_env_for_suid();
 
 // bb_askpass() already handles this
 //     signal(SIGALRM, catchalarm);