From e263b3624c417960e09d02d8ff97b1e763d58843 Mon Sep 17 00:00:00 2001 From: Giovanni Campagna Date: Tue, 20 Aug 2013 15:45:08 +0200 Subject: [PATCH] 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 | 70 +++++++++++++++++++++---------------- 2 files changed, 45 insertions(+), 30 deletions(-) diff --git a/configure.ac b/configure.ac index 7072ea119..415ca5d42 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 8e6587d97..8fab8494e 100644 --- a/src/wayland/weston-launch.c +++ b/src/wayland/weston-launch.c @@ -374,33 +374,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; + char *session, *tty; + char path[PATH_MAX]; + int ok; - 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 { - wl->tty = STDIN_FILENO; - } + 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; } @@ -429,9 +448,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"); @@ -462,7 +479,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"); } @@ -472,9 +488,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 } @@ -484,9 +498,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; @@ -510,7 +521,7 @@ main(int argc, char *argv[]) if (!weston_launch_allowed(&wl)) error(1, 0, "Permission denied. You must run from an active and local (systemd) session."); - if (setup_tty(&wl, tty) < 0) + if (setup_tty(&wl) < 0) exit(EXIT_FAILURE); if (setup_launcher_socket(&wl) < 0) @@ -529,8 +540,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];