summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiovanni Campagna <gcampagn@redhat.com>2013-08-20 15:45:08 +0200
committerGiovanni Campagna <gcampagn@redhat.com>2013-08-28 11:12:43 +0200
commit1cb5284113a2b3ddd924c3f875797b5253a2a4cf (patch)
tree968e9eec2880671440c867934a849f261837c598
parentb1e758b34192aee3be44f43415ffde5eae66a9d2 (diff)
downloadmutter-1cb5284113a2b3ddd924c3f875797b5253a2a4cf.tar.gz
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
-rw-r--r--configure.ac5
-rw-r--r--src/wayland/weston-launch.c72
2 files changed, 46 insertions, 31 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;
-
- 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;
- }
+ 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;
}
@@ -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];