pipewire: add policy for PipeWire multimedia daemon#1109
Conversation
There was a problem hiding this comment.
Please see the StyleGuide, as there are numerous style issues. The lint check below also identified some issues.
| /usr/share/pipewire(/.*)? gen_context(system_u:object_r:pipewire_share_t,s0) | ||
|
|
||
| # --- Runtime directories --- | ||
| /run/pipewire(/.*)? gen_context(system_u:object_r:pipewire_run_t,s0) |
There was a problem hiding this comment.
Where is this coming from...? Surely this should be relative to XDG_RUNTIME_DIR no?
There was a problem hiding this comment.
This policy was initially developed for a Qualcomm embedded platform where PipeWire runs as a system service (init_daemon_domain).
Modified now accordingly.
|
Other things which seem to be missing:
|
a8f64d8 to
c4a758b
Compare
| manage_files_pattern(pipewire_t, pipewire_tmpfs_t, pipewire_tmpfs_t) | ||
| allow pipewire_t pipewire_tmpfs_t:file map; |
There was a problem hiding this comment.
These lines can be merged by using the mmap_manage_files_pattern macro.
There was a problem hiding this comment.
Done. Replaced manage_files_pattern + file map for tmpfs with mmap_manage_files_pattern.
There was a problem hiding this comment.
Apologies, this was missed in the previous update. Now fixed.
| type pipewire_tmpfs_t; | ||
| userdom_user_tmpfs_file(pipewire_tmpfs_t) | ||
|
|
||
| type pipewire_var_lib_t; |
There was a problem hiding this comment.
Probably makes sense to rename this to pipewire_home_t (?) and alias pipewire_var_lib_t so it makes sense in system mode.
There was a problem hiding this comment.
Updated. Renamed to pipewire_home_t and added alias pipewire_var_lib_t. updated the file context label
accordingly
There was a problem hiding this comment.
I realized that there are still separate types here. pipewire_var_lib_t is not aliased to pipewire_home_t.
0f73a8a to
d5b2a82
Compare
thesamesam
left a comment
There was a problem hiding this comment.
I'm a bit surprised to not see WirePlumber in here, which is needed with remotely modern PipeWire unless you are using a custom session manager. Do you have plans for that?
| ## </summary> | ||
| ## </param> | ||
| # | ||
| interface(`pipewire_stream_connect',` |
There was a problem hiding this comment.
Do pw-cli and friends need this?
$ equery f pipewire | grep -i bin/
/usr/bin/pipewire
/usr/bin/pipewire-aes67
/usr/bin/pipewire-avb
/usr/bin/pipewire-pulse
/usr/bin/pw-cli
/usr/bin/pw-config
/usr/bin/pw-container
/usr/bin/pw-dot
/usr/bin/pw-dump
/usr/bin/pw-jack
/usr/bin/pw-link
/usr/bin/pw-loopback
/usr/bin/pw-metadata
/usr/bin/pw-mididump
/usr/bin/pw-mon
/usr/bin/pw-profiler
/usr/bin/pw-reserve
/usr/bin/pw-top
/usr/bin/pw-v4l2
/usr/bin/spa-acp-tool
/usr/bin/spa-inspect
/usr/bin/spa-json-dump
/usr/bin/spa-monitor
There was a problem hiding this comment.
yes, pw-cli and friends need pipewire_stream_connect called for their respective domains
There was a problem hiding this comment.
Pending still AFAICT, to be clear for Chris.
|
Thanks for all the review feedback. I'll be pushing an updated version shortly that addresses all open comments. |
|
One additional change I'd like to include: adding a pipewire_system_service tunable (defaulting to false) to support deployments where PipeWire runs as a system service rather than a user service. This is a real use-case on embedded Linux platforms, and downstream consumers of this policy have also requested that both modes be covered in a single upstream implementation rather than maintaining a separate out-of-tree patch. This aligns with pebenito's earlier suggestion: "I am also open to having it support system service, as long as it does not provide privileged/dangerous access when the system uses it as a user service." |
Yes, this is still acceptable. |
d5b2a82 to
84c99c7
Compare
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 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 - 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 SELinuxProject#1109). Please merge PR SELinuxProject#1109 before this patch. Signed-off-by: Tejas Vijay Kanfade <tkanfade@qti.qualcomm.com>
84c99c7 to
7ae3170
Compare
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 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 - 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 SELinuxProject#1109). Please merge PR SELinuxProject#1109 before this patch. Signed-off-by: Tejas Vijay Kanfade <tkanfade@qti.qualcomm.com>
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 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 - 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 SELinuxProject#1109). Please merge PR SELinuxProject#1109 before this patch. Signed-off-by: Tejas Vijay Kanfade <tkanfade@qti.qualcomm.com>
7ae3170 to
a06e374
Compare
a06e374 to
5434c95
Compare
| files_read_all_tmp_files(pipewire_t) | ||
|
|
||
| # Allow use of inherited stream sockets from init scripts (e.g. ADB shell) | ||
| init_rw_script_stream_sockets(pipewire_t) |
There was a problem hiding this comment.
I'm not sure if we really want to be doing this in every single consumer (e.g. #1137) and whether it should be handled elsewhere, but I'm still new to refpolicy development and I defer to Chris et. al.
There was a problem hiding this comment.
Thanks for raising this. A few points worth noting:
- Most distros don't use ADB shell as a primary shell, so this is a narrow, specific case.
- refpolicy itself doesn't provide a dedicated domain for ADB shell — it falls into initrc_t by default.
- initrc_t is effectively unconfined (we confirmed this with Chris Pebenito directly: Is unconfined_mount_t allowed to run with system role ? #1100 (comment)), so granting init_rw_script_stream_sockets to pipewire_t doesn't open up any meaningful new attack surface.
- This rule won't disturb anything in practice — it's a safe, no-op permission in the vast majority of deployments.
Given this, we believe keeping the rule as-is is fine. It follows the existing pattern used in policy modules and poses no real security concern.
There was a problem hiding this comment.
Most distros don't use ADB shell as a primary shell, so this is a narrow, specific case.
That's exactly why it's odd.
I'm still not sure it makes sense to put into every single policy w/ an init script but I won't argue over it, someone who knows refpol better can suggest an alternative.
There was a problem hiding this comment.
Thanks for raising this. A few points worth noting:
- Most distros don't use ADB shell as a primary shell, so this is a narrow, specific case.
Why is it initrc_t? That just doesn't make sense.
- refpolicy itself doesn't provide a dedicated domain for ADB shell — it falls into
initrc_t by default.
Well this is quite clearly needed by a lot of stuff. I don't understand why not just create a private domain for the adb shell?
- initrc_t is effectively unconfined (we confirmed this with Chris Pebenito directly: Is unconfined_mount_t allowed to run with system role ? #1100 (comment)), so granting init_rw_script_stream_sockets to pipewire_t doesn't open up any meaningful new attack surface.
I'd disagree. In fact, it actually opens up oodles of attack surface because it allows talking to a highly privileged process.
- This rule won't disturb anything in practice — it's a safe, no-op permission in the vast majority of deployments.
Given this, we believe keeping the rule as-is is fine. It follows the existing pattern used in policy modules and poses no real security concern.
I think at the minimum this should really be a tunable.
I am not an authority here, so judgement reserved for @pebenito, but I don't think it's wise to start adding the near endless talking to initrc_t that will be necessary because adb shell seems to break the tradition model of a "shell", and probably breaks rbac to it given that it's system_r. I think really there should be some kind of private domain for it.
There was a problem hiding this comment.
I don't think it's wise to start adding the near endless talking to initrc_t that will be necessary because adb shell seems to break the tradition model of a "shell
This is a good point; I think the access should remain a patch in the Qualcomm policy. Once we have a proper adb policy, you can drop it.
There was a problem hiding this comment.
I suggest #1137 should probably be reverted then.
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 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 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 SELinuxProject#1109). Please merge PR SELinuxProject#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 <tkanfade@qti.qualcomm.com>
WavyEbuilder
left a comment
There was a problem hiding this comment.
How was this tested? I'm not seeing RBAC for the user roles, nor am I seeing any process transitions either to actually run pipewire in the pipewire domain. I don't see a pipewire_role interface, nor do I see any domtrans_pattern either for user domains. I'm a bit concerned about whether this works correctly.
5434c95 to
84c7d10
Compare
added pipewire_role($1, $2) interface with roleattribute and domtrans_pattern. On the per-user type question: pulseaudio.te uses the same single-domain approach and it's the established upstream pattern. |
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 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 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 SELinuxProject#1109). Please merge PR SELinuxProject#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 <tkanfade@qti.qualcomm.com>
Tested on Qualcomm embedded in system-service mode. For user-service mode: userdom_user_application_domain sets up the exec entrypoint. pipewire_role (now added) wires up the role side for completeness. On the per-user $1_pipewire_t question, as pebenito noted on #1138, a derived per-user domain is only needed when there are transitions out of that domain to another derived domain or back to the user domain. PipeWire doesn't have those requirements, so a single pipewire_t with UBAC separation is sufficient, same as pulseaudio.te |
Ok, so I'm assuming that's what has been tested.
Well, yes, I left that note on my review. Stating my own review comments back to me does not alleviate my primary concern. My concern is that user services appear to be entirely untested given that this stuff is only being caught by review. I therefore don't think it's wise to write policy to target the user domain if it's not actually being tested by Qualcomm at all (which very much appears to be the case). Else, it'll end up either as:
As a side question, are you using an LLM for replies? I'm concerned that comments are not really being taken to heart or acknowledged, and I'd rather not partake in a debate with an LLM by proxy. I am finding it concerning that seemingly LLM written replies stating review comments back are used as justification.
At least for the user pipewire instance of which I can speak to, pipewire clients also needs to have their own tmpfs type, which pipewire needs to be able to read and write. The Wayland policy module is a good reference for the design there in my opinion as the semantics are fairly similar (though I might point out very much not a direct 1-1 clone at all; some design is still required). I'm not seeing any interfaces to allow clients to communicate properly with pipewire. I'm not seeing pipewire-pulse support or testing. Frankly, I'm not seeing any testing of reasonable quality. I'm concerned that this did not show up in testing either. I'm not saying it would require for certain at all, but my understanding of PipeWire leads me to ask, and the other omissions here make me doubt that it's been carefully checked. If Qualcomm does not wish to support and actually test an implementation of user pipewire, that is fine. I would however wish that we would be clear about that from the get go and then see if Chris is happy to accept a patch plainly for the system service rather than doing incomplete, insufficiently tested policy for user services. We have our own needs for a user service and I'd rather it be left for someone else to implement if you aren't able to test it properly. |
|
I'm willing to accept either an incomplete user implementation or a system-only implementation since I believe there is a substantial overlap in system vs user. However, an incomplete user implementation would delay merging until after the next refpolicy release (which is very soon). |
84c7d10 to
a4d3c36
Compare
|
validated in User-service mode on a Fedora vm (aarch64 kernel).
I might have missed some points due to unaware or in progress. |
WavyEbuilder
left a comment
There was a problem hiding this comment.
I've left some review comments, but I'm still extremely concerned about the quality of this PR and the testing going into it.
The client and daemon seem to have been conflated, and interfaces seem to be entirely ignored. Private labels are lacking throughout, and unorthodox accesses are placed without any explanation.
Adding to my concerns, it seems that the conditional for pipewire_system_service is wrong?
Various gen_require calls seem to exist within the policy module itself, including where interfaces exist, even when the appropriate places for said interfaces are mentioned in comments above.
After various review cycles, it is now unclear what accesses are actually needed, which is something that's almost certainly going to become much, much more confusing once the client and daemon are split into separate domains.
| # Allow pw-play to read files from /tmp | ||
| files_search_tmp(pipewire_t) | ||
| files_read_all_tmp_files(pipewire_t) |
There was a problem hiding this comment.
This does not look right at all... could you provide an AVC for this?
I also don't think it makes sense to have pw-cat running in pipewire_t.
There was a problem hiding this comment.
Yes. This was added incorrectly for pw-play/pw-cat which is running in pipewire_t.
Made seperate domain pipewire_client_t which labelled as pipewire_client_exec_t in .fc. pw-cat runs in it.
| /run/user/%{USERID}/pipewire(/.*)? gen_context(system_u:object_r:pipewire_runtime_t,s0) | ||
|
|
||
| /usr/bin/pipewire -- gen_context(system_u:object_r:pipewire_exec_t,s0) | ||
| /usr/bin/pw-cat -- gen_context(system_u:object_r:pipewire_exec_t,s0) |
There was a problem hiding this comment.
This should be a separate domain to the daemon, it's a utility?
The manual page indicates it's a client for pipewire:
pw-cat is a simple tool for playing back or capturing raw or encoded media files on a PipeWire server.
There was a problem hiding this comment.
Fixed. pw-cat is now labelled pipewire_client_exec_t
| # Name-service and ALSA config reads observed in enforcing logs. | ||
| optional_policy(` | ||
| gen_require(` | ||
| type passwd_file_t; | ||
| ') | ||
| allow pipewire_t passwd_file_t:file { getattr open read }; | ||
| ') |
There was a problem hiding this comment.
... what?
If it's the name service, which you seem to have indicated in your comment, then I'm not following as to why you're manually adding passwd_file_t instead of using the various interfaces in authlogin, such as auth_use_nsswitch, for this?
There was a problem hiding this comment.
yes, it was added from an AVC I saw during enforcing validation. Replaced with auth_use_nsswitch interface for NSS/name-service lookups.
| allow pipewire_t system_dbusd_t:unix_stream_socket connectto; | ||
| ') | ||
|
|
||
| # Name-service and ALSA config reads observed in enforcing logs. |
There was a problem hiding this comment.
Comments like this aren't really useful at all. What's more useful is explaining why pipewire needs for example the name service access. The ALSA config is somewhat self explanatory, so that can be left out imo.
There was a problem hiding this comment.
comment updated to explain the reason. For Alsa config, removed comment as you suggested.
| gen_require(` | ||
| type alsa_etc_rw_t; | ||
| ') | ||
| allow pipewire_t alsa_etc_rw_t:file { getattr open read map }; |
There was a problem hiding this comment.
Why not use the interface for this? alsa_read_config?
There was a problem hiding this comment.
Done. Replaced with interface. gen_require block is not optimal here to use.
| optional_policy(` | ||
| gen_require(` | ||
| type systemd_user_t; | ||
| ') | ||
| domtrans_pattern(systemd_user_t, pipewire_exec_t, pipewire_t) | ||
| allow systemd_user_t pipewire_t:unix_stream_socket { create setopt bind listen connectto getopt }; | ||
| allow systemd_user_t pipewire_t:process { signal sigkill signull }; | ||
| allow systemd_user_t pipewire_t:process2 nnp_transition; | ||
| allow systemd_user_t pipewire_tmpfs_t:file { read write map getattr open }; | ||
| ') |
There was a problem hiding this comment.
This is also not correct. As stated above, please look at other examples in the repo of systemd user services.
| gen_require(` | ||
| type user_tmp_t; | ||
| ') | ||
| manage_files_pattern(pipewire_t, user_tmp_t, user_tmp_t) |
There was a problem hiding this comment.
What is this for? This is a very broad access.
There was a problem hiding this comment.
This was added becuase userdom_user_runtime_filetrans is not available in fedora vm (validation done on its SElinux policy which was not full aligned with upstream refpolicy). But now changed to use proper runtime directory transition.
| ifdef(`userdom_user_home_dir_filetrans',` | ||
| userdom_user_home_dir_filetrans(pipewire_t, pipewire_home_t, dir) | ||
| ',` | ||
| # Older trees fallback: keep compile compatibility; rely on FC/restorecon for home paths. |
There was a problem hiding this comment.
I'm not following? Could you make this comment more clear?
There was a problem hiding this comment.
Apologies for the confusing comment. That entire block has been removed in the updated code. We now use userdom_user_home_dir_filetrans(pipewire_t, pipewire_home_t, dir, ".local") directly without any fallback ifdef. the interface is available in upstream refpolicy and no compatibility workaround is needed.
| # Session/system D-Bus socket access for PipeWire helpers. | ||
| optional_policy(` | ||
| gen_require(` | ||
| type session_dbusd_tmp_t; | ||
| type staff_dbusd_t; | ||
| ') | ||
| allow pipewire_t session_dbusd_tmp_t:sock_file write; | ||
| allow pipewire_t staff_dbusd_t:unix_stream_socket connectto; | ||
| ') | ||
|
|
||
| optional_policy(` | ||
| gen_require(` | ||
| type system_dbusd_var_run_t; | ||
| type system_dbusd_t; | ||
| ') | ||
| allow pipewire_t system_dbusd_var_run_t:sock_file write; | ||
| allow pipewire_t system_dbusd_t:unix_stream_socket connectto; |
There was a problem hiding this comment.
Please use the interfaces.
| init_rw_script_stream_sockets(pipewire_t) | ||
| dev_rw_dma_dev(pipewire_t) | ||
|
|
||
| # Allow pw-record to create/write output files in /tmp (e.g. pw-record /tmp/test.wav). |
There was a problem hiding this comment.
Please do not conflate the client and the daemon. They are separate programs.
a4d3c36 to
ce2530d
Compare
pebenito
left a comment
There was a problem hiding this comment.
Thanks for all your effort on this.
Only some minor style fixes.
| ## </summary> | ||
| ## </param> | ||
| # | ||
| interface(`pipewire_client_domtrans',` |
There was a problem hiding this comment.
Please rename to pipewire_domtrans_client.
There was a problem hiding this comment.
Renamed to pipewire_domtrans_client
| type pipewire_t; | ||
| ') | ||
|
|
||
| allow $1 pipewire_t:unix_stream_socket { getattr getopt read setopt write }; |
There was a problem hiding this comment.
Please use rw_socket_perms for the perimssions.
| ## </summary> | ||
| ## </param> | ||
| # | ||
| interface(`pipewire_client_use_fds',` |
There was a problem hiding this comment.
Renamed from pipewire_client_use_fds to pipewire_use_client_fds
| rw_files_pattern($1, pipewire_tmpfs_t, pipewire_tmpfs_t) | ||
| allow $1 pipewire_tmpfs_t:file map; |
There was a problem hiding this comment.
These two lines can be merged with mmap_rw_files_pattern.
There was a problem hiding this comment.
Replaced those 2 lines with mmap_rw_files_pattern.
| @@ -0,0 +1,215 @@ | |||
| policy_module(pipewire, 2.0.0) | |||
There was a problem hiding this comment.
The version parameter here is deprecated.
ce2530d to
8d0adb1
Compare
| type pipewire_tmpfs_t; | ||
| userdom_user_tmpfs_file(pipewire_tmpfs_t) | ||
|
|
||
| type pipewire_var_lib_t; |
There was a problem hiding this comment.
I realized that there are still separate types here. pipewire_var_lib_t is not aliased to pipewire_home_t.
| manage_files_pattern(pipewire_t, pipewire_tmpfs_t, pipewire_tmpfs_t) | ||
| allow pipewire_t pipewire_tmpfs_t:file map; |
| # pipewire_t — user-service-only policy | ||
| # | ||
|
|
||
| ifdef(`pipewire_system_service',`',` |
There was a problem hiding this comment.
There is a ifndef macro in refpolicy, so you don't need to do the empty true block trick.
| ## </summary> | ||
| ## </param> | ||
| # | ||
| interface(`pipewire_rw_tmpfs_files',` |
There was a problem hiding this comment.
I missed this on my last review, but this should be named pipewire_mmap_rw_tmpfs_files.
Add a new SELinux policy module for the PipeWire multimedia daemon. PipeWire is a low-latency audio/video server that replaces PulseAudio and JACK on modern Linux systems. The policy supports two mutually exclusive modes selected at build time via ifdef(`pipewire_system_service'): User-service mode (default): - userdom_user_application_domain for pipewire_t - Role access via pipewire_role template in .if, called from unprivuser.te and staff.te following the pulseaudio_role pattern - Runtime socket directory under $XDG_RUNTIME_DIR/pipewire via userdom_user_runtime_filetrans - Home state under ~/.local/share/pipewire (pipewire_home_t) - systemd --user integration via systemd_user_daemon_domain and systemd_user_app_status/systemd_user_app_socket_create - Session D-Bus via dbus_all_session_bus_client and dbus_connect_all_session_bus - Validated on Fedora VM (aarch64) in enforcing mode System-service mode (ifdef pipewire_system_service): - init_daemon_domain for pipewire_t - dac_override for /dev/snd/* access when running as system user - Persistent state under /var/lib/pipewire (pipewire_var_lib_t) - Runtime socket under /run/pipewire via files_runtime_filetrans - DMA buffer access via dev_rw_dma_dev - System D-Bus registration via dbus_system_domain Common to both modes: - pipewire_client_t: separate domain for pw-cat and client utilities (pw-play, pw-record etc. are symlinks to pw-cat and inherit its label) - ALSA sound device access via dev_read_sound/dev_write_sound - Shared memory (memfd) via pipewire_tmpfs_t for zero-copy audio buffers - sysfs read for hardware discovery, procfs read for scheduling info - NSS lookups via auth_use_nsswitch - ALSA config via alsa_read_config (optional) - RTKit scheduling via rtkit_scheduled (optional) - PulseAudio compatibility via pulseaudio_stream_connect (optional) - Suppress harmless /proc scan denials via domain_dontaudit_read_all_domains_state Interfaces added in pipewire.if: - pipewire_role: 4-arg template matching pulseaudio_role pattern - pipewire_stream_connect: connect to daemon socket - pipewire_rw_stream_sockets: post-connect socket I/O - pipewire_rw_tmpfs_files: shared memory buffer access - pipewire_use_fds / pipewire_use_client_fds: fd inheritance - pipewire_domtrans / pipewire_domtrans_client: domain transitions - pipewire_read_home_files: read pipewire home content Signed-off-by: Chiluka Rohith <rchiluka@qti.qualcomm.com>
8d0adb1 to
74cdfe5
Compare
pebenito
left a comment
There was a problem hiding this comment.
Thanks for all your effort on this.
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>
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>
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>
The upstream PipeWire SELinux policy has been merged into refpolicy (SELinuxProject/refpolicy#1109). Enable it for Qualcomm targets with system-service mode and add a Qualcomm-specific downstream patch for ADB shell support. - Set POLICY_CUSTOM_BUILDOPT to pipewire_system_service so PipeWire runs as a system-wide daemon on Qualcomm embedded targets - Add init_rw_script_stream_sockets(pipewire_t) to allow ADB shell (initrc_t) to interact with PipeWire on Qualcomm targets where ADB is the primary debug interface - Add domtrans_pattern(initrc_t, pipewire_client_exec_t, pipewire_client_t) so pw-play, pw-record and other client utilities transition into the correct pipewire_client_t domain when launched from ADB shell instead of remaining in initrc_t init_rw_script_stream_sockets was explicitly requested to remain downstream by upstream maintainer Chris PeBenito. Note: the ADB shell patch applies to policy/modules/apps/pipewire.te which is present once meta-selinux updates its SRCREV to include the upstream pipewire merge (SELinuxProject/refpolicy#1109, merged 2026-06-26). Validated on rb3gen2-core-kit in SELinux enforcing mode: - pipewire and pipewire-pulse correctly transition to pipewire_t - Playback and record pass with no PipeWire AVC denials Upstream-Status: Inappropriate [Qualcomm-specific ADB shell use case] Signed-off-by: Chiluka Rohith <rchiluka@qti.qualcomm.com>
The upstream PipeWire SELinux policy has been merged into refpolicy (SELinuxProject/refpolicy#1109, merged 2026-06-26). Set POLICY_CUSTOM_BUILDOPT to pipewire_system_service so that PipeWire runs as a system-wide daemon on Qualcomm embedded targets. This activates the system-service branch of the upstream pipewire module: init_daemon_domain, dac_override for /dev/snd/* access, DMA buffer access, /var/lib/pipewire state management, and system D-Bus registration. Validated on rb3gen2-core-kit in SELinux enforcing mode: - pipewire and pipewire-pulse correctly transition to pipewire_t - Playback and record pass with no PipeWire AVC denials Signed-off-by: Chiluka Rohith <rchiluka@qti.qualcomm.com>
On Qualcomm embedded targets ADB shell is the primary debug interface and runs as initrc_t due to the absence of a dedicated ADB domain in the current policy. - Add init_rw_script_stream_sockets(pipewire_t) so the PipeWire daemon can use stream sockets inherited from the ADB shell process - Add domtrans_pattern(initrc_t, pipewire_client_exec_t, pipewire_client_t) so pw-play and pw-record transition into the correct pipewire_client_t domain when launched from ADB shell init_rw_script_stream_sockets was explicitly requested to remain as a downstream Qualcomm patch by upstream maintainer Chris PeBenito, with the note that it can be dropped once a proper ADB domain exists in upstream refpolicy. Note: this patch applies to policy/modules/apps/pipewire.te which is present once meta-selinux updates its SRCREV to include the upstream pipewire merge (SELinuxProject/refpolicy#1109, merged 2026-06-26). Upstream-Status: Inappropriate [Qualcomm-specific; temporary workaround until a proper ADB domain exists in upstream refpolicy] Signed-off-by: Chiluka Rohith <rchiluka@qti.qualcomm.com>
The upstream PipeWire SELinux policy has been merged into refpolicy (SELinuxProject/refpolicy#1109, merged 2026-06-26). Set POLICY_CUSTOM_BUILDOPT to pipewire_system_service so that PipeWire runs as a system-wide daemon on Qualcomm embedded targets. This activates the system-service branch of the upstream pipewire module: init_daemon_domain, dac_override for /dev/snd/* access, DMA buffer access, /var/lib/pipewire state management, and system D-Bus registration. Signed-off-by: Chiluka Rohith <rchiluka@qti.qualcomm.com>
The upstream PipeWire SELinux policy has been merged into refpolicy (SELinuxProject/refpolicy#1109). Set POLICY_CUSTOM_BUILDOPT to pipewire_system_service so that PipeWire runs as a system-wide daemon on Qualcomm embedded targets. Signed-off-by: Chiluka Rohith <rchiluka@qti.qualcomm.com>
The upstream PipeWire SELinux policy has been merged into refpolicy (SELinuxProject/refpolicy#1109). Set POLICY_CUSTOM_BUILDOPT to pipewire_system_service so that PipeWire runs as a system-wide daemon on Qualcomm embedded targets. Signed-off-by: Chiluka Rohith <rchiluka@qti.qualcomm.com>
The upstream PipeWire SELinux policy has been merged into refpolicy (SELinuxProject/refpolicy#1109). Set POLICY_CUSTOM_BUILDOPT to pipewire_system_service so that PipeWire runs as a system-wide daemon on Qualcomm embedded targets. Signed-off-by: Chiluka Rohith <rchiluka@qti.qualcomm.com>
Add a new SELinux policy module for the PipeWire multimedia daemon. PipeWire is a low-latency audio and video server that replaces PulseAudio and JACK on modern Linux systems.
The policy confines the pipewire_t domain with:
pipewire-pulse is a symlink to the pipewire binary and transitions into the same pipewire_t domain, so no separate domain is needed.