diff options
author | Marco Vedovati <mvedovati@suse.com> | 2018-08-09 13:09:59 +0200 |
---|---|---|
committer | Atomic Bot <atomic-devel@projectatomic.io> | 2018-08-24 17:08:11 +0000 |
commit | 72e41c81aaa2c5ea39f7b5bd1c0654937703a346 (patch) | |
tree | 779314912b63eed2e4d97d872982386745ee54fe /cmd | |
parent | af9f83f11c9b92ea806b33b75337de7e5d93592d (diff) | |
download | podman-72e41c81aaa2c5ea39f7b5bd1c0654937703a346.tar.gz podman-72e41c81aaa2c5ea39f7b5bd1c0654937703a346.tar.bz2 podman-72e41c81aaa2c5ea39f7b5bd1c0654937703a346.zip |
Do not try to enable AppArmor in rootless mode
When in rootless mode it's not possible to load profiles or
check which profiles are loaded.
Added a few baseline tests to check all possible cases.
Signed-off-by: Marco Vedovati <mvedovati@suse.com>
Closes: #1250
Approved by: mheon
Diffstat (limited to 'cmd')
-rw-r--r-- | cmd/podman/create.go | 122 |
1 files changed, 73 insertions, 49 deletions
diff --git a/cmd/podman/create.go b/cmd/podman/create.go index 3429c4d97..95b7a8bed 100644 --- a/cmd/podman/create.go +++ b/cmd/podman/create.go @@ -15,6 +15,7 @@ import ( ann "github.com/containers/libpod/pkg/annotations" "github.com/containers/libpod/pkg/apparmor" "github.com/containers/libpod/pkg/inspect" + "github.com/containers/libpod/pkg/rootless" cc "github.com/containers/libpod/pkg/spec" "github.com/containers/libpod/pkg/util" libpodVersion "github.com/containers/libpod/version" @@ -148,52 +149,20 @@ func createCmd(c *cli.Context) error { return nil } -func parseSecurityOpt(config *cc.CreateConfig, securityOpts []string) error { - var ( - labelOpts []string - err error - ) - - if config.PidMode.IsHost() { - labelOpts = append(labelOpts, label.DisableSecOpt()...) - } else if config.PidMode.IsContainer() { - ctr, err := config.Runtime.LookupContainer(config.PidMode.Container()) - if err != nil { - return errors.Wrapf(err, "container %q not found", config.PidMode.Container()) - } - labelOpts = append(labelOpts, label.DupSecOpt(ctr.ProcessLabel())...) - } - - if config.IpcMode.IsHost() { - labelOpts = append(labelOpts, label.DisableSecOpt()...) - } else if config.IpcMode.IsContainer() { - ctr, err := config.Runtime.LookupContainer(config.IpcMode.Container()) - if err != nil { - return errors.Wrapf(err, "container %q not found", config.IpcMode.Container()) - } - labelOpts = append(labelOpts, label.DupSecOpt(ctr.ProcessLabel())...) - } - - for _, opt := range securityOpts { - if opt == "no-new-privileges" { - config.NoNewPrivs = true - } else { - con := strings.SplitN(opt, "=", 2) - if len(con) != 2 { - return fmt.Errorf("Invalid --security-opt 1: %q", opt) - } - - switch con[0] { - case "label": - labelOpts = append(labelOpts, con[1]) - case "apparmor": - config.ApparmorProfile = con[1] - case "seccomp": - config.SeccompProfilePath = con[1] - default: - return fmt.Errorf("Invalid --security-opt 2: %q", opt) - } +// Checks if a user-specified AppArmor profile is loaded, or loads the default profile if +// AppArmor is enabled. +// Any interaction with AppArmor requires root permissions. +func loadAppArmor(config *cc.CreateConfig) error { + if rootless.IsRootless() { + noAAMsg := "AppArmor security is not available in rootless mode" + switch config.ApparmorProfile { + case "": + logrus.Warn(noAAMsg) + case "unconfined": + default: + return fmt.Errorf(noAAMsg) } + return nil } if config.ApparmorProfile == "" && apparmor.IsEnabled() { @@ -233,23 +202,78 @@ func parseSecurityOpt(config *cc.CreateConfig, securityOpts []string) error { } } else if config.ApparmorProfile != "" && config.ApparmorProfile != "unconfined" { if !apparmor.IsEnabled() { - return fmt.Errorf("profile specified but AppArmor is disabled on the host") + return fmt.Errorf("Profile specified but AppArmor is disabled on the host") } isLoaded, err := apparmor.IsLoaded(config.ApparmorProfile) if err != nil { switch err { case apparmor.ErrApparmorUnsupported: - return fmt.Errorf("profile specified but AppArmor is not supported") + return fmt.Errorf("Profile specified but AppArmor is not supported") default: - return fmt.Errorf("error checking if AppArmor profile is loaded: %v", err) + return fmt.Errorf("Error checking if AppArmor profile is loaded: %v", err) } } if !isLoaded { - return fmt.Errorf("specified AppArmor profile '%s' is not loaded", config.ApparmorProfile) + return fmt.Errorf("The specified AppArmor profile '%s' is not loaded", config.ApparmorProfile) } } + return nil +} + +func parseSecurityOpt(config *cc.CreateConfig, securityOpts []string) error { + var ( + labelOpts []string + err error + ) + + if config.PidMode.IsHost() { + labelOpts = append(labelOpts, label.DisableSecOpt()...) + } else if config.PidMode.IsContainer() { + ctr, err := config.Runtime.LookupContainer(config.PidMode.Container()) + if err != nil { + return errors.Wrapf(err, "container %q not found", config.PidMode.Container()) + } + labelOpts = append(labelOpts, label.DupSecOpt(ctr.ProcessLabel())...) + } + + if config.IpcMode.IsHost() { + labelOpts = append(labelOpts, label.DisableSecOpt()...) + } else if config.IpcMode.IsContainer() { + ctr, err := config.Runtime.LookupContainer(config.IpcMode.Container()) + if err != nil { + return errors.Wrapf(err, "container %q not found", config.IpcMode.Container()) + } + labelOpts = append(labelOpts, label.DupSecOpt(ctr.ProcessLabel())...) + } + + for _, opt := range securityOpts { + if opt == "no-new-privileges" { + config.NoNewPrivs = true + } else { + con := strings.SplitN(opt, "=", 2) + if len(con) != 2 { + return fmt.Errorf("Invalid --security-opt 1: %q", opt) + } + + switch con[0] { + case "label": + labelOpts = append(labelOpts, con[1]) + case "apparmor": + config.ApparmorProfile = con[1] + case "seccomp": + config.SeccompProfilePath = con[1] + default: + return fmt.Errorf("Invalid --security-opt 2: %q", opt) + } + } + } + + if err := loadAppArmor(config); err != nil { + return err + } + if config.SeccompProfilePath == "" { if _, err := os.Stat(libpod.SeccompOverridePath); err == nil { config.SeccompProfilePath = libpod.SeccompOverridePath |