@@ -19,6 +19,7 @@ package server
1919import (
2020 "os"
2121 "path/filepath"
22+ "sort"
2223 "strconv"
2324 "strings"
2425 "time"
@@ -351,8 +352,8 @@ func (c *criService) generateContainerSpec(id string, sandboxID string, sandboxP
351352 return nil , errors .Wrapf (err , "failed to init selinux options %+v" , securityContext .GetSelinuxOptions ())
352353 }
353354
354- // Add extra mounts first so that CRI specified mounts can override .
355- mounts := append ( extraMounts , config .GetMounts ()... )
355+ // Merge extra mounts and CRI mounts.
356+ mounts := mergeMounts ( config .GetMounts (), extraMounts )
356357 if err := c .addOCIBindMounts (& g , mounts , mountLabel ); err != nil {
357358 return nil , errors .Wrapf (err , "failed to set OCI bind mounts %+v" , mounts )
358359 }
@@ -616,13 +617,40 @@ func setOCIDevicesPrivileged(g *generate.Generator) error {
616617
617618// addOCIBindMounts adds bind mounts.
618619func (c * criService ) addOCIBindMounts (g * generate.Generator , mounts []* runtime.Mount , mountLabel string ) error {
620+ // Sort mounts in number of parts. This ensures that high level mounts don't
621+ // shadow other mounts.
622+ sort .Sort (orderedMounts (mounts ))
623+
619624 // Mount cgroup into the container as readonly, which inherits docker's behavior.
620625 g .AddMount (runtimespec.Mount {
621626 Source : "cgroup" ,
622627 Destination : "/sys/fs/cgroup" ,
623628 Type : "cgroup" ,
624629 Options : []string {"nosuid" , "noexec" , "nodev" , "relatime" , "ro" },
625630 })
631+
632+ // Copy all mounts from default mounts, except for
633+ // - mounts overriden by supplied mount;
634+ // - all mounts under /dev if a supplied /dev is present.
635+ mountSet := make (map [string ]struct {})
636+ for _ , m := range mounts {
637+ mountSet [filepath .Clean (m .ContainerPath )] = struct {}{}
638+ }
639+ defaultMounts := g .Mounts ()
640+ g .ClearMounts ()
641+ for _ , m := range defaultMounts {
642+ dst := filepath .Clean (m .Destination )
643+ if _ , ok := mountSet [dst ]; ok {
644+ // filter out mount overridden by a supplied mount
645+ continue
646+ }
647+ if _ , mountDev := mountSet ["/dev" ]; mountDev && strings .HasPrefix (dst , "/dev/" ) {
648+ // filter out everything under /dev if /dev is a supplied mount
649+ continue
650+ }
651+ g .AddMount (m )
652+ }
653+
626654 for _ , mount := range mounts {
627655 dst := mount .GetContainerPath ()
628656 src := mount .GetHostPath ()
@@ -841,10 +869,6 @@ func defaultRuntimeSpec(id string) (*runtimespec.Spec, error) {
841869 if mount .Destination == "/run" {
842870 continue
843871 }
844- // CRI plugin handles `/dev/shm` itself.
845- if mount .Destination == "/dev/shm" {
846- continue
847- }
848872 mounts = append (mounts , mount )
849873 }
850874 spec .Mounts = mounts
@@ -988,3 +1012,25 @@ func generateUserString(username string, uid, gid *runtime.Int64Value) (string,
9881012 }
9891013 return userstr , nil
9901014}
1015+
1016+ // mergeMounts merge CRI mounts with extra mounts. If a mount destination
1017+ // is mounted by both a CRI mount and an extra mount, the CRI mount will
1018+ // be kept.
1019+ func mergeMounts (criMounts , extraMounts []* runtime.Mount ) []* runtime.Mount {
1020+ var mounts []* runtime.Mount
1021+ mounts = append (mounts , criMounts ... )
1022+ // Copy all mounts from extra mounts, except for mounts overriden by CRI.
1023+ for _ , e := range extraMounts {
1024+ found := false
1025+ for _ , c := range criMounts {
1026+ if filepath .Clean (e .ContainerPath ) == filepath .Clean (c .ContainerPath ) {
1027+ found = true
1028+ break
1029+ }
1030+ }
1031+ if ! found {
1032+ mounts = append (mounts , e )
1033+ }
1034+ }
1035+ return mounts
1036+ }
0 commit comments