From f0654a636901fb59febeef3ebff5cf974bcb78b1 Mon Sep 17 00:00:00 2001 From: Tejas Vijay Kanfade Date: Wed, 27 May 2026 18:41:44 +0530 Subject: [PATCH 01/13] wireplumber: add SELinux policy module 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_rw_tmpfs_files() for zero-copy memfd buffer sharing (depends on pipewire policy PR #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 Also adds ofono_dbus_chat() interface to ofono.if to allow bidirectional D-Bus communication between a domain and oFono. Also adds wireplumber_role() interface to wireplumber.if to wire up role access for user-service mode, following the same pattern as pipewire_role() in pipewire.if. Also extends pipewire.fc to label /usr/bin/wpctl as pipewire_exec_t so that wpctl transitions into pipewire_t and operates without AVC denials. Note: This patch depends on the pipewire policy (PR #1109). Please merge PR #1109 before this patch, as wireplumber.te uses pipewire_stream_connect(), pipewire_use_fds() and pipewire_rw_tmpfs_files() defined in pipewire.if. Signed-off-by: Tejas Vijay Kanfade --- policy/modules/apps/pipewire.fc | 1 + policy/modules/apps/wireplumber.fc | 9 ++ policy/modules/apps/wireplumber.if | 45 ++++++++++ policy/modules/apps/wireplumber.te | 138 +++++++++++++++++++++++++++++ policy/modules/services/ofono.if | 26 ++++++ 5 files changed, 219 insertions(+) create mode 100644 policy/modules/apps/wireplumber.fc create mode 100644 policy/modules/apps/wireplumber.if create mode 100644 policy/modules/apps/wireplumber.te diff --git a/policy/modules/apps/pipewire.fc b/policy/modules/apps/pipewire.fc index 10276c7d93..c86e4fbfdc 100644 --- a/policy/modules/apps/pipewire.fc +++ b/policy/modules/apps/pipewire.fc @@ -1,5 +1,6 @@ # PipeWire daemon executable. /usr/bin/pipewire -- gen_context(system_u:object_r:pipewire_exec_t,s0) +/usr/bin/wpctl -- gen_context(system_u:object_r:pipewire_exec_t,s0) # pw-cat is a standalone client utility (plays/captures audio via a running # PipeWire daemon); it runs in pipewire_client_t, not pipewire_t. diff --git a/policy/modules/apps/wireplumber.fc b/policy/modules/apps/wireplumber.fc new file mode 100644 index 0000000000..8d36908778 --- /dev/null +++ b/policy/modules/apps/wireplumber.fc @@ -0,0 +1,9 @@ +HOME_DIR/\.config/wireplumber(/.*)? gen_context(system_u:object_r:wireplumber_home_t,s0) +HOME_DIR/\.local/share/wireplumber(/.*)? gen_context(system_u:object_r:wireplumber_home_t,s0) + +/run/wireplumber(/.*)? gen_context(system_u:object_r:wireplumber_runtime_t,s0) +/run/user/%{USERID}/wireplumber(/.*)? gen_context(system_u:object_r:wireplumber_runtime_t,s0) + +/usr/bin/wireplumber -- gen_context(system_u:object_r:wireplumber_exec_t,s0) + +/var/lib/wireplumber(/.*)? gen_context(system_u:object_r:wireplumber_var_lib_t,s0) diff --git a/policy/modules/apps/wireplumber.if b/policy/modules/apps/wireplumber.if new file mode 100644 index 0000000000..f3516fbb2d --- /dev/null +++ b/policy/modules/apps/wireplumber.if @@ -0,0 +1,45 @@ +## Policy for WirePlumber, the PipeWire session manager. + +######################################## +## +## Connect to WirePlumber over a unix stream socket. +## +## +## +## Domain allowed access. +## +## +# +interface(`wireplumber_stream_connect',` + gen_require(` + type wireplumber_t, wireplumber_runtime_t; + ') + + files_search_runtime($1) + stream_connect_pattern($1, wireplumber_runtime_t, wireplumber_runtime_t, wireplumber_t) +') + +######################################## +## +## Role access for WirePlumber in user-service mode. +## +## +## +## Role allowed access. +## +## +## +## +## User domain for the role. +## +## +# +interface(`wireplumber_role',` + gen_require(` + type wireplumber_t, wireplumber_exec_t; + attribute_role wireplumber_roles; + ') + + roleattribute $1 wireplumber_roles; + domtrans_pattern($2, wireplumber_exec_t, wireplumber_t) +') diff --git a/policy/modules/apps/wireplumber.te b/policy/modules/apps/wireplumber.te new file mode 100644 index 0000000000..42a60353ab --- /dev/null +++ b/policy/modules/apps/wireplumber.te @@ -0,0 +1,138 @@ +policy_module(wireplumber) + +######################################## +# +# Declarations +# + +attribute_role wireplumber_roles; + +type wireplumber_t; +type wireplumber_exec_t; +ifdef(`wireplumber_system_service',` + init_daemon_domain(wireplumber_t, wireplumber_exec_t) +',` + userdom_user_application_domain(wireplumber_t, wireplumber_exec_t) + role wireplumber_roles types wireplumber_t; +') + +type wireplumber_home_t alias wireplumber_var_lib_t; +userdom_user_home_content(wireplumber_home_t) + +type wireplumber_runtime_t; +files_runtime_file(wireplumber_runtime_t) + +type wireplumber_tmpfs_t; +userdom_user_tmpfs_file(wireplumber_tmpfs_t) + +######################################## +# +# Local policy +# + +allow wireplumber_t self:process { getsched setsched signal signull }; +allow wireplumber_t self:capability sys_nice; +allow wireplumber_t self:fifo_file rw_fifo_file_perms; +allow wireplumber_t self:unix_stream_socket { create_stream_socket_perms connectto }; +allow wireplumber_t self:unix_dgram_socket create_socket_perms; + +# Bluetooth socket (for BlueZ audio routing) +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 }; + +dev_read_sysfs(wireplumber_t) + +# /dev/snd inotify watch for device monitoring +dev_watch_dev_dirs(wireplumber_t) + +# filesystem getattr +dev_getattr_fs(wireplumber_t) +fs_getattr_xattr_fs(wireplumber_t) + +# v4l device getattr (video device enumeration) +dev_dontaudit_getattr_video_dev(wireplumber_t) + +files_read_usr_files(wireplumber_t) +files_map_usr_files(wireplumber_t) +files_read_etc_files(wireplumber_t) + +# /etc/machine-id +files_read_etc_runtime_files(wireplumber_t) + +kernel_read_system_state(wireplumber_t) + +domain_dontaudit_read_all_domains_state(wireplumber_t) + +logging_send_syslog_msg(wireplumber_t) + +miscfiles_read_localization(wireplumber_t) + +# Connect to PipeWire runtime socket +optional_policy(` + pipewire_stream_connect(wireplumber_t) +') + +# Use file descriptors passed from PipeWire (e.g. memfd) +optional_policy(` + pipewire_use_fds(wireplumber_t) +') + +# Access PipeWire tmpfs shared memory (memfd zero-copy buffers) +optional_policy(` + pipewire_rw_tmpfs_files(wireplumber_t) +') + +# Runtime directory management - differs between system and user service +ifdef(`wireplumber_system_service',` + files_var_lib_filetrans(wireplumber_t, wireplumber_home_t, { dir file }) + files_runtime_filetrans(wireplumber_t, wireplumber_runtime_t, { dir file sock_file }) +',` + userdom_user_runtime_filetrans(wireplumber_t, wireplumber_runtime_t, dir) + userdom_user_home_dir_filetrans(wireplumber_t, wireplumber_home_t, dir) +') + +# tmpfs shared memory (memfd for zero-copy audio buffers) +mmap_manage_files_pattern(wireplumber_t, wireplumber_tmpfs_t, wireplumber_tmpfs_t) +fs_tmpfs_filetrans(wireplumber_t, wireplumber_tmpfs_t, file) + +# udev runtime data (/run/udev) +udev_search_runtime(wireplumber_t) +udev_read_runtime_files(wireplumber_t) + +# systemd sessions (/run/systemd/sessions) +systemd_read_logind_sessions_files(wireplumber_t) +systemd_watch_logind_sessions_dirs(wireplumber_t) + +optional_policy(` + dbus_system_bus_client(wireplumber_t) + dbus_connect_system_bus(wireplumber_t) + + ifdef(`wireplumber_system_service',` + dbus_system_domain(wireplumber_t, wireplumber_exec_t) + ') +') + +# Allow ModemManager D-Bus replies to wireplumber_t +optional_policy(` + modemmanager_dbus_chat(wireplumber_t) +') + +# Allow BlueZ D-Bus signals to wireplumber_t +optional_policy(` + bluetooth_dbus_chat(wireplumber_t) +') + +# Allow oFono D-Bus communication (telephony) +optional_policy(` + ofono_dbus_chat(wireplumber_t) +') + +optional_policy(` + rtkit_scheduled(wireplumber_t) +') + +optional_policy(` + systemd_read_journal_files(wireplumber_t) +') diff --git a/policy/modules/services/ofono.if b/policy/modules/services/ofono.if index 51c9d4e195..2d075ae633 100644 --- a/policy/modules/services/ofono.if +++ b/policy/modules/services/ofono.if @@ -7,3 +7,29 @@ ## ## https://git.kernel.org/pub/scm/network/ofono/ofono.git ## + +######################################## +## +## Allow D-Bus communication with oFono. +## +## +##

+## Allow the specified domain to send and receive D-Bus +## messages to/from oFono for telephony audio routing. +##

+##
+## +## +## Domain allowed access. +## +## +# +interface(`ofono_dbus_chat',` + gen_require(` + type ofono_t; + class dbus send_msg; + ') + + allow $1 ofono_t:dbus send_msg; + allow ofono_t $1:dbus send_msg; +') From 6fb3db13048a740c579fc95979165b609c796982 Mon Sep 17 00:00:00 2001 From: Antonio Enrico Russo Date: Mon, 29 Jun 2026 04:23:16 -0600 Subject: [PATCH 02/13] ofono: remove typo in comments This extra `#` character causes a compilation error when any interfaces are added to `ofono.if`. Signed-off-by: Antonio Enrico Russo --- policy/modules/services/ofono.if | 1 - 1 file changed, 1 deletion(-) diff --git a/policy/modules/services/ofono.if b/policy/modules/services/ofono.if index 2d075ae633..3c91f815dc 100644 --- a/policy/modules/services/ofono.if +++ b/policy/modules/services/ofono.if @@ -1,5 +1,4 @@ ## ofono -# ## ## oFono is a stack for mobile telephony devices on Linux. ## oFono supports speaking to telephony devices through specific drivers, From 75e2aa57c9f9264cd9d541aee05d82c68132424b Mon Sep 17 00:00:00 2001 From: Antonio Enrico Russo Date: Sat, 27 Jun 2026 08:44:27 -0600 Subject: [PATCH 03/13] pulseaudio: add server interface Many programs interact with pulseaudio through an interface, and the pulseaudio module allows pulseaudio_t to expose that interface. Other programs (in particualr, pipewire acting as pipewire-pulseaudio) also expose this interface. Here, that interface is exposed via a new `pulseaudio_provide_server` interface, and pipewire uses it. Signed-off-by: Antonio Enrico Russo --- policy/modules/apps/pipewire.te | 2 +- policy/modules/apps/pulseaudio.if | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/policy/modules/apps/pipewire.te b/policy/modules/apps/pipewire.te index a30e2da62c..dc9a21ed2f 100644 --- a/policy/modules/apps/pipewire.te +++ b/policy/modules/apps/pipewire.te @@ -100,7 +100,7 @@ optional_policy(` # PulseAudio compatibility layer (pipewire-pulse connects to PulseAudio clients). optional_policy(` - pulseaudio_stream_connect(pipewire_t) + pulseaudio_provide_server(pipewire_t) ') # Real-time scheduling priority via rtkit-daemon. diff --git a/policy/modules/apps/pulseaudio.if b/policy/modules/apps/pulseaudio.if index 06c262d98d..6372251c45 100644 --- a/policy/modules/apps/pulseaudio.if +++ b/policy/modules/apps/pulseaudio.if @@ -446,3 +446,30 @@ interface(`pulseaudio_rw_tmpfs_files',` fs_search_tmpfs($1) rw_files_pattern($1, pulseaudio_tmpfs_t, pulseaudio_tmpfs_t) ') + +####################################### +## +## Allow specified domain to act as a pulseaudio server. +## +## +## +## Domain allowed/allowing access. +## +## +# +interface(`pulseaudio_provide_server',` + gen_require(` + attribute pulseaudio_client; + type pulseaudio_tmp_t; + ') + + manage_dirs_pattern($1, pulseaudio_tmp_t, pulseaudio_tmp_t) + manage_files_pattern($1, pulseaudio_tmp_t, pulseaudio_tmp_t) + allow $1 pulseaudio_tmp_t:file map; + manage_sock_files_pattern($1, pulseaudio_tmp_t, pulseaudio_tmp_t) + userdom_user_runtime_filetrans($1, pulseaudio_tmp_t, dir, "pulse") + pulseaudio_stream_connect($1) + ps_process_pattern($1, pulseaudio_client) + + allow pulseaudio_client $1:fd use; +') From 54bd92951dfcbbcf6dffe0e0517892c3c604dbfb Mon Sep 17 00:00:00 2001 From: Antonio Enrico Russo Date: Mon, 29 Jun 2026 04:38:12 -0600 Subject: [PATCH 04/13] pipewire: more runtime transitions pipewire makes (at least) pipewire-*{,-manager}{,.lock} files under the user runtime directory. This allows pipewire to properly label them. Signed-off-by: Antonio Enrico Russo --- policy/modules/apps/pipewire.fc | 4 +++- policy/modules/apps/pipewire.te | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/policy/modules/apps/pipewire.fc b/policy/modules/apps/pipewire.fc index c86e4fbfdc..cc4672c13d 100644 --- a/policy/modules/apps/pipewire.fc +++ b/policy/modules/apps/pipewire.fc @@ -12,7 +12,9 @@ /run/pipewire(/.*)? gen_context(system_u:object_r:pipewire_runtime_t,s0) # User-session runtime sockets live under $XDG_RUNTIME_DIR/pipewire and are -# labelled at runtime via userdom_user_runtime_filetrans; no static entry needed. +# labelled at runtime via userdom_user_runtime_filetrans +# Static entry added for restorecon +/run/user/%{USERID}/pipewire-.* gen_context(system_u:object_r:pipewire_runtime_t,s0) # Persistent system-service state. /var/lib/pipewire(/.*)? gen_context(system_u:object_r:pipewire_var_lib_t,s0) diff --git a/policy/modules/apps/pipewire.te b/policy/modules/apps/pipewire.te index dc9a21ed2f..4b43ba6ef4 100644 --- a/policy/modules/apps/pipewire.te +++ b/policy/modules/apps/pipewire.te @@ -154,8 +154,8 @@ ifndef(`pipewire_system_service',` allow pipewire_t pipewire_home_t:file mmap_manage_file_perms; manage_lnk_files_pattern(pipewire_t, pipewire_home_t, pipewire_home_t) - # Runtime socket directory transition under $XDG_RUNTIME_DIR/pipewire. - userdom_user_runtime_filetrans(pipewire_t, pipewire_runtime_t, dir, "pipewire") + # Runtime transition under $XDG_RUNTIME_DIR + userdom_user_runtime_filetrans(pipewire_t, pipewire_runtime_t, { dir file sock_file }) # Session D-Bus (register org.PipeWire.* on the per-user session bus). optional_policy(` From d6a15697b89e56d8a9b3425074573a72bf3d0b72 Mon Sep 17 00:00:00 2001 From: Antonio Enrico Russo Date: Mon, 29 Jun 2026 04:49:09 -0600 Subject: [PATCH 05/13] pipewire: add new pipewire_dbus_chat Many programs will talk with the pipewire server over dbus. Allow such activity via a new pipewire_dbus_chat interface. Signed-off-by: Antonio Enrico Russo --- policy/modules/apps/pipewire.if | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/policy/modules/apps/pipewire.if b/policy/modules/apps/pipewire.if index f24a7466f0..cfe69a80b6 100644 --- a/policy/modules/apps/pipewire.if +++ b/policy/modules/apps/pipewire.if @@ -165,6 +165,27 @@ interface(`pipewire_use_fds',` allow $1 pipewire_t:fd use; ') +######################################## +## +## Send and receive messages from +## pipewire over dbus. +## +## +## +## Domain allowed access. +## +## +# +interface(`pipewire_dbus_chat',` + gen_require(` + type pipewire_t; + class dbus send_msg; + ') + + allow $1 pipewire_t:dbus send_msg; + allow pipewire_t $1:dbus send_msg; +') + ######################################## ## ## Use file descriptors inherited from PipeWire clients. From 78cf27a89e1fce09a20337793017220aa470d364 Mon Sep 17 00:00:00 2001 From: Antonio Enrico Russo Date: Mon, 29 Jun 2026 04:46:41 -0600 Subject: [PATCH 06/13] pipewire: add pipewire_client_domain interface Many programs will interact with pipewire through an interface. Define that interface, and expose it via the new pipewire_client_domain. Additionally, use it for the pipewire_client_t domain. Signed-off-by: Antonio Enrico Russo --- policy/modules/apps/pipewire.if | 22 ++++++++++++++++++++++ policy/modules/apps/pipewire.te | 30 ++++++++++++++++++++---------- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/policy/modules/apps/pipewire.if b/policy/modules/apps/pipewire.if index cfe69a80b6..7ccc2aa484 100644 --- a/policy/modules/apps/pipewire.if +++ b/policy/modules/apps/pipewire.if @@ -61,6 +61,8 @@ template(`pipewire_role',` allow $2 pipewire_runtime_t:dir { manage_dir_perms relabel_dir_perms }; allow $2 pipewire_runtime_t:sock_file { manage_sock_file_perms relabel_sock_file_perms }; + pipewire_client_domain($2) + # Allow the user domain to manage shared memory files created by the daemon. pipewire_mmap_rw_tmpfs_files($2) allow $2 pipewire_tmpfs_t:file relabel_file_perms; @@ -244,3 +246,23 @@ interface(`pipewire_read_home_files',` read_files_pattern($1, pipewire_home_t, pipewire_home_t) read_lnk_files_pattern($1, pipewire_home_t, pipewire_home_t) ') + +######################################## +## +## Connect to pipewire and manage +## pipewire config data. +## +## +## +## Domain allowed access. +## +## +# +interface(`pipewire_client_domain',` + gen_require(` + attribute pipewire_client; + ') + + typeattribute $1 pipewire_client; + dbus_all_session_bus_client($1) +') diff --git a/policy/modules/apps/pipewire.te b/policy/modules/apps/pipewire.te index 4b43ba6ef4..2aa9a68986 100644 --- a/policy/modules/apps/pipewire.te +++ b/policy/modules/apps/pipewire.te @@ -16,6 +16,8 @@ policy_module(pipewire) attribute_role pipewire_roles; +attribute pipewire_client; + # # pipewire_t — the PipeWire multimedia daemon. # @@ -170,6 +172,23 @@ ifndef(`pipewire_system_service',` ') ') +######################################## +# +# pipewire_client domain +# +# domain that captures requirements to use the pipewire service +# + +pipewire_stream_connect(pipewire_client) +pipewire_rw_stream_sockets(pipewire_client) +pipewire_mmap_rw_tmpfs_files(pipewire_client) +pipewire_use_fds(pipewire_client) +allow pipewire_t pipewire_client:fd use; + +optional_policy(` + pipewire_dbus_chat(pipewire_client) +') + ######################################## # # pipewire_client_t — pw-cat and other client utilities @@ -192,11 +211,7 @@ kernel_read_system_state(pipewire_client_t) miscfiles_read_localization(pipewire_client_t) # Connect to the PipeWire daemon socket and map its shared memory buffers. -pipewire_stream_connect(pipewire_client_t) -pipewire_rw_stream_sockets(pipewire_client_t) -pipewire_mmap_rw_tmpfs_files(pipewire_client_t) -pipewire_use_fds(pipewire_client_t) -pipewire_use_client_fds(pipewire_t) +pipewire_client_domain(pipewire_client_t) # Read media files from the user's home, and allow capture tools such as # pw-record to manage user-selected output files in /tmp. @@ -207,8 +222,3 @@ userdom_tmp_filetrans_user_tmp(pipewire_client_t, file) optional_policy(` alsa_read_config(pipewire_client_t) ') - -optional_policy(` - dbus_all_session_bus_client(pipewire_client_t) - dbus_connect_all_session_bus(pipewire_client_t) -') From c878ed70863098843bc134bd49ad49cd92ef8c39 Mon Sep 17 00:00:00 2001 From: Antonio Enrico Russo Date: Mon, 29 Jun 2026 04:50:19 -0600 Subject: [PATCH 07/13] pipewire: allow setting rlimits Pipewire manages its resource limits. As a relatively trusted service, this should be allowed. Signed-off-by: Antonio Enrico Russo --- policy/modules/apps/pipewire.te | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/policy/modules/apps/pipewire.te b/policy/modules/apps/pipewire.te index 2aa9a68986..140b516dea 100644 --- a/policy/modules/apps/pipewire.te +++ b/policy/modules/apps/pipewire.te @@ -56,7 +56,7 @@ userdom_user_tmpfs_file(pipewire_tmpfs_t) # allow pipewire_t self:capability sys_nice; -allow pipewire_t self:process { getsched setsched signal sigchld }; +allow pipewire_t self:process { getsched setsched signal sigchld setrlimit }; allow pipewire_t self:fifo_file rw_fifo_file_perms; allow pipewire_t self:unix_stream_socket { create_stream_socket_perms connectto }; From fd4a47df47e9a68e66cdbd80991869e0d4be9c9e Mon Sep 17 00:00:00 2001 From: Antonio Enrico Russo Date: Mon, 29 Jun 2026 04:51:24 -0600 Subject: [PATCH 08/13] pipewire: allow video access Pipewire goes beyond serving audio, and needs access to video devices. Signed-off-by: Antonio Enrico Russo --- policy/modules/apps/pipewire.te | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/policy/modules/apps/pipewire.te b/policy/modules/apps/pipewire.te index 140b516dea..3fc7f2f9a9 100644 --- a/policy/modules/apps/pipewire.te +++ b/policy/modules/apps/pipewire.te @@ -74,6 +74,10 @@ fs_tmpfs_filetrans(pipewire_t, pipewire_tmpfs_t, file) dev_read_sound(pipewire_t) dev_write_sound(pipewire_t) +# Video hardware access. +dev_read_video_dev(pipewire_t) +dev_write_video_dev(pipewire_t) + # Device enumeration via sysfs (discovering ALSA/USB audio devices at startup). dev_read_sysfs(pipewire_t) From 38fc0cffa3434a073ce0fc97f58b554295173986 Mon Sep 17 00:00:00 2001 From: Antonio Enrico Russo Date: Mon, 29 Jun 2026 04:52:12 -0600 Subject: [PATCH 09/13] pipewire: allow kernel module loading Pipewire will load modules to handle "hotplugged" audio and/or audio codec changes. Allow these module loads. Signed-off-by: Antonio Enrico Russo --- policy/modules/apps/pipewire.te | 1 + 1 file changed, 1 insertion(+) diff --git a/policy/modules/apps/pipewire.te b/policy/modules/apps/pipewire.te index 3fc7f2f9a9..0e4b1bec18 100644 --- a/policy/modules/apps/pipewire.te +++ b/policy/modules/apps/pipewire.te @@ -87,6 +87,7 @@ domain_dontaudit_read_all_domains_state(pipewire_t) # Read /proc state for scheduling and memory info. kernel_read_system_state(pipewire_t) +kernel_request_load_module(pipewire_t) files_read_etc_files(pipewire_t) files_read_usr_files(pipewire_t) From b065433b20be434e3245046ca55c2924d0eed2ed Mon Sep 17 00:00:00 2001 From: Antonio Enrico Russo Date: Mon, 29 Jun 2026 04:53:15 -0600 Subject: [PATCH 10/13] pipewire: allow terminal access Command line utilities write to the terminal; allow such access. Signed-off-by: Antonio Enrico Russo --- policy/modules/apps/pipewire.te | 3 +++ 1 file changed, 3 insertions(+) diff --git a/policy/modules/apps/pipewire.te b/policy/modules/apps/pipewire.te index 0e4b1bec18..a8cba0a37c 100644 --- a/policy/modules/apps/pipewire.te +++ b/policy/modules/apps/pipewire.te @@ -97,6 +97,8 @@ logging_send_syslog_msg(pipewire_t) miscfiles_read_localization(pipewire_t) +userdom_use_user_terminals(pipewire_t) + # NSS/name-service lookups to resolve user names for session ownership checks. auth_use_nsswitch(pipewire_t) @@ -223,6 +225,7 @@ pipewire_client_domain(pipewire_client_t) userdom_read_user_home_content_files(pipewire_client_t) userdom_manage_user_tmp_files(pipewire_client_t) userdom_tmp_filetrans_user_tmp(pipewire_client_t, file) +userdom_use_user_terminals(pipewire_client_t) optional_policy(` alsa_read_config(pipewire_client_t) From ebaaf370a6e4c8d07a97e9faefb6732b448eb7c8 Mon Sep 17 00:00:00 2001 From: Antonio Enrico Russo Date: Mon, 29 Jun 2026 04:54:18 -0600 Subject: [PATCH 11/13] pipewire: miscellaneous configuration access Signed-off-by: Antonio Enrico Russo --- policy/modules/apps/pipewire.te | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/policy/modules/apps/pipewire.te b/policy/modules/apps/pipewire.te index a8cba0a37c..b3e7fd80aa 100644 --- a/policy/modules/apps/pipewire.te +++ b/policy/modules/apps/pipewire.te @@ -105,6 +105,8 @@ auth_use_nsswitch(pipewire_t) # ALSA configuration files (/etc/alsa/*, ~/.asoundrc). optional_policy(` alsa_read_config(pipewire_t) + alsa_read_home_files(pipewire_t) + alsa_read_lib(pipewire_t) ') # PulseAudio compatibility layer (pipewire-pulse connects to PulseAudio clients). @@ -177,6 +179,10 @@ ifndef(`pipewire_system_service',` systemd_user_daemon_domain(user, pipewire_exec_t, pipewire_t) systemd_user_daemon_domain(staff, pipewire_exec_t, pipewire_t) ') + + optional_policy(` + xdg_search_config_dirs(pipewire_t) + ') ') ######################################## From 6906e65d9f300afb300e5986153a4f0ae742f7ae Mon Sep 17 00:00:00 2001 From: Antonio Enrico Russo Date: Mon, 29 Jun 2026 04:55:07 -0600 Subject: [PATCH 12/13] pipewire: miscellaneous dbus access Signed-off-by: Antonio Enrico Russo --- policy/modules/apps/pipewire.te | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/policy/modules/apps/pipewire.te b/policy/modules/apps/pipewire.te index b3e7fd80aa..064bbd77b2 100644 --- a/policy/modules/apps/pipewire.te +++ b/policy/modules/apps/pipewire.te @@ -124,6 +124,10 @@ optional_policy(` systemd_read_journal_files(pipewire_t) ') +optional_policy(` + dbus_system_bus_client(pipewire_t) +') + ######################################## # # pipewire_t — system-service-only policy @@ -172,6 +176,7 @@ ifndef(`pipewire_system_service',` optional_policy(` dbus_all_session_bus_client(pipewire_t) dbus_connect_all_session_bus(pipewire_t) + dbus_write_session_runtime_socket(pipewire_t) ') # Allow systemd --user to start the user-service instance. From a43226e1ffc235c48acbdae9eaff8e19a5ca98c8 Mon Sep 17 00:00:00 2001 From: Antonio Enrico Russo Date: Mon, 29 Jun 2026 04:55:59 -0600 Subject: [PATCH 13/13] wireplumber: revisions These changes got wireplumber working on a Debian trixie desktop. Signed-off-by: Antonio Enrico Russo --- policy/modules/apps/wireplumber.fc | 1 + policy/modules/apps/wireplumber.if | 58 ++++++++++++++++++++++++++---- policy/modules/apps/wireplumber.te | 54 +++++++++++++++++++--------- policy/modules/roles/staff.te | 4 +++ policy/modules/roles/unprivuser.te | 4 +++ 5 files changed, 98 insertions(+), 23 deletions(-) diff --git a/policy/modules/apps/wireplumber.fc b/policy/modules/apps/wireplumber.fc index 8d36908778..ff24bf0a4a 100644 --- a/policy/modules/apps/wireplumber.fc +++ b/policy/modules/apps/wireplumber.fc @@ -1,5 +1,6 @@ HOME_DIR/\.config/wireplumber(/.*)? gen_context(system_u:object_r:wireplumber_home_t,s0) HOME_DIR/\.local/share/wireplumber(/.*)? gen_context(system_u:object_r:wireplumber_home_t,s0) +HOME_DIR/\.local/state/wireplumber(/.*)? gen_context(system_u:object_r:wireplumber_home_t,s0) /run/wireplumber(/.*)? gen_context(system_u:object_r:wireplumber_runtime_t,s0) /run/user/%{USERID}/wireplumber(/.*)? gen_context(system_u:object_r:wireplumber_runtime_t,s0) diff --git a/policy/modules/apps/wireplumber.if b/policy/modules/apps/wireplumber.if index f3516fbb2d..b5fc97aa5b 100644 --- a/policy/modules/apps/wireplumber.if +++ b/policy/modules/apps/wireplumber.if @@ -19,27 +19,73 @@ interface(`wireplumber_stream_connect',` stream_connect_pattern($1, wireplumber_runtime_t, wireplumber_runtime_t, wireplumber_t) ') +######################################## +## +## Send and receive messages from +## wireplumber over dbus. +## +## +## +## Domain allowed access. +## +## +# +interface(`wireplumber_dbus_chat',` + gen_require(` + type wireplumber_t; + class dbus send_msg; + ') + + allow $1 wireplumber_t:dbus send_msg; + allow wireplumber_t $1:dbus send_msg; +') + ######################################## ## ## Role access for WirePlumber in user-service mode. ## -## +## ## -## Role allowed access. +## The prefix of the user role (e.g., "user" for user_r). ## ## -## +## +## +## User domain for the role (e.g., user_t). +## +## +## ## -## User domain for the role. +## User exec domain for execute and transition access +## (e.g., user_application_exec_domain). +## +## +## +## +## Role allowed access (e.g., user_r). ## ## # interface(`wireplumber_role',` gen_require(` type wireplumber_t, wireplumber_exec_t; + type wireplumber_tmpfs_t, wireplumber_runtime_t, wireplumber_home_t; attribute_role wireplumber_roles; ') - roleattribute $1 wireplumber_roles; - domtrans_pattern($2, wireplumber_exec_t, wireplumber_t) + wireplumber_dbus_chat($2) + + roleattribute $4 wireplumber_roles; + ifndef(`wireplumber_system_service',` + manage_files_pattern($2, wireplumber_tmpfs_t, wireplumber_tmpfs_t) + manage_sock_files_pattern($2, wireplumber_tmpfs_t, wireplumber_tmpfs_t) + manage_dirs_pattern($2, wireplumber_tmpfs_t, wireplumber_tmpfs_t) + manage_files_pattern($2, wireplumber_runtime_t, wireplumber_runtime_t) + manage_sock_files_pattern($2, wireplumber_runtime_t, wireplumber_runtime_t) + manage_dirs_pattern($2, wireplumber_runtime_t, wireplumber_runtime_t) + manage_files_pattern($2, wireplumber_home_t, wireplumber_home_t) + manage_dirs_pattern($2, wireplumber_home_t, wireplumber_home_t) + systemd_user_daemon_domain($1, wireplumber_exec_t, wireplumber_t) + domtrans_pattern($3, wireplumber_exec_t, wireplumber_t) + ') ') diff --git a/policy/modules/apps/wireplumber.te b/policy/modules/apps/wireplumber.te index 42a60353ab..0be2016dcd 100644 --- a/policy/modules/apps/wireplumber.te +++ b/policy/modules/apps/wireplumber.te @@ -30,17 +30,20 @@ userdom_user_tmpfs_file(wireplumber_tmpfs_t) # Local policy # -allow wireplumber_t self:process { getsched setsched signal signull }; +allow wireplumber_t self:process { getsched setsched signal signull setrlimit }; allow wireplumber_t self:capability sys_nice; allow wireplumber_t self:fifo_file rw_fifo_file_perms; allow wireplumber_t self:unix_stream_socket { create_stream_socket_perms connectto }; allow wireplumber_t self:unix_dgram_socket create_socket_perms; +manage_files_pattern(wireplumber_t, wireplumber_home_t, wireplumber_home_t) +manage_dirs_pattern(wireplumber_t, wireplumber_home_t, wireplumber_home_t) + # Bluetooth socket (for BlueZ audio routing) -allow wireplumber_t self:bluetooth_socket { create bind setopt listen }; +allow wireplumber_t self:bluetooth_socket { create bind setopt listen shutdown connect getopt read write }; # netlink kobject uevent socket (for udev device monitoring) -allow wireplumber_t self:netlink_kobject_uevent_socket { create bind setopt getattr getopt }; +allow wireplumber_t self:netlink_kobject_uevent_socket { create bind setopt getattr getopt read }; dev_read_sysfs(wireplumber_t) @@ -49,6 +52,7 @@ dev_watch_dev_dirs(wireplumber_t) # filesystem getattr dev_getattr_fs(wireplumber_t) +dev_getattr_sysfs(wireplumber_t) fs_getattr_xattr_fs(wireplumber_t) # v4l device getattr (video device enumeration) @@ -58,6 +62,12 @@ files_read_usr_files(wireplumber_t) files_map_usr_files(wireplumber_t) files_read_etc_files(wireplumber_t) +dev_read_sound(wireplumber_t) +dev_write_sound(wireplumber_t) + +dev_read_video_dev(wireplumber_t) +dev_write_video_dev(wireplumber_t) + # /etc/machine-id files_read_etc_runtime_files(wireplumber_t) @@ -69,19 +79,8 @@ logging_send_syslog_msg(wireplumber_t) miscfiles_read_localization(wireplumber_t) -# Connect to PipeWire runtime socket -optional_policy(` - pipewire_stream_connect(wireplumber_t) -') - -# Use file descriptors passed from PipeWire (e.g. memfd) optional_policy(` - pipewire_use_fds(wireplumber_t) -') - -# Access PipeWire tmpfs shared memory (memfd zero-copy buffers) -optional_policy(` - pipewire_rw_tmpfs_files(wireplumber_t) + pipewire_client_domain(wireplumber_t) ') # Runtime directory management - differs between system and user service @@ -91,6 +90,12 @@ ifdef(`wireplumber_system_service',` ',` userdom_user_runtime_filetrans(wireplumber_t, wireplumber_runtime_t, dir) userdom_user_home_dir_filetrans(wireplumber_t, wireplumber_home_t, dir) + + optional_policy(` + xdg_search_data_dirs(wireplumber_t) + xdg_search_config_dirs(wireplumber_t) + xdg_data_filetrans(wireplumber_t, wireplumber_home_t, dir, "wireplumber") + ') ') # tmpfs shared memory (memfd for zero-copy audio buffers) @@ -101,13 +106,23 @@ fs_tmpfs_filetrans(wireplumber_t, wireplumber_tmpfs_t, file) udev_search_runtime(wireplumber_t) udev_read_runtime_files(wireplumber_t) +optional_policy(` + alsa_read_config(wireplumber_t) + alsa_read_lib(wireplumber_t) +') + # systemd sessions (/run/systemd/sessions) -systemd_read_logind_sessions_files(wireplumber_t) -systemd_watch_logind_sessions_dirs(wireplumber_t) + +optional_policy(` + systemd_read_logind_sessions_files(wireplumber_t) + systemd_watch_logind_sessions_dirs(wireplumber_t) +') optional_policy(` dbus_system_bus_client(wireplumber_t) dbus_connect_system_bus(wireplumber_t) + dbus_write_session_runtime_socket(wireplumber_t) + dbus_connect_all_session_bus(wireplumber_t) ifdef(`wireplumber_system_service',` dbus_system_domain(wireplumber_t, wireplumber_exec_t) @@ -122,6 +137,11 @@ optional_policy(` # Allow BlueZ D-Bus signals to wireplumber_t optional_policy(` bluetooth_dbus_chat(wireplumber_t) + bluetooth_use(wireplumber_t) +') + +optional_policy(` + devicekit_dbus_chat_power(wireplumber_t) ') # Allow oFono D-Bus communication (telephony) diff --git a/policy/modules/roles/staff.te b/policy/modules/roles/staff.te index dfd4bfca8a..3ac58b097c 100644 --- a/policy/modules/roles/staff.te +++ b/policy/modules/roles/staff.te @@ -218,6 +218,10 @@ ifndef(`distro_redhat',` vmware_role(staff, staff_t, staff_application_exec_domain, staff_r) ') + optional_policy(` + wireplumber_role(staff, staff_t, staff_application_exec_domain, staff_r) + ') + optional_policy(` wireshark_role(staff, staff_t, staff_application_exec_domain, staff_r) ') diff --git a/policy/modules/roles/unprivuser.te b/policy/modules/roles/unprivuser.te index 888950f7c7..76fa12566e 100644 --- a/policy/modules/roles/unprivuser.te +++ b/policy/modules/roles/unprivuser.te @@ -198,6 +198,10 @@ ifndef(`distro_redhat',` vmware_role(user, user_t, user_application_exec_domain, user_r) ') + optional_policy(` + wireplumber_role(user, user_t, user_application_exec_domain, user_r) + ') + optional_policy(` wireshark_role(user, user_t, user_application_exec_domain, user_r) ')