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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions