From f2d6db5af1c9ec4a74557984c38ee1f7585b90f1 Mon Sep 17 00:00:00 2001 From: "Dustin C. Hatch" Date: Tue, 21 Feb 2023 09:52:49 -0600 Subject: [PATCH] Enable SELinux Enabling SELinux on the target system needs build-time and run-time configuration changes for ther kernel and userspace. Additionally, SELinux requires a policy that defines allowed operations. Gentoo provides a reasonable baseline for all of these changes, but some modifications are required. First and foremost, the Gentoo SELinux policy is missing several necessary rules for systemd-based systems. Notably, services that use alternate namespaces will fail to start because the base policy does not allow systemd components the necessary privileges, so these rules have to be added. Similarly, `systemd-journald` needs additional privileges in order to be able to capture all metadata for processes generating syslog messages. Finally, additional rules are necessary in order to allow systemd to create files and directories prior to launching servies. Besides patching the policy, we also do some hackery to avoid shipping the Python runtime in SELinux-enabled builds. Several SELinux-related packages, including *libselinux* and *policycoreutils* have dependencies on Python modules for some of their functionality. Unfortunately, the Python build system does NOT properly cross-compile native extension modules, so this functionality is not available on the target system. Fortunately, none of the features provided by these modules are actually needed at runtime, so we can safely ignore them and thus omit the entire Python runtime and all Python programs from the final image. It is important to note that it is impossible to build an SELinux-enabled image on a host that is itself SELinux-enabled. Operations such as changing file labels are checked against the SELinux policy in the running kernel, and may be denied if the target policy differs significantly from the running policy. The `setfiles` command fails, for example, when run on a Fedora host. As such, building an SELinux-enabled system should be done in a virtual machine using a kernel that does not have a loaded SELinux policy. The `ocivm` script can be used to create a suitable runtime from a container image. --- build-rootfs.sh | 24 ++++++ busybox.symlinks | 1 + config | 2 +- host-portage/package.use/selinux | 2 + host-portage/package.use/systemd | 2 + host-tools.packages | 2 + linux.config | 7 ++ overlay/etc/selinux/config | 15 ++++ .../system-preset/80-local-default.preset | 2 + .../system/auditd.service.d/augenrules.conf | 5 ++ portage/package.use/python | 1 + .../patches/sec-policy/selinux-base-policy | 1 + ...1-systemd-Fixes-for-systemd-resolved.patch | 40 ++++++++++ .../0002-mount-Allow-mounting-on-etc_t.patch | 24 ++++++ ...Mark-unlabeled_t-as-mount-point-type.patch | 24 ++++++ ...emd-journald-list-cgroup-directories.patch | 24 ++++++ ...-Allow-systemd-to-create-directories.patch | 76 +++++++++++++++++++ portage/profile/package.provided | 1 + portage/savedconfig/sys-apps/busybox | 4 +- squashfs.exclude | 18 +++++ 20 files changed, 272 insertions(+), 3 deletions(-) create mode 100644 host-portage/package.use/selinux create mode 100644 overlay/etc/selinux/config create mode 100644 overlay/usr/lib/systemd/system/auditd.service.d/augenrules.conf create mode 100644 portage/package.use/python create mode 120000 portage/patches/sec-policy/selinux-base-policy create mode 100644 portage/patches/sec-policy/selinux-base/0001-systemd-Fixes-for-systemd-resolved.patch create mode 100644 portage/patches/sec-policy/selinux-base/0002-mount-Allow-mounting-on-etc_t.patch create mode 100644 portage/patches/sec-policy/selinux-base/0003-kernel-Mark-unlabeled_t-as-mount-point-type.patch create mode 100644 portage/patches/sec-policy/selinux-base/0004-Allow-systemd-journald-list-cgroup-directories.patch create mode 100644 portage/patches/sec-policy/selinux-base/0005-Allow-systemd-to-create-directories.patch create mode 100644 portage/profile/package.provided diff --git a/build-rootfs.sh b/build-rootfs.sh index 9943ec0..2316838 100755 --- a/build-rootfs.sh +++ b/build-rootfs.sh @@ -80,3 +80,27 @@ if ! grep -q Include /mnt/gentoo/etc/ssh/sshd_config; then echo 'Include /etc/ssh/sshd_config.d/*.conf' \ >> /mnt/gentoo/etc/ssh/sshd_config fi + +# Although `semanage` accepts a `--store` argument that supposedly +# instructs it to operate on an alternate SELinux policy store, it +# doesn't actually work. As such, we have to run `semanage` in an +# alternate mount namespace with the target policy store bind-mounted +# at the default location so `semanage` can operate on it. +unshare -m sh -e < +Date: Fri, 3 Mar 2023 15:04:28 -0600 +Subject: [PATCH] systemd: Fixes for systemd-resolved + +--- + refpolicy/policy/modules/system/systemd.te | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/refpolicy/policy/modules/system/systemd.te b/refpolicy/policy/modules/system/systemd.te +index ef25974..78f2b07 100644 +--- a/refpolicy/policy/modules/system/systemd.te ++++ b/refpolicy/policy/modules/system/systemd.te +@@ -228,6 +228,7 @@ init_system_domain(systemd_resolved_t, systemd_resolved_exec_t) + + type systemd_resolved_runtime_t alias systemd_resolved_var_run_t; + files_runtime_file(systemd_resolved_runtime_t) ++init_mountpoint(systemd_resolved_runtime_t) + + type systemd_stdio_bridge_t; + type systemd_stdio_bridge_exec_t; +@@ -1441,6 +1442,7 @@ corenet_tcp_bind_llmnr_port(systemd_resolved_t) + corenet_udp_bind_generic_node(systemd_resolved_t) + corenet_udp_bind_dns_port(systemd_resolved_t) + corenet_udp_bind_llmnr_port(systemd_resolved_t) ++corenet_udp_bind_howl_port(systemd_resolved_t) + + selinux_use_status_page(systemd_resolved_t) + +@@ -1452,6 +1454,7 @@ files_list_runtime(systemd_resolved_t) + + fs_getattr_all_fs(systemd_resolved_t) + fs_search_cgroup_dirs(systemd_resolved_t) ++fs_search_all(systemd_resolved_t) + + init_dgram_send(systemd_resolved_t) + +-- +2.39.0 + diff --git a/portage/patches/sec-policy/selinux-base/0002-mount-Allow-mounting-on-etc_t.patch b/portage/patches/sec-policy/selinux-base/0002-mount-Allow-mounting-on-etc_t.patch new file mode 100644 index 0000000..dc38752 --- /dev/null +++ b/portage/patches/sec-policy/selinux-base/0002-mount-Allow-mounting-on-etc_t.patch @@ -0,0 +1,24 @@ +From c1510fe7d63665ea133da3b044c2c63a9b104a02 Mon Sep 17 00:00:00 2001 +From: "Dustin C. Hatch" +Date: Sat, 4 Mar 2023 09:57:44 -0600 +Subject: [PATCH] mount: Allow mounting on etc_t + +--- + refpolicy/policy/modules/system/mount.te | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/refpolicy/policy/modules/system/mount.te b/refpolicy/policy/modules/system/mount.te +index d028723..f73cd29 100644 +--- a/refpolicy/policy/modules/system/mount.te ++++ b/refpolicy/policy/modules/system/mount.te +@@ -89,6 +89,7 @@ files_manage_etc_runtime_files(mount_t) + files_etc_filetrans_etc_runtime(mount_t, file) + files_mounton_all_mountpoints(mount_t) + files_unmount_rootfs(mount_t) ++files_mounton_etc_dirs(mount_t) + # These rules need to be generalized. Only admin, initrc should have it: + files_relabelto_all_file_type_fs(mount_t) + files_mount_all_file_type_fs(mount_t) +-- +2.39.0 + diff --git a/portage/patches/sec-policy/selinux-base/0003-kernel-Mark-unlabeled_t-as-mount-point-type.patch b/portage/patches/sec-policy/selinux-base/0003-kernel-Mark-unlabeled_t-as-mount-point-type.patch new file mode 100644 index 0000000..7906797 --- /dev/null +++ b/portage/patches/sec-policy/selinux-base/0003-kernel-Mark-unlabeled_t-as-mount-point-type.patch @@ -0,0 +1,24 @@ +From 81e1ed4da36c7638f63e78969f70d77f87fb3600 Mon Sep 17 00:00:00 2001 +From: "Dustin C. Hatch" +Date: Sat, 4 Mar 2023 10:16:13 -0600 +Subject: [PATCH] kernel: Mark unlabeled_t as mount point type + +--- + refpolicy/policy/modules/kernel/kernel.te | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/refpolicy/policy/modules/kernel/kernel.te b/refpolicy/policy/modules/kernel/kernel.te +index 5124ae0..b0d7e8f 100644 +--- a/refpolicy/policy/modules/kernel/kernel.te ++++ b/refpolicy/policy/modules/kernel/kernel.te +@@ -267,6 +267,7 @@ allow kernel_t sysctl_kernel_ns_last_pid_t:file read_file_perms; + + # Other possible mount points for the root fs are in files + allow kernel_t unlabeled_t:dir mounton; ++files_mountpoint(unlabeled_t) + # Kernel-generated traffic e.g., TCP resets on + # connections with invalidated labels: + allow kernel_t unlabeled_t:packet send; +-- +2.39.0 + diff --git a/portage/patches/sec-policy/selinux-base/0004-Allow-systemd-journald-list-cgroup-directories.patch b/portage/patches/sec-policy/selinux-base/0004-Allow-systemd-journald-list-cgroup-directories.patch new file mode 100644 index 0000000..74dc110 --- /dev/null +++ b/portage/patches/sec-policy/selinux-base/0004-Allow-systemd-journald-list-cgroup-directories.patch @@ -0,0 +1,24 @@ +From 552ee711eaba5d9efff087feff23b2e6f6249743 Mon Sep 17 00:00:00 2001 +From: "Dustin C. Hatch" +Date: Mon, 6 Mar 2023 12:10:19 -0600 +Subject: [PATCH] Allow systemd-journald list cgroup directories + +--- + refpolicy/policy/modules/system/logging.te | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/refpolicy/policy/modules/system/logging.te b/refpolicy/policy/modules/system/logging.te +index abd61e6..08f77b5 100644 +--- a/refpolicy/policy/modules/system/logging.te ++++ b/refpolicy/policy/modules/system/logging.te +@@ -500,6 +500,7 @@ files_var_lib_filetrans(syslogd_t, syslogd_var_lib_t, { file dir }) + + fs_getattr_all_fs(syslogd_t) + fs_search_auto_mountpoints(syslogd_t) ++fs_list_cgroup_dirs(syslogd_t) + + mls_file_write_all_levels(syslogd_t) # Need to be able to write to /var/run/ and /var/log directories + +-- +2.39.0 + diff --git a/portage/patches/sec-policy/selinux-base/0005-Allow-systemd-to-create-directories.patch b/portage/patches/sec-policy/selinux-base/0005-Allow-systemd-to-create-directories.patch new file mode 100644 index 0000000..5059391 --- /dev/null +++ b/portage/patches/sec-policy/selinux-base/0005-Allow-systemd-to-create-directories.patch @@ -0,0 +1,76 @@ +From bb58cbda2f45ee5d25b44dd256bd3de52bfcc3d8 Mon Sep 17 00:00:00 2001 +From: "Dustin C. Hatch" +Date: Fri, 10 Mar 2023 12:39:41 -0600 +Subject: [PATCH] Allow systemd to create directories + +This allows use of the `RuntimeDirectory`, `StateDirectory`, etc. unit +settings. +--- + refpolicy/policy/modules/kernel/files.if | 18 ++++++++++++++++++ + refpolicy/policy/modules/system/init.te | 14 ++++++++++++++ + 2 files changed, 32 insertions(+) + +diff --git a/refpolicy/policy/modules/kernel/files.if b/refpolicy/policy/modules/kernel/files.if +index f7217b2..9966a21 100644 +--- a/refpolicy/policy/modules/kernel/files.if ++++ b/refpolicy/policy/modules/kernel/files.if +@@ -608,6 +608,24 @@ interface(`files_manage_non_security_dirs',` + allow $1 non_security_file_type:dir manage_dir_perms; + ') + ++######################################## ++## ++## Allow attempts to setattr any directory ++## ++## ++## ++## Domain allowed access. ++## ++## ++# ++interface(`files_setattr_non_security_dirs',` ++ gen_require(` ++ attribute non_security_file_type; ++ ') ++ ++ allow $1 non_security_file_type:dir { read setattr }; ++') ++ + ######################################## + ## + ## Create non-security directories. +diff --git a/refpolicy/policy/modules/system/init.te b/refpolicy/policy/modules/system/init.te +index 97a75cf..7b44a43 100644 +--- a/refpolicy/policy/modules/system/init.te ++++ b/refpolicy/policy/modules/system/init.te +@@ -37,6 +37,13 @@ gen_tunable(init_daemons_use_tty, false) + ## + gen_tunable(init_mounton_non_security, false) + ++## ++##

++## Enable init create, setattr, mounton on non_security_file_type ++##

++##
++gen_tunable(init_create_dirs, true) ++ + attribute init_mountpoint_type; + attribute init_path_unit_loc_type; + attribute init_script_domain_type; +@@ -606,6 +613,13 @@ ifdef(`init_systemd',` + unconfined_create_keys(init_t) + unconfined_write_keys(init_t) + ') ++ ++ tunable_policy(`init_create_dirs',` ++ files_create_non_security_dirs(init_t) ++ files_mounton_non_security(init_t) ++ files_setattr_non_security_dirs(init_t) ++ ') ++ + ',` + tunable_policy(`init_upstart',` + corecmd_shell_domtrans(init_t, initrc_t) +-- +2.39.0 + diff --git a/portage/profile/package.provided b/portage/profile/package.provided new file mode 100644 index 0000000..8edbdcb --- /dev/null +++ b/portage/profile/package.provided @@ -0,0 +1 @@ +app-admin/setools-4.4.0-r3 diff --git a/portage/savedconfig/sys-apps/busybox b/portage/savedconfig/sys-apps/busybox index 378e46b..900dd76 100644 --- a/portage/savedconfig/sys-apps/busybox +++ b/portage/savedconfig/sys-apps/busybox @@ -32,7 +32,7 @@ CONFIG_FEATURE_SUID=y # CONFIG_FEATURE_SUID_CONFIG_QUIET is not set # CONFIG_FEATURE_PREFER_APPLETS is not set CONFIG_BUSYBOX_EXEC_PATH="/proc/self/exe" -# CONFIG_SELINUX is not set +CONFIG_SELINUX=y # CONFIG_FEATURE_CLEAN_UP is not set # CONFIG_FEATURE_SYSLOG_INFO is not set # CONFIG_FEATURE_SYSLOG is not set @@ -1076,7 +1076,7 @@ CONFIG_SV_DEFAULT_SERVICE_DIR="" # CONFIG_SVC is not set # CONFIG_SVOK is not set # CONFIG_SVLOGD is not set -# CONFIG_CHCON is not set +CONFIG_CHCON=y # CONFIG_GETENFORCE is not set # CONFIG_GETSEBOOL is not set # CONFIG_LOAD_POLICY is not set diff --git a/squashfs.exclude b/squashfs.exclude index 61ccb9f..675e922 100644 --- a/squashfs.exclude +++ b/squashfs.exclude @@ -8,13 +8,27 @@ etc/conf.d etc/csh.env etc/init.d etc/portage +etc/python-exec etc/runlevels usr/aarch64-unknown-linux-gnu +usr/bin/2to3* +usr/bin/audit2* +usr/bin/chcat +usr/bin/idle +usr/bin/pydoc* +usr/bin/python* +usr/bin/pyvenv +usr/bin/rlpkg +usr/bin/semanage +usr/bin/sepolgen* +usr/bin/sepolicy usr/include usr/lib*/*.a usr/lib*/cmake +usr/lib*/libpython* usr/lib*/pkgconfig usr/lib/kernel +usr/lib/python* usr/lib/rpm usr/lib/udev/hwdb.d usr/local @@ -23,10 +37,14 @@ usr/share/baselayout usr/share/bash-completion usr/share/doc usr/share/factory +usr/share/gdb usr/share/info +usr/share/locale/*/*/*python* usr/share/man usr/share/pkgconfig usr/share/polkit-1 +usr/share/portage +usr/share/selinux/*/include usr/share/zsh var/cache/edb var/db/Makefile