diff options
author | Rahat Mahmood <rahat@google.com> | 2019-03-26 16:15:55 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2019-03-26 16:16:57 -0700 |
commit | 06ec97a3f823f1f5d928fc9c2beb3a11c2c88487 (patch) | |
tree | a2b501718c82aede761d7235527492782ef65cc2 /pkg/sentry/syscalls/linux/sys_file.go | |
parent | 79aca14a0cd70720e8a8f8bd6c1499ab1ffbd8d3 (diff) |
Implement memfd_create.
Memfds are simply anonymous tmpfs files with no associated
mounts. Also implementing file seals, which Linux only implements for
memfds at the moment.
PiperOrigin-RevId: 240450031
Change-Id: I31de78b950101ae8d7a13d0e93fe52d98ea06f2f
Diffstat (limited to 'pkg/sentry/syscalls/linux/sys_file.go')
-rw-r--r-- | pkg/sentry/syscalls/linux/sys_file.go | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/pkg/sentry/syscalls/linux/sys_file.go b/pkg/sentry/syscalls/linux/sys_file.go index cf6fdc190..3193718b5 100644 --- a/pkg/sentry/syscalls/linux/sys_file.go +++ b/pkg/sentry/syscalls/linux/sys_file.go @@ -23,6 +23,7 @@ import ( "gvisor.googlesource.com/gvisor/pkg/sentry/context" "gvisor.googlesource.com/gvisor/pkg/sentry/fs" "gvisor.googlesource.com/gvisor/pkg/sentry/fs/lock" + "gvisor.googlesource.com/gvisor/pkg/sentry/fs/tmpfs" "gvisor.googlesource.com/gvisor/pkg/sentry/kernel" "gvisor.googlesource.com/gvisor/pkg/sentry/kernel/auth" "gvisor.googlesource.com/gvisor/pkg/sentry/kernel/fasync" @@ -933,6 +934,15 @@ func Fcntl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall case linux.F_SETOWN: fSetOwn(t, file, args[2].Int()) return 0, nil, nil + case linux.F_GET_SEALS: + val, err := tmpfs.GetSeals(file.Dirent.Inode) + return uintptr(val), nil, err + case linux.F_ADD_SEALS: + if !file.Flags().Write { + return 0, nil, syserror.EPERM + } + err := tmpfs.AddSeals(file.Dirent.Inode, args[2].Uint()) + return 0, nil, err default: // Everything else is not yet supported. return 0, nil, syserror.EINVAL @@ -2066,3 +2076,52 @@ func Sendfile(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc // arbitrarily. return uintptr(n), nil, handleIOError(t, n != 0, err, kernel.ERESTARTSYS, "sendfile", inFile) } + +const ( + memfdPrefix = "/memfd:" + memfdAllFlags = uint32(linux.MFD_CLOEXEC | linux.MFD_ALLOW_SEALING) + memfdMaxNameLen = linux.NAME_MAX - len(memfdPrefix) + 1 +) + +// MemfdCreate implements the linux syscall memfd_create(2). +func MemfdCreate(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { + addr := args[0].Pointer() + flags := args[1].Uint() + + if flags&^memfdAllFlags != 0 { + // Unknown bits in flags. + return 0, nil, syserror.EINVAL + } + + allowSeals := flags&linux.MFD_ALLOW_SEALING != 0 + cloExec := flags&linux.MFD_CLOEXEC != 0 + + name, err := t.CopyInString(addr, syscall.PathMax-len(memfdPrefix)) + if err != nil { + return 0, nil, err + } + if len(name) > memfdMaxNameLen { + return 0, nil, syserror.EINVAL + } + name = memfdPrefix + name + + inode := tmpfs.NewMemfdInode(t, allowSeals) + dirent := fs.NewDirent(inode, name) + // Per Linux, mm/shmem.c:__shmem_file_setup(), memfd files are set up with + // FMODE_READ | FMODE_WRITE. + file, err := inode.GetFile(t, dirent, fs.FileFlags{Read: true, Write: true}) + if err != nil { + return 0, nil, err + } + + defer dirent.DecRef() + defer file.DecRef() + + fdFlags := kernel.FDFlags{CloseOnExec: cloExec} + newFD, err := t.FDMap().NewFDFrom(0, file, fdFlags, t.ThreadGroup().Limits()) + if err != nil { + return 0, nil, err + } + + return uintptr(newFD), nil, nil +} |