diff --git a/policy/modules/apps/pipewire.fc b/policy/modules/apps/pipewire.fc index 10276c7d93..cc4672c13d 100644 --- a/policy/modules/apps/pipewire.fc +++ b/policy/modules/apps/pipewire.fc @@ -1,5 +1,6 @@ # PipeWire daemon executable. /usr/bin/pipewire -- gen_context(system_u:object_r:pipewire_exec_t,s0) +/usr/bin/wpctl -- gen_context(system_u:object_r:pipewire_exec_t,s0) # pw-cat is a standalone client utility (plays/captures audio via a running # PipeWire daemon); it runs in pipewire_client_t, not pipewire_t. @@ -11,7 +12,9 @@ /run/pipewire(/.*)? gen_context(system_u:object_r:pipewire_runtime_t,s0) # User-session runtime sockets live under $XDG_RUNTIME_DIR/pipewire and are -# labelled at runtime via userdom_user_runtime_filetrans; no static entry needed. +# labelled at runtime via userdom_user_runtime_filetrans +# Static entry added for restorecon +/run/user/%{USERID}/pipewire-.* gen_context(system_u:object_r:pipewire_runtime_t,s0) # Persistent system-service state. /var/lib/pipewire(/.*)? gen_context(system_u:object_r:pipewire_var_lib_t,s0) diff --git a/policy/modules/apps/pipewire.if b/policy/modules/apps/pipewire.if index f24a7466f0..7ccc2aa484 100644 --- a/policy/modules/apps/pipewire.if +++ b/policy/modules/apps/pipewire.if @@ -61,6 +61,8 @@ template(`pipewire_role',` allow $2 pipewire_runtime_t:dir { manage_dir_perms relabel_dir_perms }; allow $2 pipewire_runtime_t:sock_file { manage_sock_file_perms relabel_sock_file_perms }; + pipewire_client_domain($2) + # Allow the user domain to manage shared memory files created by the daemon. pipewire_mmap_rw_tmpfs_files($2) allow $2 pipewire_tmpfs_t:file relabel_file_perms; @@ -165,6 +167,27 @@ interface(`pipewire_use_fds',` allow $1 pipewire_t:fd use; ') +######################################## +## +## Send and receive messages from +## pipewire over dbus. +## +## +## +## Domain allowed access. +## +## +# +interface(`pipewire_dbus_chat',` + gen_require(` + type pipewire_t; + class dbus send_msg; + ') + + allow $1 pipewire_t:dbus send_msg; + allow pipewire_t $1:dbus send_msg; +') + ######################################## ## ## Use file descriptors inherited from PipeWire clients. @@ -223,3 +246,23 @@ interface(`pipewire_read_home_files',` read_files_pattern($1, pipewire_home_t, pipewire_home_t) read_lnk_files_pattern($1, pipewire_home_t, pipewire_home_t) ') + +######################################## +## +## Connect to pipewire and manage +## pipewire config data. +## +## +## +## Domain allowed access. +## +## +# +interface(`pipewire_client_domain',` + gen_require(` + attribute pipewire_client; + ') + + typeattribute $1 pipewire_client; + dbus_all_session_bus_client($1) +') diff --git a/policy/modules/apps/pipewire.te b/policy/modules/apps/pipewire.te index a30e2da62c..064bbd77b2 100644 --- a/policy/modules/apps/pipewire.te +++ b/policy/modules/apps/pipewire.te @@ -16,6 +16,8 @@ policy_module(pipewire) attribute_role pipewire_roles; +attribute pipewire_client; + # # pipewire_t — the PipeWire multimedia daemon. # @@ -54,7 +56,7 @@ userdom_user_tmpfs_file(pipewire_tmpfs_t) # allow pipewire_t self:capability sys_nice; -allow pipewire_t self:process { getsched setsched signal sigchld }; +allow pipewire_t self:process { getsched setsched signal sigchld setrlimit }; allow pipewire_t self:fifo_file rw_fifo_file_perms; allow pipewire_t self:unix_stream_socket { create_stream_socket_perms connectto }; @@ -72,6 +74,10 @@ fs_tmpfs_filetrans(pipewire_t, pipewire_tmpfs_t, file) dev_read_sound(pipewire_t) dev_write_sound(pipewire_t) +# Video hardware access. +dev_read_video_dev(pipewire_t) +dev_write_video_dev(pipewire_t) + # Device enumeration via sysfs (discovering ALSA/USB audio devices at startup). dev_read_sysfs(pipewire_t) @@ -81,6 +87,7 @@ domain_dontaudit_read_all_domains_state(pipewire_t) # Read /proc state for scheduling and memory info. kernel_read_system_state(pipewire_t) +kernel_request_load_module(pipewire_t) files_read_etc_files(pipewire_t) files_read_usr_files(pipewire_t) @@ -90,17 +97,21 @@ logging_send_syslog_msg(pipewire_t) miscfiles_read_localization(pipewire_t) +userdom_use_user_terminals(pipewire_t) + # NSS/name-service lookups to resolve user names for session ownership checks. auth_use_nsswitch(pipewire_t) # ALSA configuration files (/etc/alsa/*, ~/.asoundrc). optional_policy(` alsa_read_config(pipewire_t) + alsa_read_home_files(pipewire_t) + alsa_read_lib(pipewire_t) ') # PulseAudio compatibility layer (pipewire-pulse connects to PulseAudio clients). optional_policy(` - pulseaudio_stream_connect(pipewire_t) + pulseaudio_provide_server(pipewire_t) ') # Real-time scheduling priority via rtkit-daemon. @@ -113,6 +124,10 @@ optional_policy(` systemd_read_journal_files(pipewire_t) ') +optional_policy(` + dbus_system_bus_client(pipewire_t) +') + ######################################## # # pipewire_t — system-service-only policy @@ -154,13 +169,14 @@ ifndef(`pipewire_system_service',` allow pipewire_t pipewire_home_t:file mmap_manage_file_perms; manage_lnk_files_pattern(pipewire_t, pipewire_home_t, pipewire_home_t) - # Runtime socket directory transition under $XDG_RUNTIME_DIR/pipewire. - userdom_user_runtime_filetrans(pipewire_t, pipewire_runtime_t, dir, "pipewire") + # Runtime transition under $XDG_RUNTIME_DIR + userdom_user_runtime_filetrans(pipewire_t, pipewire_runtime_t, { dir file sock_file }) # Session D-Bus (register org.PipeWire.* on the per-user session bus). optional_policy(` dbus_all_session_bus_client(pipewire_t) dbus_connect_all_session_bus(pipewire_t) + dbus_write_session_runtime_socket(pipewire_t) ') # Allow systemd --user to start the user-service instance. @@ -168,6 +184,27 @@ ifndef(`pipewire_system_service',` systemd_user_daemon_domain(user, pipewire_exec_t, pipewire_t) systemd_user_daemon_domain(staff, pipewire_exec_t, pipewire_t) ') + + optional_policy(` + xdg_search_config_dirs(pipewire_t) + ') +') + +######################################## +# +# pipewire_client domain +# +# domain that captures requirements to use the pipewire service +# + +pipewire_stream_connect(pipewire_client) +pipewire_rw_stream_sockets(pipewire_client) +pipewire_mmap_rw_tmpfs_files(pipewire_client) +pipewire_use_fds(pipewire_client) +allow pipewire_t pipewire_client:fd use; + +optional_policy(` + pipewire_dbus_chat(pipewire_client) ') ######################################## @@ -192,23 +229,15 @@ kernel_read_system_state(pipewire_client_t) miscfiles_read_localization(pipewire_client_t) # Connect to the PipeWire daemon socket and map its shared memory buffers. -pipewire_stream_connect(pipewire_client_t) -pipewire_rw_stream_sockets(pipewire_client_t) -pipewire_mmap_rw_tmpfs_files(pipewire_client_t) -pipewire_use_fds(pipewire_client_t) -pipewire_use_client_fds(pipewire_t) +pipewire_client_domain(pipewire_client_t) # Read media files from the user's home, and allow capture tools such as # pw-record to manage user-selected output files in /tmp. userdom_read_user_home_content_files(pipewire_client_t) userdom_manage_user_tmp_files(pipewire_client_t) userdom_tmp_filetrans_user_tmp(pipewire_client_t, file) +userdom_use_user_terminals(pipewire_client_t) optional_policy(` alsa_read_config(pipewire_client_t) ') - -optional_policy(` - dbus_all_session_bus_client(pipewire_client_t) - dbus_connect_all_session_bus(pipewire_client_t) -') diff --git a/policy/modules/apps/pulseaudio.if b/policy/modules/apps/pulseaudio.if index 06c262d98d..6372251c45 100644 --- a/policy/modules/apps/pulseaudio.if +++ b/policy/modules/apps/pulseaudio.if @@ -446,3 +446,30 @@ interface(`pulseaudio_rw_tmpfs_files',` fs_search_tmpfs($1) rw_files_pattern($1, pulseaudio_tmpfs_t, pulseaudio_tmpfs_t) ') + +####################################### +## +## Allow specified domain to act as a pulseaudio server. +## +## +## +## Domain allowed/allowing access. +## +## +# +interface(`pulseaudio_provide_server',` + gen_require(` + attribute pulseaudio_client; + type pulseaudio_tmp_t; + ') + + manage_dirs_pattern($1, pulseaudio_tmp_t, pulseaudio_tmp_t) + manage_files_pattern($1, pulseaudio_tmp_t, pulseaudio_tmp_t) + allow $1 pulseaudio_tmp_t:file map; + manage_sock_files_pattern($1, pulseaudio_tmp_t, pulseaudio_tmp_t) + userdom_user_runtime_filetrans($1, pulseaudio_tmp_t, dir, "pulse") + pulseaudio_stream_connect($1) + ps_process_pattern($1, pulseaudio_client) + + allow pulseaudio_client $1:fd use; +') diff --git a/policy/modules/apps/wireplumber.fc b/policy/modules/apps/wireplumber.fc new file mode 100644 index 0000000000..ff24bf0a4a --- /dev/null +++ b/policy/modules/apps/wireplumber.fc @@ -0,0 +1,10 @@ +HOME_DIR/\.config/wireplumber(/.*)? gen_context(system_u:object_r:wireplumber_home_t,s0) +HOME_DIR/\.local/share/wireplumber(/.*)? gen_context(system_u:object_r:wireplumber_home_t,s0) +HOME_DIR/\.local/state/wireplumber(/.*)? gen_context(system_u:object_r:wireplumber_home_t,s0) + +/run/wireplumber(/.*)? gen_context(system_u:object_r:wireplumber_runtime_t,s0) +/run/user/%{USERID}/wireplumber(/.*)? gen_context(system_u:object_r:wireplumber_runtime_t,s0) + +/usr/bin/wireplumber -- gen_context(system_u:object_r:wireplumber_exec_t,s0) + +/var/lib/wireplumber(/.*)? gen_context(system_u:object_r:wireplumber_var_lib_t,s0) diff --git a/policy/modules/apps/wireplumber.if b/policy/modules/apps/wireplumber.if new file mode 100644 index 0000000000..b5fc97aa5b --- /dev/null +++ b/policy/modules/apps/wireplumber.if @@ -0,0 +1,91 @@ +## Policy for WirePlumber, the PipeWire session manager. + +######################################## +## +## Connect to WirePlumber over a unix stream socket. +## +## +## +## Domain allowed access. +## +## +# +interface(`wireplumber_stream_connect',` + gen_require(` + type wireplumber_t, wireplumber_runtime_t; + ') + + files_search_runtime($1) + stream_connect_pattern($1, wireplumber_runtime_t, wireplumber_runtime_t, wireplumber_t) +') + +######################################## +## +## Send and receive messages from +## wireplumber over dbus. +## +## +## +## Domain allowed access. +## +## +# +interface(`wireplumber_dbus_chat',` + gen_require(` + type wireplumber_t; + class dbus send_msg; + ') + + allow $1 wireplumber_t:dbus send_msg; + allow wireplumber_t $1:dbus send_msg; +') + +######################################## +## +## Role access for WirePlumber in user-service mode. +## +## +## +## The prefix of the user role (e.g., "user" for user_r). +## +## +## +## +## User domain for the role (e.g., user_t). +## +## +## +## +## User exec domain for execute and transition access +## (e.g., user_application_exec_domain). +## +## +## +## +## Role allowed access (e.g., user_r). +## +## +# +interface(`wireplumber_role',` + gen_require(` + type wireplumber_t, wireplumber_exec_t; + type wireplumber_tmpfs_t, wireplumber_runtime_t, wireplumber_home_t; + attribute_role wireplumber_roles; + ') + + wireplumber_dbus_chat($2) + + roleattribute $4 wireplumber_roles; + ifndef(`wireplumber_system_service',` + manage_files_pattern($2, wireplumber_tmpfs_t, wireplumber_tmpfs_t) + manage_sock_files_pattern($2, wireplumber_tmpfs_t, wireplumber_tmpfs_t) + manage_dirs_pattern($2, wireplumber_tmpfs_t, wireplumber_tmpfs_t) + manage_files_pattern($2, wireplumber_runtime_t, wireplumber_runtime_t) + manage_sock_files_pattern($2, wireplumber_runtime_t, wireplumber_runtime_t) + manage_dirs_pattern($2, wireplumber_runtime_t, wireplumber_runtime_t) + manage_files_pattern($2, wireplumber_home_t, wireplumber_home_t) + manage_dirs_pattern($2, wireplumber_home_t, wireplumber_home_t) + systemd_user_daemon_domain($1, wireplumber_exec_t, wireplumber_t) + domtrans_pattern($3, wireplumber_exec_t, wireplumber_t) + ') +') diff --git a/policy/modules/apps/wireplumber.te b/policy/modules/apps/wireplumber.te new file mode 100644 index 0000000000..0be2016dcd --- /dev/null +++ b/policy/modules/apps/wireplumber.te @@ -0,0 +1,158 @@ +policy_module(wireplumber) + +######################################## +# +# Declarations +# + +attribute_role wireplumber_roles; + +type wireplumber_t; +type wireplumber_exec_t; +ifdef(`wireplumber_system_service',` + init_daemon_domain(wireplumber_t, wireplumber_exec_t) +',` + userdom_user_application_domain(wireplumber_t, wireplumber_exec_t) + role wireplumber_roles types wireplumber_t; +') + +type wireplumber_home_t alias wireplumber_var_lib_t; +userdom_user_home_content(wireplumber_home_t) + +type wireplumber_runtime_t; +files_runtime_file(wireplumber_runtime_t) + +type wireplumber_tmpfs_t; +userdom_user_tmpfs_file(wireplumber_tmpfs_t) + +######################################## +# +# Local policy +# + +allow wireplumber_t self:process { getsched setsched signal signull setrlimit }; +allow wireplumber_t self:capability sys_nice; +allow wireplumber_t self:fifo_file rw_fifo_file_perms; +allow wireplumber_t self:unix_stream_socket { create_stream_socket_perms connectto }; +allow wireplumber_t self:unix_dgram_socket create_socket_perms; + +manage_files_pattern(wireplumber_t, wireplumber_home_t, wireplumber_home_t) +manage_dirs_pattern(wireplumber_t, wireplumber_home_t, wireplumber_home_t) + +# Bluetooth socket (for BlueZ audio routing) +allow wireplumber_t self:bluetooth_socket { create bind setopt listen shutdown connect getopt read write }; + +# netlink kobject uevent socket (for udev device monitoring) +allow wireplumber_t self:netlink_kobject_uevent_socket { create bind setopt getattr getopt read }; + +dev_read_sysfs(wireplumber_t) + +# /dev/snd inotify watch for device monitoring +dev_watch_dev_dirs(wireplumber_t) + +# filesystem getattr +dev_getattr_fs(wireplumber_t) +dev_getattr_sysfs(wireplumber_t) +fs_getattr_xattr_fs(wireplumber_t) + +# v4l device getattr (video device enumeration) +dev_dontaudit_getattr_video_dev(wireplumber_t) + +files_read_usr_files(wireplumber_t) +files_map_usr_files(wireplumber_t) +files_read_etc_files(wireplumber_t) + +dev_read_sound(wireplumber_t) +dev_write_sound(wireplumber_t) + +dev_read_video_dev(wireplumber_t) +dev_write_video_dev(wireplumber_t) + +# /etc/machine-id +files_read_etc_runtime_files(wireplumber_t) + +kernel_read_system_state(wireplumber_t) + +domain_dontaudit_read_all_domains_state(wireplumber_t) + +logging_send_syslog_msg(wireplumber_t) + +miscfiles_read_localization(wireplumber_t) + +optional_policy(` + pipewire_client_domain(wireplumber_t) +') + +# Runtime directory management - differs between system and user service +ifdef(`wireplumber_system_service',` + files_var_lib_filetrans(wireplumber_t, wireplumber_home_t, { dir file }) + files_runtime_filetrans(wireplumber_t, wireplumber_runtime_t, { dir file sock_file }) +',` + userdom_user_runtime_filetrans(wireplumber_t, wireplumber_runtime_t, dir) + userdom_user_home_dir_filetrans(wireplumber_t, wireplumber_home_t, dir) + + optional_policy(` + xdg_search_data_dirs(wireplumber_t) + xdg_search_config_dirs(wireplumber_t) + xdg_data_filetrans(wireplumber_t, wireplumber_home_t, dir, "wireplumber") + ') +') + +# tmpfs shared memory (memfd for zero-copy audio buffers) +mmap_manage_files_pattern(wireplumber_t, wireplumber_tmpfs_t, wireplumber_tmpfs_t) +fs_tmpfs_filetrans(wireplumber_t, wireplumber_tmpfs_t, file) + +# udev runtime data (/run/udev) +udev_search_runtime(wireplumber_t) +udev_read_runtime_files(wireplumber_t) + +optional_policy(` + alsa_read_config(wireplumber_t) + alsa_read_lib(wireplumber_t) +') + +# systemd sessions (/run/systemd/sessions) + +optional_policy(` + systemd_read_logind_sessions_files(wireplumber_t) + systemd_watch_logind_sessions_dirs(wireplumber_t) +') + +optional_policy(` + dbus_system_bus_client(wireplumber_t) + dbus_connect_system_bus(wireplumber_t) + dbus_write_session_runtime_socket(wireplumber_t) + dbus_connect_all_session_bus(wireplumber_t) + + ifdef(`wireplumber_system_service',` + dbus_system_domain(wireplumber_t, wireplumber_exec_t) + ') +') + +# Allow ModemManager D-Bus replies to wireplumber_t +optional_policy(` + modemmanager_dbus_chat(wireplumber_t) +') + +# Allow BlueZ D-Bus signals to wireplumber_t +optional_policy(` + bluetooth_dbus_chat(wireplumber_t) + bluetooth_use(wireplumber_t) +') + +optional_policy(` + devicekit_dbus_chat_power(wireplumber_t) +') + +# Allow oFono D-Bus communication (telephony) +optional_policy(` + ofono_dbus_chat(wireplumber_t) +') + +optional_policy(` + rtkit_scheduled(wireplumber_t) +') + +optional_policy(` + systemd_read_journal_files(wireplumber_t) +') diff --git a/policy/modules/roles/staff.te b/policy/modules/roles/staff.te index dfd4bfca8a..3ac58b097c 100644 --- a/policy/modules/roles/staff.te +++ b/policy/modules/roles/staff.te @@ -218,6 +218,10 @@ ifndef(`distro_redhat',` vmware_role(staff, staff_t, staff_application_exec_domain, staff_r) ') + optional_policy(` + wireplumber_role(staff, staff_t, staff_application_exec_domain, staff_r) + ') + optional_policy(` wireshark_role(staff, staff_t, staff_application_exec_domain, staff_r) ') diff --git a/policy/modules/roles/unprivuser.te b/policy/modules/roles/unprivuser.te index 888950f7c7..76fa12566e 100644 --- a/policy/modules/roles/unprivuser.te +++ b/policy/modules/roles/unprivuser.te @@ -198,6 +198,10 @@ ifndef(`distro_redhat',` vmware_role(user, user_t, user_application_exec_domain, user_r) ') + optional_policy(` + wireplumber_role(user, user_t, user_application_exec_domain, user_r) + ') + optional_policy(` wireshark_role(user, user_t, user_application_exec_domain, user_r) ') diff --git a/policy/modules/services/ofono.if b/policy/modules/services/ofono.if index 51c9d4e195..3c91f815dc 100644 --- a/policy/modules/services/ofono.if +++ b/policy/modules/services/ofono.if @@ -1,5 +1,4 @@ ## ofono -# ## ## oFono is a stack for mobile telephony devices on Linux. ## oFono supports speaking to telephony devices through specific drivers, @@ -7,3 +6,29 @@ ## ## https://git.kernel.org/pub/scm/network/ofono/ofono.git ## + +######################################## +## +## Allow D-Bus communication with oFono. +## +## +## +## Allow the specified domain to send and receive D-Bus +## messages to/from oFono for telephony audio routing. +## +## +## +## +## Domain allowed access. +## +## +# +interface(`ofono_dbus_chat',` + gen_require(` + type ofono_t; + class dbus send_msg; + ') + + allow $1 ofono_t:dbus send_msg; + allow ofono_t $1:dbus send_msg; +')
+## Allow the specified domain to send and receive D-Bus +## messages to/from oFono for telephony audio routing. +##