| ... | ... |
@@ -301,3 +301,14 @@ func TestDockerRunWithRelativePath(t *testing.T) {
|
| 301 | 301 |
|
| 302 | 302 |
logDone("run - volume with relative path")
|
| 303 | 303 |
} |
| 304 |
+ |
|
| 305 |
+func TestVolumesMountedAsReadonly(t *testing.T) {
|
|
| 306 |
+ cmd := exec.Command(dockerBinary, "run", "-v", "/test:/test:ro", "busybox", "touch", "/test/somefile") |
|
| 307 |
+ if code, err := runCommand(cmd); err == nil || code == 0 {
|
|
| 308 |
+ t.Fatalf("run should fail because volume is ro: exit code %d", code)
|
|
| 309 |
+ } |
|
| 310 |
+ |
|
| 311 |
+ deleteAllContainers() |
|
| 312 |
+ |
|
| 313 |
+ logDone("run - volumes as readonly mount")
|
|
| 314 |
+} |
| ... | ... |
@@ -37,14 +37,21 @@ func setupNewMountNamespace(rootfs string, bindMounts []libcontainer.Mount, cons |
| 37 | 37 |
} |
| 38 | 38 |
|
| 39 | 39 |
for _, m := range bindMounts {
|
| 40 |
- flags := syscall.MS_BIND | syscall.MS_REC |
|
| 40 |
+ var ( |
|
| 41 |
+ flags = syscall.MS_BIND | syscall.MS_REC |
|
| 42 |
+ dest = filepath.Join(rootfs, m.Destination) |
|
| 43 |
+ ) |
|
| 41 | 44 |
if !m.Writable {
|
| 42 | 45 |
flags = flags | syscall.MS_RDONLY |
| 43 | 46 |
} |
| 44 |
- dest := filepath.Join(rootfs, m.Destination) |
|
| 45 | 47 |
if err := system.Mount(m.Source, dest, "bind", uintptr(flags), ""); err != nil {
|
| 46 | 48 |
return fmt.Errorf("mounting %s into %s %s", m.Source, dest, err)
|
| 47 | 49 |
} |
| 50 |
+ if !m.Writable {
|
|
| 51 |
+ if err := system.Mount(m.Source, dest, "bind", uintptr(flags|syscall.MS_REMOUNT), ""); err != nil {
|
|
| 52 |
+ return fmt.Errorf("remounting %s into %s %s", m.Source, dest, err)
|
|
| 53 |
+ } |
|
| 54 |
+ } |
|
| 48 | 55 |
if m.Private {
|
| 49 | 56 |
if err := system.Mount("", dest, "none", uintptr(syscall.MS_PRIVATE), ""); err != nil {
|
| 50 | 57 |
return fmt.Errorf("mounting %s private %s", dest, err)
|