Search code examples
selinux

SELinux: root user cannot delete file, AVC denial for custom type


I want to use Pihole on Rocky Linux 9 and wrote a policy for it. During testing some files were put there (by the sed command) which I now want to clean up. Upon trying to remove the files it looks as follows.

[root@pihole03 ~]# rm /etc/pihole/sed*
rm: remove regular file '/etc/pihole/sedGcMe6O'? y
rm: cannot remove '/etc/pihole/sedGcMe6O': Permission denied
rm: remove regular file '/etc/pihole/sedkOdgd5'? y
rm: cannot remove '/etc/pihole/sedkOdgd5': Permission denied
rm: remove regular file '/etc/pihole/sedTetiRf'? y
rm: cannot remove '/etc/pihole/sedTetiRf': Permission denied

The files themselves look as follows.

drwxrwxr-x.   3 pihole pihole system_u:object_r:pihole_t:s0              4096 May 31 08:19 .
[...]
-rw-r--r--.   1 root   root   system_u:object_r:pihole_etc_t:s0           398 May 30 20:40 sedGcMe6O
-rw-------.   1 root   root   system_u:object_r:pihole_etc_t:s0           399 May 30 21:47 sedkOdgd5
-rw-r--r--.   1 root   root   system_u:object_r:pihole_etc_t:s0           399 May 30 21:49 sedTetiRf
[...]

I do get denials for the removal action.

type=AVC msg=audit(1685513107.410:217): avc:  denied  { remove_name } for  pid=17665 comm="rm" name="sedGcMe6O" dev="dm-0" ino=482814 scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=system_u:object_r:pihole_t:s0 tclass=dir permissive=0
type=AVC msg=audit(1685513108.270:218): avc:  denied  { remove_name } for  pid=17665 comm="rm" name="sedkOdgd5" dev="dm-0" ino=469130 scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=system_u:object_r:pihole_t:s0 tclass=dir permissive=0
type=AVC msg=audit(1685513108.793:219): avc:  denied  { remove_name } for  pid=17665 comm="rm" name="sedTetiRf" dev="dm-0" ino=480817 scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=system_u:object_r:pihole_t:s0 tclass=dir permissive=0

It just doesn't seem the right way to add a rule like allow unconfined_t pihole_t:dir remove_name; so I guess I am missing something essential when creating the type pihole_t or similar.

For the sake of visibility and overview I'll post my in-place policy at the end.

Type enforcement

policy_module(pihole,1.0.0)

gen_require(`
  type chkpwd_t;
  type dnsmasq_etc_t;
  type dns_port_t;
  type fs_t;
  type httpd_t;
  type httpd_sys_rw_content_t;
  type ifconfig_exec_t;
  type init_t;
  type initrc_var_run_t;
  type kernel_t;
  type net_conf_t;
  type node_t;
  type passwd_file_t;
  type proc_net_t;
  type proc_t;
  type shadow_t;
  type shell_exec_t;
  type sssd_conf_t;
  type sssd_var_lib_t;
  type systemd_userdbd_runtime_t;
  type tmpfs_t;
  type unconfined_service_t;
  type unconfined_t;
  type unreserved_port_t;
  type user_devpts_t;
  type var_log_t;
  type var_run_t;
')

type pihole_t;
type pihole_content_t;
type pihole_etc_t;
type pihole_exec_t;
type pihole_log_t;
type pihole_var_run_t;
init_daemon_domain(pihole_t, pihole_exec_t)
logging_log_file(pihole_log_t)
logging_search_logs(pihole_t)
logging_log_filetrans(pihole_t, pihole_log_t, file)
userdom_use_inherited_user_terminals(pihole_t)
files_pid_file(pihole_var_run_t)
files_search_pids(pihole_t)
files_pid_filetrans(pihole_t, pihole_var_run_t, file)
files_type(pihole_content_t)
files_type(pihole_etc_t)

allow httpd_t self:capability { audit_write net_admin };
allow httpd_t self:netlink_audit_socket { create nlmsg_relay read write };
allow httpd_t self:netlink_tcpdiag_socket { bind create getattr nlmsg_read read setopt write };
allow httpd_t dnsmasq_etc_t:dir { add_name remove_name write };
allow httpd_t dnsmasq_etc_t:file { append create getattr ioctl open read rename setattr unlink write };
allow httpd_t initrc_var_run_t:file { lock open read };
allow httpd_t kernel_t:dir { getattr search };
allow httpd_t kernel_t:file { read open };
allow httpd_t pihole_t:dir { add_name getattr ioctl open read remove_name search setattr write };
allow httpd_t pihole_t:file { create getattr lock open read rename setattr unlink write };
allow httpd_t pihole_t:lnk_file read;
allow httpd_t pihole_t:process signal;
allow httpd_t pihole_content_t:file { getattr lock open read rename setattr unlink write };
allow httpd_t pihole_etc_t:file { create getattr lock ioctl open read rename setattr unlink write };
allow httpd_t pihole_exec_t:file { execute execute_no_trans getattr ioctl map open read };
allow httpd_t pihole_log_t:file { open read };
allow httpd_t shadow_t:file { getattr read open };
allow httpd_t sssd_conf_t:file { getattr open read };
allow httpd_t var_run_t:file { getattr read open };

allow init_t pihole_t:dir mounton;
allow init_t pihole_exec_t:file { execute execute_no_trans map read open };

allow pihole_t self:capability { net_bind_service sys_nice };
allow pihole_t self:dir { add_name remove_name write };
allow pihole_t self:file { create setattr unlink };
allow pihole_t self:netlink_route_socket { bind create getattr getopt nlmsg_read read setopt write };
allow pihole_t self:process { execmem setsched };
allow pihole_t self:tcp_socket { accept bind create ioctl listen read setopt write };
allow pihole_t self:udp_socket { bind create connect getattr ioctl read setopt write };
allow pihole_t self:unix_dgram_socket { connect create };
allow pihole_t dnsmasq_etc_t:dir { getattr open read search };
allow pihole_t dnsmasq_etc_t:file { getattr open read };
allow pihole_t dns_port_t:tcp_socket name_bind;
allow pihole_t dns_port_t:udp_socket name_bind;
allow pihole_t fs_t:filesystem { associate getattr };
allow pihole_t httpd_sys_rw_content_t:dir { getattr search };
allow pihole_t httpd_sys_rw_content_t:file { getattr lock open read };
allow pihole_t ifconfig_exec_t:file { execute execute_no_trans getattr map open read };
allow pihole_t net_conf_t:file { getattr open read };
allow pihole_t node_t:tcp_socket node_bind;
allow pihole_t node_t:udp_socket node_bind;
allow pihole_t pihole_content_t:file { getattr lock open read setattr write };
allow pihole_t pihole_etc_t:file { getattr lock open read };
allow pihole_t pihole_log_t:dir search;
allow pihole_t pihole_log_t:file { open read };
allow pihole_t pihole_var_run_t:file manage_file_perms;
allow pihole_t proc_t:file { open read };
allow pihole_t proc_net_t:file { getattr open read };
allow pihole_t proc_net_t:lnk_file read;
allow pihole_t shell_exec_t:file { execute execute_no_trans map };
allow pihole_t tmpfs_t:file { create map open read unlink write };
allow pihole_t tmpfs_t:filesystem getattr;
allow pihole_t unreserved_port_t:tcp_socket name_bind;
allow pihole_t var_run_t:file { getattr open read write };
allow pihole_t var_run_t:sock_file create;
dontaudit pihole_t passwd_file_t:file read;
dontaudit pihole_t sssd_var_lib_t:dir search;
dontaudit pihole_t systemd_userdbd_runtime_t:dir read;

# necessary for the "pihole -up" updater
allow unconfined_t pihole_t:dir { add_name write };

allow unconfined_service_t pihole_t:dir setattr;

File context

/etc/pihole(/.*)? gen_context(system_u:object_r:pihole_etc_t,s0)
/etc/pihole/(pihole-FTL\.conf|setupVars\.conf) gen_context(system_u:object_r:pihole_etc_t,s0)
/etc/pihole/gravity(_old)?\.db(_temp(-journal)?)? gen_context(system_u:object_r:pihole_content_t,s0)
/etc/pihole/pihole-FTL\.db gen_context(system_u:object_r:pihole_content_t,s0)
/usr/bin/pihole-FTL gen_context(system_u:object_r:pihole_exec_t,s0)
/usr/local/bin/pihole gen_context(system_u:object_r:pihole_exec_t,s0)
/var/log/pihole(-FTL)?\.log gen_context(system_u:object_r:pihole_log_t,s0)
/var/log/pihole(/.*)? gen_context(system_u:object_r:pihole_log_t,s0)

This is still work in progress but still I'm happy for feedback regarding improvement also.


Solution

  • It just doesn't seem the right way to add a rule like allow unconfined_t pihole_t:dir remove_name;

    I think it is. Unless you are managing a system with confined users, selinux is here to prevent processes to access something they should not, not to prevent unconfined users access files. chown / chmod and setfacl can be used for this.

    Although, if it is a one time job, you could change the context of the files before removing them with chcon.

    Or, if it's not a one time removal, and you don't want to grants unconfined_t permissions, you could write a script, run it with systemd service and timer, and allow init_t to remove files with pihole_t context.