There is no limit on the number of inputs/outputs of a graph but the
filter-chain assumes it is at most 128 and also that there are at most
128 buffer datas.
Increase the limit (1024) and clamp and log an error when the
filter-graph has more channels. Also clamp the buffer datas so that we
don't overflow the stack allocated buffers.
module-access: add NULL check after pw_properties_new for
socket_access.
module-pulse-tunnel: add NULL check after 4MB calloc for ring
buffer.
module-rt: add NULL check after calloc in thread create.
module-rtp-session: add goto error after failed
pw_net_parse_address instead of falling through.
module-snapcast-discover: fix missing null-termination on
network-received data before logging it as a string.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Three modules had "impl->capture_info.rate = !impl->playback_info.rate"
which evaluates to 0 (logical NOT of a non-zero rate) instead of
copying the playback rate. This is a copy-paste typo from the line
above which correctly uses "= impl->capture_info.rate".
Affects module-filter-chain, module-loopback, module-example-filter.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
module-filter-chain: fix NULL pointer dereference when
pw_stream_dequeue_buffer returns NULL and out->requested is
accessed outside the NULL check.
module-zeroconf-discover: add NULL checks for name, type,
host_name, address, and port from mDNS lookups that could be
missing in malformed announcements.
module-raop-sink: cap net.mtu to 9000 to prevent stack overflow
via VLA uint32_t out[8 + mtu].
module-rtp-sap: fix buffer over-read in SDP "i=" line parsing
that read past a self-inserted null terminator. Also fix fd leak
when fd is 0 (fd > 0 should be fd >= 0).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The aec_method parameter is interpolated into a SPA library path
as "aec/libspa-aec-%s". A client could use "../" sequences to
load arbitrary SPA plugins. Reject values containing ".." or "/".
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
A PulseAudio client can load this module with an arbitrarily complex
blocklist regex, causing catastrophic backtracking in regexec on
every new device. Cap the regex string at 1024 characters.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
A negative max-clients value in the config is parsed as int then
assigned to uint32_t, wrapping to UINT32_MAX and effectively
disabling the client limit.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
When sink_name/source_name is not provided, pw_properties_get for
PW_KEY_NODE_NAME returns NULL, which is then passed to
pw_properties_setf as a %s argument.
Add NULL check before calling pw_properties_setf.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
A client-supplied device name ending in ".monitor" was stack-allocated
via strndupa without any size limit. Since protocol messages can be up
to 16MB, a malicious client could send a very long device name and
overflow the stack, crashing the daemon.
Cap the strndupa length at MAX_NAME (1024) in both find_device and
do_set_default.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- volume.c: add spa_pod_is_object check before casting param to
spa_pod_object, preventing out-of-bounds reads on malformed pods
- manager.c: add NULL check for p->param in has_param before
dereferencing via SPA_POD_SIZE
- snap-policy.c: check strings1[1] and strings2[1] for NULL before
passing to g_str_equal, fixing wrong operand order
- format.c: use map->channels consistently in format_build_param
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- module-zeroconf-publish: guard spa_hook_remove of impl_listener with
a flag to prevent operating on uninitialized hook when unload is called
after a partial load failure; bail out of create_service when
pw_properties_new fails to prevent NULL dereference in publish_service
- module-device-restore: add missing NULL check after message_alloc in
emit_event; make manager_events static const
- module-jackdbus-detect: fix memory leak on error paths in prepare by
using goto out instead of early return; free props/sink_props/source_props
in unload
- module-roc-sink-input: add missing valid_args whitelist
- module-rtp-recv: add missing valid_args whitelist
- module-rtp-send: add missing valid_args whitelist
- module-gsettings: add missing NULL check after strdup in load_group
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
For playback and capture streams we allocate MAXLENGTH (4M) buffers but
for upload streams we must allow space for the total upload stream, which
can be up to the max allowed sample size (16M).
Keep the allocated size for the stream around in a variable so that we
can use it when writing/reading to/from the ringbuffer.
This could later also be extended to use the attr.maxlength variable to
size the buffer (but it's usually 4M anyway). This is more complicated
because we need to grow the buffer size when new attributes are set,
which is probably more complicated than useful.
Use the JSON builder to prepare arguments for modules and metadata
instead of custom memopen and fprintf. This makes it easier to ensure
the strings are all properly escaped.
This removes the use of spa_json_encode_string(), which could return a
truncated, non-zero terminated result, which we needed to check
everywhere.
spa_json_encode_string was called with sizeof(name)-1, which would
not write a null terminator on truncation. Use sizeof(name) and skip
sink names that don't fit in the buffer.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
pw_properties_new can return NULL under OOM. The result was used
directly without a check, leading to a NULL pointer dereference.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
In the SPA_CHOICE_Enum case, values[index+1] was used to skip the
default value at index 0, but the bounds check only validated index,
not index+1. Move bounds checks into each case with the correct limit.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The listen address was inserted into a JSON array without escaping.
Build the address string first, then encode it with
spa_json_encode_string.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The switch in message_get had no default case. An unrecognized tag byte
from a malicious client would skip the switch body without consuming
the va_arg parameter, desynchronizing all subsequent argument reads
and causing undefined behavior.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
do_cork_stream, do_flush_trigger_prebuf_stream, and do_set_stream_name
did not check whether the stream had completed format negotiation.
Add create_tag guards matching the pattern in do_set_stream_buffer_attr.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
A trailing backslash in a module argument string would cause the
escape handling to advance past the null terminator, reading one
byte out of bounds on the next loop iteration.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
strndup can return NULL under OOM. The result was passed directly to
spa_json_begin_array which would dereference the NULL pointer.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
If a client sends UPDATE_PLAYBACK_STREAM_SAMPLE_RATE before format
negotiation completes, stream->ss.rate could be 0, causing a
floating-point division by zero. Add the same create_tag guard used
in do_set_stream_buffer_attr.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Client-supplied int64_t offset was multiplied by 1000 without overflow
check. Use spa_overflow_mul to detect and reject values that would
overflow.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The create_tag guard added in a2de6c886 also rejected memblocks for
upload streams, which never clear create_tag. Upload streams allocate
their buffer immediately, so the NULL deref risk does not apply to
them. Exempt STREAM_TYPE_UPLOAD from the check.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
operation_complete removed the operation from the list and freed it
but never decremented client->n_operations. After 64 completed
operations the client would be permanently locked out.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Use spa_json_encode_string to escape user-supplied strings before
inserting them into JSON configs in module-always-sink,
module-x11-bell, and module-switch-on-connect.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Both reply_new and reply_error passed the message_alloc result directly
to message_put without checking for NULL, which would cause a NULL
pointer dereference on allocation failure.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The listen address was inserted into JSON without escaping. Build the
address string first, then encode it with spa_json_encode_string to
prevent injection of arbitrary JSON keys.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The plugin and label parameters in module-ladspa-sink and
module-ladspa-source were inserted into the filter-chain JSON config
without escaping. Use spa_json_encode_string to prevent injection.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
read_cvolume accepted channels=0, creating a degenerate zero-length
volume array that is passed to pw_stream_set_control and SPA pod
building. Reject zero channels alongside the existing CHANNELS_MAX
upper bound check.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was no limit on concurrent PLAY_SAMPLE operations per client.
Each creates a PipeWire stream, allowing a client to exhaust server
resources. Add a MAX_PENDING_SAMPLES (64) limit per client.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was no limit on pending operations per client. Commands like
SET_SINK_VOLUME each allocate an operation that persists until a
manager sync completes. A client flooding these commands can exhaust
server memory. Add a MAX_OPERATIONS (64) limit per client.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
If module_create succeeded but the subsequent calloc for
pending_module failed, the module was leaked in the modules map.
Move the calloc before module_create so failure cleanup is trivial.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The device name was interpolated into a JSON metadata string without
escaping. A node with crafted name containing quote characters could
inject arbitrary JSON keys into the default sink/source metadata.
Use spa_json_encode_string to properly escape the value.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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>
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>
pw_properties_new can return NULL on OOM. Passing NULL to read_props
causes a NULL pointer dereference through pw_properties_set. Only
reachable when debug logging is enabled.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
message_alloc can return NULL on allocation failure but the result
was not checked, causing the next do_read call to misinterpret
the NULL as a protocol error instead of an OOM condition.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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>
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>
The device_name from a client message was interpolated directly into
a JSON string without escaping. A malicious client could inject
arbitrary JSON keys by including quote characters in the device name.
Use spa_json_encode_string to properly escape the value.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
A client can send memblock data to a playback stream channel before
format negotiation completes and the stream buffer is allocated,
causing a NULL pointer dereference crash. Reject memblock data for
streams that are still being created (create_tag != SPA_ID_INVALID).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>