From cd929e846ba8123c7d82846e58516f413ea00e6c Mon Sep 17 00:00:00 2001 From: Kenton Groombridge <me@concord.sh> Date: Fri, 17 Jun 2022 13:14:49 -0400 Subject: [PATCH] various: fixes for kubernetes Signed-off-by: Kenton Groombridge <me@concord.sh> --- policy/modules/services/container.if | 131 ++++++++++----- policy/modules/services/container.te | 79 +++++++-- policy/modules/services/crio.te | 10 +- policy/modules/services/kubernetes.if | 146 +++++++++++++++-- policy/modules/services/kubernetes.te | 228 ++++++++++++++++++-------- policy/modules/services/podman.te | 6 +- policy/modules/services/rpc.te | 6 + policy/modules/system/miscfiles.if | 60 +++++++ policy/modules/system/mount.if | 18 ++ policy/modules/system/selinuxutil.te | 4 + 10 files changed, 549 insertions(+), 139 deletions(-) diff --git a/policy/modules/services/container.if b/policy/modules/services/container.if index 8c9f6cbe6..ec8b0c81d 100644 --- a/policy/modules/services/container.if +++ b/policy/modules/services/container.if @@ -815,26 +815,6 @@ interface(`container_signal_all_containers',` allow $1 container_domain:process signal_perms; ') -######################################## -## <summary> -## Allow the specified domain to -## get the process group ID of all -## containers. -## </summary> -## <param name="domain"> -## <summary> -## Domain allowed to transition. -## </summary> -## </param> -# -interface(`container_getpgid_all_containers',` - gen_require(` - attribute container_domain; - ') - - allow $1 container_domain:process getpgid; -') - ######################################## ## <summary> ## Set the attributes of container ptys. @@ -902,7 +882,7 @@ interface(`container_mountpoint',` ## </summary> ## </param> # -interface(`container_list_plugins',` +interface(`container_list_plugin_dirs',` gen_require(` type container_plugin_t; ') @@ -910,6 +890,26 @@ interface(`container_list_plugins',` allow $1 container_plugin_t:dir list_dir_perms; ') +######################################## +## <summary> +## Allow the specified domain to +## add a watch on container plugin +## directories. +## </summary> +## <param name="domain"> +## <summary> +## Domain allowed access. +## </summary> +## </param> +# +interface(`container_watch_plugin_dirs',` + gen_require(` + type container_plugin_t; + ') + + allow $1 container_plugin_t:dir watch; +') + ######################################## ## <summary> ## Allow the specified domain to @@ -945,7 +945,7 @@ interface(`container_exec_plugins',` type container_plugin_t; ') - container_list_plugins($1) + container_list_plugin_dirs($1) can_exec($1, container_plugin_t) ') @@ -1026,25 +1026,6 @@ interface(`container_rw_config_files',` rw_files_pattern($1, container_config_t, container_config_t) ') -######################################## -## <summary> -## Allow the specified domain to -## write container config files. -## </summary> -## <param name="domain"> -## <summary> -## Domain allowed access. -## </summary> -## </param> -# -interface(`container_write_config_files',` - gen_require(` - type container_config_t; - ') - - write_files_pattern($1, container_config_t, container_config_t) -') - ######################################## ## <summary> ## Allow the specified domain to @@ -1934,6 +1915,25 @@ interface(`container_manage_var_lib_files',` manage_files_pattern($1, container_var_lib_t, container_var_lib_t) ') +######################################## +## <summary> +## Allow the specified domain to memory +## map container files in /var/lib. +## </summary> +## <param name="domain"> +## <summary> +## Domain allowed access. +## </summary> +## </param> +# +interface(`container_map_var_lib_files',` + gen_require(` + type container_var_lib_t; + ') + + allow $1 container_var_lib_t:file map; +') + ######################################## ## <summary> ## Allow the specified domain to manage @@ -2021,6 +2021,36 @@ interface(`container_var_lib_filetrans',` files_var_lib_filetrans($1, container_var_lib_t, $2, $3) ') +######################################## +## <summary> +## Allow the specified domain to create +## objects in /var/lib with an automatic +## transition to the container file type. +## </summary> +## <param name="domain"> +## <summary> +## Domain allowed access. +## </summary> +## </param> +## <param name="object"> +## <summary> +## The object class of the object being created. +## </summary> +## </param> +## <param name="name" optional="true"> +## <summary> +## The name of the object being created. +## </summary> +## </param> +# +interface(`container_var_lib_filetrans_file',` + gen_require(` + type container_file_t; + ') + + files_var_lib_filetrans($1, container_file_t, $2, $3) +') + ######################################## ## <summary> ## Allow the specified domain to create @@ -2239,6 +2269,25 @@ interface(`container_manage_log_files',` manage_files_pattern($1, container_log_t, container_log_t) ') +######################################## +## <summary> +## Allow the specified domain to watch +## container log files. +## </summary> +## <param name="domain"> +## <summary> +## Domain allowed access. +## </summary> +## </param> +# +interface(`container_watch_log_files',` + gen_require(` + type container_log_t; + ') + + allow $1 container_log_t:file watch; +') + ######################################## ## <summary> ## Allow the specified domain to create diff --git a/policy/modules/services/container.te b/policy/modules/services/container.te index 527e9135a..92dc11c3e 100644 --- a/policy/modules/services/container.te +++ b/policy/modules/services/container.te @@ -86,6 +86,9 @@ roleattribute system_r container_roles; container_domain_template(container) typealias container_t alias svirt_lxc_net_t; typeattribute container_t container_system_domain, container_user_domain, container_net_domain; +optional_policy(` + kubernetes_container(container_t) +') container_engine_domain_template(container_engine) typeattribute container_engine_t container_engine_system_domain; @@ -100,6 +103,9 @@ mls_trusted_object(container_engine_t) type spc_t, container_domain, container_net_domain, container_system_domain, privileged_container_domain; domain_type(spc_t) role system_r types spc_t; +optional_policy(` + kubernetes_container(spc_t) +') type spc_user_t, container_domain, container_net_domain, container_user_domain, privileged_container_domain; domain_type(spc_user_t) @@ -153,6 +159,9 @@ files_mountpoint(container_file_t) files_associate_rootfs(container_file_t) term_pty(container_file_t) container_mountpoint(container_file_t) +optional_policy(` + kubernetes_mountpoint(container_file_t) +') type container_ro_file_t; files_mountpoint(container_ro_file_t) @@ -204,6 +213,7 @@ manage_fifo_files_pattern(container_domain, container_file_t, container_file_t) rw_chr_files_pattern(container_domain, container_file_t, container_file_t) rw_blk_files_pattern(container_domain, container_file_t, container_file_t) allow container_domain container_file_t:dir_file_class_set watch; +allow container_domain container_file_t:file { entrypoint map }; allow container_domain container_ro_file_t:blk_file read_blk_file_perms; allow container_domain container_ro_file_t:dir list_dir_perms; @@ -283,10 +293,10 @@ tunable_policy(`container_read_public_content',` ') tunable_policy(`container_use_ecryptfs',` - fs_manage_ecryptfs_dirs(container_domain) - fs_manage_ecryptfs_files(container_domain) - fs_manage_ecryptfs_named_sockets(container_domain) - fs_list_ecryptfs(container_domain) + fs_manage_ecryptfs_dirs(container_domain) + fs_manage_ecryptfs_files(container_domain) + fs_manage_ecryptfs_named_sockets(container_domain) + fs_list_ecryptfs(container_domain) ') tunable_policy(`container_use_nfs',` @@ -307,10 +317,10 @@ tunable_policy(`container_use_samba',` optional_policy(` kubernetes_list_tmpfs(container_domain) - kubernetes_watch_tmpfs_dirs(container_domain) - kubernetes_watch_tmpfs_files(container_domain) kubernetes_read_tmpfs_files(container_domain) kubernetes_read_tmpfs_symlinks(container_domain) + kubernetes_watch_tmpfs_dirs(container_domain) + kubernetes_watch_tmpfs_files(container_domain) ') optional_policy(` @@ -382,7 +392,6 @@ allow container_t self:capability { chown dac_override dac_read_search fowner fs dontaudit container_t self:capability2 block_suspend; allow container_t self:process setrlimit; -allow container_t container_file_t:file entrypoint; allow container_t container_file_t:filesystem getattr; kernel_read_network_state(container_t) @@ -437,7 +446,8 @@ allow container_engine_domain container_port_t:tcp_socket name_bind; dontaudit container_engine_domain container_domain:process { noatsecure rlimitinh siginh }; allow container_engine_domain container_domain:process2 { nnp_transition nosuid_transition }; -allow container_engine_domain container_mountpoint_type:dir_file_class_set mounton; +allow container_engine_domain container_mountpoint_type:dir search_dir_perms; +allow container_engine_domain container_mountpoint_type:dir_file_class_set { getattr mounton }; corecmd_bin_entry_type(container_engine_domain) corecmd_exec_bin(container_engine_domain) @@ -644,6 +654,11 @@ ps_process_pattern(container_engine_system_domain, container_system_domain) allow container_system_domain container_engine_system_domain:fd use; allow container_system_domain container_engine_system_domain:fifo_file rw_fifo_file_perms; +# for managing container storage on ZFS volumes +fstools_exec(container_engine_system_domain) + +logging_send_syslog_msg(container_engine_system_domain) + create_dirs_pattern(container_engine_system_domain, container_config_t, container_config_t) files_etc_filetrans(container_engine_system_domain, container_config_t, dir) @@ -683,6 +698,13 @@ allow container_engine_system_domain container_engine_cache_t:dir manage_dir_per allow container_engine_system_domain container_engine_cache_t:file manage_file_perms; files_var_filetrans(container_engine_system_domain, container_engine_cache_t, { dir file }) +container_exec_plugins(container_engine_system_domain) +container_watch_plugin_dirs(container_engine_system_domain) + +optional_policy(` + zfs_domtrans(container_engine_system_domain) +') + ######################################## # # Common user container engine local policy @@ -770,10 +792,11 @@ domtrans_pattern(container_engine_system_domain, container_file_t, spc_t) domtrans_pattern(container_engine_system_domain, container_ro_file_t, spc_t) domtrans_pattern(container_engine_system_domain, container_var_lib_t, spc_t) -allow spc_t self:process setrlimit; -allow spc_t self:capability { sys_admin sys_resource }; +allow spc_t self:process { getcap setrlimit }; +allow spc_t self:capability { audit_write chown dac_read_search fowner fsetid sys_admin sys_ptrace sys_rawio sys_resource }; allow spc_t self:capability2 { bpf perfmon }; allow spc_t self:bpf { map_create map_read map_write prog_load prog_run }; +allow spc_t self:netlink_audit_socket { create_netlink_socket_perms nlmsg_relay }; allow spc_t self:netlink_generic_socket create_socket_perms; allow spc_t self:netlink_netfilter_socket create_socket_perms; allow spc_t self:netlink_xfrm_socket create_socket_perms; @@ -782,6 +805,19 @@ allow container_engine_system_domain spc_t:process { setsched signal_perms }; allow spc_t container_engine_system_domain:fifo_file rw_fifo_file_perms; +# for kubernetes debug pods - for some reason, +# cri-o does not relabel the container's /dev +# when a debug pod is created, so the user will +# be unable to attach to its terminal unless +# this is allowed +allow spc_t container_engine_tmpfs_t:dir list_dir_perms; +allow spc_t container_engine_tmpfs_t:chr_file rw_chr_file_perms; +allow spc_t container_engine_tmpfs_t:lnk_file read_lnk_file_perms; + +# for kubernetes storage class providers +allow spc_t container_file_t:{ dir file } mounton; +allow spc_t container_file_t:dir_file_class_set { relabelfrom relabelto }; + allow spc_t container_runtime_t:dir { manage_dir_perms mounton }; allow spc_t container_runtime_t:file manage_file_perms; allow spc_t container_runtime_t:sock_file manage_sock_file_perms; @@ -790,7 +826,10 @@ dev_mounton_sysfs_dirs(spc_t) dev_read_sysfs(spc_t) fs_read_nsfs_files(spc_t) +fs_mount_xattr_fs(spc_t) +fs_unmount_xattr_fs(spc_t) fs_mount_cgroup(spc_t) +fs_mounton_cgroup(spc_t) fs_list_cgroup_dirs(spc_t) fs_mount_bpf(spc_t) fs_create_bpf_dirs(spc_t) @@ -801,15 +840,21 @@ fs_watch_tmpfs_dirs(spc_t) kernel_load_module(spc_t) kernel_request_load_module(spc_t) kernel_read_network_state(spc_t) +kernel_read_vm_overcommit_sysctl(spc_t) +kernel_dontaudit_list_unlabeled(spc_t) -init_dbus_chat(spc_t) -init_run_bpf(spc_t) +storage_raw_rw_fixed_disk(spc_t) + +init_read_state(spc_t) iptables_read_runtime_files(spc_t) modutils_read_module_deps(spc_t) -container_list_plugins(spc_t) +# for kubernetes debug pods +term_use_generic_ptys(spc_t) + +container_list_plugin_dirs(spc_t) container_manage_plugin_files(spc_t) container_create_config_files(spc_t) @@ -821,7 +866,12 @@ container_manage_log_files(spc_t) container_manage_var_lib_dirs(spc_t) container_manage_var_lib_files(spc_t) -allow spc_t container_var_lib_t:file map; +container_map_var_lib_files(spc_t) + +ifdef(`init_systemd',` + init_dbus_chat(spc_t) + init_run_bpf(spc_t) +') optional_policy(` dbus_system_bus_client(spc_t) @@ -836,6 +886,7 @@ optional_policy(` kubernetes_watch_plugin_dirs(spc_t) kubernetes_manage_plugin_files(spc_t) + # Calico runs as a privileged container kubernetes_run_engine_bpf(spc_t) ') diff --git a/policy/modules/services/crio.te b/policy/modules/services/crio.te index dfe1ee5db..8ac9e9fdb 100644 --- a/policy/modules/services/crio.te +++ b/policy/modules/services/crio.te @@ -10,7 +10,6 @@ container_system_engine(crio_t) kubernetes_container_engine(crio_t) type crio_exec_t; container_engine_executable_file(crio_exec_t) -application_domain(crio_t, crio_exec_t) init_daemon_domain(crio_t, crio_exec_t) ifdef(`enable_mls',` init_ranged_daemon_domain(crio_t, crio_exec_t, s0 - mls_systemhigh) @@ -74,7 +73,7 @@ optional_policy(` # crio conmon local policy # -allow crio_conmon_t self:capability { sys_ptrace sys_resource }; +allow crio_conmon_t self:capability { kill sys_ptrace sys_resource }; files_search_tmp(crio_conmon_t) @@ -83,10 +82,12 @@ fs_list_cgroup_dirs(crio_conmon_t) init_rw_inherited_stream_socket(crio_conmon_t) init_use_fds(crio_conmon_t) -container_getpgid_all_containers(crio_conmon_t) container_kill_all_containers(crio_conmon_t) container_read_all_container_state(crio_conmon_t) +# for kubernetes debug pods +container_use_container_ptys(crio_conmon_t) + # crio logs are tmp files container_manage_engine_tmp_files(crio_conmon_t) container_manage_engine_tmp_sock_files(crio_conmon_t) @@ -103,3 +104,6 @@ container_manage_var_lib_fifo_files(crio_conmon_t) container_manage_var_lib_sock_files(crio_conmon_t) container_manage_log_files(crio_conmon_t) + +kubernetes_getpgid_containers(crio_conmon_t) +kubernetes_kubelet_kill(crio_conmon_t) diff --git a/policy/modules/services/kubernetes.if b/policy/modules/services/kubernetes.if index 3c8640e1c..2b1a67809 100644 --- a/policy/modules/services/kubernetes.if +++ b/policy/modules/services/kubernetes.if @@ -30,7 +30,7 @@ template(`kubernetes_kubectl_role',` gen_require(` attribute kubectl_domain; type kubectl_exec_t; - type kubernetes_conf_home_t; + type kubernetes_home_t; ') ######################################## @@ -49,17 +49,17 @@ template(`kubernetes_kubectl_role',` domtrans_pattern($3, kubectl_exec_t, $1_kubectl_t) - allow $2 kubernetes_conf_home_t:dir { manage_dir_perms relabel_dir_perms }; - allow $2 kubernetes_conf_home_t:file { manage_file_perms relabel_file_perms }; - allow $2 kubernetes_conf_home_t:lnk_file { manage_lnk_file_perms relabel_lnk_file_perms }; - userdom_user_home_dir_filetrans($2, kubernetes_conf_home_t, dir, ".kube") + allow $2 kubernetes_home_t:dir { manage_dir_perms relabel_dir_perms }; + allow $2 kubernetes_home_t:file { manage_file_perms relabel_file_perms }; + allow $2 kubernetes_home_t:lnk_file { manage_lnk_file_perms relabel_lnk_file_perms }; + userdom_user_home_dir_filetrans($2, kubernetes_home_t, dir, ".kube") allow $3 $1_kubectl_t:process { ptrace signal_perms }; ps_process_pattern($3, $1_kubectl_t) auth_use_nsswitch($1_kubectl_t) - # kubectl executes an editor when editing files + # kubectl executes an editor when editing files. # transition back to the user domain when running them corecmd_bin_domtrans($1_kubectl_t, $2) @@ -133,6 +133,44 @@ interface(`kubernetes_read_kubelet_state',` ps_process_pattern($1, kubelet_t) ') +####################################### +## <summary> +## Inherit and use file descriptors from +## kubelet. +## </summary> +## <param name="domain"> +## <summary> +## Domain allowed access. +## </summary> +## </param> +# +interface(`kubernetes_use_kubelet_fds',` + gen_require(` + type kubelet_t; + ') + + allow $1 kubelet_t:fd use; +') + +####################################### +## <summary> +## Allow kubelet to send a kill signal +## to the specified domain. +## </summary> +## <param name="domain"> +## <summary> +## Domain allowed access. +## </summary> +## </param> +# +interface(`kubernetes_kubelet_kill',` + gen_require(` + type kubelet_t; + ') + + allow kubelet_t $1:process sigkill; +') + ####################################### ## <summary> ## Execute kubeadm in the kubeadm domain. @@ -200,6 +238,28 @@ interface(`kubernetes_container_engine',` typeattribute $1 kubernetes_container_engine_domain; ') +######################################## +## <summary> +## Associated the specified domain to +## be a domain which is capable of +## operating as a container domain +## which can be spawned by kubernetes. +## engine. +## </summary> +## <param name="domain"> +## <summary> +## Domain allowed access. +## </summary> +## </param> +# +interface(`kubernetes_container',` + gen_require(` + attribute kubernetes_container_domain; + ') + + typeattribute $1 kubernetes_container_domain; +') + ######################################## ## <summary> ## Allow the specified file type to be @@ -219,6 +279,26 @@ interface(`kubernetes_mountpoint',` typeattribute $1 kubernetes_mountpoint_type; ') +######################################## +## <summary> +## Allow the specified domain to +## get the process group ID of all +## kubernetes containers. +## </summary> +## <param name="domain"> +## <summary> +## Domain allowed to transition. +## </summary> +## </param> +# +interface(`kubernetes_getpgid_containers',` + gen_require(` + attribute kubernetes_container_domain; + ') + + allow $1 kubernetes_container_domain:process getpgid; +') + ######################################## ## <summary> ## Run kubernetes container engine bpf @@ -314,6 +394,24 @@ interface(`kubernetes_watch_config_dirs',` allow $1 kubernetes_config_t:dir watch; ') +######################################## +## <summary> +## Manage kubernetes config files. +## </summary> +## <param name="domain"> +## <summary> +## Domain allowed access. +## </summary> +## </param> +# +interface(`kubernetes_manage_config_files',` + gen_require(` + type kubernetes_config_t; + ') + + manage_files_pattern($1, kubernetes_config_t, kubernetes_config_t) +') + ######################################## ## <summary> ## Mount on kubernetes config files. @@ -351,6 +449,27 @@ interface(`kubernetes_watch_config_files',` allow $1 kubernetes_config_t:file watch; ') +######################################## +## <summary> +## Allow the specified domain to search +## through the contents of kubernetes plugin +## directories. +## </summary> +## <param name="domain"> +## <summary> +## Domain allowed access. +## </summary> +## </param> +# +interface(`kubernetes_search_plugin_dirs',` + gen_require(` + type kubernetes_plugin_t; + ') + + corecmd_search_bin($1) + allow $1 kubernetes_plugin_t:dir search_dir_perms; +') + ######################################## ## <summary> ## Allow the specified domain to list @@ -412,6 +531,7 @@ interface(`kubernetes_manage_plugin_files',` ######################################## ## <summary> ## List the contents of kubernetes tmpfs +## directories. ## </summary> ## <param name="domain"> ## <summary> @@ -707,7 +827,7 @@ interface(`kubernetes_admin',` type kubectl_exec_t; type kubernetes_config_t, kubernetes_tmp_t; type kubernetes_tmpfs_t, kubernetes_runtime_t; - type kubernetes_conf_home_t; + type kubernetes_home_t; ') container_admin($1, $2) @@ -721,6 +841,8 @@ interface(`kubernetes_admin',` # kubectl executes an editor when editing files # transition back to the user domain when running them corecmd_bin_domtrans(kubectl_t, $1) + allow $1 kubectl_t:fd use; + allow $1 kubectl_t:fifo_file rw_inherited_fifo_file_perms; allow $1 kubeadm_t:process { ptrace signal_perms }; ps_process_pattern($1, kubeadm_t) @@ -734,17 +856,17 @@ interface(`kubernetes_admin',` files_search_etc($1) admin_pattern($1, kubernetes_config_t) + files_search_runtime($1) + admin_pattern($1, kubernetes_runtime_t) + files_search_tmp($1) admin_pattern($1, kubernetes_tmp_t) fs_search_tmpfs($1) admin_pattern($1, kubernetes_tmpfs_t) - files_search_runtime($1) - admin_pattern($1, kubernetes_runtime_t) - - admin_pattern($1, kubernetes_conf_home_t) - userdom_user_home_dir_filetrans($1, kubernetes_conf_home_t, dir, ".kube") + admin_pattern($1, kubernetes_home_t) + userdom_user_home_dir_filetrans($1, kubernetes_home_t, dir, ".kube") optional_policy(` crio_admin($1, $2) diff --git a/policy/modules/services/kubernetes.te b/policy/modules/services/kubernetes.te index 79e32292d..558c4d430 100644 --- a/policy/modules/services/kubernetes.te +++ b/policy/modules/services/kubernetes.te @@ -20,12 +20,11 @@ attribute kubernetes_container_domain; # on by kubernetes containers attribute kubernetes_mountpoint_type; -# common attribute for all kubectl domains +# attribute for kubectl domains attribute kubectl_domain; -type kubelet_t; +type kubelet_t, kubectl_domain; type kubelet_exec_t; -domain_type(kubelet_t) container_engine_executable_file(kubelet_exec_t) init_daemon_domain(kubelet_t, kubelet_exec_t) role kubernetes_roles types kubelet_t; @@ -51,12 +50,12 @@ type kubernetes_runtime_t; files_runtime_file(kubernetes_runtime_t) kubernetes_mountpoint(kubernetes_runtime_t) -# files created in /tmp by kubectl for editing type kubernetes_tmp_t; files_tmp_file(kubernetes_tmp_t) type kubernetes_tmpfs_t; files_type(kubernetes_tmpfs_t) +kubernetes_mountpoint(kubernetes_tmpfs_t) type kubernetes_unit_t; init_unit_file(kubernetes_unit_t) @@ -69,17 +68,29 @@ xdg_config_content(kubernetes_home_t) # common kubernetes container engine policy # +allow kubernetes_container_engine_domain kubernetes_mountpoint_type:dir search_dir_perms; allow kubernetes_container_engine_domain kubernetes_mountpoint_type:dir_file_class_set { getattr mounton }; +allow kubernetes_container_engine_domain kubernetes_container_domain:process getpgid; + +ps_process_pattern(kubernetes_container_engine_domain, kubernetes_container_domain) + +# for kubectl port-forward +corenet_tcp_connect_all_ports(kubernetes_container_engine_domain) + files_getattr_kernel_modules(kubernetes_container_engine_domain) +# for replicated storage that may be mounted in /mnt +files_search_mnt(kubernetes_container_engine_domain) fs_mounton_tmpfs(kubernetes_container_engine_domain) +fs_relabelfrom_tmpfs_dirs(kubernetes_container_engine_domain) + +# for relabeling newly provisioned persistent volumes +kernel_list_unlabeled(kubernetes_container_engine_domain) +kernel_relabelfrom_unlabeled_dirs(kubernetes_container_engine_domain) iptables_getattr_runtime_files(kubernetes_container_engine_domain) -corecmd_search_bin(kubernetes_container_engine_domain) -allow kubernetes_container_engine_domain kubernetes_plugin_t:dir search_dir_perms; - container_use_container_ptys(kubernetes_container_engine_domain) container_exec_plugins(kubernetes_container_engine_domain) @@ -87,8 +98,10 @@ container_exec_plugins(kubernetes_container_engine_domain) container_search_logs(kubernetes_container_engine_domain) container_watch_log_dirs(kubernetes_container_engine_domain) -container_filetrans_var_lib_file(kubernetes_container_engine_domain, dir, "calico") -container_filetrans_var_lib_file(kubernetes_container_engine_domain, dir, "etcd") +container_var_lib_filetrans_file(kubernetes_container_engine_domain, dir, "calico") +container_var_lib_filetrans_file(kubernetes_container_engine_domain, dir, "etcd") + +kubernetes_search_plugin_dirs(kubernetes_container_engine_domain) ifdef(`init_systemd',` init_dbus_chat(kubernetes_container_engine_domain) @@ -102,13 +115,49 @@ ifdef(`init_systemd',` init_stop_transient_units(kubernetes_container_engine_domain) ') +tunable_policy(`container_manage_public_content',` + miscfiles_mounton_all_public_dirs(kubernetes_container_engine_domain) + miscfiles_mounton_all_public_files(kubernetes_container_engine_domain) +') + +tunable_policy(`container_read_public_content',` + miscfiles_mounton_all_public_dirs(kubernetes_container_engine_domain) + miscfiles_mounton_all_public_files(kubernetes_container_engine_domain) +') + +######################################## +# +# common kubernetes container policy +# + +allow kubernetes_container_domain kubernetes_container_engine_domain:fd use; + +# for control plane IPC +container_stream_connect_spec_container(kubernetes_container_domain, kubernetes_container_domain) + +container_manage_var_lib_dirs(kubernetes_container_domain) +container_manage_var_lib_files(kubernetes_container_domain) +container_map_var_lib_files(kubernetes_container_domain) + +# for kube-apiserver if using an volume for storing logs +container_list_log_dirs(kubernetes_container_domain) +container_create_log_dirs(kubernetes_container_domain) +container_manage_log_files(kubernetes_container_domain) + +kubernetes_watch_config_dirs(kubernetes_container_domain) +kubernetes_watch_config_files(kubernetes_container_domain) + +kubernetes_list_plugins(kubernetes_container_domain) +kubernetes_watch_plugin_dirs(kubernetes_container_domain) +kubernetes_manage_plugin_files(kubernetes_container_domain) + ######################################## # # kubelet local policy # allow kubelet_t self:process { getattr getsched setrlimit signal }; -allow kubelet_t self:capability { chown dac_override dac_read_search net_admin net_raw sys_ptrace sys_resource }; +allow kubelet_t self:capability { chown dac_override dac_read_search fowner fsetid kill net_admin net_raw sys_ptrace sys_resource }; allow kubelet_t self:cap_userns sys_ptrace; allow kubelet_t self:fifo_file rw_fifo_file_perms; allow kubelet_t self:rawip_socket create_socket_perms; @@ -116,13 +165,18 @@ allow kubelet_t self:tcp_socket create_stream_socket_perms; allow kubelet_t self:unix_dgram_socket create_socket_perms; allow kubelet_t self:unix_stream_socket { connectto create_stream_socket_perms }; +allow kubelet_t kubernetes_container_engine_domain:process sigkill; +allow kubelet_t kubernetes_container_domain:process sigkill; + +allow kubelet_t kubernetes_mountpoint_type:dir search_dir_perms; + allow kubelet_t kubernetes_plugin_t:dir { create_dir_perms list_dir_perms watch }; -allow kubelet_t kubernetes_plugin_t:file { create_file_perms rw_file_perms }; +manage_files_pattern(kubelet_t, kubernetes_plugin_t, kubernetes_plugin_t) can_exec(kubelet_t, kubernetes_plugin_t) # kubelet drops plugins in /usr/libexec/kubernetes corecmd_bin_filetrans(kubelet_t, kubernetes_plugin_t, dir, "kubernetes") -allow kubelet_t kubernetes_config_t:dir { list_dir_perms watch }; +allow kubelet_t kubernetes_config_t:dir { create_dir_perms list_dir_perms watch }; allow kubelet_t kubernetes_config_t:file { read_file_perms watch }; allow kubelet_t kubernetes_config_t:lnk_file read_lnk_file_perms; files_etc_filetrans(kubelet_t, kubernetes_config_t, dir) @@ -137,6 +191,10 @@ allow kubelet_t kubernetes_runtime_t:file manage_file_perms; allow kubelet_t kubernetes_runtime_t:sock_file manage_sock_file_perms; files_runtime_filetrans(kubelet_t, kubernetes_runtime_t, { dir file sock_file }) +# kubelet detects unsafe mount behavior in /tmp by creating and unmounting a dir +manage_dirs_pattern(kubelet_t, kubernetes_tmp_t, kubernetes_tmp_t) +files_tmp_filetrans(kubelet_t, kubernetes_tmp_t, dir) + kubernetes_manage_tmpfs_dirs(kubelet_t) kubernetes_manage_tmpfs_files(kubelet_t) kubernetes_manage_tmpfs_symlinks(kubelet_t) @@ -149,9 +207,8 @@ corenet_tcp_bind_kubernetes_port(kubelet_t) corenet_tcp_connect_kubernetes_port(kubelet_t) corenet_tcp_connect_all_unreserved_ports(kubelet_t) -corecmd_search_bin(kubelet_t) -corecmd_watch_bin_dirs(kubelet_t) corecmd_exec_bin(kubelet_t) +corecmd_watch_bin_dirs(kubelet_t) dev_getattr_mtrr_dev(kubelet_t) dev_read_kmsg(kubelet_t) @@ -161,33 +218,34 @@ domain_dontaudit_read_all_domains_state(kubelet_t) domain_setpriority_all_domains(kubelet_t) files_dontaudit_getattr_all_dirs(kubelet_t) -files_dontaudit_search_mnt(kubelet_t) files_dontaudit_search_tmp(kubelet_t) -files_search_tmp(kubelet_t) +# search mnt for using persistent storage, if mounted there +files_search_mnt(kubelet_t) files_read_kernel_symbol_table(kubelet_t) # read /usr/share/mime/globs2 files_read_usr_files(kubelet_t) fs_getattr_tmpfs(kubelet_t) fs_search_tmpfs(kubelet_t) +fs_setattr_tmpfs_dirs(kubelet_t) fs_getattr_xattr_fs(kubelet_t) fs_getattr_cgroup(kubelet_t) -fs_list_cgroup_dirs(kubelet_t) +fs_manage_cgroup_dirs(kubelet_t) +fs_manage_cgroup_files(kubelet_t) fs_watch_cgroup_dirs(kubelet_t) -fs_rw_cgroup_files(kubelet_t) +kernel_dontaudit_getattr_proc(kubelet_t) kernel_getattr_message_if(kubelet_t) kernel_read_ring_buffer(kubelet_t) kernel_read_irq_sysctls(kubelet_t) kernel_read_network_state(kubelet_t) kernel_read_system_state(kubelet_t) +kernel_read_state(kubelet_t) kernel_rw_kernel_sysctl(kubelet_t) kernel_rw_net_sysctls(kubelet_t) kernel_rw_vm_overcommit_sysctl(kubelet_t) -kernel_dontaudit_getattr_proc(kubelet_t) -kernel_read_state(kubelet_t) -storage_dontaudit_getattr_fixed_disk_dev(kubelet_t) +storage_getattr_fixed_disk_dev(kubelet_t) auth_use_nsswitch(kubelet_t) @@ -205,6 +263,13 @@ miscfiles_read_localization(kubelet_t) modutils_domtrans(kubelet_t) mount_domtrans(kubelet_t) +# for kubelet's metrics gathering +mount_read_state(kubelet_t) + +# kubelet performs CSI driver actions. At startup, kubelet determines +# if SELinux is enabled in order to relabel newly provisioned volumes +selinux_get_fs_mount(kubelet_t) +selinux_get_enforce_mode(kubelet_t) seutil_read_default_contexts(kubelet_t) @@ -227,19 +292,6 @@ container_stream_connect_spec_container(kubelet_t, kubernetes_container_domain) container_read_all_container_state(kubelet_t) container_read_all_container_engine_state(kubelet_t) -container_list_var_lib(kubelet_t) -container_manage_dirs(kubelet_t) -container_manage_files(kubelet_t) -container_manage_lnk_files(kubelet_t) -container_manage_sock_files(kubelet_t) -container_rw_fifo_files(kubelet_t) -container_watch_dirs(kubelet_t) -container_list_ro_dirs(kubelet_t) - -container_manage_log_dirs(kubelet_t) -container_manage_log_files(kubelet_t) -container_manage_log_symlinks(kubelet_t) - # kubelet will preemptively relabel container # files to the same label even if the labels # are correct, so just dontaudit these @@ -258,9 +310,30 @@ container_filetrans_var_lib_file(kubelet_t, dir, "pods") container_filetrans_var_lib_file(kubelet_t, dir, "plugins") container_filetrans_var_lib_file(kubelet_t, dir, "plugins_registry") +container_manage_dirs(kubelet_t) +container_manage_files(kubelet_t) +container_manage_lnk_files(kubelet_t) +container_manage_sock_files(kubelet_t) +container_rw_fifo_files(kubelet_t) +container_watch_dirs(kubelet_t) +container_list_ro_dirs(kubelet_t) +container_relabel_all_content(kubelet_t) + +container_manage_log_dirs(kubelet_t) +container_manage_log_files(kubelet_t) +container_manage_log_symlinks(kubelet_t) +container_watch_log_files(kubelet_t) +container_log_filetrans(kubelet_t, { dir file }) + +kubernetes_manage_tmpfs_dirs(kubelet_t) +kubernetes_manage_tmpfs_files(kubelet_t) +kubernetes_manage_tmpfs_symlinks(kubelet_t) +fs_tmpfs_filetrans(kubelet_t, kubernetes_tmpfs_t, { dir file lnk_file }) + ifdef(`init_systemd',` init_dbus_chat(kubelet_t) + init_get_system_status(kubelet_t) init_start_system(kubelet_t) init_stop_system(kubelet_t) init_get_transient_units_status(kubelet_t) @@ -272,9 +345,21 @@ ifdef(`init_systemd',` kubernetes_stop_unit(kubelet_t) ') -optional_policy(` - docker_read_state(kubelet_t) - docker_write_state(kubelet_t) +tunable_policy(`container_manage_public_content',` + miscfiles_search_public_dirs(kubelet_t) +') + +tunable_policy(`container_read_public_content',` + miscfiles_search_public_dirs(kubelet_t) +') + +tunable_policy(`container_use_nfs',` + fs_getattr_nfs(kubelet_t) + fs_getattr_nfsd_fs(kubelet_t) + fs_search_nfsd_fs(kubelet_t) + fs_manage_nfs_dirs(kubelet_t) + fs_manage_nfs_files(kubelet_t) + fs_manage_nfs_symlinks(kubelet_t) ') optional_policy(` @@ -298,13 +383,14 @@ allow kubeadm_t self:unix_dgram_socket create_socket_perms; domtrans_pattern(kubeadm_t, kubelet_exec_t, kubelet_t) ps_process_pattern(kubeadm_t, kubelet_t) +allow kubeadm_t kubernetes_mountpoint_type:dir search_dir_perms; + manage_dirs_pattern(kubeadm_t, kubernetes_config_t, kubernetes_config_t) manage_files_pattern(kubeadm_t, kubernetes_config_t, kubernetes_config_t) manage_lnk_files_pattern(kubeadm_t, kubernetes_config_t, kubernetes_config_t) -allow kubeadm_t kubernetes_home_t:dir search_dir_perms; -allow kubeadm_t kubernetes_home_t:file read_file_perms; -allow kubeadm_t kubernetes_home_t:lnk_file read_lnk_file_perms; +read_files_pattern(kubeadm_t, kubernetes_home_t, kubernetes_home_t) +read_lnk_files_pattern(kubeadm_t, kubernetes_home_t, kubernetes_home_t) corenet_tcp_bind_generic_node(kubeadm_t) @@ -318,24 +404,27 @@ corecmd_exec_bin(kubeadm_t) domain_use_interactive_fds(kubeadm_t) files_read_boot_files(kubeadm_t) -files_read_etc_files(kubeadm_t) files_search_kernel_modules(kubeadm_t) files_search_src(kubeadm_t) files_read_usr_files(kubeadm_t) files_read_usr_src_files(kubeadm_t) +# not actually required, but useful for reading manifests copied to /tmp +files_search_tmp(kubeadm_t) fs_getattr_tmpfs(kubeadm_t) fs_list_tmpfs(kubeadm_t) fs_unmount_tmpfs(kubeadm_t) +fs_manage_tmpfs_dirs(kubeadm_t) fs_getattr_xattr_fs(kubeadm_t) +fs_unmount_xattr_fs(kubeadm_t) fs_getattr_cgroup(kubeadm_t) fs_search_cgroup_dirs(kubeadm_t) fs_read_cgroup_files(kubeadm_t) kernel_read_network_state(kubeadm_t) kernel_read_system_state(kubeadm_t) -kernel_read_net_sysctls(kubeadm_t) kernel_read_kernel_sysctls(kubeadm_t) +kernel_read_net_sysctls(kubeadm_t) kernel_dontaudit_getattr_proc(kubeadm_t) auth_use_nsswitch(kubeadm_t) @@ -356,26 +445,23 @@ userdom_search_user_home_content(kubeadm_t) userdom_use_user_terminals(kubeadm_t) userdom_lock_user_terminals(kubeadm_t) -# getattr on /run/docker.sock -container_getattr_runtime_sock_files(kubeadm_t) -# for connecting to cri-o and maybe others container_stream_connect_system_engine(kubeadm_t) -container_list_var_lib(kubeadm_t) -container_manage_var_lib_dirs(kubeadm_t) -container_manage_var_lib_files(kubeadm_t) -container_filetrans_var_lib_file(kubeadm_t, dir, "etcd") - -container_manage_dirs(kubeadm_t) -container_manage_files(kubeadm_t) -container_manage_lnk_files(kubeadm_t) -container_manage_sock_files(kubeadm_t) - container_manage_var_lib_dirs(kubeadm_t) container_manage_var_lib_files(kubeadm_t) container_manage_var_lib_lnk_files(kubeadm_t) container_manage_var_lib_sock_files(kubeadm_t) -container_var_lib_filetrans(kubeadm_t, dir) +container_var_lib_filetrans_file(kubeadm_t, dir) + +container_manage_dirs(kubeadm_t) +container_manage_files(kubeadm_t) +container_manage_chr_files(kubeadm_t) +container_manage_fifo_files(kubeadm_t) +container_manage_lnk_files(kubeadm_t) +container_manage_sock_files(kubeadm_t) + +kubernetes_list_tmpfs(kubeadm_t) +kubernetes_read_tmpfs_symlinks(kubeadm_t) ifdef(`init_systemd',` init_get_system_status(kubeadm_t) @@ -391,9 +477,8 @@ ifdef(`init_systemd',` systemd_read_journal_files(kubeadm_t) ') -optional_policy(` - docker_domtrans_cli(kubeadm_t) - docker_read_state(kubeadm_t) +tunable_policy(`container_use_nfs',` + fs_unmount_nfs(kubeadm_t) ') ######################################## @@ -405,30 +490,36 @@ allow kubectl_domain self:process { getsched signal }; allow kubectl_domain self:fifo_file rw_fifo_file_perms; allow kubectl_domain self:tcp_socket create_stream_socket_perms; -manage_dirs_pattern(kubectl_domain, kubernetes_conf_home_t, kubernetes_conf_home_t) -manage_files_pattern(kubectl_domain, kubernetes_conf_home_t, kubernetes_conf_home_t) -read_lnk_files_pattern(kubectl_domain, kubernetes_conf_home_t, kubernetes_conf_home_t) +manage_dirs_pattern(kubectl_domain, kubernetes_home_t, kubernetes_home_t) +manage_files_pattern(kubectl_domain, kubernetes_home_t, kubernetes_home_t) +read_lnk_files_pattern(kubectl_domain, kubernetes_home_t, kubernetes_home_t) -files_search_tmp(kubectl_domain) +manage_dirs_pattern(kubectl_domain, kubernetes_tmp_t, kubernetes_tmp_t) manage_files_pattern(kubectl_domain, kubernetes_tmp_t, kubernetes_tmp_t) -files_tmp_filetrans(kubectl_domain, kubernetes_tmp_t, file) +manage_lnk_files_pattern(kubectl_domain, kubernetes_tmp_t, kubernetes_tmp_t) +files_tmp_filetrans(kubectl_domain, kubernetes_tmp_t, { dir file }) + +corenet_tcp_bind_generic_node(kubectl_domain) # binds to 8001 for proxy corenet_tcp_bind_all_unreserved_ports(kubectl_domain) -corenet_tcp_bind_generic_node(kubectl_domain) corenet_tcp_connect_http_port(kubectl_domain) +corenet_tcp_connect_http_cache_port(kubectl_domain) corenet_tcp_connect_kubernetes_port(kubectl_domain) domain_use_interactive_fds(kubectl_domain) -files_read_etc_files(kubectl_domain) files_read_usr_files(kubectl_domain) +files_search_tmp(kubectl_domain) kernel_dontaudit_search_network_sysctl(kubectl_domain) miscfiles_read_generic_certs(kubectl_domain) miscfiles_read_localization(kubectl_domain) +# allow users to store manifests in their home directories +userdom_manage_user_home_content_files(kubectl_domain) + userdom_use_user_terminals(kubectl_domain) ######################################## @@ -437,3 +528,8 @@ userdom_use_user_terminals(kubectl_domain) # auth_use_nsswitch(kubectl_t) + +# not required, but convenient for using config commands +# in the config directory +kubernetes_read_config(kubectl_t) +kubernetes_manage_config_files(kubectl_t) diff --git a/policy/modules/services/podman.te b/policy/modules/services/podman.te index 24c7092f5..5cc13da70 100644 --- a/policy/modules/services/podman.te +++ b/policy/modules/services/podman.te @@ -39,9 +39,9 @@ userdom_user_application_domain(podman_user_conmon_t, conmon_exec_t) allow podman_t podman_conmon_t:process setsched; -# podman 4.0.0 now creates OCI networking configs -container_create_config_files(podman_t) -container_write_config_files(podman_t) +# podman creates OCI networking configs and will +# remove them when running podman system reset +container_manage_config_files(podman_t) logging_send_syslog_msg(podman_t) diff --git a/policy/modules/services/rpc.te b/policy/modules/services/rpc.te index 37d2b7ae0..e6eea666e 100644 --- a/policy/modules/services/rpc.te +++ b/policy/modules/services/rpc.te @@ -284,6 +284,12 @@ ifdef(`distro_debian',` term_dontaudit_use_unallocated_ttys(rpcd_t) ') +optional_policy(` + tunable_policy(`container_use_nfs',` + kubernetes_use_kubelet_fds(rpcd_t) + ') +') + optional_policy(` automount_signal(rpcd_t) automount_dontaudit_write_pipes(rpcd_t) diff --git a/policy/modules/system/miscfiles.if b/policy/modules/system/miscfiles.if index 6a3e8cfbd..1ad6442f7 100644 --- a/policy/modules/system/miscfiles.if +++ b/policy/modules/system/miscfiles.if @@ -839,6 +839,26 @@ interface(`miscfiles_relabel_man_cache',` relabel_files_pattern($1, man_cache_t, man_cache_t) ') +######################################## +## <summary> +## Search public directories. +## </summary> +## <param name="domain"> +## <summary> +## Domain allowed access. +## </summary> +## </param> +# +interface(`miscfiles_search_public_dirs',` + gen_require(` + type public_content_t; + type public_content_rw_t; + ') + + allow $1 public_content_t:dir search_dir_perms; + allow $1 public_content_rw_t:dir search_dir_perms; +') + ######################################## ## <summary> ## Read public files used for file @@ -901,6 +921,46 @@ interface(`miscfiles_watch_public_dirs',` allow $1 public_content_rw_t:dir watch; ') +######################################## +## <summary> +## Mount on all public content directories. +## </summary> +## <param name="domain"> +## <summary> +## Domain allowed access. +## </summary> +## </param> +# +interface(`miscfiles_mounton_all_public_dirs',` + gen_require(` + type public_content_t; + type public_content_rw_t; + ') + + allow $1 public_content_t:dir mounton; + allow $1 public_content_rw_t:dir mounton; +') + +######################################## +## <summary> +## Mount on all public content files. +## </summary> +## <param name="domain"> +## <summary> +## Domain allowed access. +## </summary> +## </param> +# +interface(`miscfiles_mounton_all_public_files',` + gen_require(` + type public_content_t; + type public_content_rw_t; + ') + + allow $1 public_content_t:file mounton; + allow $1 public_content_rw_t:file mounton; +') + ######################################## ## <summary> ## Read TeX data diff --git a/policy/modules/system/mount.if b/policy/modules/system/mount.if index 975c461dd..17cc7aafd 100644 --- a/policy/modules/system/mount.if +++ b/policy/modules/system/mount.if @@ -69,6 +69,24 @@ interface(`mount_exec',` can_exec($1, mount_exec_t) ') +######################################## +## <summary> +## Read the process state (/proc/pid) of mount. +## </summary> +## <param name="domain"> +## <summary> +## Domain allowed access. +## </summary> +## </param> +# +interface(`mount_read_state',` + gen_require(` + type mount_t; + ') + + ps_process_pattern($1, mount_t) +') + ######################################## ## <summary> ## Send a generic signal to mount. diff --git a/policy/modules/system/selinuxutil.te b/policy/modules/system/selinuxutil.te index d7f047c2d..cfb0e2f19 100644 --- a/policy/modules/system/selinuxutil.te +++ b/policy/modules/system/selinuxutil.te @@ -697,6 +697,10 @@ optional_policy(` apt_use_fds(setfiles_t) ') +optional_policy(` + container_getattr_fs(setfiles_t) +') + optional_policy(` # leaked file descriptors udev_dontaudit_rw_dgram_sockets(setfiles_t)