diff options
-rw-r--r-- | cmd/podman/create.go | 8 | ||||
-rw-r--r-- | docs/podman-create.1.md | 5 | ||||
-rw-r--r-- | docs/podman-run.1.md | 5 | ||||
-rw-r--r-- | pkg/spec/createconfig.go | 8 | ||||
-rw-r--r-- | pkg/spec/parse.go | 15 | ||||
-rw-r--r-- | pkg/spec/spec.go | 21 |
6 files changed, 53 insertions, 9 deletions
diff --git a/cmd/podman/create.go b/cmd/podman/create.go index 6fe68ebab..c7982d551 100644 --- a/cmd/podman/create.go +++ b/cmd/podman/create.go @@ -369,12 +369,12 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim tty := c.Bool("tty") pidMode := container.PidMode(c.String("pid")) - if !pidMode.Valid() { + if !cc.IsNS(string(pidMode)) && !pidMode.Valid() { return nil, errors.Errorf("--pid %q is not valid", c.String("pid")) } usernsMode := container.UsernsMode(c.String("userns")) - if !usernsMode.Valid() { + if !cc.IsNS(string(usernsMode)) && !usernsMode.Valid() { return nil, errors.Errorf("--userns %q is not valid", c.String("userns")) } @@ -389,11 +389,11 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim } utsMode := container.UTSMode(c.String("uts")) - if !utsMode.Valid() { + if !cc.IsNS(string(utsMode)) && !utsMode.Valid() { return nil, errors.Errorf("--uts %q is not valid", c.String("uts")) } ipcMode := container.IpcMode(c.String("ipc")) - if !ipcMode.Valid() { + if !cc.IsNS(string(ipcMode)) && !ipcMode.Valid() { return nil, errors.Errorf("--ipc %q is not valid", ipcMode) } shmDir := "" diff --git a/docs/podman-create.1.md b/docs/podman-create.1.md index dc0b0375d..36a7fda11 100644 --- a/docs/podman-create.1.md +++ b/docs/podman-create.1.md @@ -291,6 +291,7 @@ Not implemented Default is to create a private IPC namespace (POSIX SysV IPC) for the container 'container:<name|id>': reuses another container shared memory, semaphores and message queues 'host': use the host shared memory,semaphores and message queues inside the container. Note: the host mode gives the container full access to local shared memory and is therefore considered insecure. + 'ns:<path>' path to an IPC namespace to join. **--kernel-memory**="" @@ -391,6 +392,7 @@ Set the Network mode for the container 'container:<name|id>': reuse another container's network stack 'host': use the podman host network stack. Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure. '<network-name>|<network-id>': connect to a user-defined network + 'ns:<path>' path to a network namespace to join **--network-alias**=[] @@ -410,6 +412,7 @@ Set the PID mode for the container Default is to create a private PID namespace for the container 'container:<name|id>': join another container's PID namespace 'host': use the host's PID namespace for the container. Note: the host mode gives the container full access to local PID and is therefore considered insecure. + 'ns': join the specified PID namespace **--pids-limit**="" @@ -581,11 +584,13 @@ Without this argument the command will be run as root in the container. Set the usernamespace mode for the container. The use of userns is disabled by default. **host**: use the host usernamespace and enable all privileged options (e.g., `pid=host` or `--privileged`). + **ns**: specify the usernamespace to use. **--uts**=*host* Set the UTS mode for the container **host**: use the host's UTS namespace inside the container. + **ns**: specify the usernamespace to use. Note: the host mode gives the container access to changing the host's hostname and is therefore considered insecure. **-v**|**--volume**[=*[HOST-DIR:CONTAINER-DIR[:OPTIONS]]*] diff --git a/docs/podman-run.1.md b/docs/podman-run.1.md index 00c78f321..3a3115964 100644 --- a/docs/podman-run.1.md +++ b/docs/podman-run.1.md @@ -302,6 +302,7 @@ Default is to create a private IPC namespace (POSIX SysV IPC) for the container - `container:<name|id>`: reuses another container shared memory, semaphores and message queues - `host`: use the host shared memory,semaphores and message queues inside the container. Note: the host mode gives the container full access to local shared memory and is therefore considered insecure. +- `ns:<path>` path to an IPC namespace to join. **--kernel-memory**="" @@ -405,6 +406,7 @@ Set the Network mode for the container: - `container:<name|id>`: reuse another container's network stack - `host`: use the podman host network stack. Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure. - `<network-name>|<network-id>`: connect to a user-defined network +- `ns:<path>` path to a network namespace to join **--network-alias**=[] @@ -426,6 +428,7 @@ Default is to create a private PID namespace for the container - `container:<name|id>`: join another container's PID namespace - `host`: use the host's PID namespace for the container. Note: the host mode gives the container full access to local PID and is therefore considered insecure. +- `ns`: join the specified PID namespace **--pids-limit**="" @@ -611,12 +614,14 @@ Without this argument the command will be run as root in the container. Set the usernamespace mode for the container. The use of userns is disabled by default. `host`: use the host usernamespace and enable all privileged options (e.g., `pid=host` or `--privileged`). +`ns`: specify the usernamespace to use. **--uts**=*host* Set the UTS mode for the container `host`: use the host's UTS namespace inside the container. +`ns`: specify the usernamespace to use. **NOTE**: the host mode gives the container access to changing the host's hostname and is therefore considered insecure. diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go index 57416732d..1dba8cdb4 100644 --- a/pkg/spec/createconfig.go +++ b/pkg/spec/createconfig.go @@ -370,17 +370,15 @@ func (c *CreateConfig) GetContainerCreateOptions(runtime *libpod.Runtime) ([]lib } } - if rootless.IsRootless() { - if !c.NetMode.IsHost() && !c.NetMode.IsNone() { - options = append(options, libpod.WithNetNS(portBindings, true, networks)) - } + if IsNS(string(c.NetMode)) { + // pass } else if c.NetMode.IsContainer() { connectedCtr, err := c.Runtime.LookupContainer(c.NetMode.ConnectedContainer()) if err != nil { return nil, errors.Wrapf(err, "container %q not found", c.NetMode.ConnectedContainer()) } options = append(options, libpod.WithNetNSFrom(connectedCtr)) - } else if !c.NetMode.IsHost() && !c.NetMode.IsNone() { + } else if !rootless.IsRootless() && !c.NetMode.IsHost() && !c.NetMode.IsNone() { postConfigureNetNS := (len(c.IDMappings.UIDMap) > 0 || len(c.IDMappings.GIDMap) > 0) && !c.UsernsMode.IsHost() options = append(options, libpod.WithNetNS(portBindings, postConfigureNetNS, networks)) } diff --git a/pkg/spec/parse.go b/pkg/spec/parse.go index 82ca92dff..d4a655e4f 100644 --- a/pkg/spec/parse.go +++ b/pkg/spec/parse.go @@ -18,6 +18,21 @@ func (w *weightDevice) String() string { return fmt.Sprintf("%s:%d", w.path, w.weight) } +// IsNS returns if the specified string has a ns: prefix +func IsNS(s string) bool { + parts := strings.SplitN(s, ":", 2) + return len(parts) > 1 && parts[0] == "ns" +} + +// NS is the path to the namespace to join. +func NS(s string) string { + parts := strings.SplitN(s, ":", 2) + if len(parts) > 1 { + return parts[1] + } + return "" +} + // validateweightDevice validates that the specified string has a valid device-weight format // for blkio-weight-device flag func validateweightDevice(val string) (*weightDevice, error) { diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go index 35651f2ed..d9888e999 100644 --- a/pkg/spec/spec.go +++ b/pkg/spec/spec.go @@ -316,6 +316,9 @@ func blockAccessToKernelFilesystems(config *CreateConfig, g *generate.Generator) func addPidNS(config *CreateConfig, g *generate.Generator) error { pidMode := config.PidMode + if IsNS(string(pidMode)) { + return g.AddOrReplaceLinuxNamespace(string(spec.PIDNamespace), NS(string(pidMode))) + } if pidMode.IsHost() { return g.RemoveLinuxNamespace(string(spec.PIDNamespace)) } @@ -326,6 +329,14 @@ func addPidNS(config *CreateConfig, g *generate.Generator) error { } func addUserNS(config *CreateConfig, g *generate.Generator) error { + if IsNS(string(config.UsernsMode)) { + g.AddOrReplaceLinuxNamespace(spec.UserNamespace, NS(string(config.UsernsMode))) + + // runc complains if no mapping is specified, even if we join another ns. So provide a dummy mapping + g.AddLinuxUIDMapping(uint32(0), uint32(0), uint32(1)) + g.AddLinuxGIDMapping(uint32(0), uint32(0), uint32(1)) + } + if (len(config.IDMappings.UIDMap) > 0 || len(config.IDMappings.GIDMap) > 0) && !config.UsernsMode.IsHost() { g.AddOrReplaceLinuxNamespace(spec.UserNamespace, "") } @@ -345,6 +356,10 @@ func addNetNS(config *CreateConfig, g *generate.Generator) error { return nil } else if netMode.IsContainer() { logrus.Debug("Using container netmode") + return nil + } else if IsNS(string(netMode)) { + logrus.Debug("Using ns netmode") + return g.AddOrReplaceLinuxNamespace(spec.NetworkNamespace, NS(string(netMode))) } else if netMode.IsUserDefined() { logrus.Debug("Using user defined netmode") return nil @@ -354,6 +369,9 @@ func addNetNS(config *CreateConfig, g *generate.Generator) error { func addUTSNS(config *CreateConfig, g *generate.Generator) error { utsMode := config.UtsMode + if IsNS(string(utsMode)) { + return g.AddOrReplaceLinuxNamespace(string(spec.UTSNamespace), NS(string(utsMode))) + } if utsMode.IsHost() { return g.RemoveLinuxNamespace(spec.UTSNamespace) } @@ -362,6 +380,9 @@ func addUTSNS(config *CreateConfig, g *generate.Generator) error { func addIpcNS(config *CreateConfig, g *generate.Generator) error { ipcMode := config.IpcMode + if IsNS(string(ipcMode)) { + return g.AddOrReplaceLinuxNamespace(string(spec.IPCNamespace), NS(string(ipcMode))) + } if ipcMode.IsHost() { return g.RemoveLinuxNamespace(spec.IPCNamespace) } |