From 3ba3e1c7510d1780b6527a4aa52e40ac2c5b576a Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Sun, 6 Oct 2019 11:11:29 +0200 Subject: systemd: expect full path /usr/sbin/init "init" is a quite common name for the command executed in a container image and Podman ends up using the systemd mode also when not required. Be stricter on enabling the systemd mode and not enable it automatically when the basename is "init" but expect the full path "/usr/sbin/init". Signed-off-by: Giuseppe Scrivano --- cmd/podman/shared/create.go | 2 +- docs/podman-create.1.md | 7 ++--- docs/podman-derivative-api | 64 +++++++++++++++++++++++++++++++++++++++++++++ docs/podman-run.1.md | 5 ++-- pkg/spec/createconfig.go | 3 +-- test/e2e/systemd_test.go | 2 +- 6 files changed, 74 insertions(+), 9 deletions(-) create mode 100644 docs/podman-derivative-api diff --git a/cmd/podman/shared/create.go b/cmd/podman/shared/create.go index 9020613c5..675dfbad6 100644 --- a/cmd/podman/shared/create.go +++ b/cmd/podman/shared/create.go @@ -663,7 +663,7 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. } var systemd bool - if command != nil && c.Bool("systemd") && ((filepath.Base(command[0]) == "init") || (filepath.Base(command[0]) == "systemd")) { + if command != nil && c.Bool("systemd") && (command[0] == "/usr/sbin/init" || (filepath.Base(command[0]) == "systemd")) { systemd = true if signalString == "" { stopSignal, err = signal.ParseSignal("RTMIN+3") diff --git a/docs/podman-create.1.md b/docs/podman-create.1.md index 46fa4fcd4..418ad2c4e 100644 --- a/docs/podman-create.1.md +++ b/docs/podman-create.1.md @@ -709,13 +709,14 @@ Network Namespace - current sysctls allowed: Sysctls beginning with net.* Note: if you use the --network=host option these sysctls will not be allowed. - +x **--systemd**=*true|false* Run container in systemd mode. The default is *true*. -If the command you running inside of the container is systemd or init, podman -will setup tmpfs mount points in the following directories: +If the command you are running inside of the container is systemd or +/usr/sbin/init, Podman will setup tmpfs mount points in the following +directories: /run, /run/lock, /tmp, /sys/fs/cgroup/systemd, /var/lib/journal diff --git a/docs/podman-derivative-api b/docs/podman-derivative-api new file mode 100644 index 000000000..1b6153df5 --- /dev/null +++ b/docs/podman-derivative-api @@ -0,0 +1,64 @@ +.TH How to use libpod for custom/derivative projects +.PP +libpod today is a Golang library and a CLI. The choice of interface you make has advantages and disadvantages. + +.SH Running as a subprocess +.PP +Advantages: + +.RS +.IP \(bu 2 +Many commands output JSON +.IP \(bu 2 +Works with languages other than Golang +.IP \(bu 2 +Easy to get started + +.RE + +.PP +Disadvantages: + +.RS +.IP \(bu 2 +Error handling is harder +.IP \(bu 2 +May be slower +.IP \(bu 2 +Can't hook into or control low\-level things like how images are pulled + +.RE + +.SH Vendoring into a Go project +.PP +Advantages: + +.RS +.IP \(bu 2 +Significant power and control + +.RE + +.PP +Disadvantages: + +.RS +.IP \(bu 2 +You are now on the hook for container runtime security updates (partially, \fB\fCrunc\fR/\fB\fCcrun\fR are separate) +.IP \(bu 2 +Binary size +.IP \(bu 2 +Potential skew between multiple libpod versions operating on the same storage can cause problems + +.RE + +.SH Varlink +.PP +Some code exists for this; splits the difference. Future uncertain. + +.SH Making the choice +.PP +A good question to ask first is: Do you want users to be able to use \fB\fCpodman\fR to manipulate the containers created by your project? +If so, that makes it more likely that you want to run \fB\fCpodman\fR as a subprocess. If you want a separate image store and a fundamentally +different experience; if what you're doing with containers is quite different from those created by the \fB\fCpodman\fR CLI, +that may drive you towards vendoring. diff --git a/docs/podman-run.1.md b/docs/podman-run.1.md index dfc634288..5cbe1a38f 100644 --- a/docs/podman-run.1.md +++ b/docs/podman-run.1.md @@ -751,8 +751,9 @@ Note: if you use the `--network=host` option these sysctls will not be allowed. Run container in systemd mode. The default is *true*. -If the command you are running inside of the container is systemd or init, Podman -will setup tmpfs mount points in the following directories: +If the command you are running inside of the container is systemd or +/usr/sbin/init, Podman will setup tmpfs mount points in the following +directories: /run, /run/lock, /tmp, /sys/fs/cgroup/systemd, /var/lib/journal diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go index a65263b7d..3685450f0 100644 --- a/pkg/spec/createconfig.go +++ b/pkg/spec/createconfig.go @@ -195,8 +195,7 @@ func (c *CreateConfig) getContainerCreateOptions(runtime *libpod.Runtime, pod *l if c.Interactive { options = append(options, libpod.WithStdin()) } - if c.Systemd && (strings.HasSuffix(c.Command[0], "init") || - strings.HasSuffix(c.Command[0], "systemd")) { + if c.Systemd { options = append(options, libpod.WithSystemd()) } if c.Name != "" { diff --git a/test/e2e/systemd_test.go b/test/e2e/systemd_test.go index 02778d493..9ec48ba00 100644 --- a/test/e2e/systemd_test.go +++ b/test/e2e/systemd_test.go @@ -94,7 +94,7 @@ WantedBy=multi-user.target Expect(pull.ExitCode()).To(Equal(0)) ctrName := "testSystemd" - run := podmanTest.Podman([]string{"run", "--name", ctrName, "-t", "-i", "-d", systemdImage, "init"}) + run := podmanTest.Podman([]string{"run", "--name", ctrName, "-t", "-i", "-d", systemdImage, "/usr/sbin/init"}) run.WaitWithDefaultTimeout() Expect(run.ExitCode()).To(Equal(0)) ctrID := run.OutputToString() -- cgit v1.2.3-54-g00ecf From 5963077e93937046b6b13d6f1da8c1f932c0e6ff Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Mon, 7 Oct 2019 14:02:54 +0200 Subject: cli: support --systemd=always it enforces the systemd mode also when the command name doesn't match /usr/sbin/init or systemd. Signed-off-by: Giuseppe Scrivano --- API.md | 2 +- cmd/podman/cliconfig/defaults.go | 5 ----- cmd/podman/common.go | 6 +++--- cmd/podman/shared/create.go | 14 +++++++++++--- cmd/podman/shared/intermediate.go | 2 +- cmd/podman/shared/intermediate_varlink.go | 5 +++-- cmd/podman/varlink/io.podman.varlink | 2 +- docs/podman-create.1.md | 9 +++++++-- docs/podman-run.1.md | 7 ++++++- 9 files changed, 33 insertions(+), 19 deletions(-) diff --git a/API.md b/API.md index a9905c940..a2a093bec 100755 --- a/API.md +++ b/API.md @@ -1591,7 +1591,7 @@ subgidname [?string](#?string) sysctl [?[]string](#?[]string) -systemd [?bool](#?bool) +systemd [?string](#?string) tmpfs [?[]string](#?[]string) diff --git a/cmd/podman/cliconfig/defaults.go b/cmd/podman/cliconfig/defaults.go index d5dae0874..ce695d153 100644 --- a/cmd/podman/cliconfig/defaults.go +++ b/cmd/podman/cliconfig/defaults.go @@ -1,10 +1,5 @@ package cliconfig -const ( - // DefaultSystemD value - DefaultSystemD bool = true -) - var ( // DefaultHealthCheckInterval default value DefaultHealthCheckInterval = "30s" diff --git a/cmd/podman/common.go b/cmd/podman/common.go index 2a3f8f3ad..e93586b62 100644 --- a/cmd/podman/common.go +++ b/cmd/podman/common.go @@ -455,9 +455,9 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { "sysctl", []string{}, "Sysctl options (default [])", ) - createFlags.Bool( - "systemd", cliconfig.DefaultSystemD, - "Run container in systemd mode if the command executable is systemd or init", + createFlags.String( + "systemd", "true", + `Run container in systemd mode ("true"|"false"|"always" (default "true")`, ) createFlags.StringArray( "tmpfs", []string{}, diff --git a/cmd/podman/shared/create.go b/cmd/podman/shared/create.go index 675dfbad6..7c56db8db 100644 --- a/cmd/podman/shared/create.go +++ b/cmd/podman/shared/create.go @@ -662,9 +662,17 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. return nil, errors.Errorf("invalid image-volume type %q. Pick one of bind, tmpfs, or ignore", c.String("image-volume")) } - var systemd bool - if command != nil && c.Bool("systemd") && (command[0] == "/usr/sbin/init" || (filepath.Base(command[0]) == "systemd")) { - systemd = true + systemd := c.String("systemd") == "always" + if !systemd && command != nil { + x, err := strconv.ParseBool(c.String("systemd")) + if err != nil { + return nil, errors.Wrapf(err, "cannot parse bool %s", c.String("systemd")) + } + if x && (command[0] == "/usr/sbin/init" || (filepath.Base(command[0]) == "systemd")) { + systemd = true + } + } + if systemd { if signalString == "" { stopSignal, err = signal.ParseSignal("RTMIN+3") if err != nil { diff --git a/cmd/podman/shared/intermediate.go b/cmd/podman/shared/intermediate.go index cccdd1bea..0f71dc087 100644 --- a/cmd/podman/shared/intermediate.go +++ b/cmd/podman/shared/intermediate.go @@ -449,7 +449,7 @@ func NewIntermediateLayer(c *cliconfig.PodmanCommand, remote bool) GenericCLIRes m["subgidname"] = newCRString(c, "subgidname") m["subuidname"] = newCRString(c, "subuidname") m["sysctl"] = newCRStringSlice(c, "sysctl") - m["systemd"] = newCRBool(c, "systemd") + m["systemd"] = newCRString(c, "systemd") m["tmpfs"] = newCRStringArray(c, "tmpfs") m["tty"] = newCRBool(c, "tty") m["uidmap"] = newCRStringSlice(c, "uidmap") diff --git a/cmd/podman/shared/intermediate_varlink.go b/cmd/podman/shared/intermediate_varlink.go index 9dbf83950..c95470a72 100644 --- a/cmd/podman/shared/intermediate_varlink.go +++ b/cmd/podman/shared/intermediate_varlink.go @@ -152,7 +152,7 @@ func (g GenericCLIResults) MakeVarlink() iopodman.Create { Subuidname: StringToPtr(g.Find("subuidname")), Subgidname: StringToPtr(g.Find("subgidname")), Sysctl: StringSliceToPtr(g.Find("sysctl")), - Systemd: BoolToPtr(g.Find("systemd")), + Systemd: StringToPtr(g.Find("systemd")), Tmpfs: StringSliceToPtr(g.Find("tmpfs")), Tty: BoolToPtr(g.Find("tty")), Uidmap: StringSliceToPtr(g.Find("uidmap")), @@ -321,6 +321,7 @@ func VarlinkCreateToGeneric(opts iopodman.Create) GenericCLIResults { var memSwapDefault int64 = -1 netModeDefault := "bridge" + systemdDefault := "true" if rootless.IsRootless() { netModeDefault = "slirp4netns" } @@ -409,7 +410,7 @@ func VarlinkCreateToGeneric(opts iopodman.Create) GenericCLIResults { m["subgidname"] = stringFromVarlink(opts.Subgidname, "subgidname", nil) m["subuidname"] = stringFromVarlink(opts.Subuidname, "subuidname", nil) m["sysctl"] = stringSliceFromVarlink(opts.Sysctl, "sysctl", nil) - m["systemd"] = boolFromVarlink(opts.Systemd, "systemd", cliconfig.DefaultSystemD) + m["systemd"] = stringFromVarlink(opts.Systemd, "systemd", &systemdDefault) m["tmpfs"] = stringSliceFromVarlink(opts.Tmpfs, "tmpfs", nil) m["tty"] = boolFromVarlink(opts.Tty, "tty", false) m["uidmap"] = stringSliceFromVarlink(opts.Uidmap, "uidmap", nil) diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink index 2408dc80c..13e8394fb 100644 --- a/cmd/podman/varlink/io.podman.varlink +++ b/cmd/podman/varlink/io.podman.varlink @@ -363,7 +363,7 @@ type Create ( subuidname: ?string, subgidname: ?string, sysctl: ?[]string, - systemd: ?bool, + systemd: ?string, tmpfs: ?[]string, tty: ?bool, uidmap: ?[]string, diff --git a/docs/podman-create.1.md b/docs/podman-create.1.md index 418ad2c4e..35602f97b 100644 --- a/docs/podman-create.1.md +++ b/docs/podman-create.1.md @@ -709,11 +709,16 @@ Network Namespace - current sysctls allowed: Sysctls beginning with net.* Note: if you use the --network=host option these sysctls will not be allowed. -x -**--systemd**=*true|false* + +**--systemd**=*true|false|always* Run container in systemd mode. The default is *true*. +The value *always* enforces the systemd mode is enforced without +looking at the executable name. Otherwise, if set to true and the +command you are running inside the container is systemd or +/usr/sbin/init. + If the command you are running inside of the container is systemd or /usr/sbin/init, Podman will setup tmpfs mount points in the following directories: diff --git a/docs/podman-run.1.md b/docs/podman-run.1.md index 5cbe1a38f..e255119d7 100644 --- a/docs/podman-run.1.md +++ b/docs/podman-run.1.md @@ -747,10 +747,15 @@ Network Namespace - current sysctls allowed: Note: if you use the `--network=host` option these sysctls will not be allowed. -**--systemd**=*true|false* +**--systemd**=*true|false|always* Run container in systemd mode. The default is *true*. +The value *always* enforces the systemd mode is enforced without +looking at the executable name. Otherwise, if set to true and the +command you are running inside the container is systemd or +/usr/sbin/init. + If the command you are running inside of the container is systemd or /usr/sbin/init, Podman will setup tmpfs mount points in the following directories: -- cgit v1.2.3-54-g00ecf