security: fix file descriptor leak in PulseAudio server on_connect error path

File and Resource Handling: Medium

In on_connect(), if client_new() fails or pw_loop_add_io() fails, the
accepted client_fd is never closed. The error path only calls
client_free() which relies on pw_loop_destroy_source() to close the fd,
but if the source was never created, the fd leaks.

Fix by closing client_fd in the error path when it has not been
transferred to a loop source.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Wim Taymans 2026-04-29 14:15:18 +02:00
parent 398326f19c
commit 0c4a0dcf7d

View file

@ -391,7 +391,6 @@ on_connect(void *data, int fd, uint32_t mask)
} }
if (server->n_clients >= server->max_clients) { if (server->n_clients >= server->max_clients) {
close(client_fd);
error_reason = "too many client application connections"; error_reason = "too many client application connections";
errno = ECONNREFUSED; errno = ECONNREFUSED;
goto error; goto error;
@ -404,7 +403,7 @@ on_connect(void *data, int fd, uint32_t mask)
pw_log_debug("server %p: new client %p fd:%d", server, client, client_fd); pw_log_debug("server %p: new client %p fd:%d", server, client, client_fd);
client->source = pw_loop_add_io(impl->main_loop, client->source = pw_loop_add_io(impl->main_loop,
client_fd, spa_steal_fd(client_fd),
SPA_IO_ERR | SPA_IO_HUP | SPA_IO_IN, SPA_IO_ERR | SPA_IO_HUP | SPA_IO_IN,
true, on_client_data, client); true, on_client_data, client);
if (client->source == NULL) if (client->source == NULL)
@ -521,6 +520,8 @@ error:
if (client) if (client)
client_free(client); client_free(client);
if (client_fd >= 0)
close(client_fd);
} }
static int parse_unix_address(const char *address, struct sockaddr_storage *addrs, int len) static int parse_unix_address(const char *address, struct sockaddr_storage *addrs, int len)