Skip to content

pipewire: add policy for PipeWire multimedia daemon#1109

Merged
pebenito merged 1 commit into
SELinuxProject:mainfrom
rchiluka29:pipewire_module
Jun 26, 2026
Merged

pipewire: add policy for PipeWire multimedia daemon#1109
pebenito merged 1 commit into
SELinuxProject:mainfrom
rchiluka29:pipewire_module

Conversation

@rchiluka29

Copy link
Copy Markdown
Contributor

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:

  • Process control: fork, signal handling and scheduling (sys_nice) for low-latency audio operation
  • Runtime socket and directory management under /run/pipewire
  • ALSA sound device access via dev_read_sound/dev_write_sound
  • Shared memory (tmpfs/memfd) for zero-copy audio buffer handling
  • sysfs and procfs read access for hardware discovery
  • System logging via syslog and systemd journal
  • PulseAudio runtime compatibility via optional_policy
  • Suppressed audit noise for expected /proc scan denials

pipewire-pulse is a symlink to the pipewire binary and transitions into the same pipewire_t domain, so no separate domain is needed.

@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 see the StyleGuide, as there are numerous style issues. The lint check below also identified some issues.

Comment thread policy/modules/services/pipewire.te Outdated
Comment thread policy/modules/services/pipewire.te Outdated
Comment thread policy/modules/services/pipewire.te Outdated
Comment thread policy/modules/services/pipewire.te Outdated
Comment thread policy/modules/services/pipewire.te Outdated
Comment thread policy/modules/services/pipewire.fc Outdated
/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)

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.

Where is this coming from...? Surely this should be relative to XDG_RUNTIME_DIR no?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This policy was initially developed for a Qualcomm embedded platform where PipeWire runs as a system service (init_daemon_domain).
Modified now accordingly.

Comment thread policy/modules/services/pipewire.fc Outdated
Comment thread policy/modules/services/pipewire.te Outdated
@WavyEbuilder

Copy link
Copy Markdown
Contributor

Other things which seem to be missing:

  • dbus
  • rtkit
  • pipewire pulse

Comment thread policy/modules/services/pipewire.te Outdated
@rchiluka29 rchiluka29 force-pushed the pipewire_module branch 4 times, most recently from a8f64d8 to c4a758b Compare May 5, 2026 09:38
Comment thread policy/modules/apps/pipewire.te Outdated
Comment thread policy/modules/apps/pipewire.te Outdated
Comment on lines +36 to +37
manage_files_pattern(pipewire_t, pipewire_tmpfs_t, pipewire_tmpfs_t)
allow pipewire_t pipewire_tmpfs_t:file map;

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 lines can be merged by using the mmap_manage_files_pattern macro.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done. Replaced manage_files_pattern + file map for tmpfs with mmap_manage_files_pattern.

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 change also wasn't made.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Apologies, this was missed in the previous update. Now fixed.

Comment thread policy/modules/apps/pipewire.te
Comment thread policy/modules/apps/pipewire.te Outdated
Comment thread policy/modules/apps/pipewire.te Outdated
Comment thread policy/modules/apps/pipewire.te
Comment thread policy/modules/apps/pipewire.te Outdated
type pipewire_tmpfs_t;
userdom_user_tmpfs_file(pipewire_tmpfs_t)

type pipewire_var_lib_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.

Probably makes sense to rename this to pipewire_home_t (?) and alias pipewire_var_lib_t so it makes sense in system mode.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated. Renamed to pipewire_home_t and added alias pipewire_var_lib_t. updated the file context label
accordingly

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.

I realized that there are still separate types here. pipewire_var_lib_t is not aliased to pipewire_home_t.

@rchiluka29 rchiluka29 force-pushed the pipewire_module branch 2 times, most recently from 0f73a8a to d5b2a82 Compare May 11, 2026 07:37

@thesamesam thesamesam 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.

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?

Comment thread policy/modules/apps/pipewire.fc Outdated
## </summary>
## </param>
#
interface(`pipewire_stream_connect',`

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.

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

@rchiluka29 rchiluka29 May 27, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yes, pw-cli and friends need pipewire_stream_connect called for their respective domains

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.

Pending still AFAICT, to be clear for Chris.

Comment thread policy/modules/apps/pipewire.fc
@rchiluka29

Copy link
Copy Markdown
Contributor Author

Thanks for all the review feedback. I'll be pushing an updated version shortly that addresses all open comments.

@rchiluka29

Copy link
Copy Markdown
Contributor Author

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."

@pebenito

Copy link
Copy Markdown
Member

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.

Yes, this is still acceptable.

tkanfade added a commit to tkanfade/wireplumber-selinux-policy that referenced this pull request May 25, 2026
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>
@rchiluka29 rchiluka29 requested a review from pebenito May 25, 2026 07:45
tkanfade added a commit to tkanfade/wireplumber-selinux-policy that referenced this pull request May 25, 2026
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>
tkanfade added a commit to tkanfade/wireplumber-selinux-policy that referenced this pull request May 25, 2026
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>
@rchiluka29 rchiluka29 requested a review from WavyEbuilder May 27, 2026 06:55
Comment thread policy/modules/apps/pipewire.te Outdated
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)

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.

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.

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.

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.

@thesamesam thesamesam Jun 1, 2026

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.

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.

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.

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?

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.

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.

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.

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.

I suggest #1137 should probably be reverted then.

tkanfade added a commit to tkanfade/wireplumber-selinux-policy that referenced this pull request May 27, 2026
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 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.

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.

@rchiluka29

Copy link
Copy Markdown
Contributor Author

I think we might want $1_pipewire_t for the user services as it's a per user instance. As such, we also probably want $1_pipewire_tmpfs_t, $1_pipewire_runtime_t, etc.

This also seems to be missing role access calls for user_r/staff_r/sysadm_r.

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.

tkanfade added a commit to tkanfade/wireplumber-selinux-policy that referenced this pull request Jun 3, 2026
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>
@rchiluka29

Copy link
Copy Markdown
Contributor Author

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.

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

@WavyEbuilder

Copy link
Copy Markdown
Contributor

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.

Tested on Qualcomm embedded in system-service mode.

Ok, so I'm assuming that's what has been tested.

For user-service mode: userdom_user_application_domain sets up the exec entrypoint.
pipewire_role (now added) wires up the role side for completeness.

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:

  1. Writing user services pipewire by proxy, or
  2. Based on guesses.

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.

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

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.

@pebenito

pebenito commented Jun 9, 2026

Copy link
Copy Markdown
Member

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).

@rchiluka29

rchiluka29 commented Jun 9, 2026

Copy link
Copy Markdown
Contributor Author

validated in User-service mode on a Fedora vm (aarch64 kernel).

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.

Tested on Qualcomm embedded in system-service mode.

Ok, so I'm assuming that's what has been tested.

For user-service mode: userdom_user_application_domain sets up the exec entrypoint.
pipewire_role (now added) wires up the role side for completeness.

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:

  1. Writing user services pipewire by proxy, or
  2. Based on guesses.

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.

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

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 might have missed some points due to unaware or in progress.
Anyways, validated User-service mode on Fedora VM (aarch64 kernel) and system-service on qualcomm targets respectively. updated the PR.

@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.

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.

Comment thread policy/modules/apps/pipewire.te Outdated
Comment on lines +63 to +65
# Allow pw-play to read files from /tmp
files_search_tmp(pipewire_t)
files_read_all_tmp_files(pipewire_t)

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 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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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.

Comment thread policy/modules/apps/pipewire.fc Outdated
/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)

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 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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed. pw-cat is now labelled pipewire_client_exec_t

Comment thread policy/modules/apps/pipewire.te Outdated
Comment on lines +140 to +146
# 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 };
')

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.

... 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?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yes, it was added from an AVC I saw during enforcing validation. Replaced with auth_use_nsswitch interface for NSS/name-service lookups.

Comment thread policy/modules/apps/pipewire.te Outdated
allow pipewire_t system_dbusd_t:unix_stream_socket connectto;
')

# Name-service and ALSA config reads observed in enforcing logs.

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.

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.

@rchiluka29 rchiluka29 Jun 25, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

comment updated to explain the reason. For Alsa config, removed comment as you suggested.

Comment thread policy/modules/apps/pipewire.te Outdated
gen_require(`
type alsa_etc_rw_t;
')
allow pipewire_t alsa_etc_rw_t:file { getattr open read map };

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.

Why not use the interface for this? alsa_read_config?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done. Replaced with interface. gen_require block is not optimal here to use.

Comment thread policy/modules/apps/pipewire.te Outdated
Comment on lines +219 to +228
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 };
')

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 is also not correct. As stated above, please look at other examples in the repo of systemd user services.

Comment thread policy/modules/apps/pipewire.te Outdated
gen_require(`
type user_tmp_t;
')
manage_files_pattern(pipewire_t, user_tmp_t, user_tmp_t)

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.

What is this for? This is a very broad access.

@rchiluka29 rchiluka29 Jun 25, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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.

Comment thread policy/modules/apps/pipewire.te Outdated
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.

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.

I'm not following? Could you make this comment more clear?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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.

Comment thread policy/modules/apps/pipewire.te Outdated
Comment on lines +121 to +137
# 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;

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.

Please use the interfaces.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

Comment thread policy/modules/apps/pipewire.te Outdated
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).

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.

Please do not conflate the client and the daemon. They are separate programs.

@rchiluka29 rchiluka29 Jun 25, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ok, changed

@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.

Thanks for all your effort on this.

Only some minor style fixes.

Comment thread policy/modules/apps/pipewire.if Outdated
## </summary>
## </param>
#
interface(`pipewire_client_domtrans',`

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 rename to pipewire_domtrans_client.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Renamed to pipewire_domtrans_client

Comment thread policy/modules/apps/pipewire.if Outdated
type pipewire_t;
')

allow $1 pipewire_t:unix_stream_socket { getattr getopt read setopt write };

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 use rw_socket_perms for the perimssions.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done.

Comment thread policy/modules/apps/pipewire.if Outdated
## </summary>
## </param>
#
interface(`pipewire_client_use_fds',`

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.

pipewire_use_client_fds

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Renamed from pipewire_client_use_fds to pipewire_use_client_fds

Comment thread policy/modules/apps/pipewire.if Outdated
Comment on lines +204 to +205
rw_files_pattern($1, pipewire_tmpfs_t, pipewire_tmpfs_t)
allow $1 pipewire_tmpfs_t:file map;

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 two lines can be merged with mmap_rw_files_pattern.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Replaced those 2 lines with mmap_rw_files_pattern.

Comment thread policy/modules/apps/pipewire.te Outdated
@@ -0,0 +1,215 @@
policy_module(pipewire, 2.0.0)

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.

The version parameter here is deprecated.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removed.

Comment thread policy/modules/apps/pipewire.te
Comment thread policy/modules/apps/pipewire.te Outdated
Comment thread policy/modules/apps/pipewire.te
Comment thread policy/modules/apps/pipewire.te Outdated
Comment thread policy/modules/apps/pipewire.te Outdated
Comment thread policy/modules/apps/pipewire.te Outdated
type pipewire_tmpfs_t;
userdom_user_tmpfs_file(pipewire_tmpfs_t)

type pipewire_var_lib_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.

I realized that there are still separate types here. pipewire_var_lib_t is not aliased to pipewire_home_t.

Comment thread policy/modules/apps/pipewire.te Outdated
Comment on lines +36 to +37
manage_files_pattern(pipewire_t, pipewire_tmpfs_t, pipewire_tmpfs_t)
allow pipewire_t pipewire_tmpfs_t:file map;

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 change also wasn't made.

Comment thread policy/modules/apps/pipewire.te Outdated
# pipewire_t — user-service-only policy
#

ifdef(`pipewire_system_service',`',`

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.

There is a ifndef macro in refpolicy, so you don't need to do the empty true block trick.

Comment thread policy/modules/apps/pipewire.if Outdated
## </summary>
## </param>
#
interface(`pipewire_rw_tmpfs_files',`

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.

I missed this on my last review, but this should be named pipewire_mmap_rw_tmpfs_files.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

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>

@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.

Thanks for all your effort on this.

@pebenito pebenito merged commit 5f5048f into SELinuxProject:main Jun 26, 2026
119 checks passed
tkanfade added a commit to tkanfade/wireplumber-selinux-policy that referenced this pull request Jun 30, 2026
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 added a commit to tkanfade/wireplumber-selinux-policy that referenced this pull request Jul 1, 2026
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 added a commit to tkanfade/wireplumber-selinux-policy that referenced this pull request Jul 1, 2026
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>
rchiluka29 added a commit to rchiluka29/meta-qcom that referenced this pull request Jul 1, 2026
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>
rchiluka29 added a commit to rchiluka29/meta-qcom that referenced this pull request Jul 1, 2026
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>
rchiluka29 added a commit to rchiluka29/meta-qcom that referenced this pull request Jul 1, 2026
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>
rchiluka29 added a commit to rchiluka29/meta-qcom that referenced this pull request Jul 1, 2026
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>
rchiluka29 added a commit to rchiluka29/meta-qcom that referenced this pull request Jul 1, 2026
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>
rchiluka29 added a commit to rchiluka29/meta-qcom that referenced this pull request Jul 1, 2026
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>
rchiluka29 added a commit to rchiluka29/meta-qcom-distro that referenced this pull request Jul 2, 2026
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>
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.

5 participants