Commit graph

582 commits

Author SHA1 Message Date
Wim Taymans
d3e1be8b6e security: fix division by zero in PulseAudio set_stream_buffer_attr
A client can create a stream with invalid sample_spec (rate=0) via
format_info negotiation, then send SET_STREAM_BUFFER_ATTR before
negotiation completes. fix_playback_buffer_attr divides by ss.rate,
crashing the daemon. Reject buffer attr changes on streams that
have not completed format negotiation.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-29 17:08:17 +02:00
Wim Taymans
cd7bb1e37d security: validate sample rate in PulseAudio update_stream_sample_rate
The client-provided rate was used without validation. A zero or
excessively large rate produces extreme correction values passed
to pw_stream_set_control. Reject rates that are zero or exceed
RATE_MAX.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-29 16:51:46 +02:00
Wim Taymans
52afec565b security: add total sample cache size limit in PulseAudio protocol
There was no limit on the total size of the sample cache. A client
could upload many samples to exhaust server memory. Add a configurable
pulse.max-sample-cache property (default 64MB) to cap the total size
of all cached samples.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-29 16:39:57 +02:00
Wim Taymans
37990b5e90 security: add per-client stream limit in PulseAudio protocol
There was no limit on the number of streams a single client could
create. Each stream allocates a 4MB ring buffer, allowing a malicious
client to exhaust server memory. Add a configurable pulse.max-streams
property (default 64) to limit streams per client.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-29 16:28:05 +02:00
Wim Taymans
6efaf12d00 security: clamp channel count in PulseAudio volume control handler
Memory Safety: High

The stream_control_info() callback copied control->n_values floats
into stream->volume.values without checking bounds. The source allows
up to MAX_VALUES (256) entries but the destination volume array is
only CHANNELS_MAX (64) entries, so a stream with more than 64 channel
volumes would overflow the buffer. Clamp n_values to CHANNELS_MAX
before the copy.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-27 11:24:30 +02:00
Wim Taymans
ed2c0ad4ee spa: add spa_alloca that does overflow and limit checks
Make a function like alloca but with overflow checks and a max
allocation size.

Use this function where we can and also make sure that all alloca calls
are in some way limited.
2026-04-27 10:53:44 +02:00
Wim Taymans
a9f1ad414e security: fix integer truncation in peer_name alloca size
Memory Safety: Medium

The strlen() return value (size_t) is stored in an int before being
passed to alloca(). If a malicious client sets an extremely long
PW_KEY_NODE_NAME property, the addition could overflow the int,
resulting in a small or negative alloca size and a subsequent buffer
overflow in snprintf().

Change the type to size_t and add a bounds check to prevent
excessively large stack allocations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-24 16:09:08 +02:00
Wim Taymans
a6155387da security: fix unchecked alloca in pulse-server property list handling
Memory Safety: Medium

Two alloca() calls in the PulseAudio protocol server were missed by the
previous alloca bounds-checking fix (commit 0d2877c0d):

1. fill_node_info_proplist() adds n_items counts from node properties
   and client properties without checking the total before alloca().
   A client with a very large number of properties can exhaust the stack.

2. fill_card_info() uses pi->n_props from port info for an alloca()
   without bounds checking. A card object with many port properties can
   similarly exhaust the stack.

Add MAX_ALLOCA_SIZE checks consistent with the existing pattern to
prevent stack overflow from large property counts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-24 15:55:35 +02:00
Wim Taymans
00413a3263 security: fix stack exhaustion via unbounded alloca in pulse-server
Memory Safety: Medium

Several functions in the PulseAudio protocol implementation use alloca()
to allocate arrays of port_info, profile_info, or dict_item structs
based on counts derived from card parameters or client property lists.
These counts have no upper bounds, so a card object with a very large
number of parameters or a client sending many properties can cause
alloca() to exhaust the stack, resulting in a stack overflow crash.

Add a MAX_ALLOCA_SIZE (64KB) limit and check element counts before each
alloca() call. If the requested allocation exceeds the limit, the
function returns -ENOMEM instead of crashing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-24 15:55:35 +02:00
Wim Taymans
e490c503fd pulse-server: update initial stream is_paused state
When the stream starts corked, we set the INACTIVE flag and we also need
to set the stream state as PAUSED or else uncork will not unpause
anything.
2026-04-15 18:25:28 +02:00
Wim Taymans
823dcd8843 scheduler: make nodes move to IDLE when inactive
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
2026-04-14 14:28:29 +02:00
Wim Taymans
0e0c325194 fix some uninitialized variables warnings 2026-04-08 11:29:36 +02:00
Wim Taymans
be0e037809 pulse-server: avoid doing allocations and string copies
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.
2026-02-19 13:03:50 +01:00
Wim Taymans
6eb4483069 pulse-server: add client props to sink_input/source_output
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
2026-02-19 12:08:23 +01:00
Arun Raghavan
ed59342d28 pipewire-pulse: Expose bluetooth headset autoswitch config as a message
Makes it easier for libpulse-based clients to modify this setting if
they want.
2026-01-26 14:44:30 -08:00
Arun Raghavan
703380d62d pulse-server: Fix querying after setting of mono mixdown 2026-01-26 14:37:08 -08:00
Arun Raghavan
385161b12a pulse-server: Add a message to enable/disable mono mixdown
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.
2025-12-18 16:35:35 -08:00
Wim Taymans
2c6aa8e0d0 pulse-server: only use passive for devices
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
2025-11-25 10:17:14 +01:00
Arun Raghavan
3337af64ca pulse-server: Support clearing default sink/source
The PulseAudio way of doing this is to accept @NONE@ to clear the
default setting, so let's accept that.
2025-11-06 17:23:16 -08:00
Wim Taymans
7bd65cfe93 pulse-server: increase min quantum values
The default values of 128/48000 seem to be too low as a good default.
Bump them to 256/48000.

Fixes #4875
2025-11-06 12:52:48 +01:00
Wim Taymans
06efc8ffb6 pulse-server: clear timer when stream is created
Make a function when the stream is created so that we can clear the
create_tag and the timer.
2025-09-18 14:22:00 +02:00
Wim Taymans
ca713c08ee pulse-server: use the new timer-queue for timeouts
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.
2025-09-18 13:55:43 +02:00
Wim Taymans
370d190572 pulse: improve stream suspended state handling
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.
2025-09-01 12:55:51 +02:00
Wim Taymans
bd7ce5c7fa pulse-server: only react to state changes when not corked
When we are starting or corked we don't emit suspend/resume caused
by state changes.
2025-06-25 10:31:32 +02:00
Arun Raghavan
220b037683 pulse-server: Implement stream suspended callback 2025-06-23 09:19:10 +00:00
Wim Taymans
83c644fe09 pulse-server: mark empty buffers
This makes it use some more optimal paths in the mixer.
2025-06-13 18:07:55 +02:00
Wim Taymans
13105a8e64 pulse-server: Implement record PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND
Also implement the flag for record streams, where it is more usually
used, like in pavucontrol to disable starting a network source.
2025-06-02 11:48:01 +02:00
Arun Raghavan
60669920f0 pulse-server: Implement PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND
We do this by setting the node as passive.

Fixes: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/4255
Fixes: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/4726
2025-06-02 14:38:22 +05:30
Wim Taymans
c45d667934 loop: spa_loop_invoke -> spa_loop_locked where possible
When we simply need to change some state for the code executed in the
loop, we can use locked() instead of invoke(). This is more efficient
and avoids some context switches in the normal case.
2025-05-30 11:59:35 +02:00
Wim Taymans
3905e3b3d3 stream: set errno to the current error
Make the state_changed event and _get_state() function set errno with
the current error value if the state is in error, so that application
can use this to give more detailed error reporting.

Use this in alsa, v4l2 and pulse to give some other error codes than
EIO.

Fixes #4574
2025-03-04 13:22:51 +01:00
Wim Taymans
cf7e917024 pulse-server: make a function to silence a buffer 2025-01-16 16:16:39 +01:00
Pauli Virtanen
e393e57a26 pulse-server: ensure positive stream delay in GET_PLAYBACK/RECORD_LATENCY
Pulseaudio protocol requires stream latency is uint64. Clamp the
Pipewire signed latency to the range, better than wrapping around.
2024-11-19 22:07:09 +02:00
Wim Taymans
0dfd6d997f protocol-pulse: implement readiness notification
Write a newline to the fd in the PIPEWIRE_PULSE_NOTIFICATION_FD env
variable when set.

This is to implement readiness notification as suggested in
https://skarnet.org/software/s6/notifywhenup.html

Fixes #4347
2024-10-22 09:50:27 +02:00
Wim Taymans
9e932ec671 pulse-server: set pulse.corked on streams
Set the corked state on streams so that we can use this in sink-input
and source-output info without guessing.

The problem is that when a stream starts un-corked, the state is less
than RUNNING and so before this patch, pulse-server reports a corked
stream, which is not what pulseaudio reports.
2024-09-30 15:02:08 +02:00
Wim Taymans
ca488a5dcc pulse-server: add quirk to block record and playback streams
Add aquirk to block any record or playback stream.
2024-09-23 10:56:40 +02:00
Barnabás Pőcze
27b76ae686 pulse-server: calculate event mask from facility and type
Make `client_queue_subscribe_event()` take the facility and type
separately, and calculate the mask itself, so that the caller
does not need to be concerned with that.
2024-09-18 19:35:08 +02:00
Wim Taymans
b5cccdb382 json: add and use spa_json_str_object_find()
Parse a string as a json object and copy the value with key as a string.
2024-09-16 13:12:05 +02:00
Wim Taymans
ce390d5b22 spa: add spa_json_object_next
This gets the next key and value from an object. This function is better
because it will skip key/value pairs that don't fit in the array to hold
the key.

The previous code patter would stop parsing the object as soon as a key
larger than the available space was found.
2024-09-16 09:50:36 +02:00
Wim Taymans
cd81b5f39a spa: add spa_json_begin_array/object and relaxed versions
Add spa_json_begin_array/object to replace
spa_json_init+spa_json_begin_array/object

This function is better because it does not waste a useless spa_json
structure as an iterator. The relaxed versions also error out when the
container is mismatched because parsing a mismatched container is not
going to give any results anyway.
2024-09-16 09:50:33 +02:00
Wim Taymans
1ae4374ccf Fix compilation with -Werror=float-conversion
Better make the conversions explicit so that we don't get any surprises.

Fixes #4065
2024-06-18 12:17:56 +02:00
Barnabás Pőcze
b3bd026699 pipewire: remove cleanup.h
Since `spa/utils/cleanup.h` is not a private header anymore, there is
no need for a separate `pipewire/cleanup.h` since the definitions of
the cleanup routines can now be moved into the respective headers.
2024-05-16 17:35:58 +02:00
Wim Taymans
a30c27dce0 pulse-server: add pulse.allow-module-loading option
Add an option to disable loading and unloading of modules with the
native protocol.

Document some more options.
2024-05-06 15:28:43 +02:00
Barnabás Pőcze
6a26e6dd3f treewide: fix some format string issues
Use the proper specifier, and cast to a known type where the type
is not guaranteed by any standard.

See #3975
2024-04-25 07:24:10 +00:00
Wim Taymans
7e9e261fa6 conf: support property rules
Add pw_conf_section_update_props_rules() that will not only update the
properties of a section but wil also apply rules in section.rules and
match against the context properties.

Use this by default when using pw_context_conf_update_props().

Add a new method to get a string name of the VM type. Place the
cpu.vm.name in the context properties.

This makes it possible to deprecate the vm.overrides with something more
flexible based on rules. Update the conf files and docs to refect this.
2024-03-15 12:10:41 +01:00
Wim Taymans
3c27dcd868 pulse-server: Make sure peer_sink name is filled
Use 'unknown' when we can't find the peer_name. Otherwise we will just
get a protocol error when the node.name is missing.
2024-02-19 17:39:39 +01:00
Wim Taymans
ac91c0dc1c pulse-server: implement stream-restore EVENT
Add method to update the client routes. Add an event when the client
routes changed.

Listen for route_changed events on clients that do a subscribe on the
stream-restore extension. Emit an EVENT when the routes change.

This keeps the system notifications volumes in sync between
gnome-control center and pavucontrol and probably in other tools
as well.

Fixes #3805
2024-01-23 13:31:05 +01:00
Wim Taymans
d71fb40989 pulse-server: move extension to modules
Add extension support to modules. This is a list of extension commands
that can be performed on the module.

Remove the custom registry of extensions and make proper modules that
implement the extensions.

This is more in line with what pulseaudio does. The advantage is that the
modules actually show up in the module list and that we can use the
module user_data to implement the extension later.
2024-01-23 13:31:05 +01:00
Wim Taymans
a3c6b3acae log: add pw_log_topic_custom_enabled()
Add a function to check if a specfic custom log level has been defined
for a topic.

We can use this to dynamically check if we need to do the connection debug
messages.

We can also get rid of the conn.* pattern hack to disable connection
messages by default.
2024-01-04 17:40:57 +01:00
Wim Taymans
0c857f5455 pulse-server: add stream/device state in dev_info
Also include and update the state of the device/stream in
collect_device_info so that we can compare it against the previous value
and emit a change event.

Fixes #3660
2023-11-20 11:39:31 +01:00
Wim Taymans
11320cf203 tweak number of buffers
In most cases we can use just 1 buffer.

The alsa-pcm-source needs at least 2 buffers so increment the min
limit.
2023-10-13 14:00:29 +02:00