Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start unprivileged container without root with an apparmor profile #4358

Open
raldone01 opened this issue Oct 11, 2023 · 8 comments
Open

Start unprivileged container without root with an apparmor profile #4358

raldone01 opened this issue Oct 11, 2023 · 8 comments
Labels
Incomplete Waiting on more information from reporter

Comments

@raldone01
Copy link

raldone01 commented Oct 11, 2023

Required information

  • Distribution: arch linux
  • Distribution version: rolling
❯ lxc-start --version
5.0.3
❯ uname -a
Linux argon 6.5.6-arch2-1 #1 SMP PREEMPT_DYNAMIC Sat, 07 Oct 2023 08:14:55 +0000 x86_64 GNU/Linux
❯ cat /proc/self/cgroup
0::/user.slice/user-1000.slice/session-3.scope

Issue description

Running an unprivileged user with app armor confinement fails.
Is it possible to run an unprivileged container with confinement?

# whoami
root
# lxc-create -n lxc-arch -t download -- --dist archlinux --release current --arch amd64
# lxc-start -s lxc.apparmor.profile=generated -n lxc-arch -F
Working and starts fine.
❯ su main # unprivileged_user
❯ lxc-create -n lxc-arch -t download -- --dist archlinux --release current --arch amd64
❯ lxc-start -s lxc.apparmor.profile=generated -n lxc-arch -F
lxc-start: lxc-arch: ../src/lxc/lsm/apparmor.c: make_apparmor_namespace: 869 Permission denied - Error creating AppArmor namespace: /sys/kernel/security/apparmor/policy/namespaces/lxc-lxc-arch_<-home-main-.local-share-lxc>
lxc-start: lxc-arch: ../src/lxc/lsm/apparmor.c: apparmor_prepare: 1088 Failed to load generated AppArmor profile
lxc-start: lxc-arch: ../src/lxc/start.c: lxc_init: 876 Failed to initialize LSM
lxc-start: lxc-arch: ../src/lxc/start.c: __lxc_start: 2027 Failed to initialize container "lxc-arch"
lxc-start: lxc-arch: ../src/lxc/tools/lxc_start.c: main: 306 The container failed to start
lxc-start: lxc-arch: ../src/lxc/tools/lxc_start.c: main: 311 Additional information can be obtained by setting the --logfile and --logpriority options
❯ lxc-start -s lxc.apparmor.profile=unconfined -n lxc-arch -F
Working and starts fine.
@raldone01 raldone01 changed the title Start unpriviledged container without root with an apparmor profile Start unprivileged container without root with an apparmor profile Oct 11, 2023
@mihalicyn
Copy link
Member

Hi @raldone01

Sorry for long delay with reply.

Running an unprivileged user with app armor confinement fails.
Is it possible to run an unprivileged container with confinement?

You need to have CAP_MAC_ADMIN in the current user namespace to manage policies (https://github.com/torvalds/linux/blob/ffd2cb6b718e189e7e2d5d0c19c25611f92e061a/security/apparmor/policy.c#L839)

So, no, you can't manage apparmor from an unprivileged user. As far as I remember there is a feature (apparmor stacking) that allows you to create a stacked profiles inside the user namespace. But it is another story anyways.

If you are unprivileged, there is not so much sense to user AppArmor at all.

Why do you want to do that?

@mihalicyn mihalicyn added the Incomplete Waiting on more information from reporter label Feb 23, 2024
@raldone01
Copy link
Author

raldone01 commented Feb 23, 2024

It has been a while.
Thanks for getting back to me though.

I don't remember the exact reasons but I think I was under the impression that apparmor confinement was necessary for safe operation.

So using an unprivileged user with USER_NS was less safe than using a privileged user with apparmor confinement.
Ideally both techniques should be combined.

Lets say I host a webserver in a LXC container and an attacker gains RCE on it.
Which is safer?

  • A: Container with privileged user and confinement.
  • B: Container with unprivileged user (USER_NS) and unconfined.
  • C: Container with privileged user (USER_NS) and confinement. (Is that even possible?)

No vulnerable mounts/reachable services exist...

@mihalicyn
Copy link
Member

So using an unprivileged user with USER_NS was less safe than using a privileged user with apparmor confinement.

I don't think so. unprivileged user + user namespace is a very-very safe thing. And this is an upstream Linux kernel default option, so all the vulnerability researchers are paying attention to this configuration all the time. That's why this combo has so big history of CVEs. But that's a sign of a big attention to it! It does not mean that this is an ugly combo from a security standpoint.

If we speak about AppArmor, I makes sense to say that AppArmor is just a specific LSM module for Linux kernel. Not so many eyes looking at it and not so many researchers as a consequence.

It's a classical https://en.wikipedia.org/wiki/Survivorship_bias ;-)

Which is safer?

A: Container with privileged user and confinement.

You mean "privileged container" right? Privileged container means that container is not using user namespace at all.
It means that root inside the container IS root on the host. But it's confined with AppArmor.

B: Container with unprivileged user (USER_NS) and unconfined.

Yep, it means that root inside the container, is just a regular user on the host. All the security tricks in this case comes
from the vanilla upstream Linux kernel, without any custom things like AppArmor. (Very popular and well tested!)

C: Container with privileged user (USER_NS) and confinement. (Is that even possible?)

hm, yep, there is a confusion about naming. Let's try to sort this out:

  • privileged container means that container does NOT use user namespaces
  • privileged user (usually) means that user has a capabilities on the host (in the initial user namespace)

Once you create a user namespace, then you lose all the capabilities in the initial user namespace. For example:

# create user namespace and enter to it
root@host $ unshare -Ur

or

# create user namespace and enter to it
user@host $ unshare -Ur

There is no difference from the capabilities perspective at all! The only difference would be that in first case uid 0 inside the user namespace will be uid 0 outside. In 2nd case uid 0 inside the user namespace will be uid 1000 (if a user "user" has uid 1000). But from the permissions perspective there is no difference at all! Because uid 0 does not mean that you have a power of root. Power of root is about having capabilities, not UID!

Let's get back to your list of options A, B, C and ordering. I can't say anything about C because it's not clear what it means.
But I definitely say that B is more secure than A. Using unconfined user namespace is safer.

I'm pretty sure that Stéphane has something to add :-)
cc @stgraber

@raldone01
Copy link
Author

raldone01 commented Feb 23, 2024

My terminology was not clear. I wasn't talking about privileged containers at all.
Just about the user launching them.

Let me try again:

Lets say I host a webserver in a LXC container and an attacker gains RCE on it.
Which is safer?

A: Container launched by a privileged user and apparmor confinement.
B: Container launched by an unprivileged user (subuid/subgid) and unconfined.
C: Container launched by a privileged user (subuid/subgid) and confinement. (Is that even possible?)

No vulnerable mounts/reachable services exist...

With [C] I meant to use subui/subgids with the root user and launching containers with it.


I think for my use case option [B] is best then.
You are right in pointing out the survivor bias.
So unintuitive :-D.


Maybe a short sentence in the docs would be nice mentioning that unconfined is not automatically unsafe if combined with an unprivileged user and subuid/subgids.

More information is always appreciated.

@hallyn
Copy link
Member

hallyn commented Feb 23, 2024

Thanks for the clarification - fwiw, [a] is imo not safe. [c] certainly is possible. There is also [D]: Container launched by un unpriv user and confined. That is, of course, the safest.

@raldone01
Copy link
Author

raldone01 commented Feb 23, 2024

So to achieve [D] I would have to give the unprivileged user the CAP_MAC_ADMIN privilege right? Otherwise I run into my initial issue.
Do you happen to know how I can give my user the CAP_MAC_ADMIN.
Is it a bad idea to give this to my regular user account?

Edit and a bit off topic I guess:
I read up that users can't have capabilities.
Where in the systemd chain would I have to inject capabilities for my user to have?
Maybe I could copy the shell to a separate directory for my user and set the caps on it...

@hallyn
Copy link
Member

hallyn commented Feb 23, 2024

Sorry I probably shouldn't have jumped in.

Yes, to load newly generated or ad-hoc policies requires CAP_MAC_ADMIN, and you do not want to give that to users.

What you can do is load custom policies for them in advance. Then the users can start containers using those policies at any time. This is generally the norm: unprivileged containers are not actually un-confined, but are confined by a rather general policy.

@raldone01
Copy link
Author

raldone01 commented Feb 23, 2024

Thanks. I learned a few things.

So if I go back to my original issue:

  • lxc-start -s lxc.apparmor.profile=generated-n lxc-arch -F - Does not work with main user.
  • lxc-start -s lxc.apparmor.profile=unconfined -n lxc-arch -F - Works but I assume is completely unconfined.

How would I start a container with this general profile?

lxc-start -s lxc.apparmor.profile=? -n lxc-arch -F

Simply omitting -s lxc.apparmor.profile yields:

❯ lxc-start -n lxc-arch -F
systemd 255.3-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 fork off sandboxing environment for executing generators: Protocol error
[!!!!!!] Failed to start up manager.
Exiting PID 1...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Incomplete Waiting on more information from reporter
Development

No branches or pull requests

3 participants