Skip to content

Commit 55d217f

Browse files
committed
Allow rootless containers to use AppArmor profiles
Previously, Podman would print an error if you tried to run a container with an AppArmor profile as a non-root user, e.g. $ podman run --security-opt apparmor=my-profile ... Error: Apparmor profile "my-profile" specified, but Apparmor is not enabled on this system In fact, the only thing that Podman needs root privileges for is reading /sys/kernel/security/apparmor/profiles to see if the profile is already loaded, which isn't strictly necessary. This commit removes the 'IsLoaded()' check that occurs when you try to specify an AppArmor profile as a non-root user, as well as the other checks in pkg/apparmor/ for whether the program is running as UID 0. The check for whether the AppArmor profile is loaded should now be deferred to the container runtime at the point where it writes to either /proc/self/attr/exec or /proc/self/attr/apparmor/exec, since the write should fail if the profile is not loaded. Closes #958. Signed-off-by: kernelmethod <17100608+kernelmethod@users.noreply.github.com>
1 parent ac6671d commit 55d217f

File tree

3 files changed

+4
-36
lines changed

3 files changed

+4
-36
lines changed

pkg/apparmor/apparmor.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,4 @@ const (
1717
var (
1818
// ErrApparmorUnsupported indicates that AppArmor support is not supported.
1919
ErrApparmorUnsupported = errors.New("AppArmor is not supported")
20-
// ErrApparmorRootless indicates that AppArmor support is not supported in rootless mode.
21-
ErrApparmorRootless = errors.New("AppArmor is not supported in rootless mode")
2220
)

pkg/apparmor/apparmor_linux.go

Lines changed: 4 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import (
1414
"text/template"
1515

1616
"github.com/containers/common/pkg/apparmor/internal/supported"
17-
"github.com/containers/storage/pkg/unshare"
1817
runcaa "github.com/opencontainers/runc/libcontainer/apparmor"
1918
"github.com/pkg/errors"
2019
"github.com/sirupsen/logrus"
@@ -77,10 +76,6 @@ func macroExists(m string) bool {
7776
// InstallDefault generates a default profile and loads it into the kernel
7877
// using 'apparmor_parser'.
7978
func InstallDefault(name string) error {
80-
if unshare.IsRootless() {
81-
return ErrApparmorRootless
82-
}
83-
8479
p := profileData{
8580
Name: name,
8681
}
@@ -137,12 +132,9 @@ func DefaultContent(name string) ([]byte, error) {
137132
}
138133

139134
// IsLoaded checks if a profile with the given name has been loaded into the
140-
// kernel.
135+
// kernel. This function checks for the existence of a profile by reading
136+
// /sys/kernel/security/apparmor/profiles, and hence requires root permissions.
141137
func IsLoaded(name string) (bool, error) {
142-
if name != "" && unshare.IsRootless() {
143-
return false, errors.Wrapf(ErrApparmorRootless, "cannot load AppArmor profile %q", name)
144-
}
145-
146138
file, err := os.Open("/sys/kernel/security/apparmor/profiles")
147139
if err != nil {
148140
if os.IsNotExist(err) {
@@ -238,25 +230,13 @@ func parseAAParserVersion(output string) (int, error) {
238230
// CheckProfileAndLoadDefault checks if the specified profile is loaded and
239231
// loads the DefaultLibpodProfile if the specified on is prefixed by
240232
// DefaultLipodProfilePrefix. This allows to always load and apply the latest
241-
// default AppArmor profile. Note that AppArmor requires root. If it's a
242-
// default profile, return DefaultLipodProfilePrefix, otherwise the specified
243-
// one.
233+
// default AppArmor profile. If it's a default profile, return
234+
// DefaultLipodProfilePrefix, otherwise the specified one.
244235
func CheckProfileAndLoadDefault(name string) (string, error) {
245236
if name == "unconfined" {
246237
return name, nil
247238
}
248239

249-
// AppArmor is not supported in rootless mode as it requires root
250-
// privileges. Return an error in case a specific profile is specified.
251-
if unshare.IsRootless() {
252-
if name != "" {
253-
return "", errors.Wrapf(ErrApparmorRootless, "cannot load AppArmor profile %q", name)
254-
} else {
255-
logrus.Debug("Skipping loading default AppArmor profile (rootless mode)")
256-
return "", nil
257-
}
258-
}
259-
260240
// Check if AppArmor is disabled and error out if a profile is to be set.
261241
if !runcaa.IsEnabled() {
262242
if name == "" {
@@ -271,13 +251,6 @@ func CheckProfileAndLoadDefault(name string) (string, error) {
271251
} else if !strings.HasPrefix(name, ProfilePrefix) {
272252
// If the specified name is not a default one, ignore it and return the
273253
// name.
274-
isLoaded, err := IsLoaded(name)
275-
if err != nil {
276-
return "", errors.Wrapf(err, "verify if profile %s is loaded", name)
277-
}
278-
if !isLoaded {
279-
return "", errors.Errorf("AppArmor profile %q specified but not loaded", name)
280-
}
281254
return name, nil
282255
}
283256

pkg/apparmor/internal/supported/supported.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,6 @@ func NewAppArmorVerifier() *ApparmorVerifier {
4040
// - AppArmor is disabled by the host system
4141
// - the `apparmor_parser` binary is not discoverable
4242
func (a *ApparmorVerifier) IsSupported() error {
43-
if a.impl.UnshareIsRootless() {
44-
return errors.New("AppAmor is not supported on rootless containers")
45-
}
4643
if !a.impl.RuncIsEnabled() {
4744
return errors.New("AppArmor not supported by the host system")
4845
}

0 commit comments

Comments
 (0)