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
This commit is contained in:
Giovanni Campagna 2013-08-20 15:45:08 +02:00
parent 1c34f0b342
commit e263b3624c
2 changed files with 45 additions and 30 deletions

View File

@ -141,6 +141,11 @@ AM_GLIB_GNU_GETTEXT
PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.14.0) PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.14.0)
PKG_CHECK_MODULES(MUTTER_LAUNCH, libdrm libsystemd-login) 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 # Unconditionally use this dir to avoid a circular dep with gnomecc
GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings" GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings"
AC_SUBST(GNOME_KEYBINDINGS_KEYSDIR) AC_SUBST(GNOME_KEYBINDINGS_KEYSDIR)

View File

@ -374,33 +374,52 @@ handle_signal(struct weston_launch *wl)
} }
static int static int
setup_tty(struct weston_launch *wl, const char *tty) setup_tty(struct weston_launch *wl)
{ {
struct stat buf; struct stat buf;
char *t; char *session, *tty;
char path[PATH_MAX];
int ok;
if (tty) { ok = sd_pid_get_session(getpid(), &session);
t = ttyname(STDIN_FILENO); if (ok < 0)
if (t && strcmp(t, tty) == 0) error(1, -ok, "could not determine current session");
wl->tty = STDIN_FILENO;
else ok = sd_session_get_tty(session, &tty);
wl->tty = open(tty, O_RDWR | O_NOCTTY); if (ok == 0) {
} else { snprintf(path, PATH_MAX, "/dev/%s", tty);
wl->tty = STDIN_FILENO; 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) if (wl->tty < 0)
error(1, errno, "failed to open tty"); error(1, errno, "failed to open tty");
if (tty) { if (fstat(wl->tty, &buf) < 0)
if (fstat(wl->tty, &buf) < 0) error(1, errno, "stat %s failed", path);
error(1, errno, "stat %s failed", tty);
if (major(buf.st_rdev) != TTY_MAJOR) if (major(buf.st_rdev) != TTY_MAJOR)
error(1, 0, "invalid tty device: %s", tty); error(1, 0, "invalid tty device: %s", path);
wl->ttynr = minor(buf.st_rdev); wl->ttynr = minor(buf.st_rdev);
}
return 0; return 0;
} }
@ -429,9 +448,7 @@ launch_compositor(struct weston_launch *wl, int argc, char *argv[])
drop_privileges(wl); 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_fd("WESTON_LAUNCHER_SOCK", wl->sock[1]);
setenv("LD_LIBRARY_PATH", LIBDIR, 1); setenv("LD_LIBRARY_PATH", LIBDIR, 1);
unsetenv("DISPLAY"); unsetenv("DISPLAY");
@ -462,7 +479,6 @@ help(const char *name)
{ {
fprintf(stderr, "Usage: %s [args...] [-- [weston args..]]\n", name); fprintf(stderr, "Usage: %s [args...] [-- [weston args..]]\n", name);
fprintf(stderr, " -u, --user Start session as specified username\n"); 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, " -v, --verbose Be verbose\n");
fprintf(stderr, " -h, --help Display this help message\n"); fprintf(stderr, " -h, --help Display this help message\n");
} }
@ -472,9 +488,7 @@ main(int argc, char *argv[])
{ {
struct weston_launch wl; struct weston_launch wl;
int i, c; int i, c;
char *tty = NULL;
struct option opts[] = { struct option opts[] = {
{ "tty", required_argument, NULL, 't' },
{ "verbose", no_argument, NULL, 'v' }, { "verbose", no_argument, NULL, 'v' },
{ "help", no_argument, NULL, 'h' }, { "help", no_argument, NULL, 'h' },
{ 0, 0, NULL, 0 } { 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) { while ((c = getopt_long(argc, argv, "u:t::vh", opts, &i)) != -1) {
switch (c) { switch (c) {
case 't':
tty = optarg;
break;
case 'v': case 'v':
wl.verbose = 1; wl.verbose = 1;
break; break;
@ -510,7 +521,7 @@ main(int argc, char *argv[])
if (!weston_launch_allowed(&wl)) if (!weston_launch_allowed(&wl))
error(1, 0, "Permission denied. You must run from an active and local (systemd) session."); 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); exit(EXIT_FAILURE);
if (setup_launcher_socket(&wl) < 0) if (setup_launcher_socket(&wl) < 0)
@ -529,8 +540,7 @@ main(int argc, char *argv[])
launch_compositor(&wl, argc - optind, argv + optind); launch_compositor(&wl, argc - optind, argv + optind);
close(wl.sock[1]); close(wl.sock[1]);
if (wl.tty != STDIN_FILENO) close(wl.tty);
close(wl.tty);
while (1) { while (1) {
struct pollfd fds[2]; struct pollfd fds[2];