github.com/opencontainers/runtime-tools@v0.9.0/validation/linux_masked_paths/linux_masked_paths.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 9 "github.com/mndrix/tap-go" 10 "github.com/opencontainers/runtime-tools/validation/util" 11 "golang.org/x/sys/unix" 12 ) 13 14 func checkMaskedPaths(t *tap.T) error { 15 g, err := util.GetDefaultGenerator() 16 if err != nil { 17 return err 18 } 19 20 maskedDir := "masked-dir" 21 maskedSubDir := "masked-subdir" 22 maskedFile := "masked-file" 23 24 maskedDirTop := filepath.Join("/", maskedDir) 25 maskedFileTop := filepath.Join("/", maskedFile) 26 27 maskedDirSub := filepath.Join(maskedDirTop, maskedSubDir) 28 maskedFileSub := filepath.Join(maskedDirTop, maskedFile) 29 maskedFileSubSub := filepath.Join(maskedDirSub, maskedFile) 30 31 g.AddLinuxMaskedPaths(maskedDirTop) 32 g.AddLinuxMaskedPaths(maskedFileTop) 33 g.AddLinuxMaskedPaths(maskedDirSub) 34 g.AddLinuxMaskedPaths(maskedFileSub) 35 g.AddLinuxMaskedPaths(maskedFileSubSub) 36 g.AddAnnotation("TestName", "check masked paths") 37 err = util.RuntimeInsideValidate(g, t, func(path string) error { 38 testDir := filepath.Join(path, maskedDirSub) 39 err = os.MkdirAll(testDir, 0777) 40 if err != nil { 41 return err 42 } 43 // create a temp file to make testDir non-empty 44 tmpfile, err := ioutil.TempFile(testDir, "tmp") 45 if err != nil { 46 return err 47 } 48 defer os.Remove(tmpfile.Name()) 49 50 // runtimetest cannot check the readability of empty files, so 51 // write something. 52 testSubSubFile := filepath.Join(path, maskedFileSubSub) 53 if err := ioutil.WriteFile(testSubSubFile, []byte("secrets"), 0777); err != nil { 54 return err 55 } 56 57 testSubFile := filepath.Join(path, maskedFileSub) 58 if err := ioutil.WriteFile(testSubFile, []byte("secrets"), 0777); err != nil { 59 return err 60 } 61 62 testFile := filepath.Join(path, maskedFile) 63 return ioutil.WriteFile(testFile, []byte("secrets"), 0777) 64 }) 65 return err 66 } 67 68 func checkMaskedRelPaths(t *tap.T) error { 69 g, err := util.GetDefaultGenerator() 70 if err != nil { 71 return err 72 } 73 74 // Deliberately set a relative path to be masked, and expect an error 75 maskedRelPath := "masked-relpath" 76 77 g.AddLinuxMaskedPaths(maskedRelPath) 78 g.AddAnnotation("TestName", "check masked relative paths") 79 err = util.RuntimeInsideValidate(g, t, func(path string) error { 80 testFile := filepath.Join(path, maskedRelPath) 81 if _, err := os.Stat(testFile); err != nil && os.IsNotExist(err) { 82 return err 83 } 84 85 return nil 86 }) 87 if err != nil { 88 return nil 89 } 90 return fmt.Errorf("expected: err != nil, actual: err == nil") 91 } 92 93 func checkMaskedSymlinks(t *tap.T) error { 94 g, err := util.GetDefaultGenerator() 95 if err != nil { 96 return err 97 } 98 99 // Deliberately create a masked symlink that points an invalid file, 100 // and expect an error. 101 maskedSymlink := "/masked-symlink" 102 103 g.AddLinuxMaskedPaths(maskedSymlink) 104 g.AddAnnotation("TestName", "check masked symlinks") 105 err = util.RuntimeInsideValidate(g, t, func(path string) error { 106 testFile := filepath.Join(path, maskedSymlink) 107 // ln -s .. /masked-symlink ; readlink -f /masked-symlink; ls -L /masked-symlink 108 if err := os.Symlink("../masked-symlink", testFile); err != nil { 109 return err 110 } 111 rPath, errR := os.Readlink(testFile) 112 if errR != nil { 113 return errR 114 } 115 _, errS := os.Stat(rPath) 116 if errS != nil && os.IsNotExist(errS) { 117 return errS 118 } 119 120 return nil 121 }) 122 if err != nil { 123 return nil 124 } 125 return fmt.Errorf("expected: err != nil, actual: err == nil") 126 } 127 128 func checkMaskedDeviceNodes(t *tap.T, mode uint32) error { 129 g, err := util.GetDefaultGenerator() 130 if err != nil { 131 return err 132 } 133 134 maskedDevice := "/masked-device" 135 136 g.AddLinuxMaskedPaths(maskedDevice) 137 g.AddAnnotation("TestName", "check masked device nodes") 138 return util.RuntimeInsideValidate(g, t, func(path string) error { 139 testFile := filepath.Join(path, maskedDevice) 140 141 if err := unix.Mknod(testFile, mode, 0); err != nil { 142 return err 143 } 144 145 if _, err := os.Stat(testFile); err != nil && os.IsNotExist(err) { 146 return err 147 } 148 149 return nil 150 }) 151 } 152 153 func main() { 154 t := tap.New() 155 t.Header(0) 156 defer t.AutoPlan() 157 158 if err := checkMaskedPaths(t); err != nil { 159 util.Fatal(err) 160 } 161 162 if err := checkMaskedRelPaths(t); err != nil { 163 util.Fatal(err) 164 } 165 166 if err := checkMaskedSymlinks(t); err != nil { 167 util.Fatal(err) 168 } 169 170 // test creation of different type of devices, i.e. block device, 171 // character device, and FIFO. 172 modes := []uint32{ 173 unix.S_IFBLK | 0666, 174 unix.S_IFCHR | 0666, 175 unix.S_IFIFO | 0666, 176 } 177 178 for _, m := range modes { 179 if err := checkMaskedDeviceNodes(t, m); err != nil { 180 util.Fatal(err) 181 } 182 } 183 }