[mutter/wip/wayland-work: 41/44] mutter-launch: use systemd to obtain the TTY



commit 1510f8e1664be774dbf6421114150567dd1853b6
Author: Giovanni Campagna <gcampagn redhat com>
Date:   Thu Aug 22 11:40:11 2013 +0200

    mutter-launch: use systemd to obtain the TTY
    
    Using the command line or an environment variable is dangerous,
    as those can be spoofed to gain access to other sessions.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=705861

 configure.ac                |    5 +++
 src/wayland/weston-launch.c |   81 ++++++++++++++++++++++---------------------
 2 files changed, 46 insertions(+), 40 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 705350a..efd8fb8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -141,6 +141,11 @@ AM_GLIB_GNU_GETTEXT
 PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.14.0)
 PKG_CHECK_MODULES(MUTTER_LAUNCH, libdrm libsystemd-login)
 
+saved_LIBS="$LIBS"
+LIBS="$LIBS $MUTTER_LAUNCH"
+AC_CHECK_FUNCS([sd_session_get_vt])
+LIBS="$saved_LIBS"
+
 # Unconditionally use this dir to avoid a circular dep with gnomecc
 GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings"
 AC_SUBST(GNOME_KEYBINDINGS_KEYSDIR)
diff --git a/src/wayland/weston-launch.c b/src/wayland/weston-launch.c
index a1cf72e..c1518b4 100644
--- a/src/wayland/weston-launch.c
+++ b/src/wayland/weston-launch.c
@@ -53,9 +53,7 @@
 
 #include <xf86drm.h>
 
-#ifdef HAVE_SYSTEMD_LOGIN
 #include <systemd/sd-login.h>
-#endif
 
 #include "weston-launch.h"
 
@@ -353,40 +351,52 @@ handle_signal(struct weston_launch *wl)
 }
 
 static int
-setup_tty(struct weston_launch *wl, const char *tty)
+setup_tty(struct weston_launch *wl)
 {
        struct stat buf;
-       char *t;
-
-       if (tty) {
-               t = ttyname(STDIN_FILENO);
-               if (t && strcmp(t, tty) == 0)
-                       wl->tty = STDIN_FILENO;
-               else
-                       wl->tty = open(tty, O_RDWR | O_NOCTTY);
-       } else {
-               if (isatty (STDIN_FILENO))
-                       wl->tty = STDIN_FILENO;
-               else {
-                       char path[PATH_MAX];
-
-                       snprintf(path, PATH_MAX, "/dev/tty%s", getenv("XDG_VTNR"));
-                       wl->tty = open(path, O_RDWR | O_NOCTTY);
-               }
-       }
+       char *session, *tty;
+       char path[PATH_MAX];
+       int ok;
+
+       ok = sd_pid_get_session(getpid(), &session);
+       if (ok < 0)
+         error(1, -ok, "could not determine current session");
+
+       ok = sd_session_get_tty(session, &tty);
+       if (ok == 0) {
+               snprintf(path, PATH_MAX, "/dev/%s", tty);
+               wl->tty = open(path, O_RDWR | O_NOCTTY);
+               free(tty);
+#ifdef HAVE_SD_SESSION_GET_VT
+       } else if (ok == -ENOENT) {
+               /* Negative errnos are cool, right?
+                  So cool that we can't distinguish "session not found"
+                  from "key does not exist in the session file"!
+                  Let's assume the latter, as we got the value
+                  from sd_pid_get_session()...
+               */
+
+               ok = sd_session_get_vt(session, &tty);
+               if (ok < 0)
+                       error(1, -ok, "could not determine current TTY");
+
+               snprintf(path, PATH_MAX, "/dev/tty%s", tty);
+               wl->tty = open(path, O_RDWR | O_NOCTTY);
+               free(tty);
+#endif
+       } else
+               error(1, -ok, "could not determine current TTY");
 
        if (wl->tty < 0)
                error(1, errno, "failed to open tty");
 
-       if (tty) {
-               if (fstat(wl->tty, &buf) < 0)
-                       error(1, errno, "stat %s failed", tty);
+       if (fstat(wl->tty, &buf) < 0)
+               error(1, errno, "stat %s failed", path);
 
-               if (major(buf.st_rdev) != TTY_MAJOR)
-                       error(1, 0, "invalid tty device: %s", tty);
+       if (major(buf.st_rdev) != TTY_MAJOR)
+               error(1, 0, "invalid tty device: %s", path);
 
-               wl->ttynr = minor(buf.st_rdev);
-       }
+       wl->ttynr = minor(buf.st_rdev);
 
        return 0;
 }
@@ -415,9 +425,7 @@ launch_compositor(struct weston_launch *wl, int argc, char *argv[])
 
        drop_privileges(wl);
 
-       if (wl->tty != STDIN_FILENO)
-               setenv_fd("WESTON_TTY_FD", wl->tty);
-
+       setenv_fd("WESTON_TTY_FD", wl->tty);
        setenv_fd("WESTON_LAUNCHER_SOCK", wl->sock[1]);
        setenv("LD_LIBRARY_PATH", LIBDIR, 1);
        unsetenv("DISPLAY");
@@ -448,7 +456,6 @@ help(const char *name)
 {
        fprintf(stderr, "Usage: %s [args...] [-- [weston args..]]\n", name);
        fprintf(stderr, "  -u, --user      Start session as specified username\n");
-       fprintf(stderr, "  -t, --tty       Start session on alternative tty\n");
        fprintf(stderr, "  -v, --verbose   Be verbose\n");
        fprintf(stderr, "  -h, --help      Display this help message\n");
 }
@@ -458,9 +465,7 @@ main(int argc, char *argv[])
 {
        struct weston_launch wl;
        int i, c;
-       char *tty = NULL;
        struct option opts[] = {
-               { "tty",     required_argument, NULL, 't' },
                { "verbose", no_argument,       NULL, 'v' },
                { "help",    no_argument,       NULL, 'h' },
                { 0,         0,                 NULL,  0  }
@@ -470,9 +475,6 @@ main(int argc, char *argv[])
 
        while ((c = getopt_long(argc, argv, "u:t::vh", opts, &i)) != -1) {
                switch (c) {
-               case 't':
-                       tty = optarg;
-                       break;
                case 'v':
                        wl.verbose = 1;
                        break;
@@ -493,7 +495,7 @@ main(int argc, char *argv[])
        if (wl.pw == NULL)
                error(1, errno, "failed to get username");
 
-       if (setup_tty(&wl, tty) < 0)
+       if (setup_tty(&wl) < 0)
                exit(EXIT_FAILURE);
 
        if (setup_launcher_socket(&wl) < 0)
@@ -512,8 +514,7 @@ main(int argc, char *argv[])
                launch_compositor(&wl, argc - optind, argv + optind);
 
        close(wl.sock[1]);
-       if (wl.tty != STDIN_FILENO)
-               close(wl.tty);
+       close(wl.tty);
 
        while (1) {
                struct pollfd fds[2];


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]