diff options
author | Ryan Farley <ryan.farley@gmx.com> | 2021-04-13 19:41:27 -0500 |
---|---|---|
committer | Simon Ser <contact@emersion.fr> | 2021-04-16 11:53:05 +0200 |
commit | d87ede0d695b0b891fda45e85df94cb5b1c3bf0e (patch) | |
tree | 1c0d4fec947df7ecde309d0d60ca7ded942ff9f9 | |
parent | 3c6826df7108fd11427817602023c03b94a6ec46 (diff) |
xwayland/sockets: ensure proper permissions
Create a private UNIX socket directory (755), or use an existing one but
ensure proper permissions are set to prevent meddling from other users.
-rw-r--r-- | xwayland/sockets.c | 39 |
1 files changed, 37 insertions, 2 deletions
diff --git a/xwayland/sockets.c b/xwayland/sockets.c index 6360745f..873fde8d 100644 --- a/xwayland/sockets.c +++ b/xwayland/sockets.c @@ -1,4 +1,4 @@ -#define _POSIX_C_SOURCE 200809L +#define _XOPEN_SOURCE 700 #include <errno.h> #include <fcntl.h> #include <signal.h> @@ -84,11 +84,46 @@ cleanup: return -1; } +static bool check_socket_dir(void) { + struct stat buf; + + if (lstat(socket_dir, &buf)) { + wlr_log_errno(WLR_ERROR, "Failed to stat %s", socket_dir); + return false; + } + if (!(buf.st_mode & S_IFDIR)) { + wlr_log(WLR_ERROR, "%s is not a directory", socket_dir); + return false; + } + if (!((buf.st_uid == 0) || (buf.st_uid == getuid()))) { + wlr_log(WLR_ERROR, "%s not owned by root or us", socket_dir); + return false; + } + if (!(buf.st_mode & S_ISVTX)) { + /* we can deal with no sticky bit... */ + if ((buf.st_mode & (S_IWGRP | S_IWOTH))) { + /* but not if other users can mess with our sockets */ + wlr_log(WLR_ERROR, "sticky bit not set on %s", socket_dir); + return false; + } + } + return true; +} + static bool open_sockets(int socks[2], int display) { struct sockaddr_un addr = { .sun_family = AF_UNIX }; size_t path_size; - mkdir(socket_dir, 0777); + if (mkdir(socket_dir, 0755) == 0) { + wlr_log(WLR_INFO, "Created %s ourselves -- other users will " + "be unable to create X11 UNIX sockets of their own", + socket_dir); + } else if (errno != EEXIST) { + wlr_log_errno(WLR_ERROR, "Unable to mkdir %s", socket_dir); + return false; + } else if (!check_socket_dir()) { + return false; + } #ifdef __linux__ addr.sun_path[0] = 0; |