Skip to content

Allow rootless containers to use AppArmor profiles #958

@kernelmethod

Description

@kernelmethod

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:

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions