mirror of
https://github.com/opencontainers/runc.git
synced 2026-11-06 05:17:05 +00:00
libct: don't change host mounts propagation
When the container does not have its own mount namespace, prepareRoot
is run in the host mount namespace. Since commit 91ca3314 ("chroot when
no mount namespaces is provided"), this results in host's / being
recursively made a slave (which, in the host mount namespace, means
private), and the parent mount of the container rootfs being made
private (or slave).
In the host mount namespace, do not change the propagation of the
existing mounts. Instead, make the new rootfs mount a slave, so that
container mounts do not propagate to the host and other mount
namespaces (otherwise, if the rootfs parent mount is shared, every
container mount appears twice in the host mount namespace, and is
propagated to all its slaves).
Add an integration test.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This commit is contained in:
1 parent
7f0569a822
commit
bd825f99bc
3 files changed
+41
-1
No files matched your search
@@ -22,6 +22,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
mount namespace, and without one, container mounts (such as `/proc`) were
|
||||
mounted on top of the host ones. (#5535)
|
||||
|
||||
### Fixed ###
|
||||
- Running a container which does not have its own mount namespace no longer
|
||||
changes the propagation of host's `/` and of the parent mount of the
|
||||
container rootfs (they were made private or slave). (#5537)
|
||||
|
||||
## [1.6.0-rc.1] - 2026-10-06
|
||||
|
||||
> Lo bueno, si breve, dos veces bueno.
|
||||
|
||||
@@ -169,7 +169,11 @@ func setupAndMountToRootfs(pipe *syncSocket, config *configs.Config, mountConfig
|
||||
// finalizeRootfs after this function to finish setting up the rootfs.
|
||||
func prepareRootfs(pipe *syncSocket, iConfig *initConfig) (err error) {
|
||||
config := iConfig.Config
|
||||
if err := prepareRoot(config); err != nil {
|
||||
prepare := prepareRoot
|
||||
if !config.Namespaces.Contains(configs.NEWNS) {
|
||||
prepare = prepareRootInHostMountNS
|
||||
}
|
||||
if err := prepare(config); err != nil {
|
||||
return fmt.Errorf("error preparing rootfs: %w", err)
|
||||
}
|
||||
|
||||
@@ -1112,6 +1116,18 @@ func prepareRoot(config *configs.Config) error {
|
||||
return mount(config.Rootfs, config.Rootfs, "bind", unix.MS_BIND|unix.MS_REC, "")
|
||||
}
|
||||
|
||||
// prepareRootInHostMountNS is like prepareRoot, but for a container that
|
||||
// runs in the host mount namespace. The propagation of existing mounts
|
||||
// must not be changed, as this would affect the host.
|
||||
func prepareRootInHostMountNS(config *configs.Config) error {
|
||||
if err := mount(config.Rootfs, config.Rootfs, "bind", unix.MS_BIND|unix.MS_REC, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
// Make the new rootfs mount a slave, so that container mounts
|
||||
// do not propagate to the host (and other mount namespaces).
|
||||
return mount("", config.Rootfs, "", unix.MS_SLAVE|unix.MS_REC, "")
|
||||
}
|
||||
|
||||
func setReadonly() error {
|
||||
flags := uintptr(unix.MS_BIND | unix.MS_REMOUNT | unix.MS_RDONLY)
|
||||
|
||||
|
||||
@@ -17,6 +17,25 @@ function teardown() {
|
||||
teardown_bundle
|
||||
}
|
||||
|
||||
# This test goes first, since without the fix, any test which runs
|
||||
# a container in the host mount namespace changes the host mounts
|
||||
# propagation, so the bug would go unnoticed.
|
||||
@test "runc run [host mount ns] must not change host mounts propagation" {
|
||||
update_config ' .process.args = ["true"]
|
||||
| .linux.namespaces -= [{"type": "mount"}]
|
||||
| .linux.maskedPaths = []
|
||||
| .linux.readonlyPaths = []
|
||||
| .root.readonly = false'
|
||||
|
||||
# Check / and the mount the container bundle resides on.
|
||||
before=$(findmnt -n -o TARGET,PROPAGATION / && findmnt -n -o TARGET,PROPAGATION -T "$ROOT/bundle")
|
||||
run -0 runc run test_host_mntns
|
||||
after=$(findmnt -n -o TARGET,PROPAGATION / && findmnt -n -o TARGET,PROPAGATION -T "$ROOT/bundle")
|
||||
echo "before: $before"
|
||||
echo "after: $after"
|
||||
[ "$before" = "$after" ]
|
||||
}
|
||||
|
||||
@test "runc run [host mount ns + hooks]" {
|
||||
update_config ' .process.args = ["/bin/echo", "Hello World"]
|
||||
| .hooks |= . + {"createRuntime": [{"path": "/bin/sh", "args": ["/bin/sh", "-c", "touch createRuntimeHook.$$"]}]}
|
||||
|
||||
Reference in new issue
Block a user