github.com/criyle/go-sandbox@v0.10.3/pkg/mount/builder_linux.go (about) 1 package mount 2 3 import ( 4 "os" 5 "strings" 6 7 "golang.org/x/sys/unix" 8 ) 9 10 const ( 11 bind = unix.MS_BIND | unix.MS_NOSUID | unix.MS_PRIVATE | unix.MS_REC 12 mFlag = unix.MS_NOSUID | unix.MS_NOATIME | unix.MS_NODEV 13 ) 14 15 // NewDefaultBuilder creates default builder for minimal rootfs 16 func NewDefaultBuilder() *Builder { 17 return NewBuilder(). 18 WithBind("/usr", "usr", true). 19 WithBind("/lib", "lib", true). 20 WithBind("/lib64", "lib64", true). 21 WithBind("/bin", "bin", true) 22 } 23 24 // Build creates sequence of syscalls for fork_exec 25 func (b *Builder) Build() ([]SyscallParams, error) { 26 var err error 27 ret := make([]SyscallParams, 0, len(b.Mounts)) 28 for _, m := range b.Mounts { 29 var mknod bool 30 if mknod, err = isBindMountFileOrNotExists(m); err != nil { 31 return nil, err 32 } 33 sp, err := m.ToSyscall() 34 if err != nil { 35 return nil, err 36 } 37 sp.MakeNod = mknod 38 ret = append(ret, *sp) 39 } 40 return ret, nil 41 } 42 43 // FilterNotExist removes bind mount that does not exists 44 func (b *Builder) FilterNotExist() *Builder { 45 rt := b.Mounts[:0] 46 for _, m := range b.Mounts { 47 if m.IsBindMount() { 48 if _, err := os.Stat(m.Source); os.IsNotExist(err) { 49 continue 50 } 51 } 52 rt = append(rt, m) 53 } 54 b.Mounts = rt 55 return b 56 } 57 58 func isBindMountFileOrNotExists(m Mount) (bool, error) { 59 if m.IsBindMount() { 60 if fi, err := os.Stat(m.Source); os.IsNotExist(err) { 61 return false, err 62 } else if !fi.IsDir() { 63 return true, err 64 } 65 } 66 return false, nil 67 } 68 69 // WithMounts add mounts to builder 70 func (b *Builder) WithMounts(m []Mount) *Builder { 71 b.Mounts = append(b.Mounts, m...) 72 return b 73 } 74 75 // WithMount add single mount to builder 76 func (b *Builder) WithMount(m Mount) *Builder { 77 b.Mounts = append(b.Mounts, m) 78 return b 79 } 80 81 // WithBind adds a bind mount to builder 82 func (b *Builder) WithBind(source, target string, readonly bool) *Builder { 83 var flags uintptr = bind 84 if readonly { 85 flags |= unix.MS_RDONLY 86 } 87 b.Mounts = append(b.Mounts, Mount{ 88 Source: source, 89 Target: target, 90 Flags: flags, 91 }) 92 return b 93 } 94 95 // WithTmpfs add a tmpfs mount to builder 96 func (b *Builder) WithTmpfs(target, data string) *Builder { 97 b.Mounts = append(b.Mounts, Mount{ 98 Source: "tmpfs", 99 Target: target, 100 FsType: "tmpfs", 101 Flags: mFlag, 102 Data: data, 103 }) 104 return b 105 } 106 107 // WithProc add proc file system 108 func (b *Builder) WithProc() *Builder { 109 b.Mounts = append(b.Mounts, Mount{ 110 Source: "proc", 111 Target: "proc", 112 FsType: "proc", 113 Flags: unix.MS_NOSUID | unix.MS_NODEV | unix.MS_NOEXEC | unix.MS_RDONLY, 114 }) 115 return b 116 } 117 118 func (b Builder) String() string { 119 var sb strings.Builder 120 sb.WriteString("Mounts: ") 121 for i, m := range b.Mounts { 122 sb.WriteString(m.String()) 123 if i != len(b.Mounts)-1 { 124 sb.WriteString(", ") 125 } 126 } 127 return sb.String() 128 }