From ea35f1bba057ace3bbe76186c04eb360c6aa57a8 Mon Sep 17 00:00:00 2001 From: Ben Cressey Date: Tue, 6 Apr 2021 23:50:22 +0000 Subject: [PATCH] selinux-policy: add file read restrictions Since host container user data can be used to pass secrets, we should block reads as well as writes to this content. Similarly, because the user data is saved in the datastore, we should also restrict access to those files. Signed-off-by: Ben Cressey --- packages/os/host-containers-tmpfiles.conf | 2 +- packages/selinux-policy/files.cil | 55 ++++++++++++++++++----- packages/selinux-policy/fs.cil | 4 +- packages/selinux-policy/object.cil | 13 +++++- packages/selinux-policy/rules.cil | 47 +++++++++++++------ sources/host-ctr/cmd/host-ctr/main.go | 2 +- 6 files changed, 93 insertions(+), 30 deletions(-) diff --git a/packages/os/host-containers-tmpfiles.conf b/packages/os/host-containers-tmpfiles.conf index c01134f69a2..4c6bffc278e 100644 --- a/packages/os/host-containers-tmpfiles.conf +++ b/packages/os/host-containers-tmpfiles.conf @@ -1,3 +1,3 @@ d /etc/host-containers 0755 root root - d /local/host-containers 0700 root root - -T /local/host-containers - - - - security.selinux=system_u:object_r:state_t:s0 +T /local/host-containers - - - - security.selinux=system_u:object_r:secret_t:s0 diff --git a/packages/selinux-policy/files.cil b/packages/selinux-policy/files.cil index 5669d47b579..43786328ecb 100644 --- a/packages/selinux-policy/files.cil +++ b/packages/selinux-policy/files.cil @@ -1,5 +1,5 @@ ; Permission groups for files. -(classmap files (relabel mount relax enter load mutate block)) +(classmap files (relabel mount relax enter describe load mutate block)) ; Permission group for relabeling files. (classmapping files relabel relabel_file) @@ -34,6 +34,16 @@ ; Permission group for using files as entry points. (classmapping files enter enter_file) +; Permission group for describing files. +(classmapping files describe describe_file) +(classmapping files describe describe_dir) +(classmapping files describe describe_lnk_file) +(classmapping files describe describe_chr_file) +(classmapping files describe describe_blk_file) +(classmapping files describe describe_sock_file) +(classmapping files describe describe_fifo_file) +(classmapping files describe describe_filesystem) + ; Permission group for reading and executing files. (classmapping files load load_file) (classmapping files load load_dir) @@ -146,6 +156,32 @@ (classpermissionset enter_file ( file (entrypoint))) +; Sets of permissions for describing file objects. +(classpermission describe_file) +(classpermission describe_dir) +(classpermission describe_lnk_file) +(classpermission describe_chr_file) +(classpermission describe_blk_file) +(classpermission describe_sock_file) +(classpermission describe_fifo_file) +(classpermission describe_filesystem) +(classpermissionset describe_file ( + file (getattr))) +(classpermissionset describe_dir ( + dir (getattr))) +(classpermissionset describe_lnk_file ( + lnk_file (getattr))) +(classpermissionset describe_chr_file ( + chr_file (getattr))) +(classpermissionset describe_blk_file ( + blk_file (getattr))) +(classpermissionset describe_sock_file ( + sock_file (getattr))) +(classpermissionset describe_fifo_file ( + fifo_file (getattr))) +(classpermissionset describe_filesystem ( + filesystem (getattr quotaget))) + ; Sets of permissions for read-only actions that do not affect the ; integrity of file objects. (classpermission load_file) @@ -159,35 +195,34 @@ (classpermission load_fd) (classpermissionset load_file ( file ( - execute getattr ioctl map open read execute_no_trans + execute ioctl map open read execute_no_trans watch watch_mount watch_reads watch_sb))) (classpermissionset load_dir ( dir ( - execute getattr ioctl map open read search + execute ioctl map open read search watch watch_mount watch_reads watch_sb))) (classpermissionset load_lnk_file ( lnk_file ( - execute ioctl getattr map open read + execute ioctl map open read watch watch_mount watch_reads watch_sb))) (classpermissionset load_chr_file ( chr_file ( - execute ioctl getattr map open read + execute ioctl map open read watch watch_mount watch_reads watch_sb))) (classpermissionset load_blk_file ( blk_file ( - execute ioctl getattr map open read + execute ioctl map open read watch watch_mount watch_reads watch_sb))) (classpermissionset load_sock_file ( sock_file ( - execute ioctl getattr map open read + execute ioctl map open read watch watch_mount watch_reads watch_sb))) (classpermissionset load_fifo_file ( fifo_file ( - execute ioctl getattr map open read + execute ioctl map open read watch watch_mount watch_reads watch_sb))) (classpermissionset load_filesystem ( - filesystem ( - getattr quotaget watch))) + filesystem (watch))) (classpermissionset load_fd ( fd (use))) diff --git a/packages/selinux-policy/fs.cil b/packages/selinux-policy/fs.cil index 58f0dfc4d1d..eb21896a194 100644 --- a/packages/selinux-policy/fs.cil +++ b/packages/selinux-policy/fs.cil @@ -62,8 +62,8 @@ (filecon "/var/.*" any ()) ; Label local state directories. -(filecon "/local/host-containers" any state) -(filecon "/local/host-containers/.*" any state) +(filecon "/local/host-containers" any secret) +(filecon "/local/host-containers/.*" any secret) (filecon "/var/lib/chrony" any measure) (filecon "/var/lib/chrony/.*" any measure) (filecon "/var/lib/systemd" any state) diff --git a/packages/selinux-policy/object.cil b/packages/selinux-policy/object.cil index 259695cc084..37f398727e3 100644 --- a/packages/selinux-policy/object.cil +++ b/packages/selinux-policy/object.cil @@ -100,6 +100,11 @@ (roletype object_r state_t) (context state (system_u object_r state_t s0)) +; Files for saved system secrets. +(type secret_t) +(roletype object_r secret_t) +(context secret (system_u object_r secret_t s0)) + ; Files that are mount points for external filesystems. (type external_t) (roletype object_r external_t) @@ -112,7 +117,11 @@ ; Protected objects are files on local storage with special rules. (typeattribute protected_o) (typeattributeset protected_o ( - cache_t private_t lease_t measure_t state_t)) + cache_t private_t lease_t measure_t secret_t state_t)) + +; Restricted objects are files that cannot be read by all processes. +(typeattribute restricted_o) +(typeattributeset restricted_o (private_t secret_t)) ; Immutable objects reside on read-only storage. (typeattribute immutable_o) @@ -132,6 +141,6 @@ os_t init_exec_t api_exec_t clock_exec_t network_exec_t bus_exec_t runtime_exec_t any_t etc_t unlabeled_t external_t - local_t private_t cache_t + local_t private_t secret_t cache_t lease_t measure_t state_t api_socket_t)) diff --git a/packages/selinux-policy/rules.cil b/packages/selinux-policy/rules.cil index 8d86c23349c..8fe239faced 100644 --- a/packages/selinux-policy/rules.cil +++ b/packages/selinux-policy/rules.cil @@ -1,17 +1,18 @@ ; Deny any action that is not defined by the policy. (handleunknown deny) -; Define the set of all subject and object types, to allow certain -; actions to be whitelisted or blacklisted for everything. +; Define the set of all subject and object types, to allow certain actions to +; be allowed or denied for everything. (typeattribute global) (typeattributeset global ((all_s) (all_o))) +; Define a subset of these types which are considered public. +(typeattribute public) +(typeattributeset public (xor (global) (restricted_o))) + ; All subjects are allowed to use the label they already have. (allow all_s self (processes (transform))) -; All subjects are allowed to read and execute all files. -(allow all_s global (files (load))) - ; All subjects are allowed to interact with processes in ; most ways without policy restrictions. (allow all_s global (processes (interact))) @@ -62,11 +63,11 @@ ; unprivileged containers, unless automatic labeling is disabled. (typetransition runtime_t local_t process control_t) (typetransition runtime_t cache_t process control_t) -(typetransition runtime_t state_t process control_t) +(typetransition runtime_t secret_t process control_t) (allow runtime_t container_s (processes (transform))) (allow container_s local_t (file (entrypoint))) (allow container_s cache_t (file (entrypoint))) -(allow container_s state_t (file (entrypoint))) +(allow container_s secret_t (file (entrypoint))) ; Also allow entry to container domains through `docker-init`, which ; is mounted from the root filesystem and used as the init process. @@ -92,12 +93,24 @@ (typetransition runtime_t local_t dir "overlay2" cache_t) ; If a system process creates a directory for host container state, it -; receives the "state_t" label. -(typetransition system_t local_t dir "host-containers" state_t) +; receives the "secret_t" label. +(typetransition system_t local_t dir "host-containers" secret_t) ; The socket for the API server gets the "api_socket_t" label. (typetransition api_t any_t sock_file "api.sock" api_socket_t) +; All subjects can describe anything. +(allow all_s global (files (describe))) + +; All subjects can read from anything that's public. +(allow all_s public (files (load))) + +; Trusted subjects can read from anything at all. +(allow trusted_s global (files (load))) + +; Untrusted subjects cannot read from restricted objects. +(neverallow untrusted_s restricted_o (files (load))) + ; All subjects are allowed to write to objects with their own label. ; This includes files like the ones under /proc/self. (allow all_s self (files (mutate))) @@ -121,19 +134,25 @@ (allow unconfined_s local_t (files (mutate mount))) ; Subjects that control the OS, including helpers spawned by apiserver, can -; write to and manage mounts for "state" files and directories on /local. +; write to and manage mounts for "secret" files and directories on /local. ; Our runtimes also need to be able to perform these operations so that ; they can launch host containers. -(allow api_s state_t (files (mutate mount))) +(allow api_s secret_t (files (mutate mount))) +(allow control_s secret_t (files (mutate mount))) +(allow runtime_s secret_t (files (mutate mount))) + +; Subjects that control the OS can write to and manage mounts for "state" +; files and directories on /local. (allow control_s state_t (files (mutate mount))) -(allow runtime_s state_t (files (mutate mount))) -; Untrusted subjects cannot modify the "state" files. +; Untrusted subjects cannot modify "state" or "secret" files. (neverallow untrusted_s state_t (files (mutate mount))) +(neverallow untrusted_s secret_t (files (mutate mount))) -; Confined subjects cannot modify either "state" or "local" files. +; Confined subjects cannot modify "state", "secret", or "local" files. (neverallow confined_s local_t (files (mutate mount))) (neverallow confined_s state_t (files (mutate mount))) +(neverallow confined_s secret_t (files (mutate mount))) ; Trusted components are allowed to manage mounts everywhere. (allow trusted_s global (files (mount))) diff --git a/sources/host-ctr/cmd/host-ctr/main.go b/sources/host-ctr/cmd/host-ctr/main.go index 6d96888d8ef..8a0373e3402 100644 --- a/sources/host-ctr/cmd/host-ctr/main.go +++ b/sources/host-ctr/cmd/host-ctr/main.go @@ -232,7 +232,7 @@ func runCtr(containerdSocket string, namespace string, containerID string, sourc // Mount in the persistent storage location for this container withPersistentStorage(containerID), // Mount the rootfs with an SELinux label that makes it writable - withMountLabel("system_u:object_r:state_t:s0"), + withMountLabel("system_u:object_r:secret_t:s0"), // Include conditional options for superpowered containers. withSuperpowered(superpowered), )