commit:     cd1f76c3b2dbfee05ce585561e4c32e847ca4d46
Author:     Russell Coker <russell <AT> coker <DOT> com <DOT> au>
AuthorDate: Sat Jun 14 04:19:36 2025 +0000
Commit:     Jason Zaman <perfinion <AT> gentoo <DOT> org>
CommitDate: Tue Jul 15 07:52:23 2025 +0000
URL:        
https://gitweb.gentoo.org/proj/hardened-refpolicy.git/commit/?id=cd1f76c3

Policy for needrestart to run with minimum privs so it can't be exploited

Signed-off-by: Russell Coker <russell <AT> coker.com.au>
Signed-off-by: Jason Zaman <perfinion <AT> gentoo.org>

 policy/modules/admin/apt.te          |   4 ++
 policy/modules/roles/sysadm.te       |   4 ++
 policy/modules/services/xserver.if   |  18 ++++++
 policy/modules/system/needrestart.fc |   1 +
 policy/modules/system/needrestart.if |  52 +++++++++++++++
 policy/modules/system/needrestart.te | 119 +++++++++++++++++++++++++++++++++++
 policy/modules/system/systemd.if     |  18 ++++++
 policy/modules/system/unconfined.te  |   4 ++
 8 files changed, 220 insertions(+)

diff --git a/policy/modules/admin/apt.te b/policy/modules/admin/apt.te
index 4161da753..5327f3ed8 100644
--- a/policy/modules/admin/apt.te
+++ b/policy/modules/admin/apt.te
@@ -158,6 +158,10 @@ optional_policy(`
        networkmanager_dbus_chat(apt_t)
 ')
 
+optional_policy(`
+       needrestart_domtrans(apt_t)
+')
+
 optional_policy(`
        nis_use_ypbind(apt_t)
 ')

diff --git a/policy/modules/roles/sysadm.te b/policy/modules/roles/sysadm.te
index 96b13107a..fb3de81ec 100644
--- a/policy/modules/roles/sysadm.te
+++ b/policy/modules/roles/sysadm.te
@@ -698,6 +698,10 @@ optional_policy(`
        nagios_admin(sysadm_t, sysadm_r)
 ')
 
+optional_policy(`
+       needrestart_run(sysadm_t, sysadm_r)
+')
+
 optional_policy(`
        nessus_admin(sysadm_t, sysadm_r)
 ')

diff --git a/policy/modules/services/xserver.if 
b/policy/modules/services/xserver.if
index 6ecf3514a..c6485d064 100644
--- a/policy/modules/services/xserver.if
+++ b/policy/modules/services/xserver.if
@@ -271,6 +271,24 @@ interface(`xserver_ro_session',`
        allow $1 $2:file map;
 ')
 
+########################################
+## <summary>
+##      Send a null signal to xdm processes.
+## </summary>
+## <param name="domain">
+##      <summary>
+##      Domain allowed access.
+##      </summary>
+## </param>
+#
+interface(`xdm_signull',`
+        gen_require(`
+                type xdm_t;
+        ')
+
+        allow $1 xdm_t:process signull;
+')
+
 #######################################
 ## <summary>
 ##     Create sessions on the X server, with read and write

diff --git a/policy/modules/system/needrestart.fc 
b/policy/modules/system/needrestart.fc
new file mode 100644
index 000000000..eb9e16ed9
--- /dev/null
+++ b/policy/modules/system/needrestart.fc
@@ -0,0 +1 @@
+/usr/sbin/needrestart  --      
gen_context(system_u:object_r:needrestart_exec_t,s0)

diff --git a/policy/modules/system/needrestart.if 
b/policy/modules/system/needrestart.if
new file mode 100644
index 000000000..c601089a3
--- /dev/null
+++ b/policy/modules/system/needrestart.if
@@ -0,0 +1,52 @@
+## <summary>Policy for needrestart utility.</summary>
+##
+## <desc>
+## Utility to restart daemons after system updates
+## </desc>
+
+########################################
+## <summary>
+##      Execute needrestart in the user role
+## </summary>
+## <param name="domain">
+##      <summary>
+##      Domain allowed to transition.
+##      </summary>
+## </param>
+## <param name="role">
+##      <summary>
+##      Role allowed access.
+##      </summary>
+## </param>
+## <rolecap/>
+#
+interface(`needrestart_run',`
+       gen_require(`
+               attribute_role needrestart_roles;
+               type needrestart_exec_t, needrestart_t;
+       ')
+
+       domtrans_pattern($1, needrestart_exec_t, needrestart_t)
+       roleattribute $2 needrestart_roles;
+       systemd_run_passwd_agent(needrestart_t, $2)
+')
+
+########################################
+## <summary>
+##     Execute needrestart programs in the needrestart domain.
+## </summary>
+## <param name="domain">
+##     <summary>
+##     Domain allowed to transition.
+##     </summary>
+## </param>
+#
+interface(`needrestart_domtrans',`
+       gen_require(`
+               type needrestart_t, needrestart_exec_t;
+       ')
+
+       corecmd_search_bin($1)
+       domtrans_pattern($1, needrestart_exec_t, needrestart_t)
+')
+

diff --git a/policy/modules/system/needrestart.te 
b/policy/modules/system/needrestart.te
new file mode 100644
index 000000000..2e4d77455
--- /dev/null
+++ b/policy/modules/system/needrestart.te
@@ -0,0 +1,119 @@
+policy_module(needrestart)
+
+########################################
+#
+# Declarations
+#
+
+type needrestart_t;
+type needrestart_exec_t;
+init_system_domain(needrestart_t, needrestart_exec_t)
+attribute_role needrestart_roles;
+role needrestart_roles types needrestart_t;
+
+type needrestart_tmp_t;
+files_tmp_file(needrestart_tmp_t)
+
+########################################
+#
+# Local policy
+#
+
+dontaudit needrestart_t self:capability { net_admin };
+# sys_ptrace is for getting stats of processes
+# sys_resource is for sd-askpwagent
+allow needrestart_t self:capability { dac_read_search kill sys_ptrace 
sys_resource };
+allow needrestart_t self:capability2 checkpoint_restore;
+allow needrestart_t self:process { getcap signal setrlimit };
+allow needrestart_t self:fifo_file rw_fifo_file_perms;
+
+# for /proc/*/cwd etc
+allow needrestart_t self:cap_userns sys_ptrace;
+
+allow needrestart_t needrestart_tmp_t:dir manage_dir_perms;
+files_tmp_filetrans(needrestart_t, needrestart_tmp_t, { dir })
+
+kernel_getattr_core_if(needrestart_t)
+kernel_read_kernel_sysctls(needrestart_t)
+kernel_read_fs_sysctls(needrestart_t)
+kernel_read_state(needrestart_t)
+kernel_read_system_state(needrestart_t)
+kernel_read_vm_overcommit_sysctl(needrestart_t)
+
+kernel_getattr_proc(needrestart_t)
+
+dev_read_urand(needrestart_t)
+dev_read_rand(needrestart_t)
+dev_read_sysfs(needrestart_t)
+dev_dontaudit_getattr_all_blk_files(needrestart_t)
+dev_dontaudit_getattr_all_chr_files(needrestart_t)
+gpm_dontaudit_getattr_gpmctl(needrestart_t)
+
+corecmd_exec_all_executables(needrestart_t)
+domain_read_all_domains_state(needrestart_t)
+
+corecmd_exec_bin(needrestart_t)
+
+# for /var/cache/debconf/config.dat-new
+files_dontaudit_rw_var_files(needrestart_t)
+files_dontaudit_write_var_dirs(needrestart_t)
+
+# for /etc/needrestart files
+files_exec_etc_files(needrestart_t)
+
+files_list_boot(needrestart_t)
+files_read_kernel_img(needrestart_t)
+
+# for /var/cache/debconf/config.dat do we need a different label for that?
+files_read_var_files(needrestart_t)
+
+files_read_etc_files(needrestart_t)
+
+files_read_usr_symlinks(needrestart_t)
+files_read_usr_files(needrestart_t)
+
+files_search_var_lib(needrestart_t)
+
+fs_getattr_cgroup(needrestart_t)
+fs_getattr_nsfs_files(needrestart_t)
+
+init_admin(needrestart_t)
+init_list_var_lib_dirs(needrestart_t)
+init_manage_all_units(needrestart_t)
+init_read_state(needrestart_t)
+init_start_generic_units(needrestart_t)
+init_unix_stream_socket_connectto(needrestart_t)
+
+libs_exec_lib_files(needrestart_t)
+
+miscfiles_read_localization(needrestart_t)
+
+term_getattr_generic_ptys(needrestart_t)
+term_getattr_ptmx(needrestart_t)
+term_getattr_unallocated_ttys(needrestart_t)
+term_read_console(needrestart_t)
+
+userdom_use_user_ptys(needrestart_t)
+
+optional_policy(`
+       dpkg_read_db(needrestart_t)
+')
+
+optional_policy(`
+       ssh_use_sshd_pidfds(needrestart_t)
+       ssh_signull(needrestart_t)
+')
+
+optional_policy(`
+       systemd_exec_systemctl(needrestart_t)
+       systemd_read_logind_sessions_files(needrestart_t)
+       systemd_signal_all_user_sessions(needrestart_t)
+')
+
+optional_policy(`
+       unconfined_signal(needrestart_t)
+')
+
+optional_policy(`
+       xdm_signull(needrestart_t)
+')

diff --git a/policy/modules/system/systemd.if b/policy/modules/system/systemd.if
index 0f92c23bd..6ed99034c 100644
--- a/policy/modules/system/systemd.if
+++ b/policy/modules/system/systemd.if
@@ -2804,6 +2804,24 @@ interface(`systemd_write_all_user_keys',`
        allow $1 systemd_user_session_type:key write;
 ')
 
+########################################
+## <summary>
+##    signal all systemd --user domains.
+## </summary>
+## <param name="domain">
+##    <summary>
+##    Domain allowed access.
+##    </summary>
+## </param>
+#
+interface(`systemd_signal_all_user_sessions',`
+       gen_require(`
+               attribute systemd_user_session_type;
+       ')
+
+       allow $1 systemd_user_session_type:process signal;
+')
+
 ########################################
 ## <summary>
 ##  Execute systemd-sysusers in the

diff --git a/policy/modules/system/unconfined.te 
b/policy/modules/system/unconfined.te
index fb5494e5a..759c83776 100644
--- a/policy/modules/system/unconfined.te
+++ b/policy/modules/system/unconfined.te
@@ -158,6 +158,10 @@ optional_policy(`
        mta_role(unconfined, unconfined_t, unconfined_application_exec_domain, 
unconfined_r)
 ')
 
+optional_policy(`
+       needrestart_run(unconfined_t, unconfined_r)
+')
+
 optional_policy(`
        oddjob_run_mkhomedir(unconfined_t, unconfined_r)
 ')

Reply via email to