Skip to content

wireplumber: add SELinux policy module#1138

Open
tkanfade wants to merge 1 commit into
SELinuxProject:mainfrom
tkanfade:wireplumber_module
Open

wireplumber: add SELinux policy module#1138
tkanfade wants to merge 1 commit into
SELinuxProject:mainfrom
tkanfade:wireplumber_module

Conversation

@tkanfade

Copy link
Copy Markdown

WirePlumber is the session manager for the PipeWire multimedia framework. On standard Linux desktops it runs as a user service (systemd --user). On embedded/headless platforms such as Qualcomm QLI 2.0 it runs as a system-wide service (User=pipewire under system systemd).

Without a dedicated policy WirePlumber falls back to the generic initrc_t domain. In initrc_t, SELinux blocks D-Bus method replies from modemmanager_t and bluetooth_t which are required for telephony and Bluetooth audio routing. The blocked replies cause WirePlumber to crash with SIGSEGV every ~25 seconds resulting in wpctl set-default and pw-play --target failures.

The policy uses a compile-time ifdef(`wireplumber_system_service') switch following the same pattern as pipewire.te to select between system-service and user-service mode at m4 build time.

The policy module is placed in apps/ consistent with pipewire.

The policy confines the wireplumber_t domain with:

  • Domain transition via wireplumber_exec_t
  • PipeWire socket communication via pipewire_stream_connect() (depends on pipewire policy PR pipewire: add policy for PipeWire multimedia daemon #1109)
  • Runtime directory management (system: /run/wireplumber, user: XDG_RUNTIME_DIR/wireplumber)
  • tmpfs/memfd shared memory for zero-copy audio buffers
  • Config file mmap via files_map_usr_files()
  • D-Bus system bus; dbus_system_domain when system service
  • D-Bus communication with ModemManager, BlueZ and oFono
  • udev runtime access for device monitoring
  • systemd sessions, /etc/machine-id, procfs, sysfs
  • /dev/snd inotify watch for device monitoring
  • RTKit realtime scheduling support
  • systemd journal logging

Also adds ofono_dbus_chat() interface to ofono.if to allow bidirectional D-Bus communication between a domain and oFono.

Note: This patch depends on the pipewire policy (PR #1109). Please merge PR #1109 before this patch, as wireplumber.te uses
pipewire_stream_connect() defined in pipewire.if.

@tkanfade tkanfade force-pushed the wireplumber_module branch 4 times, most recently from 0ebc4bc to e2590da Compare May 27, 2026 13:11

@WavyEbuilder WavyEbuilder left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should also probably be $1_wireplumber_t for the user instances. We also seem to be missing domain transitions and rbac allows for the user, staff, and sysadm roles. How was this patch tested? I'm also a bit concerned that this won't work as expected, especially given that a huge amount of domain transitions seem to be missing.

@pebenito

pebenito commented Jun 2, 2026

Copy link
Copy Markdown
Member

This should also probably be $1_wireplumber_t for the user instances. We also seem to be missing domain transitions and rbac allows for the user, staff, and sysadm roles. How was this patch tested? I'm also a bit concerned that this won't work as expected, especially given that a huge amount of domain transitions seem to be missing.

Having a derived domain typically depends on some specific need we can't specify otherwise, most commonly transitions out of the derived domain to another derived domain or back to the user domain. For example:

user_t -> user_foo_t -> user_t

user_t -> user_foo_t -> user_bar_t

Absent these types of issues, UBAC separations are typically sufficient.

@pebenito

pebenito commented Jun 9, 2026

Copy link
Copy Markdown
Member

Since you have pipewire commits in this PR, it will have to wait on #1109 to complete.

@tkanfade tkanfade marked this pull request as draft June 11, 2026 12:48
@aerusso

aerusso commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

I previously just marked pipewire and wireplumber as pulseaudio_t, but this added granularity is probably better. I have some comments about the new pipewire_t domain, but I can't test anything until I also get wireplumber working (since that's apparently a very important part of the pipewire ecosystem).

I'm going to pull the version of the new wireplumber module here and use it as a starting point. @tkanfade if you have another updated version of this that you'd rather me base off, let me know. I don't want my (already outrageously large) patchset to diverge any further from mainline refpolicy!

@aerusso

aerusso commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

@tkanfade I've got a (messy) revision of this that gets audio and screen sharing working for me. I'd like to share it---how would be best to get it out? I could open another MR. I had to make fixes in both the pipewire and pulseaudio modules as well. Once we're all happy with the rough ideas, I can clean it up.

@tkanfade

tkanfade commented Jun 29, 2026

Copy link
Copy Markdown
Author

@tkanfade I've got a (messy) revision of this that gets audio and screen sharing working for me. I'd like to share it---how would be best to get it out? I could open another MR. I had to make fixes in both the pipewire and pulseaudio modules as well. Once we're all happy with the rough ideas, I can clean it up.

@aerusso I am updating my wireplumber files, I was waiting for pipewire PR:
#1109 to get merged. I will update this PR shortly.

@tkanfade tkanfade force-pushed the wireplumber_module branch from 569ab34 to b0f80a5 Compare June 30, 2026 11:28
@tkanfade

Copy link
Copy Markdown
Author

Updated the PR, wireplumber_role is now a 4-param template in .if (matching pipewire_role), wired into unprivuser.te and staff.te. Also Validated User-service mode on Fedora VM (aarch64 kernel) and system-service on qualcomm targets respectively.

@tkanfade tkanfade marked this pull request as ready for review June 30, 2026 12:07
@tkanfade tkanfade requested a review from WavyEbuilder June 30, 2026 12:14

@pebenito pebenito left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please review the StyleGuide as several lines across the files are out of order.

Comment thread policy/modules/apps/wireplumber.te Outdated
allow wireplumber_t self:unix_dgram_socket create_socket_perms;

# Bluetooth socket for BlueZ audio routing (A2DP/HFP profile management).
allow wireplumber_t self:bluetooth_socket { create bind setopt listen };

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please upgrade permissions to create_socket_perms.

Comment thread policy/modules/apps/wireplumber.te Outdated
allow wireplumber_t self:bluetooth_socket { create bind setopt listen };

# netlink kobject uevent socket for udev device monitoring.
allow wireplumber_t self:netlink_kobject_uevent_socket { create bind setopt getattr getopt };

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also create_socket_perms.

Comment thread policy/modules/apps/wireplumber.te Outdated
Comment on lines +102 to +103
systemd_read_logind_sessions_files(wireplumber_t)
systemd_watch_logind_sessions_dirs(wireplumber_t)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should go down with the other rule in the systemd optional_policy.

Comment thread policy/modules/apps/wireplumber.te Outdated
Comment on lines +110 to +118
# Use file descriptors passed from PipeWire (e.g. memfd for zero-copy buffers).
optional_policy(`
pipewire_use_fds(wireplumber_t)
')

# Map PipeWire shared memory (memfd) files for zero-copy audio buffer access.
optional_policy(`
pipewire_mmap_rw_tmpfs_files(wireplumber_t)
')

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These can merge to a single optional.

Comment thread policy/modules/apps/wireplumber.te Outdated
Comment on lines +191 to +194
optional_policy(`
systemd_user_daemon_domain(user, wireplumber_exec_t, wireplumber_t)
systemd_user_daemon_domain(staff, wireplumber_exec_t, wireplumber_t)
')

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should go as a single call in wireplumber_role().

@tkanfade tkanfade force-pushed the wireplumber_module branch from b0f80a5 to 2ccde9e Compare July 1, 2026 06:54
WirePlumber is the session manager for the PipeWire multimedia
framework. On standard Linux desktops it runs as a user service
(systemd --user). On embedded/headless platforms such as Qualcomm
QLI 2.0 it runs as a system-wide service (User=pipewire under
system systemd).

Without a dedicated policy WirePlumber falls back to the generic
initrc_t domain. In initrc_t, SELinux blocks D-Bus method replies
from modemmanager_t and bluetooth_t which are required for telephony
and Bluetooth audio routing. The blocked replies cause WirePlumber
to crash with SIGSEGV every ~25 seconds resulting in wpctl set-default
and pw-play --target failures.

The policy uses a compile-time ifdef(`wireplumber_system_service')
switch following the same pattern as pipewire.te to select between
system-service and user-service mode at m4 build time.

The policy module is placed in apps/ consistent with pipewire.

The policy confines the wireplumber_t domain with:
- Domain transition via wireplumber_exec_t
- PipeWire socket communication via pipewire_stream_connect(),
  pipewire_use_fds() and pipewire_mmap_rw_tmpfs_files() for zero-copy
  memfd buffer sharing (depends on pipewire policy PR SELinuxProject#1109)
- Runtime directory management (system: /run/wireplumber,
  user: XDG_RUNTIME_DIR/wireplumber)
- tmpfs/memfd shared memory for zero-copy audio buffers
- Config file mmap via files_map_usr_files()
- D-Bus system bus; dbus_system_domain when system service
- D-Bus communication with ModemManager, BlueZ and oFono
- udev runtime access for device monitoring including
  netlink_kobject_uevent_socket and xattr filesystem getattr
- systemd sessions and logind session directory watch
- /etc/machine-id, procfs, sysfs
- /dev/snd inotify watch for device monitoring
- Bluetooth socket with listen permission for BlueZ audio routing
- RTKit realtime scheduling support
- systemd journal logging
- NSS lookups via auth_use_nsswitch

Also adds ofono_dbus_chat() interface to ofono.if to allow
bidirectional D-Bus communication between a domain and oFono.

Also adds wireplumber_role() 4-param template to wireplumber.if and
wires it into unprivuser.te and staff.te following the same pattern as
pipewire_role() in pipewire.if.

Validated:
- System-service mode: RB3Gen2-Core-Kit (QCS6490) SELinux enforcing,
  wireplumber_t domain confirmed, wpctl set-default exit:0,
  pw-play --target exit:0, zero AVC denials.
- System-service mode: IQ-9075-EVK (SA9075) SELinux enforcing,
  wireplumber_t domain confirmed, wpctl status OK, zero AVC denials.
- User-service mode: Fedora 41 VM SELinux enforcing,
  wireplumber_t domain confirmed, zero AVC denials.

Note: This patch depends on the pipewire policy (PR SELinuxProject#1109, now merged).
wireplumber.te uses pipewire_stream_connect(), pipewire_use_fds() and
pipewire_mmap_rw_tmpfs_files() defined in pipewire.if.

Signed-off-by: Tejas Vijay Kanfade <tkanfade@qti.qualcomm.com>
@tkanfade tkanfade force-pushed the wireplumber_module branch from 2ccde9e to 97c83a2 Compare July 1, 2026 08:32
@pebenito

pebenito commented Jul 2, 2026

Copy link
Copy Markdown
Member

@WavyEbuilder @aerusso do you have any further comments?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants