summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libpod/oci_conmon_exec_linux.go2
-rw-r--r--libpod/oci_conmon_linux.go18
-rw-r--r--test/e2e/exec_test.go15
-rw-r--r--test/e2e/run_privileged_test.go36
4 files changed, 47 insertions, 24 deletions
diff --git a/libpod/oci_conmon_exec_linux.go b/libpod/oci_conmon_exec_linux.go
index f8e7020f7..4546acefb 100644
--- a/libpod/oci_conmon_exec_linux.go
+++ b/libpod/oci_conmon_exec_linux.go
@@ -387,7 +387,7 @@ func (r *ConmonOCIRuntime) startExec(c *Container, sessionID string, options *Ex
finalEnv = append(finalEnv, fmt.Sprintf("%s=%s", k, v))
}
- processFile, err := prepareProcessExec(c, options.Cmd, finalEnv, options.Terminal, options.Cwd, options.User, sessionID)
+ processFile, err := prepareProcessExec(c, options, finalEnv, sessionID)
if err != nil {
return nil, nil, err
}
diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go
index c99086b33..199b40097 100644
--- a/libpod/oci_conmon_linux.go
+++ b/libpod/oci_conmon_linux.go
@@ -1185,26 +1185,33 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co
// prepareProcessExec returns the path of the process.json used in runc exec -p
// caller is responsible to close the returned *os.File if needed.
-func prepareProcessExec(c *Container, cmd, env []string, tty bool, cwd, user, sessionID string) (*os.File, error) {
+func prepareProcessExec(c *Container, options *ExecOptions, env []string, sessionID string) (*os.File, error) {
f, err := ioutil.TempFile(c.execBundlePath(sessionID), "exec-process-")
if err != nil {
return nil, err
}
pspec := c.config.Spec.Process
pspec.SelinuxLabel = c.config.ProcessLabel
- pspec.Args = cmd
+ pspec.Args = options.Cmd
+ for _, cap := range options.CapAdd {
+ pspec.Capabilities.Bounding = append(pspec.Capabilities.Bounding, cap)
+ pspec.Capabilities.Effective = append(pspec.Capabilities.Effective, cap)
+ pspec.Capabilities.Inheritable = append(pspec.Capabilities.Inheritable, cap)
+ pspec.Capabilities.Permitted = append(pspec.Capabilities.Permitted, cap)
+ pspec.Capabilities.Ambient = append(pspec.Capabilities.Ambient, cap)
+ }
// We need to default this to false else it will inherit terminal as true
// from the container.
pspec.Terminal = false
- if tty {
+ if options.Terminal {
pspec.Terminal = true
}
if len(env) > 0 {
pspec.Env = append(pspec.Env, env...)
}
- if cwd != "" {
- pspec.Cwd = cwd
+ if options.Cwd != "" {
+ pspec.Cwd = options.Cwd
}
@@ -1212,6 +1219,7 @@ func prepareProcessExec(c *Container, cmd, env []string, tty bool, cwd, user, se
var sgids []uint32
// if the user is empty, we should inherit the user that the container is currently running with
+ user := options.User
if user == "" {
user = c.config.User
addGroups = c.config.Groups
diff --git a/test/e2e/exec_test.go b/test/e2e/exec_test.go
index f61f52589..18737105e 100644
--- a/test/e2e/exec_test.go
+++ b/test/e2e/exec_test.go
@@ -119,6 +119,21 @@ var _ = Describe("Podman exec", func() {
Expect(session.ExitCode()).To(Equal(100))
})
+ It("podman exec --privileged", func() {
+ hostCap := SystemExec("awk", []string{"/^CapEff/ { print $2 }", "/proc/self/status"})
+ Expect(hostCap.ExitCode()).To(Equal(0))
+
+ setup := podmanTest.RunTopContainer("test-privileged")
+ setup.WaitWithDefaultTimeout()
+ Expect(setup.ExitCode()).To(Equal(0))
+
+ session := podmanTest.Podman([]string{"exec", "--privileged", "test-privileged", "sh", "-c", "grep ^CapEff /proc/self/status | cut -f 2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ containerCapMatchesHost(session.OutputToString(), hostCap.OutputToString())
+ })
+
It("podman exec terminal doesn't hang", func() {
setup := podmanTest.Podman([]string{"run", "-dti", "--name", "test1", fedoraMinimal, "sleep", "+Inf"})
setup.WaitWithDefaultTimeout()
diff --git a/test/e2e/run_privileged_test.go b/test/e2e/run_privileged_test.go
index 760de55b6..cadda7224 100644
--- a/test/e2e/run_privileged_test.go
+++ b/test/e2e/run_privileged_test.go
@@ -16,22 +16,22 @@ import (
// know about at compile time. That is: the kernel may have more caps
// available than we are aware of, leading to host=FFF... and ctr=3FF...
// because the latter is all we request. Accept that.
-func containerCapMatchesHost(ctr_cap string, host_cap string) {
+func containerCapMatchesHost(ctrCap string, hostCap string) {
if isRootless() {
return
}
- ctr_cap_n, err := strconv.ParseUint(ctr_cap, 16, 64)
- Expect(err).NotTo(HaveOccurred(), "Error parsing %q as hex", ctr_cap)
+ ctrCap_n, err := strconv.ParseUint(ctrCap, 16, 64)
+ Expect(err).NotTo(HaveOccurred(), "Error parsing %q as hex", ctrCap)
- host_cap_n, err := strconv.ParseUint(host_cap, 16, 64)
- Expect(err).NotTo(HaveOccurred(), "Error parsing %q as hex", host_cap)
+ hostCap_n, err := strconv.ParseUint(hostCap, 16, 64)
+ Expect(err).NotTo(HaveOccurred(), "Error parsing %q as hex", hostCap)
// host caps can never be zero (except rootless).
// and host caps must always be a superset (inclusive) of container
- Expect(host_cap_n).To(BeNumerically(">", 0), "host cap %q should be nonzero", host_cap)
- Expect(host_cap_n).To(BeNumerically(">=", ctr_cap_n), "host cap %q should never be less than container cap %q", host_cap, ctr_cap)
- host_cap_masked := host_cap_n & (1<<len(capability.List()) - 1)
- Expect(ctr_cap_n).To(Equal(host_cap_masked), "container cap %q is not a subset of host cap %q", ctr_cap, host_cap)
+ Expect(hostCap_n).To(BeNumerically(">", 0), "host cap %q should be nonzero", hostCap)
+ Expect(hostCap_n).To(BeNumerically(">=", ctrCap_n), "host cap %q should never be less than container cap %q", hostCap, ctrCap)
+ hostCap_masked := hostCap_n & (1<<len(capability.List()) - 1)
+ Expect(ctrCap_n).To(Equal(hostCap_masked), "container cap %q is not a subset of host cap %q", ctrCap, hostCap)
}
var _ = Describe("Podman privileged container tests", func() {
@@ -68,38 +68,38 @@ var _ = Describe("Podman privileged container tests", func() {
})
It("podman privileged CapEff", func() {
- host_cap := SystemExec("awk", []string{"/^CapEff/ { print $2 }", "/proc/self/status"})
- Expect(host_cap.ExitCode()).To(Equal(0))
+ hostCap := SystemExec("awk", []string{"/^CapEff/ { print $2 }", "/proc/self/status"})
+ Expect(hostCap.ExitCode()).To(Equal(0))
session := podmanTest.Podman([]string{"run", "--privileged", "busybox", "awk", "/^CapEff/ { print $2 }", "/proc/self/status"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- containerCapMatchesHost(session.OutputToString(), host_cap.OutputToString())
+ containerCapMatchesHost(session.OutputToString(), hostCap.OutputToString())
})
It("podman cap-add CapEff", func() {
// Get caps of current process
- host_cap := SystemExec("awk", []string{"/^CapEff/ { print $2 }", "/proc/self/status"})
- Expect(host_cap.ExitCode()).To(Equal(0))
+ hostCap := SystemExec("awk", []string{"/^CapEff/ { print $2 }", "/proc/self/status"})
+ Expect(hostCap.ExitCode()).To(Equal(0))
session := podmanTest.Podman([]string{"run", "--cap-add", "all", "busybox", "awk", "/^CapEff/ { print $2 }", "/proc/self/status"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- containerCapMatchesHost(session.OutputToString(), host_cap.OutputToString())
+ containerCapMatchesHost(session.OutputToString(), hostCap.OutputToString())
})
It("podman cap-add CapEff with --user", func() {
// Get caps of current process
- host_cap := SystemExec("awk", []string{"/^CapEff/ { print $2 }", "/proc/self/status"})
- Expect(host_cap.ExitCode()).To(Equal(0))
+ hostCap := SystemExec("awk", []string{"/^CapEff/ { print $2 }", "/proc/self/status"})
+ Expect(hostCap.ExitCode()).To(Equal(0))
session := podmanTest.Podman([]string{"run", "--user=bin", "--cap-add", "all", "busybox", "awk", "/^CapEff/ { print $2 }", "/proc/self/status"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- containerCapMatchesHost(session.OutputToString(), host_cap.OutputToString())
+ containerCapMatchesHost(session.OutputToString(), hostCap.OutputToString())
})
It("podman cap-drop CapEff", func() {