diff --git a/pkg/forkexec/fork.go b/pkg/forkexec/fork.go index 7983d97..a4069bd 100644 --- a/pkg/forkexec/fork.go +++ b/pkg/forkexec/fork.go @@ -273,7 +273,15 @@ func (r *Runner) Start() (int, error) { // performing mounts for _, m := range r.Mounts { // mkdirs(target) - for _, p := range m.Prefixes { + for i, p := range m.Prefixes { + // if target mount point is a file, mknod(target) + if i == len(m.Prefixes)-1 && m.MakeNod { + _, _, err1 = syscall.RawSyscall(syscall.SYS_MKNODAT, uintptr(_AT_FDCWD), uintptr(unsafe.Pointer(p)), 0755) + if err1 != 0 && err1 != syscall.EEXIST { + goto childerror + } + break + } _, _, err1 = syscall.RawSyscall(syscall.SYS_MKDIRAT, uintptr(_AT_FDCWD), uintptr(unsafe.Pointer(p)), 0755) if err1 != 0 && err1 != syscall.EEXIST { goto childerror diff --git a/pkg/mount/builder.go b/pkg/mount/builder.go index 0a6e6c4..53d7176 100644 --- a/pkg/mount/builder.go +++ b/pkg/mount/builder.go @@ -7,9 +7,8 @@ import ( ) const ( - bind = unix.MS_BIND | unix.MS_NOSUID | unix.MS_PRIVATE - roBind = bind | unix.MS_RDONLY - mFlag = unix.MS_NOSUID | unix.MS_NOATIME | unix.MS_NODEV + bind = unix.MS_BIND | unix.MS_NOSUID | unix.MS_PRIVATE + mFlag = unix.MS_NOSUID | unix.MS_NOATIME | unix.MS_NODEV ) // Builder builds fork_exec friendly mount syscall format @@ -25,9 +24,11 @@ func NewBuilder() *Builder { // Build creates sequence of syscalls for fork_exec // skipNotExists skips bind mounts that source not exists func (b *Builder) Build(skipNotExists bool) ([]SyscallParams, error) { + var err error ret := make([]SyscallParams, 0, len(b.Mounts)) for _, m := range b.Mounts { - if err := isBindMountNotExists(m); err != nil { + mknod := false + if mknod, err = isBindMountFileOrNotExists(m); err != nil { if skipNotExists { continue } @@ -37,18 +38,21 @@ func (b *Builder) Build(skipNotExists bool) ([]SyscallParams, error) { if err != nil { return nil, err } + sp.MakeNod = mknod ret = append(ret, *sp) } return ret, nil } -func isBindMountNotExists(m Mount) error { +func isBindMountFileOrNotExists(m Mount) (bool, error) { if m.Flags&unix.MS_BIND == unix.MS_BIND { - if _, err := os.Stat(m.Source); os.IsNotExist(err) { - return err + if fi, err := os.Stat(m.Source); os.IsNotExist(err) { + return false, err + } else if !fi.IsDir() { + return true, err } } - return nil + return false, nil } // WithMounts add mounts to builder @@ -67,7 +71,7 @@ func (b *Builder) WithMount(m Mount) *Builder { func (b *Builder) WithBind(source, target string, readonly bool) *Builder { var flags uintptr = bind if readonly { - flags = roBind + flags |= unix.MS_RDONLY } b.Mounts = append(b.Mounts, Mount{ Source: source, diff --git a/pkg/mount/mount.go b/pkg/mount/mount.go index dde4079..5172011 100644 --- a/pkg/mount/mount.go +++ b/pkg/mount/mount.go @@ -15,6 +15,7 @@ type SyscallParams struct { Source, Target, FsType, Data *byte Flags uintptr Prefixes []*byte + MakeNod bool } // ToSyscall convert Mount to SyscallPrams @@ -65,10 +66,10 @@ func pathPrefix(path string) []string { return ret } -// arrayPtrFromStrings converts srings to c style strings -func arrayPtrFromStrings(strs []string) ([]*byte, error) { - bytes := make([]*byte, 0, len(strs)) - for _, s := range strs { +// arrayPtrFromStrings converts strings to c style strings +func arrayPtrFromStrings(str []string) ([]*byte, error) { + bytes := make([]*byte, 0, len(str)) + for _, s := range str { b, err := syscall.BytePtrFromString(s) if err != nil { return nil, err