From 30ff420ca9707fbbde7e70e789a8698058b4cb4b Mon Sep 17 00:00:00 2001 From: Dylan Noblesmith Date: Sat, 30 Jun 2012 19:50:09 +0000 Subject: wayland-server: fix socket ownership race condition Always unlink() the lock file before closing the file descriptor for it. Otherwise, there is a race like this: Process A closes fd, releasing the lock Process B opens the same file, taking the lock Process A unlinks the lock file Process C opens the same file, which now no longer exists, and takes the lock on the newly created lock file Process B and C both 'own' the same display socket. unlink()ing while holding the lock is effectively a better way to release the lock atomically. --- src/wayland-server.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/wayland-server.c b/src/wayland-server.c index 93cc38a..72aa88d 100644 --- a/src/wayland-server.c +++ b/src/wayland-server.c @@ -1001,10 +1001,10 @@ wl_display_destroy(struct wl_display *display) wl_list_for_each_safe(s, next, &display->socket_list, link) { wl_event_source_remove(s->source); - close(s->fd); unlink(s->addr.sun_path); - close(s->fd_lock); + close(s->fd); unlink(s->lock_addr); + close(s->fd_lock); free(s); } wl_event_loop_destroy(display->loop); @@ -1196,18 +1196,18 @@ wl_display_add_socket(struct wl_display *display, const char *name) size = offsetof (struct sockaddr_un, sun_path) + name_size; if (bind(s->fd, (struct sockaddr *) &s->addr, size) < 0) { - close(s->fd_lock); - unlink(s->lock_addr); close(s->fd); + unlink(s->lock_addr); + close(s->fd_lock); free(s); return -1; } if (listen(s->fd, 1) < 0) { - close(s->fd_lock); - unlink(s->lock_addr); - close(s->fd); unlink(s->addr.sun_path); + close(s->fd); + unlink(s->lock_addr); + close(s->fd_lock); free(s); return -1; } @@ -1216,10 +1216,10 @@ wl_display_add_socket(struct wl_display *display, const char *name) WL_EVENT_READABLE, socket_data, display); if (s->source == NULL) { - close(s->fd_lock); - unlink(s->lock_addr); - close(s->fd); unlink(s->addr.sun_path); + close(s->fd); + unlink(s->lock_addr); + close(s->fd_lock); free(s); return -1; } -- cgit v1.2.3