--- rxvt-unicode/src/ptytty.C 2006/01/22 01:00:46 1.55 +++ rxvt-unicode/src/ptytty.C 2006/01/22 12:21:47 1.57 @@ -8,6 +8,7 @@ * All portions of code are copyright by their respective author/s. * Copyright (c) 1999-2001 Geoff Wing * Copyright (c) 2004-2006 Marc Lehmann + * Copyright (c) 2006 Emanuele Giaquinta * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,7 +27,6 @@ #include "../config.h" -#include "fdpass.h" #include "ptytty.h" #include @@ -237,7 +237,7 @@ int fd = open ("/dev/tty", O_WRONLY); if (fd < 0) - return -1; /* fatal */ + return -1; /* fatal */ close (fd); @@ -375,8 +375,8 @@ #if PTYTTY_HELPER -static int sock_fd; -static int pid; +static int sock_fd = -1; +static int helper_pid, owner_pid; struct command { @@ -414,14 +414,14 @@ write (sock_fd, &cmd, sizeof (cmd)); if (read (sock_fd, &id, sizeof (id)) != sizeof (id)) - fatal ("protocol error while creating pty using helper process, aborting.\n"); + ptytty_fatal ("protocol error while creating pty using helper process, aborting.\n"); if (!id) return false; - if ((pty = ptytty_recv_fd (sock_fd)) < 0 - || (tty = ptytty_recv_fd (sock_fd)) < 0) - fatal ("protocol error while reading pty/tty fds from helper process, aborting.\n"); + if ((pty = recv_fd (sock_fd)) < 0 + || (tty = recv_fd (sock_fd)) < 0) + ptytty_fatal ("protocol error while reading pty/tty fds from helper process, aborting.\n"); return true; } @@ -471,8 +471,8 @@ write (sock_fd, &cmd.id, sizeof (cmd.id)); ptys.push_back (cmd.id); - ptytty_send_fd (sock_fd, cmd.id->pty); - ptytty_send_fd (sock_fd, cmd.id->tty); + ptytty::send_fd (sock_fd, cmd.id->pty); + ptytty::send_fd (sock_fd, cmd.id->tty); } else { @@ -493,9 +493,9 @@ } else if (cmd.type == command::destroy) { - ptytty **pty = find (ptys.begin (), ptys.end (), cmd.id); + vector::iterator pty = find (ptys.begin (), ptys.end (), cmd.id); - if (pty) + if (pty != ptys.end ()) { delete *pty; ptys.erase (pty); @@ -506,23 +506,31 @@ } // destroy all ptys - for (ptytty **i = ptys.end (); i-- > ptys.begin (); ) + for (vector::iterator i = ptys.end (); i-- > ptys.begin (); ) delete *i; } -void ptytty_server () +void +ptytty::use_helper () { + int pid = getpid (); + + if (sock_fd >= 0 && pid == owner_pid) + return; + + owner_pid = pid; + int sv[2]; if (socketpair (AF_UNIX, SOCK_STREAM, 0, sv)) - fatal ("could not create socket to communicate with pty/sessiondb helper, aborting.\n"); + ptytty_fatal ("could not create socket to communicate with pty/sessiondb helper, aborting.\n"); - pid = fork (); + helper_pid = fork (); - if (pid < 0) - fatal ("could not create pty/sessiondb helper process, aborting.\n"); + if (helper_pid < 0) + ptytty_fatal ("could not create pty/sessiondb helper process, aborting.\n"); - if (pid) + if (helper_pid) { // client, process sock_fd = sv[0]; @@ -534,6 +542,8 @@ // server, pty-helper sock_fd = sv[1]; + chdir ("/"); + for (int fd = 0; fd < 1023; fd++) if (fd != sock_fd) close (fd); @@ -545,12 +555,11 @@ #endif -// a "factory" *g* ptytty * -new_ptytty () +ptytty::create () { #if PTYTTY_HELPER - if (pid > 0) + if (helper_pid && getpid () == owner_pid) // use helper process return new ptytty_proxy; else @@ -558,5 +567,47 @@ return new ptytty_unix; } -/*----------------------- end-of-file (C source) -----------------------*/ +void +ptytty::init () +{ + 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 + use_helper (); +#else + ptytty_warn ("running setuid/setgid without pty helper compiled in, continuing unprivileged.\n"); +#endif + + drop_privileges (); + } +} + +void +ptytty::drop_privileges () +{ + uid_t uid = getuid (); + gid_t gid = getgid (); + + // 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 ()) + ptytty_fatal ("unable to drop privileges, aborting.\n"); +}