diff --git a/include/wlr/xwayland/server.h b/include/wlr/xwayland/server.h index b699b8f4f..baab3f29f 100644 --- a/include/wlr/xwayland/server.h +++ b/include/wlr/xwayland/server.h @@ -35,8 +35,8 @@ struct wlr_xwayland_server { int display; char display_name[16]; - int x_fd[2]; - struct wl_event_source *x_fd_read_event[2]; + int x_fd; + struct wl_event_source *x_fd_read_event; struct wlr_xwayland_server_options options; struct wl_display *wl_display; diff --git a/xwayland/server.c b/xwayland/server.c index 0e8ad44fe..f2520e7ab 100644 --- a/xwayland/server.c +++ b/xwayland/server.c @@ -25,8 +25,7 @@ static void safe_close(int fd) { noreturn static void exec_xwayland(struct wlr_xwayland_server *server, int notify_fd) { - if (!set_cloexec(server->x_fd[0], false) || - !set_cloexec(server->x_fd[1], false) || + if (!set_cloexec(server->x_fd, false) || !set_cloexec(server->wl_fd[1], false)) { wlr_log(WLR_ERROR, "Failed to unset CLOEXEC on FD"); _exit(EXIT_FAILURE); @@ -39,9 +38,8 @@ noreturn static void exec_xwayland(struct wlr_xwayland_server *server, char *argv[64] = {0}; size_t i = 0; - char listenfd0[16], listenfd1[16], displayfd[16]; - snprintf(listenfd0, sizeof(listenfd0), "%d", server->x_fd[0]); - snprintf(listenfd1, sizeof(listenfd1), "%d", server->x_fd[1]); + char listenfd[16], displayfd[16]; + snprintf(listenfd, sizeof(listenfd), "%d", server->x_fd); snprintf(displayfd, sizeof(displayfd), "%d", notify_fd); argv[i++] = "Xwayland"; @@ -61,14 +59,10 @@ noreturn static void exec_xwayland(struct wlr_xwayland_server *server, #if HAVE_XWAYLAND_LISTENFD argv[i++] = "-listenfd"; - argv[i++] = listenfd0; - argv[i++] = "-listenfd"; - argv[i++] = listenfd1; + argv[i++] = listenfd; #else argv[i++] = "-listen"; - argv[i++] = listenfd0; - argv[i++] = "-listen"; - argv[i++] = listenfd1; + argv[i++] = listenfd; #endif argv[i++] = "-displayfd"; argv[i++] = displayfd; @@ -141,11 +135,9 @@ static void server_finish_process(struct wlr_xwayland_server *server) { return; } - if (server->x_fd_read_event[0]) { - wl_event_source_remove(server->x_fd_read_event[0]); - wl_event_source_remove(server->x_fd_read_event[1]); - - server->x_fd_read_event[0] = server->x_fd_read_event[1] = NULL; + if (server->x_fd_read_event) { + wl_event_source_remove(server->x_fd_read_event); + server->x_fd_read_event = NULL; } if (server->client) { @@ -182,9 +174,8 @@ static void server_finish_display(struct wlr_xwayland_server *server) { return; } - safe_close(server->x_fd[0]); - safe_close(server->x_fd[1]); - server->x_fd[0] = server->x_fd[1] = -1; + safe_close(server->x_fd); + server->x_fd = -1; unlink_display_sockets(server->display); server->display = -1; @@ -309,7 +300,7 @@ static bool server_start_display(struct wlr_xwayland_server *server, server->display_destroy.notify = handle_display_destroy; wl_display_add_destroy_listener(wl_display, &server->display_destroy); - server->display = open_display_sockets(server->x_fd); + server->display = open_display_sockets(&server->x_fd); if (server->display < 0) { server_finish_display(server); return false; @@ -412,9 +403,8 @@ static bool server_start(struct wlr_xwayland_server *server) { static int xwayland_socket_connected(int fd, uint32_t mask, void *data) { struct wlr_xwayland_server *server = data; - wl_event_source_remove(server->x_fd_read_event[0]); - wl_event_source_remove(server->x_fd_read_event[1]); - server->x_fd_read_event[0] = server->x_fd_read_event[1] = NULL; + wl_event_source_remove(server->x_fd_read_event); + server->x_fd_read_event = NULL; server_start(server); @@ -424,18 +414,11 @@ static int xwayland_socket_connected(int fd, uint32_t mask, void *data) { static bool server_start_lazy(struct wlr_xwayland_server *server) { struct wl_event_loop *loop = wl_display_get_event_loop(server->wl_display); - if (!(server->x_fd_read_event[0] = wl_event_loop_add_fd(loop, server->x_fd[0], + if (!(server->x_fd_read_event = wl_event_loop_add_fd(loop, server->x_fd, WL_EVENT_READABLE, xwayland_socket_connected, server))) { return false; } - if (!(server->x_fd_read_event[1] = wl_event_loop_add_fd(loop, server->x_fd[1], - WL_EVENT_READABLE, xwayland_socket_connected, server))) { - wl_event_source_remove(server->x_fd_read_event[0]); - server->x_fd_read_event[0] = NULL; - return false; - } - return true; } @@ -485,7 +468,7 @@ struct wlr_xwayland_server *wlr_xwayland_server_create( server->options.terminate_delay = 0; #endif - server->x_fd[0] = server->x_fd[1] = -1; + server->x_fd = -1; server->wl_fd[0] = server->wl_fd[1] = -1; server->wm_fd[0] = server->wm_fd[1] = -1; diff --git a/xwayland/sockets.c b/xwayland/sockets.c index 9e287f361..f1ab752fa 100644 --- a/xwayland/sockets.c +++ b/xwayland/sockets.c @@ -18,9 +18,6 @@ static const char lock_fmt[] = "/tmp/.X%d-lock"; static const char socket_dir[] = "/tmp/.X11-unix"; static const char socket_fmt[] = "/tmp/.X11-unix/X%d"; -#ifndef __linux__ -static const char socket_fmt2[] = "/tmp/.X11-unix/X%d_"; -#endif bool set_cloexec(int fd, bool cloexec) { int flags = fcntl(fd, F_GETFD); @@ -40,51 +37,6 @@ bool set_cloexec(int fd, bool cloexec) { return true; } -static int open_socket(struct sockaddr_un *addr, size_t path_size) { - int fd, rc; - socklen_t size = offsetof(struct sockaddr_un, sun_path) + path_size + 1; - - fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (fd < 0) { - wlr_log_errno(WLR_ERROR, "Failed to create socket %c%s", - addr->sun_path[0] ? addr->sun_path[0] : '@', - addr->sun_path + 1); - return -1; - } - if (!set_cloexec(fd, true)) { - close(fd); - return -1; - } - - if (addr->sun_path[0]) { - unlink(addr->sun_path); - } - if (bind(fd, (struct sockaddr*)addr, size) < 0) { - rc = errno; - wlr_log_errno(WLR_ERROR, "Failed to bind socket %c%s", - addr->sun_path[0] ? addr->sun_path[0] : '@', - addr->sun_path + 1); - goto cleanup; - } - if (listen(fd, 1) < 0) { - rc = errno; - wlr_log_errno(WLR_ERROR, "Failed to listen to socket %c%s", - addr->sun_path[0] ? addr->sun_path[0] : '@', - addr->sun_path + 1); - goto cleanup; - } - - return fd; - -cleanup: - close(fd); - if (addr->sun_path[0]) { - unlink(addr->sun_path); - } - errno = rc; - return -1; -} - static bool check_socket_dir(void) { struct stat buf; @@ -111,66 +63,91 @@ static bool check_socket_dir(void) { return true; } -static bool open_sockets(int socks[2], int display) { - struct sockaddr_un addr = { .sun_family = AF_UNIX }; - size_t path_size; +static bool setup_socket_dir(void) { + mode_t dir_mode = 01777; - 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) { + if (mkdir(socket_dir, dir_mode) != 0) { + if (errno == EEXIST) { + return check_socket_dir(); + } 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; - path_size = snprintf(addr.sun_path + 1, sizeof(addr.sun_path) - 1, socket_fmt, display); -#else - path_size = snprintf(addr.sun_path, sizeof(addr.sun_path), socket_fmt2, display); -#endif - socks[0] = open_socket(&addr, path_size); - if (socks[0] < 0) { - return false; - } + wlr_log(WLR_INFO, "Created %s ourselves -- other users will " + "be unable to create X11 UNIX sockets of their own", + socket_dir); - path_size = snprintf(addr.sun_path, sizeof(addr.sun_path), socket_fmt, display); - socks[1] = open_socket(&addr, path_size); - if (socks[1] < 0) { - close(socks[0]); - socks[0] = -1; + // The mode passed to mkdir() is affected by umask, so set it again + if (chmod(socket_dir, dir_mode) != 0) { + wlr_log_errno(WLR_ERROR, "Failed to chmod %s", socket_dir); return false; } return true; } -void unlink_display_sockets(int display) { - char sun_path[64]; +static int open_socket(int display) { + if (!setup_socket_dir()) { + return -1; + } - snprintf(sun_path, sizeof(sun_path), socket_fmt, display); - unlink(sun_path); + struct sockaddr_un addr = { .sun_family = AF_UNIX }; + size_t path_size = snprintf(addr.sun_path, sizeof(addr.sun_path), socket_fmt, display); -#ifndef __linux__ - snprintf(sun_path, sizeof(sun_path), socket_fmt2, display); - unlink(sun_path); -#endif + socklen_t size = offsetof(struct sockaddr_un, sun_path) + path_size + 1; - snprintf(sun_path, sizeof(sun_path), lock_fmt, display); - unlink(sun_path); + int fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd < 0) { + wlr_log_errno(WLR_ERROR, "Failed to create socket %s", addr.sun_path); + return -1; + } + if (!set_cloexec(fd, true)) { + close(fd); + return -1; + } + + int rc; + unlink(addr.sun_path); + if (bind(fd, (struct sockaddr *)&addr, size) < 0) { + rc = errno; + wlr_log_errno(WLR_ERROR, "Failed to bind socket %s", addr.sun_path); + goto cleanup; + } + if (listen(fd, 1) < 0) { + rc = errno; + wlr_log_errno(WLR_ERROR, "Failed to listen to socket %s", addr.sun_path); + goto cleanup; + } + + return fd; + +cleanup: + close(fd); + unlink(addr.sun_path); + errno = rc; + return -1; } -int open_display_sockets(int socks[2]) { +void unlink_display_sockets(int display) { + char path[64]; + + snprintf(path, sizeof(path), socket_fmt, display); + unlink(path); + + snprintf(path, sizeof(path), lock_fmt, display); + unlink(path); +} + +int open_display_sockets(int *sock) { int lock_fd, display; char lock_name[64]; for (display = 0; display <= 32; display++) { snprintf(lock_name, sizeof(lock_name), lock_fmt, display); if ((lock_fd = open(lock_name, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0444)) >= 0) { - if (!open_sockets(socks, display)) { + *sock = open_socket(display); + if (*sock < 0) { unlink(lock_name); close(lock_fd); continue; diff --git a/xwayland/sockets.h b/xwayland/sockets.h index 4c55a087e..7797e5574 100644 --- a/xwayland/sockets.h +++ b/xwayland/sockets.h @@ -5,6 +5,6 @@ bool set_cloexec(int fd, bool cloexec); void unlink_display_sockets(int display); -int open_display_sockets(int socks[2]); +int open_display_sockets(int *sock); #endif