From: Alexander Mikhalitsyn Date: Fri, 31 Mar 2023 11:25:37 +0000 (+0200) Subject: lsm: apparmor: allow to change mount propagation X-Git-Tag: v6.0.0~49^2 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F4295%2Fhead;p=thirdparty%2Flxc.git lsm: apparmor: allow to change mount propagation Long story behind this. Many years ago, Stéphane Graber discovered an issue with apparmor mount rules. Since https://github.com/lxc/lxc/commit/7f2b13275daf68b173474900b1ce2c04105da33f commit ("apparmor: Update mount states handling") it was prohibited to change mount propagation flags, just because adding rules which allow mount propagation user inside the container gets an ability to mount everything [1]. Now with modern systemd versions this problem become more critical than before. For instance, ArchLinux containers fail to start without nesting apparmor profile enabled (because nesting profile effectively just allow all mounts). Of course, that's a security issue. We've also enabled sharing on the container rootfs: https://github.com/lxc/lxc/pull/4229 Now for many workloads it's needed to change propagation flag to private (see https://github.com/canonical/craft-parts/pull/400). Issue: $ lxc-start -F archlinux-test systemd 253-1-arch running in system mode (+PAM +AUDIT -SELINUX -APPARMOR -IMA +SMACK +SECCOMP +GCRYPT +GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP +LIBFDISK +PCRE2 -PWQUALITY +P11KIT -QRENCODE +TPM2 +BZIP2 +LZ4 +XZ +ZLIB +ZSTD +BPF_FRAMEWORK +XKBCOMMON +UTMP -SYSVINIT default-hierarchy=unified) Detected virtualization lxc. Detected architecture x86-64. Welcome to Arch Linux! bpf-lsm: BPF LSM hook not enabled in the kernel, BPF LSM not supported Failed to remount root directory as MS_SLAVE: Permission denied (sd-gens) failed with exit status 1. [!!!!!!] Failed to start up manager. Exiting PID 1... Workaround (unsafe): $ lxc-start -s lxc.apparmor.allow_nesting=1 -s lxc.apparmor.profile=generated -F arch-test John Johansen (Apparmor maintainer) and LXD team worked on fix [2]. It was merged to stable AppArmor 3.0 and 3.1 branches already. There is no stable AppArmor version tag for that, but I think it will be in the AppArmor version 3.0.10. See also: [1] https://bugs.launchpad.net/apparmor/+bug/1597017 [2] https://gitlab.com/apparmor/apparmor/-/merge_requests/333 Fixes: #4280 Signed-off-by: Alexander Mikhalitsyn --- diff --git a/config/apparmor/abstractions/container-base b/config/apparmor/abstractions/container-base index 077476559..69bf6c3b5 100644 --- a/config/apparmor/abstractions/container-base +++ b/config/apparmor/abstractions/container-base @@ -92,15 +92,14 @@ deny /sys/kernel/debug/{,**} rwklx, # allow paths to be made slave, shared, private or unbindable - # FIXME: This currently doesn't work due to the apparmor parser treating those as allowing all mounts. -# mount options=(rw,make-slave) -> **, -# mount options=(rw,make-rslave) -> **, -# mount options=(rw,make-shared) -> **, -# mount options=(rw,make-rshared) -> **, -# mount options=(rw,make-private) -> **, -# mount options=(rw,make-rprivate) -> **, -# mount options=(rw,make-unbindable) -> **, -# mount options=(rw,make-runbindable) -> **, + mount options=(rw,make-slave) -> **, + mount options=(rw,make-rslave) -> **, + mount options=(rw,make-shared) -> **, + mount options=(rw,make-rshared) -> **, + mount options=(rw,make-private) -> **, + mount options=(rw,make-rprivate) -> **, + mount options=(rw,make-unbindable) -> **, + mount options=(rw,make-runbindable) -> **, # allow bind-mounts of anything except /proc, /sys and /dev mount options=(rw,bind) /[^spd]*{,/**}, diff --git a/config/apparmor/abstractions/container-base.in b/config/apparmor/abstractions/container-base.in index 2606fb64c..2ca4e2f7b 100644 --- a/config/apparmor/abstractions/container-base.in +++ b/config/apparmor/abstractions/container-base.in @@ -92,15 +92,14 @@ deny /sys/kernel/debug/{,**} rwklx, # allow paths to be made slave, shared, private or unbindable - # FIXME: This currently doesn't work due to the apparmor parser treating those as allowing all mounts. -# mount options=(rw,make-slave) -> **, -# mount options=(rw,make-rslave) -> **, -# mount options=(rw,make-shared) -> **, -# mount options=(rw,make-rshared) -> **, -# mount options=(rw,make-private) -> **, -# mount options=(rw,make-rprivate) -> **, -# mount options=(rw,make-unbindable) -> **, -# mount options=(rw,make-runbindable) -> **, + mount options=(rw,make-slave) -> **, + mount options=(rw,make-rslave) -> **, + mount options=(rw,make-shared) -> **, + mount options=(rw,make-rshared) -> **, + mount options=(rw,make-private) -> **, + mount options=(rw,make-rprivate) -> **, + mount options=(rw,make-unbindable) -> **, + mount options=(rw,make-runbindable) -> **, # allow bind-mounts of anything except /proc, /sys and /dev mount options=(rw,bind) /[^spd]*{,/**}, diff --git a/src/lxc/lsm/apparmor.c b/src/lxc/lsm/apparmor.c index 685d3b9ef..ba486c63d 100644 --- a/src/lxc/lsm/apparmor.c +++ b/src/lxc/lsm/apparmor.c @@ -113,25 +113,14 @@ static const char AA_PROFILE_BASE[] = " deny /sys/kernel/debug/{,**} rwklx,\n" "\n" " # allow paths to be made dependent, shared, private or unbindable\n" -" # TODO: This currently doesn't work due to the apparmor parser treating those as allowing all mounts.\n" -"# mount options=(rw,make-slave) -> **,\n" -"# mount options=(rw,make-rslave) -> **,\n" -"# mount options=(rw,make-shared) -> **,\n" -"# mount options=(rw,make-rshared) -> **,\n" -"# mount options=(rw,make-private) -> **,\n" -"# mount options=(rw,make-rprivate) -> **,\n" -"# mount options=(rw,make-unbindable) -> **,\n" -"# mount options=(rw,make-runbindable) -> **,\n" -"\n" -"# Allow limited modification of mount propagation\n" -" mount options=(rw,make-slave) -> /,\n" -" mount options=(rw,make-rslave) -> /,\n" -" mount options=(rw,make-shared) -> /,\n" -" mount options=(rw,make-rshared) -> /,\n" -" mount options=(rw,make-private) -> /,\n" -" mount options=(rw,make-rprivate) -> /,\n" -" mount options=(rw,make-unbindable) -> /,\n" -" mount options=(rw,make-runbindable) -> /,\n" +" mount options=(rw,make-slave) -> **,\n" +" mount options=(rw,make-rslave) -> **,\n" +" mount options=(rw,make-shared) -> **,\n" +" mount options=(rw,make-rshared) -> **,\n" +" mount options=(rw,make-private) -> **,\n" +" mount options=(rw,make-rprivate) -> **,\n" +" mount options=(rw,make-unbindable) -> **,\n" +" mount options=(rw,make-runbindable) -> **,\n" "\n" " # allow bind-mounts of anything except /proc, /sys and /dev\n" " mount options=(rw,bind) /[^spd]*{,/**},\n"