From da8b04b78f19e0b88714e6b1603c440ba70810f3 Mon Sep 17 00:00:00 2001 From: Ben Cressey Date: Wed, 22 Apr 2020 18:06:19 +0000 Subject: [PATCH 1/2] selinux-policy: add labels and rules for API subjects We expect most API interactions to be mediated by the API socket. A few processes need to directly manipulate the datastore: * apiserver, for regular interactions * early-boot-config, to write its marker file * migrator, when running migrations * storewolf, during initial creation Otherwise, only subjects with the break-glass `super_t` label are allowed to modify these files and directories. Signed-off-by: Ben Cressey --- packages/selinux-policy/fs.cil | 4 ++++ packages/selinux-policy/object.cil | 6 +----- packages/selinux-policy/rules.cil | 21 +++++++++++++++------ packages/selinux-policy/subject.cil | 4 ++++ 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/packages/selinux-policy/fs.cil b/packages/selinux-policy/fs.cil index 17be5cc777b..2c7d26c75e8 100644 --- a/packages/selinux-policy/fs.cil +++ b/packages/selinux-policy/fs.cil @@ -43,6 +43,10 @@ (filecon "/.*/usr/bin/containerd.*" file runtime_exec) (filecon "/.*/usr/bin/docker.*" file runtime_exec) (filecon "/.*/usr/sbin/runc" file runtime_exec) +(filecon "/.*/usr/bin/apiserver" file api_exec) +(filecon "/.*/usr/bin/early-boot-config" file api_exec) +(filecon "/.*/usr/bin/migrator" file api_exec) +(filecon "/.*/usr/bin/storewolf" file api_exec) ; Label local storage mounts. (filecon "/local" any local) diff --git a/packages/selinux-policy/object.cil b/packages/selinux-policy/object.cil index 533309c197f..5b09f3ef91f 100644 --- a/packages/selinux-policy/object.cil +++ b/packages/selinux-policy/object.cil @@ -58,14 +58,10 @@ (typeattribute ephemeral_o) (typeattributeset ephemeral_o (any_t)) -; Protected objects are certain files on local storage. +; Protected objects are files on local storage with special rules. (typeattribute protected_o) (typeattributeset protected_o (cache_t private_t)) -; Unprotected objects are everything else on local storage. -(typeattribute unprotected_o) -(typeattributeset unprotected_o (local_t)) - ; Immutable objects reside on read-only storage. (typeattribute immutable_o) (typeattributeset immutable_o ( diff --git a/packages/selinux-policy/rules.cil b/packages/selinux-policy/rules.cil index 663779d7a44..f1ef102d259 100644 --- a/packages/selinux-policy/rules.cil +++ b/packages/selinux-policy/rules.cil @@ -26,6 +26,11 @@ (allow init_t system_t (processes (transform))) (allow system_t os_t (file (entrypoint))) +; PID 1 starts API components as "api_t". +(typetransition init_t api_exec_t process api_t) +(allow init_t api_t (processes (transform))) +(allow api_t api_exec_t (file (entrypoint))) + ; PID 1 starts container runtimes as "runtime_t". ; The level range is adjusted to span all categories at the same time, ; to support Docker's use of MCS labels. @@ -66,18 +71,22 @@ ; All subjects are allowed to write to, set watches for, and manage ; mounts for most files and directories on /local. -(allow all_s unprotected_o (files (mutate watch mount))) +(allow all_s local_t (files (mutate watch mount))) ; Trusted components are allowed to manage mounts everywhere. (allow trusted_s global (files (mount))) -; Only trusted components can write to "cache_t" or "private_t", as -; they provide a means to persist changes across container restarts -; and reboots. We restrict the ability to set watches as this can -; be used to block access for another process. -(allow trusted_s protected_o (files (mutate watch))) +; Trusted components can set watches on immutable files, since we +; expect this behavior from systemd and dbus-broker. (allow trusted_s immutable_o (files (watch))) +; Only specific components can write to "private_t" or "cache_t", as +; they provide a means to persist changes across container restarts +; and reboots. We also restrict the ability to set watches as this +; can be used to block access for another process. +(allow api_s private_t (files (mutate watch))) +(allow runtime_s cache_t (files (mutate watch))) + ; Untrusted processes should not be permitted to modify these files, ; set watches for them, or to manage mounts for these directories. (neverallow untrusted_s protected_o (files (mutate watch mount))) diff --git a/packages/selinux-policy/subject.cil b/packages/selinux-policy/subject.cil index e46683d0f8b..ba27e82ddf2 100644 --- a/packages/selinux-policy/subject.cil +++ b/packages/selinux-policy/subject.cil @@ -59,6 +59,10 @@ (typeattribute host_s) (typeattributeset host_s (not container_s)) +; Subjects that are allowed to manage the API datastore. +(typeattribute api_s) +(typeattributeset api_s (api_t super_t)) + ; Subjects that are treated as container runtimes. (typeattribute runtime_s) (typeattributeset runtime_s (runtime_t super_t)) From f513115687a2a78dfffb48310b3c149b3ea0442d Mon Sep 17 00:00:00 2001 From: Ben Cressey Date: Wed, 22 Apr 2020 20:22:08 +0000 Subject: [PATCH 2/2] updog: move repo metadata cache to general storage We want to restrict the private filesystem to API processes only, and updog does not have any current need to directly modify the datastore. Signed-off-by: Ben Cressey --- sources/updater/updog/src/main.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sources/updater/updog/src/main.rs b/sources/updater/updog/src/main.rs index 4781d2aa405..475fbf8b10e 100644 --- a/sources/updater/updog/src/main.rs +++ b/sources/updater/updog/src/main.rs @@ -31,6 +31,7 @@ const TARGET_ARCH: &str = "aarch64"; const TRUSTED_ROOT_PATH: &str = "/usr/share/updog/root.json"; const MIGRATION_PATH: &str = "/var/lib/bottlerocket-migrations"; +const METADATA_PATH: &str = "/var/cache/bottlerocket-metadata"; #[derive(Debug, Deserialize, PartialEq)] #[serde(rename_all = "kebab-case")] @@ -104,14 +105,14 @@ fn load_repository<'a>( transport: &'a HttpQueryTransport, config: &'a Config, ) -> Result> { - fs::create_dir_all("/var/lib/bottlerocket/updog").context(error::CreateMetadataCache)?; + fs::create_dir_all(METADATA_PATH).context(error::CreateMetadataCache)?; Repository::load( transport, Settings { root: File::open(TRUSTED_ROOT_PATH).context(error::OpenRoot { path: TRUSTED_ROOT_PATH, })?, - datastore: Path::new("/var/lib/bottlerocket/updog"), + datastore: Path::new(METADATA_PATH), metadata_base_url: &config.metadata_base_url, target_base_url: &config.targets_base_url, limits: Limits {