Skip to content

add apparmor support#4182

Draft
ChrisIgel wants to merge 1 commit intolinuxkit:masterfrom
ChrisIgel:apparmor
Draft

add apparmor support#4182
ChrisIgel wants to merge 1 commit intolinuxkit:masterfrom
ChrisIgel:apparmor

Conversation

@ChrisIgel
Copy link
Contributor

- What I did
Enabled AppArmor in the kernel, load it by default and allow the AppArmor profile to be configured per container.

- How I did it
Update the kernel config for 6.6.x (x86) and the LinuxKit YAML schema.

- How to verify it
Start a container with a /sys:/sys mount and the apparmor-tools installed and run aa-status should show AppArmor is loaded/active.

- Description for the changelog
Enable the AppArmor modules in the kernel, load it by default and allow configuring the AppArmor profile that should be applied for each container individually.

gh-108

Enable the AppArmor modules in the kernel, load it by default and allow
configuring the AppArmor profile that should be applied for each
container individually.

linuxkitgh-108

Signed-off-by: Chris Irrgang <chris.irrgang@gmx.de>
@ChrisIgel
Copy link
Contributor Author

I had some trouble updating the arm64 and riscv configs but I would expect the changes to be the same. When I updated them with menuconfig I got additional unexpected changes so I left them out for now.

@deitch
Copy link
Collaborator

deitch commented Oct 10, 2025

Let's get this to move forward. I have some suggestions and (more) questions.

First, I am strongly in favour of this, as long as it is optional. We don't want apparmor to be enabled by surprise. From what I understood from what you wrote in the linked issue, it is compiled into the kernel but not enabled unless you add the onboot container or some other method, is that correct? So this becomes an option? That would make it good.

We definitely need the changes in riscv64 and arm64 as well.

There is a process for updating the kernel, documented in kernels.md. There are updated versions of kernels regularly, so it likely is easiest to take the most recent version of 6.6.x and update to it while adding these changes. It all is documented there, including how to update dependencies in the repo. I know you cannot push out the changes, but I can take care of that when the rest is done.

Of course, if you want to cut a new series, I won't complain. 😁

Next, can you explain what the changes to moby/config.go are? I see you including the apparmor profile on each container's OCI config, which makes sense. But what is put in there? Where is it controlled and what is the default?

@deitch
Copy link
Collaborator

deitch commented Oct 10, 2025

Last, are you on docker slack? Do you mind pinging me there? Thanks!

@ChrisIgel
Copy link
Contributor Author

No, I'm not in the Docker Slack (or Slack in general), but that could be changed :)

So with the current changes the AppArmor module would be enabled automatically but it won't do anything until some policies are loaded from user space. It can also be fully optional (i.e. the module isn't loaded at all) if we don't set the CONFIG_DEFAULT_SECURITY_APPARMOR=y and don't add apparmor to the CONFIG_LSM. It then has to be manually enabled during runtime via the cmdline by setting security=apparmor. The latter would probably be the method we want.

I'll try updating the riscv64 and arm64 versions as well. Also I can create a new kernel series 6.12.x, that I already introduced to our customers anyway. Should I then deprecate the old ones or also update them with AppArmor support?

So the change in moby/config.go technically isn't mandatory but it makes it really easy to enforce AppArmor profiles for container as containerd natively supports it (otherwise you would need the AppArmor tools in the container and execute your code with aa-exec for example). You would put an AppArmor profile name in there. So let's say you have created the following AppArmor profile:

#include <tunables/global>

profile example-profile-name flags=(enforce) {
  #include <abstractions/base>

  # Deny all file writes.
  deny /** w,
}

You would then put example-profile-name in there if you want the container to be restricted by this profile. Of course the profile would have to be loaded somehow beforehand, e.g. via calling the apparmor_parser. This could and maybe even should be done by the current init container even before the onboot containers start. Alternatively, we could provide a simple onboot container with the AppArmor tools, that can be specified in the YAML as first container and loads the profiles.

@deitch
Copy link
Collaborator

deitch commented Oct 12, 2025

No, I'm not in the Docker Slack (or Slack in general), but that could be changed

Definitely join up. Or any of the other slacks (I am on Docker community, CNCF community, Kubernetes community, lfedge community, I can keep going; not to mention databack for the open source database backup software I manage). Pick one if you are up for it and ping me?

@deitch
Copy link
Collaborator

deitch commented Oct 12, 2025

So with the current changes the AppArmor module would be enabled automatically but it won't do anything until some policies are loaded from user space. It can also be fully optional (i.e. the module isn't loaded at all) if we don't set the CONFIG_DEFAULT_SECURITY_APPARMOR=y and don't add apparmor to the CONFIG_LSM. It then has to be manually enabled during runtime via the cmdline by setting security=apparmor. The latter would probably be the method we want

Actually, I think the first option you described - and what you did here - is best. Make it available, but not enabled until policies are loaded - makes sense. I would say stick with what you did.

I'll try updating the riscv64 and arm64 versions as well. Also I can create a new kernel series 6.12.x,

Thanks that sounds solid.

that I already introduced to our customers anyway.

Which I want to hear more about (among other things to discuss via DM in Slack).

Should I then deprecate the old ones or also update them with AppArmor support?

I wouldn't go backwards for this. Leave the old ones around, don't bother building again for them. Maybe 6.6 would stay around. I guess that is deprecation?

So the change in moby/config.go technically isn't mandatory but it makes it really easy to enforce AppArmor profiles for container as containerd natively supports it

Got it. That makes sense, so go for it.

You would then put example-profile-name in there

Where is "in there"?

This sounds like it is the kind of thing you would want either on the build.yml for an individual container, or as part of the linuxkit.yml definition for an onboot/services/onshutdown container. Am I reading this correctly?

If so, then I don't think you need a change to the init container, which just starts up containerd (services) and runc (onboot/onshutdown). It is at build time (lkt build linuxkit.yml) that it lays them all out and sets up the container config json. It would be in there.

Either way, I still think one step at a time:

  1. Get kernel support, even if unused. That is the harder change.
  2. Add it to linuxkit build, along with a sample and tests. That has more parts but is an easier change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments