stream: only mmap buffers when not already mapped

Don't just blindly mmap the buffer but only when the data pointer
is NULL. If it was mapped already by the peer or the adapter or the
buffer allocation, we don't want to mmap it again and override the buffer
data pointer.

Also mmap with the permissions on the data. There is not much point in
limiting the permissions for an input port (to read only). We could do
this but then we would not be allowed to modify the existing data
pointer. The problem is that when the stream mmaps the data as READ only
and set the data pointer, if it is then handed to the mixer, it would
assume it is mapped with the permissions and then segfault when it
tries to write to the memory. It's just better to only mmap when the
data is NULL.
This commit is contained in:
Wim Taymans 2025-10-06 13:17:00 +02:00
parent e7bc261830
commit 5ccaf29793
2 changed files with 14 additions and 9 deletions

View file

@ -885,8 +885,7 @@ static int impl_port_use_buffers(void *object,
struct port *port;
struct pw_filter *filter = &impl->this;
uint32_t i, j, impl_flags;
int prot, res;
int size = 0;
int res, size = 0;
pw_log_debug("%p: port:%d.%d buffers:%u disconnecting:%d", impl,
direction, port_id, n_buffers, impl->disconnecting);
@ -900,7 +899,6 @@ static int impl_port_use_buffers(void *object,
clear_buffers(port);
impl_flags = port->flags;
prot = PROT_READ | (direction == SPA_DIRECTION_OUTPUT ? PROT_WRITE : 0);
if (n_buffers > MAX_BUFFERS)
return -ENOSPC;
@ -915,7 +913,12 @@ static int impl_port_use_buffers(void *object,
if (SPA_FLAG_IS_SET(impl_flags, PW_FILTER_PORT_FLAG_MAP_BUFFERS)) {
for (j = 0; j < buffers[i]->n_datas; j++) {
struct spa_data *d = &buffers[i]->datas[j];
if (SPA_FLAG_IS_SET(d->flags, SPA_DATA_FLAG_MAPPABLE)) {
if (d->data == NULL && SPA_FLAG_IS_SET(d->flags, SPA_DATA_FLAG_MAPPABLE)) {
int prot = 0;
if (SPA_FLAG_IS_SET(d->flags, SPA_DATA_FLAG_READABLE))
prot |= PROT_READ;
if (SPA_FLAG_IS_SET(d->flags, SPA_DATA_FLAG_WRITABLE))
prot |= PROT_WRITE;
if ((res = map_data(impl, d, prot)) < 0)
return res;
SPA_FLAG_SET(b->flags, BUFFER_FLAG_MAPPED);

View file

@ -979,8 +979,7 @@ static int impl_port_use_buffers(void *object,
struct stream *impl = object;
struct pw_stream *stream = &impl->this;
uint32_t i, j, impl_flags = impl->flags;
int prot, res;
int size = 0;
int res, size = 0;
pw_log_debug("%p: port:%d.%d buffers:%u disconnecting:%d", impl,
direction, port_id, n_buffers, impl->disconnecting);
@ -988,8 +987,6 @@ static int impl_port_use_buffers(void *object,
if (impl->disconnecting && n_buffers > 0)
return -EIO;
prot = PROT_READ | (direction == SPA_DIRECTION_OUTPUT ? PROT_WRITE : 0);
clear_buffers(stream);
if (n_buffers > MAX_BUFFERS)
@ -1005,7 +1002,12 @@ static int impl_port_use_buffers(void *object,
if (SPA_FLAG_IS_SET(impl_flags, PW_STREAM_FLAG_MAP_BUFFERS)) {
for (j = 0; j < buffers[i]->n_datas; j++) {
struct spa_data *d = &buffers[i]->datas[j];
if (SPA_FLAG_IS_SET(d->flags, SPA_DATA_FLAG_MAPPABLE)) {
if (d->data == NULL && SPA_FLAG_IS_SET(d->flags, SPA_DATA_FLAG_MAPPABLE)) {
int prot = 0;
if (SPA_FLAG_IS_SET(d->flags, SPA_DATA_FLAG_READABLE))
prot |= PROT_READ;
if (SPA_FLAG_IS_SET(d->flags, SPA_DATA_FLAG_WRITABLE))
prot |= PROT_WRITE;
if ((res = map_data(impl, d, prot)) < 0)
return res;
SPA_FLAG_SET(b->flags, BUFFER_FLAG_MAPPED);