]> granicus.if.org Git - sudo/commitdiff
When trying to determine the tty, fall back on /proc/ppid/fd/{0,1,2}
authorTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 3 Jan 2012 15:47:33 +0000 (10:47 -0500)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 3 Jan 2012 15:47:33 +0000 (10:47 -0500)
if the main process's fds 0-2 are not hooked up to a tty.  Adapted
from a diff by Zdenek Behan.

src/sudo.c

index 15e78e9e53465b826f02138474ef6ed5587b8447..0cc8f8c3c2cf4933a8929a1e3aa3e85b40a3416e 100644 (file)
@@ -421,6 +421,39 @@ get_user_groups(struct user_details *ud)
     debug_return_str(gid_list);
 }
 
+/*
+ * Return a string from ttyname() containing the tty to which the process is
+ * attached or NULL if there is no tty associated with the process (or its
+ * parent).  First tries std{in,out,err} then falls back to the parent's /proc
+ * entry.  We could try following the parent all the way to pid 1 but
+ * /proc/%d/status is system-specific (text on Linux, a struct on Solaris).
+ */
+static char *
+get_process_tty(void)
+{
+    char path[PATH_MAX], *tty = NULL;
+    pid_t ppid;
+    int i, fd;
+    debug_decl(get_process_tty, SUDO_DEBUG_UTIL)
+
+    if ((tty = ttyname(STDIN_FILENO)) == NULL &&
+       (tty = ttyname(STDOUT_FILENO)) == NULL &&
+       (tty = ttyname(STDERR_FILENO)) == NULL) {
+       /* No tty for child, check the parent via /proc. */
+       ppid = getppid();
+       for (i = STDIN_FILENO; i < STDERR_FILENO && tty == NULL; i++) {
+           snprintf(path, sizeof(path), "/proc/%d/fd/%d", ppid, i);
+           fd = open(path, O_RDONLY|O_NOCTTY, 0);
+           if (fd != -1) {
+               tty = ttyname(fd);
+               close(fd);
+           }
+       }
+    }
+
+    debug_return_str(tty);
+}
+
 /*
  * Return user information as an array of name=value pairs.
  * and fill in struct user_details (which shares the same strings).
@@ -471,8 +504,7 @@ get_user_info(struct user_details *ud)
        ud->cwd = user_info[i] + sizeof("cwd=") - 1;
     }
 
-    if ((cp = ttyname(STDIN_FILENO)) || (cp = ttyname(STDOUT_FILENO)) ||
-       (cp = ttyname(STDERR_FILENO))) {
+    if ((cp = get_process_tty()) != NULL) {
        user_info[++i] = fmt_string("tty", cp);
        if (user_info[i] == NULL)
            errorx(1, _("unable to allocate memory"));