github.com/zhouyu0/docker-note@v0.0.0-20190722021225-b8d3825084db/pkg/mount/sharedsubtree_linux_test.go (about) 1 // +build linux 2 3 package mount // import "github.com/docker/docker/pkg/mount" 4 5 import ( 6 "os" 7 "path" 8 "testing" 9 10 "github.com/pkg/errors" 11 "golang.org/x/sys/unix" 12 ) 13 14 // nothing is propagated in or out 15 func TestSubtreePrivate(t *testing.T) { 16 if os.Getuid() != 0 { 17 t.Skip("root required") 18 } 19 20 tmp := path.Join(os.TempDir(), "mount-tests") 21 if err := os.MkdirAll(tmp, 0777); err != nil { 22 t.Fatal(err) 23 } 24 defer os.RemoveAll(tmp) 25 26 var ( 27 sourceDir = path.Join(tmp, "source") 28 targetDir = path.Join(tmp, "target") 29 outside1Dir = path.Join(tmp, "outside1") 30 outside2Dir = path.Join(tmp, "outside2") 31 32 outside1Path = path.Join(outside1Dir, "file.txt") 33 outside2Path = path.Join(outside2Dir, "file.txt") 34 outside1CheckPath = path.Join(targetDir, "a", "file.txt") 35 outside2CheckPath = path.Join(sourceDir, "b", "file.txt") 36 ) 37 if err := os.MkdirAll(path.Join(sourceDir, "a"), 0777); err != nil { 38 t.Fatal(err) 39 } 40 if err := os.MkdirAll(path.Join(sourceDir, "b"), 0777); err != nil { 41 t.Fatal(err) 42 } 43 if err := os.Mkdir(targetDir, 0777); err != nil { 44 t.Fatal(err) 45 } 46 if err := os.Mkdir(outside1Dir, 0777); err != nil { 47 t.Fatal(err) 48 } 49 if err := os.Mkdir(outside2Dir, 0777); err != nil { 50 t.Fatal(err) 51 } 52 53 if err := createFile(outside1Path); err != nil { 54 t.Fatal(err) 55 } 56 if err := createFile(outside2Path); err != nil { 57 t.Fatal(err) 58 } 59 60 // mount the shared directory to a target 61 if err := Mount(sourceDir, targetDir, "none", "bind,rw"); err != nil { 62 t.Fatal(err) 63 } 64 defer func() { 65 if err := Unmount(targetDir); err != nil { 66 t.Fatal(err) 67 } 68 }() 69 70 // next, make the target private 71 if err := MakePrivate(targetDir); err != nil { 72 t.Fatal(err) 73 } 74 defer func() { 75 if err := Unmount(targetDir); err != nil { 76 t.Fatal(err) 77 } 78 }() 79 80 // mount in an outside path to a mounted path inside the _source_ 81 if err := Mount(outside1Dir, path.Join(sourceDir, "a"), "none", "bind,rw"); err != nil { 82 t.Fatal(err) 83 } 84 defer func() { 85 if err := Unmount(path.Join(sourceDir, "a")); err != nil { 86 t.Fatal(err) 87 } 88 }() 89 90 // check that this file _does_not_ show in the _target_ 91 if _, err := os.Stat(outside1CheckPath); err != nil && !os.IsNotExist(err) { 92 t.Fatal(err) 93 } else if err == nil { 94 t.Fatalf("%q should not be visible, but is", outside1CheckPath) 95 } 96 97 // next mount outside2Dir into the _target_ 98 if err := Mount(outside2Dir, path.Join(targetDir, "b"), "none", "bind,rw"); err != nil { 99 t.Fatal(err) 100 } 101 defer func() { 102 if err := Unmount(path.Join(targetDir, "b")); err != nil { 103 t.Fatal(err) 104 } 105 }() 106 107 // check that this file _does_not_ show in the _source_ 108 if _, err := os.Stat(outside2CheckPath); err != nil && !os.IsNotExist(err) { 109 t.Fatal(err) 110 } else if err == nil { 111 t.Fatalf("%q should not be visible, but is", outside2CheckPath) 112 } 113 } 114 115 // Testing that when a target is a shared mount, 116 // then child mounts propagate to the source 117 func TestSubtreeShared(t *testing.T) { 118 if os.Getuid() != 0 { 119 t.Skip("root required") 120 } 121 122 tmp := path.Join(os.TempDir(), "mount-tests") 123 if err := os.MkdirAll(tmp, 0777); err != nil { 124 t.Fatal(err) 125 } 126 defer os.RemoveAll(tmp) 127 128 var ( 129 sourceDir = path.Join(tmp, "source") 130 targetDir = path.Join(tmp, "target") 131 outsideDir = path.Join(tmp, "outside") 132 133 outsidePath = path.Join(outsideDir, "file.txt") 134 sourceCheckPath = path.Join(sourceDir, "a", "file.txt") 135 ) 136 137 if err := os.MkdirAll(path.Join(sourceDir, "a"), 0777); err != nil { 138 t.Fatal(err) 139 } 140 if err := os.Mkdir(targetDir, 0777); err != nil { 141 t.Fatal(err) 142 } 143 if err := os.Mkdir(outsideDir, 0777); err != nil { 144 t.Fatal(err) 145 } 146 147 if err := createFile(outsidePath); err != nil { 148 t.Fatal(err) 149 } 150 151 // mount the source as shared 152 if err := MakeShared(sourceDir); err != nil { 153 t.Fatal(err) 154 } 155 defer func() { 156 if err := Unmount(sourceDir); err != nil { 157 t.Fatal(err) 158 } 159 }() 160 161 // mount the shared directory to a target 162 if err := Mount(sourceDir, targetDir, "none", "bind,rw"); err != nil { 163 t.Fatal(err) 164 } 165 defer func() { 166 if err := Unmount(targetDir); err != nil { 167 t.Fatal(err) 168 } 169 }() 170 171 // mount in an outside path to a mounted path inside the target 172 if err := Mount(outsideDir, path.Join(targetDir, "a"), "none", "bind,rw"); err != nil { 173 t.Fatal(err) 174 } 175 defer func() { 176 if err := Unmount(path.Join(targetDir, "a")); err != nil { 177 t.Fatal(err) 178 } 179 }() 180 181 // NOW, check that the file from the outside directory is available in the source directory 182 if _, err := os.Stat(sourceCheckPath); err != nil { 183 t.Fatal(err) 184 } 185 } 186 187 // testing that mounts to a shared source show up in the slave target, 188 // and that mounts into a slave target do _not_ show up in the shared source 189 func TestSubtreeSharedSlave(t *testing.T) { 190 if os.Getuid() != 0 { 191 t.Skip("root required") 192 } 193 194 tmp := path.Join(os.TempDir(), "mount-tests") 195 if err := os.MkdirAll(tmp, 0777); err != nil { 196 t.Fatal(err) 197 } 198 defer os.RemoveAll(tmp) 199 200 var ( 201 sourceDir = path.Join(tmp, "source") 202 targetDir = path.Join(tmp, "target") 203 outside1Dir = path.Join(tmp, "outside1") 204 outside2Dir = path.Join(tmp, "outside2") 205 206 outside1Path = path.Join(outside1Dir, "file.txt") 207 outside2Path = path.Join(outside2Dir, "file.txt") 208 outside1CheckPath = path.Join(targetDir, "a", "file.txt") 209 outside2CheckPath = path.Join(sourceDir, "b", "file.txt") 210 ) 211 if err := os.MkdirAll(path.Join(sourceDir, "a"), 0777); err != nil { 212 t.Fatal(err) 213 } 214 if err := os.MkdirAll(path.Join(sourceDir, "b"), 0777); err != nil { 215 t.Fatal(err) 216 } 217 if err := os.Mkdir(targetDir, 0777); err != nil { 218 t.Fatal(err) 219 } 220 if err := os.Mkdir(outside1Dir, 0777); err != nil { 221 t.Fatal(err) 222 } 223 if err := os.Mkdir(outside2Dir, 0777); err != nil { 224 t.Fatal(err) 225 } 226 227 if err := createFile(outside1Path); err != nil { 228 t.Fatal(err) 229 } 230 if err := createFile(outside2Path); err != nil { 231 t.Fatal(err) 232 } 233 234 // mount the source as shared 235 if err := MakeShared(sourceDir); err != nil { 236 t.Fatal(err) 237 } 238 defer func() { 239 if err := Unmount(sourceDir); err != nil { 240 t.Fatal(err) 241 } 242 }() 243 244 // mount the shared directory to a target 245 if err := Mount(sourceDir, targetDir, "none", "bind,rw"); err != nil { 246 t.Fatal(err) 247 } 248 defer func() { 249 if err := Unmount(targetDir); err != nil { 250 t.Fatal(err) 251 } 252 }() 253 254 // next, make the target slave 255 if err := MakeSlave(targetDir); err != nil { 256 t.Fatal(err) 257 } 258 defer func() { 259 if err := Unmount(targetDir); err != nil { 260 t.Fatal(err) 261 } 262 }() 263 264 // mount in an outside path to a mounted path inside the _source_ 265 if err := Mount(outside1Dir, path.Join(sourceDir, "a"), "none", "bind,rw"); err != nil { 266 t.Fatal(err) 267 } 268 defer func() { 269 if err := Unmount(path.Join(sourceDir, "a")); err != nil { 270 t.Fatal(err) 271 } 272 }() 273 274 // check that this file _does_ show in the _target_ 275 if _, err := os.Stat(outside1CheckPath); err != nil { 276 t.Fatal(err) 277 } 278 279 // next mount outside2Dir into the _target_ 280 if err := Mount(outside2Dir, path.Join(targetDir, "b"), "none", "bind,rw"); err != nil { 281 t.Fatal(err) 282 } 283 defer func() { 284 if err := Unmount(path.Join(targetDir, "b")); err != nil { 285 t.Fatal(err) 286 } 287 }() 288 289 // check that this file _does_not_ show in the _source_ 290 if _, err := os.Stat(outside2CheckPath); err != nil && !os.IsNotExist(err) { 291 t.Fatal(err) 292 } else if err == nil { 293 t.Fatalf("%q should not be visible, but is", outside2CheckPath) 294 } 295 } 296 297 func TestSubtreeUnbindable(t *testing.T) { 298 if os.Getuid() != 0 { 299 t.Skip("root required") 300 } 301 302 tmp := path.Join(os.TempDir(), "mount-tests") 303 if err := os.MkdirAll(tmp, 0777); err != nil { 304 t.Fatal(err) 305 } 306 defer os.RemoveAll(tmp) 307 308 var ( 309 sourceDir = path.Join(tmp, "source") 310 targetDir = path.Join(tmp, "target") 311 ) 312 if err := os.MkdirAll(sourceDir, 0777); err != nil { 313 t.Fatal(err) 314 } 315 if err := os.MkdirAll(targetDir, 0777); err != nil { 316 t.Fatal(err) 317 } 318 319 // next, make the source unbindable 320 if err := MakeUnbindable(sourceDir); err != nil { 321 t.Fatal(err) 322 } 323 defer func() { 324 if err := Unmount(sourceDir); err != nil { 325 t.Fatal(err) 326 } 327 }() 328 329 // then attempt to mount it to target. It should fail 330 if err := Mount(sourceDir, targetDir, "none", "bind,rw"); err != nil && errors.Cause(err) != unix.EINVAL { 331 t.Fatal(err) 332 } else if err == nil { 333 t.Fatalf("%q should not have been bindable", sourceDir) 334 } 335 defer func() { 336 if err := Unmount(targetDir); err != nil { 337 t.Fatal(err) 338 } 339 }() 340 } 341 342 func createFile(path string) error { 343 f, err := os.Create(path) 344 if err != nil { 345 return err 346 } 347 f.WriteString("hello world!") 348 return f.Close() 349 }