From 91f29837cd92245bc6f3fd0664c3d782542bc195 Mon Sep 17 00:00:00 2001 From: Dongsu Park Date: Thu, 31 May 2018 13:01:11 +0200 Subject: [PATCH 1/4] validation: more test cases for readonly paths tests Split out the test function into `checkReadonlyPaths()`, and add more cases for readonly paths like subdirectory, file under subdirectory, and directory under subdirectory. Signed-off-by: Dongsu Park --- validation/linux_readonly_paths.go | 45 ++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/validation/linux_readonly_paths.go b/validation/linux_readonly_paths.go index 1f2d1263..fbd91861 100644 --- a/validation/linux_readonly_paths.go +++ b/validation/linux_readonly_paths.go @@ -8,15 +8,30 @@ import ( "github.com/opencontainers/runtime-tools/validation/util" ) -func main() { +func checkReadonlyPaths() error { g, err := util.GetDefaultGenerator() if err != nil { - util.Fatal(err) + return err } - g.AddLinuxReadonlyPaths("/readonly-dir") - g.AddLinuxReadonlyPaths("/readonly-file") + + readonlyDir := "readonly-dir" + readonlySubDir := "readonly-subdir" + readonlyFile := "readonly-file" + + readonlyDirTop := filepath.Join("/", readonlyDir) + readonlyFileTop := filepath.Join("/", readonlyFile) + + readonlyDirSub := filepath.Join(readonlyDirTop, readonlySubDir) + readonlyFileSub := filepath.Join(readonlyDirTop, readonlyFile) + readonlyFileSubSub := filepath.Join(readonlyDirSub, readonlyFile) + + g.AddLinuxReadonlyPaths(readonlyDirTop) + g.AddLinuxReadonlyPaths(readonlyFileTop) + g.AddLinuxReadonlyPaths(readonlyDirSub) + g.AddLinuxReadonlyPaths(readonlyFileSub) + g.AddLinuxReadonlyPaths(readonlyFileSubSub) err = util.RuntimeInsideValidate(g, func(path string) error { - testDir := filepath.Join(path, "readonly-dir") + testDir := filepath.Join(path, readonlyDirSub) err = os.MkdirAll(testDir, 0777) if err != nil { return err @@ -28,13 +43,27 @@ func main() { } defer os.Remove(tmpfile.Name()) - testFile := filepath.Join(path, "readonly-file") - // runtimetest cannot check the readability of empty files, so // write something. + testSubSubFile := filepath.Join(path, readonlyFileSubSub) + if err := ioutil.WriteFile(testSubSubFile, []byte("immutable"), 0777); err != nil { + return err + } + + testSubFile := filepath.Join(path, readonlyFileSub) + if err := ioutil.WriteFile(testSubFile, []byte("immutable"), 0777); err != nil { + return err + } + + testFile := filepath.Join(path, readonlyFile) return ioutil.WriteFile(testFile, []byte("immutable"), 0777) }) - if err != nil { + return err +} + +func main() { + if err := checkReadonlyPaths(); err != nil { util.Fatal(err) } + } From 5dd461f2bfb731703374ac9334dfda143e147959 Mon Sep 17 00:00:00 2001 From: Dongsu Park Date: Thu, 31 May 2018 13:05:55 +0200 Subject: [PATCH 2/4] validation: check for a read-only relative path Test inside container should return error if a relative path is given for read-only paths. Signed-off-by: Dongsu Park --- validation/linux_readonly_paths.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/validation/linux_readonly_paths.go b/validation/linux_readonly_paths.go index fbd91861..73c03c79 100644 --- a/validation/linux_readonly_paths.go +++ b/validation/linux_readonly_paths.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "io/ioutil" "os" "path/filepath" @@ -61,9 +62,36 @@ func checkReadonlyPaths() error { return err } +func checkReadonlyRelPaths() error { + g, err := util.GetDefaultGenerator() + if err != nil { + return err + } + + // Deliberately set a relative path to be read-only, and expect an error + readonlyRelPath := "readonly-relpath" + + g.AddLinuxReadonlyPaths(readonlyRelPath) + err = util.RuntimeInsideValidate(g, func(path string) error { + testFile := filepath.Join(path, readonlyRelPath) + if _, err := os.Stat(testFile); err != nil && os.IsNotExist(err) { + return err + } + + return nil + }) + if err != nil { + return nil + } + return fmt.Errorf("expected: err != nil, actual: err == nil") +} + func main() { if err := checkReadonlyPaths(); err != nil { util.Fatal(err) } + if err := checkReadonlyRelPaths(); err != nil { + util.Fatal(err) + } } From e60cd0691d7b92c60cfb21cda30ed756c686771a Mon Sep 17 00:00:00 2001 From: Dongsu Park Date: Thu, 31 May 2018 13:08:22 +0200 Subject: [PATCH 3/4] validation: check for invalid symlink inside container Deliberately create an invalid read-only symlink that points out of the container, to see if the test fails inside the container. Signed-off-by: Dongsu Park --- validation/linux_readonly_paths.go | 39 ++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/validation/linux_readonly_paths.go b/validation/linux_readonly_paths.go index 73c03c79..0e5c42ed 100644 --- a/validation/linux_readonly_paths.go +++ b/validation/linux_readonly_paths.go @@ -86,6 +86,40 @@ func checkReadonlyRelPaths() error { return fmt.Errorf("expected: err != nil, actual: err == nil") } +func checkReadonlySymlinks() error { + g, err := util.GetDefaultGenerator() + if err != nil { + return err + } + + // Deliberately create a read-only symlink that points an invalid file, + // and expect an error. + readonlySymlink := "/readonly-symlink" + + g.AddLinuxReadonlyPaths(readonlySymlink) + err = util.RuntimeInsideValidate(g, func(path string) error { + testFile := filepath.Join(path, readonlySymlink) + // ln -s .. /readonly-symlink ; readlink -f /readonly-symlink; ls -L /readonly-symlink + if err := os.Symlink("../readonly-symlink", testFile); err != nil { + return err + } + rPath, errR := os.Readlink(testFile) + if errR != nil { + return errR + } + _, errS := os.Stat(rPath) + if errS != nil && os.IsNotExist(errS) { + return errS + } + + return nil + }) + if err != nil { + return nil + } + return fmt.Errorf("expected: err != nil, actual: err == nil") +} + func main() { if err := checkReadonlyPaths(); err != nil { util.Fatal(err) @@ -94,4 +128,9 @@ func main() { if err := checkReadonlyRelPaths(); err != nil { util.Fatal(err) } + + if err := checkReadonlySymlinks(); err != nil { + util.Fatal(err) + } + } From 303ae301e6aa2719d58db2c99a1f97f18cfd8498 Mon Sep 17 00:00:00 2001 From: Dongsu Park Date: Thu, 31 May 2018 13:12:40 +0200 Subject: [PATCH 4/4] validation: check for read-only block, char devices, fifo Create read-only block device, char device, and fifo, to check if they are read-only as expected. Signed-off-by: Dongsu Park --- validation/linux_readonly_paths.go | 38 ++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/validation/linux_readonly_paths.go b/validation/linux_readonly_paths.go index 0e5c42ed..6a784065 100644 --- a/validation/linux_readonly_paths.go +++ b/validation/linux_readonly_paths.go @@ -7,6 +7,7 @@ import ( "path/filepath" "github.com/opencontainers/runtime-tools/validation/util" + "golang.org/x/sys/unix" ) func checkReadonlyPaths() error { @@ -120,6 +121,30 @@ func checkReadonlySymlinks() error { return fmt.Errorf("expected: err != nil, actual: err == nil") } +func checkReadonlyDeviceNodes(mode uint32) error { + g, err := util.GetDefaultGenerator() + if err != nil { + return err + } + + readonlyDevice := "/readonly-device" + + g.AddLinuxReadonlyPaths(readonlyDevice) + return util.RuntimeInsideValidate(g, func(path string) error { + testFile := filepath.Join(path, readonlyDevice) + + if err := unix.Mknod(testFile, mode, 0); err != nil { + return err + } + + if _, err := os.Stat(testFile); err != nil && os.IsNotExist(err) { + return err + } + + return nil + }) +} + func main() { if err := checkReadonlyPaths(); err != nil { util.Fatal(err) @@ -133,4 +158,17 @@ func main() { util.Fatal(err) } + // test creation of different type of devices, i.e. block device, + // character device, and FIFO. + modes := []uint32{ + unix.S_IFBLK | 0666, + unix.S_IFCHR | 0666, + unix.S_IFIFO | 0666, + } + + for _, m := range modes { + if err := checkReadonlyDeviceNodes(m); err != nil { + util.Fatal(err) + } + } }