--- rxvt-unicode/src/main.C 2006/01/17 15:17:39 1.185 +++ rxvt-unicode/src/main.C 2006/01/19 09:47:15 1.189 @@ -48,21 +48,6 @@ # include #endif -#if (defined(HAVE_SETEUID) || defined(HAVE_SETREUID)) && !defined(__CYGWIN32__) -static uid_t saved_euid; -static gid_t saved_egid; -#endif - -bool -rxvt_tainted () -{ -#if (defined(HAVE_SETEUID) || defined(HAVE_SETREUID)) && !defined(__CYGWIN32__) - return getuid () != saved_euid || getgid () != saved_egid; -#else - return false; -#endif -} - vector rxvt_term::termlist; static char curlocale[128], savelocale[128]; @@ -186,6 +171,7 @@ #endif termwin_ev (this, &rxvt_term::x_cb), vt_ev (this, &rxvt_term::x_cb), + child_ev (this, &rxvt_term::child_cb), check_ev (this, &rxvt_term::check_cb), flush_ev (this, &rxvt_term::flush_cb), destroy_ev (this, &rxvt_term::destroy_cb), @@ -211,10 +197,6 @@ if (cmd_pid) kill (-cmd_pid, SIGHUP); -#ifdef UTMP_SUPPORT - privileged_utmp (RESTORE); -#endif - delete pty; pty = 0; } @@ -306,9 +288,12 @@ #endif } +// child has exited, usually destroys void -rxvt_term::child_exit () +rxvt_term::child_cb (child_watcher &w, int status) { + HOOK_INVOKE ((this, HOOK_CHILD_EXIT, DT_INT, status, DT_END)); + cmd_pid = 0; if (!OPTION (Opt_hold)) @@ -493,19 +478,6 @@ || (rs[Rs_perl_ext_2] && *rs[Rs_perl_ext_2]) || (rs[Rs_perl_eval] && *rs[Rs_perl_eval])) { -#if (defined(HAVE_SETEUID) || defined(HAVE_SETREUID)) && !defined(__CYGWIN32__) - // ignore some perl-related arguments if some bozo installed us set[ug]id - if (rxvt_tainted ()) - { - if ((rs[Rs_perl_lib] && *rs[Rs_perl_lib]) - || (rs[Rs_perl_eval] && *rs[Rs_perl_eval])) - { - rxvt_warn ("running with elevated privileges: ignoring perl-lib and perl-eval.\n"); - rs[Rs_perl_lib] = 0; - rs[Rs_perl_eval] = 0; - } - } -#endif rxvt_perl.init (this); HOOK_INVOKE ((this, HOOK_INIT, DT_END)); } @@ -559,22 +531,8 @@ static struct sig_handlers { - sig_watcher sw_chld, sw_term, sw_int; + sig_watcher sw_term, sw_int; - void sig_chld (sig_watcher &w) - { - // we are being called for every SIGCHLD, find the corresponding term - int pid; - - while ((pid = waitpid (-1, NULL, WNOHANG)) > 0) - for (rxvt_term **t = rxvt_term::termlist.begin (); t < rxvt_term::termlist.end (); t++) - if (pid == (*t)->cmd_pid) - { - (*t)->child_exit (); - break; - } - } - /* * Catch a fatal signal and tidy up before quitting */ @@ -590,8 +548,7 @@ } sig_handlers () - : sw_chld (this, &sig_handlers::sig_chld), - sw_term (this, &sig_handlers::sig_term), + : sw_term (this, &sig_handlers::sig_term), sw_int (this, &sig_handlers::sig_term) { } @@ -602,22 +559,42 @@ void rxvt_init () { - rxvt_environ = environ; + uid_t uid = getuid (); + gid_t gid = getgid (); + + // before doing anything else, check for setuid/setgid operation, + // start the helper process and drop privileges + if (uid != geteuid () + || gid != getegid ()) + { +#if PTYTTY_HELPER + rxvt_ptytty_server (); +#else + rxvt_warn ("running setuid/setgid without pty helper compiled in, continuing unprivileged.\n"); +#endif - /* - * Save and then give up any super-user privileges - * If we need privileges in any area then we must specifically request it. - * We should only need to be root in these cases: - * 1. write utmp entries on some systems - * 2. chown tty on some systems - */ - rxvt_privileges (SAVE); - rxvt_privileges (IGNORE); + // drop privileges +#if HAVE_SETRESUID + setresgid (gid, gid, gid); + setresuid (uid, uid, uid); +#elif HAVE_SETREUID + setregid (gid, gid); + setreuid (uid, uid); +#elif HAVE_SETUID + setgid (gid); + setuid (uid); +#endif + + if (uid != geteuid () + || gid != getegid ()) + rxvt_fatal ("unable to drop privileges, aborting.\n"); + } + + rxvt_environ = environ; signal (SIGHUP, SIG_IGN); signal (SIGPIPE, SIG_IGN); - sig_handlers.sw_chld.start (SIGCHLD); sig_handlers.sw_term.start (SIGTERM); sig_handlers.sw_int.start (SIGINT); @@ -667,56 +644,6 @@ return p; } -/* ------------------------------------------------------------------------- * - * PRIVILEGED OPERATIONS * - * ------------------------------------------------------------------------- */ -/* take care of suid/sgid super-user (root) privileges */ -void -rxvt_privileges (rxvt_privaction action) -{ -#if ! defined(__CYGWIN32__) -# if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) - /* setreuid () is the poor man's setuid (), seteuid () */ -# define seteuid(a) setreuid(-1, (a)) -# define setegid(a) setregid(-1, (a)) -# define HAVE_SETEUID -# endif -# ifdef HAVE_SETEUID - switch (action) - { - case IGNORE: - /* - * change effective uid/gid - not real uid/gid - so we can switch - * back to root later, as required - */ - setegid (getgid ()); - seteuid (getuid ()); - break; - case SAVE: - saved_egid = getegid (); - saved_euid = geteuid (); - break; - case RESTORE: - setegid (saved_egid); - seteuid (saved_euid); - break; - } -# else - switch (action) - { - case IGNORE: - setgid (getgid ()); - setuid (getuid ()); - /* FALLTHROUGH */ - case SAVE: - /* FALLTHROUGH */ - case RESTORE: - break; - } -# endif -#endif -} - /*----------------------------------------------------------------------*/ /* * window size/position calculcations for XSizeHint and other storage.