diff options
Diffstat (limited to 'cmd/podman/create.go')
-rw-r--r-- | cmd/podman/create.go | 132 |
1 files changed, 42 insertions, 90 deletions
diff --git a/cmd/podman/create.go b/cmd/podman/create.go index dae429047..065d08df4 100644 --- a/cmd/podman/create.go +++ b/cmd/podman/create.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "io/ioutil" "os" "path/filepath" "strconv" @@ -15,13 +16,11 @@ import ( "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/image" ann "github.com/containers/libpod/pkg/annotations" - "github.com/containers/libpod/pkg/apparmor" "github.com/containers/libpod/pkg/inspect" ns "github.com/containers/libpod/pkg/namespaces" "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" "github.com/docker/docker/pkg/signal" "github.com/docker/go-connections/nat" "github.com/docker/go-units" @@ -146,7 +145,7 @@ func createContainer(c *cli.Context, runtime *libpod.Runtime) (*libpod.Container return nil, nil, err } - ctr, err := createContainerFromCreateConfig(runtime, createConfig, ctx) + ctr, err := createContainerFromCreateConfig(runtime, createConfig, ctx, nil) if err != nil { return nil, nil, err } @@ -162,83 +161,9 @@ func createContainer(c *cli.Context, runtime *libpod.Runtime) (*libpod.Container return ctr, createConfig, nil } -// 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() { - // Unless specified otherwise, make sure that the default AppArmor - // profile is installed. To avoid redundantly loading the profile - // on each invocation, check if it's loaded before installing it. - // Suffix the profile with the current libpod version to allow - // loading the new, potentially updated profile after an update. - profile := fmt.Sprintf("%s-%s", apparmor.DefaultLibpodProfile, libpodVersion.Version) - - loadProfile := func() error { - isLoaded, err := apparmor.IsLoaded(profile) - if err != nil { - return err - } - if !isLoaded { - err = apparmor.InstallDefault(profile) - if err != nil { - return err - } - - } - return nil - } - - if err := loadProfile(); err != nil { - switch err { - case apparmor.ErrApparmorUnsupported: - // do not set the profile when AppArmor isn't supported - logrus.Debugf("AppArmor is not supported: setting empty profile") - default: - return err - } - } else { - logrus.Infof("Sucessfully loaded AppAmor profile '%s'", profile) - config.ApparmorProfile = profile - } - } else if config.ApparmorProfile != "" && config.ApparmorProfile != "unconfined" { - if !apparmor.IsEnabled() { - 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") - default: - return fmt.Errorf("Error checking if AppArmor profile is loaded: %v", err) - } - } - if !isLoaded { - 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() { @@ -248,7 +173,11 @@ func parseSecurityOpt(config *cc.CreateConfig, securityOpts []string) error { if err != nil { return errors.Wrapf(err, "container %q not found", config.PidMode.Container()) } - labelOpts = append(labelOpts, label.DupSecOpt(ctr.ProcessLabel())...) + secopts, err := label.DupSecOpt(ctr.ProcessLabel()) + if err != nil { + return errors.Wrapf(err, "failed to duplicate label %q ", ctr.ProcessLabel()) + } + labelOpts = append(labelOpts, secopts...) } if config.IpcMode.IsHost() { @@ -258,7 +187,11 @@ func parseSecurityOpt(config *cc.CreateConfig, securityOpts []string) error { if err != nil { return errors.Wrapf(err, "container %q not found", config.IpcMode.Container()) } - labelOpts = append(labelOpts, label.DupSecOpt(ctr.ProcessLabel())...) + secopts, err := label.DupSecOpt(ctr.ProcessLabel()) + if err != nil { + return errors.Wrapf(err, "failed to duplicate label %q ", ctr.ProcessLabel()) + } + labelOpts = append(labelOpts, secopts...) } for _, opt := range securityOpts { @@ -283,10 +216,6 @@ func parseSecurityOpt(config *cc.CreateConfig, securityOpts []string) error { } } - if err := loadAppArmor(config); err != nil { - return err - } - if config.SeccompProfilePath == "" { if _, err := os.Stat(libpod.SeccompOverridePath); err == nil { config.SeccompProfilePath = libpod.SeccompOverridePath @@ -304,7 +233,7 @@ func parseSecurityOpt(config *cc.CreateConfig, securityOpts []string) error { } } config.LabelOpts = labelOpts - return err + return nil } // isPortInPortBindings determines if an exposed host port is in user @@ -501,6 +430,16 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim } if c.IsSet("pod") { if strings.HasPrefix(originalPodName, "new:") { + if rootless.IsRootless() { + // To create a new pod, we must immediately create the userns. + became, ret, err := rootless.BecomeRootInUserNS() + if err != nil { + return nil, err + } + if became { + os.Exit(ret) + } + } // pod does not exist; lets make it var podOptions []libpod.PodCreateOption podOptions = append(podOptions, libpod.WithPodName(podName), libpod.WithInfraContainer(), libpod.WithPodCgroups()) @@ -809,6 +748,16 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim Syslog: c.GlobalBool("syslog"), } + if c.Bool("init") { + initPath := c.String("init-path") + if initPath == "" { + initPath = runtime.GetConfig().InitPath + } + if err := config.AddContainerInitBinary(initPath); err != nil { + return nil, err + } + } + if config.Privileged { config.LabelOpts = label.DisableSecOpt() } else { @@ -855,11 +804,15 @@ func joinOrCreateRootlessUserNamespace(createConfig *cc.CreateConfig, runtime *l if s != libpod.ContainerStateRunning && s != libpod.ContainerStatePaused { continue } - pid, err := prevCtr.PID() + data, err := ioutil.ReadFile(prevCtr.Config().ConmonPidFile) if err != nil { - return false, -1, err + return false, -1, errors.Wrapf(err, "cannot read conmon PID file %q", prevCtr.Config().ConmonPidFile) } - return rootless.JoinNS(uint(pid)) + conmonPid, err := strconv.Atoi(string(data)) + if err != nil { + return false, -1, errors.Wrapf(err, "cannot parse PID %q", data) + } + return rootless.JoinDirectUserAndMountNS(uint(conmonPid)) } } @@ -887,17 +840,16 @@ func joinOrCreateRootlessUserNamespace(createConfig *cc.CreateConfig, runtime *l return rootless.BecomeRootInUserNS() } -func createContainerFromCreateConfig(r *libpod.Runtime, createConfig *cc.CreateConfig, ctx context.Context) (*libpod.Container, error) { +func createContainerFromCreateConfig(r *libpod.Runtime, createConfig *cc.CreateConfig, ctx context.Context, pod *libpod.Pod) (*libpod.Container, error) { runtimeSpec, err := cc.CreateConfigToOCISpec(createConfig) if err != nil { return nil, err } - options, err := createConfig.GetContainerCreateOptions(r) + options, err := createConfig.GetContainerCreateOptions(r, pod) if err != nil { return nil, err } - became, ret, err := joinOrCreateRootlessUserNamespace(createConfig, r) if err != nil { return nil, err |