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