userns: use the intermediate mountns for volumes
when --uidmap is used, the user won't be able to access /var/lib/containers/storage/volumes. Use the intermediate mount namespace, that is accessible to root in the container, for mounting the volumes inside the container. Closes: https://github.com/containers/libpod/issues/2713 Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
parent
bf10fac193
commit
7f6f2f3f4a
|
|
@ -203,7 +203,8 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
|
|||
}
|
||||
// Check if the spec file mounts contain the label Relabel flags z or Z.
|
||||
// If they do, relabel the source directory and then remove the option.
|
||||
for _, m := range g.Mounts() {
|
||||
for i := range g.Config.Mounts {
|
||||
m := &g.Config.Mounts[i]
|
||||
var options []string
|
||||
for _, o := range m.Options {
|
||||
switch o {
|
||||
|
|
@ -219,6 +220,13 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
|
|||
}
|
||||
}
|
||||
m.Options = options
|
||||
|
||||
// If we are using a user namespace, we will use an intermediate
|
||||
// directory to bind mount volumes
|
||||
if c.state.UserNSRoot != "" && strings.HasPrefix(m.Source, c.runtime.config.VolumePath) {
|
||||
newSourceDir := filepath.Join(c.state.UserNSRoot, "volumes")
|
||||
m.Source = strings.Replace(m.Source, c.runtime.config.VolumePath, newSourceDir, 1)
|
||||
}
|
||||
}
|
||||
|
||||
g.SetProcessSelinuxLabel(c.ProcessLabel())
|
||||
|
|
|
|||
|
|
@ -106,6 +106,23 @@ func (r *OCIRuntime) createContainer(ctr *Container, cgroupParent string, restor
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if ctr.state.UserNSRoot != "" {
|
||||
_, err := os.Stat(ctr.runtime.config.VolumePath)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return
|
||||
}
|
||||
if err == nil {
|
||||
volumesTarget := filepath.Join(ctr.state.UserNSRoot, "volumes")
|
||||
if err := idtools.MkdirAs(volumesTarget, 0700, ctr.RootUID(), ctr.RootGID()); err != nil {
|
||||
return
|
||||
}
|
||||
if err = unix.Mount(ctr.runtime.config.VolumePath, volumesTarget, "none", unix.MS_BIND, ""); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = r.createOCIContainer(ctr, cgroupParent, restoreOptions)
|
||||
}()
|
||||
wg.Wait()
|
||||
|
|
|
|||
|
|
@ -69,6 +69,21 @@ var _ = Describe("Podman UserNS support", func() {
|
|||
Expect(ok).To(BeTrue())
|
||||
})
|
||||
|
||||
It("podman uidmapping and gidmapping with a volume", func() {
|
||||
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", "--uidmap=0:1:70000", "--gidmap=0:20000:70000", "-v", "my-foo-volume:/foo:Z", "busybox", "echo", "hello"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session.ExitCode()).To(Equal(0))
|
||||
ok, _ := session.GrepString("hello")
|
||||
Expect(ok).To(BeTrue())
|
||||
})
|
||||
|
||||
It("podman uidmapping and gidmapping --net=host", func() {
|
||||
if os.Getenv("SKIP_USERNS") != "" {
|
||||
Skip("Skip userns tests.")
|
||||
|
|
|
|||
Loading…
Reference in New Issue