Commit 7120976d74195 ("Implement none, private, and shareable ipc
modes") introduces a bug: if a user-specified mount for /dev/shm
is provided, its size is overriden by value of ShmSize.
A reproducer is simple:
docker run --rm
--mount type=tmpfs,dst=/dev/shm,tmpfs-size=100K \
alpine df /dev/shm
This commit is an attempt to fix the bug, as well as optimize things
a but and make the code easier to read.
https://github.com/moby/moby/issues/35271
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
| ... | ... |
@@ -528,23 +528,35 @@ func setMounts(daemon *Daemon, s *specs.Spec, c *container.Container, mounts []c |
| 528 | 528 |
userMounts[m.Destination] = struct{}{}
|
| 529 | 529 |
} |
| 530 | 530 |
|
| 531 |
- // Filter out mounts from spec |
|
| 532 |
- noIpc := c.HostConfig.IpcMode.IsNone() |
|
| 533 |
- // Filter out mounts that are overridden by user supplied mounts |
|
| 531 |
+ // Copy all mounts from spec to defaultMounts, except for |
|
| 532 |
+ // - mounts overriden by a user supplied mount; |
|
| 533 |
+ // - all mounts under /dev if a user supplied /dev is present; |
|
| 534 |
+ // - /dev/shm, in case IpcMode is none. |
|
| 535 |
+ // While at it, also |
|
| 536 |
+ // - set size for /dev/shm from shmsize. |
|
| 534 | 537 |
var defaultMounts []specs.Mount |
| 535 | 538 |
_, mountDev := userMounts["/dev"] |
| 536 | 539 |
for _, m := range s.Mounts {
|
| 537 |
- // filter out /dev/shm mount if case IpcMode is none |
|
| 538 |
- if noIpc && m.Destination == "/dev/shm" {
|
|
| 540 |
+ if _, ok := userMounts[m.Destination]; ok {
|
|
| 541 |
+ // filter out mount overridden by a user supplied mount |
|
| 539 | 542 |
continue |
| 540 | 543 |
} |
| 541 |
- // filter out mount overridden by a user supplied mount |
|
| 542 |
- if _, ok := userMounts[m.Destination]; !ok {
|
|
| 543 |
- if mountDev && strings.HasPrefix(m.Destination, "/dev/") {
|
|
| 544 |
+ if mountDev && strings.HasPrefix(m.Destination, "/dev/") {
|
|
| 545 |
+ // filter out everything under /dev if /dev is user-mounted |
|
| 546 |
+ continue |
|
| 547 |
+ } |
|
| 548 |
+ |
|
| 549 |
+ if m.Destination == "/dev/shm" {
|
|
| 550 |
+ if c.HostConfig.IpcMode.IsNone() {
|
|
| 551 |
+ // filter out /dev/shm for "none" IpcMode |
|
| 544 | 552 |
continue |
| 545 | 553 |
} |
| 546 |
- defaultMounts = append(defaultMounts, m) |
|
| 554 |
+ // set size for /dev/shm mount from spec |
|
| 555 |
+ sizeOpt := "size=" + strconv.FormatInt(c.HostConfig.ShmSize, 10) |
|
| 556 |
+ m.Options = append(m.Options, sizeOpt) |
|
| 547 | 557 |
} |
| 558 |
+ |
|
| 559 |
+ defaultMounts = append(defaultMounts, m) |
|
| 548 | 560 |
} |
| 549 | 561 |
|
| 550 | 562 |
s.Mounts = defaultMounts |
| ... | ... |
@@ -652,14 +664,6 @@ func setMounts(daemon *Daemon, s *specs.Spec, c *container.Container, mounts []c |
| 652 | 652 |
s.Linux.MaskedPaths = nil |
| 653 | 653 |
} |
| 654 | 654 |
|
| 655 |
- // Set size for /dev/shm mount that comes from spec (IpcMode: private only) |
|
| 656 |
- for i, m := range s.Mounts {
|
|
| 657 |
- if m.Destination == "/dev/shm" {
|
|
| 658 |
- sizeOpt := "size=" + strconv.FormatInt(c.HostConfig.ShmSize, 10) |
|
| 659 |
- s.Mounts[i].Options = append(s.Mounts[i].Options, sizeOpt) |
|
| 660 |
- } |
|
| 661 |
- } |
|
| 662 |
- |
|
| 663 | 655 |
// TODO: until a kernel/mount solution exists for handling remount in a user namespace, |
| 664 | 656 |
// we must clear the readonly flag for the cgroups mount (@mrunalp concurs) |
| 665 | 657 |
if uidMap := daemon.idMappings.UIDs(); uidMap != nil || c.HostConfig.Privileged {
|