@@ -485,18 +485,6 @@ func (g *Gofer) setupRootFS(spec *specs.Spec, conf *config.Config, goferToHostRP
485485 g .setupDev (spec , conf , root , procPath )
486486 }
487487
488- // Create working directory if needed.
489- if spec .Process .Cwd != "" {
490- dst , err := resolveSymlinks (root , spec .Process .Cwd )
491- if err != nil {
492- return fmt .Errorf ("resolving symlinks to %q: %v" , spec .Process .Cwd , err )
493- }
494- log .Infof ("Create working directory %q if needed" , spec .Process .Cwd )
495- if err := os .MkdirAll (dst , 0755 ); err != nil {
496- return fmt .Errorf ("creating working directory %q: %v" , spec .Process .Cwd , err )
497- }
498- }
499-
500488 // Check if root needs to be remounted as readonly.
501489 if rootfsConf .ShouldUseLisafs () && (spec .Root .Readonly || rootfsConf .ShouldUseOverlayfs ()) {
502490 // If root is a mount point but not read-only, we can change mount options
@@ -526,7 +514,7 @@ func (g *Gofer) setupRootFS(spec *specs.Spec, conf *config.Config, goferToHostRP
526514// setupMounts bind mounts all mounts specified in the spec in their correct
527515// location inside root. It will resolve relative paths and symlinks. It also
528516// creates directories as needed.
529- func (g * Gofer ) setupMounts (conf * config.Config , mounts []specs.Mount , root , procPath string , goferToHostRPC * urpc.Client ) error {
517+ func (g * Gofer ) setupMounts (conf * config.Config , mounts []specs.Mount , root , procPath string , goferToHostRPC * urpc.Client ) ( retErr error ) {
530518 mountIdx := 1 // First index is for rootfs.
531519 for _ , m := range mounts {
532520 if ! specutils .IsGoferMount (m ) {
@@ -569,6 +557,52 @@ func (g *Gofer) setupMounts(conf *config.Config, mounts []specs.Mount, root, pro
569557 return fmt .Errorf ("mounting %+v: %v" , m , err )
570558 }
571559
560+ dstFD , err := unix .Open (dst , unix .O_PATH | unix .O_CLOEXEC , 0 )
561+ if err != nil {
562+ return fmt .Errorf ("Open(%s, _, _): %w" , dst , err )
563+ }
564+ defer unix .Close (dstFD )
565+ // Apply mount options after creating all mount points.
566+ // Otherwise they can be remounted into read-only.
567+ defer func (dstFD int , flags uint32 , dst string ) {
568+ path := fmt .Sprintf ("/proc/self/fd/%d" , dstFD )
569+ // The gofer process doesn't execute anything nativly.
570+ flags |= unix .MS_NOSUID
571+
572+ statfs := unix.Statfs_t {}
573+ if err := unix .Statfs (path , & statfs ); err != nil {
574+ retErr = fmt .Errorf ("stat dst: %q" , dst )
575+ return
576+ }
577+ lockedFlags := uint32 (0 )
578+ for _ , f := range []struct {
579+ st , ms int
580+ }{
581+ // MS_NOSUID are always set.
582+ {unix .ST_RDONLY , unix .MS_RDONLY },
583+ {unix .ST_NOEXEC , unix .MS_NOEXEC },
584+ {unix .ST_NODEV , unix .MS_NODEV },
585+ {unix .ST_NOATIME , unix .MS_NOATIME },
586+ {unix .ST_NODIRATIME , unix .MS_NODIRATIME },
587+ {unix .ST_RELATIME , unix .MS_RELATIME },
588+ } {
589+ if int (statfs .Flags )& f .st == f .st {
590+ lockedFlags |= uint32 (f .ms )
591+ }
592+ }
593+ if lockedFlags & unix .MS_NOATIME | unix .MS_RELATIME == 0 {
594+ lockedFlags |= unix .MS_STRICTATIME
595+ }
596+
597+ // The previous SafeSetupAndMount creates a new bind-mount, but
598+ // it doesn't change mount flags. A separate MS_BIND|MS_REMOUNT
599+ // has to be done to apply the mount options.
600+ if err := unix .Mount ("" , path , "" , uintptr (flags | lockedFlags | unix .MS_REMOUNT ), "" ); err != nil {
601+ retErr = fmt .Errorf ("mount dst: %q, flags: %#x, err: %v" , dst , flags , err )
602+ return
603+ }
604+ }(dstFD , flags , dst )
605+
572606 // Set propagation options that cannot be set together with other options.
573607 flags = specutils .PropOptionsToFlags (m .Options )
574608 if flags != 0 {
0 commit comments