mirror of
https://github.com/containers/podman.git
synced 2025-06-26 04:46:57 +08:00
Merge pull request #13221 from LStandman/main
Add support for --chrootdirs
This commit is contained in:
@ -631,6 +631,14 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
|
||||
"Write the container process ID to the file")
|
||||
_ = cmd.RegisterFlagCompletionFunc(pidFileFlagName, completion.AutocompleteDefault)
|
||||
|
||||
chrootDirsFlagName := "chrootdirs"
|
||||
createFlags.StringSliceVar(
|
||||
&cf.ChrootDirs,
|
||||
chrootDirsFlagName, []string{},
|
||||
"Chroot directories inside the container",
|
||||
)
|
||||
_ = cmd.RegisterFlagCompletionFunc(chrootDirsFlagName, completion.AutocompleteDefault)
|
||||
|
||||
if registry.IsRemote() {
|
||||
_ = createFlags.MarkHidden("env-host")
|
||||
_ = createFlags.MarkHidden("http-proxy")
|
||||
|
@ -1453,6 +1453,11 @@ After the container is started, the location for the pidfile can be discovered w
|
||||
$ podman inspect --format '{{ .PidFile }}' $CID
|
||||
/run/containers/storage/${storage-driver}-containers/$CID/userdata/pidfile
|
||||
|
||||
#### **--chrootdirs**=*path*
|
||||
|
||||
Path to a directory inside the container that should be treated as a `chroot` directory.
|
||||
Any Podman managed file (e.g., /etc/resolv.conf, /etc/hosts, etc/hostname) that is mounted into the root directory will be mounted into that location as well.
|
||||
Multiple directories should be separated with a comma.
|
||||
|
||||
## EXAMPLES
|
||||
|
||||
|
@ -1529,6 +1529,12 @@ After the container is started, the location for the pidfile can be discovered w
|
||||
$ podman inspect --format '{{ .PidFile }}' $CID
|
||||
/run/containers/storage/${storage-driver}-containers/$CID/userdata/pidfile
|
||||
|
||||
#### **--chrootdirs**=*path*
|
||||
|
||||
Path to a directory inside the container that should be treated as a `chroot` directory.
|
||||
Any Podman managed file (e.g., /etc/resolv.conf, /etc/hosts, etc/hostname) that is mounted into the root directory will be mounted into that location as well.
|
||||
Multiple directories should be separated with a comma.
|
||||
|
||||
## Exit Status
|
||||
|
||||
The exit code from **podman run** gives information about why the container
|
||||
|
@ -165,6 +165,10 @@ type ContainerRootFSConfig struct {
|
||||
Volatile bool `json:"volatile,omitempty"`
|
||||
// Passwd allows to user to override podman's passwd/group file setup
|
||||
Passwd *bool `json:"passwd,omitempty"`
|
||||
// ChrootDirs is an additional set of directories that need to be
|
||||
// treated as root directories. Standard bind mounts will be mounted
|
||||
// into paths relative to these directories.
|
||||
ChrootDirs []string `json:"chroot_directories,omitempty"`
|
||||
}
|
||||
|
||||
// ContainerSecurityConfig is an embedded sub-config providing security configuration
|
||||
|
@ -411,6 +411,7 @@ func (c *Container) generateInspectContainerConfig(spec *spec.Spec) *define.Insp
|
||||
}
|
||||
|
||||
ctrConfig.Passwd = c.config.Passwd
|
||||
ctrConfig.ChrootDirs = append(ctrConfig.ChrootDirs, c.config.ChrootDirs...)
|
||||
|
||||
return ctrConfig
|
||||
}
|
||||
|
@ -1811,6 +1811,17 @@ func (c *Container) getRootNetNsDepCtr() (depCtr *Container, err error) {
|
||||
return depCtr, nil
|
||||
}
|
||||
|
||||
// Ensure standard bind mounts are mounted into all root directories (including chroot directories)
|
||||
func (c *Container) mountIntoRootDirs(mountName string, mountPath string) error {
|
||||
c.state.BindMounts[mountName] = mountPath
|
||||
|
||||
for _, chrootDir := range c.config.ChrootDirs {
|
||||
c.state.BindMounts[filepath.Join(chrootDir, mountName)] = mountPath
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Make standard bind mounts to include in the container
|
||||
func (c *Container) makeBindMounts() error {
|
||||
if err := os.Chown(c.state.RunDir, c.RootUID(), c.RootGID()); err != nil {
|
||||
@ -1864,7 +1875,11 @@ func (c *Container) makeBindMounts() error {
|
||||
// If it doesn't, don't copy them
|
||||
resolvPath, exists := bindMounts["/etc/resolv.conf"]
|
||||
if !c.config.UseImageResolvConf && exists {
|
||||
c.state.BindMounts["/etc/resolv.conf"] = resolvPath
|
||||
err := c.mountIntoRootDirs("/etc/resolv.conf", resolvPath)
|
||||
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error assigning mounts to container %s", c.ID())
|
||||
}
|
||||
}
|
||||
|
||||
// check if dependency container has an /etc/hosts file.
|
||||
@ -1884,7 +1899,11 @@ func (c *Container) makeBindMounts() error {
|
||||
depCtr.lock.Unlock()
|
||||
|
||||
// finally, save it in the new container
|
||||
c.state.BindMounts["/etc/hosts"] = hostsPath
|
||||
err := c.mountIntoRootDirs("/etc/hosts", hostsPath)
|
||||
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error assigning mounts to container %s", c.ID())
|
||||
}
|
||||
}
|
||||
|
||||
if !hasCurrentUserMapped(c) {
|
||||
@ -1901,7 +1920,11 @@ func (c *Container) makeBindMounts() error {
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating resolv.conf for container %s", c.ID())
|
||||
}
|
||||
c.state.BindMounts["/etc/resolv.conf"] = newResolv
|
||||
err = c.mountIntoRootDirs("/etc/resolv.conf", newResolv)
|
||||
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error assigning mounts to container %s", c.ID())
|
||||
}
|
||||
}
|
||||
|
||||
if !c.config.UseImageHosts {
|
||||
@ -2329,7 +2352,11 @@ func (c *Container) updateHosts(path string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.state.BindMounts["/etc/hosts"] = newHosts
|
||||
|
||||
if err = c.mountIntoRootDirs("/etc/hosts", newHosts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -75,6 +75,10 @@ type InspectContainerConfig struct {
|
||||
StopTimeout uint `json:"StopTimeout"`
|
||||
// Passwd determines whether or not podman can add entries to /etc/passwd and /etc/group
|
||||
Passwd *bool `json:"Passwd,omitempty"`
|
||||
// ChrootDirs is an additional set of directories that need to be
|
||||
// treated as root directories. Standard bind mounts will be mounted
|
||||
// into paths relative to these directories.
|
||||
ChrootDirs []string `json:"ChrootDirs,omitempty"`
|
||||
}
|
||||
|
||||
// InspectRestartPolicy holds information about the container's restart policy.
|
||||
|
@ -2036,3 +2036,18 @@ func WithVolatile() CtrCreateOption {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithChrootDirs is an additional set of directories that need to be
|
||||
// treated as root directories. Standard bind mounts will be mounted
|
||||
// into paths relative to these directories.
|
||||
func WithChrootDirs(dirs []string) CtrCreateOption {
|
||||
return func(ctr *Container) error {
|
||||
if ctr.valid {
|
||||
return define.ErrCtrFinalized
|
||||
}
|
||||
|
||||
ctr.config.ChrootDirs = dirs
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -263,6 +263,7 @@ type ContainerCreateOptions struct {
|
||||
Workdir string
|
||||
SeccompPolicy string
|
||||
PidFile string
|
||||
ChrootDirs []string
|
||||
IsInfra bool
|
||||
IsClone bool
|
||||
|
||||
|
@ -526,6 +526,10 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen.
|
||||
options = append(options, libpod.WithPidFile(s.PidFile))
|
||||
}
|
||||
|
||||
if len(s.ChrootDirs) != 0 {
|
||||
options = append(options, libpod.WithChrootDirs(s.ChrootDirs))
|
||||
}
|
||||
|
||||
options = append(options, libpod.WithSelectedPasswordManagement(s.Passwd))
|
||||
|
||||
return options, nil
|
||||
|
@ -301,6 +301,10 @@ type ContainerStorageConfig struct {
|
||||
// Volatile specifies whether the container storage can be optimized
|
||||
// at the cost of not syncing all the dirty files in memory.
|
||||
Volatile bool `json:"volatile,omitempty"`
|
||||
// ChrootDirs is an additional set of directories that need to be
|
||||
// treated as root directories. Standard bind mounts will be mounted
|
||||
// into paths relative to these directories.
|
||||
ChrootDirs []string `json:"chroot_directories,omitempty"`
|
||||
}
|
||||
|
||||
// ContainerSecurityConfig is a container's security features, including
|
||||
|
@ -819,6 +819,9 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions
|
||||
if !s.UnsetEnvAll {
|
||||
s.UnsetEnvAll = c.UnsetEnvAll
|
||||
}
|
||||
if len(s.ChrootDirs) == 0 || len(c.ChrootDirs) != 0 {
|
||||
s.ChrootDirs = c.ChrootDirs
|
||||
}
|
||||
|
||||
// Initcontainers
|
||||
if len(s.InitContainerType) == 0 || len(c.InitContainerType) != 0 {
|
||||
|
@ -706,4 +706,34 @@ var _ = Describe("Podman create", func() {
|
||||
Expect(create.ErrorToString()).To(ContainSubstring("cannot specify a new uid/gid map when entering a pod with an infra container"))
|
||||
|
||||
})
|
||||
|
||||
It("podman create --chrootdirs inspection test", func() {
|
||||
session := podmanTest.Podman([]string{"create", "--chrootdirs", "/var/local/qwerty", ALPINE})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).Should(Exit(0))
|
||||
|
||||
setup := podmanTest.Podman([]string{"container", "inspect", session.OutputToString()})
|
||||
setup.WaitWithDefaultTimeout()
|
||||
Expect(setup).Should(Exit(0))
|
||||
|
||||
data := setup.InspectContainerToJSON()
|
||||
Expect(data).To(HaveLen(1))
|
||||
Expect(data[0].Config.ChrootDirs).To(HaveLen(1))
|
||||
Expect(data[0].Config.ChrootDirs[0]).To(Equal("/var/local/qwerty"))
|
||||
})
|
||||
|
||||
It("podman create --chrootdirs functionality test", func() {
|
||||
session := podmanTest.Podman([]string{"create", "-t", "--chrootdirs", "/var/local/qwerty", ALPINE, "/bin/cat"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session).Should(Exit(0))
|
||||
ctrID := session.OutputToString()
|
||||
|
||||
setup := podmanTest.Podman([]string{"start", ctrID})
|
||||
setup.WaitWithDefaultTimeout()
|
||||
Expect(setup).Should(Exit(0))
|
||||
|
||||
setup = podmanTest.Podman([]string{"exec", ctrID, "cmp", "/etc/resolv.conf", "/var/local/qwerty/etc/resolv.conf"})
|
||||
setup.WaitWithDefaultTimeout()
|
||||
Expect(setup).Should(Exit(0))
|
||||
})
|
||||
})
|
||||
|
Reference in New Issue
Block a user