Memory Safety: High
In ensure_size(), the check `m->length + size <= m->allocated` could
overflow when both m->length and size are large uint32_t values,
wrapping around to a small number and incorrectly passing the bounds
check. This could allow writing past the end of the allocated buffer.
Rewrite the check as `size <= m->allocated - m->length` which cannot
overflow since we already verified m->length <= m->allocated. Also add
an explicit overflow check for the new allocation size calculation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Memory Safety: Medium
sprintf was used to format a /proc path without bounds checking.
While pid_t values are practically bounded, using snprintf with
sizeof(root_path) ensures the buffer cannot overflow regardless
of the input value, following defense-in-depth principles.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When a node is inactive but linked to a driver, the only reason it is
not being scheduled is because it is inactive.
We already set up the links and negotiate the format and buffers to
prepare going to RUNNING. This patch now also make the node go to IDLE,
which makes the adapter negotiate a forma and buffers with the internal
node.
This makes things more symetrical, when linking a node, it becomes IDLE,
when activating it becomes RUNNABLE, when inactive it goes back to IDLE.
The switch to RUNNING will also be faster when things are already set up
in the IDLE state.
The main advantage is that it allows us to implement the startup of
corked streams in pulseaudio better. Before this patch we had to set the
stream to active to make it go through the Format and buffer negotiation
and then quickly set it back to inactive, hopefully without skipping a
cycle. After this patch, the corked stream goes all the way to IDLE,
where it then waits to become active.
See #4991
Fix path comparison in is_socket_unix() and don't unset LISTEN_FDS since
the function that uses it is called more than once and it was not unset
when sd_listen_fds() was used.
Fixes#5140
We can just concatenate the stream and client dict on the stack, reusing
all the strings without having to do allocations or copies.
Also filter out the object.id and object.serial from the client, we want
to keep the ones from the streams.
Instead of adding the client props to the stream props when we create
it, add them when we enumerate the streams.
This makes it possible to also have the client props in the stream props
for streams that are not created with the pulse API.
Fixes#5090
Socket activation uses sd_listen_fds from libsystemd, and can only be
compiled on systems with systemd.
This is an issue for Alpine / postmarketOS, where upstream has no
systemd package, but downstream depends on upstream's pipewire package
and wants to rely on socket activation. This also prevents using
socket-activation on other non-systemd distributions, including
non-Linux.
Implement equivalent functionality without a dependency on libsystemd.
Add 35 sec timeout for PLAY_SAMPLE streams to start streaming, similar
to what we do with normal streams, and fail playback if they don't
start.
This avoids pending sample playback using up resources indefinitely if
streams fail to start for some reason, e.g. session manager is not
linking them.
If we get EPROTO, we likely have missed on some messages from the
server, and our state is now out of sync.
It's likely we can't recover (e.g. if error is due to fd limit hit), so
just drop the server connection in this case, similarly as if we got
EPIPE.
WirePlumber recently added a mechanism to force mono mixdown on audio
outputs, which is a useful feature for accessibility. Let's also expose
that setting via libpulse for existing audio settings UIs to be able to
use.
The dont-inhibit-auto-suspend flag does not do anything when using
direct-on-input-idx (capturing from a stream) in pulseaudio, so also
make it do nothing on pulse-server.
See #4991
When a device profile changes (e.g., Bluetooth headset switching from
a2dp-sink to headset-head-unit), the active port information changes
but PulseAudio compatibility layer clients don't receive the expected
PA_SUBSCRIPTION_EVENT_SOURCE or PA_SUBSCRIPTION_EVENT_SINK change events.
Root cause:
The collect_device_info() function updates the active_port index from
SPA_PARAM_Route parameters, but doesn't update the corresponding
active_port_name field. When update_device_info() uses memcmp() to
detect changes in the device_info structure, it compares the entire
structure including active_port_name. If the pointer value doesn't
change (even though the actual port changed), no change is detected,
and the change_mask flag (PW_MANAGER_OBJECT_FLAG_SOURCE/SINK) is not
set, preventing subscription events from being sent.
Solution:
After setting active_port in collect_device_info(), look up the
corresponding port name from SPA_PARAM_EnumRoute parameters by
matching both the port index and direction. Initialize active_port_name
to NULL at the start to ensure it's always recalculated.
This fix applies to all device types (Bluetooth, USB, PCI sound cards)
and all profile switching scenarios, ensuring applications using the
PulseAudio compatibility layer receive proper device change notifications.
Tested with:
- Bluetooth headset profile switching (a2dp-sink ↔ headset-head-unit)
- Applications subscribing to PA_SUBSCRIPTION_MASK_SOURCE/SINK events
- Verified no regression in audio initialization
Add a function that accepts the size of the position array when reading
the audio positions. This makes it possible to decouple the position
array size from SPA_AUDIO_MAX_CHANNELS.
Also use SPA_N_ELEMENTS to pass the number of array elements to
functions instead of a fixed constant. This makes it easier to change
the array size later to a different constant without having to patch up
all the places where the size is used.
Instead of using timerfd, use the context timer-queue to schedule
timeouts. This saves fds and removes some redundant code.
Make the rtp-source timeout and standby code a bit better by using
atomic operations.
When clients connect with IP, add the peer IP address to properties. We
might use this later to make a better stream node.name than a copy of the
client application name.
Use the timer queue for scheduling stream and object data timeouts.
This avoids allocating timerfds for these timeouts and the timer queue
can handle many timeouts more efficiently.
If we don't get a link on a stream, we might never send a create stream
reply. The client handles this fine by timing out after 30s and dropping
the stream, but the server holds on to the pw_stream forever (or until
the client quits).
Let's add a timer to clean up such streams on the server.
Fixes: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/4901
Only send out SUSPENDED event when there is a change in the suspended
state. This avoids sending out unsuspend events when we simply uncork.
Implement the fail_on_suspend flag for capture and playback streams.
Instead of suspending those streams, we need to kill them.
The parser does not check that POD arrays have the correct size for
their type, so the calling code must do that.
This also enumerates some of the code that cannot handle the size of the
values of an array not being the exact expected size for its type.
There is a lot of it.