Skip to content

Commit 1a24909

Browse files
author
Zhou Hao
authored
Merge pull request #511 from Mashimiao/add-rootfs-propagation
runtimetest: add rootfs propagation test
2 parents 7d57b31 + 7026311 commit 1a24909

2 files changed

Lines changed: 95 additions & 0 deletions

File tree

cmd/runtimetest/main.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import (
2424
"github.com/opencontainers/runtime-tools/cmd/runtimetest/mount"
2525
rfc2119 "github.com/opencontainers/runtime-tools/error"
2626
"github.com/opencontainers/runtime-tools/specerror"
27+
28+
"golang.org/x/sys/unix"
2729
)
2830

2931
// PrGetNoNewPrivs isn't exposed in Golang so we define it ourselves copying the value from
@@ -346,6 +348,71 @@ func validateRootFS(spec *rspec.Spec) error {
346348
return nil
347349
}
348350

351+
func validateRootfsPropagation(spec *rspec.Spec) error {
352+
if spec.Linux == nil || spec.Linux.RootfsPropagation == "" {
353+
return nil
354+
}
355+
356+
targetDir, err := ioutil.TempDir("/", "target")
357+
if err != nil {
358+
return err
359+
}
360+
defer os.RemoveAll(targetDir)
361+
362+
switch spec.Linux.RootfsPropagation {
363+
case "shared", "slave", "private":
364+
mountDir, err := ioutil.TempDir("/", "mount")
365+
if err != nil {
366+
return err
367+
}
368+
defer os.RemoveAll(mountDir)
369+
370+
testDir, err := ioutil.TempDir("/", "test")
371+
if err != nil {
372+
return err
373+
}
374+
defer os.RemoveAll(testDir)
375+
376+
tmpfile, err := ioutil.TempFile(testDir, "example")
377+
if err != nil {
378+
return err
379+
}
380+
defer os.Remove(tmpfile.Name())
381+
382+
if err := unix.Mount("/", targetDir, "", unix.MS_BIND|unix.MS_REC, ""); err != nil {
383+
return err
384+
}
385+
defer unix.Unmount(targetDir, unix.MNT_DETACH)
386+
if err := unix.Mount(testDir, mountDir, "", unix.MS_BIND|unix.MS_REC, ""); err != nil {
387+
return err
388+
}
389+
defer unix.Unmount(mountDir, unix.MNT_DETACH)
390+
if _, err := os.Stat(filepath.Join(targetDir, filepath.Join(mountDir, filepath.Base(tmpfile.Name())))); os.IsNotExist(err) {
391+
if spec.Linux.RootfsPropagation == "shared" {
392+
return fmt.Errorf("rootfs should be %s, but not", spec.Linux.RootfsPropagation)
393+
}
394+
return nil
395+
}
396+
if spec.Linux.RootfsPropagation == "shared" {
397+
return nil
398+
}
399+
return fmt.Errorf("rootfs should be %s, but not", spec.Linux.RootfsPropagation)
400+
case "unbindable":
401+
if err := unix.Mount("/", targetDir, "", unix.MS_BIND|unix.MS_REC, ""); err != nil {
402+
if err == syscall.EINVAL {
403+
return nil
404+
}
405+
return err
406+
}
407+
defer unix.Unmount(targetDir, unix.MNT_DETACH)
408+
return fmt.Errorf("rootfs expected to be unbindable, but not")
409+
default:
410+
logrus.Warnf("unrecognized linux.rootfsPropagation %s", spec.Linux.RootfsPropagation)
411+
}
412+
413+
return nil
414+
}
415+
349416
func validateDefaultFS(spec *rspec.Spec) error {
350417
mountInfos, err := mount.GetMounts()
351418
if err != nil {
@@ -779,6 +846,10 @@ func run(context *cli.Context) error {
779846
test: validateROPaths,
780847
description: "read only paths",
781848
},
849+
{
850+
test: validateRootfsPropagation,
851+
description: "rootfs propagation",
852+
},
782853
{
783854
test: validateSysctls,
784855
description: "sysctls",

validation/validation_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,30 @@ func TestValidateHostname(t *testing.T) {
116116
assert.Nil(t, runtimeInsideValidate(g))
117117
}
118118

119+
func TestValidateRootfsPropagationPrivate(t *testing.T) {
120+
t.Skip("has not been implemented yet")
121+
}
122+
123+
func TestValidateRootfsPropagationSlave(t *testing.T) {
124+
t.Skip("has not been implemented yet")
125+
}
126+
127+
func TestValidateRootfsPropagationShared(t *testing.T) {
128+
g := getDefaultGenerator()
129+
g.SetupPrivileged(true)
130+
g.SetLinuxRootPropagation("shared")
131+
132+
assert.Nil(t, runtimeInsideValidate(g))
133+
}
134+
135+
func TestValidateRootfsPropagationUnbindable(t *testing.T) {
136+
g := getDefaultGenerator()
137+
g.SetupPrivileged(true)
138+
g.SetLinuxRootPropagation("unbindable")
139+
140+
assert.Nil(t, runtimeInsideValidate(g))
141+
}
142+
119143
// Test whether mounts are correctly mounted
120144
func TestValidateMounts(t *testing.T) {
121145
// TODO mounts generation options have not been implemented

0 commit comments

Comments
 (0)