Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions base/mkosi.skeleton/init
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions bob/bob.conf
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ Packages=podman
openssh-sftp-server
udev
libsnappy1v5
apparmor

BuildPackages=build-essential
git
Expand Down
12 changes: 11 additions & 1 deletion bob/kernel.config
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,17 @@ 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
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
CONFIG_CRYPTO_USER_API_AEAD=y
CONFIG_CRYPTO_USER_API_AEAD=y
46 changes: 46 additions & 0 deletions bob/mkosi.extra/etc/apparmor.d/searcher-container
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include <tunables/global>

profile searcher-container flags=(attach_disconnected,mediate_deleted) {
#include <abstractions/base>

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/<number>/** 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,
Comment on lines +17 to +34
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not that familiar with apparmor profiles, but maybe we should make deny-all by default and only allowlist what's required?


# 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,
}
4 changes: 2 additions & 2 deletions bob/mkosi.extra/etc/systemd/system/searcher-container.service
Original file line number Diff line number Diff line change
@@ -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
Expand Down
3 changes: 3 additions & 0 deletions bob/mkosi.extra/usr/bin/init-container.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ 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 \
Expand Down
5 changes: 5 additions & 0 deletions bob/mkosi.postinst
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ for service in \
fluent-bit.service \
wait-for-key.service \
searcher-firewall.service \
apparmor.service \
dropbear.service \
lighthouse.service \
searcher-container.service \
Expand All @@ -43,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
Expand Down
15 changes: 15 additions & 0 deletions bob/runc-apparmor.sh
Original file line number Diff line number Diff line change
@@ -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 "$@"