Memory Safety: Medium
spa_bt_midi_server_new() did not check the return value of strdup()
when duplicating the characteristic path. On allocation failure, a
NULL chr_path would be returned as part of the server object,
leading to a NULL pointer dereference when later used. Add a NULL
check that jumps to the existing fail cleanup path.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Memory Safety: Medium
Multiple allocation results in the HSP/HFP daemon backend were not
checked for NULL:
- transport_data->transport_path strdup in new_audio_connection()
- endpoint->remote_address and local_address strdup in property parsing
- t_path strdup before spa_bt_transport_create()
- endpoint calloc and endpoint->path strdup in interface enumeration
- backend->hsphfpd_service_id strdup after registration
Each could cause a NULL pointer dereference under memory pressure. Add
appropriate NULL checks with error returns matching the existing patterns
in each function (DBUS_HANDLER_RESULT_NEED_MEMORY or -ENOMEM).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Memory Safety: Medium
Four strdup() calls in the ModemManager Bluetooth integration had no
NULL checks, which could lead to NULL pointer dereferences under
memory pressure:
- mm_parse_call_properties(): call->number assignment
- mm_parse_interfaces(): this->modem.path assignment
- mm_filter_cb(): call_object->path assignment (also leaked calloc
on failure)
- mm_register(): this->allowed_modem_device assignment
Each site now checks for NULL and handles the failure appropriately
for its context (early return, goto cleanup, or return error).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Memory Safety: High
dbus_message_iter_get_fixed_array() returns the array length as a
signed int. A malformed DBus message could produce a negative length
value. In the Configuration property handler, the check 'if (!len)'
does not catch negative values, allowing negative lengths to be passed
to malloc() and memcpy() where sign extension to size_t creates
enormous values. The debug logging call spa_debug_log_mem() also
receives the negative length cast to size_t, causing an out-of-bounds
read.
In the Capabilities/Metadata handler, 'if (n)' is similarly true for
negative values, and the negative int assigned to the size_t *size
output parameter corrupts the stored length.
Fix by using 'len <= 0' and 'n > 0' checks respectively, and move
debug logging after validation. Explicitly zero the length on the
negative/zero path to prevent storing corrupted sizes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Memory Safety: Critical
When a Bluetooth BIS metadata entry has length=0 (e.g. when the JSON
config contains a "type" key but no "value" key, leaving the
calloc-initialized length at zero), the expression
'metadata_entry->length - 1' underflows to SIZE_MAX because the int
value is implicitly converted to size_t in the memcpy call. This causes
memcpy to read far past the metadata_entry->value buffer, leading to a
heap buffer overflow and likely crash.
Add a check that metadata_entry->length >= 1 before the subtraction,
rejecting entries with invalid length.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Memory Safety: Medium
The broadcast_code field is a 16-byte array that can be filled with
exactly 16 bytes of data via memcpy without null termination when the
input string length equals BROADCAST_CODE_LEN. The field is then
logged with %s format, which reads past the buffer boundary into
adjacent struct fields, potentially disclosing sensitive data.
Fix by changing the boundary check from > to >= to ensure room for
the null terminator, and copy the terminator along with the data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Memory Safety: High
Several Bluetooth audio codec implementations calculate codesize by
multiplying samples * channels * sizeof(sample_type) without overflow
checks. The parameters come from Bluetooth codec negotiation, which is
influenced by the remote peer. If the multiplication overflows, codesize
wraps to a small value, causing subsequent buffer size checks to pass
while the actual data processing operates on the full (larger) sample
count, leading to heap buffer overflows.
Affected codecs: LC3 (BAP), LC3plus (A2DP), Opus (A2DP), Opus-G (A2DP).
Add overflow checks before each codesize multiplication to ensure the
result fits in the target integer type, returning -EINVAL on overflow.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
MT7925 fails to setup a SCO connection that results to working LC3-24kHz
audio. Other controllers (Intel etc) appear to work OK.
Add quirk for disabling this codec, and disable it for this Mediatek
controller.
When there is a stream without tx_latency enabled, the fill_count ends
with MIN_FILL value. This causes one buffer of silence to be written to
every stream before the actual data in each iteration.
Consequently, more data is written than consumed in each iteration.
After several iterations, spa_bt_send fails, triggering a
group_latency_check failure in few next iterations and leading to
dropped data.
Skip streams without tx_latency enabled in fill level calculations
to prevent these audio glitches.
FDK-AAC encoder uses band pass filter, which is automatically
applied at all bitrates.
For CBR encoding mode, its values are as follows (for stereo):
* 0-12 kb/s: 5 kHz
* 12-20 kb/s: 6.4 kHz
* 20-28 kb/s: 9.6 kHz
* 40-56 kb/s: 13 kHz
* 56-72 kb/s: 16 kHz
* 72-576 kb/s: 17 kHz
VBR uses the following table (stereo):
* Mode 1: 13 kHz
* Mode 2: 13 kHz
* Mode 3: 15.7 kHz
* Mode 4: 16.5 kHz
* Mode 5: 19.3 kHz
17 kHz for CBR is a limiting value for high bitrate.
Assume >110 kbit/s as a "high bitrate" CBR and increase the
band pass cutout up to 19.3 kHz (as in mode 5 VBR).
Link: d8e6b1a3aa/libAACenc/src/bandwidth.cpp (L114-L160)
Add a control.ump port property. When true, the port wants UMP and the
mixer will convert to it. When false, the port supports both UMP and
Midi1 and no conversions will happen. When unset, the mixer will always
convert UMP to midi1.
Remove the CONTROL_types property from the filter. This causes problems
because this is the format negotiated with peers, which might not
support the types but can still be linked because the mixer will
convert.
The control.ump port property is supposed to be a temporary fix until we
can negotiate the mixer ports properly with the CONTROL_types.
Remove UMP handling from bluetooth midi, just use the raw Midi1 events
now that the mixer will give those and we are supposed to output our
unconverted format.
Fix midi events in-place in netjack because we can.
Update docs and pw-mididump to note that we are back to midi1 as the
default format.
With this, most of the midi<->UMP conversion should be gone again and we
should be able to avoid conversion problems in ALSA and PipeWire.
Fixes#5183
Since SBC is mandatory in all devices that support A2DP, we dont need to inclide
them in the priority tables.
This change also increases the priority of OPUS_G codec as it has better latency
and quality than SBC.
These 2 new profiles will select the highest quality and lowest latency A2DP
codecs respectively, making it easier for users to know which codec is the best
based on their needs.
The priority for these 2 new profiles is 0, so the default behavior should not
change.
HFP codecs don't have a direction dependent "target" profile, and this
function was returning false if A2DP is disabled.
Don't check target profile for HFP, leave checks to backend.
Fixes HFP-only configurations, which were missing profiles.
Non-spec compliant devices may set multiple bits in code config, which
we currently reject in validate_config().
enum_config() does work to deal with multiple bits set, but this is
never used, so write the code in a simpler way to return a single
configuration.
Non-spec compliant devices may set multiple bits in AAC AOT, which is
invalid.
In this case, we should normalize to MPEG-2 AAC LC which is the
mandatory value in spec, not to MPEG-4 AAC LC. In select_config() we
also prefer MPEG-2 over MPEG-4.
Some non-spec compliant devices (Sony XB100) set multiple bits
in all AAC field, including the frequency & channels.
Although they set multiple bits, these devices appear to intend that the
sender picks some specific format and uses it, and don't work correctly
with the others.
validate_config() already picks one configuration, so use the result in
enum_config(), instead of allowing also other settings.
Assume devices generally want preferably 44.1 kHz stereo.
Note we cannot reject the configuration, as BlueZ does not necessarily
retry, leaving the device connected but with no audio.
When there is no DBus session bus, creation of the telephony backend
fails, and we later crash on null ptr deref.
In this case, avoid crash trying to create telephony_ag or iterate its
call list.
Newer glibc versions have made certain `str*()` functions into macros
that ensure that the const-ness of the argument is propagated to the
return type.
With keepalive enabled, we need to emit state change event on acquire
similarly as we do if refcount was already positive.
Co-authored-by: Martin Geier <martin.geier@streamunlimited.com>
Depending on the codec kind, select appropriate settings to pass
to select_config().
This allows to pass the bluez5.bap.force-target-latency property,
and so to select the same configuration.
Some PTS tests (e.g. BAP/UCL/SCC/BV-046-C or BAP/UCL/SCC/BV-077-C)
requests to select QoS from low-latency or high-reliabilty.
The bluez5.bap.force-target-latency device property allows to force it.
For other values than low-latency or high-reliabilty the QoS selection
will use both tables to find the more appropriate configuration.
On some device combinations (MT7925 / Sony LinkBuds S) the low-latency
48 kHz QoS crackle.
It's probably better to default to high-reliability for those, until we
have proper quality vs. latency configuration in place.
sizeof(adapter) is larger than the big_entry->adapter and so the code
would copy too much. Instead only copy the strlen of the parsed
adapter, which we checked above to be smaller than the available size.
This doesn't copy the 0 byte because the memory is assumed to be 0
filled already by the calloc.
If the address is exactly the HCI_DEV_NAME_LEN, it will result in a non-0
terminated string, which may or may not be a problem...
By setting the hci handle (e.g. hci0) of the desired adapter, the BIG
config will only applied on that adapter. In case no "adapter" entry in
the config is given, it will be applied on all adapters.
Signed-off-by: Alexander Sarmanow <a.sarmanow@televic.com>
Commit 2942bae034 introduced parsing of
"SupportedFeatures" which uses a third DBusMessageIter pointer.
*** stack smashing detected ***: terminated
==389050==
==389050== Process terminating with default action of signal 6 (SIGABRT)
==389050== at 0x4F57B2C: __pthread_kill_implementation (pthread_kill.c:44)
==389050== by 0x4F57B2C: __pthread_kill_internal (pthread_kill.c:78)
==389050== by 0x4F57B2C: pthread_kill@@GLIBC_2.34 (pthread_kill.c:89)
==389050== by 0x4EFE27D: raise (raise.c:26)
==389050== by 0x4EE18FE: abort (abort.c:79)
==389050== by 0x4EE27B5: __libc_message_impl.cold (libc_fatal.c:134)
==389050== by 0x4FEFC48: __fortify_fail (fortify_fail.c:24)
==389050== by 0x4FF0ED3: __stack_chk_fail (stack_chk_fail.c:24)
==389050== by 0xBC1D1A1: remote_endpoint_update_props (bluez5-dbus.c:3137)
==389050== by 0xB53609F: ???
==389050== by 0x1DF: ???
==389050== by 0x61C17BF: ??? (in /usr/lib/x86_64-linux-gnu/libdbus-1.so.3.32.4)
==389050== by 0x1DF: ???
==389050== by 0xC5ED113: ???
Replace magic numbers (0x02, 0x05) with named constants BT_CODEC_CVSD
and BT_CODEC_MSBC for better code readability. Also remove redundant
zero initialization of num_caps field since the buffer is already
memset to zero.
The sco_offload_btcodec() function now returns void and only skips
offload setup when using the default datapath, simplifying the logic
and removing the need for explicit feature flag checks.
Add support for configuring the SCO hardware offload data path for
HFP/HSP profiles using the Bluetooth SIG-specified procedure. This
enables vendor-specific SCO offload integrations.
Changes:
- Add `bluez5.hw-offload-datapath` configuration property (default: 0)
- Implement `sco_offload_btcodec()` to set BT_CODEC socket option
- Add `SPA_BT_FEATURE_HW_OFFLOAD` quirk feature flag
- Apply offload configuration when creating SCO sockets if quirk enabled
- Document new property in pipewire-props.7.md
The datapath ID is configurable via device parameters and only applied
when the hardware offload feature flag is set in quirks, allowing
platform-specific SCO offload implementations.