summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/common/volumes.go2
-rw-r--r--docs/source/markdown/podman-create.1.md19
-rw-r--r--docs/source/markdown/podman-run.1.md17
-rw-r--r--docs/tutorials/README.md2
-rw-r--r--libpod/container_inspect.go2
-rw-r--r--libpod/container_internal_linux.go2
-rw-r--r--pkg/spec/storage.go2
-rw-r--r--pkg/specgen/generate/config_linux.go5
-rw-r--r--pkg/specgen/generate/security.go10
-rw-r--r--pkg/util/mountOpts.go2
-rw-r--r--test/e2e/common_test.go8
-rw-r--r--test/e2e/play_kube_test.go2
-rw-r--r--test/e2e/run_test.go33
-rw-r--r--test/e2e/toolbox_test.go15
14 files changed, 91 insertions, 30 deletions
diff --git a/cmd/podman/common/volumes.go b/cmd/podman/common/volumes.go
index 8ab20ccae..b3c160ddf 100644
--- a/cmd/podman/common/volumes.go
+++ b/cmd/podman/common/volumes.go
@@ -313,7 +313,7 @@ func getBindMount(args []string) (spec.Mount, error) {
}
setExec = true
newMount.Options = append(newMount.Options, kv[0])
- case "shared", "rshared", "private", "rprivate", "slave", "rslave", "Z", "z":
+ case "shared", "rshared", "private", "rprivate", "slave", "rslave", "unbindable", "runbindable", "Z", "z":
newMount.Options = append(newMount.Options, kv[0])
case "bind-propagation":
if len(kv) == 1 {
diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md
index f823ac565..e243a5842 100644
--- a/docs/source/markdown/podman-create.1.md
+++ b/docs/source/markdown/podman-create.1.md
@@ -541,7 +541,7 @@ Current supported mount TYPEs are **bind**, **volume**, **image**, **tmpfs** and
· ro, readonly: true or false (default).
- · bind-propagation: shared, slave, private, rshared, rslave, or rprivate(default). See also mount(2).
+ · bind-propagation: shared, slave, private, unbindable, rshared, rslave, runbindable, or rprivate(default). See also mount(2).
. bind-nonrecursive: do not setup a recursive bind mount. By default it is recursive.
@@ -962,7 +962,7 @@ The _options_ is a comma delimited list and can be:
* **rw**|**ro**
* **z**|**Z**
-* [**r**]**shared**|[**r**]**slave**|[**r**]**private**
+* [**r**]**shared**|[**r**]**slave**|[**r**]**private**[**r**]**unbindable**
* [**r**]**bind**
* [**no**]**exec**
* [**no**]**dev**
@@ -1048,13 +1048,14 @@ visible on host and vice versa. Making a volume `slave` enables only one
way mount propagation and that is mounts done on host under that volume
will be visible inside container but not the other way around. <sup>[[1]](#Footnote1)</sup>
-To control mount propagation property of volume one can use `:[r]shared`,
-`:[r]slave` or `:[r]private` propagation flag. Propagation property can
-be specified only for bind mounted volumes and not for internal volumes or
-named volumes. For mount propagation to work source mount point (mount point
-where source dir is mounted on) has to have right propagation properties. For
-shared volumes, source mount point has to be shared. And for slave volumes,
-source mount has to be either shared or slave. <sup>[[1]](#Footnote1)</sup>
+To control mount propagation property of a volume one can use the [**r**]**shared**,
+[**r**]**slave**, [**r**]**private** or the [**r**]**unbindable** propagation flag.
+Propagation property can be specified only for bind mounted volumes and not for
+internal volumes or named volumes. For mount propagation to work the source mount
+point (the mount point where source dir is mounted on) has to have the right propagation
+properties. For shared volumes, the source mount point has to be shared. And for
+slave volumes, the source mount point has to be either shared or slave.
+<sup>[[1]](#Footnote1)</sup>
If you want to recursively mount a volume and all of its submounts into a
container, then you can use the `rbind` option. By default the bind option is
diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md
index 71f77d307..0166a344a 100644
--- a/docs/source/markdown/podman-run.1.md
+++ b/docs/source/markdown/podman-run.1.md
@@ -567,7 +567,7 @@ Current supported mount TYPEs are **bind**, **volume**, **image**, **tmpfs** and
· ro, readonly: true or false (default).
- · bind-propagation: shared, slave, private, rshared, rslave, or rprivate(default). See also mount(2).
+ · bind-propagation: shared, slave, private, unbindable, rshared, rslave, runbindable, or rprivate(default). See also mount(2).
. bind-nonrecursive: do not setup a recursive bind mount. By default it is recursive.
@@ -1015,7 +1015,7 @@ The _options_ is a comma delimited list and can be: <sup>[[1]](#Footnote1)</sup>
* **rw**|**ro**
* **z**|**Z**
-* [**r**]**shared**|[**r**]**slave**|[**r**]**private**
+* [**r**]**shared**|[**r**]**slave**|[**r**]**private**[**r**]**unbindable**
* [**r**]**bind**
* [**no**]**exec**
* [**no**]**dev**
@@ -1099,12 +1099,13 @@ way mount propagation and that is mounts done on host under that volume
will be visible inside container but not the other way around. <sup>[[1]](#Footnote1)</sup>
To control mount propagation property of volume one can use [**r**]**shared**,
-[**r**]**slave** or [**r**]**private** propagation flag. Propagation property can
-be specified only for bind mounted volumes and not for internal volumes or
-named volumes. For mount propagation to work source mount point (mount point
-where source dir is mounted on) has to have right propagation properties. For
-shared volumes, source mount point has to be shared. And for slave volumes,
-source mount has to be either shared or slave. <sup>[[1]](#Footnote1)</sup>
+[**r**]**slave**, [**r**]**private** or [**r**]**unbindable** propagation flag.
+Propagation property can be specified only for bind mounted volumes and not for
+internal volumes or named volumes. For mount propagation to work source mount
+point (mount point where source dir is mounted on) has to have right propagation
+properties. For shared volumes, source mount point has to be shared. And for
+slave volumes, source mount has to be either shared or slave.
+<sup>[[1]](#Footnote1)</sup>
If you want to recursively mount a volume and all of its submounts into a
container, then you can use the **rbind** option. By default the bind option is
diff --git a/docs/tutorials/README.md b/docs/tutorials/README.md
index 7f7b4853d..246d235ee 100644
--- a/docs/tutorials/README.md
+++ b/docs/tutorials/README.md
@@ -12,7 +12,7 @@ Learn how to setup Podman and perform some basic commands with the utility.
The steps required to setup rootless Podman are enumerated.
-**[Setup Mac/Windows](mac_win_client.md)
+**[Setup Mac/Windows](mac_win_client.md)**
Special setup for running the Podman remote client on a Mac or Windows PC and connecting to Podman running on a Linux VM are documented.
diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go
index 162f70326..f78d74ef7 100644
--- a/libpod/container_inspect.go
+++ b/libpod/container_inspect.go
@@ -270,7 +270,7 @@ func parseMountOptionsForInspect(options []string, mount *define.InspectMount) {
isRW = false
case "rw":
// Do nothing, silently discard
- case "shared", "slave", "private", "rshared", "rslave", "rprivate":
+ case "shared", "slave", "private", "rshared", "rslave", "rprivate", "unbindable", "runbindable":
mountProp = opt
case "z", "Z":
zZ = opt
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index bf74ca954..83d5c20cb 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -344,7 +344,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
Type: "bind",
Source: srcPath,
Destination: dstPath,
- Options: []string{"bind", "private"},
+ Options: []string{"bind", "rprivate"},
}
if c.IsReadOnly() && dstPath != "/dev/shm" {
newMount.Options = append(newMount.Options, "ro", "nosuid", "noexec", "nodev")
diff --git a/pkg/spec/storage.go b/pkg/spec/storage.go
index ebf5ec196..b441daf08 100644
--- a/pkg/spec/storage.go
+++ b/pkg/spec/storage.go
@@ -445,7 +445,7 @@ func getBindMount(args []string) (spec.Mount, error) {
}
setExec = true
newMount.Options = append(newMount.Options, kv[0])
- case "shared", "rshared", "private", "rprivate", "slave", "rslave", "Z", "z":
+ case "shared", "rshared", "private", "rprivate", "slave", "rslave", "unbindable", "runbindable", "Z", "z":
newMount.Options = append(newMount.Options, kv[0])
case "bind-propagation":
if len(kv) == 1 {
diff --git a/pkg/specgen/generate/config_linux.go b/pkg/specgen/generate/config_linux.go
index fcb7641d2..2d40dba8f 100644
--- a/pkg/specgen/generate/config_linux.go
+++ b/pkg/specgen/generate/config_linux.go
@@ -350,3 +350,8 @@ func deviceFromPath(path string) (*spec.LinuxDevice, error) {
Minor: int64(unix.Minor(devNumber)),
}, nil
}
+
+func supportAmbientCapabilities() bool {
+ err := unix.Prctl(unix.PR_CAP_AMBIENT, unix.PR_CAP_AMBIENT_IS_SET, 0, 0, 0)
+ return err == nil
+}
diff --git a/pkg/specgen/generate/security.go b/pkg/specgen/generate/security.go
index d17cd4a9a..dee140282 100644
--- a/pkg/specgen/generate/security.go
+++ b/pkg/specgen/generate/security.go
@@ -135,7 +135,9 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator,
configSpec.Process.Capabilities.Bounding = caplist
configSpec.Process.Capabilities.Inheritable = caplist
- if s.User == "" || s.User == "root" || s.User == "0" {
+ user := strings.Split(s.User, ":")[0]
+
+ if (user == "" && s.UserNS.NSMode != specgen.KeepID) || user == "root" || user == "0" {
configSpec.Process.Capabilities.Effective = caplist
configSpec.Process.Capabilities.Permitted = caplist
} else {
@@ -145,6 +147,12 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator,
}
configSpec.Process.Capabilities.Effective = userCaps
configSpec.Process.Capabilities.Permitted = userCaps
+
+ // Ambient capabilities were added to Linux 4.3. Set ambient
+ // capabilities only when the kernel supports them.
+ if supportAmbientCapabilities() {
+ configSpec.Process.Capabilities.Ambient = userCaps
+ }
}
g.SetProcessNoNewPrivileges(s.NoNewPrivileges)
diff --git a/pkg/util/mountOpts.go b/pkg/util/mountOpts.go
index eab2657e3..580aaf4f2 100644
--- a/pkg/util/mountOpts.go
+++ b/pkg/util/mountOpts.go
@@ -57,7 +57,7 @@ func ProcessOptions(options []string, isTmpfs bool, sourcePath string) ([]string
return nil, errors.Wrapf(ErrDupeMntOption, "only one of 'rw' and 'ro' can be used")
}
foundWrite = true
- case "private", "rprivate", "slave", "rslave", "shared", "rshared":
+ case "private", "rprivate", "slave", "rslave", "shared", "rshared", "unbindable", "runbindable":
if foundProp {
return nil, errors.Wrapf(ErrDupeMntOption, "only one root propagation mode can be used")
}
diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go
index 3814d161d..678b2c882 100644
--- a/test/e2e/common_test.go
+++ b/test/e2e/common_test.go
@@ -613,12 +613,10 @@ func SkipIfRootlessCgroupsV1(reason string) {
}
}
-func SkipIfUnprevilegedCPULimits() {
+func SkipIfUnprivilegedCPULimits() {
info := GetHostDistributionInfo()
- if isRootless() &&
- info.Distribution == "fedora" &&
- (info.Version == "31" || info.Version == "32") {
- ginkgo.Skip("Rootless Fedora doesn't have permission to set CPU limits before version 33")
+ if isRootless() && info.Distribution == "fedora" {
+ ginkgo.Skip("Rootless Fedora doesn't have permission to set CPU limits")
}
}
diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go
index 6dcfa9bd8..1d683e987 100644
--- a/test/e2e/play_kube_test.go
+++ b/test/e2e/play_kube_test.go
@@ -1406,7 +1406,7 @@ spec:
It("podman play kube allows setting resource limits", func() {
SkipIfContainerized("Resource limits require a running systemd")
SkipIfRootlessCgroupsV1("Limits require root or cgroups v2")
- SkipIfUnprevilegedCPULimits()
+ SkipIfUnprivilegedCPULimits()
podmanTest.CgroupManager = "systemd"
var (
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index e6bba9f67..deb4419af 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -315,6 +315,39 @@ var _ = Describe("Podman run", func() {
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(ContainSubstring("00000000a80425fb"))
+
+ session = podmanTest.Podman([]string{"run", "--user=1000:1000", "--cap-add=DAC_OVERRIDE", "--rm", ALPINE, "grep", "CapAmb", "/proc/self/status"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("0000000000000002"))
+
+ session = podmanTest.Podman([]string{"run", "--user=1000:1000", "--rm", ALPINE, "grep", "CapAmb", "/proc/self/status"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("0000000000000000"))
+
+ session = podmanTest.Podman([]string{"run", "--user=0", "--cap-add=DAC_OVERRIDE", "--rm", ALPINE, "grep", "CapAmb", "/proc/self/status"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("0000000000000000"))
+
+ session = podmanTest.Podman([]string{"run", "--user=0:0", "--cap-add=DAC_OVERRIDE", "--rm", ALPINE, "grep", "CapAmb", "/proc/self/status"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("0000000000000000"))
+
+ if os.Geteuid() > 0 {
+ if os.Getenv("SKIP_USERNS") != "" {
+ Skip("Skip userns tests.")
+ }
+ if _, err := os.Stat("/proc/self/uid_map"); err != nil {
+ Skip("User namespaces not supported.")
+ }
+ session = podmanTest.Podman([]string{"run", "--userns=keep-id", "--cap-add=DAC_OVERRIDE", "--rm", ALPINE, "grep", "CapAmb", "/proc/self/status"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("0000000000000002"))
+ }
})
It("podman run user capabilities test with image", func() {
diff --git a/test/e2e/toolbox_test.go b/test/e2e/toolbox_test.go
index fbff8d19e..822159fc2 100644
--- a/test/e2e/toolbox_test.go
+++ b/test/e2e/toolbox_test.go
@@ -30,10 +30,12 @@ import (
"os"
"os/exec"
"os/user"
+ "path"
"strconv"
"strings"
"syscall"
+ "github.com/containers/podman/v2/pkg/rootless"
. "github.com/containers/podman/v2/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@@ -371,10 +373,23 @@ var _ = Describe("Toolbox-specific testing", func() {
currentUser, err := user.Current()
Expect(err).To(BeNil())
+
session = podmanTest.Podman([]string{"run", "-v", fmt.Sprintf("%s:%s", currentUser.HomeDir, currentUser.HomeDir), "--userns=keep-id", fedoraToolbox, "sh", "-c", "echo $HOME"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(ContainSubstring(currentUser.HomeDir))
+
+ if rootless.IsRootless() {
+ location := path.Dir(currentUser.HomeDir)
+ volumeArg := fmt.Sprintf("%s:%s", location, location)
+ session = podmanTest.Podman([]string{"run",
+ "--userns=keep-id",
+ "--volume", volumeArg,
+ fedoraToolbox, "sh", "-c", "echo $HOME"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring(currentUser.HomeDir))
+ }
})
})