-
Notifications
You must be signed in to change notification settings - Fork 223
Description
TL;DR: it seems like Podman should be able to load custom AppArmor profiles for a rootless container with some minor changes to the way that this library checks for the existence of a profile.
At the moment, Podman doesn't support using an AppArmor profile in a rootless container. As it turns out, though, the only thing that Podman needs root permissions for if you want to use a custom AppArmor profile is reading /sys/kernel/security/apparmor/profiles
:
common/pkg/apparmor/apparmor_linux.go
Line 146 in f187752
file, err := os.Open("/sys/kernel/security/apparmor/profiles") |
This check is a convenient way to determine whether the provided AppArmor profile actually exists, but it isn't strictly necessary. The "normal" way of making this check (as in, the method used by aa-exec
) is to try to write the profile to /proc/self/attr/exec
or /proc/self/attr/apparmor/exec
(AppArmor docs) and see if the write fails. E.g., suppose we have the following AppArmor profile:
#include <tunables/global>
profile my-profile {
#include <abstractions/base>
/bin/ls rix,
/usr/ r,
}
The following code just loads the AppArmor profile specified by the AA_PROFILE
environmental variable and then runs /bin/ls
:
// main.go
package main
import (
"fmt"
"os"
"os/exec"
)
func main() {
profile := os.Getenv("AA_PROFILE")
file, err := os.OpenFile("/proc/self/attr/apparmor/exec", os.O_WRONLY, 0)
if err != nil {
fmt.Printf("error = '%v'\n", err)
return
}
if _, err = fmt.Fprintf(file, "exec %s", profile); err != nil {
fmt.Printf("error = '%v'\nthe profile '%s' does not exist\n", err, profile)
return
}
if err = file.Close(); err != nil {
fmt.Printf("error = '%v'", err)
return
}
cmd := exec.Command("/bin/ls", os.Args[1:]...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Run()
}
The check on fmt.Fprintf
tells us whether or not the provided AppArmor profile exists:
# Runs successfully
$ AA_PROFILE=my-profile ./main /usr
bin games include lib lib64 libexec libx32 local sbin share src
# Generates an error since the profile doesn't allow us to read /var
$ AA_PROFILE=my-profile ./main /var
/bin/ls: cannot open directory '/var': Permission denied
# Generates an error since the profile 'foobarbaz' doesn't exist
$ AA_PROFILE=foobarbaz ./main /usr
error = 'write /proc/self/attr/apparmor/exec: no such file or directory'
the profile 'foobarbaz' does not exist
So it should be possible to add AppArmor support for rootless containers by dropping the check to /sys/kernel/security/apparmor/profiles
, and instead determining whether the profile exists based on whether the write to /proc/self/attr{,/apparmor}/exec
is successful.