From 1c1fd35323795e075adb7a44783fca87b2c12b44 Mon Sep 17 00:00:00 2001 From: alexhulbert Date: Mon, 25 Aug 2025 22:54:20 -0400 Subject: [PATCH 1/2] Apparmor support --- bob/bob.conf | 1 + bob/kernel.config | 3 ++ .../etc/apparmor.d/searcher-container | 46 +++++++++++++++++++ .../systemd/system/searcher-container.service | 4 +- bob/mkosi.extra/usr/bin/init-container.sh | 4 ++ bob/mkosi.postinst | 1 + 6 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 bob/mkosi.extra/etc/apparmor.d/searcher-container diff --git a/bob/bob.conf b/bob/bob.conf index e814b7e..219d783 100644 --- a/bob/bob.conf +++ b/bob/bob.conf @@ -28,6 +28,7 @@ Packages=podman openssh-sftp-server udev libsnappy1v5 + apparmor BuildPackages=build-essential git diff --git a/bob/kernel.config b/bob/kernel.config index 76d762d..8129792 100644 --- a/bob/kernel.config +++ b/bob/kernel.config @@ -34,3 +34,6 @@ CONFIG_IP_NF_TARGET_REDIRECT=y CONFIG_IP_NF_MANGLE=y CONFIG_IP_NF_RAW=y CONFIG_NET_SCHED=y +CONFIG_SECURITY_APPARMOR=y +CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE=1 +CONFIG_DEFAULT_SECURITY_APPARMOR=y diff --git a/bob/mkosi.extra/etc/apparmor.d/searcher-container b/bob/mkosi.extra/etc/apparmor.d/searcher-container new file mode 100644 index 0000000..d8d4d22 --- /dev/null +++ b/bob/mkosi.extra/etc/apparmor.d/searcher-container @@ -0,0 +1,46 @@ +#include + +profile searcher-container flags=(attach_disconnected,mediate_deleted) { + #include + + network, + capability, + file, + umount, + + # Allow signals from privileged profiles and from within the same profile + signal (receive) peer=unconfined, + signal (send,receive) peer=searcher-container, + # Allow signals from podman/runc/crun + signal (receive) peer={/usr/bin/,/usr/sbin/,}{podman,runc,crun*}, + + deny @{PROC}/* w, # deny write for all files directly in /proc (not in a subdir) + # deny write to files not in /proc//** or /proc/sys/** + deny @{PROC}/{[^1-9],[^1-9][^0-9],[^1-9s][^0-9y][^0-9s],[^1-9][^0-9][^0-9][^0-9/]*}/** w, + deny @{PROC}/sys/[^k]** w, # deny /proc/sys except /proc/sys/k* (effectively /proc/sys/kernel) + deny @{PROC}/sys/kernel/{?,??,[^s][^h][^m]**} w, # deny everything except shm* in /proc/sys/kernel/ + deny @{PROC}/sysrq-trigger rwklx, + deny @{PROC}/kcore rwklx, + + deny mount, + + deny /sys/[^f]*/** wklx, + deny /sys/f[^s]*/** wklx, + deny /sys/fs/[^c]*/** wklx, + deny /sys/fs/c[^g]*/** wklx, + deny /sys/fs/cg[^r]*/** wklx, + deny /sys/firmware/** rwklx, + deny /sys/devices/virtual/powercap/** rwklx, + deny /sys/kernel/security/** rwklx, + + # suppress ptrace denials when using 'ps' inside a container + ptrace (trace,read,tracedby,readby) peer=searcher-container, + + # Additional rules for searcher-specific paths + /persistent/** rw, + /etc/searcher/** r, + /var/log/searcher/** w, + /var/log/lighthouse/** r, + /secrets/** r, + /tmp/jwt.hex r, +} diff --git a/bob/mkosi.extra/etc/systemd/system/searcher-container.service b/bob/mkosi.extra/etc/systemd/system/searcher-container.service index eccf0d0..f6c2c9f 100644 --- a/bob/mkosi.extra/etc/systemd/system/searcher-container.service +++ b/bob/mkosi.extra/etc/systemd/system/searcher-container.service @@ -1,7 +1,7 @@ [Unit] Description=Searcher SSH Container -After=dropbear.service searcher-firewall.service persistent-mount.service -Requires=dropbear.service searcher-firewall.service persistent-mount.service +After=dropbear.service searcher-firewall.service persistent-mount.service apparmor.service +Requires=dropbear.service searcher-firewall.service persistent-mount.service apparmor.service [Service] Type=oneshot diff --git a/bob/mkosi.extra/usr/bin/init-container.sh b/bob/mkosi.extra/usr/bin/init-container.sh index a3aed3c..4a885d9 100755 --- a/bob/mkosi.extra/usr/bin/init-container.sh +++ b/bob/mkosi.extra/usr/bin/init-container.sh @@ -9,9 +9,13 @@ ENGINE_API_PORT=8551 EL_P2P_PORT=30303 SEARCHER_INPUT_CHANNEL=27017 +# Enabling apparmor profile +/usr/sbin/apparmor_parser -r /etc/apparmor.d/searcher-container + echo "Starting $NAME..." su -s /bin/sh searcher -c "cd ~ && podman run -d \ --name $NAME --replace \ + --security-opt apparmor=searcher-container \ -p ${SEARCHER_SSH_PORT}:22 \ -p ${ENGINE_API_PORT}:${ENGINE_API_PORT} \ -p ${EL_P2P_PORT}:${EL_P2P_PORT} \ diff --git a/bob/mkosi.postinst b/bob/mkosi.postinst index 7c38275..ef54827 100755 --- a/bob/mkosi.postinst +++ b/bob/mkosi.postinst @@ -34,6 +34,7 @@ for service in \ searcher-log-writer.service \ wait-for-key.service \ searcher-firewall.service \ + apparmor.service \ dropbear.service \ lighthouse.service \ searcher-container.service \ From 5861c7c2663c6c5b514803fbac1f3cefa4c42b8e Mon Sep 17 00:00:00 2001 From: alexhulbert Date: Fri, 26 Sep 2025 21:57:43 -0400 Subject: [PATCH 2/2] Working AppArmor --- base/mkosi.skeleton/init | 1 + bob/kernel.config | 7 +++++++ bob/mkosi.extra/usr/bin/init-container.sh | 1 - bob/mkosi.postinst | 4 ++++ bob/runc-apparmor.sh | 15 +++++++++++++++ 5 files changed, 27 insertions(+), 1 deletion(-) create mode 100755 bob/runc-apparmor.sh diff --git a/base/mkosi.skeleton/init b/base/mkosi.skeleton/init index b6f1256..b210f83 100755 --- a/base/mkosi.skeleton/init +++ b/base/mkosi.skeleton/init @@ -7,6 +7,7 @@ mount -t sysfs none /sys mount -t devtmpfs none /dev mount -t tmpfs none /run mount -t configfs none /sys/kernel/config +mount -t securityfs none /sys/kernel/security # Workaround to make pivot_root work # https://aconz2.github.io/2024/07/29/container-from-initramfs.html diff --git a/bob/kernel.config b/bob/kernel.config index 2a4733b..c46a3c7 100644 --- a/bob/kernel.config +++ b/bob/kernel.config @@ -37,6 +37,13 @@ CONFIG_NET_SCHED=y CONFIG_SECURITY_APPARMOR=y CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE=1 CONFIG_DEFAULT_SECURITY_APPARMOR=y +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +CONFIG_AUDIT_GENERIC=y +CONFIG_SECURITY_PATH=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +CONFIG_LSM="landlock,lockdown,yama,apparmor,loadpin,safesetid,bpf" CONFIG_CRYPTO_USER_API_HASH=y CONFIG_CRYPTO_USER_API_SKCIPHER=y CONFIG_CRYPTO_USER_API_RNG=y diff --git a/bob/mkosi.extra/usr/bin/init-container.sh b/bob/mkosi.extra/usr/bin/init-container.sh index ce1533b..f76c8f4 100755 --- a/bob/mkosi.extra/usr/bin/init-container.sh +++ b/bob/mkosi.extra/usr/bin/init-container.sh @@ -15,7 +15,6 @@ SEARCHER_INPUT_CHANNEL=27017 echo "Starting $NAME..." su -s /bin/sh searcher -c "cd ~ && podman run -d \ --name $NAME --replace \ - --security-opt apparmor=searcher-container \ -p ${SEARCHER_SSH_PORT}:22 \ -p ${ENGINE_API_PORT}:${ENGINE_API_PORT} \ -p ${EL_P2P_PORT}:${EL_P2P_PORT} \ diff --git a/bob/mkosi.postinst b/bob/mkosi.postinst index d91ffa1..40ead52 100755 --- a/bob/mkosi.postinst +++ b/bob/mkosi.postinst @@ -44,6 +44,10 @@ do ln -sf "/etc/systemd/system/$service" "$BUILDROOT/etc/systemd/system/minimal.target.wants/" done +# Monkey-patch runc to add apparmorProfile to config.json on "create" +mv "$BUILDROOT/usr/bin/runc" "$BUILDROOT/usr/bin/runc.real" +install -m 755 $SRCDIR/bob/runc-apparmor.sh "$BUILDROOT/usr/bin/runc" + # Don't reserve port 22 mkosi-chroot systemctl disable ssh.service ssh.socket mkosi-chroot systemctl mask ssh.service ssh.socket diff --git a/bob/runc-apparmor.sh b/bob/runc-apparmor.sh new file mode 100755 index 0000000..68c880b --- /dev/null +++ b/bob/runc-apparmor.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +# Check if "create" appears anywhere in arguments +if echo "$@" | grep -q " create "; then + # Find bundle path (comes after --bundle) + BUNDLE=$(echo "$@" | sed -n 's/.*--bundle \([^ ]*\).*/\1/p') + + if [ -n "$BUNDLE" ] && [ -f "$BUNDLE/config.json" ]; then + # Add apparmorProfile right after '"process":{' + sed -i 's/"process":{"user":/"process":{"apparmorProfile":"searcher-container","user":/' "$BUNDLE/config.json" + fi +fi + +# Run real runc +exec /usr/bin/runc.real "$@"