Conversation
…nt debug messages; change how blocks of audio very far in the future are handled; add pw=true to the Bonjour information for classic AirPlay when built for AirPlay 2.
The two error branches in mqtt_publish() logged at debug(1), which is invisible at default syslog verbosity. A silently-dropped MQTT publish is the exact failure mode users report as 'MQTT just stopped working' with no errors anywhere in the logs. Raising these to inform() makes such drops legible at default verbosity and includes the target topic plus mosquitto_strerror() text in the non-NO_CONN branch so the diagnostic actually names the failing call site.
…h-errors MQTT: promote publish-error log paths to inform() for debuggability
…orm-publish-errors Revert "mqtt: promote publish-error log paths to inform() for debuggability" This needs to be done to the `development` branch.
Added caution regarding installing systemd-dev on backported systems.
Update settings document.
Update of configuration flag documentation.
Added a markdown test section to the Bug Report template.
Removed markdown test section from Bug Report template.
Summary of changes: * If the output rate is different to the input rate (e.g. 48,000 vs 44,100), look for the deepest output bit depth so that the transcoder has the maximum dynamic range available to minimise transcoding inaccuracies. * Fix a bug whereby the audio backend latency offset was mishandled in AirPlay 2 operation. * Fix an output format selection bug. * Update the README reference to the MPRIS specification to the latest version. * Remove the explicit `-` for `xxd` to read from `STDIN`. It's not necessary, and removing it makes it easier to package Shairport Sync on other build systems, such as OpenWrt.
Only do one job at a time...
Updated the README to clarify remote control support for AirPlay clients.
…HSA-jgrm-g4c3-wq2r) In handle_setup_2(), each element of the SETUP plist's timingPeerInfo.Addresses array is read with plist_get_string_val(). That function only writes *val when the node is a PLIST_STRING; for any other node type ip_address stays NULL and is then passed to strncat(), which calls strlen(NULL) -> NULL-pointer dereference. A SETUP whose timingPeerInfo.Addresses array contains a non-string element (e.g. an integer) therefore crashes the RTSP thread. As Shairport Sync installs no SIGSEGV handler and has no per-connection fault isolation, the crash terminates the whole daemon, ending audio for every connected client. Guard the append with a NULL check so a non-string element is skipped and the rest of the message is processed normally, rather than crashing. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…-6fg5-25pp) handle_setup_2() reads the "shk" session key from the SETUP plist with plist_get_data_val(), which returns the data's length in item_value, but that length is never checked. conn->session_key is later used directly as a fixed 32-byte ChaCha20-Poly1305-IETF key in rtp.c, where libsodium always reads crypto_aead_chacha20poly1305_ietf_KEYBYTES (32) bytes. A client that supplies an "shk" shorter than 32 bytes therefore causes an out-of-bounds heap read on every realtime-audio packet decrypt (crash, or decrypted output influenced by adjacent heap bytes). Reject a session key whose length is not 32 bytes: free it and leave conn->session_key NULL, matching the existing handling for a missing key (rtp.c already guards on session_key != NULL before decrypting). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…thods Backport of the fix merged to development in PR mikebrady#2263. The unrecognised-method hex-dump fills obf[4096] with two hex chars per input byte for an input clamped to 4096 bytes, writing up to 8193 bytes -- a pre-auth stack overflow reachable on AirPlay 2 (fresh connections default to ap_2, bypassing auth). Size the buffer to hold two hex chars per byte plus the terminating nul. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ge_process Backport of the fix merged to development in PR mikebrady#2264. message_process() reads error->value[0] after only checking that the TLVType_Error item is present; a zero-length Error TLV (07 00) parses to value == NULL, so this is a pre-auth NULL dereference. Guard with error->size > 0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…HSA-536j-295w-5jxr) In unencrypted_packet_decode(), the ast_uncompressed branch copies length/2 16-bit samples from the received packet into dest (abuf->data), which the caller allocates for exactly one packet: conn->frames_per_packet * conn->input_bytes_per_frame bytes. The copy is bounded only by the received packet length, which is attacker-controlled and never checked against the allocation, so an oversized uncompressed-PCM packet overflows the heap buffer. Clamp length to the destination size before copying. Note: this decode path is only reachable in a classic-AirPlay build using a built-in decoder (decoder_hammerton / decoder_apple_alac); FFmpeg builds (and therefore all AirPlay-2 builds) handle uncompressed audio via a different path and do not call this function. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…hang (GHSA-q4w3-3jf5-q43j) uncompress_nlabel() follows DNS name-compression pointers without any cycle or hop limit: the target of a pointer is never checked to be earlier in the packet, and visited offsets are not tracked. A crafted mDNS packet whose compression pointers form a cycle makes both traversal loops run forever, pinning the mDNS responder thread at 100% CPU -- a remote, unauthenticated denial of service from anyone on the local network segment (single UDP packet to 224.0.0.251:5353). Bound each traversal to pkt_len steps; no legitimate name can exceed the packet length, so this stops the loop on a malformed/cyclic name while leaving valid names unaffected. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…q4ff-xh78) rr->data.AAAA.addr is heap-allocated for every parsed or created AAAA record, but rr_entry_destroy() only frees RR_PTR/RR_TXT/RR_SRV data; RR_AAAA fell through to the no-op default, leaking the in6_addr allocation. A stream of mDNS packets containing AAAA records (no reply required) causes a slow memory- exhaustion denial of service, notable on memory-constrained devices. Add a RR_AAAA case that frees the address. (RR_A stores its address inline, so it does not need freeing.) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…e (GHSA-j3r8-57f9-jqf7) When recvfrom() returns -1, the mDNS server loop logged the error but continued on to call mdns_parse_pkt(pkt_buffer, recvsize). recvsize is an ssize_t of -1, which converts to SIZE_MAX as the size_t pkt_len parameter, so every bounds check in the parser (label_len(), uncompress_nlabel(), mdns_parse_rr()) is computed against a wildly out-of-range length -- an out-of-bounds heap read past the packet buffer, crashing the daemon. This is reachable when recvfrom() fails with a packet present (e.g. transient ENOBUFS under a UDP flood). Skip the datagram (continue) when recvfrom() returns a negative size. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…r-obf-pair-nullderef Backport pre-auth security fixes to master (obf overflow, pairing NULL deref).
Fix NULL deref on non-string timingPeerInfo address in SETUP (master)
Validate shk session key length in SETUP (master)
Bound uncompressed-PCM decode copy to destination size (master)
Bound mDNS compression-pointer following to stop parser hang (master)
Skip datagram on recvfrom() error to avoid SIZE_MAX parse (master)
Free AAAA record address in rr_entry_destroy (master)
….5 upwards across master (previously 5.2.3) an development (previously 5.4-dev) branches.
sink as the volume that shairport-sync controls.
in the pipewire { } block this parameter is allowed:
mixer_type = "sink"; // pipewire_mixer_type "stream" or "sink"
This parameter changes the SHairport-sync volume to a native pipewire
output either a stream or sink to control the actual output device
directly.
Owner
|
Thanks again for this. Would it be possible for it to target the |
Author
|
Oops, I thought that was the branch I targeted... Let me see if I can fix it. |
Author
|
I opened a new PR. Could not figure out how to revise this one. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Allows Shairport-sync tocontrol native pipewire volumes
.
in the pipewire { } block this parameter is allowed:
mixer_type = "sink"; // pipewire_mixer_type "stream" or "sink"
This parameter changes the Shairport-sync volume to a native PipeWire output either a stream or sink to control the actual output device directly.
Pull Requests
Thanks for helping to improve Shairport Sync. This template is an effort to make a Pull Request as trouble-free and useful as possible.
Please ensure your pull request targets the
developmentbranch, notmaster.Contributions should be submitted against the
developmentbranch for review and testing before they are merged into the main release branch.Description
Please provide a brief description of your changes:
This adds a pipewire/wireplumber mixer to shairport-sync to allow the shairport-sync volume control to directly control either the pipewire stream or sink.
The impetus for this was to allow our headless music appliance on an RPi to directly control the pipewire sink volume. This is similar to having shairport-sync control the alsa hardware mixer when it is configured to do so, but with the abstraction of pipewire.
the config needs to have the backend set to
"pipewire"and then this in the backend sectionType of Change
Please delete options that are not relevant:
Related Issue
If this PR addresses an existing issue, please link it here:
Fixes #(issue number)
Testing
Please describe the tests you ran to verify your changes:
Test Configuration:
on RPiOS
--prefix=/usr
--sysconfdir=/etc
--with-alsa
--with-stdout
--with-pipe
--with-pipewire
--with-avahi
--with-pkg-config
--with-configfiles
--with-mqtt-client
--with-ssl=openssl
--with-metadata
--with-convolution
--with-soxr
--with-systemd-startup
--with-dbus-interface
--with-airplay-2
--with-ffmpeg
On Arch:
--prefix=/usr
--sysconfdir=/etc
--with-alsa
--with-stdout
--with-pipe
--with-pipewire
--with-avahi
--with-dns_sd
--with-pkg-config
--with-configfiles
--with-mqtt-client
--with-ssl=openssl
--with-metadata
--with-soxr
--with-systemd-startup
--with-dbus-interface
--with-airplay-2
Checklist
developmentbranchAdditional Notes
Any additional information, context, or screenshots that would help reviewers understand your changes: