module-protocol-native: close fds from zombie clients

When a client is zombie, close the fds we got in the discarded message
or else we leak them.

See #1840
This commit is contained in:
Wim Taymans 2023-06-05 13:28:04 +02:00
parent 22acf94f7d
commit 8db98b114d
2 changed files with 16 additions and 5 deletions

View file

@ -919,12 +919,18 @@ process_remote(struct client *impl)
proxy = pw_core_find_proxy(this, msg->id); proxy = pw_core_find_proxy(this, msg->id);
if (proxy == NULL || proxy->zombie) { if (proxy == NULL || proxy->zombie) {
uint32_t i;
if (proxy == NULL) if (proxy == NULL)
pw_log_error("%p: could not find proxy %u", this, msg->id); pw_log_error("%p: could not find proxy %u", this, msg->id);
else else
pw_log_debug("%p: zombie proxy %u", this, msg->id); pw_log_debug("%p: zombie proxy %u", this, msg->id);
/* FIXME close fds */ /* close fds */
for (i = 0; i < msg->n_fds; i++) {
pw_log_debug("%p: close fd:%d", conn, msg->fds[i]);
close(msg->fds[i]);
}
continue; continue;
} }

View file

@ -205,7 +205,7 @@ static int refill_buffer(struct pw_protocol_native_connection *conn, struct buff
char cmsgbuf[CMSG_SPACE(MAX_FDS_MSG * sizeof(int))]; char cmsgbuf[CMSG_SPACE(MAX_FDS_MSG * sizeof(int))];
struct cmsghdr align; struct cmsghdr align;
} cmsgbuf; } cmsgbuf;
int n_fds = 0; int i, n_fds = 0, *fds;
size_t avail; size_t avail;
avail = buf->buffer_maxsize - buf->buffer_size; avail = buf->buffer_maxsize - buf->buffer_size;
@ -242,10 +242,13 @@ static int refill_buffer(struct pw_protocol_native_connection *conn, struct buff
continue; continue;
n_fds = cmsg_data_length(cmsg) / sizeof(int); n_fds = cmsg_data_length(cmsg) / sizeof(int);
fds = (int*)CMSG_DATA(cmsg);
if (n_fds + buf->n_fds > MAX_FDS) if (n_fds + buf->n_fds > MAX_FDS)
goto too_many_fds; goto too_many_fds;
memcpy(&buf->fds[buf->n_fds], CMSG_DATA(cmsg), n_fds * sizeof(int)); for (i = 0; i < n_fds; i++) {
buf->n_fds += n_fds; pw_log_debug("connection %p: buffer:%p got fd:%d", conn, buf, fds[i]);
buf->fds[buf->n_fds++] = fds[i];
}
} }
pw_log_trace("connection %p: %d read %zd bytes and %d fds", conn, conn->fd, len, pw_log_trace("connection %p: %d read %zd bytes and %d fds", conn, conn->fd, len,
n_fds); n_fds);
@ -272,7 +275,7 @@ static void clear_buffer(struct buffer *buf, bool fds)
{ {
uint32_t i; uint32_t i;
pw_log_debug("clear fds:%d", fds); pw_log_debug("%p clear fds:%d n_fds:%d", buf, fds, buf->n_fds);
if (fds) { if (fds) {
for (i = 0; i < buf->n_fds; i++) { for (i = 0; i < buf->n_fds; i++) {
pw_log_debug("%p: close fd:%d", buf, buf->fds[i]); pw_log_debug("%p: close fd:%d", buf, buf->fds[i]);
@ -848,6 +851,8 @@ int pw_protocol_native_connection_clear(struct pw_protocol_native_connection *co
{ {
struct impl *impl = SPA_CONTAINER_OF(conn, struct impl, this); struct impl *impl = SPA_CONTAINER_OF(conn, struct impl, this);
pw_log_debug("%p: clear", conn);
clear_buffer(&impl->out, true); clear_buffer(&impl->out, true);
clear_buffer(&impl->in, true); clear_buffer(&impl->in, true);