github.com/rootless-containers/rootlesskit/v2@v2.3.4/pkg/copyup/tmpfssymlink/tmpfssymlink.go (about) 1 package tmpfssymlink 2 3 import ( 4 "errors" 5 "fmt" 6 "os" 7 "path/filepath" 8 9 "golang.org/x/sys/unix" 10 11 "github.com/rootless-containers/rootlesskit/v2/pkg/copyup" 12 ) 13 14 func NewChildDriver() copyup.ChildDriver { 15 return &childDriver{} 16 } 17 18 type childDriver struct { 19 } 20 21 func (d *childDriver) CopyUp(dirs []string) ([]string, error) { 22 // we create bind0 outside of StateDir so as to allow 23 // copying up /run with stateDir=/run/user/1001/rootlesskit/default. 24 bind0, err := os.MkdirTemp("/tmp", "rootlesskit-b") 25 if err != nil { 26 return nil, fmt.Errorf("creating bind0 directory under /tmp: %w", err) 27 } 28 defer os.RemoveAll(bind0) 29 var copied []string 30 for _, d := range dirs { 31 d := filepath.Clean(d) 32 if d == "/tmp" { 33 // TODO: we can support copy-up /tmp by changing bind0TempDir 34 return copied, errors.New("/tmp cannot be copied up") 35 } 36 37 if err := unix.Mount(d, bind0, "", uintptr(unix.MS_BIND|unix.MS_REC), ""); err != nil { 38 return copied, fmt.Errorf("failed to create bind mount on %s: %w", d, err) 39 } 40 41 if err := unix.Mount("none", d, "tmpfs", 0, ""); err != nil { 42 return copied, fmt.Errorf("failed to mount tmpfs on %s: %w", d, err) 43 } 44 45 bind1, err := os.MkdirTemp(d, ".ro") 46 if err != nil { 47 return copied, fmt.Errorf("creating a directory under %s: %w", d, err) 48 } 49 if err := unix.Mount(bind0, bind1, "", uintptr(unix.MS_MOVE), ""); err != nil { 50 return copied, fmt.Errorf("failed to move mount point from %s to %s: %w", bind0, bind1, err) 51 } 52 53 files, err := os.ReadDir(bind1) 54 if err != nil { 55 return copied, fmt.Errorf("reading dir %s: %w", bind1, err) 56 } 57 for _, f := range files { 58 fFull := filepath.Join(bind1, f.Name()) 59 var symlinkSrc string 60 if f.Type()&os.ModeSymlink != 0 { 61 symlinkSrc, err = os.Readlink(fFull) 62 if err != nil { 63 return copied, fmt.Errorf("reading dir %s: %w", fFull, err) 64 } 65 } else { 66 symlinkSrc = filepath.Join(filepath.Base(bind1), f.Name()) 67 } 68 symlinkDst := filepath.Join(d, f.Name()) 69 // `mount` may create extra `/etc/mtab` after mounting empty tmpfs on /etc 70 // https://github.com/rootless-containers/rootlesskit/issues/45 71 if err = os.RemoveAll(symlinkDst); err != nil { 72 return copied, fmt.Errorf("removing %s: %w", symlinkDst, err) 73 } 74 if err := os.Symlink(symlinkSrc, symlinkDst); err != nil { 75 return copied, fmt.Errorf("symlinking %s to %s: %w", symlinkSrc, symlinkDst, err) 76 } 77 } 78 copied = append(copied, d) 79 } 80 return copied, nil 81 }