summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/sentry')
-rw-r--r--pkg/sentry/arch/BUILD5
-rw-r--r--pkg/sentry/arch/arch.go14
-rw-r--r--pkg/sentry/arch/arch_aarch64.go5
-rw-r--r--pkg/sentry/arch/arch_x86.go5
-rw-r--r--pkg/sentry/arch/signal.go276
-rw-r--r--pkg/sentry/arch/signal_act.go83
-rw-r--r--pkg/sentry/arch/signal_amd64.go26
-rw-r--r--pkg/sentry/arch/signal_arm64.go26
-rw-r--r--pkg/sentry/arch/signal_info.go66
-rw-r--r--pkg/sentry/arch/signal_stack.go68
-rw-r--r--pkg/sentry/arch/stack.go2
-rw-r--r--pkg/sentry/control/proc.go9
-rw-r--r--pkg/sentry/devices/tundev/BUILD1
-rw-r--r--pkg/sentry/devices/tundev/tundev.go3
-rw-r--r--pkg/sentry/fs/BUILD2
-rw-r--r--pkg/sentry/fs/attr.go14
-rw-r--r--pkg/sentry/fs/copy_up.go5
-rw-r--r--pkg/sentry/fs/dev/BUILD1
-rw-r--r--pkg/sentry/fs/dev/dev.go8
-rw-r--r--pkg/sentry/fs/dev/net_tun.go3
-rw-r--r--pkg/sentry/fs/dirent.go5
-rw-r--r--pkg/sentry/fs/fdpipe/BUILD2
-rw-r--r--pkg/sentry/fs/fdpipe/pipe.go3
-rw-r--r--pkg/sentry/fs/fdpipe/pipe_test.go6
-rw-r--r--pkg/sentry/fs/file_overlay.go7
-rw-r--r--pkg/sentry/fs/fsutil/BUILD1
-rw-r--r--pkg/sentry/fs/fsutil/file.go31
-rw-r--r--pkg/sentry/fs/fsutil/host_mappable.go21
-rw-r--r--pkg/sentry/fs/fsutil/inode.go7
-rw-r--r--pkg/sentry/fs/fsutil/inode_cached.go27
-rw-r--r--pkg/sentry/fs/gofer/BUILD1
-rw-r--r--pkg/sentry/fs/gofer/cache_policy.go2
-rw-r--r--pkg/sentry/fs/gofer/file.go17
-rw-r--r--pkg/sentry/fs/gofer/inode.go18
-rw-r--r--pkg/sentry/fs/gofer/path.go25
-rw-r--r--pkg/sentry/fs/host/BUILD3
-rw-r--r--pkg/sentry/fs/host/socket.go3
-rw-r--r--pkg/sentry/fs/host/socket_iovec.go4
-rw-r--r--pkg/sentry/fs/host/tty.go5
-rw-r--r--pkg/sentry/fs/host/util.go4
-rw-r--r--pkg/sentry/fs/inode_overlay.go7
-rw-r--r--pkg/sentry/fs/inode_overlay_test.go5
-rw-r--r--pkg/sentry/fs/inotify.go9
-rw-r--r--pkg/sentry/fs/mock.go3
-rw-r--r--pkg/sentry/fs/mounts.go3
-rw-r--r--pkg/sentry/fs/overlay.go4
-rw-r--r--pkg/sentry/fs/proc/BUILD1
-rw-r--r--pkg/sentry/fs/proc/exec_args.go4
-rw-r--r--pkg/sentry/fs/proc/net.go4
-rw-r--r--pkg/sentry/fs/proc/proc.go5
-rw-r--r--pkg/sentry/fs/proc/sys.go22
-rw-r--r--pkg/sentry/fs/proc/sys_net.go4
-rw-r--r--pkg/sentry/fs/proc/task.go5
-rw-r--r--pkg/sentry/fs/proc/uid_gid_map.go10
-rw-r--r--pkg/sentry/fs/proc/uptime.go4
-rw-r--r--pkg/sentry/fs/splice.go5
-rw-r--r--pkg/sentry/fs/timerfd/BUILD1
-rw-r--r--pkg/sentry/fs/timerfd/timerfd.go5
-rw-r--r--pkg/sentry/fs/tmpfs/BUILD1
-rw-r--r--pkg/sentry/fs/tmpfs/fs.go2
-rw-r--r--pkg/sentry/fs/tmpfs/inode_file.go22
-rw-r--r--pkg/sentry/fs/tmpfs/tmpfs.go31
-rw-r--r--pkg/sentry/fs/tty/BUILD1
-rw-r--r--pkg/sentry/fs/tty/fs.go4
-rw-r--r--pkg/sentry/fs/user/BUILD1
-rw-r--r--pkg/sentry/fs/user/path.go5
-rw-r--r--pkg/sentry/fs/user/user_test.go5
-rw-r--r--pkg/sentry/fsimpl/cgroupfs/BUILD1
-rw-r--r--pkg/sentry/fsimpl/cgroupfs/base.go25
-rw-r--r--pkg/sentry/fsimpl/cgroupfs/cgroupfs.go12
-rw-r--r--pkg/sentry/fsimpl/devpts/BUILD1
-rw-r--r--pkg/sentry/fsimpl/devpts/devpts.go3
-rw-r--r--pkg/sentry/fsimpl/devpts/master.go3
-rw-r--r--pkg/sentry/fsimpl/devpts/replica.go3
-rw-r--r--pkg/sentry/fsimpl/ext/BUILD3
-rw-r--r--pkg/sentry/fsimpl/ext/block_map_file.go3
-rw-r--r--pkg/sentry/fsimpl/ext/directory.go6
-rw-r--r--pkg/sentry/fsimpl/ext/ext.go6
-rw-r--r--pkg/sentry/fsimpl/ext/ext_test.go8
-rw-r--r--pkg/sentry/fsimpl/ext/extent_file.go5
-rw-r--r--pkg/sentry/fsimpl/ext/filesystem.go3
-rw-r--r--pkg/sentry/fsimpl/ext/inode.go3
-rw-r--r--pkg/sentry/fsimpl/ext/regular_file.go5
-rw-r--r--pkg/sentry/fsimpl/fuse/BUILD2
-rw-r--r--pkg/sentry/fsimpl/fuse/connection_test.go4
-rw-r--r--pkg/sentry/fsimpl/fuse/dev.go9
-rw-r--r--pkg/sentry/fsimpl/fuse/fusefs.go51
-rw-r--r--pkg/sentry/fsimpl/fuse/read_write.go5
-rw-r--r--pkg/sentry/fsimpl/fuse/regular_file.go11
-rw-r--r--pkg/sentry/fsimpl/gofer/BUILD1
-rw-r--r--pkg/sentry/fsimpl/gofer/directory.go8
-rw-r--r--pkg/sentry/fsimpl/gofer/filesystem.go51
-rw-r--r--pkg/sentry/fsimpl/gofer/gofer.go56
-rw-r--r--pkg/sentry/fsimpl/gofer/host_named_pipe.go3
-rw-r--r--pkg/sentry/fsimpl/gofer/regular_file.go60
-rw-r--r--pkg/sentry/fsimpl/gofer/save_restore.go4
-rw-r--r--pkg/sentry/fsimpl/gofer/special_file.go10
-rw-r--r--pkg/sentry/fsimpl/host/BUILD2
-rw-r--r--pkg/sentry/fsimpl/host/host.go19
-rw-r--r--pkg/sentry/fsimpl/host/socket.go3
-rw-r--r--pkg/sentry/fsimpl/host/socket_iovec.go4
-rw-r--r--pkg/sentry/fsimpl/host/tty.go5
-rw-r--r--pkg/sentry/fsimpl/host/util.go4
-rw-r--r--pkg/sentry/fsimpl/kernfs/BUILD2
-rw-r--r--pkg/sentry/fsimpl/kernfs/fd_impl_util.go5
-rw-r--r--pkg/sentry/fsimpl/kernfs/filesystem.go28
-rw-r--r--pkg/sentry/fsimpl/kernfs/inode_impl_util.go5
-rw-r--r--pkg/sentry/fsimpl/kernfs/kernfs_test.go5
-rw-r--r--pkg/sentry/fsimpl/overlay/BUILD1
-rw-r--r--pkg/sentry/fsimpl/overlay/copy_up.go3
-rw-r--r--pkg/sentry/fsimpl/overlay/directory.go7
-rw-r--r--pkg/sentry/fsimpl/overlay/filesystem.go35
-rw-r--r--pkg/sentry/fsimpl/overlay/overlay.go21
-rw-r--r--pkg/sentry/fsimpl/overlay/regular_file.go13
-rw-r--r--pkg/sentry/fsimpl/proc/BUILD3
-rw-r--r--pkg/sentry/fsimpl/proc/filesystem.go4
-rw-r--r--pkg/sentry/fsimpl/proc/task_files.go11
-rw-r--r--pkg/sentry/fsimpl/proc/task_net.go4
-rw-r--r--pkg/sentry/fsimpl/proc/tasks_files.go5
-rw-r--r--pkg/sentry/fsimpl/proc/tasks_sys.go15
-rw-r--r--pkg/sentry/fsimpl/proc/tasks_test.go6
-rw-r--r--pkg/sentry/fsimpl/proc/yama.go6
-rw-r--r--pkg/sentry/fsimpl/sys/BUILD1
-rw-r--r--pkg/sentry/fsimpl/sys/kcov.go3
-rw-r--r--pkg/sentry/fsimpl/sys/sys.go3
-rw-r--r--pkg/sentry/fsimpl/testutil/BUILD1
-rw-r--r--pkg/sentry/fsimpl/testutil/kernel.go10
-rw-r--r--pkg/sentry/fsimpl/timerfd/BUILD1
-rw-r--r--pkg/sentry/fsimpl/timerfd/timerfd.go3
-rw-r--r--pkg/sentry/fsimpl/tmpfs/BUILD2
-rw-r--r--pkg/sentry/fsimpl/tmpfs/directory.go6
-rw-r--r--pkg/sentry/fsimpl/tmpfs/filesystem.go30
-rw-r--r--pkg/sentry/fsimpl/tmpfs/pipe_test.go3
-rw-r--r--pkg/sentry/fsimpl/tmpfs/regular_file.go15
-rw-r--r--pkg/sentry/fsimpl/tmpfs/tmpfs.go72
-rw-r--r--pkg/sentry/fsimpl/verity/BUILD3
-rw-r--r--pkg/sentry/fsimpl/verity/filesystem.go40
-rw-r--r--pkg/sentry/fsimpl/verity/verity.go71
-rw-r--r--pkg/sentry/fsimpl/verity/verity_test.go16
-rw-r--r--pkg/sentry/fsmetric/fsmetric.go1
-rw-r--r--pkg/sentry/hostfd/hostfd_linux.go9
-rw-r--r--pkg/sentry/hostfd/hostfd_unsafe.go17
-rw-r--r--pkg/sentry/kernel/BUILD7
-rw-r--r--pkg/sentry/kernel/auth/BUILD3
-rw-r--r--pkg/sentry/kernel/auth/credentials.go11
-rw-r--r--pkg/sentry/kernel/auth/id_map.go21
-rw-r--r--pkg/sentry/kernel/cgroup.go29
-rw-r--r--pkg/sentry/kernel/fasync/BUILD3
-rw-r--r--pkg/sentry/kernel/fasync/fasync.go9
-rw-r--r--pkg/sentry/kernel/fd_table.go4
-rw-r--r--pkg/sentry/kernel/futex/BUILD3
-rw-r--r--pkg/sentry/kernel/futex/futex.go5
-rw-r--r--pkg/sentry/kernel/kcov.go13
-rw-r--r--pkg/sentry/kernel/kernel.go80
-rw-r--r--pkg/sentry/kernel/pending_signals.go9
-rw-r--r--pkg/sentry/kernel/pending_signals_state.go6
-rw-r--r--pkg/sentry/kernel/pipe/BUILD2
-rw-r--r--pkg/sentry/kernel/pipe/node.go3
-rw-r--r--pkg/sentry/kernel/pipe/node_test.go3
-rw-r--r--pkg/sentry/kernel/pipe/pipe.go3
-rw-r--r--pkg/sentry/kernel/pipe/pipe_util.go8
-rw-r--r--pkg/sentry/kernel/pipe/vfs.go5
-rw-r--r--pkg/sentry/kernel/posixtimer.go22
-rw-r--r--pkg/sentry/kernel/ptrace.go36
-rw-r--r--pkg/sentry/kernel/rseq.go21
-rw-r--r--pkg/sentry/kernel/seccomp.go6
-rw-r--r--pkg/sentry/kernel/semaphore/BUILD1
-rw-r--r--pkg/sentry/kernel/semaphore/semaphore.go23
-rw-r--r--pkg/sentry/kernel/sessions.go8
-rw-r--r--pkg/sentry/kernel/shm/BUILD1
-rw-r--r--pkg/sentry/kernel/shm/shm.go9
-rw-r--r--pkg/sentry/kernel/signal.go15
-rw-r--r--pkg/sentry/kernel/signal_handlers.go17
-rw-r--r--pkg/sentry/kernel/signalfd/BUILD1
-rw-r--r--pkg/sentry/kernel/signalfd/signalfd.go3
-rw-r--r--pkg/sentry/kernel/task.go19
-rw-r--r--pkg/sentry/kernel/task_acct.go6
-rw-r--r--pkg/sentry/kernel/task_block.go3
-rw-r--r--pkg/sentry/kernel/task_cgroup.go8
-rw-r--r--pkg/sentry/kernel/task_clone.go15
-rw-r--r--pkg/sentry/kernel/task_context.go5
-rw-r--r--pkg/sentry/kernel/task_exec.go3
-rw-r--r--pkg/sentry/kernel/task_exit.go43
-rw-r--r--pkg/sentry/kernel/task_identity.go19
-rw-r--r--pkg/sentry/kernel/task_image.go4
-rw-r--r--pkg/sentry/kernel/task_sched.go14
-rw-r--r--pkg/sentry/kernel/task_signals.go131
-rw-r--r--pkg/sentry/kernel/task_start.go3
-rw-r--r--pkg/sentry/kernel/task_syscall.go6
-rw-r--r--pkg/sentry/kernel/task_usermem.go5
-rw-r--r--pkg/sentry/kernel/thread_group.go20
-rw-r--r--pkg/sentry/kernel/time/BUILD2
-rw-r--r--pkg/sentry/kernel/time/time.go25
-rw-r--r--pkg/sentry/kernel/timekeeper.go42
-rw-r--r--pkg/sentry/kernel/timekeeper_test.go4
-rw-r--r--pkg/sentry/loader/BUILD2
-rw-r--r--pkg/sentry/loader/elf.go7
-rw-r--r--pkg/sentry/loader/interpreter.go2
-rw-r--r--pkg/sentry/loader/loader.go3
-rw-r--r--pkg/sentry/loader/vdso.go3
-rw-r--r--pkg/sentry/mm/BUILD3
-rw-r--r--pkg/sentry/mm/aio_context.go13
-rw-r--r--pkg/sentry/mm/mm_test.go8
-rw-r--r--pkg/sentry/mm/shm.go6
-rw-r--r--pkg/sentry/mm/special_mappable.go5
-rw-r--r--pkg/sentry/mm/syscalls.go59
-rw-r--r--pkg/sentry/pgalloc/pgalloc.go18
-rw-r--r--pkg/sentry/platform/kvm/BUILD3
-rw-r--r--pkg/sentry/platform/kvm/address_space.go9
-rw-r--r--pkg/sentry/platform/kvm/address_space_amd64.go24
-rw-r--r--pkg/sentry/platform/kvm/address_space_arm64.go25
-rw-r--r--pkg/sentry/platform/kvm/bluepill_arm64.go23
-rw-r--r--pkg/sentry/platform/kvm/bluepill_arm64_unsafe.go29
-rw-r--r--pkg/sentry/platform/kvm/context.go7
-rw-r--r--pkg/sentry/platform/kvm/kvm_amd64_test.go5
-rw-r--r--pkg/sentry/platform/kvm/kvm_test.go33
-rw-r--r--pkg/sentry/platform/kvm/machine_amd64.go36
-rw-r--r--pkg/sentry/platform/kvm/machine_arm64.go12
-rw-r--r--pkg/sentry/platform/kvm/machine_arm64_unsafe.go21
-rw-r--r--pkg/sentry/platform/platform.go6
-rw-r--r--pkg/sentry/platform/ptrace/ptrace.go4
-rw-r--r--pkg/sentry/platform/ptrace/ptrace_unsafe.go2
-rw-r--r--pkg/sentry/platform/ptrace/subprocess.go3
-rw-r--r--pkg/sentry/platform/ptrace/subprocess_amd64.go2
-rw-r--r--pkg/sentry/platform/ptrace/subprocess_arm64.go2
-rw-r--r--pkg/sentry/sighandling/sighandling_unsafe.go13
-rw-r--r--pkg/sentry/socket/control/BUILD1
-rw-r--r--pkg/sentry/socket/control/control.go35
-rw-r--r--pkg/sentry/socket/hostinet/BUILD1
-rw-r--r--pkg/sentry/socket/hostinet/socket.go194
-rw-r--r--pkg/sentry/socket/hostinet/socket_unsafe.go18
-rw-r--r--pkg/sentry/socket/netfilter/BUILD1
-rw-r--r--pkg/sentry/socket/netfilter/extensions.go16
-rw-r--r--pkg/sentry/socket/netfilter/ipv4.go9
-rw-r--r--pkg/sentry/socket/netfilter/ipv6.go9
-rw-r--r--pkg/sentry/socket/netfilter/netfilter.go22
-rw-r--r--pkg/sentry/socket/netfilter/owner_matcher.go24
-rw-r--r--pkg/sentry/socket/netfilter/targets.go5
-rw-r--r--pkg/sentry/socket/netfilter/tcp_matcher.go5
-rw-r--r--pkg/sentry/socket/netfilter/udp_matcher.go5
-rw-r--r--pkg/sentry/socket/netlink/BUILD2
-rw-r--r--pkg/sentry/socket/netlink/socket.go6
-rw-r--r--pkg/sentry/socket/netstack/BUILD2
-rw-r--r--pkg/sentry/socket/netstack/netstack.go192
-rw-r--r--pkg/sentry/socket/netstack/stack.go9
-rw-r--r--pkg/sentry/socket/netstack/tun.go6
-rw-r--r--pkg/sentry/socket/socket.go2
-rw-r--r--pkg/sentry/socket/unix/BUILD1
-rw-r--r--pkg/sentry/socket/unix/unix.go5
-rw-r--r--pkg/sentry/socket/unix/unix_vfs2.go3
-rw-r--r--pkg/sentry/state/BUILD2
-rw-r--r--pkg/sentry/state/state.go8
-rw-r--r--pkg/sentry/strace/BUILD2
-rw-r--r--pkg/sentry/strace/clone.go46
-rw-r--r--pkg/sentry/strace/linux64_amd64.go2
-rw-r--r--pkg/sentry/strace/linux64_arm64.go2
-rw-r--r--pkg/sentry/strace/mmap.go92
-rw-r--r--pkg/sentry/strace/open.go42
-rw-r--r--pkg/sentry/strace/signal.go4
-rw-r--r--pkg/sentry/strace/strace.go4
-rw-r--r--pkg/sentry/strace/syscalls.go6
-rw-r--r--pkg/sentry/syscalls/BUILD1
-rw-r--r--pkg/sentry/syscalls/epoll.go3
-rw-r--r--pkg/sentry/syscalls/linux/BUILD1
-rw-r--r--pkg/sentry/syscalls/linux/error.go25
-rw-r--r--pkg/sentry/syscalls/linux/linux64.go5
-rw-r--r--pkg/sentry/syscalls/linux/sigset.go3
-rw-r--r--pkg/sentry/syscalls/linux/sys_aio.go27
-rw-r--r--pkg/sentry/syscalls/linux/sys_capability.go7
-rw-r--r--pkg/sentry/syscalls/linux/sys_epoll.go7
-rw-r--r--pkg/sentry/syscalls/linux/sys_eventfd.go4
-rw-r--r--pkg/sentry/syscalls/linux/sys_file.go113
-rw-r--r--pkg/sentry/syscalls/linux/sys_futex.go9
-rw-r--r--pkg/sentry/syscalls/linux/sys_getdents.go5
-rw-r--r--pkg/sentry/syscalls/linux/sys_identity.go8
-rw-r--r--pkg/sentry/syscalls/linux/sys_inotify.go7
-rw-r--r--pkg/sentry/syscalls/linux/sys_lseek.go3
-rw-r--r--pkg/sentry/syscalls/linux/sys_membarrier.go25
-rw-r--r--pkg/sentry/syscalls/linux/sys_mempolicy.go33
-rw-r--r--pkg/sentry/syscalls/linux/sys_mmap.go26
-rw-r--r--pkg/sentry/syscalls/linux/sys_mount.go10
-rw-r--r--pkg/sentry/syscalls/linux/sys_pipe.go4
-rw-r--r--pkg/sentry/syscalls/linux/sys_poll.go17
-rw-r--r--pkg/sentry/syscalls/linux/sys_prctl.go25
-rw-r--r--pkg/sentry/syscalls/linux/sys_random.go6
-rw-r--r--pkg/sentry/syscalls/linux/sys_read.go19
-rw-r--r--pkg/sentry/syscalls/linux/sys_rlimit.go9
-rw-r--r--pkg/sentry/syscalls/linux/sys_rseq.go3
-rw-r--r--pkg/sentry/syscalls/linux/sys_rusage.go4
-rw-r--r--pkg/sentry/syscalls/linux/sys_sched.go15
-rw-r--r--pkg/sentry/syscalls/linux/sys_seccomp.go8
-rw-r--r--pkg/sentry/syscalls/linux/sys_sem.go43
-rw-r--r--pkg/sentry/syscalls/linux/sys_shm.go12
-rw-r--r--pkg/sentry/syscalls/linux/sys_signal.go68
-rw-r--r--pkg/sentry/syscalls/linux/sys_socket.go45
-rw-r--r--pkg/sentry/syscalls/linux/sys_splice.go23
-rw-r--r--pkg/sentry/syscalls/linux/sys_stat.go7
-rw-r--r--pkg/sentry/syscalls/linux/sys_sync.go5
-rw-r--r--pkg/sentry/syscalls/linux/sys_syslog.go3
-rw-r--r--pkg/sentry/syscalls/linux/sys_thread.go41
-rw-r--r--pkg/sentry/syscalls/linux/sys_time.go87
-rw-r--r--pkg/sentry/syscalls/linux/sys_timerfd.go11
-rw-r--r--pkg/sentry/syscalls/linux/sys_tls_amd64.go3
-rw-r--r--pkg/sentry/syscalls/linux/sys_utsname.go5
-rw-r--r--pkg/sentry/syscalls/linux/sys_write.go13
-rw-r--r--pkg/sentry/syscalls/linux/sys_xattr.go9
-rw-r--r--pkg/sentry/syscalls/linux/timespec.go3
-rw-r--r--pkg/sentry/syscalls/linux/vfs2/BUILD1
-rw-r--r--pkg/sentry/syscalls/linux/vfs2/aio.go18
-rw-r--r--pkg/sentry/syscalls/linux/vfs2/epoll.go17
-rw-r--r--pkg/sentry/syscalls/linux/vfs2/eventfd.go4
-rw-r--r--pkg/sentry/syscalls/linux/vfs2/execve.go6
-rw-r--r--pkg/sentry/syscalls/linux/vfs2/fd.go21
-rw-r--r--pkg/sentry/syscalls/linux/vfs2/filesystem.go8
-rw-r--r--pkg/sentry/syscalls/linux/vfs2/getdents.go8
-rw-r--r--pkg/sentry/syscalls/linux/vfs2/inotify.go7
-rw-r--r--pkg/sentry/syscalls/linux/vfs2/ioctl.go3
-rw-r--r--pkg/sentry/syscalls/linux/vfs2/lock.go3
-rw-r--r--pkg/sentry/syscalls/linux/vfs2/memfd.go4
-rw-r--r--pkg/sentry/syscalls/linux/vfs2/mmap.go6
-rw-r--r--pkg/sentry/syscalls/linux/vfs2/mount.go8
-rw-r--r--pkg/sentry/syscalls/linux/vfs2/pipe.go7
-rw-r--r--pkg/sentry/syscalls/linux/vfs2/poll.go21
-rw-r--r--pkg/sentry/syscalls/linux/vfs2/read_write.go35
-rw-r--r--pkg/sentry/syscalls/linux/vfs2/setstat.go30
-rw-r--r--pkg/sentry/syscalls/linux/vfs2/signal.go8
-rw-r--r--pkg/sentry/syscalls/linux/vfs2/socket.go45
-rw-r--r--pkg/sentry/syscalls/linux/vfs2/splice.go31
-rw-r--r--pkg/sentry/syscalls/linux/vfs2/stat.go16
-rw-r--r--pkg/sentry/syscalls/linux/vfs2/sync.go5
-rw-r--r--pkg/sentry/syscalls/linux/vfs2/timerfd.go11
-rw-r--r--pkg/sentry/syscalls/linux/vfs2/xattr.go13
-rw-r--r--pkg/sentry/time/BUILD5
-rw-r--r--pkg/sentry/time/calibrated_clock.go4
-rw-r--r--pkg/sentry/time/sampler.go7
-rw-r--r--pkg/sentry/time/sampler_amd64.go26
-rw-r--r--pkg/sentry/time/sampler_arm64.go42
-rw-r--r--pkg/sentry/time/tsc_arm64.s6
-rw-r--r--pkg/sentry/usage/memory.go2
-rw-r--r--pkg/sentry/usage/memory_unsafe.go6
-rw-r--r--pkg/sentry/vfs/BUILD2
-rw-r--r--pkg/sentry/vfs/anonfs.go3
-rw-r--r--pkg/sentry/vfs/file_description.go9
-rw-r--r--pkg/sentry/vfs/file_description_impl_util.go15
-rw-r--r--pkg/sentry/vfs/file_description_impl_util_test.go9
-rw-r--r--pkg/sentry/vfs/inotify.go9
-rw-r--r--pkg/sentry/vfs/memxattr/BUILD1
-rw-r--r--pkg/sentry/vfs/memxattr/xattr.go33
-rw-r--r--pkg/sentry/vfs/mount.go11
-rw-r--r--pkg/sentry/vfs/vfs.go35
-rw-r--r--pkg/sentry/watchdog/watchdog.go13
351 files changed, 2689 insertions, 2508 deletions
diff --git a/pkg/sentry/arch/BUILD b/pkg/sentry/arch/BUILD
index c9c52530d..068a0c8d9 100644
--- a/pkg/sentry/arch/BUILD
+++ b/pkg/sentry/arch/BUILD
@@ -14,12 +14,8 @@ go_library(
"arch_x86.go",
"arch_x86_impl.go",
"auxv.go",
- "signal.go",
- "signal_act.go",
"signal_amd64.go",
"signal_arm64.go",
- "signal_info.go",
- "signal_stack.go",
"stack.go",
"stack_unsafe.go",
"syscalls_amd64.go",
@@ -32,6 +28,7 @@ go_library(
"//pkg/abi/linux",
"//pkg/context",
"//pkg/cpuid",
+ "//pkg/errors/linuxerr",
"//pkg/hostarch",
"//pkg/log",
"//pkg/marshal",
diff --git a/pkg/sentry/arch/arch.go b/pkg/sentry/arch/arch.go
index 290863ee6..c9393b091 100644
--- a/pkg/sentry/arch/arch.go
+++ b/pkg/sentry/arch/arch.go
@@ -134,21 +134,13 @@ type Context interface {
// RegisterMap returns a map of all registers.
RegisterMap() (map[string]uintptr, error)
- // NewSignalAct returns a new object that is equivalent to struct sigaction
- // in the guest architecture.
- NewSignalAct() NativeSignalAct
-
- // NewSignalStack returns a new object that is equivalent to stack_t in the
- // guest architecture.
- NewSignalStack() NativeSignalStack
-
// SignalSetup modifies the context in preparation for handling the
// given signal.
//
// st is the stack where the signal handler frame should be
// constructed.
//
- // act is the SignalAct that specifies how this signal is being
+ // act is the SigAction that specifies how this signal is being
// handled.
//
// info is the SignalInfo of the signal being delivered.
@@ -157,7 +149,7 @@ type Context interface {
// stack is not going to be used).
//
// sigset is the signal mask before entering the signal handler.
- SignalSetup(st *Stack, act *SignalAct, info *SignalInfo, alt *SignalStack, sigset linux.SignalSet) error
+ SignalSetup(st *Stack, act *linux.SigAction, info *linux.SignalInfo, alt *linux.SignalStack, sigset linux.SignalSet) error
// SignalRestore restores context after returning from a signal
// handler.
@@ -167,7 +159,7 @@ type Context interface {
// rt is true if SignalRestore is being entered from rt_sigreturn and
// false if SignalRestore is being entered from sigreturn.
// SignalRestore returns the thread's new signal mask.
- SignalRestore(st *Stack, rt bool) (linux.SignalSet, SignalStack, error)
+ SignalRestore(st *Stack, rt bool) (linux.SignalSet, linux.SignalStack, error)
// CPUIDEmulate emulates a CPUID instruction according to current register state.
CPUIDEmulate(l log.Logger)
diff --git a/pkg/sentry/arch/arch_aarch64.go b/pkg/sentry/arch/arch_aarch64.go
index 08789f517..7def71fef 100644
--- a/pkg/sentry/arch/arch_aarch64.go
+++ b/pkg/sentry/arch/arch_aarch64.go
@@ -22,6 +22,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/cpuid"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/sentry/arch/fpu"
rpb "gvisor.dev/gvisor/pkg/sentry/arch/registers_go_proto"
@@ -237,7 +238,7 @@ func (s *State) PtraceGetRegSet(regset uintptr, dst io.Writer, maxlen int) (int,
}
return s.PtraceGetRegs(dst)
default:
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
}
@@ -250,7 +251,7 @@ func (s *State) PtraceSetRegSet(regset uintptr, src io.Reader, maxlen int) (int,
}
return s.PtraceSetRegs(src)
default:
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
}
diff --git a/pkg/sentry/arch/arch_x86.go b/pkg/sentry/arch/arch_x86.go
index e8e52d3a8..d13e12f8c 100644
--- a/pkg/sentry/arch/arch_x86.go
+++ b/pkg/sentry/arch/arch_x86.go
@@ -23,6 +23,7 @@ import (
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/cpuid"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/sentry/arch/fpu"
rpb "gvisor.dev/gvisor/pkg/sentry/arch/registers_go_proto"
@@ -361,7 +362,7 @@ func (s *State) PtraceGetRegSet(regset uintptr, dst io.Writer, maxlen int) (int,
case _NT_X86_XSTATE:
return s.fpState.PtraceGetXstateRegs(dst, maxlen, s.FeatureSet)
default:
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
}
@@ -378,7 +379,7 @@ func (s *State) PtraceSetRegSet(regset uintptr, src io.Reader, maxlen int) (int,
case _NT_X86_XSTATE:
return s.fpState.PtraceSetXstateRegs(src, maxlen, s.FeatureSet)
default:
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
}
diff --git a/pkg/sentry/arch/signal.go b/pkg/sentry/arch/signal.go
deleted file mode 100644
index 67d7edf68..000000000
--- a/pkg/sentry/arch/signal.go
+++ /dev/null
@@ -1,276 +0,0 @@
-// Copyright 2020 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package arch
-
-import (
- "gvisor.dev/gvisor/pkg/abi/linux"
- "gvisor.dev/gvisor/pkg/hostarch"
-)
-
-// SignalAct represents the action that should be taken when a signal is
-// delivered, and is equivalent to struct sigaction.
-//
-// +marshal
-// +stateify savable
-type SignalAct struct {
- Handler uint64
- Flags uint64
- Restorer uint64 // Only used on amd64.
- Mask linux.SignalSet
-}
-
-// SerializeFrom implements NativeSignalAct.SerializeFrom.
-func (s *SignalAct) SerializeFrom(other *SignalAct) {
- *s = *other
-}
-
-// DeserializeTo implements NativeSignalAct.DeserializeTo.
-func (s *SignalAct) DeserializeTo(other *SignalAct) {
- *other = *s
-}
-
-// SignalStack represents information about a user stack, and is equivalent to
-// stack_t.
-//
-// +marshal
-// +stateify savable
-type SignalStack struct {
- Addr uint64
- Flags uint32
- _ uint32
- Size uint64
-}
-
-// SerializeFrom implements NativeSignalStack.SerializeFrom.
-func (s *SignalStack) SerializeFrom(other *SignalStack) {
- *s = *other
-}
-
-// DeserializeTo implements NativeSignalStack.DeserializeTo.
-func (s *SignalStack) DeserializeTo(other *SignalStack) {
- *other = *s
-}
-
-// SignalInfo represents information about a signal being delivered, and is
-// equivalent to struct siginfo in linux kernel(linux/include/uapi/asm-generic/siginfo.h).
-//
-// +marshal
-// +stateify savable
-type SignalInfo struct {
- Signo int32 // Signal number
- Errno int32 // Errno value
- Code int32 // Signal code
- _ uint32
-
- // struct siginfo::_sifields is a union. In SignalInfo, fields in the union
- // are accessed through methods.
- //
- // For reference, here is the definition of _sifields: (_sigfault._trapno,
- // which does not exist on x86, omitted for clarity)
- //
- // union {
- // int _pad[SI_PAD_SIZE];
- //
- // /* kill() */
- // struct {
- // __kernel_pid_t _pid; /* sender's pid */
- // __ARCH_SI_UID_T _uid; /* sender's uid */
- // } _kill;
- //
- // /* POSIX.1b timers */
- // struct {
- // __kernel_timer_t _tid; /* timer id */
- // int _overrun; /* overrun count */
- // char _pad[sizeof( __ARCH_SI_UID_T) - sizeof(int)];
- // sigval_t _sigval; /* same as below */
- // int _sys_private; /* not to be passed to user */
- // } _timer;
- //
- // /* POSIX.1b signals */
- // struct {
- // __kernel_pid_t _pid; /* sender's pid */
- // __ARCH_SI_UID_T _uid; /* sender's uid */
- // sigval_t _sigval;
- // } _rt;
- //
- // /* SIGCHLD */
- // struct {
- // __kernel_pid_t _pid; /* which child */
- // __ARCH_SI_UID_T _uid; /* sender's uid */
- // int _status; /* exit code */
- // __ARCH_SI_CLOCK_T _utime;
- // __ARCH_SI_CLOCK_T _stime;
- // } _sigchld;
- //
- // /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
- // struct {
- // void *_addr; /* faulting insn/memory ref. */
- // short _addr_lsb; /* LSB of the reported address */
- // } _sigfault;
- //
- // /* SIGPOLL */
- // struct {
- // __ARCH_SI_BAND_T _band; /* POLL_IN, POLL_OUT, POLL_MSG */
- // int _fd;
- // } _sigpoll;
- //
- // /* SIGSYS */
- // struct {
- // void *_call_addr; /* calling user insn */
- // int _syscall; /* triggering system call number */
- // unsigned int _arch; /* AUDIT_ARCH_* of syscall */
- // } _sigsys;
- // } _sifields;
- //
- // _sifields is padded so that the size of siginfo is SI_MAX_SIZE = 128
- // bytes.
- Fields [128 - 16]byte
-}
-
-// FixSignalCodeForUser fixes up si_code.
-//
-// The si_code we get from Linux may contain the kernel-specific code in the
-// top 16 bits if it's positive (e.g., from ptrace). Linux's
-// copy_siginfo_to_user does
-// err |= __put_user((short)from->si_code, &to->si_code);
-// to mask out those bits and we need to do the same.
-func (s *SignalInfo) FixSignalCodeForUser() {
- if s.Code > 0 {
- s.Code &= 0x0000ffff
- }
-}
-
-// PID returns the si_pid field.
-func (s *SignalInfo) PID() int32 {
- return int32(hostarch.ByteOrder.Uint32(s.Fields[0:4]))
-}
-
-// SetPID mutates the si_pid field.
-func (s *SignalInfo) SetPID(val int32) {
- hostarch.ByteOrder.PutUint32(s.Fields[0:4], uint32(val))
-}
-
-// UID returns the si_uid field.
-func (s *SignalInfo) UID() int32 {
- return int32(hostarch.ByteOrder.Uint32(s.Fields[4:8]))
-}
-
-// SetUID mutates the si_uid field.
-func (s *SignalInfo) SetUID(val int32) {
- hostarch.ByteOrder.PutUint32(s.Fields[4:8], uint32(val))
-}
-
-// Sigval returns the sigval field, which is aliased to both si_int and si_ptr.
-func (s *SignalInfo) Sigval() uint64 {
- return hostarch.ByteOrder.Uint64(s.Fields[8:16])
-}
-
-// SetSigval mutates the sigval field.
-func (s *SignalInfo) SetSigval(val uint64) {
- hostarch.ByteOrder.PutUint64(s.Fields[8:16], val)
-}
-
-// TimerID returns the si_timerid field.
-func (s *SignalInfo) TimerID() linux.TimerID {
- return linux.TimerID(hostarch.ByteOrder.Uint32(s.Fields[0:4]))
-}
-
-// SetTimerID sets the si_timerid field.
-func (s *SignalInfo) SetTimerID(val linux.TimerID) {
- hostarch.ByteOrder.PutUint32(s.Fields[0:4], uint32(val))
-}
-
-// Overrun returns the si_overrun field.
-func (s *SignalInfo) Overrun() int32 {
- return int32(hostarch.ByteOrder.Uint32(s.Fields[4:8]))
-}
-
-// SetOverrun sets the si_overrun field.
-func (s *SignalInfo) SetOverrun(val int32) {
- hostarch.ByteOrder.PutUint32(s.Fields[4:8], uint32(val))
-}
-
-// Addr returns the si_addr field.
-func (s *SignalInfo) Addr() uint64 {
- return hostarch.ByteOrder.Uint64(s.Fields[0:8])
-}
-
-// SetAddr sets the si_addr field.
-func (s *SignalInfo) SetAddr(val uint64) {
- hostarch.ByteOrder.PutUint64(s.Fields[0:8], val)
-}
-
-// Status returns the si_status field.
-func (s *SignalInfo) Status() int32 {
- return int32(hostarch.ByteOrder.Uint32(s.Fields[8:12]))
-}
-
-// SetStatus mutates the si_status field.
-func (s *SignalInfo) SetStatus(val int32) {
- hostarch.ByteOrder.PutUint32(s.Fields[8:12], uint32(val))
-}
-
-// CallAddr returns the si_call_addr field.
-func (s *SignalInfo) CallAddr() uint64 {
- return hostarch.ByteOrder.Uint64(s.Fields[0:8])
-}
-
-// SetCallAddr mutates the si_call_addr field.
-func (s *SignalInfo) SetCallAddr(val uint64) {
- hostarch.ByteOrder.PutUint64(s.Fields[0:8], val)
-}
-
-// Syscall returns the si_syscall field.
-func (s *SignalInfo) Syscall() int32 {
- return int32(hostarch.ByteOrder.Uint32(s.Fields[8:12]))
-}
-
-// SetSyscall mutates the si_syscall field.
-func (s *SignalInfo) SetSyscall(val int32) {
- hostarch.ByteOrder.PutUint32(s.Fields[8:12], uint32(val))
-}
-
-// Arch returns the si_arch field.
-func (s *SignalInfo) Arch() uint32 {
- return hostarch.ByteOrder.Uint32(s.Fields[12:16])
-}
-
-// SetArch mutates the si_arch field.
-func (s *SignalInfo) SetArch(val uint32) {
- hostarch.ByteOrder.PutUint32(s.Fields[12:16], val)
-}
-
-// Band returns the si_band field.
-func (s *SignalInfo) Band() int64 {
- return int64(hostarch.ByteOrder.Uint64(s.Fields[0:8]))
-}
-
-// SetBand mutates the si_band field.
-func (s *SignalInfo) SetBand(val int64) {
- // Note: this assumes the platform uses `long` as `__ARCH_SI_BAND_T`.
- // On some platforms, which gVisor doesn't support, `__ARCH_SI_BAND_T` is
- // `int`. See siginfo.h.
- hostarch.ByteOrder.PutUint64(s.Fields[0:8], uint64(val))
-}
-
-// FD returns the si_fd field.
-func (s *SignalInfo) FD() uint32 {
- return hostarch.ByteOrder.Uint32(s.Fields[8:12])
-}
-
-// SetFD mutates the si_fd field.
-func (s *SignalInfo) SetFD(val uint32) {
- hostarch.ByteOrder.PutUint32(s.Fields[8:12], val)
-}
diff --git a/pkg/sentry/arch/signal_act.go b/pkg/sentry/arch/signal_act.go
deleted file mode 100644
index d3e2324a8..000000000
--- a/pkg/sentry/arch/signal_act.go
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package arch
-
-import "gvisor.dev/gvisor/pkg/marshal"
-
-// Special values for SignalAct.Handler.
-const (
- // SignalActDefault is SIG_DFL and specifies that the default behavior for
- // a signal should be taken.
- SignalActDefault = 0
-
- // SignalActIgnore is SIG_IGN and specifies that a signal should be
- // ignored.
- SignalActIgnore = 1
-)
-
-// Available signal flags.
-const (
- SignalFlagNoCldStop = 0x00000001
- SignalFlagNoCldWait = 0x00000002
- SignalFlagSigInfo = 0x00000004
- SignalFlagRestorer = 0x04000000
- SignalFlagOnStack = 0x08000000
- SignalFlagRestart = 0x10000000
- SignalFlagInterrupt = 0x20000000
- SignalFlagNoDefer = 0x40000000
- SignalFlagResetHandler = 0x80000000
-)
-
-// IsSigInfo returns true iff this handle expects siginfo.
-func (s SignalAct) IsSigInfo() bool {
- return s.Flags&SignalFlagSigInfo != 0
-}
-
-// IsNoDefer returns true iff this SignalAct has the NoDefer flag set.
-func (s SignalAct) IsNoDefer() bool {
- return s.Flags&SignalFlagNoDefer != 0
-}
-
-// IsRestart returns true iff this SignalAct has the Restart flag set.
-func (s SignalAct) IsRestart() bool {
- return s.Flags&SignalFlagRestart != 0
-}
-
-// IsResetHandler returns true iff this SignalAct has the ResetHandler flag set.
-func (s SignalAct) IsResetHandler() bool {
- return s.Flags&SignalFlagResetHandler != 0
-}
-
-// IsOnStack returns true iff this SignalAct has the OnStack flag set.
-func (s SignalAct) IsOnStack() bool {
- return s.Flags&SignalFlagOnStack != 0
-}
-
-// HasRestorer returns true iff this SignalAct has the Restorer flag set.
-func (s SignalAct) HasRestorer() bool {
- return s.Flags&SignalFlagRestorer != 0
-}
-
-// NativeSignalAct is a type that is equivalent to struct sigaction in the
-// guest architecture.
-type NativeSignalAct interface {
- marshal.Marshallable
-
- // SerializeFrom copies the data in the host SignalAct s into this object.
- SerializeFrom(s *SignalAct)
-
- // DeserializeTo copies the data in this object into the host SignalAct s.
- DeserializeTo(s *SignalAct)
-}
diff --git a/pkg/sentry/arch/signal_amd64.go b/pkg/sentry/arch/signal_amd64.go
index 082ed92b1..58e28dbba 100644
--- a/pkg/sentry/arch/signal_amd64.go
+++ b/pkg/sentry/arch/signal_amd64.go
@@ -76,21 +76,11 @@ const (
type UContext64 struct {
Flags uint64
Link uint64
- Stack SignalStack
+ Stack linux.SignalStack
MContext SignalContext64
Sigset linux.SignalSet
}
-// NewSignalAct implements Context.NewSignalAct.
-func (c *context64) NewSignalAct() NativeSignalAct {
- return &SignalAct{}
-}
-
-// NewSignalStack implements Context.NewSignalStack.
-func (c *context64) NewSignalStack() NativeSignalStack {
- return &SignalStack{}
-}
-
// From Linux 'arch/x86/include/uapi/asm/sigcontext.h' the following is the
// size of the magic cookie at the end of the xsave frame.
//
@@ -110,7 +100,7 @@ func (c *context64) fpuFrameSize() (size int, useXsave bool) {
// SignalSetup implements Context.SignalSetup. (Compare to Linux's
// arch/x86/kernel/signal.c:__setup_rt_frame().)
-func (c *context64) SignalSetup(st *Stack, act *SignalAct, info *SignalInfo, alt *SignalStack, sigset linux.SignalSet) error {
+func (c *context64) SignalSetup(st *Stack, act *linux.SigAction, info *linux.SignalInfo, alt *linux.SignalStack, sigset linux.SignalSet) error {
sp := st.Bottom
// "The 128-byte area beyond the location pointed to by %rsp is considered
@@ -187,7 +177,7 @@ func (c *context64) SignalSetup(st *Stack, act *SignalAct, info *SignalInfo, alt
// Prior to proceeding, figure out if the frame will exhaust the range
// for the signal stack. This is not allowed, and should immediately
// force signal delivery (reverting to the default handler).
- if act.IsOnStack() && alt.IsEnabled() && !alt.Contains(frameBottom) {
+ if act.Flags&linux.SA_ONSTACK != 0 && alt.IsEnabled() && !alt.Contains(frameBottom) {
return unix.EFAULT
}
@@ -203,7 +193,7 @@ func (c *context64) SignalSetup(st *Stack, act *SignalAct, info *SignalInfo, alt
return err
}
ucAddr := st.Bottom
- if act.HasRestorer() {
+ if act.Flags&linux.SA_RESTORER != 0 {
// Push the restorer return address.
// Note that this doesn't need to be popped.
if _, err := primitive.CopyUint64Out(st, StackBottomMagic, act.Restorer); err != nil {
@@ -237,15 +227,15 @@ func (c *context64) SignalSetup(st *Stack, act *SignalAct, info *SignalInfo, alt
// SignalRestore implements Context.SignalRestore. (Compare to Linux's
// arch/x86/kernel/signal.c:sys_rt_sigreturn().)
-func (c *context64) SignalRestore(st *Stack, rt bool) (linux.SignalSet, SignalStack, error) {
+func (c *context64) SignalRestore(st *Stack, rt bool) (linux.SignalSet, linux.SignalStack, error) {
// Copy out the stack frame.
var uc UContext64
if _, err := uc.CopyIn(st, StackBottomMagic); err != nil {
- return 0, SignalStack{}, err
+ return 0, linux.SignalStack{}, err
}
- var info SignalInfo
+ var info linux.SignalInfo
if _, err := info.CopyIn(st, StackBottomMagic); err != nil {
- return 0, SignalStack{}, err
+ return 0, linux.SignalStack{}, err
}
// Restore registers.
diff --git a/pkg/sentry/arch/signal_arm64.go b/pkg/sentry/arch/signal_arm64.go
index da71fb873..80df90076 100644
--- a/pkg/sentry/arch/signal_arm64.go
+++ b/pkg/sentry/arch/signal_arm64.go
@@ -61,7 +61,7 @@ type FpsimdContext struct {
type UContext64 struct {
Flags uint64
Link uint64
- Stack SignalStack
+ Stack linux.SignalStack
Sigset linux.SignalSet
// glibc uses a 1024-bit sigset_t
_pad [120]byte // (1024 - 64) / 8 = 120
@@ -71,18 +71,8 @@ type UContext64 struct {
MContext SignalContext64
}
-// NewSignalAct implements Context.NewSignalAct.
-func (c *context64) NewSignalAct() NativeSignalAct {
- return &SignalAct{}
-}
-
-// NewSignalStack implements Context.NewSignalStack.
-func (c *context64) NewSignalStack() NativeSignalStack {
- return &SignalStack{}
-}
-
// SignalSetup implements Context.SignalSetup.
-func (c *context64) SignalSetup(st *Stack, act *SignalAct, info *SignalInfo, alt *SignalStack, sigset linux.SignalSet) error {
+func (c *context64) SignalSetup(st *Stack, act *linux.SigAction, info *linux.SignalInfo, alt *linux.SignalStack, sigset linux.SignalSet) error {
sp := st.Bottom
// Construct the UContext64 now since we need its size.
@@ -114,7 +104,7 @@ func (c *context64) SignalSetup(st *Stack, act *SignalAct, info *SignalInfo, alt
// Prior to proceeding, figure out if the frame will exhaust the range
// for the signal stack. This is not allowed, and should immediately
// force signal delivery (reverting to the default handler).
- if act.IsOnStack() && alt.IsEnabled() && !alt.Contains(frameBottom) {
+ if act.Flags&linux.SA_ONSTACK != 0 && alt.IsEnabled() && !alt.Contains(frameBottom) {
return unix.EFAULT
}
@@ -137,7 +127,7 @@ func (c *context64) SignalSetup(st *Stack, act *SignalAct, info *SignalInfo, alt
c.Regs.Regs[0] = uint64(info.Signo)
c.Regs.Regs[1] = uint64(infoAddr)
c.Regs.Regs[2] = uint64(ucAddr)
- c.Regs.Regs[30] = uint64(act.Restorer)
+ c.Regs.Regs[30] = act.Restorer
// Save the thread's floating point state.
c.sigFPState = append(c.sigFPState, c.fpState)
@@ -147,15 +137,15 @@ func (c *context64) SignalSetup(st *Stack, act *SignalAct, info *SignalInfo, alt
}
// SignalRestore implements Context.SignalRestore.
-func (c *context64) SignalRestore(st *Stack, rt bool) (linux.SignalSet, SignalStack, error) {
+func (c *context64) SignalRestore(st *Stack, rt bool) (linux.SignalSet, linux.SignalStack, error) {
// Copy out the stack frame.
var uc UContext64
if _, err := uc.CopyIn(st, StackBottomMagic); err != nil {
- return 0, SignalStack{}, err
+ return 0, linux.SignalStack{}, err
}
- var info SignalInfo
+ var info linux.SignalInfo
if _, err := info.CopyIn(st, StackBottomMagic); err != nil {
- return 0, SignalStack{}, err
+ return 0, linux.SignalStack{}, err
}
// Restore registers.
diff --git a/pkg/sentry/arch/signal_info.go b/pkg/sentry/arch/signal_info.go
deleted file mode 100644
index f93ee8b46..000000000
--- a/pkg/sentry/arch/signal_info.go
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package arch
-
-// Possible values for SignalInfo.Code. These values originate from the Linux
-// kernel's include/uapi/asm-generic/siginfo.h.
-const (
- // SignalInfoUser (properly SI_USER) indicates that a signal was sent from
- // a kill() or raise() syscall.
- SignalInfoUser = 0
-
- // SignalInfoKernel (properly SI_KERNEL) indicates that the signal was sent
- // by the kernel.
- SignalInfoKernel = 0x80
-
- // SignalInfoTimer (properly SI_TIMER) indicates that the signal was sent
- // by an expired timer.
- SignalInfoTimer = -2
-
- // SignalInfoTkill (properly SI_TKILL) indicates that the signal was sent
- // from a tkill() or tgkill() syscall.
- SignalInfoTkill = -6
-
- // CLD_* codes are only meaningful for SIGCHLD.
-
- // CLD_EXITED indicates that a task exited.
- CLD_EXITED = 1
-
- // CLD_KILLED indicates that a task was killed by a signal.
- CLD_KILLED = 2
-
- // CLD_DUMPED indicates that a task was killed by a signal and then dumped
- // core.
- CLD_DUMPED = 3
-
- // CLD_TRAPPED indicates that a task was stopped by ptrace.
- CLD_TRAPPED = 4
-
- // CLD_STOPPED indicates that a thread group completed a group stop.
- CLD_STOPPED = 5
-
- // CLD_CONTINUED indicates that a group-stopped thread group was continued.
- CLD_CONTINUED = 6
-
- // SYS_* codes are only meaningful for SIGSYS.
-
- // SYS_SECCOMP indicates that a signal originates from seccomp.
- SYS_SECCOMP = 1
-
- // TRAP_* codes are only meaningful for SIGTRAP.
-
- // TRAP_BRKPT indicates a breakpoint trap.
- TRAP_BRKPT = 1
-)
diff --git a/pkg/sentry/arch/signal_stack.go b/pkg/sentry/arch/signal_stack.go
deleted file mode 100644
index c732c7503..000000000
--- a/pkg/sentry/arch/signal_stack.go
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// +build 386 amd64 arm64
-
-package arch
-
-import (
- "gvisor.dev/gvisor/pkg/hostarch"
- "gvisor.dev/gvisor/pkg/marshal"
-)
-
-const (
- // SignalStackFlagOnStack is possible set on return from getaltstack,
- // in order to indicate that the thread is currently on the alt stack.
- SignalStackFlagOnStack = 1
-
- // SignalStackFlagDisable is a flag to indicate the stack is disabled.
- SignalStackFlagDisable = 2
-)
-
-// IsEnabled returns true iff this signal stack is marked as enabled.
-func (s SignalStack) IsEnabled() bool {
- return s.Flags&SignalStackFlagDisable == 0
-}
-
-// Top returns the stack's top address.
-func (s SignalStack) Top() hostarch.Addr {
- return hostarch.Addr(s.Addr + s.Size)
-}
-
-// SetOnStack marks this signal stack as in use.
-//
-// Note that there is no corresponding ClearOnStack, and that this should only
-// be called on copies that are serialized to userspace.
-func (s *SignalStack) SetOnStack() {
- s.Flags |= SignalStackFlagOnStack
-}
-
-// Contains checks if the stack pointer is within this stack.
-func (s *SignalStack) Contains(sp hostarch.Addr) bool {
- return hostarch.Addr(s.Addr) < sp && sp <= hostarch.Addr(s.Addr+s.Size)
-}
-
-// NativeSignalStack is a type that is equivalent to stack_t in the guest
-// architecture.
-type NativeSignalStack interface {
- marshal.Marshallable
-
- // SerializeFrom copies the data in the host SignalStack s into this
- // object.
- SerializeFrom(s *SignalStack)
-
- // DeserializeTo copies the data in this object into the host SignalStack
- // s.
- DeserializeTo(s *SignalStack)
-}
diff --git a/pkg/sentry/arch/stack.go b/pkg/sentry/arch/stack.go
index 65a794c7c..85e3515af 100644
--- a/pkg/sentry/arch/stack.go
+++ b/pkg/sentry/arch/stack.go
@@ -45,7 +45,7 @@ type Stack struct {
}
// scratchBufLen is the default length of Stack.scratchBuf. The
-// largest structs the stack regularly serializes are arch.SignalInfo
+// largest structs the stack regularly serializes are linux.SignalInfo
// and arch.UContext64. We'll set the default size as the larger of
// the two, arch.UContext64.
var scratchBufLen = (*UContext64)(nil).SizeBytes()
diff --git a/pkg/sentry/control/proc.go b/pkg/sentry/control/proc.go
index 367849e75..221e98a01 100644
--- a/pkg/sentry/control/proc.go
+++ b/pkg/sentry/control/proc.go
@@ -99,6 +99,9 @@ type ExecArgs struct {
// PIDNamespace is the pid namespace for the process being executed.
PIDNamespace *kernel.PIDNamespace
+
+ // Limits is the limit set for the process being executed.
+ Limits *limits.LimitSet
}
// String prints the arguments as a string.
@@ -151,6 +154,10 @@ func (proc *Proc) execAsync(args *ExecArgs) (*kernel.ThreadGroup, kernel.ThreadI
if pidns == nil {
pidns = proc.Kernel.RootPIDNamespace()
}
+ limitSet := args.Limits
+ if limitSet == nil {
+ limitSet = limits.NewLimitSet()
+ }
initArgs := kernel.CreateProcessArgs{
Filename: args.Filename,
Argv: args.Argv,
@@ -161,7 +168,7 @@ func (proc *Proc) execAsync(args *ExecArgs) (*kernel.ThreadGroup, kernel.ThreadI
Credentials: creds,
FDTable: fdTable,
Umask: 0022,
- Limits: limits.NewLimitSet(),
+ Limits: limitSet,
MaxSymlinkTraversals: linux.MaxSymlinkTraversals,
UTSNamespace: proc.Kernel.RootUTSNamespace(),
IPCNamespace: proc.Kernel.RootIPCNamespace(),
diff --git a/pkg/sentry/devices/tundev/BUILD b/pkg/sentry/devices/tundev/BUILD
index 8b38d574d..37229e7ba 100644
--- a/pkg/sentry/devices/tundev/BUILD
+++ b/pkg/sentry/devices/tundev/BUILD
@@ -9,6 +9,7 @@ go_library(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/hostarch",
"//pkg/sentry/arch",
"//pkg/sentry/fsimpl/devtmpfs",
diff --git a/pkg/sentry/devices/tundev/tundev.go b/pkg/sentry/devices/tundev/tundev.go
index a12eeb8e7..4ef91a600 100644
--- a/pkg/sentry/devices/tundev/tundev.go
+++ b/pkg/sentry/devices/tundev/tundev.go
@@ -18,6 +18,7 @@ package tundev
import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/devtmpfs"
@@ -81,7 +82,7 @@ func (fd *tunFD) Ioctl(ctx context.Context, uio usermem.IO, args arch.SyscallArg
}
stack, ok := t.NetworkContext().(*netstack.Stack)
if !ok {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
var req linux.IFReq
diff --git a/pkg/sentry/fs/BUILD b/pkg/sentry/fs/BUILD
index 0dc100f9b..74adbfa55 100644
--- a/pkg/sentry/fs/BUILD
+++ b/pkg/sentry/fs/BUILD
@@ -48,6 +48,7 @@ go_library(
"//pkg/abi/linux",
"//pkg/amutex",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/hostarch",
"//pkg/log",
"//pkg/p9",
@@ -110,6 +111,7 @@ go_test(
deps = [
":fs",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/sentry/fs/fsutil",
"//pkg/sentry/fs/ramfs",
"//pkg/sentry/fs/tmpfs",
diff --git a/pkg/sentry/fs/attr.go b/pkg/sentry/fs/attr.go
index b90f7c1be..4c99944e7 100644
--- a/pkg/sentry/fs/attr.go
+++ b/pkg/sentry/fs/attr.go
@@ -478,6 +478,20 @@ func (f FilePermissions) AnyRead() bool {
return f.User.Read || f.Group.Read || f.Other.Read
}
+// HasSetUIDOrGID returns true if either the setuid or setgid bit is set.
+func (f FilePermissions) HasSetUIDOrGID() bool {
+ return f.SetUID || f.SetGID
+}
+
+// DropSetUIDAndMaybeGID turns off setuid, and turns off setgid if f allows
+// group execution.
+func (f *FilePermissions) DropSetUIDAndMaybeGID() {
+ f.SetUID = false
+ if f.Group.Execute {
+ f.SetGID = false
+ }
+}
+
// FileOwner represents ownership of a file.
//
// +stateify savable
diff --git a/pkg/sentry/fs/copy_up.go b/pkg/sentry/fs/copy_up.go
index 5aa668873..a8591052c 100644
--- a/pkg/sentry/fs/copy_up.go
+++ b/pkg/sentry/fs/copy_up.go
@@ -20,6 +20,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/sentry/memmap"
@@ -161,7 +162,7 @@ func doCopyUp(ctx context.Context, d *Dirent) error {
// then try to take copyMu for writing here, we'd deadlock.
t := d.Inode.overlay.lower.StableAttr.Type
if t != RegularFile && t != Directory && t != Symlink {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
// Wait to get exclusive access to the upper Inode.
@@ -410,7 +411,7 @@ func copyAttributesLocked(ctx context.Context, upper *Inode, lower *Inode) error
return err
}
lowerXattr, err := lower.ListXattr(ctx, linux.XATTR_SIZE_MAX)
- if err != nil && err != syserror.EOPNOTSUPP {
+ if err != nil && !linuxerr.Equals(linuxerr.EOPNOTSUPP, err) {
return err
}
diff --git a/pkg/sentry/fs/dev/BUILD b/pkg/sentry/fs/dev/BUILD
index 23a3a9a2d..e28a8961b 100644
--- a/pkg/sentry/fs/dev/BUILD
+++ b/pkg/sentry/fs/dev/BUILD
@@ -18,6 +18,7 @@ go_library(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/hostarch",
"//pkg/rand",
"//pkg/safemem",
diff --git a/pkg/sentry/fs/dev/dev.go b/pkg/sentry/fs/dev/dev.go
index e84ba7a5d..c62effd52 100644
--- a/pkg/sentry/fs/dev/dev.go
+++ b/pkg/sentry/fs/dev/dev.go
@@ -16,6 +16,7 @@
package dev
import (
+ "fmt"
"math"
"gvisor.dev/gvisor/pkg/context"
@@ -90,6 +91,11 @@ func newSymlink(ctx context.Context, target string, msrc *fs.MountSource) *fs.In
// New returns the root node of a device filesystem.
func New(ctx context.Context, msrc *fs.MountSource) *fs.Inode {
+ shm, err := tmpfs.NewDir(ctx, nil, fs.RootOwner, fs.FilePermsFromMode(0777), msrc, nil /* parent */)
+ if err != nil {
+ panic(fmt.Sprintf("tmpfs.NewDir failed: %v", err))
+ }
+
contents := map[string]*fs.Inode{
"fd": newSymlink(ctx, "/proc/self/fd", msrc),
"stdin": newSymlink(ctx, "/proc/self/fd/0", msrc),
@@ -108,7 +114,7 @@ func New(ctx context.Context, msrc *fs.MountSource) *fs.Inode {
"random": newMemDevice(ctx, newRandomDevice(ctx, fs.RootOwner, 0444), msrc, randomDevMinor),
"urandom": newMemDevice(ctx, newRandomDevice(ctx, fs.RootOwner, 0444), msrc, urandomDevMinor),
- "shm": tmpfs.NewDir(ctx, nil, fs.RootOwner, fs.FilePermsFromMode(0777), msrc),
+ "shm": shm,
// A devpts is typically mounted at /dev/pts to provide
// pseudoterminal support. Place an empty directory there for
diff --git a/pkg/sentry/fs/dev/net_tun.go b/pkg/sentry/fs/dev/net_tun.go
index 77e8d222a..5674978bd 100644
--- a/pkg/sentry/fs/dev/net_tun.go
+++ b/pkg/sentry/fs/dev/net_tun.go
@@ -17,6 +17,7 @@ package dev
import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fs"
@@ -102,7 +103,7 @@ func (n *netTunFileOperations) Ioctl(ctx context.Context, file *fs.File, io user
}
stack, ok := t.NetworkContext().(*netstack.Stack)
if !ok {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
var req linux.IFReq
diff --git a/pkg/sentry/fs/dirent.go b/pkg/sentry/fs/dirent.go
index 9d5d40954..e21c9d78e 100644
--- a/pkg/sentry/fs/dirent.go
+++ b/pkg/sentry/fs/dirent.go
@@ -22,6 +22,7 @@ import (
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/refs"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/socket/unix/transport"
@@ -963,7 +964,7 @@ func (d *Dirent) mount(ctx context.Context, inode *Inode) (newChild *Dirent, err
//
// See Linux equivalent in fs/namespace.c:do_add_mount.
if IsSymlink(inode.StableAttr) {
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
// Dirent that'll replace d.
@@ -1439,7 +1440,7 @@ func Rename(ctx context.Context, root *Dirent, oldParent *Dirent, oldName string
// replaced is the dirent that is being overwritten by rename.
replaced, err := newParent.walk(ctx, root, newName, false /* may unlock */)
if err != nil {
- if err != syserror.ENOENT {
+ if !linuxerr.Equals(linuxerr.ENOENT, err) {
return err
}
diff --git a/pkg/sentry/fs/fdpipe/BUILD b/pkg/sentry/fs/fdpipe/BUILD
index 2120f2bad..1bd2055d0 100644
--- a/pkg/sentry/fs/fdpipe/BUILD
+++ b/pkg/sentry/fs/fdpipe/BUILD
@@ -13,6 +13,7 @@ go_library(
visibility = ["//pkg/sentry:internal"],
deps = [
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/fd",
"//pkg/fdnotifier",
"//pkg/log",
@@ -38,6 +39,7 @@ go_test(
library = ":fdpipe",
deps = [
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/fd",
"//pkg/fdnotifier",
"//pkg/hostarch",
diff --git a/pkg/sentry/fs/fdpipe/pipe.go b/pkg/sentry/fs/fdpipe/pipe.go
index 757b7d511..f8a29816b 100644
--- a/pkg/sentry/fs/fdpipe/pipe.go
+++ b/pkg/sentry/fs/fdpipe/pipe.go
@@ -20,6 +20,7 @@ import (
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fd"
"gvisor.dev/gvisor/pkg/fdnotifier"
"gvisor.dev/gvisor/pkg/log"
@@ -158,7 +159,7 @@ func (p *pipeOperations) Write(ctx context.Context, file *fs.File, src usermem.I
// isBlockError unwraps os errors and checks if they are caused by EAGAIN or
// EWOULDBLOCK. This is so they can be transformed into syserror.ErrWouldBlock.
func isBlockError(err error) bool {
- if err == syserror.EAGAIN || err == syserror.EWOULDBLOCK {
+ if linuxerr.Equals(linuxerr.EAGAIN, err) || linuxerr.Equals(linuxerr.EWOULDBLOCK, err) {
return true
}
if pe, ok := err.(*os.PathError); ok {
diff --git a/pkg/sentry/fs/fdpipe/pipe_test.go b/pkg/sentry/fs/fdpipe/pipe_test.go
index ab0e9dac7..6ea49cbb7 100644
--- a/pkg/sentry/fs/fdpipe/pipe_test.go
+++ b/pkg/sentry/fs/fdpipe/pipe_test.go
@@ -21,14 +21,14 @@ import (
"testing"
"golang.org/x/sys/unix"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fd"
"gvisor.dev/gvisor/pkg/fdnotifier"
+ "gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/contexttest"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/syserror"
"gvisor.dev/gvisor/pkg/usermem"
-
- "gvisor.dev/gvisor/pkg/hostarch"
)
func singlePipeFD() (int, error) {
@@ -214,7 +214,7 @@ func TestPipeRequest(t *testing.T) {
{
desc: "Fsync on pipe returns EINVAL",
context: &Fsync{},
- err: unix.EINVAL,
+ err: linuxerr.EINVAL,
},
{
desc: "Seek on pipe returns ESPIPE",
diff --git a/pkg/sentry/fs/file_overlay.go b/pkg/sentry/fs/file_overlay.go
index 696613f3a..7e2f107e0 100644
--- a/pkg/sentry/fs/file_overlay.go
+++ b/pkg/sentry/fs/file_overlay.go
@@ -18,6 +18,7 @@ import (
"io"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/refs"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/memmap"
@@ -417,7 +418,7 @@ func (f *overlayFileOperations) FifoSize(ctx context.Context, overlayFile *File)
err = f.onTop(ctx, overlayFile, func(file *File, ops FileOperations) error {
sz, ok := ops.(FifoSizer)
if !ok {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
rv, err = sz.FifoSize(ctx, file)
return err
@@ -432,11 +433,11 @@ func (f *overlayFileOperations) SetFifoSize(size int64) (rv int64, err error) {
if f.upper == nil {
// Named pipes cannot be copied up and changes to the lower are prohibited.
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
sz, ok := f.upper.FileOperations.(FifoSizer)
if !ok {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
return sz.SetFifoSize(size)
}
diff --git a/pkg/sentry/fs/fsutil/BUILD b/pkg/sentry/fs/fsutil/BUILD
index 6469cc3a9..ebc90b41f 100644
--- a/pkg/sentry/fs/fsutil/BUILD
+++ b/pkg/sentry/fs/fsutil/BUILD
@@ -76,6 +76,7 @@ go_library(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/hostarch",
"//pkg/log",
"//pkg/safemem",
diff --git a/pkg/sentry/fs/fsutil/file.go b/pkg/sentry/fs/fsutil/file.go
index dc9efa5df..c3525ba8e 100644
--- a/pkg/sentry/fs/fsutil/file.go
+++ b/pkg/sentry/fs/fsutil/file.go
@@ -18,6 +18,7 @@ import (
"io"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/memmap"
@@ -63,12 +64,12 @@ func SeekWithDirCursor(ctx context.Context, file *fs.File, whence fs.SeekWhence,
switch inode.StableAttr.Type {
case fs.RegularFile, fs.SpecialFile, fs.BlockDevice:
if offset < 0 {
- return current, syserror.EINVAL
+ return current, linuxerr.EINVAL
}
return offset, nil
case fs.Directory, fs.SpecialDirectory:
if offset != 0 {
- return current, syserror.EINVAL
+ return current, linuxerr.EINVAL
}
// SEEK_SET to 0 moves the directory "cursor" to the beginning.
if dirCursor != nil {
@@ -76,22 +77,22 @@ func SeekWithDirCursor(ctx context.Context, file *fs.File, whence fs.SeekWhence,
}
return 0, nil
default:
- return current, syserror.EINVAL
+ return current, linuxerr.EINVAL
}
case fs.SeekCurrent:
switch inode.StableAttr.Type {
case fs.RegularFile, fs.SpecialFile, fs.BlockDevice:
if current+offset < 0 {
- return current, syserror.EINVAL
+ return current, linuxerr.EINVAL
}
return current + offset, nil
case fs.Directory, fs.SpecialDirectory:
if offset != 0 {
- return current, syserror.EINVAL
+ return current, linuxerr.EINVAL
}
return current, nil
default:
- return current, syserror.EINVAL
+ return current, linuxerr.EINVAL
}
case fs.SeekEnd:
switch inode.StableAttr.Type {
@@ -103,14 +104,14 @@ func SeekWithDirCursor(ctx context.Context, file *fs.File, whence fs.SeekWhence,
}
sz := uattr.Size
if sz+offset < 0 {
- return current, syserror.EINVAL
+ return current, linuxerr.EINVAL
}
return sz + offset, nil
// FIXME(b/34778850): This is not universally correct.
// Remove SpecialDirectory.
case fs.SpecialDirectory:
if offset != 0 {
- return current, syserror.EINVAL
+ return current, linuxerr.EINVAL
}
// SEEK_END to 0 moves the directory "cursor" to the end.
//
@@ -121,12 +122,12 @@ func SeekWithDirCursor(ctx context.Context, file *fs.File, whence fs.SeekWhence,
// futile (EOF will always be the result).
return fs.FileMaxOffset, nil
default:
- return current, syserror.EINVAL
+ return current, linuxerr.EINVAL
}
}
// Not a valid seek request.
- return current, syserror.EINVAL
+ return current, linuxerr.EINVAL
}
// FileGenericSeek implements fs.FileOperations.Seek for files that use a
@@ -152,7 +153,7 @@ type FileNoSeek struct{}
// Seek implements fs.FileOperations.Seek.
func (FileNoSeek) Seek(context.Context, *fs.File, fs.SeekWhence, int64) (int64, error) {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// FilePipeSeek implements fs.FileOperations.Seek and can be used for files
@@ -178,7 +179,7 @@ type FileNoFsync struct{}
// Fsync implements fs.FileOperations.Fsync.
func (FileNoFsync) Fsync(context.Context, *fs.File, int64, int64, fs.SyncType) error {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
// FileNoopFsync implements fs.FileOperations.Fsync for files that don't need
@@ -345,7 +346,7 @@ func NewFileStaticContentReader(b []byte) FileStaticContentReader {
// Read implements fs.FileOperations.Read.
func (scr *FileStaticContentReader) Read(ctx context.Context, _ *fs.File, dst usermem.IOSequence, offset int64) (int64, error) {
if offset < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
if offset >= int64(len(scr.content)) {
return 0, nil
@@ -367,7 +368,7 @@ type FileNoRead struct{}
// Read implements fs.FileOperations.Read.
func (FileNoRead) Read(context.Context, *fs.File, usermem.IOSequence, int64) (int64, error) {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// FileNoWrite implements fs.FileOperations.Write to return EINVAL.
@@ -375,7 +376,7 @@ type FileNoWrite struct{}
// Write implements fs.FileOperations.Write.
func (FileNoWrite) Write(context.Context, *fs.File, usermem.IOSequence, int64) (int64, error) {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// FileNoopRead implement fs.FileOperations.Read as a noop.
diff --git a/pkg/sentry/fs/fsutil/host_mappable.go b/pkg/sentry/fs/fsutil/host_mappable.go
index e1e38b498..8ac3738e9 100644
--- a/pkg/sentry/fs/fsutil/host_mappable.go
+++ b/pkg/sentry/fs/fsutil/host_mappable.go
@@ -155,12 +155,20 @@ func (h *HostMappable) DecRef(fr memmap.FileRange) {
// T2: Appends to file causing it to grow
// T2: Writes to mapped pages and COW happens
// T1: Continues and wronly invalidates the page mapped in step above.
-func (h *HostMappable) Truncate(ctx context.Context, newSize int64) error {
+func (h *HostMappable) Truncate(ctx context.Context, newSize int64, uattr fs.UnstableAttr) error {
h.truncateMu.Lock()
defer h.truncateMu.Unlock()
mask := fs.AttrMask{Size: true}
attr := fs.UnstableAttr{Size: newSize}
+
+ // Truncating a file clears privilege bits.
+ if uattr.Perms.HasSetUIDOrGID() {
+ mask.Perms = true
+ attr.Perms = uattr.Perms
+ attr.Perms.DropSetUIDAndMaybeGID()
+ }
+
if err := h.backingFile.SetMaskedAttributes(ctx, mask, attr, false); err != nil {
return err
}
@@ -193,10 +201,17 @@ func (h *HostMappable) Allocate(ctx context.Context, offset int64, length int64)
}
// Write writes to the file backing this mappable.
-func (h *HostMappable) Write(ctx context.Context, src usermem.IOSequence, offset int64) (int64, error) {
+func (h *HostMappable) Write(ctx context.Context, src usermem.IOSequence, offset int64, uattr fs.UnstableAttr) (int64, error) {
h.truncateMu.RLock()
+ defer h.truncateMu.RUnlock()
n, err := src.CopyInTo(ctx, &writer{ctx: ctx, hostMappable: h, off: offset})
- h.truncateMu.RUnlock()
+ if n > 0 && uattr.Perms.HasSetUIDOrGID() {
+ mask := fs.AttrMask{Perms: true}
+ uattr.Perms.DropSetUIDAndMaybeGID()
+ if err := h.backingFile.SetMaskedAttributes(ctx, mask, uattr, false); err != nil {
+ return n, err
+ }
+ }
return n, err
}
diff --git a/pkg/sentry/fs/fsutil/inode.go b/pkg/sentry/fs/fsutil/inode.go
index 85e7e35db..bda07275d 100644
--- a/pkg/sentry/fs/fsutil/inode.go
+++ b/pkg/sentry/fs/fsutil/inode.go
@@ -17,6 +17,7 @@ package fsutil
import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/fs"
ktime "gvisor.dev/gvisor/pkg/sentry/kernel/time"
"gvisor.dev/gvisor/pkg/sentry/memmap"
@@ -376,7 +377,7 @@ func (InodeNotDirectory) RemoveDirectory(context.Context, *fs.Inode, string) err
// Rename implements fs.FileOperations.Rename.
func (InodeNotDirectory) Rename(context.Context, *fs.Inode, *fs.Inode, string, *fs.Inode, string, bool) error {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
// InodeNotSocket can be used by Inodes that are not sockets.
@@ -392,7 +393,7 @@ type InodeNotTruncatable struct{}
// Truncate implements fs.InodeOperations.Truncate.
func (InodeNotTruncatable) Truncate(context.Context, *fs.Inode, int64) error {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
// InodeIsDirTruncate implements fs.InodeOperations.Truncate for directories.
@@ -416,7 +417,7 @@ type InodeNotRenameable struct{}
// Rename implements fs.InodeOperations.Rename.
func (InodeNotRenameable) Rename(context.Context, *fs.Inode, *fs.Inode, string, *fs.Inode, string, bool) error {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
// InodeNotOpenable can be used by Inodes that cannot be opened.
diff --git a/pkg/sentry/fs/fsutil/inode_cached.go b/pkg/sentry/fs/fsutil/inode_cached.go
index 7856b354b..855029b84 100644
--- a/pkg/sentry/fs/fsutil/inode_cached.go
+++ b/pkg/sentry/fs/fsutil/inode_cached.go
@@ -310,6 +310,12 @@ func (c *CachingInodeOperations) Truncate(ctx context.Context, inode *fs.Inode,
now := ktime.NowFromContext(ctx)
masked := fs.AttrMask{Size: true}
attr := fs.UnstableAttr{Size: size}
+ if c.attr.Perms.HasSetUIDOrGID() {
+ masked.Perms = true
+ attr.Perms = c.attr.Perms
+ attr.Perms.DropSetUIDAndMaybeGID()
+ c.attr.Perms = attr.Perms
+ }
if err := c.backingFile.SetMaskedAttributes(ctx, masked, attr, false); err != nil {
c.dataMu.Unlock()
return err
@@ -685,13 +691,14 @@ func (rw *inodeReadWriter) ReadToBlocks(dsts safemem.BlockSeq) (uint64, error) {
return done, nil
}
-// maybeGrowFile grows the file's size if data has been written past the old
-// size.
+// maybeUpdateAttrs updates the file's attributes after a write. It updates
+// size if data has been written past the old size, and setuid/setgid if any
+// bytes were written.
//
// Preconditions:
// * rw.c.attrMu must be locked.
// * rw.c.dataMu must be locked.
-func (rw *inodeReadWriter) maybeGrowFile() {
+func (rw *inodeReadWriter) maybeUpdateAttrs(nwritten uint64) {
// If the write ends beyond the file's previous size, it causes the
// file to grow.
if rw.offset > rw.c.attr.Size {
@@ -705,6 +712,12 @@ func (rw *inodeReadWriter) maybeGrowFile() {
rw.c.attr.Usage = rw.offset
rw.c.dirtyAttr.Usage = true
}
+
+ // If bytes were written, ensure setuid and setgid are cleared.
+ if nwritten > 0 && rw.c.attr.Perms.HasSetUIDOrGID() {
+ rw.c.dirtyAttr.Perms = true
+ rw.c.attr.Perms.DropSetUIDAndMaybeGID()
+ }
}
// WriteFromBlocks implements safemem.Writer.WriteFromBlocks.
@@ -732,7 +745,7 @@ func (rw *inodeReadWriter) WriteFromBlocks(srcs safemem.BlockSeq) (uint64, error
segMR := seg.Range().Intersect(mr)
ims, err := mf.MapInternal(seg.FileRangeOf(segMR), hostarch.Write)
if err != nil {
- rw.maybeGrowFile()
+ rw.maybeUpdateAttrs(done)
rw.c.dataMu.Unlock()
return done, err
}
@@ -744,7 +757,7 @@ func (rw *inodeReadWriter) WriteFromBlocks(srcs safemem.BlockSeq) (uint64, error
srcs = srcs.DropFirst64(n)
rw.c.dirty.MarkDirty(segMR)
if err != nil {
- rw.maybeGrowFile()
+ rw.maybeUpdateAttrs(done)
rw.c.dataMu.Unlock()
return done, err
}
@@ -765,7 +778,7 @@ func (rw *inodeReadWriter) WriteFromBlocks(srcs safemem.BlockSeq) (uint64, error
srcs = srcs.DropFirst64(n)
// Partial writes are fine. But we must stop writing.
if n != src.NumBytes() || err != nil {
- rw.maybeGrowFile()
+ rw.maybeUpdateAttrs(done)
rw.c.dataMu.Unlock()
return done, err
}
@@ -774,7 +787,7 @@ func (rw *inodeReadWriter) WriteFromBlocks(srcs safemem.BlockSeq) (uint64, error
seg, gap = gap.NextSegment(), FileRangeGapIterator{}
}
}
- rw.maybeGrowFile()
+ rw.maybeUpdateAttrs(done)
rw.c.dataMu.Unlock()
return done, nil
}
diff --git a/pkg/sentry/fs/gofer/BUILD b/pkg/sentry/fs/gofer/BUILD
index 94cb05246..c08301d19 100644
--- a/pkg/sentry/fs/gofer/BUILD
+++ b/pkg/sentry/fs/gofer/BUILD
@@ -26,6 +26,7 @@ go_library(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/fd",
"//pkg/hostarch",
"//pkg/log",
diff --git a/pkg/sentry/fs/gofer/cache_policy.go b/pkg/sentry/fs/gofer/cache_policy.go
index 07a564e92..f8b7a60fc 100644
--- a/pkg/sentry/fs/gofer/cache_policy.go
+++ b/pkg/sentry/fs/gofer/cache_policy.go
@@ -139,7 +139,7 @@ func (cp cachePolicy) revalidate(ctx context.Context, name string, parent, child
// Walk from parent to child again.
//
- // TODO(b/112031682): If we have a directory FD in the parent
+ // NOTE(b/112031682): If we have a directory FD in the parent
// inodeOperations, then we can use fstatat(2) to get the inode
// attributes instead of making this RPC.
qids, f, mask, attr, err := parentIops.fileState.file.walkGetAttr(ctx, []string{name})
diff --git a/pkg/sentry/fs/gofer/file.go b/pkg/sentry/fs/gofer/file.go
index bcdb2dda2..73d80d9b5 100644
--- a/pkg/sentry/fs/gofer/file.go
+++ b/pkg/sentry/fs/gofer/file.go
@@ -92,7 +92,6 @@ func NewFile(ctx context.Context, dirent *fs.Dirent, name string, flags fs.FileF
}
if flags.Write {
if err := dirent.Inode.CheckPermission(ctx, fs.PermMask{Execute: true}); err == nil {
- fsmetric.GoferOpensWX.Increment()
metric.SuspiciousOperationsMetric.Increment("opened_write_execute_file")
log.Warningf("Opened a writable executable: %q", name)
}
@@ -238,10 +237,20 @@ func (f *fileOperations) Write(ctx context.Context, file *fs.File, src usermem.I
// and availability of a host-mappable FD.
if f.inodeOperations.session().cachePolicy.useCachingInodeOps(file.Dirent.Inode) {
n, err = f.inodeOperations.cachingInodeOps.Write(ctx, src, offset)
- } else if f.inodeOperations.fileState.hostMappable != nil {
- n, err = f.inodeOperations.fileState.hostMappable.Write(ctx, src, offset)
} else {
- n, err = src.CopyInTo(ctx, f.handles.readWriterAt(ctx, offset))
+ uattr, e := f.UnstableAttr(ctx, file)
+ if e != nil {
+ return 0, e
+ }
+ if f.inodeOperations.fileState.hostMappable != nil {
+ n, err = f.inodeOperations.fileState.hostMappable.Write(ctx, src, offset, uattr)
+ } else {
+ n, err = src.CopyInTo(ctx, f.handles.readWriterAt(ctx, offset))
+ if n > 0 && uattr.Perms.HasSetUIDOrGID() {
+ uattr.Perms.DropSetUIDAndMaybeGID()
+ f.inodeOperations.SetPermissions(ctx, file.Dirent.Inode, uattr.Perms)
+ }
+ }
}
if n == 0 {
diff --git a/pkg/sentry/fs/gofer/inode.go b/pkg/sentry/fs/gofer/inode.go
index b97635ec4..da3178527 100644
--- a/pkg/sentry/fs/gofer/inode.go
+++ b/pkg/sentry/fs/gofer/inode.go
@@ -600,11 +600,25 @@ func (i *inodeOperations) Truncate(ctx context.Context, inode *fs.Inode, length
if i.session().cachePolicy.useCachingInodeOps(inode) {
return i.cachingInodeOps.Truncate(ctx, inode, length)
}
+
+ uattr, err := i.fileState.unstableAttr(ctx)
+ if err != nil {
+ return err
+ }
+
if i.session().cachePolicy == cacheRemoteRevalidating {
- return i.fileState.hostMappable.Truncate(ctx, length)
+ return i.fileState.hostMappable.Truncate(ctx, length, uattr)
+ }
+
+ mask := p9.SetAttrMask{Size: true}
+ attr := p9.SetAttr{Size: uint64(length)}
+ if uattr.Perms.HasSetUIDOrGID() {
+ mask.Permissions = true
+ uattr.Perms.DropSetUIDAndMaybeGID()
+ attr.Permissions = p9.FileMode(uattr.Perms.LinuxMode())
}
- return i.fileState.file.setAttr(ctx, p9.SetAttrMask{Size: true}, p9.SetAttr{Size: uint64(length)})
+ return i.fileState.file.setAttr(ctx, mask, attr)
}
// GetXattr implements fs.InodeOperations.GetXattr.
diff --git a/pkg/sentry/fs/gofer/path.go b/pkg/sentry/fs/gofer/path.go
index 6b3627813..1a6f353d0 100644
--- a/pkg/sentry/fs/gofer/path.go
+++ b/pkg/sentry/fs/gofer/path.go
@@ -18,6 +18,7 @@ import (
"fmt"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/p9"
"gvisor.dev/gvisor/pkg/sentry/device"
@@ -66,7 +67,7 @@ func (i *inodeOperations) Lookup(ctx context.Context, dir *fs.Inode, name string
// Get a p9.File for name.
qids, newFile, mask, p9attr, err := i.fileState.file.walkGetAttr(ctx, []string{name})
if err != nil {
- if err == syserror.ENOENT {
+ if linuxerr.Equals(linuxerr.ENOENT, err) {
if cp.cacheNegativeDirents() {
// Return a negative Dirent. It will stay cached until something
// is created over it.
@@ -130,7 +131,16 @@ func (i *inodeOperations) Create(ctx context.Context, dir *fs.Inode, name string
panic(fmt.Sprintf("Create called with unknown or unset open flags: %v", flags))
}
+ // If the parent directory has setgid enabled, change the new file's owner.
owner := fs.FileOwnerFromContext(ctx)
+ parentUattr, err := dir.UnstableAttr(ctx)
+ if err != nil {
+ return nil, err
+ }
+ if parentUattr.Perms.SetGID {
+ owner.GID = parentUattr.Owner.GID
+ }
+
hostFile, err := newFile.create(ctx, name, openFlags, p9.FileMode(perm.LinuxMode()), p9.UID(owner.UID), p9.GID(owner.GID))
if err != nil {
// Could not create the file.
@@ -225,7 +235,18 @@ func (i *inodeOperations) CreateDirectory(ctx context.Context, dir *fs.Inode, s
return syserror.ENAMETOOLONG
}
+ // If the parent directory has setgid enabled, change the new directory's
+ // owner and enable setgid.
owner := fs.FileOwnerFromContext(ctx)
+ parentUattr, err := dir.UnstableAttr(ctx)
+ if err != nil {
+ return err
+ }
+ if parentUattr.Perms.SetGID {
+ owner.GID = parentUattr.Owner.GID
+ perm.SetGID = true
+ }
+
if _, err := i.fileState.file.mkdir(ctx, s, p9.FileMode(perm.LinuxMode()), p9.UID(owner.UID), p9.GID(owner.GID)); err != nil {
return err
}
@@ -278,7 +299,7 @@ func (i *inodeOperations) CreateFifo(ctx context.Context, dir *fs.Inode, name st
// N.B. FIFOs use major/minor numbers 0.
if _, err := i.fileState.file.mknod(ctx, name, mode, 0, 0, p9.UID(owner.UID), p9.GID(owner.GID)); err != nil {
- if i.session().overrides == nil || err != syserror.EPERM {
+ if i.session().overrides == nil || !linuxerr.Equals(linuxerr.EPERM, err) {
return err
}
// If gofer doesn't support mknod, check if we can create an internal fifo.
diff --git a/pkg/sentry/fs/host/BUILD b/pkg/sentry/fs/host/BUILD
index 3c45f6cc5..24fc6305c 100644
--- a/pkg/sentry/fs/host/BUILD
+++ b/pkg/sentry/fs/host/BUILD
@@ -28,9 +28,9 @@ go_library(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/fd",
"//pkg/fdnotifier",
- "//pkg/iovec",
"//pkg/log",
"//pkg/marshal/primitive",
"//pkg/refs",
@@ -40,6 +40,7 @@ go_library(
"//pkg/sentry/device",
"//pkg/sentry/fs",
"//pkg/sentry/fs/fsutil",
+ "//pkg/sentry/hostfd",
"//pkg/sentry/kernel",
"//pkg/sentry/kernel/auth",
"//pkg/sentry/kernel/time",
diff --git a/pkg/sentry/fs/host/socket.go b/pkg/sentry/fs/host/socket.go
index 46a2dc47d..225244868 100644
--- a/pkg/sentry/fs/host/socket.go
+++ b/pkg/sentry/fs/host/socket.go
@@ -21,6 +21,7 @@ import (
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fd"
"gvisor.dev/gvisor/pkg/fdnotifier"
"gvisor.dev/gvisor/pkg/refs"
@@ -213,7 +214,7 @@ func (c *ConnectedEndpoint) Send(ctx context.Context, data [][]byte, controlMess
// block (and only for stream sockets).
err = syserror.EAGAIN
}
- if n > 0 && err != syserror.EAGAIN {
+ if n > 0 && !linuxerr.Equals(linuxerr.EAGAIN, err) {
// The caller may need to block to send more data, but
// otherwise there isn't anything that can be done about an
// error with a partial write.
diff --git a/pkg/sentry/fs/host/socket_iovec.go b/pkg/sentry/fs/host/socket_iovec.go
index 7380d75e7..fd48aff11 100644
--- a/pkg/sentry/fs/host/socket_iovec.go
+++ b/pkg/sentry/fs/host/socket_iovec.go
@@ -16,7 +16,7 @@ package host
import (
"golang.org/x/sys/unix"
- "gvisor.dev/gvisor/pkg/iovec"
+ "gvisor.dev/gvisor/pkg/sentry/hostfd"
"gvisor.dev/gvisor/pkg/syserror"
)
@@ -72,7 +72,7 @@ func buildIovec(bufs [][]byte, maxlen int64, truncate bool) (length int64, iovec
}
}
- if iovsRequired > iovec.MaxIovs {
+ if iovsRequired > hostfd.MaxSendRecvMsgIov {
// The kernel will reject our call if we pass this many iovs.
// Use a single intermediate buffer instead.
b := make([]byte, stopLen)
diff --git a/pkg/sentry/fs/host/tty.go b/pkg/sentry/fs/host/tty.go
index 1183727ab..2ff520100 100644
--- a/pkg/sentry/fs/host/tty.go
+++ b/pkg/sentry/fs/host/tty.go
@@ -17,6 +17,7 @@ package host
import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/marshal/primitive"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fs"
@@ -191,7 +192,7 @@ func (t *TTYFileOperations) Ioctl(ctx context.Context, _ *fs.File, io usermem.IO
if err := t.checkChange(ctx, linux.SIGTTOU); err != nil {
// drivers/tty/tty_io.c:tiocspgrp() converts -EIO from
// tty_check_change() to -ENOTTY.
- if err == syserror.EIO {
+ if linuxerr.Equals(linuxerr.EIO, err) {
return 0, syserror.ENOTTY
}
return 0, err
@@ -211,7 +212,7 @@ func (t *TTYFileOperations) Ioctl(ctx context.Context, _ *fs.File, io usermem.IO
// pgID must be non-negative.
if pgID < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// Process group with pgID must exist in this PID namespace.
diff --git a/pkg/sentry/fs/host/util.go b/pkg/sentry/fs/host/util.go
index ab74724a3..e7db79189 100644
--- a/pkg/sentry/fs/host/util.go
+++ b/pkg/sentry/fs/host/util.go
@@ -19,12 +19,12 @@ import (
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/sentry/device"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
ktime "gvisor.dev/gvisor/pkg/sentry/kernel/time"
- "gvisor.dev/gvisor/pkg/syserror"
)
func nodeType(s *unix.Stat_t) fs.InodeType {
@@ -98,7 +98,7 @@ type dirInfo struct {
// isBlockError unwraps os errors and checks if they are caused by EAGAIN or
// EWOULDBLOCK. This is so they can be transformed into syserror.ErrWouldBlock.
func isBlockError(err error) bool {
- if err == syserror.EAGAIN || err == syserror.EWOULDBLOCK {
+ if linuxerr.Equals(linuxerr.EAGAIN, err) || linuxerr.Equals(linuxerr.EWOULDBLOCK, err) {
return true
}
if pe, ok := err.(*os.PathError); ok {
diff --git a/pkg/sentry/fs/inode_overlay.go b/pkg/sentry/fs/inode_overlay.go
index e97afc626..bd1125dcc 100644
--- a/pkg/sentry/fs/inode_overlay.go
+++ b/pkg/sentry/fs/inode_overlay.go
@@ -19,6 +19,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/sentry/socket/unix/transport"
"gvisor.dev/gvisor/pkg/syserror"
@@ -71,7 +72,7 @@ func overlayLookup(ctx context.Context, parent *overlayEntry, inode *Inode, name
// A file could have been created over a whiteout, so we need to
// check if something exists in the upper file system first.
child, err := parent.upper.Lookup(ctx, name)
- if err != nil && err != syserror.ENOENT {
+ if err != nil && !linuxerr.Equals(linuxerr.ENOENT, err) {
// We encountered an error that an overlay cannot handle,
// we must propagate it to the caller.
parent.copyMu.RUnlock()
@@ -125,7 +126,7 @@ func overlayLookup(ctx context.Context, parent *overlayEntry, inode *Inode, name
// Check the lower file system.
child, err := parent.lower.Lookup(ctx, name)
// Same song and dance as above.
- if err != nil && err != syserror.ENOENT {
+ if err != nil && !linuxerr.Equals(linuxerr.ENOENT, err) {
// Don't leak resources.
if upperInode != nil {
upperInode.DecRef(ctx)
@@ -396,7 +397,7 @@ func overlayRename(ctx context.Context, o *overlayEntry, oldParent *Dirent, rena
// newName has been removed out from under us. That's fine;
// filesystems where that can happen must handle stale
// 'replaced'.
- if err != nil && err != syserror.ENOENT {
+ if err != nil && !linuxerr.Equals(linuxerr.ENOENT, err) {
return err
}
if err == nil {
diff --git a/pkg/sentry/fs/inode_overlay_test.go b/pkg/sentry/fs/inode_overlay_test.go
index aa9851b26..cc5ffa6f1 100644
--- a/pkg/sentry/fs/inode_overlay_test.go
+++ b/pkg/sentry/fs/inode_overlay_test.go
@@ -18,6 +18,7 @@ import (
"testing"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/fs/fsutil"
"gvisor.dev/gvisor/pkg/sentry/fs/ramfs"
@@ -191,11 +192,11 @@ func TestLookup(t *testing.T) {
} {
t.Run(test.desc, func(t *testing.T) {
dirent, err := test.dir.Lookup(ctx, test.name)
- if test.found && (err == syserror.ENOENT || dirent.IsNegative()) {
+ if test.found && (linuxerr.Equals(linuxerr.ENOENT, err) || dirent.IsNegative()) {
t.Fatalf("lookup %q expected to find positive dirent, got dirent %v err %v", test.name, dirent, err)
}
if !test.found {
- if err != syserror.ENOENT && !dirent.IsNegative() {
+ if !linuxerr.Equals(linuxerr.ENOENT, err) && !dirent.IsNegative() {
t.Errorf("lookup %q expected to return ENOENT or negative dirent, got dirent %v err %v", test.name, dirent, err)
}
// Nothing more to check.
diff --git a/pkg/sentry/fs/inotify.go b/pkg/sentry/fs/inotify.go
index 1b83643db..4e07043c7 100644
--- a/pkg/sentry/fs/inotify.go
+++ b/pkg/sentry/fs/inotify.go
@@ -20,6 +20,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/memmap"
@@ -132,7 +133,7 @@ func (*Inotify) Write(context.Context, *File, usermem.IOSequence, int64) (int64,
// Read implements FileOperations.Read.
func (i *Inotify) Read(ctx context.Context, _ *File, dst usermem.IOSequence, _ int64) (int64, error) {
if dst.NumBytes() < inotifyEventBaseSize {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
i.evMu.Lock()
@@ -156,7 +157,7 @@ func (i *Inotify) Read(ctx context.Context, _ *File, dst usermem.IOSequence, _ i
// write some events out.
return writeLen, nil
}
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// Linux always dequeues an available event as long as there's enough
@@ -183,7 +184,7 @@ func (*Inotify) WriteTo(context.Context, *File, io.Writer, int64, bool) (int64,
// Fsync implements FileOperations.Fsync.
func (*Inotify) Fsync(context.Context, *File, int64, int64, SyncType) error {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
// ReadFrom implements FileOperations.ReadFrom.
@@ -329,7 +330,7 @@ func (i *Inotify) RmWatch(ctx context.Context, wd int32) error {
watch, ok := i.watches[wd]
if !ok {
i.mu.Unlock()
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
// Remove the watch from this instance.
diff --git a/pkg/sentry/fs/mock.go b/pkg/sentry/fs/mock.go
index 1d6ea5736..2a54c1242 100644
--- a/pkg/sentry/fs/mock.go
+++ b/pkg/sentry/fs/mock.go
@@ -16,6 +16,7 @@ package fs
import (
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/syserror"
)
@@ -109,7 +110,7 @@ func (n *MockInodeOperations) SetPermissions(context.Context, *Inode, FilePermis
// SetOwner implements fs.InodeOperations.SetOwner.
func (*MockInodeOperations) SetOwner(context.Context, *Inode, FileOwner) error {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
// SetTimestamps implements fs.InodeOperations.SetTimestamps.
diff --git a/pkg/sentry/fs/mounts.go b/pkg/sentry/fs/mounts.go
index 243098a09..340441974 100644
--- a/pkg/sentry/fs/mounts.go
+++ b/pkg/sentry/fs/mounts.go
@@ -20,6 +20,7 @@ import (
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/refs"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sync"
@@ -357,7 +358,7 @@ func (mns *MountNamespace) Unmount(ctx context.Context, node *Dirent, detachOnly
orig, ok := mns.mounts[node]
if !ok {
// node is not a mount point.
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if orig.previous == nil {
diff --git a/pkg/sentry/fs/overlay.go b/pkg/sentry/fs/overlay.go
index f96f5a3e5..7e72e47b5 100644
--- a/pkg/sentry/fs/overlay.go
+++ b/pkg/sentry/fs/overlay.go
@@ -19,11 +19,11 @@ import (
"strings"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/sentry/memmap"
"gvisor.dev/gvisor/pkg/sync"
- "gvisor.dev/gvisor/pkg/syserror"
)
// The virtual filesystem implements an overlay configuration. For a high-level
@@ -218,7 +218,7 @@ func newOverlayEntry(ctx context.Context, upper *Inode, lower *Inode, lowerExist
// We don't support copying up from character devices,
// named pipes, or anything weird (like proc files).
log.Warningf("%s not supported in lower filesytem", lower.StableAttr.Type)
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
}
return &overlayEntry{
diff --git a/pkg/sentry/fs/proc/BUILD b/pkg/sentry/fs/proc/BUILD
index 7af7e0b45..e6d74b949 100644
--- a/pkg/sentry/fs/proc/BUILD
+++ b/pkg/sentry/fs/proc/BUILD
@@ -30,6 +30,7 @@ go_library(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/hostarch",
"//pkg/log",
"//pkg/sentry/fs",
diff --git a/pkg/sentry/fs/proc/exec_args.go b/pkg/sentry/fs/proc/exec_args.go
index 24426b225..379429ab2 100644
--- a/pkg/sentry/fs/proc/exec_args.go
+++ b/pkg/sentry/fs/proc/exec_args.go
@@ -21,11 +21,11 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/fs/fsutil"
"gvisor.dev/gvisor/pkg/sentry/kernel"
- "gvisor.dev/gvisor/pkg/syserror"
"gvisor.dev/gvisor/pkg/usermem"
"gvisor.dev/gvisor/pkg/waiter"
)
@@ -104,7 +104,7 @@ var _ fs.FileOperations = (*execArgFile)(nil)
// Read reads the exec arg from the process's address space..
func (f *execArgFile) Read(ctx context.Context, _ *fs.File, dst usermem.IOSequence, offset int64) (int64, error) {
if offset < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
m, err := getTaskMM(f.t)
diff --git a/pkg/sentry/fs/proc/net.go b/pkg/sentry/fs/proc/net.go
index 91c35eea9..187e9a921 100644
--- a/pkg/sentry/fs/proc/net.go
+++ b/pkg/sentry/fs/proc/net.go
@@ -23,6 +23,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/sentry/fs"
@@ -34,7 +35,6 @@ import (
"gvisor.dev/gvisor/pkg/sentry/socket"
"gvisor.dev/gvisor/pkg/sentry/socket/unix"
"gvisor.dev/gvisor/pkg/sentry/socket/unix/transport"
- "gvisor.dev/gvisor/pkg/syserror"
"gvisor.dev/gvisor/pkg/tcpip/header"
)
@@ -291,7 +291,7 @@ func (n *netSnmp) ReadSeqFileData(ctx context.Context, h seqfile.SeqHandle) ([]s
continue
}
if err := n.s.Statistics(stat, line.prefix); err != nil {
- if err == syserror.EOPNOTSUPP {
+ if linuxerr.Equals(linuxerr.EOPNOTSUPP, err) {
log.Infof("Failed to retrieve %s of /proc/net/snmp: %v", line.prefix, err)
} else {
log.Warningf("Failed to retrieve %s of /proc/net/snmp: %v", line.prefix, err)
diff --git a/pkg/sentry/fs/proc/proc.go b/pkg/sentry/fs/proc/proc.go
index 2f2a9f920..546b57287 100644
--- a/pkg/sentry/fs/proc/proc.go
+++ b/pkg/sentry/fs/proc/proc.go
@@ -21,6 +21,7 @@ import (
"strconv"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/fs/fsutil"
"gvisor.dev/gvisor/pkg/sentry/fs/proc/device"
@@ -130,7 +131,7 @@ func (s *self) Readlink(ctx context.Context, inode *fs.Inode) (string, error) {
}
// Who is reading this link?
- return "", syserror.EINVAL
+ return "", linuxerr.EINVAL
}
// threadSelf is more magical than "self" link.
@@ -154,7 +155,7 @@ func (s *threadSelf) Readlink(ctx context.Context, inode *fs.Inode) (string, err
}
// Who is reading this link?
- return "", syserror.EINVAL
+ return "", linuxerr.EINVAL
}
// Lookup loads an Inode at name into a Dirent.
diff --git a/pkg/sentry/fs/proc/sys.go b/pkg/sentry/fs/proc/sys.go
index b998fb75d..085aa6d61 100644
--- a/pkg/sentry/fs/proc/sys.go
+++ b/pkg/sentry/fs/proc/sys.go
@@ -77,6 +77,27 @@ func (*overcommitMemory) ReadSeqFileData(ctx context.Context, h seqfile.SeqHandl
}, 0
}
+// +stateify savable
+type maxMapCount struct{}
+
+// NeedsUpdate implements seqfile.SeqSource.
+func (*maxMapCount) NeedsUpdate(int64) bool {
+ return true
+}
+
+// ReadSeqFileData implements seqfile.SeqSource.
+func (*maxMapCount) ReadSeqFileData(ctx context.Context, h seqfile.SeqHandle) ([]seqfile.SeqData, int64) {
+ if h != nil {
+ return nil, 0
+ }
+ return []seqfile.SeqData{
+ {
+ Buf: []byte("2147483647\n"),
+ Handle: (*maxMapCount)(nil),
+ },
+ }, 0
+}
+
func (p *proc) newKernelDir(ctx context.Context, msrc *fs.MountSource) *fs.Inode {
h := hostname{
SimpleFileInode: *fsutil.NewSimpleFileInode(ctx, fs.RootOwner, fs.FilePermsFromMode(0444), linux.PROC_SUPER_MAGIC),
@@ -96,6 +117,7 @@ func (p *proc) newKernelDir(ctx context.Context, msrc *fs.MountSource) *fs.Inode
func (p *proc) newVMDir(ctx context.Context, msrc *fs.MountSource) *fs.Inode {
children := map[string]*fs.Inode{
+ "max_map_count": seqfile.NewSeqFileInode(ctx, &maxMapCount{}, msrc),
"mmap_min_addr": seqfile.NewSeqFileInode(ctx, &mmapMinAddrData{p.k}, msrc),
"overcommit_memory": seqfile.NewSeqFileInode(ctx, &overcommitMemory{}, msrc),
}
diff --git a/pkg/sentry/fs/proc/sys_net.go b/pkg/sentry/fs/proc/sys_net.go
index 4893af56b..71f37d582 100644
--- a/pkg/sentry/fs/proc/sys_net.go
+++ b/pkg/sentry/fs/proc/sys_net.go
@@ -21,6 +21,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/fs/fsutil"
@@ -28,7 +29,6 @@ import (
"gvisor.dev/gvisor/pkg/sentry/fs/ramfs"
"gvisor.dev/gvisor/pkg/sentry/inet"
"gvisor.dev/gvisor/pkg/sync"
- "gvisor.dev/gvisor/pkg/syserror"
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
"gvisor.dev/gvisor/pkg/usermem"
"gvisor.dev/gvisor/pkg/waiter"
@@ -592,7 +592,7 @@ func (pf *portRangeFile) Write(ctx context.Context, _ *fs.File, src usermem.IOSe
// Port numbers must be uint16s.
if ports[0] < 0 || ports[1] < 0 || ports[0] > math.MaxUint16 || ports[1] > math.MaxUint16 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
if err := pf.inode.stack.SetPortRange(uint16(ports[0]), uint16(ports[1])); err != nil {
diff --git a/pkg/sentry/fs/proc/task.go b/pkg/sentry/fs/proc/task.go
index ae5ed25f9..7ece1377a 100644
--- a/pkg/sentry/fs/proc/task.go
+++ b/pkg/sentry/fs/proc/task.go
@@ -23,6 +23,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/fs/fsutil"
@@ -867,7 +868,7 @@ var _ fs.FileOperations = (*commFile)(nil)
// Read implements fs.FileOperations.Read.
func (f *commFile) Read(ctx context.Context, _ *fs.File, dst usermem.IOSequence, offset int64) (int64, error) {
if offset < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
buf := []byte(f.t.Name() + "\n")
@@ -922,7 +923,7 @@ type auxvecFile struct {
// Read implements fs.FileOperations.Read.
func (f *auxvecFile) Read(ctx context.Context, _ *fs.File, dst usermem.IOSequence, offset int64) (int64, error) {
if offset < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
m, err := getTaskMM(f.t)
diff --git a/pkg/sentry/fs/proc/uid_gid_map.go b/pkg/sentry/fs/proc/uid_gid_map.go
index 30d5ad4cf..fcdc1e7bd 100644
--- a/pkg/sentry/fs/proc/uid_gid_map.go
+++ b/pkg/sentry/fs/proc/uid_gid_map.go
@@ -21,12 +21,12 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/fs/fsutil"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
- "gvisor.dev/gvisor/pkg/syserror"
"gvisor.dev/gvisor/pkg/usermem"
"gvisor.dev/gvisor/pkg/waiter"
)
@@ -108,7 +108,7 @@ const maxIDMapLines = 5
// Read implements fs.FileOperations.Read.
func (imfo *idMapFileOperations) Read(ctx context.Context, file *fs.File, dst usermem.IOSequence, offset int64) (int64, error) {
if offset < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
var entries []auth.IDMapEntry
if imfo.iops.gids {
@@ -134,7 +134,7 @@ func (imfo *idMapFileOperations) Write(ctx context.Context, file *fs.File, src u
// the file ..." - user_namespaces(7)
srclen := src.NumBytes()
if srclen >= hostarch.PageSize || offset != 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
b := make([]byte, srclen)
if _, err := src.CopyIn(ctx, b); err != nil {
@@ -154,7 +154,7 @@ func (imfo *idMapFileOperations) Write(ctx context.Context, file *fs.File, src u
}
lines := bytes.SplitN(b, []byte("\n"), maxIDMapLines+1)
if len(lines) > maxIDMapLines {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
entries := make([]auth.IDMapEntry, len(lines))
@@ -162,7 +162,7 @@ func (imfo *idMapFileOperations) Write(ctx context.Context, file *fs.File, src u
var e auth.IDMapEntry
_, err := fmt.Sscan(string(l), &e.FirstID, &e.FirstParentID, &e.Length)
if err != nil {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
entries[i] = e
}
diff --git a/pkg/sentry/fs/proc/uptime.go b/pkg/sentry/fs/proc/uptime.go
index c0f6fb802..ac896f963 100644
--- a/pkg/sentry/fs/proc/uptime.go
+++ b/pkg/sentry/fs/proc/uptime.go
@@ -20,10 +20,10 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/fs/fsutil"
ktime "gvisor.dev/gvisor/pkg/sentry/kernel/time"
- "gvisor.dev/gvisor/pkg/syserror"
"gvisor.dev/gvisor/pkg/usermem"
"gvisor.dev/gvisor/pkg/waiter"
)
@@ -74,7 +74,7 @@ type uptimeFile struct {
// Read implements fs.FileOperations.Read.
func (f *uptimeFile) Read(ctx context.Context, _ *fs.File, dst usermem.IOSequence, offset int64) (int64, error) {
if offset < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
now := ktime.NowFromContext(ctx)
diff --git a/pkg/sentry/fs/splice.go b/pkg/sentry/fs/splice.go
index 33da82868..ca9f645f6 100644
--- a/pkg/sentry/fs/splice.go
+++ b/pkg/sentry/fs/splice.go
@@ -19,6 +19,7 @@ import (
"sync/atomic"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/syserror"
)
@@ -139,7 +140,7 @@ func Splice(ctx context.Context, dst *File, src *File, opts SpliceOpts) (int64,
// Attempt to do a WriteTo; this is likely the most efficient.
n, err := src.FileOperations.WriteTo(ctx, src, w, opts.Length, opts.Dup)
- if n == 0 && err == syserror.ENOSYS && !opts.Dup {
+ if n == 0 && linuxerr.Equals(linuxerr.ENOSYS, err) && !opts.Dup {
// Attempt as a ReadFrom. If a WriteTo, a ReadFrom may also be
// more efficient than a copy if buffers are cached or readily
// available. (It's unlikely that they can actually be donated).
@@ -151,7 +152,7 @@ func Splice(ctx context.Context, dst *File, src *File, opts SpliceOpts) (int64,
// if we block at some point, we could lose data. If the source is
// not a pipe then reading is not destructive; if the destination
// is a regular file, then it is guaranteed not to block writing.
- if n == 0 && err == syserror.ENOSYS && !opts.Dup && (!dstPipe || !srcPipe) {
+ if n == 0 && linuxerr.Equals(linuxerr.ENOSYS, err) && !opts.Dup && (!dstPipe || !srcPipe) {
// Fallback to an in-kernel copy.
n, err = io.Copy(w, &io.LimitedReader{
R: r,
diff --git a/pkg/sentry/fs/timerfd/BUILD b/pkg/sentry/fs/timerfd/BUILD
index c7977a217..0148b33cf 100644
--- a/pkg/sentry/fs/timerfd/BUILD
+++ b/pkg/sentry/fs/timerfd/BUILD
@@ -8,6 +8,7 @@ go_library(
visibility = ["//pkg/sentry:internal"],
deps = [
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/hostarch",
"//pkg/sentry/fs",
"//pkg/sentry/fs/anon",
diff --git a/pkg/sentry/fs/timerfd/timerfd.go b/pkg/sentry/fs/timerfd/timerfd.go
index c8ebe256c..093a14c1f 100644
--- a/pkg/sentry/fs/timerfd/timerfd.go
+++ b/pkg/sentry/fs/timerfd/timerfd.go
@@ -20,6 +20,7 @@ import (
"sync/atomic"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/fs/anon"
@@ -121,7 +122,7 @@ func (t *TimerOperations) EventUnregister(e *waiter.Entry) {
func (t *TimerOperations) Read(ctx context.Context, file *fs.File, dst usermem.IOSequence, offset int64) (int64, error) {
const sizeofUint64 = 8
if dst.NumBytes() < sizeofUint64 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
if val := atomic.SwapUint64(&t.val, 0); val != 0 {
var buf [sizeofUint64]byte
@@ -138,7 +139,7 @@ func (t *TimerOperations) Read(ctx context.Context, file *fs.File, dst usermem.I
// Write implements fs.FileOperations.Write.
func (t *TimerOperations) Write(context.Context, *fs.File, usermem.IOSequence, int64) (int64, error) {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// Notify implements ktime.TimerListener.Notify.
diff --git a/pkg/sentry/fs/tmpfs/BUILD b/pkg/sentry/fs/tmpfs/BUILD
index 90398376a..c36a20afe 100644
--- a/pkg/sentry/fs/tmpfs/BUILD
+++ b/pkg/sentry/fs/tmpfs/BUILD
@@ -15,6 +15,7 @@ go_library(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/hostarch",
"//pkg/safemem",
"//pkg/sentry/device",
diff --git a/pkg/sentry/fs/tmpfs/fs.go b/pkg/sentry/fs/tmpfs/fs.go
index bc117ca6a..b48d475ed 100644
--- a/pkg/sentry/fs/tmpfs/fs.go
+++ b/pkg/sentry/fs/tmpfs/fs.go
@@ -151,5 +151,5 @@ func (f *Filesystem) Mount(ctx context.Context, device string, flags fs.MountSou
}
// Construct the tmpfs root.
- return NewDir(ctx, nil, owner, perms, msrc), nil
+ return NewDir(ctx, nil, owner, perms, msrc, nil /* parent */)
}
diff --git a/pkg/sentry/fs/tmpfs/inode_file.go b/pkg/sentry/fs/tmpfs/inode_file.go
index f4de8c968..ce6be6386 100644
--- a/pkg/sentry/fs/tmpfs/inode_file.go
+++ b/pkg/sentry/fs/tmpfs/inode_file.go
@@ -21,6 +21,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/safemem"
"gvisor.dev/gvisor/pkg/sentry/fs"
@@ -226,6 +227,12 @@ func (f *fileInodeOperations) Truncate(ctx context.Context, _ *fs.Inode, size in
now := ktime.NowFromContext(ctx)
f.attr.ModificationTime = now
f.attr.StatusChangeTime = now
+
+ // Truncating clears privilege bits.
+ f.attr.Perms.SetUID = false
+ if f.attr.Perms.Group.Execute {
+ f.attr.Perms.SetGID = false
+ }
}
f.dataMu.Unlock()
@@ -363,7 +370,14 @@ func (f *fileInodeOperations) write(ctx context.Context, src usermem.IOSequence,
now := ktime.NowFromContext(ctx)
f.attr.ModificationTime = now
f.attr.StatusChangeTime = now
- return src.CopyInTo(ctx, &fileReadWriter{f, offset})
+ nwritten, err := src.CopyInTo(ctx, &fileReadWriter{f, offset})
+
+ // Writing clears privilege bits.
+ if nwritten > 0 {
+ f.attr.Perms.DropSetUIDAndMaybeGID()
+ }
+
+ return nwritten, err
}
type fileReadWriter struct {
@@ -442,7 +456,7 @@ func (rw *fileReadWriter) WriteFromBlocks(srcs safemem.BlockSeq) (uint64, error)
end := fs.WriteEndOffset(rw.offset, int64(srcs.NumBytes()))
if end == math.MaxInt64 {
// Overflow.
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// Check if seals prevent either file growth or all writes.
@@ -642,7 +656,7 @@ func GetSeals(inode *fs.Inode) (uint32, error) {
return f.seals, nil
}
// Not a memfd inode.
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// AddSeals adds new file seals to a memfd inode.
@@ -670,5 +684,5 @@ func AddSeals(inode *fs.Inode, val uint32) error {
return nil
}
// Not a memfd inode.
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
diff --git a/pkg/sentry/fs/tmpfs/tmpfs.go b/pkg/sentry/fs/tmpfs/tmpfs.go
index 577052888..6aa8ff331 100644
--- a/pkg/sentry/fs/tmpfs/tmpfs.go
+++ b/pkg/sentry/fs/tmpfs/tmpfs.go
@@ -87,7 +87,20 @@ type Dir struct {
var _ fs.InodeOperations = (*Dir)(nil)
// NewDir returns a new directory.
-func NewDir(ctx context.Context, contents map[string]*fs.Inode, owner fs.FileOwner, perms fs.FilePermissions, msrc *fs.MountSource) *fs.Inode {
+func NewDir(ctx context.Context, contents map[string]*fs.Inode, owner fs.FileOwner, perms fs.FilePermissions, msrc *fs.MountSource, parent *fs.Inode) (*fs.Inode, error) {
+ // If the parent has setgid enabled, the new directory enables it and changes
+ // its GID.
+ if parent != nil {
+ parentUattr, err := parent.UnstableAttr(ctx)
+ if err != nil {
+ return nil, err
+ }
+ if parentUattr.Perms.SetGID {
+ owner.GID = parentUattr.Owner.GID
+ perms.SetGID = true
+ }
+ }
+
d := &Dir{
ramfsDir: ramfs.NewDir(ctx, contents, owner, perms),
kernel: kernel.KernelFromContext(ctx),
@@ -101,7 +114,7 @@ func NewDir(ctx context.Context, contents map[string]*fs.Inode, owner fs.FileOwn
InodeID: tmpfsDevice.NextIno(),
BlockSize: hostarch.PageSize,
Type: fs.Directory,
- })
+ }), nil
}
// afterLoad is invoked by stateify.
@@ -219,11 +232,21 @@ func (d *Dir) SetTimestamps(ctx context.Context, i *fs.Inode, ts fs.TimeSpec) er
func (d *Dir) newCreateOps() *ramfs.CreateOps {
return &ramfs.CreateOps{
NewDir: func(ctx context.Context, dir *fs.Inode, perms fs.FilePermissions) (*fs.Inode, error) {
- return NewDir(ctx, nil, fs.FileOwnerFromContext(ctx), perms, dir.MountSource), nil
+ return NewDir(ctx, nil, fs.FileOwnerFromContext(ctx), perms, dir.MountSource, dir)
},
NewFile: func(ctx context.Context, dir *fs.Inode, perms fs.FilePermissions) (*fs.Inode, error) {
+ // If the parent has setgid enabled, change the GID of the new file.
+ owner := fs.FileOwnerFromContext(ctx)
+ parentUattr, err := dir.UnstableAttr(ctx)
+ if err != nil {
+ return nil, err
+ }
+ if parentUattr.Perms.SetGID {
+ owner.GID = parentUattr.Owner.GID
+ }
+
uattr := fs.WithCurrentTime(ctx, fs.UnstableAttr{
- Owner: fs.FileOwnerFromContext(ctx),
+ Owner: owner,
Perms: perms,
// Always start unlinked.
Links: 0,
diff --git a/pkg/sentry/fs/tty/BUILD b/pkg/sentry/fs/tty/BUILD
index 86ada820e..5933cb67b 100644
--- a/pkg/sentry/fs/tty/BUILD
+++ b/pkg/sentry/fs/tty/BUILD
@@ -17,6 +17,7 @@ go_library(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/hostarch",
"//pkg/marshal/primitive",
"//pkg/refs",
diff --git a/pkg/sentry/fs/tty/fs.go b/pkg/sentry/fs/tty/fs.go
index 13f4901db..0e5916380 100644
--- a/pkg/sentry/fs/tty/fs.go
+++ b/pkg/sentry/fs/tty/fs.go
@@ -16,9 +16,9 @@ package tty
import (
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/device"
"gvisor.dev/gvisor/pkg/sentry/fs"
- "gvisor.dev/gvisor/pkg/syserror"
)
// ptsDevice is the pseudo-filesystem device.
@@ -64,7 +64,7 @@ func (f *filesystem) Mount(ctx context.Context, device string, flags fs.MountSou
// No options are supported.
if data != "" {
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
return newDir(ctx, fs.NewMountSource(ctx, &superOperations{}, f, flags)), nil
diff --git a/pkg/sentry/fs/user/BUILD b/pkg/sentry/fs/user/BUILD
index 66e949c95..4acc73ee0 100644
--- a/pkg/sentry/fs/user/BUILD
+++ b/pkg/sentry/fs/user/BUILD
@@ -12,6 +12,7 @@ go_library(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/fspath",
"//pkg/log",
"//pkg/sentry/fs",
diff --git a/pkg/sentry/fs/user/path.go b/pkg/sentry/fs/user/path.go
index 124bc95ed..f6eaab2bd 100644
--- a/pkg/sentry/fs/user/path.go
+++ b/pkg/sentry/fs/user/path.go
@@ -21,6 +21,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fspath"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/sentry/fs"
@@ -93,7 +94,7 @@ func resolve(ctx context.Context, mns *fs.MountNamespace, paths []string, name s
binPath := path.Join(p, name)
traversals := uint(linux.MaxSymlinkTraversals)
d, err := mns.FindInode(ctx, root, nil, binPath, &traversals)
- if err == syserror.ENOENT || err == syserror.EACCES {
+ if linuxerr.Equals(linuxerr.ENOENT, err) || linuxerr.Equals(linuxerr.EACCES, err) {
// Didn't find it here.
continue
}
@@ -142,7 +143,7 @@ func resolveVFS2(ctx context.Context, creds *auth.Credentials, mns *vfs.MountNam
Flags: linux.O_RDONLY,
}
dentry, err := root.Mount().Filesystem().VirtualFilesystem().OpenAt(ctx, creds, pop, opts)
- if err == syserror.ENOENT || err == syserror.EACCES {
+ if linuxerr.Equals(linuxerr.ENOENT, err) || linuxerr.Equals(linuxerr.EACCES, err) {
// Didn't find it here.
continue
}
diff --git a/pkg/sentry/fs/user/user_test.go b/pkg/sentry/fs/user/user_test.go
index 12b786224..7f8fa8038 100644
--- a/pkg/sentry/fs/user/user_test.go
+++ b/pkg/sentry/fs/user/user_test.go
@@ -104,7 +104,10 @@ func TestGetExecUserHome(t *testing.T) {
t.Run(name, func(t *testing.T) {
ctx := contexttest.Context(t)
msrc := fs.NewPseudoMountSource(ctx)
- rootInode := tmpfs.NewDir(ctx, nil, fs.RootOwner, fs.FilePermsFromMode(0777), msrc)
+ rootInode, err := tmpfs.NewDir(ctx, nil, fs.RootOwner, fs.FilePermsFromMode(0777), msrc, nil /* parent */)
+ if err != nil {
+ t.Fatalf("tmpfs.NewDir failed: %v", err)
+ }
mns, err := fs.NewMountNamespace(ctx, rootInode)
if err != nil {
diff --git a/pkg/sentry/fsimpl/cgroupfs/BUILD b/pkg/sentry/fsimpl/cgroupfs/BUILD
index 37efb641a..4c9c5b344 100644
--- a/pkg/sentry/fsimpl/cgroupfs/BUILD
+++ b/pkg/sentry/fsimpl/cgroupfs/BUILD
@@ -31,6 +31,7 @@ go_library(
"//pkg/abi/linux",
"//pkg/context",
"//pkg/coverage",
+ "//pkg/errors/linuxerr",
"//pkg/log",
"//pkg/refs",
"//pkg/refsvfs2",
diff --git a/pkg/sentry/fsimpl/cgroupfs/base.go b/pkg/sentry/fsimpl/cgroupfs/base.go
index 6512e9cdb..4290ffe0d 100644
--- a/pkg/sentry/fsimpl/cgroupfs/base.go
+++ b/pkg/sentry/fsimpl/cgroupfs/base.go
@@ -23,10 +23,10 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/kernfs"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
- "gvisor.dev/gvisor/pkg/syserror"
"gvisor.dev/gvisor/pkg/usermem"
)
@@ -133,6 +133,17 @@ func (c *cgroupInode) Controllers() []kernel.CgroupController {
return c.fs.kcontrollers
}
+// tasks returns a snapshot of the tasks inside the cgroup.
+func (c *cgroupInode) tasks() []*kernel.Task {
+ c.fs.tasksMu.RLock()
+ defer c.fs.tasksMu.RUnlock()
+ ts := make([]*kernel.Task, 0, len(c.ts))
+ for t := range c.ts {
+ ts = append(ts, t)
+ }
+ return ts
+}
+
// Enter implements kernel.CgroupImpl.Enter.
func (c *cgroupInode) Enter(t *kernel.Task) {
c.fs.tasksMu.Lock()
@@ -163,10 +174,7 @@ func (d *cgroupProcsData) Generate(ctx context.Context, buf *bytes.Buffer) error
pgids := make(map[kernel.ThreadID]struct{})
- d.fs.tasksMu.RLock()
- defer d.fs.tasksMu.RUnlock()
-
- for task := range d.ts {
+ for _, task := range d.tasks() {
// Map dedups pgid, since iterating over all tasks produces multiple
// entries for the group leaders.
if pgid := currPidns.IDOfThreadGroup(task.ThreadGroup()); pgid != 0 {
@@ -205,10 +213,7 @@ func (d *tasksData) Generate(ctx context.Context, buf *bytes.Buffer) error {
var pids []kernel.ThreadID
- d.fs.tasksMu.RLock()
- defer d.fs.tasksMu.RUnlock()
-
- for task := range d.ts {
+ for _, task := range d.tasks() {
if pid := currPidns.IDOfTask(task); pid != 0 {
pids = append(pids, pid)
}
@@ -248,7 +253,7 @@ func parseInt64FromString(ctx context.Context, src usermem.IOSequence, offset in
// Note: This also handles zero-len writes if offset is beyond the end
// of src, or src is empty.
ctx.Warningf("cgroupfs.parseInt64FromString: failed to parse %q: %v", string(buf), err)
- return 0, int64(n), syserror.EINVAL
+ return 0, int64(n), linuxerr.EINVAL
}
return val, int64(n), nil
diff --git a/pkg/sentry/fsimpl/cgroupfs/cgroupfs.go b/pkg/sentry/fsimpl/cgroupfs/cgroupfs.go
index 54050de3c..b5883cbd2 100644
--- a/pkg/sentry/fsimpl/cgroupfs/cgroupfs.go
+++ b/pkg/sentry/fsimpl/cgroupfs/cgroupfs.go
@@ -49,8 +49,9 @@
//
// kernel.CgroupRegistry.mu
// cgroupfs.filesystem.mu
-// Task.mu
-// cgroupfs.filesystem.tasksMu.
+// kernel.TaskSet.mu
+// kernel.Task.mu
+// cgroupfs.filesystem.tasksMu.
package cgroupfs
import (
@@ -61,6 +62,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/kernfs"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
@@ -166,7 +168,7 @@ func (fsType FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
maxCachedDentries, err = strconv.ParseUint(str, 10, 64)
if err != nil {
ctx.Warningf("sys.FilesystemType.GetFilesystem: invalid dentry cache limit: dentry_cache_limit=%s", str)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
}
@@ -194,7 +196,7 @@ func (fsType FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
if _, ok := mopts["all"]; ok {
if len(wantControllers) > 0 {
ctx.Debugf("cgroupfs.FilesystemType.GetFilesystem: other controllers specified with all: %v", wantControllers)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
delete(mopts, "all")
@@ -208,7 +210,7 @@ func (fsType FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
if len(mopts) != 0 {
ctx.Debugf("cgroupfs.FilesystemType.GetFilesystem: unknown options: %v", mopts)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
k := kernel.KernelFromContext(ctx)
diff --git a/pkg/sentry/fsimpl/devpts/BUILD b/pkg/sentry/fsimpl/devpts/BUILD
index 6af3c3781..50b4c02ef 100644
--- a/pkg/sentry/fsimpl/devpts/BUILD
+++ b/pkg/sentry/fsimpl/devpts/BUILD
@@ -29,6 +29,7 @@ go_library(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/log",
"//pkg/marshal",
"//pkg/marshal/primitive",
diff --git a/pkg/sentry/fsimpl/devpts/devpts.go b/pkg/sentry/fsimpl/devpts/devpts.go
index e75954105..7a488e9fd 100644
--- a/pkg/sentry/fsimpl/devpts/devpts.go
+++ b/pkg/sentry/fsimpl/devpts/devpts.go
@@ -25,6 +25,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/kernfs"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/vfs"
@@ -56,7 +57,7 @@ func (*FilesystemType) Name() string {
func (fstype *FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.VirtualFilesystem, creds *auth.Credentials, source string, opts vfs.GetFilesystemOptions) (*vfs.Filesystem, *vfs.Dentry, error) {
// No data allowed.
if opts.Data != "" {
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
fstype.initOnce.Do(func() {
diff --git a/pkg/sentry/fsimpl/devpts/master.go b/pkg/sentry/fsimpl/devpts/master.go
index 93c031c89..1374fd3be 100644
--- a/pkg/sentry/fsimpl/devpts/master.go
+++ b/pkg/sentry/fsimpl/devpts/master.go
@@ -17,6 +17,7 @@ package devpts
import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/marshal/primitive"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/kernfs"
@@ -80,7 +81,7 @@ func (mi *masterInode) Stat(ctx context.Context, vfsfs *vfs.Filesystem, opts vfs
// SetStat implements kernfs.Inode.SetStat
func (mi *masterInode) SetStat(ctx context.Context, vfsfs *vfs.Filesystem, creds *auth.Credentials, opts vfs.SetStatOptions) error {
if opts.Stat.Mask&linux.STATX_SIZE != 0 {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
return mi.InodeAttrs.SetStat(ctx, vfsfs, creds, opts)
}
diff --git a/pkg/sentry/fsimpl/devpts/replica.go b/pkg/sentry/fsimpl/devpts/replica.go
index 96d2054cb..81572b991 100644
--- a/pkg/sentry/fsimpl/devpts/replica.go
+++ b/pkg/sentry/fsimpl/devpts/replica.go
@@ -17,6 +17,7 @@ package devpts
import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/marshal/primitive"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/kernfs"
@@ -92,7 +93,7 @@ func (ri *replicaInode) Stat(ctx context.Context, vfsfs *vfs.Filesystem, opts vf
// SetStat implements kernfs.Inode.SetStat
func (ri *replicaInode) SetStat(ctx context.Context, vfsfs *vfs.Filesystem, creds *auth.Credentials, opts vfs.SetStatOptions) error {
if opts.Stat.Mask&linux.STATX_SIZE != 0 {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
return ri.InodeAttrs.SetStat(ctx, vfsfs, creds, opts)
}
diff --git a/pkg/sentry/fsimpl/ext/BUILD b/pkg/sentry/fsimpl/ext/BUILD
index 2dbc6bfd5..5e8b464a0 100644
--- a/pkg/sentry/fsimpl/ext/BUILD
+++ b/pkg/sentry/fsimpl/ext/BUILD
@@ -47,6 +47,7 @@ go_library(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/fd",
"//pkg/fspath",
"//pkg/log",
@@ -88,13 +89,13 @@ go_test(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/fspath",
"//pkg/marshal/primitive",
"//pkg/sentry/contexttest",
"//pkg/sentry/fsimpl/ext/disklayout",
"//pkg/sentry/kernel/auth",
"//pkg/sentry/vfs",
- "//pkg/syserror",
"//pkg/test/testutil",
"//pkg/usermem",
"@com_github_google_go_cmp//cmp:go_default_library",
diff --git a/pkg/sentry/fsimpl/ext/block_map_file.go b/pkg/sentry/fsimpl/ext/block_map_file.go
index 1165234f9..79719faed 100644
--- a/pkg/sentry/fsimpl/ext/block_map_file.go
+++ b/pkg/sentry/fsimpl/ext/block_map_file.go
@@ -18,6 +18,7 @@ import (
"io"
"math"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/marshal/primitive"
"gvisor.dev/gvisor/pkg/syserror"
)
@@ -84,7 +85,7 @@ func (f *blockMapFile) ReadAt(dst []byte, off int64) (int, error) {
}
if off < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
offset := uint64(off)
diff --git a/pkg/sentry/fsimpl/ext/directory.go b/pkg/sentry/fsimpl/ext/directory.go
index 512b70ede..cc067c20e 100644
--- a/pkg/sentry/fsimpl/ext/directory.go
+++ b/pkg/sentry/fsimpl/ext/directory.go
@@ -17,12 +17,12 @@ package ext
import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/ext/disklayout"
"gvisor.dev/gvisor/pkg/sentry/vfs"
"gvisor.dev/gvisor/pkg/sync"
- "gvisor.dev/gvisor/pkg/syserror"
)
// directory represents a directory inode. It holds the childList in memory.
@@ -218,7 +218,7 @@ func (fd *directoryFD) IterDirents(ctx context.Context, cb vfs.IterDirentsCallba
// Seek implements vfs.FileDescriptionImpl.Seek.
func (fd *directoryFD) Seek(ctx context.Context, offset int64, whence int32) (int64, error) {
if whence != linux.SEEK_SET && whence != linux.SEEK_CUR {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
dir := fd.inode().impl.(*directory)
@@ -234,7 +234,7 @@ func (fd *directoryFD) Seek(ctx context.Context, offset int64, whence int32) (in
if offset < 0 {
// lseek(2) specifies that EINVAL should be returned if the resulting offset
// is negative.
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
n := int64(len(dir.childMap))
diff --git a/pkg/sentry/fsimpl/ext/ext.go b/pkg/sentry/fsimpl/ext/ext.go
index 38fb7962b..80854b501 100644
--- a/pkg/sentry/fsimpl/ext/ext.go
+++ b/pkg/sentry/fsimpl/ext/ext.go
@@ -22,12 +22,12 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fd"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/ext/disklayout"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/vfs"
- "gvisor.dev/gvisor/pkg/syserror"
)
// Name is the name of this filesystem.
@@ -133,13 +133,13 @@ func (fsType FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
// mount(2) specifies that EINVAL should be returned if the superblock is
// invalid.
fs.vfsfs.DecRef(ctx)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
// Refuse to mount if the filesystem is incompatible.
if !isCompatible(fs.sb) {
fs.vfsfs.DecRef(ctx)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
fs.bgs, err = readBlockGroups(dev, fs.sb)
diff --git a/pkg/sentry/fsimpl/ext/ext_test.go b/pkg/sentry/fsimpl/ext/ext_test.go
index d9fd4590c..db712e71f 100644
--- a/pkg/sentry/fsimpl/ext/ext_test.go
+++ b/pkg/sentry/fsimpl/ext/ext_test.go
@@ -26,12 +26,12 @@ import (
"github.com/google/go-cmp/cmp/cmpopts"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fspath"
"gvisor.dev/gvisor/pkg/sentry/contexttest"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/ext/disklayout"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/vfs"
- "gvisor.dev/gvisor/pkg/syserror"
"gvisor.dev/gvisor/pkg/test/testutil"
"gvisor.dev/gvisor/pkg/usermem"
)
@@ -173,7 +173,7 @@ func TestSeek(t *testing.T) {
}
// EINVAL should be returned if the resulting offset is negative.
- if _, err := fd.Seek(ctx, -1, linux.SEEK_SET); err != syserror.EINVAL {
+ if _, err := fd.Seek(ctx, -1, linux.SEEK_SET); !linuxerr.Equals(linuxerr.EINVAL, err) {
t.Errorf("expected error EINVAL but got %v", err)
}
@@ -187,7 +187,7 @@ func TestSeek(t *testing.T) {
}
// EINVAL should be returned if the resulting offset is negative.
- if _, err := fd.Seek(ctx, -(size + 2), linux.SEEK_CUR); err != syserror.EINVAL {
+ if _, err := fd.Seek(ctx, -(size + 2), linux.SEEK_CUR); !linuxerr.Equals(linuxerr.EINVAL, err) {
t.Errorf("expected error EINVAL but got %v", err)
}
@@ -204,7 +204,7 @@ func TestSeek(t *testing.T) {
}
// EINVAL should be returned if the resulting offset is negative.
- if _, err := fd.Seek(ctx, -(size + 1), linux.SEEK_END); err != syserror.EINVAL {
+ if _, err := fd.Seek(ctx, -(size + 1), linux.SEEK_END); !linuxerr.Equals(linuxerr.EINVAL, err) {
t.Errorf("expected error EINVAL but got %v", err)
}
}
diff --git a/pkg/sentry/fsimpl/ext/extent_file.go b/pkg/sentry/fsimpl/ext/extent_file.go
index 778460107..f449bc8bd 100644
--- a/pkg/sentry/fsimpl/ext/extent_file.go
+++ b/pkg/sentry/fsimpl/ext/extent_file.go
@@ -18,6 +18,7 @@ import (
"io"
"sort"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/ext/disklayout"
"gvisor.dev/gvisor/pkg/syserror"
)
@@ -65,7 +66,7 @@ func (f *extentFile) buildExtTree() error {
if f.root.Header.NumEntries > 4 {
// read(2) specifies that EINVAL should be returned if the file is unsuitable
// for reading.
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
f.root.Entries = make([]disklayout.ExtentEntryPair, f.root.Header.NumEntries)
@@ -145,7 +146,7 @@ func (f *extentFile) ReadAt(dst []byte, off int64) (int, error) {
}
if off < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
if uint64(off) >= f.regFile.inode.diskInode.Size() {
diff --git a/pkg/sentry/fsimpl/ext/filesystem.go b/pkg/sentry/fsimpl/ext/filesystem.go
index d4fc484a2..1d2eaa0d4 100644
--- a/pkg/sentry/fsimpl/ext/filesystem.go
+++ b/pkg/sentry/fsimpl/ext/filesystem.go
@@ -20,6 +20,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fspath"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/ext/disklayout"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
@@ -344,7 +345,7 @@ func (fs *filesystem) ReadlinkAt(ctx context.Context, rp *vfs.ResolvingPath) (st
}
symlink, ok := inode.impl.(*symlink)
if !ok {
- return "", syserror.EINVAL
+ return "", linuxerr.EINVAL
}
return symlink.target, nil
}
diff --git a/pkg/sentry/fsimpl/ext/inode.go b/pkg/sentry/fsimpl/ext/inode.go
index 4a555bf72..b3df2337f 100644
--- a/pkg/sentry/fsimpl/ext/inode.go
+++ b/pkg/sentry/fsimpl/ext/inode.go
@@ -19,6 +19,7 @@ import (
"sync/atomic"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/ext/disklayout"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/vfs"
@@ -147,7 +148,7 @@ func newInode(fs *filesystem, inodeNum uint32) (*inode, error) {
return &f.inode, nil
default:
// TODO(b/134676337): Return appropriate errors for sockets, pipes and devices.
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
}
diff --git a/pkg/sentry/fsimpl/ext/regular_file.go b/pkg/sentry/fsimpl/ext/regular_file.go
index 5ad9befcd..9a094716a 100644
--- a/pkg/sentry/fsimpl/ext/regular_file.go
+++ b/pkg/sentry/fsimpl/ext/regular_file.go
@@ -19,6 +19,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/safemem"
"gvisor.dev/gvisor/pkg/sentry/memmap"
"gvisor.dev/gvisor/pkg/sentry/vfs"
@@ -139,10 +140,10 @@ func (fd *regularFileFD) Seek(ctx context.Context, offset int64, whence int32) (
case linux.SEEK_END:
offset += int64(fd.inode().diskInode.Size())
default:
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
if offset < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
fd.off = offset
return offset, nil
diff --git a/pkg/sentry/fsimpl/fuse/BUILD b/pkg/sentry/fsimpl/fuse/BUILD
index 3a4777fbe..871df5984 100644
--- a/pkg/sentry/fsimpl/fuse/BUILD
+++ b/pkg/sentry/fsimpl/fuse/BUILD
@@ -46,6 +46,7 @@ go_library(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/hostarch",
"//pkg/log",
"//pkg/marshal",
@@ -76,6 +77,7 @@ go_test(
library = ":fuse",
deps = [
"//pkg/abi/linux",
+ "//pkg/errors/linuxerr",
"//pkg/hostarch",
"//pkg/marshal",
"//pkg/sentry/fsimpl/testutil",
diff --git a/pkg/sentry/fsimpl/fuse/connection_test.go b/pkg/sentry/fsimpl/fuse/connection_test.go
index 78ea6a31e..1fddd858e 100644
--- a/pkg/sentry/fsimpl/fuse/connection_test.go
+++ b/pkg/sentry/fsimpl/fuse/connection_test.go
@@ -19,9 +19,9 @@ import (
"testing"
"golang.org/x/sys/unix"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
- "gvisor.dev/gvisor/pkg/syserror"
)
// TestConnectionInitBlock tests if initialization
@@ -104,7 +104,7 @@ func TestConnectionAbort(t *testing.T) {
// After abort, Call() should return directly with ENOTCONN.
req := conn.NewRequest(creds, 0, 0, 0, testObj)
_, err = conn.Call(task, req)
- if err != syserror.ENOTCONN {
+ if !linuxerr.Equals(linuxerr.ENOTCONN, err) {
t.Fatalf("Incorrect error code received for Call() after connection aborted")
}
diff --git a/pkg/sentry/fsimpl/fuse/dev.go b/pkg/sentry/fsimpl/fuse/dev.go
index 5d2bae14e..0d0eed543 100644
--- a/pkg/sentry/fsimpl/fuse/dev.go
+++ b/pkg/sentry/fsimpl/fuse/dev.go
@@ -18,6 +18,7 @@ import (
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/vfs"
@@ -149,7 +150,7 @@ func (fd *DeviceFD) Read(ctx context.Context, dst usermem.IOSequence, opts vfs.R
// If the read buffer is too small, error out.
if dst.NumBytes() < int64(minBuffSize) {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
fd.mu.Lock()
@@ -293,7 +294,7 @@ func (fd *DeviceFD) writeLocked(ctx context.Context, src usermem.IOSequence, opt
// Assert that the header isn't read into the writeBuf yet.
if fd.writeCursor >= hdrLen {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// We don't have the full common response header yet.
@@ -322,7 +323,7 @@ func (fd *DeviceFD) writeLocked(ctx context.Context, src usermem.IOSequence, opt
if !ok {
// Server sent us a response for a request we never sent,
// or for which we already received a reply (e.g. aborted), an unlikely event.
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
delete(fd.completions, hdr.Unique)
@@ -434,7 +435,7 @@ func (fd *DeviceFD) sendError(ctx context.Context, errno int32, unique linux.FUS
if !ok {
// A response for a request we never sent,
// or for which we already received a reply (e.g. aborted).
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
delete(fd.completions, respHdr.Unique)
diff --git a/pkg/sentry/fsimpl/fuse/fusefs.go b/pkg/sentry/fsimpl/fuse/fusefs.go
index 167c899e2..be5bcd6af 100644
--- a/pkg/sentry/fsimpl/fuse/fusefs.go
+++ b/pkg/sentry/fsimpl/fuse/fusefs.go
@@ -23,6 +23,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/marshal"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/kernfs"
@@ -121,30 +122,30 @@ func (fsType FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
deviceDescriptorStr, ok := mopts["fd"]
if !ok {
ctx.Warningf("fusefs.FilesystemType.GetFilesystem: mandatory mount option fd missing")
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
delete(mopts, "fd")
deviceDescriptor, err := strconv.ParseInt(deviceDescriptorStr, 10 /* base */, 32 /* bitSize */)
if err != nil {
ctx.Debugf("fusefs.FilesystemType.GetFilesystem: invalid fd: %q (%v)", deviceDescriptorStr, err)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
kernelTask := kernel.TaskFromContext(ctx)
if kernelTask == nil {
log.Warningf("%s.GetFilesystem: couldn't get kernel task from context", fsType.Name())
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
fuseFDGeneric := kernelTask.GetFileVFS2(int32(deviceDescriptor))
if fuseFDGeneric == nil {
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
defer fuseFDGeneric.DecRef(ctx)
fuseFD, ok := fuseFDGeneric.Impl().(*DeviceFD)
if !ok {
log.Warningf("%s.GetFilesystem: device FD is %T, not a FUSE device", fsType.Name, fuseFDGeneric)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
// Parse and set all the other supported FUSE mount options.
@@ -154,17 +155,17 @@ func (fsType FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
uid, err := strconv.ParseUint(uidStr, 10, 32)
if err != nil {
log.Warningf("%s.GetFilesystem: invalid user_id: user_id=%s", fsType.Name(), uidStr)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
kuid := creds.UserNamespace.MapToKUID(auth.UID(uid))
if !kuid.Ok() {
ctx.Warningf("fusefs.FilesystemType.GetFilesystem: unmapped uid: %d", uid)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
fsopts.uid = kuid
} else {
ctx.Warningf("fusefs.FilesystemType.GetFilesystem: mandatory mount option user_id missing")
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
if gidStr, ok := mopts["group_id"]; ok {
@@ -172,17 +173,17 @@ func (fsType FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
gid, err := strconv.ParseUint(gidStr, 10, 32)
if err != nil {
log.Warningf("%s.GetFilesystem: invalid group_id: group_id=%s", fsType.Name(), gidStr)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
kgid := creds.UserNamespace.MapToKGID(auth.GID(gid))
if !kgid.Ok() {
ctx.Warningf("fusefs.FilesystemType.GetFilesystem: unmapped gid: %d", gid)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
fsopts.gid = kgid
} else {
ctx.Warningf("fusefs.FilesystemType.GetFilesystem: mandatory mount option group_id missing")
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
if modeStr, ok := mopts["rootmode"]; ok {
@@ -190,12 +191,12 @@ func (fsType FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
mode, err := strconv.ParseUint(modeStr, 8, 32)
if err != nil {
log.Warningf("%s.GetFilesystem: invalid mode: %q", fsType.Name(), modeStr)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
fsopts.rootMode = linux.FileMode(mode)
} else {
ctx.Warningf("fusefs.FilesystemType.GetFilesystem: mandatory mount option rootmode missing")
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
// Set the maxInFlightRequests option.
@@ -206,7 +207,7 @@ func (fsType FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
maxRead, err := strconv.ParseUint(maxReadStr, 10, 32)
if err != nil {
log.Warningf("%s.GetFilesystem: invalid max_read: max_read=%s", fsType.Name(), maxReadStr)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
if maxRead < fuseMinMaxRead {
maxRead = fuseMinMaxRead
@@ -229,7 +230,7 @@ func (fsType FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
// Check for unparsed options.
if len(mopts) != 0 {
log.Warningf("%s.GetFilesystem: unsupported or unknown options: %v", fsType.Name(), mopts)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
// Create a new FUSE filesystem.
@@ -258,7 +259,7 @@ func newFUSEFilesystem(ctx context.Context, vfsObj *vfs.VirtualFilesystem, fsTyp
conn, err := newFUSEConnection(ctx, fuseFD, opts)
if err != nil {
log.Warningf("fuse.NewFUSEFilesystem: NewFUSEConnection failed with error: %v", err)
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
fs := &filesystem{
@@ -418,7 +419,7 @@ func (i *inode) Open(ctx context.Context, rp *vfs.ResolvingPath, d *kernfs.Dentr
kernelTask := kernel.TaskFromContext(ctx)
if kernelTask == nil {
log.Warningf("fusefs.Inode.Open: couldn't get kernel task from context")
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
// Build the request.
@@ -440,7 +441,7 @@ func (i *inode) Open(ctx context.Context, rp *vfs.ResolvingPath, d *kernfs.Dentr
if err != nil {
return nil, err
}
- if err := res.Error(); err == syserror.ENOSYS && !isDir {
+ if err := res.Error(); linuxerr.Equals(linuxerr.ENOSYS, err) && !isDir {
i.fs.conn.noOpen = true
} else if err != nil {
return nil, err
@@ -512,7 +513,7 @@ func (i *inode) NewFile(ctx context.Context, name string, opts vfs.OpenOptions)
kernelTask := kernel.TaskFromContext(ctx)
if kernelTask == nil {
log.Warningf("fusefs.Inode.NewFile: couldn't get kernel task from context", i.nodeID)
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
in := linux.FUSECreateIn{
CreateMeta: linux.FUSECreateMeta{
@@ -552,7 +553,7 @@ func (i *inode) Unlink(ctx context.Context, name string, child kernfs.Inode) err
kernelTask := kernel.TaskFromContext(ctx)
if kernelTask == nil {
log.Warningf("fusefs.Inode.newEntry: couldn't get kernel task from context", i.nodeID)
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
in := linux.FUSEUnlinkIn{Name: name}
req := i.fs.conn.NewRequest(auth.CredentialsFromContext(ctx), uint32(kernelTask.ThreadID()), i.nodeID, linux.FUSE_UNLINK, &in)
@@ -596,7 +597,7 @@ func (i *inode) newEntry(ctx context.Context, name string, fileType linux.FileMo
kernelTask := kernel.TaskFromContext(ctx)
if kernelTask == nil {
log.Warningf("fusefs.Inode.newEntry: couldn't get kernel task from context", i.nodeID)
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
req := i.fs.conn.NewRequest(auth.CredentialsFromContext(ctx), uint32(kernelTask.ThreadID()), i.nodeID, opcode, payload)
res, err := i.fs.conn.Call(kernelTask, req)
@@ -626,13 +627,13 @@ func (i *inode) Getlink(ctx context.Context, mnt *vfs.Mount) (vfs.VirtualDentry,
// Readlink implements kernfs.Inode.Readlink.
func (i *inode) Readlink(ctx context.Context, mnt *vfs.Mount) (string, error) {
if i.Mode().FileType()&linux.S_IFLNK == 0 {
- return "", syserror.EINVAL
+ return "", linuxerr.EINVAL
}
if len(i.link) == 0 {
kernelTask := kernel.TaskFromContext(ctx)
if kernelTask == nil {
log.Warningf("fusefs.Inode.Readlink: couldn't get kernel task from context")
- return "", syserror.EINVAL
+ return "", linuxerr.EINVAL
}
req := i.fs.conn.NewRequest(auth.CredentialsFromContext(ctx), uint32(kernelTask.ThreadID()), i.nodeID, linux.FUSE_READLINK, &linux.FUSEEmptyIn{})
res, err := i.fs.conn.Call(kernelTask, req)
@@ -728,7 +729,7 @@ func (i *inode) getAttr(ctx context.Context, fs *vfs.Filesystem, opts vfs.StatOp
task := kernel.TaskFromContext(ctx)
if task == nil {
log.Warningf("couldn't get kernel task from context")
- return linux.FUSEAttr{}, syserror.EINVAL
+ return linux.FUSEAttr{}, linuxerr.EINVAL
}
creds := auth.CredentialsFromContext(ctx)
@@ -833,7 +834,7 @@ func (i *inode) setAttr(ctx context.Context, fs *vfs.Filesystem, creds *auth.Cre
task := kernel.TaskFromContext(ctx)
if task == nil {
log.Warningf("couldn't get kernel task from context")
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
// We should retain the original file type when assigning new mode.
diff --git a/pkg/sentry/fsimpl/fuse/read_write.go b/pkg/sentry/fsimpl/fuse/read_write.go
index 66ea889f9..35d0ab6f4 100644
--- a/pkg/sentry/fsimpl/fuse/read_write.go
+++ b/pkg/sentry/fsimpl/fuse/read_write.go
@@ -20,6 +20,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/sentry/kernel"
@@ -39,7 +40,7 @@ func (fs *filesystem) ReadInPages(ctx context.Context, fd *regularFileFD, off ui
t := kernel.TaskFromContext(ctx)
if t == nil {
log.Warningf("fusefs.Read: couldn't get kernel task from context")
- return nil, 0, syserror.EINVAL
+ return nil, 0, linuxerr.EINVAL
}
// Round up to a multiple of page size.
@@ -155,7 +156,7 @@ func (fs *filesystem) Write(ctx context.Context, fd *regularFileFD, off uint64,
t := kernel.TaskFromContext(ctx)
if t == nil {
log.Warningf("fusefs.Read: couldn't get kernel task from context")
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// One request cannnot exceed either maxWrite or maxPages.
diff --git a/pkg/sentry/fsimpl/fuse/regular_file.go b/pkg/sentry/fsimpl/fuse/regular_file.go
index 5bdd096c3..a0802cd32 100644
--- a/pkg/sentry/fsimpl/fuse/regular_file.go
+++ b/pkg/sentry/fsimpl/fuse/regular_file.go
@@ -22,6 +22,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/vfs"
"gvisor.dev/gvisor/pkg/syserror"
"gvisor.dev/gvisor/pkg/usermem"
@@ -39,7 +40,7 @@ type regularFileFD struct {
// PRead implements vfs.FileDescriptionImpl.PRead.
func (fd *regularFileFD) PRead(ctx context.Context, dst usermem.IOSequence, offset int64, opts vfs.ReadOptions) (int64, error) {
if offset < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// Check that flags are supported.
@@ -56,7 +57,7 @@ func (fd *regularFileFD) PRead(ctx context.Context, dst usermem.IOSequence, offs
} else if size > math.MaxUint32 {
// FUSE only supports uint32 for size.
// Overflow.
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// TODO(gvisor.dev/issue/3678): Add direct IO support.
@@ -143,7 +144,7 @@ func (fd *regularFileFD) Write(ctx context.Context, src usermem.IOSequence, opts
// final offset should be ignored by PWrite.
func (fd *regularFileFD) pwrite(ctx context.Context, src usermem.IOSequence, offset int64, opts vfs.WriteOptions) (written, finalOff int64, err error) {
if offset < 0 {
- return 0, offset, syserror.EINVAL
+ return 0, offset, linuxerr.EINVAL
}
// Check that flags are supported.
@@ -171,11 +172,11 @@ func (fd *regularFileFD) pwrite(ctx context.Context, src usermem.IOSequence, off
if srclen > math.MaxUint32 {
// FUSE only supports uint32 for size.
// Overflow.
- return 0, offset, syserror.EINVAL
+ return 0, offset, linuxerr.EINVAL
}
if end := offset + srclen; end < offset {
// Overflow.
- return 0, offset, syserror.EINVAL
+ return 0, offset, linuxerr.EINVAL
}
srclen, err = vfs.CheckLimit(ctx, offset, srclen)
diff --git a/pkg/sentry/fsimpl/gofer/BUILD b/pkg/sentry/fsimpl/gofer/BUILD
index 368272f12..752060044 100644
--- a/pkg/sentry/fsimpl/gofer/BUILD
+++ b/pkg/sentry/fsimpl/gofer/BUILD
@@ -49,6 +49,7 @@ go_library(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/fd",
"//pkg/fdnotifier",
"//pkg/fspath",
diff --git a/pkg/sentry/fsimpl/gofer/directory.go b/pkg/sentry/fsimpl/gofer/directory.go
index 177e42649..5c48a9fee 100644
--- a/pkg/sentry/fsimpl/gofer/directory.go
+++ b/pkg/sentry/fsimpl/gofer/directory.go
@@ -20,6 +20,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/p9"
"gvisor.dev/gvisor/pkg/refsvfs2"
@@ -28,7 +29,6 @@ import (
"gvisor.dev/gvisor/pkg/sentry/socket/unix/transport"
"gvisor.dev/gvisor/pkg/sentry/vfs"
"gvisor.dev/gvisor/pkg/sync"
- "gvisor.dev/gvisor/pkg/syserror"
)
func (d *dentry) isDir() bool {
@@ -297,7 +297,7 @@ func (fd *directoryFD) Seek(ctx context.Context, offset int64, whence int32) (in
switch whence {
case linux.SEEK_SET:
if offset < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
if offset == 0 {
// Ensure that the next call to fd.IterDirents() calls
@@ -309,13 +309,13 @@ func (fd *directoryFD) Seek(ctx context.Context, offset int64, whence int32) (in
case linux.SEEK_CUR:
offset += fd.off
if offset < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// Don't clear fd.dirents in this case, even if offset == 0.
fd.off = offset
return fd.off, nil
default:
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
}
diff --git a/pkg/sentry/fsimpl/gofer/filesystem.go b/pkg/sentry/fsimpl/gofer/filesystem.go
index 91ec4a142..067b7aac1 100644
--- a/pkg/sentry/fsimpl/gofer/filesystem.go
+++ b/pkg/sentry/fsimpl/gofer/filesystem.go
@@ -23,6 +23,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fspath"
"gvisor.dev/gvisor/pkg/p9"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/host"
@@ -255,7 +256,7 @@ func (fs *filesystem) getChildLocked(ctx context.Context, parent *dentry, name s
qid, file, attrMask, attr, err := parent.file.walkGetAttrOne(ctx, name)
if err != nil {
- if err == syserror.ENOENT {
+ if linuxerr.Equals(linuxerr.ENOENT, err) {
parent.cacheNegativeLookupLocked(name)
}
return nil, err
@@ -382,7 +383,7 @@ func (fs *filesystem) doCreateAt(ctx context.Context, rp *vfs.ResolvingPath, dir
return syserror.EEXIST
}
checkExistence := func() error {
- if child, err := fs.getChildLocked(ctx, parent, name, &ds); err != nil && err != syserror.ENOENT {
+ if child, err := fs.getChildLocked(ctx, parent, name, &ds); err != nil && !linuxerr.Equals(linuxerr.ENOENT, err) {
return err
} else if child != nil {
return syserror.EEXIST
@@ -469,7 +470,7 @@ func (fs *filesystem) unlinkAt(ctx context.Context, rp *vfs.ResolvingPath, dir b
name := rp.Component()
if dir {
if name == "." {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if name == ".." {
return syserror.ENOTEMPTY
@@ -715,7 +716,7 @@ func (fs *filesystem) MkdirAt(ctx context.Context, rp *vfs.ResolvingPath, opts v
mode |= linux.S_ISGID
}
if _, err := parent.file.mkdir(ctx, name, p9.FileMode(mode), (p9.UID)(creds.EffectiveKUID), p9.GID(kgid)); err != nil {
- if !opts.ForSyntheticMountpoint || err == syserror.EEXIST {
+ if !opts.ForSyntheticMountpoint || linuxerr.Equals(linuxerr.EEXIST, err) {
return err
}
ctx.Infof("Failed to create remote directory %q: %v; falling back to synthetic directory", name, err)
@@ -752,7 +753,7 @@ func (fs *filesystem) MknodAt(ctx context.Context, rp *vfs.ResolvingPath, opts v
return fs.doCreateAt(ctx, rp, false /* dir */, func(parent *dentry, name string, ds **[]*dentry) error {
creds := rp.Credentials()
_, err := parent.file.mknod(ctx, name, (p9.FileMode)(opts.Mode), opts.DevMajor, opts.DevMinor, (p9.UID)(creds.EffectiveKUID), (p9.GID)(creds.EffectiveKGID))
- if err != syserror.EPERM {
+ if !linuxerr.Equals(linuxerr.EPERM, err) {
return err
}
@@ -765,7 +766,7 @@ func (fs *filesystem) MknodAt(ctx context.Context, rp *vfs.ResolvingPath, opts v
case err == nil:
// Step succeeded, another file exists.
return syserror.EEXIST
- case err != syserror.ENOENT:
+ case !linuxerr.Equals(linuxerr.ENOENT, err):
// Unexpected error.
return err
}
@@ -862,7 +863,7 @@ afterTrailingSymlink:
// Determine whether or not we need to create a file.
parent.dirMu.Lock()
child, _, err := fs.stepLocked(ctx, rp, parent, false /* mayFollowSymlinks */, &ds)
- if err == syserror.ENOENT && mayCreate {
+ if linuxerr.Equals(linuxerr.ENOENT, err) && mayCreate {
if parent.isSynthetic() {
parent.dirMu.Unlock()
return nil, syserror.EPERM
@@ -942,7 +943,7 @@ func (d *dentry) open(ctx context.Context, rp *vfs.ResolvingPath, opts *vfs.Open
return nil, syserror.EISDIR
}
if opts.Flags&linux.O_DIRECT != 0 {
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
if !d.isSynthetic() {
if err := d.ensureSharedHandle(ctx, ats&vfs.MayRead != 0, false /* write */, false /* trunc */); err != nil {
@@ -998,7 +999,7 @@ func (d *dentry) open(ctx context.Context, rp *vfs.ResolvingPath, opts *vfs.Open
func (d *dentry) openSocketByConnecting(ctx context.Context, opts *vfs.OpenOptions) (*vfs.FileDescription, error) {
if opts.Flags&linux.O_DIRECT != 0 {
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
fdObj, err := d.file.connect(ctx, p9.AnonymousSocket)
if err != nil {
@@ -1019,7 +1020,7 @@ func (d *dentry) openSocketByConnecting(ctx context.Context, opts *vfs.OpenOptio
func (d *dentry) openSpecialFile(ctx context.Context, mnt *vfs.Mount, opts *vfs.OpenOptions) (*vfs.FileDescription, error) {
ats := vfs.AccessTypesForOpenFlags(opts)
if opts.Flags&linux.O_DIRECT != 0 {
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
// We assume that the server silently inserts O_NONBLOCK in the open flags
// for all named pipes (because all existing gofers do this).
@@ -1033,7 +1034,7 @@ func (d *dentry) openSpecialFile(ctx context.Context, mnt *vfs.Mount, opts *vfs.
retry:
h, err := openHandle(ctx, d.file, ats.MayRead(), ats.MayWrite(), opts.Flags&linux.O_TRUNC != 0)
if err != nil {
- if isBlockingOpenOfNamedPipe && ats == vfs.MayWrite && err == syserror.ENXIO {
+ if isBlockingOpenOfNamedPipe && ats == vfs.MayWrite && linuxerr.Equals(linuxerr.ENXIO, err) {
// An attempt to open a named pipe with O_WRONLY|O_NONBLOCK fails
// with ENXIO if opening the same named pipe with O_WRONLY would
// block because there are no readers of the pipe.
@@ -1187,18 +1188,14 @@ func (fs *filesystem) ReadlinkAt(ctx context.Context, rp *vfs.ResolvingPath) (st
return "", err
}
if !d.isSymlink() {
- return "", syserror.EINVAL
+ return "", linuxerr.EINVAL
}
return d.readlink(ctx, rp.Mount())
}
// RenameAt implements vfs.FilesystemImpl.RenameAt.
func (fs *filesystem) RenameAt(ctx context.Context, rp *vfs.ResolvingPath, oldParentVD vfs.VirtualDentry, oldName string, opts vfs.RenameOptions) error {
- if opts.Flags != 0 {
- // Requires 9P support.
- return syserror.EINVAL
- }
-
+ // Resolve newParent first to verify that it's on this Mount.
var ds *[]*dentry
fs.renameMu.Lock()
defer fs.renameMuUnlockAndCheckCaching(ctx, &ds)
@@ -1206,8 +1203,21 @@ func (fs *filesystem) RenameAt(ctx context.Context, rp *vfs.ResolvingPath, oldPa
if err != nil {
return err
}
+
+ if opts.Flags&^linux.RENAME_NOREPLACE != 0 {
+ return linuxerr.EINVAL
+ }
+ if fs.opts.interop == InteropModeShared && opts.Flags&linux.RENAME_NOREPLACE != 0 {
+ // Requires 9P support to synchronize with other remote filesystem
+ // users.
+ return linuxerr.EINVAL
+ }
+
newName := rp.Component()
if newName == "." || newName == ".." {
+ if opts.Flags&linux.RENAME_NOREPLACE != 0 {
+ return syserror.EEXIST
+ }
return syserror.EBUSY
}
mnt := rp.Mount()
@@ -1251,7 +1261,7 @@ func (fs *filesystem) RenameAt(ctx context.Context, rp *vfs.ResolvingPath, oldPa
}
if renamed.isDir() {
if renamed == newParent || genericIsAncestorDentry(renamed, newParent) {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if oldParent != newParent {
if err := renamed.checkPermissions(creds, vfs.MayWrite); err != nil {
@@ -1275,11 +1285,14 @@ func (fs *filesystem) RenameAt(ctx context.Context, rp *vfs.ResolvingPath, oldPa
return syserror.ENOENT
}
replaced, err := fs.getChildLocked(ctx, newParent, newName, &ds)
- if err != nil && err != syserror.ENOENT {
+ if err != nil && !linuxerr.Equals(linuxerr.ENOENT, err) {
return err
}
var replacedVFSD *vfs.Dentry
if replaced != nil {
+ if opts.Flags&linux.RENAME_NOREPLACE != 0 {
+ return syserror.EEXIST
+ }
replacedVFSD = &replaced.vfsd
if replaced.isDir() {
if !renamed.isDir() {
diff --git a/pkg/sentry/fsimpl/gofer/gofer.go b/pkg/sentry/fsimpl/gofer/gofer.go
index 21692d2ac..c7ebd435c 100644
--- a/pkg/sentry/fsimpl/gofer/gofer.go
+++ b/pkg/sentry/fsimpl/gofer/gofer.go
@@ -46,6 +46,7 @@ import (
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/p9"
@@ -318,7 +319,7 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
mfp := pgalloc.MemoryFileProviderFromContext(ctx)
if mfp == nil {
ctx.Warningf("gofer.FilesystemType.GetFilesystem: context does not provide a pgalloc.MemoryFileProvider")
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
mopts := vfs.GenericParseMountOptions(opts.Data)
@@ -354,7 +355,7 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
fsopts.interop = InteropModeShared
default:
ctx.Warningf("gofer.FilesystemType.GetFilesystem: invalid cache policy: %s=%s", moptCache, cache)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
}
@@ -365,7 +366,7 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
dfltuid, err := strconv.ParseUint(dfltuidstr, 10, 32)
if err != nil {
ctx.Warningf("gofer.FilesystemType.GetFilesystem: invalid default UID: %s=%s", moptDfltUID, dfltuidstr)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
// In Linux, dfltuid is interpreted as a UID and is converted to a KUID
// in the caller's user namespace, but goferfs isn't
@@ -378,7 +379,7 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
dfltgid, err := strconv.ParseUint(dfltgidstr, 10, 32)
if err != nil {
ctx.Warningf("gofer.FilesystemType.GetFilesystem: invalid default UID: %s=%s", moptDfltGID, dfltgidstr)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
fsopts.dfltgid = auth.KGID(dfltgid)
}
@@ -390,7 +391,7 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
msize, err := strconv.ParseUint(msizestr, 10, 32)
if err != nil {
ctx.Warningf("gofer.FilesystemType.GetFilesystem: invalid message size: %s=%s", moptMsize, msizestr)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
fsopts.msize = uint32(msize)
}
@@ -409,7 +410,7 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
maxCachedDentries, err := strconv.ParseUint(str, 10, 64)
if err != nil {
ctx.Warningf("gofer.FilesystemType.GetFilesystem: invalid dentry cache limit: %s=%s", moptDentryCacheLimit, str)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
fsopts.maxCachedDentries = maxCachedDentries
}
@@ -433,14 +434,14 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
// Check for unparsed options.
if len(mopts) != 0 {
ctx.Warningf("gofer.FilesystemType.GetFilesystem: unknown options: %v", mopts)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
// Handle internal options.
iopts, ok := opts.InternalData.(InternalFilesystemOptions)
if opts.InternalData != nil && !ok {
ctx.Warningf("gofer.FilesystemType.GetFilesystem: GetFilesystemOptions.InternalData has type %T, wanted gofer.InternalFilesystemOptions", opts.InternalData)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
// If !ok, iopts being the zero value is correct.
@@ -503,7 +504,7 @@ func getFDFromMountOptionsMap(ctx context.Context, mopts map[string]string) (int
trans, ok := mopts[moptTransport]
if !ok || trans != transportModeFD {
ctx.Warningf("gofer.getFDFromMountOptionsMap: transport must be specified as '%s=%s'", moptTransport, transportModeFD)
- return -1, syserror.EINVAL
+ return -1, linuxerr.EINVAL
}
delete(mopts, moptTransport)
@@ -511,28 +512,28 @@ func getFDFromMountOptionsMap(ctx context.Context, mopts map[string]string) (int
rfdstr, ok := mopts[moptReadFD]
if !ok {
ctx.Warningf("gofer.getFDFromMountOptionsMap: read FD must be specified as '%s=<file descriptor>'", moptReadFD)
- return -1, syserror.EINVAL
+ return -1, linuxerr.EINVAL
}
delete(mopts, moptReadFD)
rfd, err := strconv.Atoi(rfdstr)
if err != nil {
ctx.Warningf("gofer.getFDFromMountOptionsMap: invalid read FD: %s=%s", moptReadFD, rfdstr)
- return -1, syserror.EINVAL
+ return -1, linuxerr.EINVAL
}
wfdstr, ok := mopts[moptWriteFD]
if !ok {
ctx.Warningf("gofer.getFDFromMountOptionsMap: write FD must be specified as '%s=<file descriptor>'", moptWriteFD)
- return -1, syserror.EINVAL
+ return -1, linuxerr.EINVAL
}
delete(mopts, moptWriteFD)
wfd, err := strconv.Atoi(wfdstr)
if err != nil {
ctx.Warningf("gofer.getFDFromMountOptionsMap: invalid write FD: %s=%s", moptWriteFD, wfdstr)
- return -1, syserror.EINVAL
+ return -1, linuxerr.EINVAL
}
if rfd != wfd {
ctx.Warningf("gofer.getFDFromMountOptionsMap: read FD (%d) and write FD (%d) must be equal", rfd, wfd)
- return -1, syserror.EINVAL
+ return -1, linuxerr.EINVAL
}
return rfd, nil
}
@@ -1110,7 +1111,7 @@ func (d *dentry) setStat(ctx context.Context, creds *auth.Credentials, opts *vfs
case linux.S_IFDIR:
return syserror.EISDIR
default:
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
}
@@ -1282,9 +1283,12 @@ func (d *dentry) checkPermissions(creds *auth.Credentials, ats vfs.AccessTypes)
}
func (d *dentry) checkXattrPermissions(creds *auth.Credentials, name string, ats vfs.AccessTypes) error {
- // We only support xattrs prefixed with "user." (see b/148380782). Currently,
- // there is no need to expose any other xattrs through a gofer.
- if !strings.HasPrefix(name, linux.XATTR_USER_PREFIX) {
+ // Deny access to the "security" and "system" namespaces since applications
+ // may expect these to affect kernel behavior in unimplemented ways
+ // (b/148380782). Allow all other extended attributes to be passed through
+ // to the remote filesystem. This is inconsistent with Linux's 9p client,
+ // but consistent with other filesystems (e.g. FUSE).
+ if strings.HasPrefix(name, linux.XATTR_SECURITY_PREFIX) || strings.HasPrefix(name, linux.XATTR_SYSTEM_PREFIX) {
return syserror.EOPNOTSUPP
}
mode := linux.FileMode(atomic.LoadUint32(&d.mode))
@@ -1684,7 +1688,7 @@ func (d *dentry) setDeleted() {
}
func (d *dentry) listXattr(ctx context.Context, creds *auth.Credentials, size uint64) ([]string, error) {
- if d.file.isNil() || !d.userXattrSupported() {
+ if d.file.isNil() {
return nil, nil
}
xattrMap, err := d.file.listXattr(ctx, size)
@@ -1693,10 +1697,7 @@ func (d *dentry) listXattr(ctx context.Context, creds *auth.Credentials, size ui
}
xattrs := make([]string, 0, len(xattrMap))
for x := range xattrMap {
- // We only support xattrs in the user.* namespace.
- if strings.HasPrefix(x, linux.XATTR_USER_PREFIX) {
- xattrs = append(xattrs, x)
- }
+ xattrs = append(xattrs, x)
}
return xattrs, nil
}
@@ -1731,13 +1732,6 @@ func (d *dentry) removeXattr(ctx context.Context, creds *auth.Credentials, name
return d.file.removeXattr(ctx, name)
}
-// Extended attributes in the user.* namespace are only supported for regular
-// files and directories.
-func (d *dentry) userXattrSupported() bool {
- filetype := linux.FileMode(atomic.LoadUint32(&d.mode)).FileType()
- return filetype == linux.ModeRegular || filetype == linux.ModeDirectory
-}
-
// Preconditions:
// * !d.isSynthetic().
// * d.isRegularFile() || d.isDir().
@@ -1770,7 +1764,7 @@ func (d *dentry) ensureSharedHandle(ctx context.Context, read, write, trunc bool
openReadable := !d.readFile.isNil() || read
openWritable := !d.writeFile.isNil() || write
h, err := openHandle(ctx, d.file, openReadable, openWritable, trunc)
- if err == syserror.EACCES && (openReadable != read || openWritable != write) {
+ if linuxerr.Equals(linuxerr.EACCES, err) && (openReadable != read || openWritable != write) {
// It may not be possible to use a single handle for both
// reading and writing, since permissions on the file may have
// changed to e.g. disallow reading after previously being
diff --git a/pkg/sentry/fsimpl/gofer/host_named_pipe.go b/pkg/sentry/fsimpl/gofer/host_named_pipe.go
index c7bf10007..398288ee3 100644
--- a/pkg/sentry/fsimpl/gofer/host_named_pipe.go
+++ b/pkg/sentry/fsimpl/gofer/host_named_pipe.go
@@ -21,6 +21,7 @@ import (
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/syserror"
)
@@ -78,7 +79,7 @@ func nonblockingPipeHasWriter(fd int32) (bool, error) {
defer tempPipeMu.Unlock()
// Copy 1 byte from fd into the temporary pipe.
n, err := unix.Tee(int(fd), tempPipeWriteFD, 1, unix.SPLICE_F_NONBLOCK)
- if err == syserror.EAGAIN {
+ if linuxerr.Equals(linuxerr.EAGAIN, err) {
// The pipe represented by fd is empty, but has a writer.
return true, nil
}
diff --git a/pkg/sentry/fsimpl/gofer/regular_file.go b/pkg/sentry/fsimpl/gofer/regular_file.go
index 0a954c138..89eab04cd 100644
--- a/pkg/sentry/fsimpl/gofer/regular_file.go
+++ b/pkg/sentry/fsimpl/gofer/regular_file.go
@@ -22,6 +22,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/metric"
@@ -60,7 +61,6 @@ func newRegularFileFD(mnt *vfs.Mount, d *dentry, flags uint32) (*regularFileFD,
return nil, err
}
if fd.vfsfd.IsWritable() && (atomic.LoadUint32(&d.mode)&0111 != 0) {
- fsmetric.GoferOpensWX.Increment()
metric.SuspiciousOperationsMetric.Increment("opened_write_execute_file")
}
if atomic.LoadInt32(&d.mmapFD) >= 0 {
@@ -125,7 +125,7 @@ func (fd *regularFileFD) PRead(ctx context.Context, dst usermem.IOSequence, offs
}()
if offset < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// Check that flags are supported.
@@ -195,7 +195,7 @@ func (fd *regularFileFD) PWrite(ctx context.Context, src usermem.IOSequence, off
// offset should be ignored by PWrite.
func (fd *regularFileFD) pwrite(ctx context.Context, src usermem.IOSequence, offset int64, opts vfs.WriteOptions) (written, finalOff int64, err error) {
if offset < 0 {
- return 0, offset, syserror.EINVAL
+ return 0, offset, linuxerr.EINVAL
}
// Check that flags are supported.
@@ -298,7 +298,7 @@ func (fd *regularFileFD) writeCache(ctx context.Context, d *dentry, offset int64
pgstart := hostarch.PageRoundDown(uint64(offset))
pgend, ok := hostarch.PageRoundUp(uint64(offset + src.NumBytes()))
if !ok {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
mr := memmap.MappableRange{pgstart, pgend}
var freed []memmap.FileRange
@@ -663,10 +663,10 @@ func regularFileSeekLocked(ctx context.Context, d *dentry, fdOffset, offset int6
offset = size
}
default:
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
if offset < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
return offset, nil
}
@@ -679,28 +679,28 @@ func (fd *regularFileFD) Sync(ctx context.Context) error {
// ConfigureMMap implements vfs.FileDescriptionImpl.ConfigureMMap.
func (fd *regularFileFD) ConfigureMMap(ctx context.Context, opts *memmap.MMapOpts) error {
d := fd.dentry()
- switch d.fs.opts.interop {
- case InteropModeExclusive:
- // Any mapping is fine.
- case InteropModeWritethrough:
- // Shared writable mappings require a host FD, since otherwise we can't
- // synchronously flush memory-mapped writes to the remote file.
- if opts.Private || !opts.MaxPerms.Write {
- break
- }
- fallthrough
- case InteropModeShared:
- // All mappings require a host FD to be coherent with other filesystem
- // users.
- if d.fs.opts.forcePageCache {
- // Whether or not we have a host FD, we're not allowed to use it.
- return syserror.ENODEV
- }
- if atomic.LoadInt32(&d.mmapFD) < 0 {
- return syserror.ENODEV
+ // Force sentry page caching at your own risk.
+ if !d.fs.opts.forcePageCache {
+ switch d.fs.opts.interop {
+ case InteropModeExclusive:
+ // Any mapping is fine.
+ case InteropModeWritethrough:
+ // Shared writable mappings require a host FD, since otherwise we
+ // can't synchronously flush memory-mapped writes to the remote
+ // file.
+ if opts.Private || !opts.MaxPerms.Write {
+ break
+ }
+ fallthrough
+ case InteropModeShared:
+ // All mappings require a host FD to be coherent with other
+ // filesystem users.
+ if atomic.LoadInt32(&d.mmapFD) < 0 {
+ return syserror.ENODEV
+ }
+ default:
+ panic(fmt.Sprintf("unknown InteropMode %v", d.fs.opts.interop))
}
- default:
- panic(fmt.Sprintf("unknown InteropMode %v", d.fs.opts.interop))
}
// After this point, d may be used as a memmap.Mappable.
d.pf.hostFileMapperInitOnce.Do(d.pf.hostFileMapper.Init)
@@ -709,12 +709,12 @@ func (fd *regularFileFD) ConfigureMMap(ctx context.Context, opts *memmap.MMapOpt
}
func (d *dentry) mayCachePages() bool {
- if d.fs.opts.interop == InteropModeShared {
- return false
- }
if d.fs.opts.forcePageCache {
return true
}
+ if d.fs.opts.interop == InteropModeShared {
+ return false
+ }
return atomic.LoadInt32(&d.mmapFD) >= 0
}
diff --git a/pkg/sentry/fsimpl/gofer/save_restore.go b/pkg/sentry/fsimpl/gofer/save_restore.go
index 83e841a51..e67422a2f 100644
--- a/pkg/sentry/fsimpl/gofer/save_restore.go
+++ b/pkg/sentry/fsimpl/gofer/save_restore.go
@@ -21,13 +21,13 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fdnotifier"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/p9"
"gvisor.dev/gvisor/pkg/refsvfs2"
"gvisor.dev/gvisor/pkg/safemem"
"gvisor.dev/gvisor/pkg/sentry/vfs"
- "gvisor.dev/gvisor/pkg/syserror"
)
type saveRestoreContextID int
@@ -92,7 +92,7 @@ func (fd *specialFileFD) savePipeData(ctx context.Context) error {
fd.buf = append(fd.buf, buf[:n]...)
}
if err != nil {
- if err == io.EOF || err == syserror.EAGAIN {
+ if err == io.EOF || linuxerr.Equals(linuxerr.EAGAIN, err) {
break
}
return err
diff --git a/pkg/sentry/fsimpl/gofer/special_file.go b/pkg/sentry/fsimpl/gofer/special_file.go
index dc019ebd5..2a922d120 100644
--- a/pkg/sentry/fsimpl/gofer/special_file.go
+++ b/pkg/sentry/fsimpl/gofer/special_file.go
@@ -20,6 +20,7 @@ import (
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fdnotifier"
"gvisor.dev/gvisor/pkg/metric"
"gvisor.dev/gvisor/pkg/p9"
@@ -101,7 +102,6 @@ func newSpecialFileFD(h handle, mnt *vfs.Mount, d *dentry, flags uint32) (*speci
d.fs.specialFileFDs[fd] = struct{}{}
d.fs.syncMu.Unlock()
if fd.vfsfd.IsWritable() && (atomic.LoadUint32(&d.mode)&0111 != 0) {
- fsmetric.GoferOpensWX.Increment()
metric.SuspiciousOperationsMetric.Increment("opened_write_execute_file")
}
if h.fd >= 0 {
@@ -184,7 +184,7 @@ func (fd *specialFileFD) PRead(ctx context.Context, dst usermem.IOSequence, offs
}()
if fd.seekable && offset < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// Check that flags are supported.
@@ -229,7 +229,7 @@ func (fd *specialFileFD) PRead(ctx context.Context, dst usermem.IOSequence, offs
// Just buffer the read instead.
buf := make([]byte, dst.NumBytes())
n, err := fd.handle.readToBlocksAt(ctx, safemem.BlockSeqOf(safemem.BlockFromSafeSlice(buf)), uint64(offset))
- if err == syserror.EAGAIN {
+ if linuxerr.Equals(linuxerr.EAGAIN, err) {
err = syserror.ErrWouldBlock
}
if n == 0 {
@@ -264,7 +264,7 @@ func (fd *specialFileFD) PWrite(ctx context.Context, src usermem.IOSequence, off
// offset should be ignored by PWrite.
func (fd *specialFileFD) pwrite(ctx context.Context, src usermem.IOSequence, offset int64, opts vfs.WriteOptions) (written, finalOff int64, err error) {
if fd.seekable && offset < 0 {
- return 0, offset, syserror.EINVAL
+ return 0, offset, linuxerr.EINVAL
}
// Check that flags are supported.
@@ -317,7 +317,7 @@ func (fd *specialFileFD) pwrite(ctx context.Context, src usermem.IOSequence, off
return 0, offset, copyErr
}
n, err := fd.handle.writeFromBlocksAt(ctx, safemem.BlockSeqOf(safemem.BlockFromSafeSlice(buf[:copied])), uint64(offset))
- if err == syserror.EAGAIN {
+ if linuxerr.Equals(linuxerr.EAGAIN, err) {
err = syserror.ErrWouldBlock
}
// Update offset if the offset is valid.
diff --git a/pkg/sentry/fsimpl/host/BUILD b/pkg/sentry/fsimpl/host/BUILD
index b94dfeb7f..476545d00 100644
--- a/pkg/sentry/fsimpl/host/BUILD
+++ b/pkg/sentry/fsimpl/host/BUILD
@@ -45,10 +45,10 @@ go_library(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/fdnotifier",
"//pkg/fspath",
"//pkg/hostarch",
- "//pkg/iovec",
"//pkg/log",
"//pkg/marshal/primitive",
"//pkg/refs",
diff --git a/pkg/sentry/fsimpl/host/host.go b/pkg/sentry/fsimpl/host/host.go
index a81f550b1..4d2b282a0 100644
--- a/pkg/sentry/fsimpl/host/host.go
+++ b/pkg/sentry/fsimpl/host/host.go
@@ -24,6 +24,7 @@ import (
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fdnotifier"
"gvisor.dev/gvisor/pkg/fspath"
"gvisor.dev/gvisor/pkg/hostarch"
@@ -109,7 +110,7 @@ type inode struct {
func newInode(ctx context.Context, fs *filesystem, hostFD int, savable bool, fileType linux.FileMode, isTTY bool) (*inode, error) {
// Determine if hostFD is seekable.
_, err := unix.Seek(hostFD, 0, linux.SEEK_CUR)
- seekable := err != syserror.ESPIPE
+ seekable := !linuxerr.Equals(linuxerr.ESPIPE, err)
// We expect regular files to be seekable, as this is required for them to
// be memory-mappable.
if !seekable && fileType == unix.S_IFREG {
@@ -289,10 +290,10 @@ func (i *inode) Mode() linux.FileMode {
// Stat implements kernfs.Inode.Stat.
func (i *inode) Stat(ctx context.Context, vfsfs *vfs.Filesystem, opts vfs.StatOptions) (linux.Statx, error) {
if opts.Mask&linux.STATX__RESERVED != 0 {
- return linux.Statx{}, syserror.EINVAL
+ return linux.Statx{}, linuxerr.EINVAL
}
if opts.Sync&linux.AT_STATX_SYNC_TYPE == linux.AT_STATX_SYNC_TYPE {
- return linux.Statx{}, syserror.EINVAL
+ return linux.Statx{}, linuxerr.EINVAL
}
fs := vfsfs.Impl().(*filesystem)
@@ -301,7 +302,7 @@ func (i *inode) Stat(ctx context.Context, vfsfs *vfs.Filesystem, opts vfs.StatOp
mask := opts.Mask & linux.STATX_ALL
var s unix.Statx_t
err := unix.Statx(i.hostFD, "", int(unix.AT_EMPTY_PATH|opts.Sync), int(mask), &s)
- if err == syserror.ENOSYS {
+ if linuxerr.Equals(linuxerr.ENOSYS, err) {
// Fallback to fstat(2), if statx(2) is not supported on the host.
//
// TODO(b/151263641): Remove fallback.
@@ -425,7 +426,7 @@ func (i *inode) SetStat(ctx context.Context, fs *vfs.Filesystem, creds *auth.Cre
}
if m&linux.STATX_SIZE != 0 {
if hostStat.Mode&linux.S_IFMT != linux.S_IFREG {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if err := unix.Ftruncate(i.hostFD, int64(s.Size)); err != nil {
return err
@@ -730,7 +731,7 @@ func (f *fileDescription) Seek(_ context.Context, offset int64, whence int32) (i
switch whence {
case linux.SEEK_SET:
if offset < 0 {
- return f.offset, syserror.EINVAL
+ return f.offset, linuxerr.EINVAL
}
f.offset = offset
@@ -740,7 +741,7 @@ func (f *fileDescription) Seek(_ context.Context, offset int64, whence int32) (i
return f.offset, syserror.EOVERFLOW
}
if f.offset+offset < 0 {
- return f.offset, syserror.EINVAL
+ return f.offset, linuxerr.EINVAL
}
f.offset += offset
@@ -756,7 +757,7 @@ func (f *fileDescription) Seek(_ context.Context, offset int64, whence int32) (i
return f.offset, syserror.EOVERFLOW
}
if size+offset < 0 {
- return f.offset, syserror.EINVAL
+ return f.offset, linuxerr.EINVAL
}
f.offset = size + offset
@@ -773,7 +774,7 @@ func (f *fileDescription) Seek(_ context.Context, offset int64, whence int32) (i
default:
// Invalid whence.
- return f.offset, syserror.EINVAL
+ return f.offset, linuxerr.EINVAL
}
return f.offset, nil
diff --git a/pkg/sentry/fsimpl/host/socket.go b/pkg/sentry/fsimpl/host/socket.go
index ca85f5601..8cce36212 100644
--- a/pkg/sentry/fsimpl/host/socket.go
+++ b/pkg/sentry/fsimpl/host/socket.go
@@ -21,6 +21,7 @@ import (
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fdnotifier"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/sentry/socket/control"
@@ -160,7 +161,7 @@ func (c *ConnectedEndpoint) Send(ctx context.Context, data [][]byte, controlMess
// block (and only for stream sockets).
err = syserror.EAGAIN
}
- if n > 0 && err != syserror.EAGAIN {
+ if n > 0 && !linuxerr.Equals(linuxerr.EAGAIN, err) {
// The caller may need to block to send more data, but
// otherwise there isn't anything that can be done about an
// error with a partial write.
diff --git a/pkg/sentry/fsimpl/host/socket_iovec.go b/pkg/sentry/fsimpl/host/socket_iovec.go
index b123a63ee..e090bb725 100644
--- a/pkg/sentry/fsimpl/host/socket_iovec.go
+++ b/pkg/sentry/fsimpl/host/socket_iovec.go
@@ -16,7 +16,7 @@ package host
import (
"golang.org/x/sys/unix"
- "gvisor.dev/gvisor/pkg/iovec"
+ "gvisor.dev/gvisor/pkg/sentry/hostfd"
"gvisor.dev/gvisor/pkg/syserror"
)
@@ -70,7 +70,7 @@ func buildIovec(bufs [][]byte, maxlen int64, truncate bool) (length int64, iovec
}
}
- if iovsRequired > iovec.MaxIovs {
+ if iovsRequired > hostfd.MaxSendRecvMsgIov {
// The kernel will reject our call if we pass this many iovs.
// Use a single intermediate buffer instead.
b := make([]byte, stopLen)
diff --git a/pkg/sentry/fsimpl/host/tty.go b/pkg/sentry/fsimpl/host/tty.go
index 0f9e20a84..c7bf563f0 100644
--- a/pkg/sentry/fsimpl/host/tty.go
+++ b/pkg/sentry/fsimpl/host/tty.go
@@ -17,6 +17,7 @@ package host
import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/marshal/primitive"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
@@ -211,7 +212,7 @@ func (t *TTYFileDescription) Ioctl(ctx context.Context, io usermem.IO, args arch
if err := t.checkChange(ctx, linux.SIGTTOU); err != nil {
// drivers/tty/tty_io.c:tiocspgrp() converts -EIO from tty_check_change()
// to -ENOTTY.
- if err == syserror.EIO {
+ if linuxerr.Equals(linuxerr.EIO, err) {
return 0, syserror.ENOTTY
}
return 0, err
@@ -230,7 +231,7 @@ func (t *TTYFileDescription) Ioctl(ctx context.Context, io usermem.IO, args arch
// pgID must be non-negative.
if pgID < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// Process group with pgID must exist in this PID namespace.
diff --git a/pkg/sentry/fsimpl/host/util.go b/pkg/sentry/fsimpl/host/util.go
index 63b465859..95d7ebe2e 100644
--- a/pkg/sentry/fsimpl/host/util.go
+++ b/pkg/sentry/fsimpl/host/util.go
@@ -17,7 +17,7 @@ package host
import (
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/linux"
- "gvisor.dev/gvisor/pkg/syserror"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
)
func toTimespec(ts linux.StatxTimestamp, omit bool) unix.Timespec {
@@ -44,5 +44,5 @@ func timespecToStatxTimestamp(ts unix.Timespec) linux.StatxTimestamp {
// isBlockError checks if an error is EAGAIN or EWOULDBLOCK.
// If so, they can be transformed into syserror.ErrWouldBlock.
func isBlockError(err error) bool {
- return err == syserror.EAGAIN || err == syserror.EWOULDBLOCK
+ return linuxerr.Equals(linuxerr.EAGAIN, err) || linuxerr.Equals(linuxerr.EWOULDBLOCK, err)
}
diff --git a/pkg/sentry/fsimpl/kernfs/BUILD b/pkg/sentry/fsimpl/kernfs/BUILD
index b7d13cced..d53937db6 100644
--- a/pkg/sentry/fsimpl/kernfs/BUILD
+++ b/pkg/sentry/fsimpl/kernfs/BUILD
@@ -104,6 +104,7 @@ go_library(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/fspath",
"//pkg/hostarch",
"//pkg/log",
@@ -135,6 +136,7 @@ go_test(
":kernfs",
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/log",
"//pkg/refs",
"//pkg/refsvfs2",
diff --git a/pkg/sentry/fsimpl/kernfs/fd_impl_util.go b/pkg/sentry/fsimpl/kernfs/fd_impl_util.go
index e55111af0..8b008dc10 100644
--- a/pkg/sentry/fsimpl/kernfs/fd_impl_util.go
+++ b/pkg/sentry/fsimpl/kernfs/fd_impl_util.go
@@ -19,6 +19,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/memmap"
"gvisor.dev/gvisor/pkg/sentry/vfs"
@@ -248,10 +249,10 @@ func (fd *GenericDirectoryFD) Seek(ctx context.Context, offset int64, whence int
panic(fmt.Sprintf("Invalid GenericDirectoryFD.seekEnd = %v", fd.seekEnd))
}
default:
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
if offset < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
fd.off = offset
return offset, nil
diff --git a/pkg/sentry/fsimpl/kernfs/filesystem.go b/pkg/sentry/fsimpl/kernfs/filesystem.go
index f50b0fb08..1a314f59e 100644
--- a/pkg/sentry/fsimpl/kernfs/filesystem.go
+++ b/pkg/sentry/fsimpl/kernfs/filesystem.go
@@ -21,6 +21,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fspath"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/socket/unix/transport"
@@ -411,7 +412,7 @@ func (fs *Filesystem) MkdirAt(ctx context.Context, rp *vfs.ResolvingPath, opts v
defer rp.Mount().EndWrite()
childI, err := parent.inode.NewDir(ctx, pc, opts)
if err != nil {
- if !opts.ForSyntheticMountpoint || err == syserror.EEXIST {
+ if !opts.ForSyntheticMountpoint || linuxerr.Equals(linuxerr.EEXIST, err) {
return err
}
childI = newSyntheticDirectory(ctx, rp.Credentials(), opts.Mode)
@@ -546,7 +547,7 @@ afterTrailingSymlink:
}
// Determine whether or not we need to create a file.
child, err := fs.stepExistingLocked(ctx, rp, parent, false /* mayFollowSymlinks */)
- if err == syserror.ENOENT {
+ if linuxerr.Equals(linuxerr.ENOENT, err) {
// Already checked for searchability above; now check for writability.
if err := parent.inode.CheckPermissions(ctx, rp.Credentials(), vfs.MayWrite); err != nil {
return nil, err
@@ -622,7 +623,7 @@ func (fs *Filesystem) ReadlinkAt(ctx context.Context, rp *vfs.ResolvingPath) (st
}
if !d.isSymlink() {
fs.mu.RUnlock()
- return "", syserror.EINVAL
+ return "", linuxerr.EINVAL
}
// Inode.Readlink() cannot be called holding fs locks.
@@ -635,12 +636,6 @@ func (fs *Filesystem) ReadlinkAt(ctx context.Context, rp *vfs.ResolvingPath) (st
// RenameAt implements vfs.FilesystemImpl.RenameAt.
func (fs *Filesystem) RenameAt(ctx context.Context, rp *vfs.ResolvingPath, oldParentVD vfs.VirtualDentry, oldName string, opts vfs.RenameOptions) error {
- // Only RENAME_NOREPLACE is supported.
- if opts.Flags&^linux.RENAME_NOREPLACE != 0 {
- return syserror.EINVAL
- }
- noReplace := opts.Flags&linux.RENAME_NOREPLACE != 0
-
fs.mu.Lock()
defer fs.processDeferredDecRefs(ctx)
defer fs.mu.Unlock()
@@ -651,6 +646,13 @@ func (fs *Filesystem) RenameAt(ctx context.Context, rp *vfs.ResolvingPath, oldPa
if err != nil {
return err
}
+
+ // Only RENAME_NOREPLACE is supported.
+ if opts.Flags&^linux.RENAME_NOREPLACE != 0 {
+ return linuxerr.EINVAL
+ }
+ noReplace := opts.Flags&linux.RENAME_NOREPLACE != 0
+
mnt := rp.Mount()
if mnt != oldParentVD.Mount() {
return syserror.EXDEV
@@ -683,10 +685,12 @@ func (fs *Filesystem) RenameAt(ctx context.Context, rp *vfs.ResolvingPath, oldPa
}
return syserror.EBUSY
}
- switch err := checkCreateLocked(ctx, rp.Credentials(), newName, dstDir); err {
- case nil:
+
+ err = checkCreateLocked(ctx, rp.Credentials(), newName, dstDir)
+ switch {
+ case err == nil:
// Ok, continue with rename as replacement.
- case syserror.EEXIST:
+ case linuxerr.Equals(linuxerr.EEXIST, err):
if noReplace {
// Won't overwrite existing node since RENAME_NOREPLACE was requested.
return syserror.EEXIST
diff --git a/pkg/sentry/fsimpl/kernfs/inode_impl_util.go b/pkg/sentry/fsimpl/kernfs/inode_impl_util.go
index 3d0866ecf..62872946e 100644
--- a/pkg/sentry/fsimpl/kernfs/inode_impl_util.go
+++ b/pkg/sentry/fsimpl/kernfs/inode_impl_util.go
@@ -20,6 +20,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
ktime "gvisor.dev/gvisor/pkg/sentry/kernel/time"
@@ -158,12 +159,12 @@ type InodeNotSymlink struct{}
// Readlink implements Inode.Readlink.
func (InodeNotSymlink) Readlink(context.Context, *vfs.Mount) (string, error) {
- return "", syserror.EINVAL
+ return "", linuxerr.EINVAL
}
// Getlink implements Inode.Getlink.
func (InodeNotSymlink) Getlink(context.Context, *vfs.Mount) (vfs.VirtualDentry, string, error) {
- return vfs.VirtualDentry{}, "", syserror.EINVAL
+ return vfs.VirtualDentry{}, "", linuxerr.EINVAL
}
// InodeAttrs partially implements the Inode interface, specifically the
diff --git a/pkg/sentry/fsimpl/kernfs/kernfs_test.go b/pkg/sentry/fsimpl/kernfs/kernfs_test.go
index 1cd3137e6..de046ce1f 100644
--- a/pkg/sentry/fsimpl/kernfs/kernfs_test.go
+++ b/pkg/sentry/fsimpl/kernfs/kernfs_test.go
@@ -22,6 +22,7 @@ import (
"github.com/google/go-cmp/cmp"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/contexttest"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/kernfs"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/testutil"
@@ -318,10 +319,10 @@ func TestDirFDReadWrite(t *testing.T) {
defer fd.DecRef(sys.Ctx)
// Read/Write should fail for directory FDs.
- if _, err := fd.Read(sys.Ctx, usermem.BytesIOSequence([]byte{}), vfs.ReadOptions{}); err != syserror.EISDIR {
+ if _, err := fd.Read(sys.Ctx, usermem.BytesIOSequence([]byte{}), vfs.ReadOptions{}); !linuxerr.Equals(linuxerr.EISDIR, err) {
t.Fatalf("Read for directory FD failed with unexpected error: %v", err)
}
- if _, err := fd.Write(sys.Ctx, usermem.BytesIOSequence([]byte{}), vfs.WriteOptions{}); err != syserror.EBADF {
+ if _, err := fd.Write(sys.Ctx, usermem.BytesIOSequence([]byte{}), vfs.WriteOptions{}); !linuxerr.Equals(linuxerr.EBADF, err) {
t.Fatalf("Write for directory FD failed with unexpected error: %v", err)
}
}
diff --git a/pkg/sentry/fsimpl/overlay/BUILD b/pkg/sentry/fsimpl/overlay/BUILD
index 5504476c8..ed730e215 100644
--- a/pkg/sentry/fsimpl/overlay/BUILD
+++ b/pkg/sentry/fsimpl/overlay/BUILD
@@ -29,6 +29,7 @@ go_library(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/fspath",
"//pkg/hostarch",
"//pkg/log",
diff --git a/pkg/sentry/fsimpl/overlay/copy_up.go b/pkg/sentry/fsimpl/overlay/copy_up.go
index 45aa5a494..8fd51e9d0 100644
--- a/pkg/sentry/fsimpl/overlay/copy_up.go
+++ b/pkg/sentry/fsimpl/overlay/copy_up.go
@@ -20,6 +20,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fspath"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
@@ -349,7 +350,7 @@ func (d *dentry) copyXattrsLocked(ctx context.Context) error {
lowerXattrs, err := vfsObj.ListXattrAt(ctx, d.fs.creds, lowerPop, 0)
if err != nil {
- if err == syserror.EOPNOTSUPP {
+ if linuxerr.Equals(linuxerr.EOPNOTSUPP, err) {
// There are no guarantees as to the contents of lowerXattrs.
return nil
}
diff --git a/pkg/sentry/fsimpl/overlay/directory.go b/pkg/sentry/fsimpl/overlay/directory.go
index df4492346..417a7c630 100644
--- a/pkg/sentry/fsimpl/overlay/directory.go
+++ b/pkg/sentry/fsimpl/overlay/directory.go
@@ -19,6 +19,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fspath"
"gvisor.dev/gvisor/pkg/sentry/vfs"
"gvisor.dev/gvisor/pkg/sync"
@@ -256,7 +257,7 @@ func (fd *directoryFD) Seek(ctx context.Context, offset int64, whence int32) (in
switch whence {
case linux.SEEK_SET:
if offset < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
if offset == 0 {
// Ensure that the next call to fd.IterDirents() calls
@@ -268,13 +269,13 @@ func (fd *directoryFD) Seek(ctx context.Context, offset int64, whence int32) (in
case linux.SEEK_CUR:
offset += fd.off
if offset < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// Don't clear fd.dirents in this case, even if offset == 0.
fd.off = offset
return fd.off, nil
default:
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
}
diff --git a/pkg/sentry/fsimpl/overlay/filesystem.go b/pkg/sentry/fsimpl/overlay/filesystem.go
index 46c500427..e792677f5 100644
--- a/pkg/sentry/fsimpl/overlay/filesystem.go
+++ b/pkg/sentry/fsimpl/overlay/filesystem.go
@@ -21,6 +21,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fspath"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
@@ -218,7 +219,7 @@ func (fs *filesystem) lookupLocked(ctx context.Context, parent *dentry, name str
Start: parentVD,
Path: childPath,
}, &vfs.GetDentryOptions{})
- if err == syserror.ENOENT || err == syserror.ENAMETOOLONG {
+ if linuxerr.Equals(linuxerr.ENOENT, err) || linuxerr.Equals(linuxerr.ENAMETOOLONG, err) {
// The file doesn't exist on this layer. Proceed to the next one.
return true
}
@@ -352,7 +353,7 @@ func (fs *filesystem) lookupLayerLocked(ctx context.Context, parent *dentry, nam
}, &vfs.StatOptions{
Mask: linux.STATX_TYPE,
})
- if err == syserror.ENOENT || err == syserror.ENAMETOOLONG {
+ if linuxerr.Equals(linuxerr.ENOENT, err) || linuxerr.Equals(linuxerr.ENAMETOOLONG, err) {
// The file doesn't exist on this layer. Proceed to the next
// one.
return true
@@ -811,7 +812,7 @@ afterTrailingSymlink:
// Determine whether or not we need to create a file.
parent.dirMu.Lock()
child, topLookupLayer, err := fs.stepLocked(ctx, rp, parent, false /* mayFollowSymlinks */, &ds)
- if err == syserror.ENOENT && mayCreate {
+ if linuxerr.Equals(linuxerr.ENOENT, err) && mayCreate {
fd, err := fs.createAndOpenLocked(ctx, rp, parent, &opts, &ds, topLookupLayer == lookupLayerUpperWhiteout)
parent.dirMu.Unlock()
return fd, err
@@ -871,7 +872,7 @@ func (d *dentry) openCopiedUp(ctx context.Context, rp *vfs.ResolvingPath, opts *
return nil, syserror.EISDIR
}
if opts.Flags&linux.O_DIRECT != 0 {
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
fd := &directoryFD{}
fd.LockFD.Init(&d.locks)
@@ -1017,10 +1018,7 @@ func (fs *filesystem) ReadlinkAt(ctx context.Context, rp *vfs.ResolvingPath) (st
// RenameAt implements vfs.FilesystemImpl.RenameAt.
func (fs *filesystem) RenameAt(ctx context.Context, rp *vfs.ResolvingPath, oldParentVD vfs.VirtualDentry, oldName string, opts vfs.RenameOptions) error {
- if opts.Flags != 0 {
- return syserror.EINVAL
- }
-
+ // Resolve newParent first to verify that it's on this Mount.
var ds *[]*dentry
fs.renameMu.Lock()
defer fs.renameMuUnlockAndCheckDrop(ctx, &ds)
@@ -1028,8 +1026,16 @@ func (fs *filesystem) RenameAt(ctx context.Context, rp *vfs.ResolvingPath, oldPa
if err != nil {
return err
}
+
+ if opts.Flags&^linux.RENAME_NOREPLACE != 0 {
+ return linuxerr.EINVAL
+ }
+
newName := rp.Component()
if newName == "." || newName == ".." {
+ if opts.Flags&linux.RENAME_NOREPLACE != 0 {
+ return syserror.EEXIST
+ }
return syserror.EBUSY
}
mnt := rp.Mount()
@@ -1059,7 +1065,7 @@ func (fs *filesystem) RenameAt(ctx context.Context, rp *vfs.ResolvingPath, oldPa
}
if renamed.isDir() {
if renamed == newParent || genericIsAncestorDentry(renamed, newParent) {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if oldParent != newParent {
if err := renamed.checkPermissions(creds, vfs.MayWrite); err != nil {
@@ -1089,10 +1095,13 @@ func (fs *filesystem) RenameAt(ctx context.Context, rp *vfs.ResolvingPath, oldPa
whiteouts map[string]bool
)
replaced, replacedLayer, err = fs.getChildLocked(ctx, newParent, newName, &ds)
- if err != nil && err != syserror.ENOENT {
+ if err != nil && !linuxerr.Equals(linuxerr.ENOENT, err) {
return err
}
if replaced != nil {
+ if opts.Flags&linux.RENAME_NOREPLACE != 0 {
+ return syserror.EEXIST
+ }
replacedVFSD = &replaced.vfsd
if replaced.isDir() {
if !renamed.isDir() {
@@ -1169,7 +1178,7 @@ func (fs *filesystem) RenameAt(ctx context.Context, rp *vfs.ResolvingPath, oldPa
Root: replaced.upperVD,
Start: replaced.upperVD,
Path: fspath.Parse(whiteoutName),
- }); err != nil && err != syserror.EEXIST {
+ }); err != nil && !linuxerr.Equals(linuxerr.EEXIST, err) {
panic(fmt.Sprintf("unrecoverable overlayfs inconsistency: failed to recreate deleted whiteout after RenameAt failure: %v", err))
}
}
@@ -1277,7 +1286,7 @@ func (fs *filesystem) RmdirAt(ctx context.Context, rp *vfs.ResolvingPath) error
defer rp.Mount().EndWrite()
name := rp.Component()
if name == "." {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if name == ".." {
return syserror.ENOTEMPTY
@@ -1336,7 +1345,7 @@ func (fs *filesystem) RmdirAt(ctx context.Context, rp *vfs.ResolvingPath) error
Root: child.upperVD,
Start: child.upperVD,
Path: fspath.Parse(whiteoutName),
- }); err != nil && err != syserror.EEXIST {
+ }); err != nil && !linuxerr.Equals(linuxerr.EEXIST, err) {
panic(fmt.Sprintf("unrecoverable overlayfs inconsistency: failed to recreate deleted whiteout after RmdirAt failure: %v", err))
}
}
diff --git a/pkg/sentry/fsimpl/overlay/overlay.go b/pkg/sentry/fsimpl/overlay/overlay.go
index 454c20d4f..4c7243764 100644
--- a/pkg/sentry/fsimpl/overlay/overlay.go
+++ b/pkg/sentry/fsimpl/overlay/overlay.go
@@ -40,6 +40,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fspath"
"gvisor.dev/gvisor/pkg/refsvfs2"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
@@ -135,7 +136,7 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
fsopts, ok := fsoptsRaw.(FilesystemOptions)
if fsoptsRaw != nil && !ok {
ctx.Infof("overlay.FilesystemType.GetFilesystem: GetFilesystemOptions.InternalData has type %T, wanted overlay.FilesystemOptions or nil", fsoptsRaw)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
vfsroot := vfs.RootFromContext(ctx)
if vfsroot.Ok() {
@@ -145,7 +146,7 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
if upperPathname, ok := mopts["upperdir"]; ok {
if fsopts.UpperRoot.Ok() {
ctx.Infof("overlay.FilesystemType.GetFilesystem: both upperdir and FilesystemOptions.UpperRoot are specified")
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
delete(mopts, "upperdir")
// Linux overlayfs also requires a workdir when upperdir is
@@ -154,7 +155,7 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
upperPath := fspath.Parse(upperPathname)
if !upperPath.Absolute {
ctx.Infof("overlay.FilesystemType.GetFilesystem: upperdir %q must be absolute", upperPathname)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
upperRoot, err := vfsObj.GetDentryAt(ctx, creds, &vfs.PathOperation{
Root: vfsroot,
@@ -181,7 +182,7 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
if lowerPathnamesStr, ok := mopts["lowerdir"]; ok {
if len(fsopts.LowerRoots) != 0 {
ctx.Infof("overlay.FilesystemType.GetFilesystem: both lowerdir and FilesystemOptions.LowerRoots are specified")
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
delete(mopts, "lowerdir")
lowerPathnames := strings.Split(lowerPathnamesStr, ":")
@@ -189,7 +190,7 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
lowerPath := fspath.Parse(lowerPathname)
if !lowerPath.Absolute {
ctx.Infof("overlay.FilesystemType.GetFilesystem: lowerdir %q must be absolute", lowerPathname)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
lowerRoot, err := vfsObj.GetDentryAt(ctx, creds, &vfs.PathOperation{
Root: vfsroot,
@@ -216,21 +217,21 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
if len(mopts) != 0 {
ctx.Infof("overlay.FilesystemType.GetFilesystem: unused options: %v", mopts)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
if len(fsopts.LowerRoots) == 0 {
ctx.Infof("overlay.FilesystemType.GetFilesystem: at least one lower layer is required")
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
if len(fsopts.LowerRoots) < 2 && !fsopts.UpperRoot.Ok() {
ctx.Infof("overlay.FilesystemType.GetFilesystem: at least two lower layers are required when no upper layer is present")
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
const maxLowerLayers = 500 // Linux: fs/overlay/super.c:OVL_MAX_STACK
if len(fsopts.LowerRoots) > maxLowerLayers {
ctx.Infof("overlay.FilesystemType.GetFilesystem: %d lower layers specified, maximum %d", len(fsopts.LowerRoots), maxLowerLayers)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
// Take extra references held by the filesystem.
@@ -283,7 +284,7 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
ctx.Infof("overlay.FilesystemType.GetFilesystem: filesystem root is a whiteout")
root.destroyLocked(ctx)
fs.vfsfs.DecRef(ctx)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
root.mode = uint32(rootStat.Mode)
root.uid = rootStat.UID
diff --git a/pkg/sentry/fsimpl/overlay/regular_file.go b/pkg/sentry/fsimpl/overlay/regular_file.go
index 43bfd69a3..82491a0f8 100644
--- a/pkg/sentry/fsimpl/overlay/regular_file.go
+++ b/pkg/sentry/fsimpl/overlay/regular_file.go
@@ -207,9 +207,10 @@ func (fd *regularFileFD) SetStat(ctx context.Context, opts vfs.SetStatOptions) e
return err
}
- // Changing owners may clear one or both of the setuid and setgid bits,
- // so we may have to update opts before setting d.mode.
- if opts.Stat.Mask&(linux.STATX_UID|linux.STATX_GID) != 0 {
+ // Changing owners or truncating may clear one or both of the setuid and
+ // setgid bits, so we may have to update opts before setting d.mode.
+ inotifyMask := opts.Stat.Mask
+ if opts.Stat.Mask&(linux.STATX_UID|linux.STATX_GID|linux.STATX_SIZE) != 0 {
stat, err := wrappedFD.Stat(ctx, vfs.StatOptions{
Mask: linux.STATX_MODE,
})
@@ -218,10 +219,14 @@ func (fd *regularFileFD) SetStat(ctx context.Context, opts vfs.SetStatOptions) e
}
opts.Stat.Mode = stat.Mode
opts.Stat.Mask |= linux.STATX_MODE
+ // Don't generate inotify IN_ATTRIB for size-only changes (truncations).
+ if opts.Stat.Mask&(linux.STATX_UID|linux.STATX_GID) != 0 {
+ inotifyMask |= linux.STATX_MODE
+ }
}
d.updateAfterSetStatLocked(&opts)
- if ev := vfs.InotifyEventFromStatMask(opts.Stat.Mask); ev != 0 {
+ if ev := vfs.InotifyEventFromStatMask(inotifyMask); ev != 0 {
d.InotifyWithParent(ctx, ev, 0, vfs.InodeEvent)
}
return nil
diff --git a/pkg/sentry/fsimpl/proc/BUILD b/pkg/sentry/fsimpl/proc/BUILD
index 2b628bd55..1d3d2d95f 100644
--- a/pkg/sentry/fsimpl/proc/BUILD
+++ b/pkg/sentry/fsimpl/proc/BUILD
@@ -81,6 +81,7 @@ go_library(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/hostarch",
"//pkg/log",
"//pkg/refs",
@@ -119,6 +120,7 @@ go_test(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/fspath",
"//pkg/sentry/contexttest",
"//pkg/sentry/fsimpl/testutil",
@@ -127,7 +129,6 @@ go_test(
"//pkg/sentry/kernel",
"//pkg/sentry/kernel/auth",
"//pkg/sentry/vfs",
- "//pkg/syserror",
"//pkg/usermem",
],
)
diff --git a/pkg/sentry/fsimpl/proc/filesystem.go b/pkg/sentry/fsimpl/proc/filesystem.go
index ce8f55b1f..f2697c12d 100644
--- a/pkg/sentry/fsimpl/proc/filesystem.go
+++ b/pkg/sentry/fsimpl/proc/filesystem.go
@@ -21,11 +21,11 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/kernfs"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/vfs"
- "gvisor.dev/gvisor/pkg/syserror"
)
const (
@@ -76,7 +76,7 @@ func (ft FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.VirtualF
maxCachedDentries, err = strconv.ParseUint(str, 10, 64)
if err != nil {
ctx.Warningf("proc.FilesystemType.GetFilesystem: invalid dentry cache limit: dentry_cache_limit=%s", str)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
}
diff --git a/pkg/sentry/fsimpl/proc/task_files.go b/pkg/sentry/fsimpl/proc/task_files.go
index b294dfd6a..9187f5b11 100644
--- a/pkg/sentry/fsimpl/proc/task_files.go
+++ b/pkg/sentry/fsimpl/proc/task_files.go
@@ -21,6 +21,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/safemem"
"gvisor.dev/gvisor/pkg/sentry/fsbridge"
@@ -325,7 +326,7 @@ func (d *idMapData) Write(ctx context.Context, src usermem.IOSequence, offset in
// the file ..." - user_namespaces(7)
srclen := src.NumBytes()
if srclen >= hostarch.PageSize || offset != 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
b := make([]byte, srclen)
if _, err := src.CopyIn(ctx, b); err != nil {
@@ -345,7 +346,7 @@ func (d *idMapData) Write(ctx context.Context, src usermem.IOSequence, offset in
}
lines := bytes.SplitN(b, []byte("\n"), maxIDMapLines+1)
if len(lines) > maxIDMapLines {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
entries := make([]auth.IDMapEntry, len(lines))
@@ -353,7 +354,7 @@ func (d *idMapData) Write(ctx context.Context, src usermem.IOSequence, offset in
var e auth.IDMapEntry
_, err := fmt.Sscan(string(l), &e.FirstID, &e.FirstParentID, &e.Length)
if err != nil {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
entries[i] = e
}
@@ -461,10 +462,10 @@ func (fd *memFD) Seek(ctx context.Context, offset int64, whence int32) (int64, e
case linux.SEEK_CUR:
offset += fd.offset
default:
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
if offset < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
fd.offset = offset
return offset, nil
diff --git a/pkg/sentry/fsimpl/proc/task_net.go b/pkg/sentry/fsimpl/proc/task_net.go
index 177cb828f..ab47ea5a7 100644
--- a/pkg/sentry/fsimpl/proc/task_net.go
+++ b/pkg/sentry/fsimpl/proc/task_net.go
@@ -23,6 +23,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/kernfs"
@@ -33,7 +34,6 @@ import (
"gvisor.dev/gvisor/pkg/sentry/socket/unix"
"gvisor.dev/gvisor/pkg/sentry/socket/unix/transport"
"gvisor.dev/gvisor/pkg/sentry/vfs"
- "gvisor.dev/gvisor/pkg/syserror"
"gvisor.dev/gvisor/pkg/tcpip/header"
)
@@ -679,7 +679,7 @@ func (d *netSnmpData) Generate(ctx context.Context, buf *bytes.Buffer) error {
continue
}
if err := d.stack.Statistics(stat, line.prefix); err != nil {
- if err == syserror.EOPNOTSUPP {
+ if linuxerr.Equals(linuxerr.EOPNOTSUPP, err) {
log.Infof("Failed to retrieve %s of /proc/net/snmp: %v", line.prefix, err)
} else {
log.Warningf("Failed to retrieve %s of /proc/net/snmp: %v", line.prefix, err)
diff --git a/pkg/sentry/fsimpl/proc/tasks_files.go b/pkg/sentry/fsimpl/proc/tasks_files.go
index 045ed7a2d..2def1ca48 100644
--- a/pkg/sentry/fsimpl/proc/tasks_files.go
+++ b/pkg/sentry/fsimpl/proc/tasks_files.go
@@ -21,6 +21,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/kernfs"
"gvisor.dev/gvisor/pkg/sentry/kernel"
@@ -53,7 +54,7 @@ func (s *selfSymlink) Readlink(ctx context.Context, _ *vfs.Mount) (string, error
t := kernel.TaskFromContext(ctx)
if t == nil {
// Who is reading this link?
- return "", syserror.EINVAL
+ return "", linuxerr.EINVAL
}
tgid := s.pidns.IDOfThreadGroup(t.ThreadGroup())
if tgid == 0 {
@@ -94,7 +95,7 @@ func (s *threadSelfSymlink) Readlink(ctx context.Context, _ *vfs.Mount) (string,
t := kernel.TaskFromContext(ctx)
if t == nil {
// Who is reading this link?
- return "", syserror.EINVAL
+ return "", linuxerr.EINVAL
}
tgid := s.pidns.IDOfThreadGroup(t.ThreadGroup())
tid := s.pidns.IDOfTask(t)
diff --git a/pkg/sentry/fsimpl/proc/tasks_sys.go b/pkg/sentry/fsimpl/proc/tasks_sys.go
index 88ab49048..99f64a9d8 100644
--- a/pkg/sentry/fsimpl/proc/tasks_sys.go
+++ b/pkg/sentry/fsimpl/proc/tasks_sys.go
@@ -21,6 +21,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/kernfs"
"gvisor.dev/gvisor/pkg/sentry/inet"
@@ -28,7 +29,6 @@ import (
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/vfs"
"gvisor.dev/gvisor/pkg/sync"
- "gvisor.dev/gvisor/pkg/syserror"
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
"gvisor.dev/gvisor/pkg/usermem"
)
@@ -55,6 +55,7 @@ func (fs *filesystem) newSysDir(ctx context.Context, root *auth.Credentials, k *
}),
}),
"vm": fs.newStaticDir(ctx, root, map[string]kernfs.Inode{
+ "max_map_count": fs.newInode(ctx, root, 0444, newStaticFile("2147483647\n")),
"mmap_min_addr": fs.newInode(ctx, root, 0444, &mmapMinAddrData{k: k}),
"overcommit_memory": fs.newInode(ctx, root, 0444, newStaticFile("0\n")),
}),
@@ -208,7 +209,7 @@ func (d *tcpSackData) Generate(ctx context.Context, buf *bytes.Buffer) error {
func (d *tcpSackData) Write(ctx context.Context, src usermem.IOSequence, offset int64) (int64, error) {
if offset != 0 {
// No need to handle partial writes thus far.
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
if src.NumBytes() == 0 {
return 0, nil
@@ -256,7 +257,7 @@ func (d *tcpRecoveryData) Generate(ctx context.Context, buf *bytes.Buffer) error
func (d *tcpRecoveryData) Write(ctx context.Context, src usermem.IOSequence, offset int64) (int64, error) {
if offset != 0 {
// No need to handle partial writes thus far.
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
if src.NumBytes() == 0 {
return 0, nil
@@ -310,7 +311,7 @@ func (d *tcpMemData) Generate(ctx context.Context, buf *bytes.Buffer) error {
func (d *tcpMemData) Write(ctx context.Context, src usermem.IOSequence, offset int64) (int64, error) {
if offset != 0 {
// No need to handle partial writes thus far.
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
if src.NumBytes() == 0 {
return 0, nil
@@ -395,7 +396,7 @@ func (ipf *ipForwarding) Generate(ctx context.Context, buf *bytes.Buffer) error
func (ipf *ipForwarding) Write(ctx context.Context, src usermem.IOSequence, offset int64) (int64, error) {
if offset != 0 {
// No need to handle partial writes thus far.
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
if src.NumBytes() == 0 {
return 0, nil
@@ -448,7 +449,7 @@ func (pr *portRange) Generate(ctx context.Context, buf *bytes.Buffer) error {
func (pr *portRange) Write(ctx context.Context, src usermem.IOSequence, offset int64) (int64, error) {
if offset != 0 {
// No need to handle partial writes thus far.
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
if src.NumBytes() == 0 {
return 0, nil
@@ -466,7 +467,7 @@ func (pr *portRange) Write(ctx context.Context, src usermem.IOSequence, offset i
// Port numbers must be uint16s.
if ports[0] < 0 || ports[1] < 0 || ports[0] > math.MaxUint16 || ports[1] > math.MaxUint16 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
if err := pr.stack.SetPortRange(uint16(ports[0]), uint16(ports[1])); err != nil {
diff --git a/pkg/sentry/fsimpl/proc/tasks_test.go b/pkg/sentry/fsimpl/proc/tasks_test.go
index e534fbca8..14f806c3c 100644
--- a/pkg/sentry/fsimpl/proc/tasks_test.go
+++ b/pkg/sentry/fsimpl/proc/tasks_test.go
@@ -23,13 +23,13 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fspath"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/testutil"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/tmpfs"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/vfs"
- "gvisor.dev/gvisor/pkg/syserror"
"gvisor.dev/gvisor/pkg/usermem"
)
@@ -227,7 +227,7 @@ func TestTasks(t *testing.T) {
defer fd.DecRef(s.Ctx)
buf := make([]byte, 1)
bufIOSeq := usermem.BytesIOSequence(buf)
- if _, err := fd.Read(s.Ctx, bufIOSeq, vfs.ReadOptions{}); err != syserror.EISDIR {
+ if _, err := fd.Read(s.Ctx, bufIOSeq, vfs.ReadOptions{}); !linuxerr.Equals(linuxerr.EISDIR, err) {
t.Errorf("wrong error reading directory: %v", err)
}
}
@@ -237,7 +237,7 @@ func TestTasks(t *testing.T) {
s.Creds,
s.PathOpAtRoot("/proc/9999"),
&vfs.OpenOptions{},
- ); err != syserror.ENOENT {
+ ); !linuxerr.Equals(linuxerr.ENOENT, err) {
t.Fatalf("wrong error from vfsfs.OpenAt(/proc/9999): %v", err)
}
}
diff --git a/pkg/sentry/fsimpl/proc/yama.go b/pkg/sentry/fsimpl/proc/yama.go
index e039ec45e..7240563d7 100644
--- a/pkg/sentry/fsimpl/proc/yama.go
+++ b/pkg/sentry/fsimpl/proc/yama.go
@@ -21,11 +21,11 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/kernfs"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
- "gvisor.dev/gvisor/pkg/syserror"
"gvisor.dev/gvisor/pkg/usermem"
)
@@ -56,7 +56,7 @@ func (s *yamaPtraceScope) Generate(ctx context.Context, buf *bytes.Buffer) error
func (s *yamaPtraceScope) Write(ctx context.Context, src usermem.IOSequence, offset int64) (int64, error) {
if offset != 0 {
// Ignore partial writes.
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
if src.NumBytes() == 0 {
return 0, nil
@@ -73,7 +73,7 @@ func (s *yamaPtraceScope) Write(ctx context.Context, src usermem.IOSequence, off
// We do not support YAMA levels > YAMA_SCOPE_RELATIONAL.
if v < linux.YAMA_SCOPE_DISABLED || v > linux.YAMA_SCOPE_RELATIONAL {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
atomic.StoreInt32(s.level, v)
diff --git a/pkg/sentry/fsimpl/sys/BUILD b/pkg/sentry/fsimpl/sys/BUILD
index 09043b572..1af0a5cbc 100644
--- a/pkg/sentry/fsimpl/sys/BUILD
+++ b/pkg/sentry/fsimpl/sys/BUILD
@@ -26,6 +26,7 @@ go_library(
"//pkg/abi/linux",
"//pkg/context",
"//pkg/coverage",
+ "//pkg/errors/linuxerr",
"//pkg/log",
"//pkg/refs",
"//pkg/refsvfs2",
diff --git a/pkg/sentry/fsimpl/sys/kcov.go b/pkg/sentry/fsimpl/sys/kcov.go
index b13f141a8..d06aea162 100644
--- a/pkg/sentry/fsimpl/sys/kcov.go
+++ b/pkg/sentry/fsimpl/sys/kcov.go
@@ -17,6 +17,7 @@ package sys
import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/kernfs"
"gvisor.dev/gvisor/pkg/sentry/kernel"
@@ -85,7 +86,7 @@ func (fd *kcovFD) Ioctl(ctx context.Context, uio usermem.IO, args arch.SyscallAr
case linux.KCOV_DISABLE:
if arg != 0 {
// This arg is unused; it should be 0.
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
return 0, fd.kcov.DisableTrace(ctx)
default:
diff --git a/pkg/sentry/fsimpl/sys/sys.go b/pkg/sentry/fsimpl/sys/sys.go
index 14eb10dcd..546f54a5a 100644
--- a/pkg/sentry/fsimpl/sys/sys.go
+++ b/pkg/sentry/fsimpl/sys/sys.go
@@ -23,6 +23,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/coverage"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/kernfs"
"gvisor.dev/gvisor/pkg/sentry/kernel"
@@ -74,7 +75,7 @@ func (fsType FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
maxCachedDentries, err = strconv.ParseUint(str, 10, 64)
if err != nil {
ctx.Warningf("sys.FilesystemType.GetFilesystem: invalid dentry cache limit: dentry_cache_limit=%s", str)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
}
diff --git a/pkg/sentry/fsimpl/testutil/BUILD b/pkg/sentry/fsimpl/testutil/BUILD
index c766164c7..b3f9d1010 100644
--- a/pkg/sentry/fsimpl/testutil/BUILD
+++ b/pkg/sentry/fsimpl/testutil/BUILD
@@ -17,7 +17,6 @@ go_library(
"//pkg/fspath",
"//pkg/hostarch",
"//pkg/memutil",
- "//pkg/metric",
"//pkg/sentry/fsbridge",
"//pkg/sentry/fsimpl/tmpfs",
"//pkg/sentry/kernel",
diff --git a/pkg/sentry/fsimpl/testutil/kernel.go b/pkg/sentry/fsimpl/testutil/kernel.go
index 33e52ce64..473b41cff 100644
--- a/pkg/sentry/fsimpl/testutil/kernel.go
+++ b/pkg/sentry/fsimpl/testutil/kernel.go
@@ -25,7 +25,6 @@ import (
"gvisor.dev/gvisor/pkg/cpuid"
"gvisor.dev/gvisor/pkg/fspath"
"gvisor.dev/gvisor/pkg/memutil"
- "gvisor.dev/gvisor/pkg/metric"
"gvisor.dev/gvisor/pkg/sentry/fsbridge"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/tmpfs"
"gvisor.dev/gvisor/pkg/sentry/kernel"
@@ -63,8 +62,6 @@ func Boot() (*kernel.Kernel, error) {
return nil, fmt.Errorf("creating platform: %v", err)
}
- metric.CreateSentryMetrics()
-
kernel.VFS2Enabled = true
k := &kernel.Kernel{
Platform: plat,
@@ -83,10 +80,7 @@ func Boot() (*kernel.Kernel, error) {
}
// Create timekeeper.
- tk, err := kernel.NewTimekeeper(k, vdso.ParamPage.FileRange())
- if err != nil {
- return nil, fmt.Errorf("creating timekeeper: %v", err)
- }
+ tk := kernel.NewTimekeeper(k, vdso.ParamPage.FileRange())
tk.SetClocks(time.NewCalibratedClocks())
creds := auth.NewRootCredentials(auth.NewRootUserNamespace())
@@ -181,7 +175,7 @@ func createMemoryFile() (*pgalloc.MemoryFile, error) {
memfile := os.NewFile(uintptr(memfd), memfileName)
mf, err := pgalloc.NewMemoryFile(memfile, pgalloc.MemoryFileOpts{})
if err != nil {
- memfile.Close()
+ _ = memfile.Close()
return nil, fmt.Errorf("error creating pgalloc.MemoryFile: %v", err)
}
return mf, nil
diff --git a/pkg/sentry/fsimpl/timerfd/BUILD b/pkg/sentry/fsimpl/timerfd/BUILD
index 7ce7dc429..e6980a314 100644
--- a/pkg/sentry/fsimpl/timerfd/BUILD
+++ b/pkg/sentry/fsimpl/timerfd/BUILD
@@ -8,6 +8,7 @@ go_library(
visibility = ["//pkg/sentry:internal"],
deps = [
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/hostarch",
"//pkg/sentry/kernel/time",
"//pkg/sentry/vfs",
diff --git a/pkg/sentry/fsimpl/timerfd/timerfd.go b/pkg/sentry/fsimpl/timerfd/timerfd.go
index cbb8b67c5..655a1c76a 100644
--- a/pkg/sentry/fsimpl/timerfd/timerfd.go
+++ b/pkg/sentry/fsimpl/timerfd/timerfd.go
@@ -19,6 +19,7 @@ import (
"sync/atomic"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
ktime "gvisor.dev/gvisor/pkg/sentry/kernel/time"
"gvisor.dev/gvisor/pkg/sentry/vfs"
@@ -69,7 +70,7 @@ func New(ctx context.Context, vfsObj *vfs.VirtualFilesystem, clock ktime.Clock,
func (tfd *TimerFileDescription) Read(ctx context.Context, dst usermem.IOSequence, opts vfs.ReadOptions) (int64, error) {
const sizeofUint64 = 8
if dst.NumBytes() < sizeofUint64 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
if val := atomic.SwapUint64(&tfd.val, 0); val != 0 {
var buf [sizeofUint64]byte
diff --git a/pkg/sentry/fsimpl/tmpfs/BUILD b/pkg/sentry/fsimpl/tmpfs/BUILD
index e21fddd7f..ae612aae0 100644
--- a/pkg/sentry/fsimpl/tmpfs/BUILD
+++ b/pkg/sentry/fsimpl/tmpfs/BUILD
@@ -58,6 +58,7 @@ go_library(
"//pkg/abi/linux",
"//pkg/amutex",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/fspath",
"//pkg/hostarch",
"//pkg/log",
@@ -118,6 +119,7 @@ go_test(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/fspath",
"//pkg/sentry/contexttest",
"//pkg/sentry/fs/lock",
diff --git a/pkg/sentry/fsimpl/tmpfs/directory.go b/pkg/sentry/fsimpl/tmpfs/directory.go
index e8d256495..c25494c0b 100644
--- a/pkg/sentry/fsimpl/tmpfs/directory.go
+++ b/pkg/sentry/fsimpl/tmpfs/directory.go
@@ -19,10 +19,10 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/vfs"
"gvisor.dev/gvisor/pkg/sync"
- "gvisor.dev/gvisor/pkg/syserror"
)
// +stateify savable
@@ -196,10 +196,10 @@ func (fd *directoryFD) Seek(ctx context.Context, offset int64, whence int32) (in
case linux.SEEK_CUR:
offset += fd.off
default:
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
if offset < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// If the offset isn't changing (e.g. due to lseek(0, SEEK_CUR)), don't
diff --git a/pkg/sentry/fsimpl/tmpfs/filesystem.go b/pkg/sentry/fsimpl/tmpfs/filesystem.go
index 766289e60..590f7118a 100644
--- a/pkg/sentry/fsimpl/tmpfs/filesystem.go
+++ b/pkg/sentry/fsimpl/tmpfs/filesystem.go
@@ -20,6 +20,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fspath"
"gvisor.dev/gvisor/pkg/sentry/fsmetric"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
@@ -300,7 +301,7 @@ func (fs *filesystem) MknodAt(ctx context.Context, rp *vfs.ResolvingPath, opts v
case linux.S_IFSOCK:
childInode = fs.newSocketFile(creds.EffectiveKUID, creds.EffectiveKGID, opts.Mode, opts.Endpoint, parentDir)
default:
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
child := fs.newDentry(childInode)
parentDir.insertChildLocked(child, name)
@@ -488,7 +489,7 @@ func (fs *filesystem) ReadlinkAt(ctx context.Context, rp *vfs.ResolvingPath) (st
}
symlink, ok := d.inode.impl.(*symlink)
if !ok {
- return "", syserror.EINVAL
+ return "", linuxerr.EINVAL
}
symlink.inode.touchAtime(rp.Mount())
return symlink.target, nil
@@ -496,20 +497,24 @@ func (fs *filesystem) ReadlinkAt(ctx context.Context, rp *vfs.ResolvingPath) (st
// RenameAt implements vfs.FilesystemImpl.RenameAt.
func (fs *filesystem) RenameAt(ctx context.Context, rp *vfs.ResolvingPath, oldParentVD vfs.VirtualDentry, oldName string, opts vfs.RenameOptions) error {
- if opts.Flags != 0 {
- // TODO(b/145974740): Support renameat2 flags.
- return syserror.EINVAL
- }
-
- // Resolve newParent first to verify that it's on this Mount.
+ // Resolve newParentDir first to verify that it's on this Mount.
fs.mu.Lock()
defer fs.mu.Unlock()
newParentDir, err := walkParentDirLocked(ctx, rp, rp.Start().Impl().(*dentry))
if err != nil {
return err
}
+
+ if opts.Flags&^linux.RENAME_NOREPLACE != 0 {
+ // TODO(b/145974740): Support other renameat2 flags.
+ return linuxerr.EINVAL
+ }
+
newName := rp.Component()
if newName == "." || newName == ".." {
+ if opts.Flags&linux.RENAME_NOREPLACE != 0 {
+ return syserror.EEXIST
+ }
return syserror.EBUSY
}
mnt := rp.Mount()
@@ -537,7 +542,7 @@ func (fs *filesystem) RenameAt(ctx context.Context, rp *vfs.ResolvingPath, oldPa
// mounted filesystem.
if renamed.inode.isDir() {
if renamed == &newParentDir.dentry || genericIsAncestorDentry(renamed, &newParentDir.dentry) {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if oldParentDir != newParentDir {
// Writability is needed to change renamed's "..".
@@ -556,6 +561,9 @@ func (fs *filesystem) RenameAt(ctx context.Context, rp *vfs.ResolvingPath, oldPa
}
replaced, ok := newParentDir.childMap[newName]
if ok {
+ if opts.Flags&linux.RENAME_NOREPLACE != 0 {
+ return syserror.EEXIST
+ }
replacedDir, ok := replaced.inode.impl.(*directory)
if ok {
if !renamed.inode.isDir() {
@@ -639,7 +647,7 @@ func (fs *filesystem) RmdirAt(ctx context.Context, rp *vfs.ResolvingPath) error
}
name := rp.Component()
if name == "." {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if name == ".." {
return syserror.ENOTEMPTY
@@ -815,7 +823,7 @@ func (fs *filesystem) ListXattrAt(ctx context.Context, rp *vfs.ResolvingPath, si
if err != nil {
return nil, err
}
- return d.inode.listXattr(size)
+ return d.inode.listXattr(rp.Credentials(), size)
}
// GetXattrAt implements vfs.FilesystemImpl.GetXattrAt.
diff --git a/pkg/sentry/fsimpl/tmpfs/pipe_test.go b/pkg/sentry/fsimpl/tmpfs/pipe_test.go
index 2f856ce36..418c7994e 100644
--- a/pkg/sentry/fsimpl/tmpfs/pipe_test.go
+++ b/pkg/sentry/fsimpl/tmpfs/pipe_test.go
@@ -20,6 +20,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fspath"
"gvisor.dev/gvisor/pkg/sentry/contexttest"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
@@ -114,7 +115,7 @@ func TestNonblockingWriteError(t *testing.T) {
}
openOpts := vfs.OpenOptions{Flags: linux.O_WRONLY | linux.O_NONBLOCK}
_, err := vfsObj.OpenAt(ctx, creds, &pop, &openOpts)
- if err != syserror.ENXIO {
+ if !linuxerr.Equals(linuxerr.ENXIO, err) {
t.Fatalf("expected ENXIO, but got error: %v", err)
}
}
diff --git a/pkg/sentry/fsimpl/tmpfs/regular_file.go b/pkg/sentry/fsimpl/tmpfs/regular_file.go
index c45bddff6..0bc1911d9 100644
--- a/pkg/sentry/fsimpl/tmpfs/regular_file.go
+++ b/pkg/sentry/fsimpl/tmpfs/regular_file.go
@@ -22,6 +22,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/safemem"
"gvisor.dev/gvisor/pkg/sentry/fs"
@@ -366,7 +367,7 @@ func (fd *regularFileFD) PRead(ctx context.Context, dst usermem.IOSequence, offs
fsmetric.TmpfsReads.Increment()
if offset < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// Check that flags are supported. RWF_DSYNC/RWF_SYNC can be ignored since
@@ -407,7 +408,7 @@ func (fd *regularFileFD) PWrite(ctx context.Context, src usermem.IOSequence, off
// final offset should be ignored by PWrite.
func (fd *regularFileFD) pwrite(ctx context.Context, src usermem.IOSequence, offset int64, opts vfs.WriteOptions) (written, finalOff int64, err error) {
if offset < 0 {
- return 0, offset, syserror.EINVAL
+ return 0, offset, linuxerr.EINVAL
}
// Check that flags are supported. RWF_DSYNC/RWF_SYNC can be ignored since
@@ -432,7 +433,7 @@ func (fd *regularFileFD) pwrite(ctx context.Context, src usermem.IOSequence, off
}
if end := offset + srclen; end < offset {
// Overflow.
- return 0, offset, syserror.EINVAL
+ return 0, offset, linuxerr.EINVAL
}
srclen, err = vfs.CheckLimit(ctx, offset, srclen)
@@ -476,10 +477,10 @@ func (fd *regularFileFD) Seek(ctx context.Context, offset int64, whence int32) (
case linux.SEEK_END:
offset += int64(atomic.LoadUint64(&fd.inode().impl.(*regularFile).size))
default:
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
if offset < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
fd.off = offset
return offset, nil
@@ -684,7 +685,7 @@ exitLoop:
func GetSeals(fd *vfs.FileDescription) (uint32, error) {
f, ok := fd.Impl().(*regularFileFD)
if !ok {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
rf := f.inode().impl.(*regularFile)
rf.dataMu.RLock()
@@ -696,7 +697,7 @@ func GetSeals(fd *vfs.FileDescription) (uint32, error) {
func AddSeals(fd *vfs.FileDescription, val uint32) error {
f, ok := fd.Impl().(*regularFileFD)
if !ok {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
rf := f.inode().impl.(*regularFile)
rf.mapsMu.Lock()
diff --git a/pkg/sentry/fsimpl/tmpfs/tmpfs.go b/pkg/sentry/fsimpl/tmpfs/tmpfs.go
index 9ae25ce9e..bc40aad0d 100644
--- a/pkg/sentry/fsimpl/tmpfs/tmpfs.go
+++ b/pkg/sentry/fsimpl/tmpfs/tmpfs.go
@@ -36,6 +36,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/kernel/time"
@@ -138,7 +139,7 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
mode, err := strconv.ParseUint(modeStr, 8, 32)
if err != nil {
ctx.Warningf("tmpfs.FilesystemType.GetFilesystem: invalid mode: %q", modeStr)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
rootMode = linux.FileMode(mode & 07777)
}
@@ -149,12 +150,12 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
uid, err := strconv.ParseUint(uidStr, 10, 32)
if err != nil {
ctx.Warningf("tmpfs.FilesystemType.GetFilesystem: invalid uid: %q", uidStr)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
kuid := creds.UserNamespace.MapToKUID(auth.UID(uid))
if !kuid.Ok() {
ctx.Warningf("tmpfs.FilesystemType.GetFilesystem: unmapped uid: %d", uid)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
rootKUID = kuid
}
@@ -165,18 +166,18 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
gid, err := strconv.ParseUint(gidStr, 10, 32)
if err != nil {
ctx.Warningf("tmpfs.FilesystemType.GetFilesystem: invalid gid: %q", gidStr)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
kgid := creds.UserNamespace.MapToKGID(auth.GID(gid))
if !kgid.Ok() {
ctx.Warningf("tmpfs.FilesystemType.GetFilesystem: unmapped gid: %d", gid)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
rootKGID = kgid
}
if len(mopts) != 0 {
ctx.Warningf("tmpfs.FilesystemType.GetFilesystem: unknown options: %v", mopts)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
devMinor, err := vfsObj.GetAnonBlockDevMinor()
@@ -557,7 +558,7 @@ func (i *inode) setStat(ctx context.Context, creds *auth.Credentials, opts *vfs.
case *directory:
return syserror.EISDIR
default:
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
}
if mask&linux.STATX_UID != 0 {
@@ -717,44 +718,63 @@ func (i *inode) touchCMtimeLocked() {
atomic.StoreInt64(&i.ctime, now)
}
-func (i *inode) listXattr(size uint64) ([]string, error) {
- return i.xattrs.ListXattr(size)
+func checkXattrName(name string) error {
+ // Linux's tmpfs supports "security" and "trusted" xattr namespaces, and
+ // (depending on build configuration) POSIX ACL xattr namespaces
+ // ("system.posix_acl_access" and "system.posix_acl_default"). We don't
+ // support POSIX ACLs or the "security" namespace (b/148380782).
+ if strings.HasPrefix(name, linux.XATTR_TRUSTED_PREFIX) {
+ return nil
+ }
+ // We support the "user" namespace because we have tests that depend on
+ // this feature.
+ if strings.HasPrefix(name, linux.XATTR_USER_PREFIX) {
+ return nil
+ }
+ return syserror.EOPNOTSUPP
+}
+
+func (i *inode) listXattr(creds *auth.Credentials, size uint64) ([]string, error) {
+ return i.xattrs.ListXattr(creds, size)
}
func (i *inode) getXattr(creds *auth.Credentials, opts *vfs.GetXattrOptions) (string, error) {
- if err := i.checkXattrPermissions(creds, opts.Name, vfs.MayRead); err != nil {
+ if err := checkXattrName(opts.Name); err != nil {
return "", err
}
- return i.xattrs.GetXattr(opts)
+ mode := linux.FileMode(atomic.LoadUint32(&i.mode))
+ kuid := auth.KUID(atomic.LoadUint32(&i.uid))
+ kgid := auth.KGID(atomic.LoadUint32(&i.gid))
+ if err := vfs.GenericCheckPermissions(creds, vfs.MayRead, mode, kuid, kgid); err != nil {
+ return "", err
+ }
+ return i.xattrs.GetXattr(creds, mode, kuid, opts)
}
func (i *inode) setXattr(creds *auth.Credentials, opts *vfs.SetXattrOptions) error {
- if err := i.checkXattrPermissions(creds, opts.Name, vfs.MayWrite); err != nil {
+ if err := checkXattrName(opts.Name); err != nil {
return err
}
- return i.xattrs.SetXattr(opts)
-}
-
-func (i *inode) removeXattr(creds *auth.Credentials, name string) error {
- if err := i.checkXattrPermissions(creds, name, vfs.MayWrite); err != nil {
+ mode := linux.FileMode(atomic.LoadUint32(&i.mode))
+ kuid := auth.KUID(atomic.LoadUint32(&i.uid))
+ kgid := auth.KGID(atomic.LoadUint32(&i.gid))
+ if err := vfs.GenericCheckPermissions(creds, vfs.MayWrite, mode, kuid, kgid); err != nil {
return err
}
- return i.xattrs.RemoveXattr(name)
+ return i.xattrs.SetXattr(creds, mode, kuid, opts)
}
-func (i *inode) checkXattrPermissions(creds *auth.Credentials, name string, ats vfs.AccessTypes) error {
- // We currently only support extended attributes in the user.* and
- // trusted.* namespaces. See b/148380782.
- if !strings.HasPrefix(name, linux.XATTR_USER_PREFIX) && !strings.HasPrefix(name, linux.XATTR_TRUSTED_PREFIX) {
- return syserror.EOPNOTSUPP
+func (i *inode) removeXattr(creds *auth.Credentials, name string) error {
+ if err := checkXattrName(name); err != nil {
+ return err
}
mode := linux.FileMode(atomic.LoadUint32(&i.mode))
kuid := auth.KUID(atomic.LoadUint32(&i.uid))
kgid := auth.KGID(atomic.LoadUint32(&i.gid))
- if err := vfs.GenericCheckPermissions(creds, ats, mode, kuid, kgid); err != nil {
+ if err := vfs.GenericCheckPermissions(creds, vfs.MayWrite, mode, kuid, kgid); err != nil {
return err
}
- return vfs.CheckXattrPermissions(creds, ats, mode, kuid, name)
+ return i.xattrs.RemoveXattr(creds, mode, kuid, name)
}
// fileDescription is embedded by tmpfs implementations of
@@ -807,7 +827,7 @@ func (fd *fileDescription) StatFS(ctx context.Context) (linux.Statfs, error) {
// ListXattr implements vfs.FileDescriptionImpl.ListXattr.
func (fd *fileDescription) ListXattr(ctx context.Context, size uint64) ([]string, error) {
- return fd.inode().listXattr(size)
+ return fd.inode().listXattr(auth.CredentialsFromContext(ctx), size)
}
// GetXattr implements vfs.FileDescriptionImpl.GetXattr.
diff --git a/pkg/sentry/fsimpl/verity/BUILD b/pkg/sentry/fsimpl/verity/BUILD
index d473a922d..1d855234c 100644
--- a/pkg/sentry/fsimpl/verity/BUILD
+++ b/pkg/sentry/fsimpl/verity/BUILD
@@ -13,6 +13,7 @@ go_library(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/fspath",
"//pkg/hostarch",
"//pkg/marshal/primitive",
@@ -41,6 +42,7 @@ go_test(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/fspath",
"//pkg/sentry/arch",
"//pkg/sentry/fsimpl/testutil",
@@ -48,7 +50,6 @@ go_test(
"//pkg/sentry/kernel",
"//pkg/sentry/kernel/auth",
"//pkg/sentry/vfs",
- "//pkg/syserror",
"//pkg/usermem",
],
)
diff --git a/pkg/sentry/fsimpl/verity/filesystem.go b/pkg/sentry/fsimpl/verity/filesystem.go
index 3582d14c9..b5735a86d 100644
--- a/pkg/sentry/fsimpl/verity/filesystem.go
+++ b/pkg/sentry/fsimpl/verity/filesystem.go
@@ -25,6 +25,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fspath"
"gvisor.dev/gvisor/pkg/merkletree"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
@@ -195,7 +196,7 @@ func (fs *filesystem) verifyChildLocked(ctx context.Context, parent *dentry, chi
// The Merkle tree file for the child should have been created and
// contains the expected xattrs. If the file or the xattr does not
// exist, it indicates unexpected modifications to the file system.
- if err == syserror.ENOENT || err == syserror.ENODATA {
+ if linuxerr.Equals(linuxerr.ENOENT, err) || linuxerr.Equals(linuxerr.ENODATA, err) {
return nil, fs.alertIntegrityViolation(fmt.Sprintf("Failed to get xattr %s for %s: %v", merkleOffsetInParentXattr, childPath, err))
}
if err != nil {
@@ -218,7 +219,7 @@ func (fs *filesystem) verifyChildLocked(ctx context.Context, parent *dentry, chi
// The parent Merkle tree file should have been created. If it's
// missing, it indicates an unexpected modification to the file system.
- if err == syserror.ENOENT {
+ if linuxerr.Equals(linuxerr.ENOENT, err) {
return nil, fs.alertIntegrityViolation(fmt.Sprintf("Failed to open parent Merkle file for %s: %v", childPath, err))
}
if err != nil {
@@ -238,7 +239,7 @@ func (fs *filesystem) verifyChildLocked(ctx context.Context, parent *dentry, chi
// The Merkle tree file for the child should have been created and
// contains the expected xattrs. If the file or the xattr does not
// exist, it indicates unexpected modifications to the file system.
- if err == syserror.ENOENT || err == syserror.ENODATA {
+ if linuxerr.Equals(linuxerr.ENOENT, err) || linuxerr.Equals(linuxerr.ENODATA, err) {
return nil, fs.alertIntegrityViolation(fmt.Sprintf("Failed to get xattr %s for %s: %v", merkleSizeXattr, childPath, err))
}
if err != nil {
@@ -261,7 +262,7 @@ func (fs *filesystem) verifyChildLocked(ctx context.Context, parent *dentry, chi
Root: parent.lowerVD,
Start: parent.lowerVD,
}, &vfs.StatOptions{})
- if err == syserror.ENOENT {
+ if linuxerr.Equals(linuxerr.ENOENT, err) {
return nil, fs.alertIntegrityViolation(fmt.Sprintf("Failed to get parent stat for %s: %v", childPath, err))
}
if err != nil {
@@ -282,7 +283,7 @@ func (fs *filesystem) verifyChildLocked(ctx context.Context, parent *dentry, chi
Mode: uint32(parentStat.Mode),
UID: parentStat.UID,
GID: parentStat.GID,
- Children: parent.childrenNames,
+ Children: parent.childrenList,
HashAlgorithms: fs.alg.toLinuxHashAlg(),
ReadOffset: int64(offset),
ReadSize: int64(merkletree.DigestSize(fs.alg.toLinuxHashAlg())),
@@ -327,7 +328,7 @@ func (fs *filesystem) verifyStatAndChildrenLocked(ctx context.Context, d *dentry
}, &vfs.OpenOptions{
Flags: linux.O_RDONLY,
})
- if err == syserror.ENOENT {
+ if linuxerr.Equals(linuxerr.ENOENT, err) {
return fs.alertIntegrityViolation(fmt.Sprintf("Failed to open merkle file for %s: %v", childPath, err))
}
if err != nil {
@@ -341,7 +342,7 @@ func (fs *filesystem) verifyStatAndChildrenLocked(ctx context.Context, d *dentry
Size: sizeOfStringInt32,
})
- if err == syserror.ENODATA {
+ if linuxerr.Equals(linuxerr.ENODATA, err) {
return fs.alertIntegrityViolation(fmt.Sprintf("Failed to get xattr %s for merkle file of %s: %v", merkleSizeXattr, childPath, err))
}
if err != nil {
@@ -359,7 +360,7 @@ func (fs *filesystem) verifyStatAndChildrenLocked(ctx context.Context, d *dentry
Size: sizeOfStringInt32,
})
- if err == syserror.ENODATA {
+ if linuxerr.Equals(linuxerr.ENODATA, err) {
return fs.alertIntegrityViolation(fmt.Sprintf("Failed to get xattr %s for merkle file of %s: %v", childrenOffsetXattr, childPath, err))
}
if err != nil {
@@ -375,7 +376,7 @@ func (fs *filesystem) verifyStatAndChildrenLocked(ctx context.Context, d *dentry
Size: sizeOfStringInt32,
})
- if err == syserror.ENODATA {
+ if linuxerr.Equals(linuxerr.ENODATA, err) {
return fs.alertIntegrityViolation(fmt.Sprintf("Failed to get xattr %s for merkle file of %s: %v", childrenSizeXattr, childPath, err))
}
if err != nil {
@@ -403,6 +404,9 @@ func (fs *filesystem) verifyStatAndChildrenLocked(ctx context.Context, d *dentry
var buf bytes.Buffer
d.hashMu.RLock()
+
+ d.generateChildrenList()
+
params := &merkletree.VerifyParams{
Out: &buf,
Tree: &fdReader,
@@ -411,7 +415,7 @@ func (fs *filesystem) verifyStatAndChildrenLocked(ctx context.Context, d *dentry
Mode: uint32(stat.Mode),
UID: stat.UID,
GID: stat.GID,
- Children: d.childrenNames,
+ Children: d.childrenList,
HashAlgorithms: fs.alg.toLinuxHashAlg(),
ReadOffset: 0,
// Set read size to 0 so only the metadata is verified.
@@ -465,7 +469,7 @@ func (fs *filesystem) getChildLocked(ctx context.Context, parent *dentry, name s
}
childVD, err := parent.getLowerAt(ctx, vfsObj, name)
- if err == syserror.ENOENT {
+ if linuxerr.Equals(linuxerr.ENOENT, err) {
// The file was previously accessed. If the
// file does not exist now, it indicates an
// unexpected modification to the file system.
@@ -480,7 +484,7 @@ func (fs *filesystem) getChildLocked(ctx context.Context, parent *dentry, name s
// The Merkle tree file was previous accessed. If it
// does not exist now, it indicates an unexpected
// modification to the file system.
- if err == syserror.ENOENT {
+ if linuxerr.Equals(linuxerr.ENOENT, err) {
return nil, fs.alertIntegrityViolation(fmt.Sprintf("Expected Merkle file for target %s but none found", path))
}
if err != nil {
@@ -551,7 +555,7 @@ func (fs *filesystem) lookupAndVerifyLocked(ctx context.Context, parent *dentry,
}
childVD, err := parent.getLowerAt(ctx, vfsObj, name)
- if parent.verityEnabled() && err == syserror.ENOENT {
+ if parent.verityEnabled() && linuxerr.Equals(linuxerr.ENOENT, err) {
return nil, fs.alertIntegrityViolation(fmt.Sprintf("file %s expected but not found", parentPath+"/"+name))
}
if err != nil {
@@ -564,7 +568,7 @@ func (fs *filesystem) lookupAndVerifyLocked(ctx context.Context, parent *dentry,
childMerkleVD, err := parent.getLowerAt(ctx, vfsObj, merklePrefix+name)
if err != nil {
- if err == syserror.ENOENT {
+ if linuxerr.Equals(linuxerr.ENOENT, err) {
if parent.verityEnabled() {
return nil, fs.alertIntegrityViolation(fmt.Sprintf("Merkle file for %s expected but not found", parentPath+"/"+name))
}
@@ -854,7 +858,7 @@ func (d *dentry) openLocked(ctx context.Context, rp *vfs.ResolvingPath, opts *vf
// The file should exist, as we succeeded in finding its dentry. If it's
// missing, it indicates an unexpected modification to the file system.
if err != nil {
- if err == syserror.ENOENT {
+ if linuxerr.Equals(linuxerr.ENOENT, err) {
return nil, d.fs.alertIntegrityViolation(fmt.Sprintf("File %s expected but not found", path))
}
return nil, err
@@ -877,7 +881,7 @@ func (d *dentry) openLocked(ctx context.Context, rp *vfs.ResolvingPath, opts *vf
// dentry. If it's missing, it indicates an unexpected modification to
// the file system.
if err != nil {
- if err == syserror.ENOENT {
+ if linuxerr.Equals(linuxerr.ENOENT, err) {
return nil, d.fs.alertIntegrityViolation(fmt.Sprintf("Merkle file for %s expected but not found", path))
}
return nil, err
@@ -902,7 +906,7 @@ func (d *dentry) openLocked(ctx context.Context, rp *vfs.ResolvingPath, opts *vf
Flags: linux.O_WRONLY | linux.O_APPEND,
})
if err != nil {
- if err == syserror.ENOENT {
+ if linuxerr.Equals(linuxerr.ENOENT, err) {
return nil, d.fs.alertIntegrityViolation(fmt.Sprintf("Merkle file for %s expected but not found", path))
}
return nil, err
@@ -919,7 +923,7 @@ func (d *dentry) openLocked(ctx context.Context, rp *vfs.ResolvingPath, opts *vf
Flags: linux.O_WRONLY | linux.O_APPEND,
})
if err != nil {
- if err == syserror.ENOENT {
+ if linuxerr.Equals(linuxerr.ENOENT, err) {
parentPath, _ := d.fs.vfsfs.VirtualFilesystem().PathnameWithDeleted(ctx, d.fs.rootDentry.lowerVD, d.parent.lowerVD)
return nil, d.fs.alertIntegrityViolation(fmt.Sprintf("Merkle file for %s expected but not found", parentPath))
}
diff --git a/pkg/sentry/fsimpl/verity/verity.go b/pkg/sentry/fsimpl/verity/verity.go
index fa7696ad6..2227b542a 100644
--- a/pkg/sentry/fsimpl/verity/verity.go
+++ b/pkg/sentry/fsimpl/verity/verity.go
@@ -39,12 +39,14 @@ import (
"encoding/json"
"fmt"
"math"
+ "sort"
"strconv"
"strings"
"sync/atomic"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fspath"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/marshal/primitive"
@@ -251,7 +253,7 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
hash, err := hex.DecodeString(encodedRootHash)
if err != nil {
ctx.Warningf("verity.FilesystemType.GetFilesystem: Failed to decode root hash: %v", err)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
rootHash = hash
}
@@ -269,19 +271,19 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
// Check for unparsed options.
if len(mopts) != 0 {
ctx.Warningf("verity.FilesystemType.GetFilesystem: unknown options: %v", mopts)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
// Handle internal options.
iopts, ok := opts.InternalData.(InternalFilesystemOptions)
if len(lowerPathname) == 0 && !ok {
ctx.Warningf("verity.FilesystemType.GetFilesystem: missing verity configs")
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
if len(lowerPathname) != 0 {
if ok {
ctx.Warningf("verity.FilesystemType.GetFilesystem: unexpected verity configs with specified lower path")
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
iopts = InternalFilesystemOptions{
AllowRuntimeEnable: len(rootHash) == 0,
@@ -300,7 +302,7 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
lowerPath := fspath.Parse(lowerPathname)
if !lowerPath.Absolute {
ctx.Infof("verity.FilesystemType.GetFilesystem: lower_path %q must be absolute", lowerPathname)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
var err error
mountedLowerVD, err = vfsObj.GetDentryAt(ctx, creds, &vfs.PathOperation{
@@ -358,7 +360,7 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
// If runtime enable is allowed, the root merkle tree may be absent. We
// should create the tree file.
- if err == syserror.ENOENT && fs.allowRuntimeEnable {
+ if linuxerr.Equals(linuxerr.ENOENT, err) && fs.allowRuntimeEnable {
lowerMerkleFD, err := vfsObj.OpenAt(ctx, fs.creds, &vfs.PathOperation{
Root: lowerVD,
Start: lowerVD,
@@ -439,7 +441,7 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
if !d.isDir() {
ctx.Warningf("verity root must be a directory")
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
if !fs.allowRuntimeEnable {
@@ -451,7 +453,7 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
Name: childrenOffsetXattr,
Size: sizeOfStringInt32,
})
- if err == syserror.ENOENT || err == syserror.ENODATA {
+ if linuxerr.Equals(linuxerr.ENOENT, err) || linuxerr.Equals(linuxerr.ENODATA, err) {
return nil, nil, fs.alertIntegrityViolation(fmt.Sprintf("Failed to get xattr %s: %v", childrenOffsetXattr, err))
}
if err != nil {
@@ -470,7 +472,7 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
Name: childrenSizeXattr,
Size: sizeOfStringInt32,
})
- if err == syserror.ENOENT || err == syserror.ENODATA {
+ if linuxerr.Equals(linuxerr.ENOENT, err) || linuxerr.Equals(linuxerr.ENODATA, err) {
return nil, nil, fs.alertIntegrityViolation(fmt.Sprintf("Failed to get xattr %s: %v", childrenSizeXattr, err))
}
if err != nil {
@@ -487,7 +489,7 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
}, &vfs.OpenOptions{
Flags: linux.O_RDONLY,
})
- if err == syserror.ENOENT {
+ if linuxerr.Equals(linuxerr.ENOENT, err) {
return nil, nil, fs.alertIntegrityViolation(fmt.Sprintf("Failed to open root Merkle file: %v", err))
}
if err != nil {
@@ -508,6 +510,7 @@ func (fstype FilesystemType) GetFilesystem(ctx context.Context, vfsObj *vfs.Virt
if err := fs.verifyStatAndChildrenLocked(ctx, d, stat); err != nil {
return nil, nil, err
}
+ d.generateChildrenList()
}
d.vfsd.Init(d)
@@ -564,6 +567,11 @@ type dentry struct {
// populated by enableVerity. childrenNames is also protected by dirMu.
childrenNames map[string]struct{}
+ // childrenList is a complete sorted list of childrenNames. This list
+ // is generated when verity is enabled, or the first time the file is
+ // verified in non runtime enable mode.
+ childrenList []string
+
// lowerVD is the VirtualDentry in the underlying file system. It is
// never modified after initialized.
lowerVD vfs.VirtualDentry
@@ -749,6 +757,17 @@ func (d *dentry) verityEnabled() bool {
return !d.fs.allowRuntimeEnable || len(d.hash) != 0
}
+// generateChildrenList generates a sorted childrenList from childrenNames, and
+// cache it in d for hashing.
+func (d *dentry) generateChildrenList() {
+ if len(d.childrenList) == 0 && len(d.childrenNames) != 0 {
+ for child := range d.childrenNames {
+ d.childrenList = append(d.childrenList, child)
+ }
+ sort.Strings(d.childrenList)
+ }
+}
+
// getLowerAt returns the dentry in the underlying file system, which is
// represented by filename relative to d.
func (d *dentry) getLowerAt(ctx context.Context, vfsObj *vfs.VirtualFilesystem, filename string) (vfs.VirtualDentry, error) {
@@ -868,6 +887,10 @@ func (fd *fileDescription) IterDirents(ctx context.Context, cb vfs.IterDirentsCa
fd.mu.Lock()
defer fd.mu.Unlock()
+ if _, err := fd.lowerFD.Seek(ctx, fd.off, linux.SEEK_SET); err != nil {
+ return err
+ }
+
var ds []vfs.Dirent
err := fd.lowerFD.IterDirents(ctx, vfs.IterDirentsCallbackFunc(func(dirent vfs.Dirent) error {
// Do not include the Merkle tree files.
@@ -890,8 +913,8 @@ func (fd *fileDescription) IterDirents(ctx context.Context, cb vfs.IterDirentsCa
return err
}
- // The result should contain all children plus "." and "..".
- if fd.d.verityEnabled() && len(ds) != len(fd.d.childrenNames)+2 {
+ // The result should be a part of all children plus "." and "..", counting from fd.off.
+ if fd.d.verityEnabled() && len(ds) != len(fd.d.childrenNames)+2-int(fd.off) {
return fd.d.fs.alertIntegrityViolation(fmt.Sprintf("Unexpected children number %d", len(ds)))
}
@@ -917,14 +940,14 @@ func (fd *fileDescription) Seek(ctx context.Context, offset int64, whence int32)
case linux.SEEK_END:
n = int64(fd.d.size)
default:
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
if offset > math.MaxInt64-n {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
offset += n
if offset < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
fd.off = offset
return offset, nil
@@ -958,10 +981,12 @@ func (fd *fileDescription) generateMerkleLocked(ctx context.Context) ([]byte, ui
return nil, 0, err
}
+ fd.d.generateChildrenList()
+
params := &merkletree.GenerateParams{
TreeReader: &merkleReader,
TreeWriter: &merkleWriter,
- Children: fd.d.childrenNames,
+ Children: fd.d.childrenList,
HashAlgorithms: fd.d.fs.alg.toLinuxHashAlg(),
Name: fd.d.name,
Mode: uint32(stat.Mode),
@@ -1003,7 +1028,7 @@ func (fd *fileDescription) generateMerkleLocked(ctx context.Context) ([]byte, ui
default:
// TODO(b/167728857): Investigate whether and how we should
// enable other types of file.
- return nil, 0, syserror.EINVAL
+ return nil, 0, linuxerr.EINVAL
}
hash, err := merkletree.Generate(params)
return hash, uint64(params.Size), err
@@ -1121,7 +1146,7 @@ func (fd *fileDescription) enableVerity(ctx context.Context) (uintptr, error) {
func (fd *fileDescription) measureVerity(ctx context.Context, verityDigest hostarch.Addr) (uintptr, error) {
t := kernel.TaskFromContext(ctx)
if t == nil {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
var metadata linux.DigestMetadata
@@ -1174,7 +1199,7 @@ func (fd *fileDescription) verityFlags(ctx context.Context, flags hostarch.Addr)
t := kernel.TaskFromContext(ctx)
if t == nil {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
_, err := primitive.CopyInt32Out(t, flags, f)
return 0, err
@@ -1223,7 +1248,7 @@ func (fd *fileDescription) PRead(ctx context.Context, dst usermem.IOSequence, of
// The Merkle tree file for the child should have been created and
// contains the expected xattrs. If the xattr does not exist, it
// indicates unexpected modifications to the file system.
- if err == syserror.ENODATA {
+ if linuxerr.Equals(linuxerr.ENODATA, err) {
return 0, fd.d.fs.alertIntegrityViolation(fmt.Sprintf("Failed to get xattr %s: %v", merkleSizeXattr, err))
}
if err != nil {
@@ -1257,7 +1282,7 @@ func (fd *fileDescription) PRead(ctx context.Context, dst usermem.IOSequence, of
Mode: fd.d.mode,
UID: fd.d.uid,
GID: fd.d.gid,
- Children: fd.d.childrenNames,
+ Children: fd.d.childrenList,
HashAlgorithms: fd.d.fs.alg.toLinuxHashAlg(),
ReadOffset: offset,
ReadSize: dst.NumBytes(),
@@ -1345,7 +1370,7 @@ func (fd *fileDescription) Translate(ctx context.Context, required, optional mem
// The Merkle tree file for the child should have been created and
// contains the expected xattrs. If the xattr does not exist, it
// indicates unexpected modifications to the file system.
- if err == syserror.ENODATA {
+ if linuxerr.Equals(linuxerr.ENODATA, err) {
return nil, fd.d.fs.alertIntegrityViolation(fmt.Sprintf("Failed to get xattr %s: %v", merkleSizeXattr, err))
}
if err != nil {
@@ -1429,7 +1454,7 @@ func (r *mmapReadSeeker) ReadAt(p []byte, off int64) (int, error) {
// mapped region.
readOffset := off - int64(r.Offset)
if readOffset < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
bs.DropFirst64(uint64(readOffset))
view := bs.TakeFirst64(uint64(len(p)))
diff --git a/pkg/sentry/fsimpl/verity/verity_test.go b/pkg/sentry/fsimpl/verity/verity_test.go
index 5c78a0019..65465b814 100644
--- a/pkg/sentry/fsimpl/verity/verity_test.go
+++ b/pkg/sentry/fsimpl/verity/verity_test.go
@@ -24,6 +24,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fspath"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/testutil"
@@ -31,7 +32,6 @@ import (
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/vfs"
- "gvisor.dev/gvisor/pkg/syserror"
"gvisor.dev/gvisor/pkg/usermem"
)
@@ -476,7 +476,7 @@ func TestOpenNonexistentFile(t *testing.T) {
// Ensure open an unexpected file in the parent directory fails with
// ENOENT rather than verification failure.
- if _, err = openVerityAt(ctx, vfsObj, root, filename+"abc", linux.O_RDONLY, linux.ModeRegular); err != syserror.ENOENT {
+ if _, err = openVerityAt(ctx, vfsObj, root, filename+"abc", linux.O_RDONLY, linux.ModeRegular); !linuxerr.Equals(linuxerr.ENOENT, err) {
t.Errorf("OpenAt unexpected error: %v", err)
}
}
@@ -767,7 +767,7 @@ func TestOpenDeletedFileFails(t *testing.T) {
}
// Ensure reopening the verity enabled file fails.
- if _, err = openVerityAt(ctx, vfsObj, root, filename, linux.O_RDONLY, linux.ModeRegular); err != syserror.EIO {
+ if _, err = openVerityAt(ctx, vfsObj, root, filename, linux.O_RDONLY, linux.ModeRegular); !linuxerr.Equals(linuxerr.EIO, err) {
t.Errorf("got OpenAt error: %v, expected EIO", err)
}
})
@@ -829,7 +829,7 @@ func TestOpenRenamedFileFails(t *testing.T) {
}
// Ensure reopening the verity enabled file fails.
- if _, err = openVerityAt(ctx, vfsObj, root, filename, linux.O_RDONLY, linux.ModeRegular); err != syserror.EIO {
+ if _, err = openVerityAt(ctx, vfsObj, root, filename, linux.O_RDONLY, linux.ModeRegular); !linuxerr.Equals(linuxerr.EIO, err) {
t.Errorf("got OpenAt error: %v, expected EIO", err)
}
})
@@ -1063,14 +1063,14 @@ func TestDeletedSymlinkFileReadFails(t *testing.T) {
Root: root,
Start: root,
Path: fspath.Parse(symlink),
- }); err != syserror.EIO {
+ }); !linuxerr.Equals(linuxerr.EIO, err) {
t.Fatalf("ReadlinkAt succeeded with modified symlink: %v", err)
}
if tc.testWalk {
fileInSymlinkDirectory := symlink + "/verity-test-file"
// Ensure opening the verity enabled file in the symlink directory fails.
- if _, err := openVerityAt(ctx, vfsObj, root, fileInSymlinkDirectory, linux.O_RDONLY, linux.ModeRegular); err != syserror.EIO {
+ if _, err := openVerityAt(ctx, vfsObj, root, fileInSymlinkDirectory, linux.O_RDONLY, linux.ModeRegular); !linuxerr.Equals(linuxerr.EIO, err) {
t.Errorf("Open succeeded with modified symlink: %v", err)
}
}
@@ -1195,14 +1195,14 @@ func TestModifiedSymlinkFileReadFails(t *testing.T) {
Root: root,
Start: root,
Path: fspath.Parse(symlink),
- }); err != syserror.EIO {
+ }); !linuxerr.Equals(linuxerr.EIO, err) {
t.Fatalf("ReadlinkAt succeeded with modified symlink: %v", err)
}
if tc.testWalk {
fileInSymlinkDirectory := symlink + "/verity-test-file"
// Ensure opening the verity enabled file in the symlink directory fails.
- if _, err := openVerityAt(ctx, vfsObj, root, fileInSymlinkDirectory, linux.O_RDONLY, linux.ModeRegular); err != syserror.EIO {
+ if _, err := openVerityAt(ctx, vfsObj, root, fileInSymlinkDirectory, linux.O_RDONLY, linux.ModeRegular); !linuxerr.Equals(linuxerr.EIO, err) {
t.Errorf("Open succeeded with modified symlink: %v", err)
}
}
diff --git a/pkg/sentry/fsmetric/fsmetric.go b/pkg/sentry/fsmetric/fsmetric.go
index 7e535b527..17d0d5025 100644
--- a/pkg/sentry/fsmetric/fsmetric.go
+++ b/pkg/sentry/fsmetric/fsmetric.go
@@ -42,7 +42,6 @@ var (
// Metrics that only apply to fs/gofer and fsimpl/gofer.
var (
- GoferOpensWX = metric.MustCreateNewUint64Metric("/gofer/opened_write_execute_file", true /* sync */, "Number of times a executable file was opened writably from a gofer.")
GoferOpens9P = metric.MustCreateNewUint64Metric("/gofer/opens_9p", false /* sync */, "Number of times a file was opened from a gofer and did not have a host file descriptor.")
GoferOpensHost = metric.MustCreateNewUint64Metric("/gofer/opens_host", false /* sync */, "Number of times a file was opened from a gofer and did have a host file descriptor.")
GoferReads9P = metric.MustCreateNewUint64Metric("/gofer/reads_9p", false /* sync */, "Number of 9P file reads from a gofer.")
diff --git a/pkg/sentry/hostfd/hostfd_linux.go b/pkg/sentry/hostfd/hostfd_linux.go
index 1cabc848f..e103e7296 100644
--- a/pkg/sentry/hostfd/hostfd_linux.go
+++ b/pkg/sentry/hostfd/hostfd_linux.go
@@ -14,5 +14,10 @@
package hostfd
-// maxIov is the maximum permitted size of a struct iovec array.
-const maxIov = 1024 // UIO_MAXIOV
+// MaxReadWriteIov is the maximum permitted size of a struct iovec array in a
+// readv, writev, preadv, or pwritev host syscall.
+const MaxReadWriteIov = 1024 // UIO_MAXIOV
+
+// MaxSendRecvMsgIov is the maximum permitted size of a struct iovec array in a
+// sendmsg or recvmsg host syscall.
+const MaxSendRecvMsgIov = 1024 // UIO_MAXIOV
diff --git a/pkg/sentry/hostfd/hostfd_unsafe.go b/pkg/sentry/hostfd/hostfd_unsafe.go
index 03c6d2a16..a43311eb4 100644
--- a/pkg/sentry/hostfd/hostfd_unsafe.go
+++ b/pkg/sentry/hostfd/hostfd_unsafe.go
@@ -23,6 +23,11 @@ import (
"gvisor.dev/gvisor/pkg/safemem"
)
+const (
+ sizeofIovec = unsafe.Sizeof(unix.Iovec{})
+ sizeofMsghdr = unsafe.Sizeof(unix.Msghdr{})
+)
+
// Preadv2 reads up to dsts.NumBytes() bytes from host file descriptor fd into
// dsts. offset and flags are interpreted as for preadv2(2).
//
@@ -44,9 +49,9 @@ func Preadv2(fd int32, dsts safemem.BlockSeq, offset int64, flags uint32) (uint6
}
} else {
iovs := safemem.IovecsFromBlockSeq(dsts)
- if len(iovs) > maxIov {
- log.Debugf("hostfd.Preadv2: truncating from %d iovecs to %d", len(iovs), maxIov)
- iovs = iovs[:maxIov]
+ if len(iovs) > MaxReadWriteIov {
+ log.Debugf("hostfd.Preadv2: truncating from %d iovecs to %d", len(iovs), MaxReadWriteIov)
+ iovs = iovs[:MaxReadWriteIov]
}
n, _, e = unix.Syscall6(unix.SYS_PREADV2, uintptr(fd), uintptr((unsafe.Pointer)(&iovs[0])), uintptr(len(iovs)), uintptr(offset), 0 /* pos_h */, uintptr(flags))
}
@@ -80,9 +85,9 @@ func Pwritev2(fd int32, srcs safemem.BlockSeq, offset int64, flags uint32) (uint
}
} else {
iovs := safemem.IovecsFromBlockSeq(srcs)
- if len(iovs) > maxIov {
- log.Debugf("hostfd.Preadv2: truncating from %d iovecs to %d", len(iovs), maxIov)
- iovs = iovs[:maxIov]
+ if len(iovs) > MaxReadWriteIov {
+ log.Debugf("hostfd.Preadv2: truncating from %d iovecs to %d", len(iovs), MaxReadWriteIov)
+ iovs = iovs[:MaxReadWriteIov]
}
n, _, e = unix.Syscall6(unix.SYS_PWRITEV2, uintptr(fd), uintptr((unsafe.Pointer)(&iovs[0])), uintptr(len(iovs)), uintptr(offset), 0 /* pos_h */, uintptr(flags))
}
diff --git a/pkg/sentry/kernel/BUILD b/pkg/sentry/kernel/BUILD
index a1ec6daab..26614b029 100644
--- a/pkg/sentry/kernel/BUILD
+++ b/pkg/sentry/kernel/BUILD
@@ -32,7 +32,7 @@ go_template_instance(
out = "seqatomic_taskgoroutineschedinfo_unsafe.go",
package = "kernel",
suffix = "TaskGoroutineSchedInfo",
- template = "//pkg/sync:generic_seqatomic",
+ template = "//pkg/sync/seqatomic:generic_seqatomic",
types = {
"Value": "TaskGoroutineSchedInfo",
},
@@ -218,6 +218,7 @@ go_library(
":uncaught_signal_go_proto",
"//pkg/abi",
"//pkg/abi/linux",
+ "//pkg/abi/linux/errno",
"//pkg/amutex",
"//pkg/bits",
"//pkg/bpf",
@@ -225,6 +226,8 @@ go_library(
"//pkg/context",
"//pkg/coverage",
"//pkg/cpuid",
+ "//pkg/errors",
+ "//pkg/errors/linuxerr",
"//pkg/eventchannel",
"//pkg/fspath",
"//pkg/goid",
@@ -298,6 +301,7 @@ go_test(
deps = [
"//pkg/abi",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/hostarch",
"//pkg/sentry/arch",
"//pkg/sentry/contexttest",
@@ -309,6 +313,5 @@ go_test(
"//pkg/sentry/time",
"//pkg/sentry/usage",
"//pkg/sync",
- "//pkg/syserror",
],
)
diff --git a/pkg/sentry/kernel/auth/BUILD b/pkg/sentry/kernel/auth/BUILD
index 869e49ebc..7a1a36454 100644
--- a/pkg/sentry/kernel/auth/BUILD
+++ b/pkg/sentry/kernel/auth/BUILD
@@ -8,7 +8,7 @@ go_template_instance(
out = "atomicptr_credentials_unsafe.go",
package = "auth",
suffix = "Credentials",
- template = "//pkg/sync:generic_atomicptr",
+ template = "//pkg/sync/atomicptr:generic_atomicptr",
types = {
"Value": "Credentials",
},
@@ -63,6 +63,7 @@ go_library(
"//pkg/abi/linux",
"//pkg/bits",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/log",
"//pkg/sync",
"//pkg/syserror",
diff --git a/pkg/sentry/kernel/auth/credentials.go b/pkg/sentry/kernel/auth/credentials.go
index 6862f2ef5..32c344399 100644
--- a/pkg/sentry/kernel/auth/credentials.go
+++ b/pkg/sentry/kernel/auth/credentials.go
@@ -16,6 +16,7 @@ package auth
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/syserror"
)
@@ -125,7 +126,7 @@ func NewUserCredentials(kuid KUID, kgid KGID, extraKGIDs []KGID, capabilities *T
creds.EffectiveCaps = capabilities.EffectiveCaps
creds.BoundingCaps = capabilities.BoundingCaps
creds.InheritableCaps = capabilities.InheritableCaps
- // TODO(nlacasse): Support ambient capabilities.
+ // TODO(gvisor.dev/issue/3166): Support ambient capabilities.
} else {
// If no capabilities are specified, grant capabilities consistent with
// setresuid + setresgid from NewRootCredentials to the given uid and
@@ -203,7 +204,7 @@ func (c *Credentials) UseUID(uid UID) (KUID, error) {
// uid must be mapped.
kuid := c.UserNamespace.MapToKUID(uid)
if !kuid.Ok() {
- return NoID, syserror.EINVAL
+ return NoID, linuxerr.EINVAL
}
// If c has CAP_SETUID, then it can use any UID in its user namespace.
if c.HasCapability(linux.CAP_SETUID) {
@@ -222,7 +223,7 @@ func (c *Credentials) UseUID(uid UID) (KUID, error) {
func (c *Credentials) UseGID(gid GID) (KGID, error) {
kgid := c.UserNamespace.MapToKGID(gid)
if !kgid.Ok() {
- return NoID, syserror.EINVAL
+ return NoID, linuxerr.EINVAL
}
if c.HasCapability(linux.CAP_SETGID) {
return kgid, nil
@@ -239,7 +240,7 @@ func (c *Credentials) UseGID(gid GID) (KGID, error) {
func (c *Credentials) SetUID(uid UID) error {
kuid := c.UserNamespace.MapToKUID(uid)
if !kuid.Ok() {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
c.RealKUID = kuid
c.EffectiveKUID = kuid
@@ -253,7 +254,7 @@ func (c *Credentials) SetUID(uid UID) error {
func (c *Credentials) SetGID(gid GID) error {
kgid := c.UserNamespace.MapToKGID(gid)
if !kgid.Ok() {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
c.RealKGID = kgid
c.EffectiveKGID = kgid
diff --git a/pkg/sentry/kernel/auth/id_map.go b/pkg/sentry/kernel/auth/id_map.go
index 28cbe159d..955b6d40b 100644
--- a/pkg/sentry/kernel/auth/id_map.go
+++ b/pkg/sentry/kernel/auth/id_map.go
@@ -17,6 +17,7 @@ package auth
import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/syserror"
)
@@ -110,7 +111,7 @@ func (ns *UserNamespace) SetUIDMap(ctx context.Context, entries []IDMapEntry) er
}
// "At least one line must be written to the file."
if len(entries) == 0 {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
// """
// In order for a process to write to the /proc/[pid]/uid_map
@@ -170,11 +171,11 @@ func (ns *UserNamespace) trySetUIDMap(entries []IDMapEntry) error {
// checks for NoID.
lastID := e.FirstID + e.Length
if lastID <= e.FirstID {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
lastParentID := e.FirstParentID + e.Length
if lastParentID <= e.FirstParentID {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
// "3. The mapped user IDs (group IDs) must in turn have a mapping in
// the parent user namespace."
@@ -186,10 +187,10 @@ func (ns *UserNamespace) trySetUIDMap(entries []IDMapEntry) error {
}
// If either of these Adds fail, we have an overlapping range.
if !ns.uidMapFromParent.Add(idMapRange{e.FirstParentID, lastParentID}, e.FirstID) {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if !ns.uidMapToParent.Add(idMapRange{e.FirstID, lastID}, e.FirstParentID) {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
}
return nil
@@ -205,7 +206,7 @@ func (ns *UserNamespace) SetGIDMap(ctx context.Context, entries []IDMapEntry) er
return syserror.EPERM
}
if len(entries) == 0 {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if !c.HasCapabilityIn(linux.CAP_SETGID, ns) {
return syserror.EPERM
@@ -239,20 +240,20 @@ func (ns *UserNamespace) trySetGIDMap(entries []IDMapEntry) error {
for _, e := range entries {
lastID := e.FirstID + e.Length
if lastID <= e.FirstID {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
lastParentID := e.FirstParentID + e.Length
if lastParentID <= e.FirstParentID {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if !ns.parent.allIDsMapped(&ns.parent.gidMapToParent, e.FirstParentID, lastParentID) {
return syserror.EPERM
}
if !ns.gidMapFromParent.Add(idMapRange{e.FirstParentID, lastParentID}, e.FirstID) {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if !ns.gidMapToParent.Add(idMapRange{e.FirstID, lastID}, e.FirstParentID) {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
}
return nil
diff --git a/pkg/sentry/kernel/cgroup.go b/pkg/sentry/kernel/cgroup.go
index 0fbf27f64..c93ef6ac1 100644
--- a/pkg/sentry/kernel/cgroup.go
+++ b/pkg/sentry/kernel/cgroup.go
@@ -181,7 +181,23 @@ func (r *CgroupRegistry) FindHierarchy(ctypes []CgroupControllerType) *vfs.Files
for _, h := range r.hierarchies {
if h.match(ctypes) {
- h.fs.IncRef()
+ if !h.fs.TryIncRef() {
+ // Racing with filesystem destruction, namely h.fs.Release.
+ // Since we hold r.mu, we know the hierarchy hasn't been
+ // unregistered yet, but its associated filesystem is tearing
+ // down.
+ //
+ // If we simply indicate the hierarchy wasn't found without
+ // cleaning up the registry, the caller can race with the
+ // unregister and find itself temporarily unable to create a new
+ // hierarchy with a subset of the relevant controllers.
+ //
+ // To keep the result of FindHierarchy consistent with the
+ // uniqueness of controllers enforced by Register, drop the
+ // dying hierarchy now. The eventual unregister by the FS
+ // teardown will become a no-op.
+ return nil
+ }
return h.fs
}
}
@@ -230,12 +246,17 @@ func (r *CgroupRegistry) Register(cs []CgroupController, fs cgroupFS) error {
return nil
}
-// Unregister removes a previously registered hierarchy from the registry. If
-// the controller was not previously registered, Unregister is a no-op.
+// Unregister removes a previously registered hierarchy from the registry. If no
+// such hierarchy is registered, Unregister is a no-op.
func (r *CgroupRegistry) Unregister(hid uint32) {
r.mu.Lock()
- defer r.mu.Unlock()
+ r.unregisterLocked(hid)
+ r.mu.Unlock()
+}
+// Precondition: Caller must hold r.mu.
+// +checklocks:r.mu
+func (r *CgroupRegistry) unregisterLocked(hid uint32) {
if h, ok := r.hierarchies[hid]; ok {
for name, _ := range h.controllers {
delete(r.controllers, name)
diff --git a/pkg/sentry/kernel/fasync/BUILD b/pkg/sentry/kernel/fasync/BUILD
index f855f038b..6b2dd09da 100644
--- a/pkg/sentry/kernel/fasync/BUILD
+++ b/pkg/sentry/kernel/fasync/BUILD
@@ -8,13 +8,12 @@ go_library(
visibility = ["//:sandbox"],
deps = [
"//pkg/abi/linux",
- "//pkg/sentry/arch",
+ "//pkg/errors/linuxerr",
"//pkg/sentry/fs",
"//pkg/sentry/kernel",
"//pkg/sentry/kernel/auth",
"//pkg/sentry/vfs",
"//pkg/sync",
- "//pkg/syserror",
"//pkg/waiter",
],
)
diff --git a/pkg/sentry/kernel/fasync/fasync.go b/pkg/sentry/kernel/fasync/fasync.go
index dbbbaeeb0..473987a79 100644
--- a/pkg/sentry/kernel/fasync/fasync.go
+++ b/pkg/sentry/kernel/fasync/fasync.go
@@ -17,13 +17,12 @@ package fasync
import (
"gvisor.dev/gvisor/pkg/abi/linux"
- "gvisor.dev/gvisor/pkg/sentry/arch"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/vfs"
"gvisor.dev/gvisor/pkg/sync"
- "gvisor.dev/gvisor/pkg/syserror"
"gvisor.dev/gvisor/pkg/waiter"
)
@@ -125,9 +124,9 @@ func (a *FileAsync) Callback(e *waiter.Entry, mask waiter.EventMask) {
if !permCheck {
return
}
- signalInfo := &arch.SignalInfo{
+ signalInfo := &linux.SignalInfo{
Signo: int32(linux.SIGIO),
- Code: arch.SignalInfoKernel,
+ Code: linux.SI_KERNEL,
}
if a.signal != 0 {
signalInfo.Signo = int32(a.signal)
@@ -249,7 +248,7 @@ func (a *FileAsync) Signal() linux.Signal {
// to send SIGIO.
func (a *FileAsync) SetSignal(signal linux.Signal) error {
if signal != 0 && !signal.IsValid() {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
a.mu.Lock()
defer a.mu.Unlock()
diff --git a/pkg/sentry/kernel/fd_table.go b/pkg/sentry/kernel/fd_table.go
index 62777faa8..8786a70b5 100644
--- a/pkg/sentry/kernel/fd_table.go
+++ b/pkg/sentry/kernel/fd_table.go
@@ -23,12 +23,12 @@ import (
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/fs/lock"
"gvisor.dev/gvisor/pkg/sentry/limits"
"gvisor.dev/gvisor/pkg/sentry/vfs"
"gvisor.dev/gvisor/pkg/sync"
- "gvisor.dev/gvisor/pkg/syserror"
)
// FDFlags define flags for an individual descriptor.
@@ -156,7 +156,7 @@ func (f *FDTable) dropVFS2(ctx context.Context, file *vfs.FileDescription) {
// Release any POSIX lock possibly held by the FDTable.
if file.SupportsLocks() {
err := file.UnlockPOSIX(ctx, f, lock.LockRange{0, lock.LockEOF})
- if err != nil && err != syserror.ENOLCK {
+ if err != nil && !linuxerr.Equals(linuxerr.ENOLCK, err) {
panic(fmt.Sprintf("UnlockPOSIX failed: %v", err))
}
}
diff --git a/pkg/sentry/kernel/futex/BUILD b/pkg/sentry/kernel/futex/BUILD
index a75686cf3..0606d32a8 100644
--- a/pkg/sentry/kernel/futex/BUILD
+++ b/pkg/sentry/kernel/futex/BUILD
@@ -8,7 +8,7 @@ go_template_instance(
out = "atomicptr_bucket_unsafe.go",
package = "futex",
suffix = "Bucket",
- template = "//pkg/sync:generic_atomicptr",
+ template = "//pkg/sync/atomicptr:generic_atomicptr",
types = {
"Value": "bucket",
},
@@ -37,6 +37,7 @@ go_library(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/hostarch",
"//pkg/log",
"//pkg/sentry/memmap",
diff --git a/pkg/sentry/kernel/futex/futex.go b/pkg/sentry/kernel/futex/futex.go
index 0427cf3f4..5c64ce11e 100644
--- a/pkg/sentry/kernel/futex/futex.go
+++ b/pkg/sentry/kernel/futex/futex.go
@@ -20,6 +20,7 @@ package futex
import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/memmap"
"gvisor.dev/gvisor/pkg/sync"
@@ -332,7 +333,7 @@ func getKey(t Target, addr hostarch.Addr, private bool) (Key, error) {
// Ensure the address is aligned.
// It must be a DWORD boundary.
if addr&0x3 != 0 {
- return Key{}, syserror.EINVAL
+ return Key{}, linuxerr.EINVAL
}
if private {
return Key{Kind: KindPrivate, Offset: uint64(addr)}, nil
@@ -790,7 +791,7 @@ func (m *Manager) unlockPILocked(t Target, addr hostarch.Addr, tid uint32, b *bu
return err
}
if prev != cur {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
b.wakeWaiterLocked(next)
diff --git a/pkg/sentry/kernel/kcov.go b/pkg/sentry/kernel/kcov.go
index 4b943106b..941cc373f 100644
--- a/pkg/sentry/kernel/kcov.go
+++ b/pkg/sentry/kernel/kcov.go
@@ -22,6 +22,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/coverage"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/safemem"
"gvisor.dev/gvisor/pkg/sentry/memmap"
@@ -131,13 +132,13 @@ func (kcov *Kcov) InitTrace(size uint64) error {
// To simplify all the logic around mapping, we require that the length of the
// shared region is a multiple of the system page size.
if (8*size)&(hostarch.PageSize-1) != 0 {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
// We need space for at least two uint64s to hold current position and a
// single PC.
if size < 2 || size > kcovAreaSizeMax {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
kcov.size = size
@@ -157,7 +158,7 @@ func (kcov *Kcov) EnableTrace(ctx context.Context, traceKind uint8) error {
// KCOV_ENABLE must be preceded by KCOV_INIT_TRACE and an mmap call.
if kcov.mode != linux.KCOV_MODE_INIT || kcov.mappable == nil {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
switch traceKind {
@@ -167,7 +168,7 @@ func (kcov *Kcov) EnableTrace(ctx context.Context, traceKind uint8) error {
// We do not support KCOV_MODE_TRACE_CMP.
return syserror.ENOTSUP
default:
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if kcov.owningTask != nil && kcov.owningTask != t {
@@ -195,7 +196,7 @@ func (kcov *Kcov) DisableTrace(ctx context.Context) error {
}
if t != kcov.owningTask {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
kcov.mode = linux.KCOV_MODE_INIT
kcov.owningTask = nil
@@ -237,7 +238,7 @@ func (kcov *Kcov) ConfigureMMap(ctx context.Context, opts *memmap.MMapOpts) erro
defer kcov.mu.Unlock()
if kcov.mode != linux.KCOV_MODE_INIT {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if kcov.mappable == nil {
diff --git a/pkg/sentry/kernel/kernel.go b/pkg/sentry/kernel/kernel.go
index e6e9da898..352c36ba9 100644
--- a/pkg/sentry/kernel/kernel.go
+++ b/pkg/sentry/kernel/kernel.go
@@ -143,12 +143,6 @@ type Kernel struct {
// to CreateProcess, and is protected by extMu.
globalInit *ThreadGroup
- // realtimeClock is a ktime.Clock based on timekeeper's Realtime.
- realtimeClock *timekeeperClock
-
- // monotonicClock is a ktime.Clock based on timekeeper's Monotonic.
- monotonicClock *timekeeperClock
-
// syslog is the kernel log.
syslog syslog
@@ -354,19 +348,19 @@ type InitKernelArgs struct {
// before calling Init.
func (k *Kernel) Init(args InitKernelArgs) error {
if args.FeatureSet == nil {
- return fmt.Errorf("FeatureSet is nil")
+ return fmt.Errorf("args.FeatureSet is nil")
}
if args.Timekeeper == nil {
- return fmt.Errorf("Timekeeper is nil")
+ return fmt.Errorf("args.Timekeeper is nil")
}
if args.Timekeeper.clocks == nil {
return fmt.Errorf("must call Timekeeper.SetClocks() before Kernel.Init()")
}
if args.RootUserNamespace == nil {
- return fmt.Errorf("RootUserNamespace is nil")
+ return fmt.Errorf("args.RootUserNamespace is nil")
}
if args.ApplicationCores == 0 {
- return fmt.Errorf("ApplicationCores is 0")
+ return fmt.Errorf("args.ApplicationCores is 0")
}
k.featureSet = args.FeatureSet
@@ -395,8 +389,6 @@ func (k *Kernel) Init(args InitKernelArgs) error {
}
k.extraAuxv = args.ExtraAuxv
k.vdso = args.Vdso
- k.realtimeClock = &timekeeperClock{tk: args.Timekeeper, c: sentrytime.Realtime}
- k.monotonicClock = &timekeeperClock{tk: args.Timekeeper, c: sentrytime.Monotonic}
k.futexes = futex.NewManager()
k.netlinkPorts = port.New()
k.ptraceExceptions = make(map[*Task]*Task)
@@ -529,6 +521,8 @@ func (k *Kernel) SaveTo(ctx context.Context, w wire.Writer) error {
}
log.Infof("CPUID save took [%s].", time.Since(cpuidStart))
+ // Save the timekeeper's state.
+
// Save the kernel state.
kernelStart := time.Now()
stats, err := state.Save(ctx, w, k)
@@ -654,12 +648,12 @@ func (k *Kernel) invalidateUnsavableMappings(ctx context.Context) error {
defer k.tasks.mu.RUnlock()
for t := range k.tasks.Root.tids {
// We can skip locking Task.mu here since the kernel is paused.
- if mm := t.image.MemoryManager; mm != nil {
- if _, ok := invalidated[mm]; !ok {
- if err := mm.InvalidateUnsavable(ctx); err != nil {
+ if memMgr := t.image.MemoryManager; memMgr != nil {
+ if _, ok := invalidated[memMgr]; !ok {
+ if err := memMgr.InvalidateUnsavable(ctx); err != nil {
return err
}
- invalidated[mm] = struct{}{}
+ invalidated[memMgr] = struct{}{}
}
}
// I really wish we just had a sync.Map of all MMs...
@@ -673,7 +667,7 @@ func (k *Kernel) invalidateUnsavableMappings(ctx context.Context) error {
}
// LoadFrom returns a new Kernel loaded from args.
-func (k *Kernel) LoadFrom(ctx context.Context, r wire.Reader, net inet.Stack, clocks sentrytime.Clocks, vfsOpts *vfs.CompleteRestoreOptions) error {
+func (k *Kernel) LoadFrom(ctx context.Context, r wire.Reader, timeReady chan struct{}, net inet.Stack, clocks sentrytime.Clocks, vfsOpts *vfs.CompleteRestoreOptions) error {
loadStart := time.Now()
initAppCores := k.applicationCores
@@ -720,6 +714,11 @@ func (k *Kernel) LoadFrom(ctx context.Context, r wire.Reader, net inet.Stack, cl
log.Infof("Overall load took [%s]", time.Since(loadStart))
k.Timekeeper().SetClocks(clocks)
+
+ if timeReady != nil {
+ close(timeReady)
+ }
+
if net != nil {
net.Resume()
}
@@ -1101,7 +1100,7 @@ func (k *Kernel) Start() error {
}
k.started = true
- k.cpuClockTicker = ktime.NewTimer(k.monotonicClock, newKernelCPUClockTicker(k))
+ k.cpuClockTicker = ktime.NewTimer(k.timekeeper.monotonicClock, newKernelCPUClockTicker(k))
k.cpuClockTicker.Swap(ktime.Setting{
Enabled: true,
Period: linux.ClockTick,
@@ -1256,7 +1255,7 @@ func (k *Kernel) incRunningTasks() {
// These cause very different value of cpuClock. But again, since
// nothing was running while the ticker was disabled, those differences
// don't matter.
- setting, exp := k.cpuClockTickerSetting.At(k.monotonicClock.Now())
+ setting, exp := k.cpuClockTickerSetting.At(k.timekeeper.monotonicClock.Now())
if exp > 0 {
atomic.AddUint64(&k.cpuClock, exp)
}
@@ -1339,7 +1338,7 @@ func (k *Kernel) Unpause() {
// context is used only for debugging to describe how the signal was received.
//
// Preconditions: Kernel must have an init process.
-func (k *Kernel) SendExternalSignal(info *arch.SignalInfo, context string) {
+func (k *Kernel) SendExternalSignal(info *linux.SignalInfo, context string) {
k.extMu.Lock()
defer k.extMu.Unlock()
k.sendExternalSignal(info, context)
@@ -1347,7 +1346,7 @@ func (k *Kernel) SendExternalSignal(info *arch.SignalInfo, context string) {
// SendExternalSignalThreadGroup injects a signal into an specific ThreadGroup.
// This function doesn't skip signals like SendExternalSignal does.
-func (k *Kernel) SendExternalSignalThreadGroup(tg *ThreadGroup, info *arch.SignalInfo) error {
+func (k *Kernel) SendExternalSignalThreadGroup(tg *ThreadGroup, info *linux.SignalInfo) error {
k.extMu.Lock()
defer k.extMu.Unlock()
return tg.SendSignal(info)
@@ -1355,7 +1354,7 @@ func (k *Kernel) SendExternalSignalThreadGroup(tg *ThreadGroup, info *arch.Signa
// SendContainerSignal sends the given signal to all processes inside the
// namespace that match the given container ID.
-func (k *Kernel) SendContainerSignal(cid string, info *arch.SignalInfo) error {
+func (k *Kernel) SendContainerSignal(cid string, info *linux.SignalInfo) error {
k.extMu.Lock()
defer k.extMu.Unlock()
k.tasks.mu.RLock()
@@ -1466,12 +1465,12 @@ func (k *Kernel) ApplicationCores() uint {
// RealtimeClock returns the application CLOCK_REALTIME clock.
func (k *Kernel) RealtimeClock() ktime.Clock {
- return k.realtimeClock
+ return k.timekeeper.realtimeClock
}
// MonotonicClock returns the application CLOCK_MONOTONIC clock.
func (k *Kernel) MonotonicClock() ktime.Clock {
- return k.monotonicClock
+ return k.timekeeper.monotonicClock
}
// CPUClockNow returns the current value of k.cpuClock.
@@ -1551,31 +1550,6 @@ func (k *Kernel) SetSaveError(err error) {
}
}
-var _ tcpip.Clock = (*Kernel)(nil)
-
-// NowNanoseconds implements tcpip.Clock.NowNanoseconds.
-func (k *Kernel) NowNanoseconds() int64 {
- now, err := k.timekeeper.GetTime(sentrytime.Realtime)
- if err != nil {
- panic("Kernel.NowNanoseconds: " + err.Error())
- }
- return now
-}
-
-// NowMonotonic implements tcpip.Clock.NowMonotonic.
-func (k *Kernel) NowMonotonic() int64 {
- now, err := k.timekeeper.GetTime(sentrytime.Monotonic)
- if err != nil {
- panic("Kernel.NowMonotonic: " + err.Error())
- }
- return now
-}
-
-// AfterFunc implements tcpip.Clock.AfterFunc.
-func (k *Kernel) AfterFunc(d time.Duration, f func()) tcpip.Timer {
- return ktime.TcpipAfterFunc(k.realtimeClock, d, f)
-}
-
// SetMemoryFile sets Kernel.mf. SetMemoryFile must be called before Init or
// LoadFrom.
func (k *Kernel) SetMemoryFile(mf *pgalloc.MemoryFile) {
@@ -1783,7 +1757,7 @@ func (k *Kernel) EmitUnimplementedEvent(ctx context.Context) {
})
t := TaskFromContext(ctx)
- k.unimplementedSyscallEmitter.Emit(&uspb.UnimplementedSyscall{
+ _, _ = k.unimplementedSyscallEmitter.Emit(&uspb.UnimplementedSyscall{
Tid: int32(t.ThreadID()),
Registers: t.Arch().StateData().Proto(),
})
@@ -1858,7 +1832,9 @@ func (k *Kernel) PopulateNewCgroupHierarchy(root Cgroup) {
return
}
t.mu.Lock()
- t.enterCgroupLocked(root)
+ // A task can be in the cgroup if it has been created after the
+ // cgroup hierarchy was registered.
+ t.enterCgroupIfNotYetLocked(root)
t.mu.Unlock()
})
k.tasks.mu.RUnlock()
@@ -1874,7 +1850,7 @@ func (k *Kernel) ReleaseCgroupHierarchy(hid uint32) {
return
}
t.mu.Lock()
- for cg, _ := range t.cgroups {
+ for cg := range t.cgroups {
if cg.HierarchyID() == hid {
t.leaveCgroupLocked(cg)
}
diff --git a/pkg/sentry/kernel/pending_signals.go b/pkg/sentry/kernel/pending_signals.go
index 77a35b788..af455c434 100644
--- a/pkg/sentry/kernel/pending_signals.go
+++ b/pkg/sentry/kernel/pending_signals.go
@@ -17,7 +17,6 @@ package kernel
import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/bits"
- "gvisor.dev/gvisor/pkg/sentry/arch"
)
const (
@@ -65,7 +64,7 @@ type pendingSignalQueue struct {
type pendingSignal struct {
// pendingSignalEntry links into a pendingSignalList.
pendingSignalEntry
- *arch.SignalInfo
+ *linux.SignalInfo
// If timer is not nil, it is the IntervalTimer which sent this signal.
timer *IntervalTimer
@@ -75,7 +74,7 @@ type pendingSignal struct {
// on failure (if the given signal's queue is full).
//
// Preconditions: info represents a valid signal.
-func (p *pendingSignals) enqueue(info *arch.SignalInfo, timer *IntervalTimer) bool {
+func (p *pendingSignals) enqueue(info *linux.SignalInfo, timer *IntervalTimer) bool {
sig := linux.Signal(info.Signo)
q := &p.signals[sig.Index()]
if sig.IsStandard() {
@@ -93,7 +92,7 @@ func (p *pendingSignals) enqueue(info *arch.SignalInfo, timer *IntervalTimer) bo
// dequeue dequeues and returns any pending signal not masked by mask. If no
// unmasked signals are pending, dequeue returns nil.
-func (p *pendingSignals) dequeue(mask linux.SignalSet) *arch.SignalInfo {
+func (p *pendingSignals) dequeue(mask linux.SignalSet) *linux.SignalInfo {
// "Real-time signals are delivered in a guaranteed order. Multiple
// real-time signals of the same type are delivered in the order they were
// sent. If different real-time signals are sent to a process, they are
@@ -111,7 +110,7 @@ func (p *pendingSignals) dequeue(mask linux.SignalSet) *arch.SignalInfo {
return p.dequeueSpecific(linux.Signal(lowestPendingUnblockedBit + 1))
}
-func (p *pendingSignals) dequeueSpecific(sig linux.Signal) *arch.SignalInfo {
+func (p *pendingSignals) dequeueSpecific(sig linux.Signal) *linux.SignalInfo {
q := &p.signals[sig.Index()]
ps := q.pendingSignalList.Front()
if ps == nil {
diff --git a/pkg/sentry/kernel/pending_signals_state.go b/pkg/sentry/kernel/pending_signals_state.go
index ca8b4e164..e77f1a254 100644
--- a/pkg/sentry/kernel/pending_signals_state.go
+++ b/pkg/sentry/kernel/pending_signals_state.go
@@ -14,13 +14,11 @@
package kernel
-import (
- "gvisor.dev/gvisor/pkg/sentry/arch"
-)
+import "gvisor.dev/gvisor/pkg/abi/linux"
// +stateify savable
type savedPendingSignal struct {
- si *arch.SignalInfo
+ si *linux.SignalInfo
timer *IntervalTimer
}
diff --git a/pkg/sentry/kernel/pipe/BUILD b/pkg/sentry/kernel/pipe/BUILD
index 34c617b08..94ebac7c5 100644
--- a/pkg/sentry/kernel/pipe/BUILD
+++ b/pkg/sentry/kernel/pipe/BUILD
@@ -21,6 +21,7 @@ go_library(
"//pkg/abi/linux",
"//pkg/amutex",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/hostarch",
"//pkg/marshal/primitive",
"//pkg/safemem",
@@ -47,6 +48,7 @@ go_test(
library = ":pipe",
deps = [
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/sentry/contexttest",
"//pkg/sentry/fs",
"//pkg/syserror",
diff --git a/pkg/sentry/kernel/pipe/node.go b/pkg/sentry/kernel/pipe/node.go
index 6497dc4ba..2321d26dc 100644
--- a/pkg/sentry/kernel/pipe/node.go
+++ b/pkg/sentry/kernel/pipe/node.go
@@ -17,6 +17,7 @@ package pipe
import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/fs/fsutil"
"gvisor.dev/gvisor/pkg/sync"
@@ -130,7 +131,7 @@ func (i *inodeOperations) GetFile(ctx context.Context, d *fs.Dirent, flags fs.Fi
return rw, nil
default:
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
}
diff --git a/pkg/sentry/kernel/pipe/node_test.go b/pkg/sentry/kernel/pipe/node_test.go
index d6fb0fdb8..d25cf658e 100644
--- a/pkg/sentry/kernel/pipe/node_test.go
+++ b/pkg/sentry/kernel/pipe/node_test.go
@@ -19,6 +19,7 @@ import (
"time"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/contexttest"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/syserror"
@@ -258,7 +259,7 @@ func TestNonblockingWriteOpenFileNoReaders(t *testing.T) {
ctx := newSleeperContext(t)
f := NewInodeOperations(ctx, perms, newNamedPipe(t))
- if _, err := testOpen(ctx, t, f, fs.FileFlags{Write: true, NonBlocking: true}, nil); err != syserror.ENXIO {
+ if _, err := testOpen(ctx, t, f, fs.FileFlags{Write: true, NonBlocking: true}, nil); !linuxerr.Equals(linuxerr.ENXIO, err) {
t.Fatalf("Nonblocking open for write failed unexpected error %v.", err)
}
}
diff --git a/pkg/sentry/kernel/pipe/pipe.go b/pkg/sentry/kernel/pipe/pipe.go
index 06769931a..979ea10bf 100644
--- a/pkg/sentry/kernel/pipe/pipe.go
+++ b/pkg/sentry/kernel/pipe/pipe.go
@@ -22,6 +22,7 @@ import (
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/safemem"
"gvisor.dev/gvisor/pkg/sentry/fs"
@@ -428,7 +429,7 @@ func (p *Pipe) FifoSize(context.Context, *fs.File) (int64, error) {
// SetFifoSize implements fs.FifoSizer.SetFifoSize.
func (p *Pipe) SetFifoSize(size int64) (int64, error) {
if size < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
if size < MinimumPipeSize {
size = MinimumPipeSize // Per spec.
diff --git a/pkg/sentry/kernel/pipe/pipe_util.go b/pkg/sentry/kernel/pipe/pipe_util.go
index 2d89b9ccd..3fa5d1d2f 100644
--- a/pkg/sentry/kernel/pipe/pipe_util.go
+++ b/pkg/sentry/kernel/pipe/pipe_util.go
@@ -86,6 +86,12 @@ func (p *Pipe) Write(ctx context.Context, src usermem.IOSequence) (int64, error)
if n > 0 {
p.Notify(waiter.ReadableEvents)
}
+ if err == unix.EPIPE {
+ // If we are returning EPIPE send SIGPIPE to the task.
+ if sendSig := linux.SignalNoInfoFuncFromContext(ctx); sendSig != nil {
+ sendSig(linux.SIGPIPE)
+ }
+ }
return n, err
}
@@ -129,7 +135,7 @@ func (p *Pipe) Ioctl(ctx context.Context, io usermem.IO, args arch.SyscallArgume
v = math.MaxInt32 // Silently truncate.
}
// Copy result to userspace.
- iocc := primitive.IOCopyContext{
+ iocc := usermem.IOCopyContext{
IO: io,
Ctx: ctx,
Opts: usermem.IOOpts{
diff --git a/pkg/sentry/kernel/pipe/vfs.go b/pkg/sentry/kernel/pipe/vfs.go
index 95b948edb..623375417 100644
--- a/pkg/sentry/kernel/pipe/vfs.go
+++ b/pkg/sentry/kernel/pipe/vfs.go
@@ -17,6 +17,7 @@ package pipe
import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/safemem"
"gvisor.dev/gvisor/pkg/sentry/arch"
@@ -90,7 +91,7 @@ func (vp *VFSPipe) Open(ctx context.Context, mnt *vfs.Mount, vfsd *vfs.Dentry, s
readable := vfs.MayReadFileWithOpenFlags(statusFlags)
writable := vfs.MayWriteFileWithOpenFlags(statusFlags)
if !readable && !writable {
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
fd, err := vp.newFD(mnt, vfsd, statusFlags, locks)
@@ -415,7 +416,7 @@ func Tee(ctx context.Context, dst, src *VFSPipeFD, count int64) (int64, error) {
// Preconditions: count > 0.
func spliceOrTee(ctx context.Context, dst, src *VFSPipeFD, count int64, removeFromSrc bool) (int64, error) {
if dst.pipe == src.pipe {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
lockTwoPipes(dst.pipe, src.pipe)
diff --git a/pkg/sentry/kernel/posixtimer.go b/pkg/sentry/kernel/posixtimer.go
index 2e861a5a8..049cc07df 100644
--- a/pkg/sentry/kernel/posixtimer.go
+++ b/pkg/sentry/kernel/posixtimer.go
@@ -18,7 +18,7 @@ import (
"math"
"gvisor.dev/gvisor/pkg/abi/linux"
- "gvisor.dev/gvisor/pkg/sentry/arch"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
ktime "gvisor.dev/gvisor/pkg/sentry/kernel/time"
"gvisor.dev/gvisor/pkg/syserror"
)
@@ -97,7 +97,7 @@ func (it *IntervalTimer) ResumeTimer() {
}
// Preconditions: it.target's signal mutex must be locked.
-func (it *IntervalTimer) updateDequeuedSignalLocked(si *arch.SignalInfo) {
+func (it *IntervalTimer) updateDequeuedSignalLocked(si *linux.SignalInfo) {
it.sigpending = false
if it.sigorphan {
return
@@ -138,9 +138,9 @@ func (it *IntervalTimer) Notify(exp uint64, setting ktime.Setting) (ktime.Settin
it.sigpending = true
it.sigorphan = false
it.overrunCur += exp - 1
- si := &arch.SignalInfo{
+ si := &linux.SignalInfo{
Signo: int32(it.signo),
- Code: arch.SignalInfoTimer,
+ Code: linux.SI_TIMER,
}
si.SetTimerID(it.id)
si.SetSigval(it.sigval)
@@ -215,16 +215,16 @@ func (t *Task) IntervalTimerCreate(c ktime.Clock, sigev *linux.Sigevent) (linux.
target, ok := t.tg.pidns.tasks[ThreadID(sigev.Tid)]
t.tg.pidns.owner.mu.RUnlock()
if !ok || target.tg != t.tg {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
it.target = target
default:
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
if sigev.Notify != linux.SIGEV_NONE {
it.signo = linux.Signal(sigev.Signo)
if !it.signo.IsValid() {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
}
it.timer = ktime.NewTimer(c, it)
@@ -239,7 +239,7 @@ func (t *Task) IntervalTimerDelete(id linux.TimerID) error {
defer t.tg.timerMu.Unlock()
it := t.tg.timers[id]
if it == nil {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
delete(t.tg.timers, id)
it.DestroyTimer()
@@ -252,7 +252,7 @@ func (t *Task) IntervalTimerSettime(id linux.TimerID, its linux.Itimerspec, abs
defer t.tg.timerMu.Unlock()
it := t.tg.timers[id]
if it == nil {
- return linux.Itimerspec{}, syserror.EINVAL
+ return linux.Itimerspec{}, linuxerr.EINVAL
}
newS, err := ktime.SettingFromItimerspec(its, abs, it.timer.Clock())
@@ -270,7 +270,7 @@ func (t *Task) IntervalTimerGettime(id linux.TimerID) (linux.Itimerspec, error)
defer t.tg.timerMu.Unlock()
it := t.tg.timers[id]
if it == nil {
- return linux.Itimerspec{}, syserror.EINVAL
+ return linux.Itimerspec{}, linuxerr.EINVAL
}
tm, s := it.timer.Get()
@@ -286,7 +286,7 @@ func (t *Task) IntervalTimerGetoverrun(id linux.TimerID) (int32, error) {
defer t.tg.timerMu.Unlock()
it := t.tg.timers[id]
if it == nil {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// By timer_create(2) invariant, either it.target == nil (in which case
// it.overrunLast is immutably 0) or t.tg == it.target.tg; and the fact
diff --git a/pkg/sentry/kernel/ptrace.go b/pkg/sentry/kernel/ptrace.go
index 57c7659e7..1c6100efe 100644
--- a/pkg/sentry/kernel/ptrace.go
+++ b/pkg/sentry/kernel/ptrace.go
@@ -19,9 +19,9 @@ import (
"sync/atomic"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/marshal/primitive"
- "gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/mm"
"gvisor.dev/gvisor/pkg/syserror"
"gvisor.dev/gvisor/pkg/usermem"
@@ -295,7 +295,7 @@ func (t *Task) isYAMADescendantOfLocked(ancestor *Task) bool {
// Precondition: the TaskSet mutex must be locked (for reading or writing).
func (t *Task) hasYAMAExceptionForLocked(tracer *Task) bool {
- allowed, ok := t.k.ptraceExceptions[t]
+ allowed, ok := t.k.ptraceExceptions[t.tg.leader]
if !ok {
return false
}
@@ -394,7 +394,7 @@ func (t *Task) ptraceTrapLocked(code int32) {
t.trapStopPending = false
t.tg.signalHandlers.mu.Unlock()
t.ptraceCode = code
- t.ptraceSiginfo = &arch.SignalInfo{
+ t.ptraceSiginfo = &linux.SignalInfo{
Signo: int32(linux.SIGTRAP),
Code: code,
}
@@ -402,7 +402,7 @@ func (t *Task) ptraceTrapLocked(code int32) {
t.ptraceSiginfo.SetUID(int32(t.Credentials().RealKUID.In(t.UserNamespace()).OrOverflow()))
if t.beginPtraceStopLocked() {
tracer := t.Tracer()
- tracer.signalStop(t, arch.CLD_TRAPPED, int32(linux.SIGTRAP))
+ tracer.signalStop(t, linux.CLD_TRAPPED, int32(linux.SIGTRAP))
tracer.tg.eventQueue.Notify(EventTraceeStop)
}
}
@@ -542,9 +542,9 @@ func (t *Task) ptraceAttach(target *Task, seize bool, opts uintptr) error {
// "Unlike PTRACE_ATTACH, PTRACE_SEIZE does not stop the process." -
// ptrace(2)
if !seize {
- target.sendSignalLocked(&arch.SignalInfo{
+ target.sendSignalLocked(&linux.SignalInfo{
Signo: int32(linux.SIGSTOP),
- Code: arch.SignalInfoUser,
+ Code: linux.SI_USER,
}, false /* group */)
}
// Undocumented Linux feature: If the tracee is already group-stopped (and
@@ -586,7 +586,7 @@ func (t *Task) exitPtrace() {
for target := range t.ptraceTracees {
if target.ptraceOpts.ExitKill {
target.tg.signalHandlers.mu.Lock()
- target.sendSignalLocked(&arch.SignalInfo{
+ target.sendSignalLocked(&linux.SignalInfo{
Signo: int32(linux.SIGKILL),
}, false /* group */)
target.tg.signalHandlers.mu.Unlock()
@@ -652,7 +652,7 @@ func (t *Task) forgetTracerLocked() {
// Preconditions:
// * The signal mutex must be locked.
// * The caller must be running on the task goroutine.
-func (t *Task) ptraceSignalLocked(info *arch.SignalInfo) bool {
+func (t *Task) ptraceSignalLocked(info *linux.SignalInfo) bool {
if linux.Signal(info.Signo) == linux.SIGKILL {
return false
}
@@ -678,7 +678,7 @@ func (t *Task) ptraceSignalLocked(info *arch.SignalInfo) bool {
t.ptraceSiginfo = info
t.Debugf("Entering signal-delivery-stop for signal %d", info.Signo)
if t.beginPtraceStopLocked() {
- tracer.signalStop(t, arch.CLD_TRAPPED, info.Signo)
+ tracer.signalStop(t, linux.CLD_TRAPPED, info.Signo)
tracer.tg.eventQueue.Notify(EventTraceeStop)
}
return true
@@ -829,7 +829,7 @@ func (t *Task) ptraceClone(kind ptraceCloneKind, child *Task, opts *CloneOptions
if child.ptraceSeized {
child.trapStopPending = true
} else {
- child.pendingSignals.enqueue(&arch.SignalInfo{
+ child.pendingSignals.enqueue(&linux.SignalInfo{
Signo: int32(linux.SIGSTOP),
}, nil)
}
@@ -893,9 +893,9 @@ func (t *Task) ptraceExec(oldTID ThreadID) {
}
t.tg.signalHandlers.mu.Lock()
defer t.tg.signalHandlers.mu.Unlock()
- t.sendSignalLocked(&arch.SignalInfo{
+ t.sendSignalLocked(&linux.SignalInfo{
Signo: int32(linux.SIGTRAP),
- Code: arch.SignalInfoUser,
+ Code: linux.SI_USER,
}, false /* group */)
}
@@ -995,7 +995,7 @@ func (t *Task) ptraceSetOptionsLocked(opts uintptr) error {
linux.PTRACE_O_TRACEVFORK |
linux.PTRACE_O_TRACEVFORKDONE)
if opts&^valid != 0 {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
t.ptraceOpts = ptraceOptions{
ExitKill: opts&linux.PTRACE_O_EXITKILL != 0,
@@ -1222,27 +1222,27 @@ func (t *Task) Ptrace(req int64, pid ThreadID, addr, data hostarch.Addr) error {
t.tg.pidns.owner.mu.RLock()
defer t.tg.pidns.owner.mu.RUnlock()
if target.ptraceSiginfo == nil {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
_, err := target.ptraceSiginfo.CopyOut(t, data)
return err
case linux.PTRACE_SETSIGINFO:
- var info arch.SignalInfo
+ var info linux.SignalInfo
if _, err := info.CopyIn(t, data); err != nil {
return err
}
t.tg.pidns.owner.mu.RLock()
defer t.tg.pidns.owner.mu.RUnlock()
if target.ptraceSiginfo == nil {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
target.ptraceSiginfo = &info
return nil
case linux.PTRACE_GETSIGMASK:
if addr != linux.SignalSetSize {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
mask := target.SignalMask()
_, err := mask.CopyOut(t, data)
@@ -1250,7 +1250,7 @@ func (t *Task) Ptrace(req int64, pid ThreadID, addr, data hostarch.Addr) error {
case linux.PTRACE_SETSIGMASK:
if addr != linux.SignalSetSize {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
var mask linux.SignalSet
if _, err := mask.CopyIn(t, data); err != nil {
diff --git a/pkg/sentry/kernel/rseq.go b/pkg/sentry/kernel/rseq.go
index 4bc5bca44..2344565cd 100644
--- a/pkg/sentry/kernel/rseq.go
+++ b/pkg/sentry/kernel/rseq.go
@@ -18,6 +18,7 @@ import (
"fmt"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/hostcpu"
"gvisor.dev/gvisor/pkg/syserror"
@@ -59,20 +60,20 @@ func (t *Task) RSeqAvailable() bool {
func (t *Task) SetRSeq(addr hostarch.Addr, length, signature uint32) error {
if t.rseqAddr != 0 {
if t.rseqAddr != addr {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if t.rseqSignature != signature {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
return syserror.EBUSY
}
// rseq must be aligned and correctly sized.
if addr&(linux.AlignOfRSeq-1) != 0 {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if length != linux.SizeOfRSeq {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if _, ok := t.MemoryManager().CheckIORange(addr, linux.SizeOfRSeq); !ok {
return syserror.EFAULT
@@ -103,13 +104,13 @@ func (t *Task) SetRSeq(addr hostarch.Addr, length, signature uint32) error {
// Preconditions: The caller must be running on the task goroutine.
func (t *Task) ClearRSeq(addr hostarch.Addr, length, signature uint32) error {
if t.rseqAddr == 0 {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if t.rseqAddr != addr {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if length != linux.SizeOfRSeq {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if t.rseqSignature != signature {
return syserror.EPERM
@@ -152,10 +153,10 @@ func (t *Task) SetOldRSeqCriticalRegion(r OldRSeqCriticalRegion) error {
return nil
}
if r.CriticalSection.Start >= r.CriticalSection.End {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if r.CriticalSection.Contains(r.Restart) {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
// TODO(jamieliu): check that r.CriticalSection and r.Restart are in
// the application address range, for consistency with Linux.
@@ -187,7 +188,7 @@ func (t *Task) SetOldRSeqCPUAddr(addr hostarch.Addr) error {
// unfortunate, but unlikely in a correct program.
if err := t.rseqUpdateCPU(); err != nil {
t.oldRSeqCPUAddr = 0
- return syserror.EINVAL // yes, EINVAL, not err or EFAULT
+ return linuxerr.EINVAL // yes, EINVAL, not err or EFAULT
}
return nil
}
diff --git a/pkg/sentry/kernel/seccomp.go b/pkg/sentry/kernel/seccomp.go
index a95e174a2..54ca43c2e 100644
--- a/pkg/sentry/kernel/seccomp.go
+++ b/pkg/sentry/kernel/seccomp.go
@@ -39,11 +39,11 @@ func dataAsBPFInput(t *Task, d *linux.SeccompData) bpf.Input {
}
}
-func seccompSiginfo(t *Task, errno, sysno int32, ip hostarch.Addr) *arch.SignalInfo {
- si := &arch.SignalInfo{
+func seccompSiginfo(t *Task, errno, sysno int32, ip hostarch.Addr) *linux.SignalInfo {
+ si := &linux.SignalInfo{
Signo: int32(linux.SIGSYS),
Errno: errno,
- Code: arch.SYS_SECCOMP,
+ Code: linux.SYS_SECCOMP,
}
si.SetCallAddr(uint64(ip))
si.SetSyscall(sysno)
diff --git a/pkg/sentry/kernel/semaphore/BUILD b/pkg/sentry/kernel/semaphore/BUILD
index 65e5427c1..a787c00a8 100644
--- a/pkg/sentry/kernel/semaphore/BUILD
+++ b/pkg/sentry/kernel/semaphore/BUILD
@@ -25,6 +25,7 @@ go_library(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/log",
"//pkg/sentry/fs",
"//pkg/sentry/kernel/auth",
diff --git a/pkg/sentry/kernel/semaphore/semaphore.go b/pkg/sentry/kernel/semaphore/semaphore.go
index fe2ab1662..2dbc8353a 100644
--- a/pkg/sentry/kernel/semaphore/semaphore.go
+++ b/pkg/sentry/kernel/semaphore/semaphore.go
@@ -20,6 +20,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
@@ -35,10 +36,10 @@ const (
// Maximum number of semaphore sets.
setsMax = linux.SEMMNI
- // Maximum number of semaphroes in a semaphore set.
+ // Maximum number of semaphores in a semaphore set.
semsMax = linux.SEMMSL
- // Maximum number of semaphores in all semaphroe sets.
+ // Maximum number of semaphores in all semaphore sets.
semsTotalMax = linux.SEMMNS
)
@@ -127,7 +128,7 @@ func NewRegistry(userNS *auth.UserNamespace) *Registry {
// exists.
func (r *Registry) FindOrCreate(ctx context.Context, key, nsems int32, mode linux.FileMode, private, create, exclusive bool) (*Set, error) {
if nsems < 0 || nsems > semsMax {
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
r.mu.Lock()
@@ -147,7 +148,7 @@ func (r *Registry) FindOrCreate(ctx context.Context, key, nsems int32, mode linu
// Validate parameters.
if nsems > int32(set.Size()) {
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
if create && exclusive {
return nil, syserror.EEXIST
@@ -163,7 +164,7 @@ func (r *Registry) FindOrCreate(ctx context.Context, key, nsems int32, mode linu
// Zero is only valid if an existing set is found.
if nsems == 0 {
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
// Apply system limits.
@@ -171,10 +172,10 @@ func (r *Registry) FindOrCreate(ctx context.Context, key, nsems int32, mode linu
// Map semaphores and map indexes in a registry are of the same size,
// check map semaphores only here for the system limit.
if len(r.semaphores) >= setsMax {
- return nil, syserror.EINVAL
+ return nil, syserror.ENOSPC
}
if r.totalSems() > int(semsTotalMax-nsems) {
- return nil, syserror.EINVAL
+ return nil, syserror.ENOSPC
}
// Finally create a new set.
@@ -220,7 +221,7 @@ func (r *Registry) HighestIndex() int32 {
defer r.mu.Unlock()
// By default, highest used index is 0 even though
- // there is no semaphroe set.
+ // there is no semaphore set.
var highestIndex int32
for index := range r.indexes {
if index > highestIndex {
@@ -238,7 +239,7 @@ func (r *Registry) RemoveID(id int32, creds *auth.Credentials) error {
set := r.semaphores[id]
if set == nil {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
index, found := r.findIndexByID(id)
if !found {
@@ -702,7 +703,9 @@ func (s *Set) checkPerms(creds *auth.Credentials, reqPerms fs.PermMask) bool {
return s.checkCapability(creds)
}
-// destroy destroys the set. Caller must hold 's.mu'.
+// destroy destroys the set.
+//
+// Preconditions: Caller must hold 's.mu'.
func (s *Set) destroy() {
// Notify all waiters. They will fail on the next attempt to execute
// operations and return error.
diff --git a/pkg/sentry/kernel/sessions.go b/pkg/sentry/kernel/sessions.go
index 0cd9e2533..973d708a3 100644
--- a/pkg/sentry/kernel/sessions.go
+++ b/pkg/sentry/kernel/sessions.go
@@ -16,7 +16,6 @@ package kernel
import (
"gvisor.dev/gvisor/pkg/abi/linux"
- "gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/syserror"
)
@@ -233,7 +232,7 @@ func (pg *ProcessGroup) Session() *Session {
// SendSignal sends a signal to all processes inside the process group. It is
// analagous to kernel/signal.c:kill_pgrp.
-func (pg *ProcessGroup) SendSignal(info *arch.SignalInfo) error {
+func (pg *ProcessGroup) SendSignal(info *linux.SignalInfo) error {
tasks := pg.originator.TaskSet()
tasks.mu.RLock()
defer tasks.mu.RUnlock()
@@ -370,6 +369,11 @@ func (tg *ThreadGroup) CreateProcessGroup() error {
// Get the ID for this thread in the current namespace.
id := tg.pidns.tgids[tg]
+ // Check whether a process still exists or not.
+ if id == 0 {
+ return syserror.ESRCH
+ }
+
// Per above, check for a Session leader or existing group.
for s := tg.pidns.owner.sessions.Front(); s != nil; s = s.Next() {
if s.leader.pidns != tg.pidns {
diff --git a/pkg/sentry/kernel/shm/BUILD b/pkg/sentry/kernel/shm/BUILD
index 1c3c0794f..5b69333fe 100644
--- a/pkg/sentry/kernel/shm/BUILD
+++ b/pkg/sentry/kernel/shm/BUILD
@@ -28,6 +28,7 @@ go_library(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/hostarch",
"//pkg/log",
"//pkg/refs",
diff --git a/pkg/sentry/kernel/shm/shm.go b/pkg/sentry/kernel/shm/shm.go
index a73f1bdca..7a6e91004 100644
--- a/pkg/sentry/kernel/shm/shm.go
+++ b/pkg/sentry/kernel/shm/shm.go
@@ -38,6 +38,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/sentry/fs"
@@ -145,7 +146,7 @@ func (r *Registry) FindOrCreate(ctx context.Context, pid int32, key Key, size ui
//
// Note that 'private' always implies the creation of a new segment
// whether IPC_CREAT is specified or not.
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
r.mu.Lock()
@@ -175,7 +176,7 @@ func (r *Registry) FindOrCreate(ctx context.Context, pid int32, key Key, size ui
if size > shm.size {
// "A segment for the given key exists, but size is greater than
// the size of that segment." - man shmget(2)
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
if create && exclusive {
@@ -200,7 +201,7 @@ func (r *Registry) FindOrCreate(ctx context.Context, pid int32, key Key, size ui
if val, ok := hostarch.Addr(size).RoundUp(); ok {
sizeAligned = uint64(val)
} else {
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
if numPages := sizeAligned / hostarch.PageSize; r.totalPages+numPages > linux.SHMALL {
@@ -652,7 +653,7 @@ func (s *Shm) Set(ctx context.Context, ds *linux.ShmidDS) error {
uid := creds.UserNamespace.MapToKUID(auth.UID(ds.ShmPerm.UID))
gid := creds.UserNamespace.MapToKGID(auth.GID(ds.ShmPerm.GID))
if !uid.Ok() || !gid.Ok() {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
// User may only modify the lower 9 bits of the mode. All the other bits are
diff --git a/pkg/sentry/kernel/signal.go b/pkg/sentry/kernel/signal.go
index 2488ae7d5..e08474d25 100644
--- a/pkg/sentry/kernel/signal.go
+++ b/pkg/sentry/kernel/signal.go
@@ -19,7 +19,6 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/log"
- "gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/platform"
)
@@ -36,7 +35,7 @@ const SignalPanic = linux.SIGUSR2
// context is used only for debugging to differentiate these cases.
//
// Preconditions: Kernel must have an init process.
-func (k *Kernel) sendExternalSignal(info *arch.SignalInfo, context string) {
+func (k *Kernel) sendExternalSignal(info *linux.SignalInfo, context string) {
switch linux.Signal(info.Signo) {
case linux.SIGURG:
// Sent by the Go 1.14+ runtime for asynchronous goroutine preemption.
@@ -60,18 +59,18 @@ func (k *Kernel) sendExternalSignal(info *arch.SignalInfo, context string) {
}
// SignalInfoPriv returns a SignalInfo equivalent to Linux's SEND_SIG_PRIV.
-func SignalInfoPriv(sig linux.Signal) *arch.SignalInfo {
- return &arch.SignalInfo{
+func SignalInfoPriv(sig linux.Signal) *linux.SignalInfo {
+ return &linux.SignalInfo{
Signo: int32(sig),
- Code: arch.SignalInfoKernel,
+ Code: linux.SI_KERNEL,
}
}
// SignalInfoNoInfo returns a SignalInfo equivalent to Linux's SEND_SIG_NOINFO.
-func SignalInfoNoInfo(sig linux.Signal, sender, receiver *Task) *arch.SignalInfo {
- info := &arch.SignalInfo{
+func SignalInfoNoInfo(sig linux.Signal, sender, receiver *Task) *linux.SignalInfo {
+ info := &linux.SignalInfo{
Signo: int32(sig),
- Code: arch.SignalInfoUser,
+ Code: linux.SI_USER,
}
info.SetPID(int32(receiver.tg.pidns.IDOfThreadGroup(sender.tg)))
info.SetUID(int32(sender.Credentials().RealKUID.In(receiver.UserNamespace()).OrOverflow()))
diff --git a/pkg/sentry/kernel/signal_handlers.go b/pkg/sentry/kernel/signal_handlers.go
index 768fda220..147cc41bb 100644
--- a/pkg/sentry/kernel/signal_handlers.go
+++ b/pkg/sentry/kernel/signal_handlers.go
@@ -16,7 +16,6 @@ package kernel
import (
"gvisor.dev/gvisor/pkg/abi/linux"
- "gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sync"
)
@@ -30,14 +29,14 @@ type SignalHandlers struct {
mu sync.Mutex `state:"nosave"`
// actions is the action to be taken upon receiving each signal.
- actions map[linux.Signal]arch.SignalAct
+ actions map[linux.Signal]linux.SigAction
}
// NewSignalHandlers returns a new SignalHandlers specifying all default
// actions.
func NewSignalHandlers() *SignalHandlers {
return &SignalHandlers{
- actions: make(map[linux.Signal]arch.SignalAct),
+ actions: make(map[linux.Signal]linux.SigAction),
}
}
@@ -59,9 +58,9 @@ func (sh *SignalHandlers) CopyForExec() *SignalHandlers {
sh.mu.Lock()
defer sh.mu.Unlock()
for sig, act := range sh.actions {
- if act.Handler == arch.SignalActIgnore {
- sh2.actions[sig] = arch.SignalAct{
- Handler: arch.SignalActIgnore,
+ if act.Handler == linux.SIG_IGN {
+ sh2.actions[sig] = linux.SigAction{
+ Handler: linux.SIG_IGN,
}
}
}
@@ -73,15 +72,15 @@ func (sh *SignalHandlers) IsIgnored(sig linux.Signal) bool {
sh.mu.Lock()
defer sh.mu.Unlock()
sa, ok := sh.actions[sig]
- return ok && sa.Handler == arch.SignalActIgnore
+ return ok && sa.Handler == linux.SIG_IGN
}
// dequeueActionLocked returns the SignalAct that should be used to handle sig.
//
// Preconditions: sh.mu must be locked.
-func (sh *SignalHandlers) dequeueAction(sig linux.Signal) arch.SignalAct {
+func (sh *SignalHandlers) dequeueAction(sig linux.Signal) linux.SigAction {
act := sh.actions[sig]
- if act.IsResetHandler() {
+ if act.Flags&linux.SA_RESETHAND != 0 {
delete(sh.actions, sig)
}
return act
diff --git a/pkg/sentry/kernel/signalfd/BUILD b/pkg/sentry/kernel/signalfd/BUILD
index 76d472292..1110ecca5 100644
--- a/pkg/sentry/kernel/signalfd/BUILD
+++ b/pkg/sentry/kernel/signalfd/BUILD
@@ -9,6 +9,7 @@ go_library(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/sentry/fs",
"//pkg/sentry/fs/anon",
"//pkg/sentry/fs/fsutil",
diff --git a/pkg/sentry/kernel/signalfd/signalfd.go b/pkg/sentry/kernel/signalfd/signalfd.go
index f58ec4194..47958e2d4 100644
--- a/pkg/sentry/kernel/signalfd/signalfd.go
+++ b/pkg/sentry/kernel/signalfd/signalfd.go
@@ -18,6 +18,7 @@ package signalfd
import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/fs/anon"
"gvisor.dev/gvisor/pkg/sentry/fs/fsutil"
@@ -64,7 +65,7 @@ func New(ctx context.Context, mask linux.SignalSet) (*fs.File, error) {
t := kernel.TaskFromContext(ctx)
if t == nil {
// No task context? Not valid.
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
// name matches fs/signalfd.c:signalfd4.
dirent := fs.NewDirent(ctx, anon.NewInode(ctx), "anon_inode:[signalfd]")
diff --git a/pkg/sentry/kernel/task.go b/pkg/sentry/kernel/task.go
index be1371855..d211e4d82 100644
--- a/pkg/sentry/kernel/task.go
+++ b/pkg/sentry/kernel/task.go
@@ -21,8 +21,8 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/bpf"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
- "gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/inet"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
@@ -33,7 +33,6 @@ import (
"gvisor.dev/gvisor/pkg/sentry/usage"
"gvisor.dev/gvisor/pkg/sentry/vfs"
"gvisor.dev/gvisor/pkg/sync"
- "gvisor.dev/gvisor/pkg/syserror"
"gvisor.dev/gvisor/pkg/waiter"
)
@@ -151,7 +150,7 @@ type Task struct {
// which the SA_ONSTACK flag is set.
//
// signalStack is exclusive to the task goroutine.
- signalStack arch.SignalStack
+ signalStack linux.SignalStack
// signalQueue is a set of registered waiters for signal-related events.
//
@@ -395,7 +394,7 @@ type Task struct {
// ptraceSiginfo is analogous to Linux's task_struct::last_siginfo.
//
// ptraceSiginfo is protected by the TaskSet mutex.
- ptraceSiginfo *arch.SignalInfo
+ ptraceSiginfo *linux.SignalInfo
// ptraceEventMsg is the value set by PTRACE_EVENT stops and returned to
// the tracer by ptrace(PTRACE_GETEVENTMSG).
@@ -847,21 +846,19 @@ func (t *Task) OOMScoreAdj() int32 {
// value should be between -1000 and 1000 inclusive.
func (t *Task) SetOOMScoreAdj(adj int32) error {
if adj > 1000 || adj < -1000 {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
atomic.StoreInt32(&t.tg.oomScoreAdj, adj)
return nil
}
-// UID returns t's uid.
-// TODO(gvisor.dev/issue/170): This method is not namespaced yet.
-func (t *Task) UID() uint32 {
+// KUID returns t's kuid.
+func (t *Task) KUID() uint32 {
return uint32(t.Credentials().EffectiveKUID)
}
-// GID returns t's gid.
-// TODO(gvisor.dev/issue/170): This method is not namespaced yet.
-func (t *Task) GID() uint32 {
+// KGID returns t's kgid.
+func (t *Task) KGID() uint32 {
return uint32(t.Credentials().EffectiveKGID)
}
diff --git a/pkg/sentry/kernel/task_acct.go b/pkg/sentry/kernel/task_acct.go
index e574997f7..dd364ae50 100644
--- a/pkg/sentry/kernel/task_acct.go
+++ b/pkg/sentry/kernel/task_acct.go
@@ -18,10 +18,10 @@ package kernel
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
ktime "gvisor.dev/gvisor/pkg/sentry/kernel/time"
"gvisor.dev/gvisor/pkg/sentry/limits"
"gvisor.dev/gvisor/pkg/sentry/usage"
- "gvisor.dev/gvisor/pkg/syserror"
)
// Getitimer implements getitimer(2).
@@ -44,7 +44,7 @@ func (t *Task) Getitimer(id int32) (linux.ItimerVal, error) {
s, _ = t.tg.itimerProfSetting.At(tm)
t.tg.signalHandlers.mu.Unlock()
default:
- return linux.ItimerVal{}, syserror.EINVAL
+ return linux.ItimerVal{}, linuxerr.EINVAL
}
val, iv := ktime.SpecFromSetting(tm, s)
return linux.ItimerVal{
@@ -105,7 +105,7 @@ func (t *Task) Setitimer(id int32, newitv linux.ItimerVal) (linux.ItimerVal, err
return linux.ItimerVal{}, err
}
default:
- return linux.ItimerVal{}, syserror.EINVAL
+ return linux.ItimerVal{}, linuxerr.EINVAL
}
oldval, oldiv := ktime.SpecFromSetting(tm, olds)
return linux.ItimerVal{
diff --git a/pkg/sentry/kernel/task_block.go b/pkg/sentry/kernel/task_block.go
index ecbe8f920..07533d982 100644
--- a/pkg/sentry/kernel/task_block.go
+++ b/pkg/sentry/kernel/task_block.go
@@ -19,6 +19,7 @@ import (
"runtime/trace"
"time"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
ktime "gvisor.dev/gvisor/pkg/sentry/kernel/time"
"gvisor.dev/gvisor/pkg/sync"
"gvisor.dev/gvisor/pkg/syserror"
@@ -45,7 +46,7 @@ func (t *Task) BlockWithTimeout(C chan struct{}, haveTimeout bool, timeout time.
err := t.BlockWithDeadline(C, true, deadline)
// Timeout, explicitly return a remaining duration of 0.
- if err == syserror.ETIMEDOUT {
+ if linuxerr.Equals(linuxerr.ETIMEDOUT, err) {
return 0, err
}
diff --git a/pkg/sentry/kernel/task_cgroup.go b/pkg/sentry/kernel/task_cgroup.go
index 25d2504fa..7c138e80f 100644
--- a/pkg/sentry/kernel/task_cgroup.go
+++ b/pkg/sentry/kernel/task_cgroup.go
@@ -85,6 +85,14 @@ func (t *Task) enterCgroupLocked(c Cgroup) {
c.Enter(t)
}
+// +checklocks:t.mu
+func (t *Task) enterCgroupIfNotYetLocked(c Cgroup) {
+ if _, ok := t.cgroups[c]; ok {
+ return
+ }
+ t.enterCgroupLocked(c)
+}
+
// LeaveCgroups removes t out from all its cgroups.
func (t *Task) LeaveCgroups() {
t.mu.Lock()
diff --git a/pkg/sentry/kernel/task_clone.go b/pkg/sentry/kernel/task_clone.go
index 405771f3f..76fb0e2cb 100644
--- a/pkg/sentry/kernel/task_clone.go
+++ b/pkg/sentry/kernel/task_clone.go
@@ -20,6 +20,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/bpf"
"gvisor.dev/gvisor/pkg/cleanup"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/inet"
"gvisor.dev/gvisor/pkg/syserror"
@@ -142,25 +143,25 @@ func (t *Task) Clone(opts *CloneOptions) (ThreadID, *SyscallControl, error) {
// address, any set of signal handlers must refer to the same address
// space.
if !opts.NewSignalHandlers && opts.NewAddressSpace {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// In order for the behavior of thread-group-directed signals to be sane,
// all tasks in a thread group must share signal handlers.
if !opts.NewThreadGroup && opts.NewSignalHandlers {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// All tasks in a thread group must be in the same PID namespace.
if !opts.NewThreadGroup && (opts.NewPIDNamespace || t.childPIDNamespace != nil) {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// The two different ways of specifying a new PID namespace are
// incompatible.
if opts.NewPIDNamespace && t.childPIDNamespace != nil {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Thread groups and FS contexts cannot span user namespaces.
if opts.NewUserNamespace && (!opts.NewThreadGroup || !opts.NewFSContext) {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Pull task registers and FPU state, a cloned task will inherit the
@@ -463,14 +464,14 @@ func (t *Task) Unshare(opts *SharingOptions) error {
// sense that clone(2) allows a task to share signal handlers and address
// spaces with tasks in other thread groups.
if opts.NewAddressSpace || opts.NewSignalHandlers {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
creds := t.Credentials()
if opts.NewThreadGroup {
t.tg.signalHandlers.mu.Lock()
if t.tg.tasksCount != 1 {
t.tg.signalHandlers.mu.Unlock()
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
t.tg.signalHandlers.mu.Unlock()
// This isn't racy because we're the only living task, and therefore
diff --git a/pkg/sentry/kernel/task_context.go b/pkg/sentry/kernel/task_context.go
index 70b0699dc..c82d9e82b 100644
--- a/pkg/sentry/kernel/task_context.go
+++ b/pkg/sentry/kernel/task_context.go
@@ -17,6 +17,7 @@ package kernel
import (
"time"
+ "gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/sentry/fs"
@@ -113,6 +114,10 @@ func (t *Task) contextValue(key interface{}, isTaskGoroutine bool) interface{} {
return t.k.RealtimeClock()
case limits.CtxLimits:
return t.tg.limits
+ case linux.CtxSignalNoInfoFunc:
+ return func(sig linux.Signal) error {
+ return t.SendSignal(SignalInfoNoInfo(sig, t, t))
+ }
case pgalloc.CtxMemoryFile:
return t.k.mf
case pgalloc.CtxMemoryFileProvider:
diff --git a/pkg/sentry/kernel/task_exec.go b/pkg/sentry/kernel/task_exec.go
index d9897e802..cf8571262 100644
--- a/pkg/sentry/kernel/task_exec.go
+++ b/pkg/sentry/kernel/task_exec.go
@@ -66,7 +66,6 @@ package kernel
import (
"gvisor.dev/gvisor/pkg/abi/linux"
- "gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/mm"
"gvisor.dev/gvisor/pkg/sentry/vfs"
@@ -181,7 +180,7 @@ func (r *runSyscallAfterExecStop) execute(t *Task) taskRunState {
t.tg.signalHandlers = t.tg.signalHandlers.CopyForExec()
t.endStopCond.L = &t.tg.signalHandlers.mu
// "Any alternate signal stack is not preserved (sigaltstack(2))." - execve(2)
- t.signalStack = arch.SignalStack{Flags: arch.SignalStackFlagDisable}
+ t.signalStack = linux.SignalStack{Flags: linux.SS_DISABLE}
// "The termination signal is reset to SIGCHLD (see clone(2))."
t.tg.terminationSignal = linux.SIGCHLD
// execed indicates that the process can no longer join a process group
diff --git a/pkg/sentry/kernel/task_exit.go b/pkg/sentry/kernel/task_exit.go
index b1af1a7ef..d115b8783 100644
--- a/pkg/sentry/kernel/task_exit.go
+++ b/pkg/sentry/kernel/task_exit.go
@@ -28,9 +28,9 @@ import (
"errors"
"fmt"
"strconv"
+ "strings"
"gvisor.dev/gvisor/pkg/abi/linux"
- "gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/syserror"
"gvisor.dev/gvisor/pkg/waiter"
@@ -50,6 +50,23 @@ type ExitStatus struct {
Signo int
}
+func (es ExitStatus) String() string {
+ var b strings.Builder
+ if code := es.Code; code != 0 {
+ if b.Len() != 0 {
+ b.WriteByte(' ')
+ }
+ _, _ = fmt.Fprintf(&b, "Code=%d", code)
+ }
+ if signal := es.Signo; signal != 0 {
+ if b.Len() != 0 {
+ b.WriteByte(' ')
+ }
+ _, _ = fmt.Fprintf(&b, "Signal=%d", signal)
+ }
+ return b.String()
+}
+
// Signaled returns true if the ExitStatus indicates that the exiting task or
// thread group was killed by a signal.
func (es ExitStatus) Signaled() bool {
@@ -122,12 +139,12 @@ func (t *Task) killLocked() {
if t.stop != nil && t.stop.Killable() {
t.endInternalStopLocked()
}
- t.pendingSignals.enqueue(&arch.SignalInfo{
+ t.pendingSignals.enqueue(&linux.SignalInfo{
Signo: int32(linux.SIGKILL),
// Linux just sets SIGKILL in the pending signal bitmask without
// enqueueing an actual siginfo, such that
// kernel/signal.c:collect_signal() initializes si_code to SI_USER.
- Code: arch.SignalInfoUser,
+ Code: linux.SI_USER,
}, nil)
t.interrupt()
}
@@ -332,7 +349,7 @@ func (t *Task) exitThreadGroup() bool {
// signalStop must be called with t's signal mutex unlocked.
t.tg.signalHandlers.mu.Unlock()
if notifyParent && t.tg.leader.parent != nil {
- t.tg.leader.parent.signalStop(t, arch.CLD_STOPPED, int32(sig))
+ t.tg.leader.parent.signalStop(t, linux.CLD_STOPPED, int32(sig))
t.tg.leader.parent.tg.eventQueue.Notify(EventChildGroupStop)
}
return last
@@ -353,7 +370,7 @@ func (t *Task) exitChildren() {
continue
}
other.signalHandlers.mu.Lock()
- other.leader.sendSignalLocked(&arch.SignalInfo{
+ other.leader.sendSignalLocked(&linux.SignalInfo{
Signo: int32(linux.SIGKILL),
}, true /* group */)
other.signalHandlers.mu.Unlock()
@@ -368,9 +385,9 @@ func (t *Task) exitChildren() {
// wait for a parent to reap them.)
for c := range t.children {
if sig := c.ParentDeathSignal(); sig != 0 {
- siginfo := &arch.SignalInfo{
+ siginfo := &linux.SignalInfo{
Signo: int32(sig),
- Code: arch.SignalInfoUser,
+ Code: linux.SI_USER,
}
siginfo.SetPID(int32(c.tg.pidns.tids[t]))
siginfo.SetUID(int32(t.Credentials().RealKUID.In(c.UserNamespace()).OrOverflow()))
@@ -652,10 +669,10 @@ func (t *Task) exitNotifyLocked(fromPtraceDetach bool) {
t.parent.tg.signalHandlers.mu.Lock()
if t.tg.terminationSignal == linux.SIGCHLD || fromPtraceDetach {
if act, ok := t.parent.tg.signalHandlers.actions[linux.SIGCHLD]; ok {
- if act.Handler == arch.SignalActIgnore {
+ if act.Handler == linux.SIG_IGN {
t.exitParentAcked = true
signalParent = false
- } else if act.Flags&arch.SignalFlagNoCldWait != 0 {
+ } else if act.Flags&linux.SA_NOCLDWAIT != 0 {
t.exitParentAcked = true
}
}
@@ -705,17 +722,17 @@ func (t *Task) exitNotifyLocked(fromPtraceDetach bool) {
}
// Preconditions: The TaskSet mutex must be locked.
-func (t *Task) exitNotificationSignal(sig linux.Signal, receiver *Task) *arch.SignalInfo {
- info := &arch.SignalInfo{
+func (t *Task) exitNotificationSignal(sig linux.Signal, receiver *Task) *linux.SignalInfo {
+ info := &linux.SignalInfo{
Signo: int32(sig),
}
info.SetPID(int32(receiver.tg.pidns.tids[t]))
info.SetUID(int32(t.Credentials().RealKUID.In(receiver.UserNamespace()).OrOverflow()))
if t.exitStatus.Signaled() {
- info.Code = arch.CLD_KILLED
+ info.Code = linux.CLD_KILLED
info.SetStatus(int32(t.exitStatus.Signo))
} else {
- info.Code = arch.CLD_EXITED
+ info.Code = linux.CLD_EXITED
info.SetStatus(int32(t.exitStatus.Code))
}
// TODO(b/72102453): Set utime, stime.
diff --git a/pkg/sentry/kernel/task_identity.go b/pkg/sentry/kernel/task_identity.go
index 0325967e4..29f154ebd 100644
--- a/pkg/sentry/kernel/task_identity.go
+++ b/pkg/sentry/kernel/task_identity.go
@@ -16,6 +16,7 @@ package kernel
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/mm"
"gvisor.dev/gvisor/pkg/syserror"
@@ -47,7 +48,7 @@ func (t *Task) HasCapability(cp linux.Capability) bool {
func (t *Task) SetUID(uid auth.UID) error {
// setuid considers -1 to be invalid.
if !uid.Ok() {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
t.mu.Lock()
@@ -56,7 +57,7 @@ func (t *Task) SetUID(uid auth.UID) error {
creds := t.Credentials()
kuid := creds.UserNamespace.MapToKUID(uid)
if !kuid.Ok() {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
// "setuid() sets the effective user ID of the calling process. If the
// effective UID of the caller is root (more precisely: if the caller has
@@ -87,14 +88,14 @@ func (t *Task) SetREUID(r, e auth.UID) error {
if r.Ok() {
newR = creds.UserNamespace.MapToKUID(r)
if !newR.Ok() {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
}
newE := creds.EffectiveKUID
if e.Ok() {
newE = creds.UserNamespace.MapToKUID(e)
if !newE.Ok() {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
}
if !creds.HasCapability(linux.CAP_SETUID) {
@@ -223,7 +224,7 @@ func (t *Task) setKUIDsUncheckedLocked(newR, newE, newS auth.KUID) {
// SetGID implements the semantics of setgid(2).
func (t *Task) SetGID(gid auth.GID) error {
if !gid.Ok() {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
t.mu.Lock()
@@ -232,7 +233,7 @@ func (t *Task) SetGID(gid auth.GID) error {
creds := t.Credentials()
kgid := creds.UserNamespace.MapToKGID(gid)
if !kgid.Ok() {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if creds.HasCapability(linux.CAP_SETGID) {
t.setKGIDsUncheckedLocked(kgid, kgid, kgid)
@@ -255,14 +256,14 @@ func (t *Task) SetREGID(r, e auth.GID) error {
if r.Ok() {
newR = creds.UserNamespace.MapToKGID(r)
if !newR.Ok() {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
}
newE := creds.EffectiveKGID
if e.Ok() {
newE = creds.UserNamespace.MapToKGID(e)
if !newE.Ok() {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
}
if !creds.HasCapability(linux.CAP_SETGID) {
@@ -349,7 +350,7 @@ func (t *Task) SetExtraGIDs(gids []auth.GID) error {
for i, gid := range gids {
kgid := creds.UserNamespace.MapToKGID(gid)
if !kgid.Ok() {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
kgids[i] = kgid
}
diff --git a/pkg/sentry/kernel/task_image.go b/pkg/sentry/kernel/task_image.go
index bd5543d4e..c132c27ef 100644
--- a/pkg/sentry/kernel/task_image.go
+++ b/pkg/sentry/kernel/task_image.go
@@ -17,7 +17,7 @@ package kernel
import (
"fmt"
- "gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/abi/linux/errno"
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/arch"
@@ -27,7 +27,7 @@ import (
"gvisor.dev/gvisor/pkg/syserr"
)
-var errNoSyscalls = syserr.New("no syscall table found", linux.ENOEXEC)
+var errNoSyscalls = syserr.New("no syscall table found", errno.ENOEXEC)
// Auxmap contains miscellaneous data for the task.
type Auxmap map[string]interface{}
diff --git a/pkg/sentry/kernel/task_sched.go b/pkg/sentry/kernel/task_sched.go
index 9ba5f8d78..9d9fa76a6 100644
--- a/pkg/sentry/kernel/task_sched.go
+++ b/pkg/sentry/kernel/task_sched.go
@@ -23,12 +23,12 @@ import (
"time"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/hostcpu"
"gvisor.dev/gvisor/pkg/sentry/kernel/sched"
ktime "gvisor.dev/gvisor/pkg/sentry/kernel/time"
"gvisor.dev/gvisor/pkg/sentry/limits"
"gvisor.dev/gvisor/pkg/sentry/usage"
- "gvisor.dev/gvisor/pkg/syserror"
)
// TaskGoroutineState is a coarse representation of the current execution
@@ -536,7 +536,7 @@ func (tg *ThreadGroup) updateCPUTimersEnabledLocked() {
// appropriate for /proc/[pid]/status.
func (t *Task) StateStatus() string {
switch s := t.TaskGoroutineSchedInfo().State; s {
- case TaskGoroutineNonexistent:
+ case TaskGoroutineNonexistent, TaskGoroutineRunningSys:
t.tg.pidns.owner.mu.RLock()
defer t.tg.pidns.owner.mu.RUnlock()
switch t.exitState {
@@ -546,16 +546,16 @@ func (t *Task) StateStatus() string {
return "X (dead)"
default:
// The task goroutine can't exit before passing through
- // runExitNotify, so this indicates that the task has been created,
- // but the task goroutine hasn't yet started. The Linux equivalent
- // is struct task_struct::state == TASK_NEW
+ // runExitNotify, so if s == TaskGoroutineNonexistent, the task has
+ // been created but the task goroutine hasn't yet started. The
+ // Linux equivalent is struct task_struct::state == TASK_NEW
// (kernel/fork.c:copy_process() =>
// kernel/sched/core.c:sched_fork()), but the TASK_NEW bit is
// masked out by TASK_REPORT for /proc/[pid]/status, leaving only
// TASK_RUNNING.
return "R (running)"
}
- case TaskGoroutineRunningSys, TaskGoroutineRunningApp:
+ case TaskGoroutineRunningApp:
return "R (running)"
case TaskGoroutineBlockedInterruptible:
return "S (sleeping)"
@@ -601,7 +601,7 @@ func (t *Task) SetCPUMask(mask sched.CPUSet) error {
// Ensure that at least 1 CPU is still allowed.
if mask.NumCPUs() == 0 {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if t.k.useHostCores {
diff --git a/pkg/sentry/kernel/task_signals.go b/pkg/sentry/kernel/task_signals.go
index c2b9fc08f..f54c774cb 100644
--- a/pkg/sentry/kernel/task_signals.go
+++ b/pkg/sentry/kernel/task_signals.go
@@ -22,6 +22,7 @@ import (
"time"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/eventchannel"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/arch"
@@ -86,7 +87,7 @@ var defaultActions = map[linux.Signal]SignalAction{
}
// computeAction figures out what to do given a signal number
-// and an arch.SignalAct. SIGSTOP always results in a SignalActionStop,
+// and an linux.SigAction. SIGSTOP always results in a SignalActionStop,
// and SIGKILL always results in a SignalActionTerm.
// Signal 0 is always ignored as many programs use it for various internal functions
// and don't expect it to do anything.
@@ -97,7 +98,7 @@ var defaultActions = map[linux.Signal]SignalAction{
// 0, the default action is taken;
// 1, the signal is ignored;
// anything else, the function returns SignalActionHandler.
-func computeAction(sig linux.Signal, act arch.SignalAct) SignalAction {
+func computeAction(sig linux.Signal, act linux.SigAction) SignalAction {
switch sig {
case linux.SIGSTOP:
return SignalActionStop
@@ -108,9 +109,9 @@ func computeAction(sig linux.Signal, act arch.SignalAct) SignalAction {
}
switch act.Handler {
- case arch.SignalActDefault:
+ case linux.SIG_DFL:
return defaultActions[sig]
- case arch.SignalActIgnore:
+ case linux.SIG_IGN:
return SignalActionIgnore
default:
return SignalActionHandler
@@ -127,7 +128,7 @@ var StopSignals = linux.MakeSignalSet(linux.SIGSTOP, linux.SIGTSTP, linux.SIGTTI
// If there are no pending unmasked signals, dequeueSignalLocked returns nil.
//
// Preconditions: t.tg.signalHandlers.mu must be locked.
-func (t *Task) dequeueSignalLocked(mask linux.SignalSet) *arch.SignalInfo {
+func (t *Task) dequeueSignalLocked(mask linux.SignalSet) *linux.SignalInfo {
if info := t.pendingSignals.dequeue(mask); info != nil {
return info
}
@@ -155,7 +156,7 @@ func (t *Task) PendingSignals() linux.SignalSet {
}
// deliverSignal delivers the given signal and returns the following run state.
-func (t *Task) deliverSignal(info *arch.SignalInfo, act arch.SignalAct) taskRunState {
+func (t *Task) deliverSignal(info *linux.SignalInfo, act linux.SigAction) taskRunState {
sigact := computeAction(linux.Signal(info.Signo), act)
if t.haveSyscallReturn {
@@ -172,7 +173,7 @@ func (t *Task) deliverSignal(info *arch.SignalInfo, act arch.SignalAct) taskRunS
fallthrough
case sre == syserror.ERESTART_RESTARTBLOCK:
fallthrough
- case (sre == syserror.ERESTARTSYS && !act.IsRestart()):
+ case (sre == syserror.ERESTARTSYS && act.Flags&linux.SA_RESTART == 0):
t.Debugf("Not restarting syscall %d after errno %d: interrupted by signal %d", t.Arch().SyscallNo(), sre, info.Signo)
t.Arch().SetReturn(uintptr(-ExtractErrno(syserror.EINTR, -1)))
default:
@@ -236,7 +237,7 @@ func (t *Task) deliverSignal(info *arch.SignalInfo, act arch.SignalAct) taskRunS
// deliverSignalToHandler changes the task's userspace state to enter the given
// user-configured handler for the given signal.
-func (t *Task) deliverSignalToHandler(info *arch.SignalInfo, act arch.SignalAct) error {
+func (t *Task) deliverSignalToHandler(info *linux.SignalInfo, act linux.SigAction) error {
// Signal delivery to an application handler interrupts restartable
// sequences.
t.rseqInterrupt()
@@ -248,8 +249,8 @@ func (t *Task) deliverSignalToHandler(info *arch.SignalInfo, act arch.SignalAct)
// N.B. This is a *copy* of the alternate stack that the user's signal
// handler expects to see in its ucontext (even if it's not in use).
alt := t.signalStack
- if act.IsOnStack() && alt.IsEnabled() {
- alt.SetOnStack()
+ if act.Flags&linux.SA_ONSTACK != 0 && alt.IsEnabled() {
+ alt.Flags |= linux.SS_ONSTACK
if !alt.Contains(sp) {
sp = hostarch.Addr(alt.Top())
}
@@ -289,7 +290,7 @@ func (t *Task) deliverSignalToHandler(info *arch.SignalInfo, act arch.SignalAct)
// Add our signal mask.
newMask := t.signalMask | act.Mask
- if !act.IsNoDefer() {
+ if act.Flags&linux.SA_NODEFER == 0 {
newMask |= linux.SignalSetOf(linux.Signal(info.Signo))
}
t.SetSignalMask(newMask)
@@ -326,7 +327,7 @@ func (t *Task) SignalReturn(rt bool) (*SyscallControl, error) {
// Preconditions:
// * The caller must be running on the task goroutine.
// * t.exitState < TaskExitZombie.
-func (t *Task) Sigtimedwait(set linux.SignalSet, timeout time.Duration) (*arch.SignalInfo, error) {
+func (t *Task) Sigtimedwait(set linux.SignalSet, timeout time.Duration) (*linux.SignalInfo, error) {
// set is the set of signals we're interested in; invert it to get the set
// of signals to block.
mask := ^(set &^ UnblockableSignals)
@@ -370,10 +371,10 @@ func (t *Task) Sigtimedwait(set linux.SignalSet, timeout time.Duration) (*arch.S
// The following errors may be returned:
//
// syserror.ESRCH - The task has exited.
-// syserror.EINVAL - The signal is not valid.
+// linuxerr.EINVAL - The signal is not valid.
// syserror.EAGAIN - THe signal is realtime, and cannot be queued.
//
-func (t *Task) SendSignal(info *arch.SignalInfo) error {
+func (t *Task) SendSignal(info *linux.SignalInfo) error {
t.tg.pidns.owner.mu.RLock()
defer t.tg.pidns.owner.mu.RUnlock()
t.tg.signalHandlers.mu.Lock()
@@ -382,7 +383,7 @@ func (t *Task) SendSignal(info *arch.SignalInfo) error {
}
// SendGroupSignal sends the given signal to t's thread group.
-func (t *Task) SendGroupSignal(info *arch.SignalInfo) error {
+func (t *Task) SendGroupSignal(info *linux.SignalInfo) error {
t.tg.pidns.owner.mu.RLock()
defer t.tg.pidns.owner.mu.RUnlock()
t.tg.signalHandlers.mu.Lock()
@@ -392,7 +393,7 @@ func (t *Task) SendGroupSignal(info *arch.SignalInfo) error {
// SendSignal sends the given signal to tg, using tg's leader to determine if
// the signal is blocked.
-func (tg *ThreadGroup) SendSignal(info *arch.SignalInfo) error {
+func (tg *ThreadGroup) SendSignal(info *linux.SignalInfo) error {
tg.pidns.owner.mu.RLock()
defer tg.pidns.owner.mu.RUnlock()
tg.signalHandlers.mu.Lock()
@@ -400,11 +401,11 @@ func (tg *ThreadGroup) SendSignal(info *arch.SignalInfo) error {
return tg.leader.sendSignalLocked(info, true /* group */)
}
-func (t *Task) sendSignalLocked(info *arch.SignalInfo, group bool) error {
+func (t *Task) sendSignalLocked(info *linux.SignalInfo, group bool) error {
return t.sendSignalTimerLocked(info, group, nil)
}
-func (t *Task) sendSignalTimerLocked(info *arch.SignalInfo, group bool, timer *IntervalTimer) error {
+func (t *Task) sendSignalTimerLocked(info *linux.SignalInfo, group bool, timer *IntervalTimer) error {
if t.exitState == TaskExitDead {
return syserror.ESRCH
}
@@ -413,7 +414,7 @@ func (t *Task) sendSignalTimerLocked(info *arch.SignalInfo, group bool, timer *I
return nil
}
if !sig.IsValid() {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
// Signal side effects apply even if the signal is ultimately discarded.
@@ -572,9 +573,9 @@ func (t *Task) forceSignal(sig linux.Signal, unconditional bool) {
func (t *Task) forceSignalLocked(sig linux.Signal, unconditional bool) {
blocked := linux.SignalSetOf(sig)&t.signalMask != 0
act := t.tg.signalHandlers.actions[sig]
- ignored := act.Handler == arch.SignalActIgnore
+ ignored := act.Handler == linux.SIG_IGN
if blocked || ignored || unconditional {
- act.Handler = arch.SignalActDefault
+ act.Handler = linux.SIG_DFL
t.tg.signalHandlers.actions[sig] = act
if blocked {
t.setSignalMaskLocked(t.signalMask &^ linux.SignalSetOf(sig))
@@ -641,17 +642,17 @@ func (t *Task) SetSavedSignalMask(mask linux.SignalSet) {
}
// SignalStack returns the task-private signal stack.
-func (t *Task) SignalStack() arch.SignalStack {
+func (t *Task) SignalStack() linux.SignalStack {
t.p.PullFullState(t.MemoryManager().AddressSpace(), t.Arch())
alt := t.signalStack
if t.onSignalStack(alt) {
- alt.Flags |= arch.SignalStackFlagOnStack
+ alt.Flags |= linux.SS_ONSTACK
}
return alt
}
// onSignalStack returns true if the task is executing on the given signal stack.
-func (t *Task) onSignalStack(alt arch.SignalStack) bool {
+func (t *Task) onSignalStack(alt linux.SignalStack) bool {
sp := hostarch.Addr(t.Arch().Stack())
return alt.Contains(sp)
}
@@ -661,30 +662,30 @@ func (t *Task) onSignalStack(alt arch.SignalStack) bool {
// This value may not be changed if the task is currently executing on the
// signal stack, i.e. if t.onSignalStack returns true. In this case, this
// function will return false. Otherwise, true is returned.
-func (t *Task) SetSignalStack(alt arch.SignalStack) bool {
+func (t *Task) SetSignalStack(alt linux.SignalStack) bool {
// Check that we're not executing on the stack.
if t.onSignalStack(t.signalStack) {
return false
}
- if alt.Flags&arch.SignalStackFlagDisable != 0 {
+ if alt.Flags&linux.SS_DISABLE != 0 {
// Don't record anything beyond the flags.
- t.signalStack = arch.SignalStack{
- Flags: arch.SignalStackFlagDisable,
+ t.signalStack = linux.SignalStack{
+ Flags: linux.SS_DISABLE,
}
} else {
// Mask out irrelevant parts: only disable matters.
- alt.Flags &= arch.SignalStackFlagDisable
+ alt.Flags &= linux.SS_DISABLE
t.signalStack = alt
}
return true
}
-// SetSignalAct atomically sets the thread group's signal action for signal sig
+// SetSigAction atomically sets the thread group's signal action for signal sig
// to *actptr (if actptr is not nil) and returns the old signal action.
-func (tg *ThreadGroup) SetSignalAct(sig linux.Signal, actptr *arch.SignalAct) (arch.SignalAct, error) {
+func (tg *ThreadGroup) SetSigAction(sig linux.Signal, actptr *linux.SigAction) (linux.SigAction, error) {
if !sig.IsValid() {
- return arch.SignalAct{}, syserror.EINVAL
+ return linux.SigAction{}, linuxerr.EINVAL
}
tg.pidns.owner.mu.RLock()
@@ -695,7 +696,7 @@ func (tg *ThreadGroup) SetSignalAct(sig linux.Signal, actptr *arch.SignalAct) (a
oldact := sh.actions[sig]
if actptr != nil {
if sig == linux.SIGKILL || sig == linux.SIGSTOP {
- return oldact, syserror.EINVAL
+ return oldact, linuxerr.EINVAL
}
act := *actptr
@@ -718,48 +719,6 @@ func (tg *ThreadGroup) SetSignalAct(sig linux.Signal, actptr *arch.SignalAct) (a
return oldact, nil
}
-// CopyOutSignalAct converts the given SignalAct into an architecture-specific
-// type and then copies it out to task memory.
-func (t *Task) CopyOutSignalAct(addr hostarch.Addr, s *arch.SignalAct) error {
- n := t.Arch().NewSignalAct()
- n.SerializeFrom(s)
- _, err := n.CopyOut(t, addr)
- return err
-}
-
-// CopyInSignalAct copies an architecture-specific sigaction type from task
-// memory and then converts it into a SignalAct.
-func (t *Task) CopyInSignalAct(addr hostarch.Addr) (arch.SignalAct, error) {
- n := t.Arch().NewSignalAct()
- var s arch.SignalAct
- if _, err := n.CopyIn(t, addr); err != nil {
- return s, err
- }
- n.DeserializeTo(&s)
- return s, nil
-}
-
-// CopyOutSignalStack converts the given SignalStack into an
-// architecture-specific type and then copies it out to task memory.
-func (t *Task) CopyOutSignalStack(addr hostarch.Addr, s *arch.SignalStack) error {
- n := t.Arch().NewSignalStack()
- n.SerializeFrom(s)
- _, err := n.CopyOut(t, addr)
- return err
-}
-
-// CopyInSignalStack copies an architecture-specific stack_t from task memory
-// and then converts it into a SignalStack.
-func (t *Task) CopyInSignalStack(addr hostarch.Addr) (arch.SignalStack, error) {
- n := t.Arch().NewSignalStack()
- var s arch.SignalStack
- if _, err := n.CopyIn(t, addr); err != nil {
- return s, err
- }
- n.DeserializeTo(&s)
- return s, nil
-}
-
// groupStop is a TaskStop placed on tasks that have received a stop signal
// (SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU). (The term "group-stop" originates from
// the ptrace man page.)
@@ -774,7 +733,7 @@ func (*groupStop) Killable() bool { return true }
// previously-dequeued stop signal.
//
// Preconditions: The caller must be running on the task goroutine.
-func (t *Task) initiateGroupStop(info *arch.SignalInfo) {
+func (t *Task) initiateGroupStop(info *linux.SignalInfo) {
t.tg.pidns.owner.mu.RLock()
defer t.tg.pidns.owner.mu.RUnlock()
t.tg.signalHandlers.mu.Lock()
@@ -909,8 +868,8 @@ func (t *Task) signalStop(target *Task, code int32, status int32) {
t.tg.signalHandlers.mu.Lock()
defer t.tg.signalHandlers.mu.Unlock()
act, ok := t.tg.signalHandlers.actions[linux.SIGCHLD]
- if !ok || (act.Handler != arch.SignalActIgnore && act.Flags&arch.SignalFlagNoCldStop == 0) {
- sigchld := &arch.SignalInfo{
+ if !ok || (act.Handler != linux.SIG_IGN && act.Flags&linux.SA_NOCLDSTOP == 0) {
+ sigchld := &linux.SignalInfo{
Signo: int32(linux.SIGCHLD),
Code: code,
}
@@ -955,14 +914,14 @@ func (*runInterrupt) execute(t *Task) taskRunState {
// notified its tracer accordingly. But it's consistent with
// Linux...
if intr {
- tracer.signalStop(t.tg.leader, arch.CLD_STOPPED, int32(sig))
+ tracer.signalStop(t.tg.leader, linux.CLD_STOPPED, int32(sig))
if !notifyParent {
tracer.tg.eventQueue.Notify(EventGroupContinue | EventTraceeStop | EventChildGroupStop)
} else {
tracer.tg.eventQueue.Notify(EventGroupContinue | EventTraceeStop)
}
} else {
- tracer.signalStop(t.tg.leader, arch.CLD_CONTINUED, int32(sig))
+ tracer.signalStop(t.tg.leader, linux.CLD_CONTINUED, int32(sig))
tracer.tg.eventQueue.Notify(EventGroupContinue)
}
}
@@ -974,10 +933,10 @@ func (*runInterrupt) execute(t *Task) taskRunState {
// SIGCHLD is a standard signal, so the latter would always be
// dropped. Hence sending only the former is equivalent.
if intr {
- t.tg.leader.parent.signalStop(t.tg.leader, arch.CLD_STOPPED, int32(sig))
+ t.tg.leader.parent.signalStop(t.tg.leader, linux.CLD_STOPPED, int32(sig))
t.tg.leader.parent.tg.eventQueue.Notify(EventGroupContinue | EventChildGroupStop)
} else {
- t.tg.leader.parent.signalStop(t.tg.leader, arch.CLD_CONTINUED, int32(sig))
+ t.tg.leader.parent.signalStop(t.tg.leader, linux.CLD_CONTINUED, int32(sig))
t.tg.leader.parent.tg.eventQueue.Notify(EventGroupContinue)
}
}
@@ -1018,7 +977,7 @@ func (*runInterrupt) execute(t *Task) taskRunState {
// without requiring an extra PTRACE_GETSIGINFO call." -
// "Group-stop", ptrace(2)
t.ptraceCode = int32(sig) | linux.PTRACE_EVENT_STOP<<8
- t.ptraceSiginfo = &arch.SignalInfo{
+ t.ptraceSiginfo = &linux.SignalInfo{
Signo: int32(sig),
Code: t.ptraceCode,
}
@@ -1029,7 +988,7 @@ func (*runInterrupt) execute(t *Task) taskRunState {
t.ptraceSiginfo = nil
}
if t.beginPtraceStopLocked() {
- tracer.signalStop(t, arch.CLD_STOPPED, int32(sig))
+ tracer.signalStop(t, linux.CLD_STOPPED, int32(sig))
// For consistency with Linux, if the parent and tracer are in the
// same thread group, deduplicate notification signals.
if notifyParent && tracer.tg == t.tg.leader.parent.tg {
@@ -1047,7 +1006,7 @@ func (*runInterrupt) execute(t *Task) taskRunState {
t.tg.signalHandlers.mu.Unlock()
}
if notifyParent {
- t.tg.leader.parent.signalStop(t.tg.leader, arch.CLD_STOPPED, int32(sig))
+ t.tg.leader.parent.signalStop(t.tg.leader, linux.CLD_STOPPED, int32(sig))
t.tg.leader.parent.tg.eventQueue.Notify(EventChildGroupStop)
}
t.tg.pidns.owner.mu.RUnlock()
@@ -1101,7 +1060,7 @@ func (*runInterruptAfterSignalDeliveryStop) execute(t *Task) taskRunState {
if sig != linux.Signal(info.Signo) {
info.Signo = int32(sig)
info.Errno = 0
- info.Code = arch.SignalInfoUser
+ info.Code = linux.SI_USER
// pid isn't a valid field for all signal numbers, but Linux
// doesn't care (kernel/signal.c:ptrace_signal()).
//
diff --git a/pkg/sentry/kernel/task_start.go b/pkg/sentry/kernel/task_start.go
index 32031cd70..41fd2d471 100644
--- a/pkg/sentry/kernel/task_start.go
+++ b/pkg/sentry/kernel/task_start.go
@@ -18,7 +18,6 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/hostarch"
- "gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/inet"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/kernel/futex"
@@ -131,7 +130,7 @@ func (ts *TaskSet) newTask(cfg *TaskConfig) (*Task, error) {
runState: (*runApp)(nil),
interruptChan: make(chan struct{}, 1),
signalMask: cfg.SignalMask,
- signalStack: arch.SignalStack{Flags: arch.SignalStackFlagDisable},
+ signalStack: linux.SignalStack{Flags: linux.SS_DISABLE},
image: *image,
fsContext: cfg.FSContext,
fdTable: cfg.FDTable,
diff --git a/pkg/sentry/kernel/task_syscall.go b/pkg/sentry/kernel/task_syscall.go
index 601fc0d3a..409b712d8 100644
--- a/pkg/sentry/kernel/task_syscall.go
+++ b/pkg/sentry/kernel/task_syscall.go
@@ -22,6 +22,8 @@ import (
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/bits"
+ "gvisor.dev/gvisor/pkg/errors"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/marshal"
"gvisor.dev/gvisor/pkg/metric"
@@ -357,7 +359,7 @@ func (t *Task) doVsyscallInvoke(sysno uintptr, args arch.SyscallArguments, calle
t.Arch().SetReturn(uintptr(rval))
} else {
t.Debugf("vsyscall %d, caller %x: emulated syscall returned error: %v", sysno, t.Arch().Value(caller), err)
- if err == syserror.EFAULT {
+ if linuxerr.Equals(linuxerr.EFAULT, err) {
t.forceSignal(linux.SIGSEGV, false /* unconditional */)
t.SendSignal(SignalInfoPriv(linux.SIGSEGV))
// A return is not emulated in this case.
@@ -379,6 +381,8 @@ func ExtractErrno(err error, sysno int) int {
return 0
case unix.Errno:
return int(err)
+ case *errors.Error:
+ return int(err.Errno())
case syserror.SyscallRestartErrno:
return int(err)
case *memmap.BusError:
diff --git a/pkg/sentry/kernel/task_usermem.go b/pkg/sentry/kernel/task_usermem.go
index fc6d9438a..7935d15a6 100644
--- a/pkg/sentry/kernel/task_usermem.go
+++ b/pkg/sentry/kernel/task_usermem.go
@@ -19,6 +19,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/mm"
"gvisor.dev/gvisor/pkg/syserror"
@@ -202,7 +203,7 @@ func (t *Task) CopyInIovecs(addr hostarch.Addr, numIovecs int) (hostarch.AddrRan
base := hostarch.Addr(hostarch.ByteOrder.Uint64(b[0:8]))
length := hostarch.ByteOrder.Uint64(b[8:16])
if length > math.MaxInt64 {
- return hostarch.AddrRangeSeq{}, syserror.EINVAL
+ return hostarch.AddrRangeSeq{}, linuxerr.EINVAL
}
ar, ok := t.MemoryManager().CheckIORange(base, int64(length))
if !ok {
@@ -270,7 +271,7 @@ func (t *Task) SingleIOSequence(addr hostarch.Addr, length int, opts usermem.IOO
// Preconditions: Same as Task.CopyInIovecs.
func (t *Task) IovecsIOSequence(addr hostarch.Addr, iovcnt int, opts usermem.IOOpts) (usermem.IOSequence, error) {
if iovcnt < 0 || iovcnt > linux.UIO_MAXIOV {
- return usermem.IOSequence{}, syserror.EINVAL
+ return usermem.IOSequence{}, linuxerr.EINVAL
}
ars, err := t.CopyInIovecs(addr, iovcnt)
if err != nil {
diff --git a/pkg/sentry/kernel/thread_group.go b/pkg/sentry/kernel/thread_group.go
index b92e98fa1..8ae00c649 100644
--- a/pkg/sentry/kernel/thread_group.go
+++ b/pkg/sentry/kernel/thread_group.go
@@ -19,7 +19,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
- "gvisor.dev/gvisor/pkg/sentry/arch"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
ktime "gvisor.dev/gvisor/pkg/sentry/kernel/time"
@@ -279,7 +279,7 @@ func (k *Kernel) NewThreadGroup(mntns *fs.MountNamespace, pidns *PIDNamespace, s
limits: limits,
mounts: mntns,
}
- tg.itimerRealTimer = ktime.NewTimer(k.monotonicClock, &itimerRealListener{tg: tg})
+ tg.itimerRealTimer = ktime.NewTimer(k.timekeeper.monotonicClock, &itimerRealListener{tg: tg})
tg.timers = make(map[linux.TimerID]*IntervalTimer)
tg.oldRSeqCritical.Store(&OldRSeqCriticalRegion{})
return tg
@@ -358,7 +358,7 @@ func (tg *ThreadGroup) SetControllingTTY(tty *TTY, steal bool, isReadable bool)
// "The calling process must be a session leader and not have a
// controlling terminal already." - tty_ioctl(4)
if tg.processGroup.session.leader != tg || tg.tty != nil {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
creds := auth.CredentialsFromContext(tg.leader)
@@ -446,10 +446,10 @@ func (tg *ThreadGroup) ReleaseControllingTTY(tty *TTY) error {
othertg.signalHandlers.mu.Lock()
othertg.tty = nil
if othertg.processGroup == tg.processGroup.session.foreground {
- if err := othertg.leader.sendSignalLocked(&arch.SignalInfo{Signo: int32(linux.SIGHUP)}, true /* group */); err != nil {
+ if err := othertg.leader.sendSignalLocked(&linux.SignalInfo{Signo: int32(linux.SIGHUP)}, true /* group */); err != nil {
lastErr = err
}
- if err := othertg.leader.sendSignalLocked(&arch.SignalInfo{Signo: int32(linux.SIGCONT)}, true /* group */); err != nil {
+ if err := othertg.leader.sendSignalLocked(&linux.SignalInfo{Signo: int32(linux.SIGCONT)}, true /* group */); err != nil {
lastErr = err
}
}
@@ -490,10 +490,10 @@ func (tg *ThreadGroup) SetForegroundProcessGroup(tty *TTY, pgid ProcessGroupID)
tg.signalHandlers.mu.Lock()
defer tg.signalHandlers.mu.Unlock()
- // TODO(b/129283598): "If tcsetpgrp() is called by a member of a
- // background process group in its session, and the calling process is
- // not blocking or ignoring SIGTTOU, a SIGTTOU signal is sent to all
- // members of this background process group."
+ // TODO(gvisor.dev/issue/6148): "If tcsetpgrp() is called by a member of a
+ // background process group in its session, and the calling process is not
+ // blocking or ignoring SIGTTOU, a SIGTTOU signal is sent to all members of
+ // this background process group."
// tty must be the controlling terminal.
if tg.tty != tty {
@@ -502,7 +502,7 @@ func (tg *ThreadGroup) SetForegroundProcessGroup(tty *TTY, pgid ProcessGroupID)
// pgid must be positive.
if pgid < 0 {
- return -1, syserror.EINVAL
+ return -1, linuxerr.EINVAL
}
// pg must not be empty. Empty process groups are removed from their
diff --git a/pkg/sentry/kernel/time/BUILD b/pkg/sentry/kernel/time/BUILD
index 2817aa3ba..e293d9a0f 100644
--- a/pkg/sentry/kernel/time/BUILD
+++ b/pkg/sentry/kernel/time/BUILD
@@ -13,8 +13,8 @@ go_library(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/sync",
- "//pkg/syserror",
"//pkg/waiter",
],
)
diff --git a/pkg/sentry/kernel/time/time.go b/pkg/sentry/kernel/time/time.go
index f61a8e164..191b92811 100644
--- a/pkg/sentry/kernel/time/time.go
+++ b/pkg/sentry/kernel/time/time.go
@@ -22,8 +22,8 @@ import (
"time"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sync"
- "gvisor.dev/gvisor/pkg/syserror"
"gvisor.dev/gvisor/pkg/waiter"
)
@@ -322,7 +322,7 @@ func SettingFromSpec(value time.Duration, interval time.Duration, c Clock) (Sett
// interpreted as a time relative to now.
func SettingFromSpecAt(value time.Duration, interval time.Duration, now Time) (Setting, error) {
if value < 0 {
- return Setting{}, syserror.EINVAL
+ return Setting{}, linuxerr.EINVAL
}
if value == 0 {
return Setting{Period: interval}, nil
@@ -338,7 +338,7 @@ func SettingFromSpecAt(value time.Duration, interval time.Duration, now Time) (S
// interpreted as an absolute time.
func SettingFromAbsSpec(value Time, interval time.Duration) (Setting, error) {
if value.Before(ZeroTime) {
- return Setting{}, syserror.EINVAL
+ return Setting{}, linuxerr.EINVAL
}
if value.IsZero() {
return Setting{Period: interval}, nil
@@ -458,25 +458,6 @@ func NewTimer(clock Clock, listener TimerListener) *Timer {
return t
}
-// After waits for the duration to elapse according to clock and then sends a
-// notification on the returned channel. The timer is started immediately and
-// will fire exactly once. The second return value is the start time used with
-// the duration.
-//
-// Callers must call Timer.Destroy.
-func After(clock Clock, duration time.Duration) (*Timer, Time, <-chan struct{}) {
- notifier, tchan := NewChannelNotifier()
- t := NewTimer(clock, notifier)
- now := clock.Now()
-
- t.Swap(Setting{
- Enabled: true,
- Period: 0,
- Next: now.Add(duration),
- })
- return t, now, tchan
-}
-
// init initializes Timer state that is not preserved across save/restore. If
// init has already been called, calling it again is a no-op.
//
diff --git a/pkg/sentry/kernel/timekeeper.go b/pkg/sentry/kernel/timekeeper.go
index 7c4fefb16..6255bae7a 100644
--- a/pkg/sentry/kernel/timekeeper.go
+++ b/pkg/sentry/kernel/timekeeper.go
@@ -25,6 +25,7 @@ import (
"gvisor.dev/gvisor/pkg/sentry/pgalloc"
sentrytime "gvisor.dev/gvisor/pkg/sentry/time"
"gvisor.dev/gvisor/pkg/sync"
+ "gvisor.dev/gvisor/pkg/tcpip"
)
// Timekeeper manages all of the kernel clocks.
@@ -39,6 +40,12 @@ type Timekeeper struct {
// It is set only once, by SetClocks.
clocks sentrytime.Clocks `state:"nosave"`
+ // realtimeClock is a ktime.Clock based on timekeeper's Realtime.
+ realtimeClock *timekeeperClock
+
+ // monotonicClock is a ktime.Clock based on timekeeper's Monotonic.
+ monotonicClock *timekeeperClock
+
// bootTime is the realtime when the system "booted". i.e., when
// SetClocks was called in the initial (not restored) run.
bootTime ktime.Time
@@ -90,10 +97,13 @@ type Timekeeper struct {
// NewTimekeeper does not take ownership of paramPage.
//
// SetClocks must be called on the returned Timekeeper before it is usable.
-func NewTimekeeper(mfp pgalloc.MemoryFileProvider, paramPage memmap.FileRange) (*Timekeeper, error) {
- return &Timekeeper{
+func NewTimekeeper(mfp pgalloc.MemoryFileProvider, paramPage memmap.FileRange) *Timekeeper {
+ t := Timekeeper{
params: NewVDSOParamPage(mfp, paramPage),
- }, nil
+ }
+ t.realtimeClock = &timekeeperClock{tk: &t, c: sentrytime.Realtime}
+ t.monotonicClock = &timekeeperClock{tk: &t, c: sentrytime.Monotonic}
+ return &t
}
// SetClocks the backing clock source.
@@ -167,6 +177,32 @@ func (t *Timekeeper) SetClocks(c sentrytime.Clocks) {
}
}
+var _ tcpip.Clock = (*Timekeeper)(nil)
+
+// Now implements tcpip.Clock.
+func (t *Timekeeper) Now() time.Time {
+ nsec, err := t.GetTime(sentrytime.Realtime)
+ if err != nil {
+ panic("timekeeper.GetTime(sentrytime.Realtime): " + err.Error())
+ }
+ return time.Unix(0, nsec)
+}
+
+// NowMonotonic implements tcpip.Clock.
+func (t *Timekeeper) NowMonotonic() tcpip.MonotonicTime {
+ nsec, err := t.GetTime(sentrytime.Monotonic)
+ if err != nil {
+ panic("timekeeper.GetTime(sentrytime.Monotonic): " + err.Error())
+ }
+ var mt tcpip.MonotonicTime
+ return mt.Add(time.Duration(nsec) * time.Nanosecond)
+}
+
+// AfterFunc implements tcpip.Clock.
+func (t *Timekeeper) AfterFunc(d time.Duration, f func()) tcpip.Timer {
+ return ktime.TcpipAfterFunc(t.realtimeClock, d, f)
+}
+
// startUpdater starts an update goroutine that keeps the clocks updated.
//
// mu must be held.
diff --git a/pkg/sentry/kernel/timekeeper_test.go b/pkg/sentry/kernel/timekeeper_test.go
index dfc3c0719..b6039505a 100644
--- a/pkg/sentry/kernel/timekeeper_test.go
+++ b/pkg/sentry/kernel/timekeeper_test.go
@@ -17,12 +17,12 @@ package kernel
import (
"testing"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/contexttest"
"gvisor.dev/gvisor/pkg/sentry/pgalloc"
sentrytime "gvisor.dev/gvisor/pkg/sentry/time"
"gvisor.dev/gvisor/pkg/sentry/usage"
- "gvisor.dev/gvisor/pkg/syserror"
)
// mockClocks is a sentrytime.Clocks that simply returns the times in the
@@ -45,7 +45,7 @@ func (c *mockClocks) GetTime(id sentrytime.ClockID) (int64, error) {
case sentrytime.Realtime:
return c.realtime, nil
default:
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
}
diff --git a/pkg/sentry/loader/BUILD b/pkg/sentry/loader/BUILD
index 4c65215fa..54bfed644 100644
--- a/pkg/sentry/loader/BUILD
+++ b/pkg/sentry/loader/BUILD
@@ -17,8 +17,10 @@ go_library(
deps = [
"//pkg/abi",
"//pkg/abi/linux",
+ "//pkg/abi/linux/errno",
"//pkg/context",
"//pkg/cpuid",
+ "//pkg/errors/linuxerr",
"//pkg/hostarch",
"//pkg/log",
"//pkg/rand",
diff --git a/pkg/sentry/loader/elf.go b/pkg/sentry/loader/elf.go
index 8fc3e2a79..13ab7ea23 100644
--- a/pkg/sentry/loader/elf.go
+++ b/pkg/sentry/loader/elf.go
@@ -24,6 +24,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/cpuid"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/sentry/arch"
@@ -517,13 +518,13 @@ func loadParsedELF(ctx context.Context, m *mm.MemoryManager, f fsbridge.File, in
start, ok = start.AddLength(uint64(offset))
if !ok {
ctx.Infof(fmt.Sprintf("Start %#x + offset %#x overflows?", start, offset))
- return loadedELF{}, syserror.EINVAL
+ return loadedELF{}, linuxerr.EINVAL
}
end, ok = end.AddLength(uint64(offset))
if !ok {
ctx.Infof(fmt.Sprintf("End %#x + offset %#x overflows?", end, offset))
- return loadedELF{}, syserror.EINVAL
+ return loadedELF{}, linuxerr.EINVAL
}
info.entry, ok = info.entry.AddLength(uint64(offset))
@@ -621,7 +622,7 @@ func loadInitialELF(ctx context.Context, m *mm.MemoryManager, fs *cpuid.FeatureS
func loadInterpreterELF(ctx context.Context, m *mm.MemoryManager, f fsbridge.File, initial loadedELF) (loadedELF, error) {
info, err := parseHeader(ctx, f)
if err != nil {
- if err == syserror.ENOEXEC {
+ if linuxerr.Equals(linuxerr.ENOEXEC, err) {
// Bad interpreter.
err = syserror.ELIBBAD
}
diff --git a/pkg/sentry/loader/interpreter.go b/pkg/sentry/loader/interpreter.go
index 3886b4d33..3e302d92c 100644
--- a/pkg/sentry/loader/interpreter.go
+++ b/pkg/sentry/loader/interpreter.go
@@ -59,7 +59,7 @@ func parseInterpreterScript(ctx context.Context, filename string, f fsbridge.Fil
// Linux silently truncates the remainder of the line if it exceeds
// interpMaxLineLength.
i := bytes.IndexByte(line, '\n')
- if i > 0 {
+ if i >= 0 {
line = line[:i]
}
diff --git a/pkg/sentry/loader/loader.go b/pkg/sentry/loader/loader.go
index 47e3775a3..8240173ae 100644
--- a/pkg/sentry/loader/loader.go
+++ b/pkg/sentry/loader/loader.go
@@ -23,6 +23,7 @@ import (
"gvisor.dev/gvisor/pkg/abi"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/abi/linux/errno"
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/cpuid"
"gvisor.dev/gvisor/pkg/hostarch"
@@ -237,7 +238,7 @@ func Load(ctx context.Context, args LoadArgs, extraAuxv []arch.AuxEntry, vdso *V
// loaded.end is available for its use.
e, ok := loaded.end.RoundUp()
if !ok {
- return 0, nil, "", syserr.NewDynamic(fmt.Sprintf("brk overflows: %#x", loaded.end), linux.ENOEXEC)
+ return 0, nil, "", syserr.NewDynamic(fmt.Sprintf("brk overflows: %#x", loaded.end), errno.ENOEXEC)
}
args.MemoryManager.BrkSetup(ctx, e)
diff --git a/pkg/sentry/loader/vdso.go b/pkg/sentry/loader/vdso.go
index fd54261fd..054ef1723 100644
--- a/pkg/sentry/loader/vdso.go
+++ b/pkg/sentry/loader/vdso.go
@@ -23,6 +23,7 @@ import (
"gvisor.dev/gvisor/pkg/abi"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/safemem"
@@ -58,7 +59,7 @@ type byteFullReader struct {
func (b *byteFullReader) ReadFull(ctx context.Context, dst usermem.IOSequence, offset int64) (int64, error) {
if offset < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
if offset >= int64(len(b.data)) {
return 0, io.EOF
diff --git a/pkg/sentry/mm/BUILD b/pkg/sentry/mm/BUILD
index b417c2da7..69aff21b6 100644
--- a/pkg/sentry/mm/BUILD
+++ b/pkg/sentry/mm/BUILD
@@ -125,6 +125,7 @@ go_library(
"//pkg/abi/linux",
"//pkg/atomicbitops",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/hostarch",
"//pkg/log",
"//pkg/refs",
@@ -156,6 +157,7 @@ go_test(
library = ":mm",
deps = [
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/hostarch",
"//pkg/sentry/arch",
"//pkg/sentry/contexttest",
@@ -163,7 +165,6 @@ go_test(
"//pkg/sentry/memmap",
"//pkg/sentry/pgalloc",
"//pkg/sentry/platform",
- "//pkg/syserror",
"//pkg/usermem",
],
)
diff --git a/pkg/sentry/mm/aio_context.go b/pkg/sentry/mm/aio_context.go
index 346866d3c..8426fc90e 100644
--- a/pkg/sentry/mm/aio_context.go
+++ b/pkg/sentry/mm/aio_context.go
@@ -17,6 +17,7 @@ package mm
import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/memmap"
"gvisor.dev/gvisor/pkg/sentry/pgalloc"
@@ -158,7 +159,7 @@ func (ctx *AIOContext) Prepare() error {
defer ctx.mu.Unlock()
if ctx.dead {
// Context died after the caller looked it up.
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if ctx.outstanding >= ctx.maxOutstanding {
// Context is busy.
@@ -297,7 +298,7 @@ func (m *aioMappable) InodeID() uint64 {
// Msync implements memmap.MappingIdentity.Msync.
func (m *aioMappable) Msync(ctx context.Context, mr memmap.MappableRange) error {
// Linux: aio_ring_fops.fsync == NULL
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
// AddMapping implements memmap.Mappable.AddMapping.
@@ -325,7 +326,7 @@ func (m *aioMappable) CopyMapping(ctx context.Context, ms memmap.MappingSpace, s
// Linux's fs/aio.c:aio_ring_mremap().
mm, ok := ms.(*MemoryManager)
if !ok {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
am := &mm.aioManager
am.mu.Lock()
@@ -333,12 +334,12 @@ func (m *aioMappable) CopyMapping(ctx context.Context, ms memmap.MappingSpace, s
oldID := uint64(srcAR.Start)
aioCtx, ok := am.contexts[oldID]
if !ok {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
aioCtx.mu.Lock()
defer aioCtx.mu.Unlock()
if aioCtx.dead {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
// Use the new ID for the AIOContext.
am.contexts[uint64(dstAR.Start)] = aioCtx
@@ -399,7 +400,7 @@ func (mm *MemoryManager) NewAIOContext(ctx context.Context, events uint32) (uint
id := uint64(addr)
if !mm.aioManager.newAIOContext(events, id) {
mm.MUnmap(ctx, addr, aioRingBufferSize)
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
return id, nil
}
diff --git a/pkg/sentry/mm/mm_test.go b/pkg/sentry/mm/mm_test.go
index 1304b0a2f..84cb8158d 100644
--- a/pkg/sentry/mm/mm_test.go
+++ b/pkg/sentry/mm/mm_test.go
@@ -18,6 +18,7 @@ import (
"testing"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/contexttest"
@@ -25,7 +26,6 @@ import (
"gvisor.dev/gvisor/pkg/sentry/memmap"
"gvisor.dev/gvisor/pkg/sentry/pgalloc"
"gvisor.dev/gvisor/pkg/sentry/platform"
- "gvisor.dev/gvisor/pkg/syserror"
"gvisor.dev/gvisor/pkg/usermem"
)
@@ -171,7 +171,7 @@ func TestIOAfterUnmap(t *testing.T) {
}
n, err = mm.CopyIn(ctx, addr, b, usermem.IOOpts{})
- if err != syserror.EFAULT {
+ if !linuxerr.Equals(linuxerr.EFAULT, err) {
t.Errorf("CopyIn got err %v want EFAULT", err)
}
if n != 0 {
@@ -212,7 +212,7 @@ func TestIOAfterMProtect(t *testing.T) {
// Without IgnorePermissions, CopyOut should no longer succeed.
n, err = mm.CopyOut(ctx, addr, b, usermem.IOOpts{})
- if err != syserror.EFAULT {
+ if !linuxerr.Equals(linuxerr.EFAULT, err) {
t.Errorf("CopyOut got err %v want EFAULT", err)
}
if n != 0 {
@@ -249,7 +249,7 @@ func TestAIOPrepareAfterDestroy(t *testing.T) {
mm.DestroyAIOContext(ctx, id)
// Prepare should fail because aioCtx should be destroyed.
- if err := aioCtx.Prepare(); err != syserror.EINVAL {
+ if err := aioCtx.Prepare(); !linuxerr.Equals(linuxerr.EINVAL, err) {
t.Errorf("aioCtx.Prepare got err %v want nil", err)
} else if err == nil {
aioCtx.CancelPendingRequest()
diff --git a/pkg/sentry/mm/shm.go b/pkg/sentry/mm/shm.go
index 3130be80c..94d5112a1 100644
--- a/pkg/sentry/mm/shm.go
+++ b/pkg/sentry/mm/shm.go
@@ -16,16 +16,16 @@ package mm
import (
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/kernel/shm"
- "gvisor.dev/gvisor/pkg/syserror"
)
// DetachShm unmaps a sysv shared memory segment.
func (mm *MemoryManager) DetachShm(ctx context.Context, addr hostarch.Addr) error {
if addr != addr.RoundDown() {
// "... shmaddr is not aligned on a page boundary." - man shmdt(2)
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
var detached *shm.Shm
@@ -48,7 +48,7 @@ func (mm *MemoryManager) DetachShm(ctx context.Context, addr hostarch.Addr) erro
if detached == nil {
// There is no shared memory segment attached at addr.
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
// Remove all vmas that could have been created by the same attach.
diff --git a/pkg/sentry/mm/special_mappable.go b/pkg/sentry/mm/special_mappable.go
index e748b7ff8..feafe76c1 100644
--- a/pkg/sentry/mm/special_mappable.go
+++ b/pkg/sentry/mm/special_mappable.go
@@ -16,6 +16,7 @@ package mm
import (
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/memmap"
"gvisor.dev/gvisor/pkg/sentry/pgalloc"
@@ -144,11 +145,11 @@ func (m *SpecialMappable) Length() uint64 {
// leak (b/143656263). Delete this function along with VFS1.
func NewSharedAnonMappable(length uint64, mfp pgalloc.MemoryFileProvider) (*SpecialMappable, error) {
if length == 0 {
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
alignedLen, ok := hostarch.Addr(length).RoundUp()
if !ok {
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
fr, err := mfp.MemoryFile().Allocate(uint64(alignedLen), usage.Anonymous)
if err != nil {
diff --git a/pkg/sentry/mm/syscalls.go b/pkg/sentry/mm/syscalls.go
index 7ad6b7c21..7b6715815 100644
--- a/pkg/sentry/mm/syscalls.go
+++ b/pkg/sentry/mm/syscalls.go
@@ -21,6 +21,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/kernel/futex"
@@ -74,7 +75,7 @@ func (mm *MemoryManager) HandleUserFault(ctx context.Context, addr hostarch.Addr
// MMap establishes a memory mapping.
func (mm *MemoryManager) MMap(ctx context.Context, opts memmap.MMapOpts) (hostarch.Addr, error) {
if opts.Length == 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
length, ok := hostarch.Addr(opts.Length).RoundUp()
if !ok {
@@ -85,7 +86,7 @@ func (mm *MemoryManager) MMap(ctx context.Context, opts memmap.MMapOpts) (hostar
if opts.Mappable != nil {
// Offset must be aligned.
if hostarch.Addr(opts.Offset).RoundDown() != hostarch.Addr(opts.Offset) {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// Offset + length must not overflow.
if end := opts.Offset + opts.Length; end < opts.Offset {
@@ -99,7 +100,7 @@ func (mm *MemoryManager) MMap(ctx context.Context, opts memmap.MMapOpts) (hostar
// MAP_FIXED requires addr to be page-aligned; non-fixed mappings
// don't.
if opts.Fixed {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
opts.Addr = opts.Addr.RoundDown()
}
@@ -108,10 +109,10 @@ func (mm *MemoryManager) MMap(ctx context.Context, opts memmap.MMapOpts) (hostar
return 0, syserror.EACCES
}
if opts.Unmap && !opts.Fixed {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
if opts.GrowsDown && opts.Mappable != nil {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// Get the new vma.
@@ -281,18 +282,18 @@ func (mm *MemoryManager) MapStack(ctx context.Context) (hostarch.AddrRange, erro
// MUnmap implements the semantics of Linux's munmap(2).
func (mm *MemoryManager) MUnmap(ctx context.Context, addr hostarch.Addr, length uint64) error {
if addr != addr.RoundDown() {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if length == 0 {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
la, ok := hostarch.Addr(length).RoundUp()
if !ok {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
ar, ok := addr.ToRange(uint64(la))
if !ok {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
mm.mappingMu.Lock()
@@ -331,7 +332,7 @@ const (
func (mm *MemoryManager) MRemap(ctx context.Context, oldAddr hostarch.Addr, oldSize uint64, newSize uint64, opts MRemapOpts) (hostarch.Addr, error) {
// "Note that old_address has to be page aligned." - mremap(2)
if oldAddr.RoundDown() != oldAddr {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// Linux treats an old_size that rounds up to 0 as 0, which is otherwise a
@@ -340,13 +341,13 @@ func (mm *MemoryManager) MRemap(ctx context.Context, oldAddr hostarch.Addr, oldS
oldSize = uint64(oldSizeAddr)
newSizeAddr, ok := hostarch.Addr(newSize).RoundUp()
if !ok || newSizeAddr == 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
newSize = uint64(newSizeAddr)
oldEnd, ok := oldAddr.AddLength(oldSize)
if !ok {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
mm.mappingMu.Lock()
@@ -450,15 +451,15 @@ func (mm *MemoryManager) MRemap(ctx context.Context, oldAddr hostarch.Addr, oldS
case MRemapMustMove:
newAddr := opts.NewAddr
if newAddr.RoundDown() != newAddr {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
var ok bool
newAR, ok = newAddr.ToRange(newSize)
if !ok {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
if (hostarch.AddrRange{oldAddr, oldEnd}).Overlaps(newAR) {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// Check that the new region is valid.
@@ -504,7 +505,7 @@ func (mm *MemoryManager) MRemap(ctx context.Context, oldAddr hostarch.Addr, oldS
if vma := vseg.ValuePtr(); vma.mappable != nil {
// Check that offset+length does not overflow.
if vma.off+uint64(newAR.Length()) < vma.off {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// Inform the Mappable, if any, of the new mapping.
if err := vma.mappable.CopyMapping(ctx, mm, oldAR, newAR, vseg.mappableOffsetAt(oldAR.Start), vma.canWriteMappableLocked()); err != nil {
@@ -590,7 +591,7 @@ func (mm *MemoryManager) MRemap(ctx context.Context, oldAddr hostarch.Addr, oldS
// MProtect implements the semantics of Linux's mprotect(2).
func (mm *MemoryManager) MProtect(addr hostarch.Addr, length uint64, realPerms hostarch.AccessType, growsDown bool) error {
if addr.RoundDown() != addr {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if length == 0 {
return nil
@@ -618,7 +619,7 @@ func (mm *MemoryManager) MProtect(addr hostarch.Addr, length uint64, realPerms h
}
if growsDown {
if !vseg.ValuePtr().growsDown {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if ar.End <= vseg.Start() {
return syserror.ENOMEM
@@ -711,7 +712,7 @@ func (mm *MemoryManager) Brk(ctx context.Context, addr hostarch.Addr) (hostarch.
if addr < mm.brk.Start {
addr = mm.brk.End
mm.mappingMu.Unlock()
- return addr, syserror.EINVAL
+ return addr, linuxerr.EINVAL
}
// TODO(gvisor.dev/issue/156): This enforces RLIMIT_DATA, but is
@@ -780,7 +781,7 @@ func (mm *MemoryManager) MLock(ctx context.Context, addr hostarch.Addr, length u
la, _ := hostarch.Addr(length + addr.PageOffset()).RoundUp()
ar, ok := addr.RoundDown().ToRange(uint64(la))
if !ok {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
mm.mappingMu.Lock()
@@ -855,10 +856,10 @@ func (mm *MemoryManager) MLock(ctx context.Context, addr hostarch.Addr, length u
mm.activeMu.Unlock()
mm.mappingMu.RUnlock()
// Linux: mm/mlock.c:__mlock_posix_error_return()
- if err == syserror.EFAULT {
+ if linuxerr.Equals(linuxerr.EFAULT, err) {
return syserror.ENOMEM
}
- if err == syserror.ENOMEM {
+ if linuxerr.Equals(linuxerr.ENOMEM, err) {
return syserror.EAGAIN
}
return err
@@ -898,7 +899,7 @@ type MLockAllOpts struct {
// depending on opts.
func (mm *MemoryManager) MLockAll(ctx context.Context, opts MLockAllOpts) error {
if !opts.Current && !opts.Future {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
mm.mappingMu.Lock()
@@ -979,13 +980,13 @@ func (mm *MemoryManager) NumaPolicy(addr hostarch.Addr) (linux.NumaPolicy, uint6
// SetNumaPolicy implements the semantics of Linux's mbind().
func (mm *MemoryManager) SetNumaPolicy(addr hostarch.Addr, length uint64, policy linux.NumaPolicy, nodemask uint64) error {
if !addr.IsPageAligned() {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
// Linux allows this to overflow.
la, _ := hostarch.Addr(length).RoundUp()
ar, ok := addr.ToRange(uint64(la))
if !ok {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if ar.Length() == 0 {
return nil
@@ -1021,7 +1022,7 @@ func (mm *MemoryManager) SetNumaPolicy(addr hostarch.Addr, length uint64, policy
func (mm *MemoryManager) SetDontFork(addr hostarch.Addr, length uint64, dontfork bool) error {
ar, ok := addr.ToRange(length)
if !ok {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
mm.mappingMu.Lock()
@@ -1047,7 +1048,7 @@ func (mm *MemoryManager) SetDontFork(addr hostarch.Addr, length uint64, dontfork
func (mm *MemoryManager) Decommit(addr hostarch.Addr, length uint64) error {
ar, ok := addr.ToRange(length)
if !ok {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
mm.mappingMu.RLock()
@@ -1063,7 +1064,7 @@ func (mm *MemoryManager) Decommit(addr hostarch.Addr, length uint64) error {
for vseg := mm.vmas.LowerBoundSegment(ar.Start); vseg.Ok() && vseg.Start() < ar.End; vseg = vseg.NextSegment() {
vma := vseg.ValuePtr()
if vma.mlockMode != memmap.MLockNone {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
vsegAR := vseg.Range().Intersect(ar)
// pseg should already correspond to either this vma or a later one,
@@ -1114,7 +1115,7 @@ type MSyncOpts struct {
// MSync implements the semantics of Linux's msync().
func (mm *MemoryManager) MSync(ctx context.Context, addr hostarch.Addr, length uint64, opts MSyncOpts) error {
if addr != addr.RoundDown() {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if length == 0 {
return nil
diff --git a/pkg/sentry/pgalloc/pgalloc.go b/pkg/sentry/pgalloc/pgalloc.go
index b81292c46..d1a883da4 100644
--- a/pkg/sentry/pgalloc/pgalloc.go
+++ b/pkg/sentry/pgalloc/pgalloc.go
@@ -1062,10 +1062,20 @@ func (f *MemoryFile) runReclaim() {
break
}
- // If ManualZeroing is in effect, pages will be zeroed on allocation
- // and may not be freed by decommitFile, so calling decommitFile is
- // unnecessary.
- if !f.opts.ManualZeroing {
+ if f.opts.ManualZeroing {
+ // If ManualZeroing is in effect, only hugepage-aligned regions may
+ // be safely passed to decommitFile. Pages will be zeroed on
+ // reallocation, so we don't need to perform any manual zeroing
+ // here, whether or not decommitFile succeeds.
+ if startAddr, ok := hostarch.Addr(fr.Start).HugeRoundUp(); ok {
+ if endAddr := hostarch.Addr(fr.End).HugeRoundDown(); startAddr < endAddr {
+ decommitFR := memmap.FileRange{uint64(startAddr), uint64(endAddr)}
+ if err := f.decommitFile(decommitFR); err != nil {
+ log.Warningf("Reclaim failed to decommit %v: %v", decommitFR, err)
+ }
+ }
+ }
+ } else {
if err := f.decommitFile(fr); err != nil {
log.Warningf("Reclaim failed to decommit %v: %v", fr, err)
// Zero the pages manually. This won't reduce memory usage, but at
diff --git a/pkg/sentry/platform/kvm/BUILD b/pkg/sentry/platform/kvm/BUILD
index b307832fd..8a490b3de 100644
--- a/pkg/sentry/platform/kvm/BUILD
+++ b/pkg/sentry/platform/kvm/BUILD
@@ -6,6 +6,8 @@ go_library(
name = "kvm",
srcs = [
"address_space.go",
+ "address_space_amd64.go",
+ "address_space_arm64.go",
"bluepill.go",
"bluepill_allocator.go",
"bluepill_amd64.go",
@@ -77,6 +79,7 @@ go_test(
"requires-kvm",
],
deps = [
+ "//pkg/abi/linux",
"//pkg/hostarch",
"//pkg/ring0",
"//pkg/ring0/pagetables",
diff --git a/pkg/sentry/platform/kvm/address_space.go b/pkg/sentry/platform/kvm/address_space.go
index 5524e8727..9929caebb 100644
--- a/pkg/sentry/platform/kvm/address_space.go
+++ b/pkg/sentry/platform/kvm/address_space.go
@@ -85,15 +85,6 @@ type addressSpace struct {
dirtySet *dirtySet
}
-// invalidate is the implementation for Invalidate.
-func (as *addressSpace) invalidate() {
- as.dirtySet.forEach(as.machine, func(c *vCPU) {
- if c.active.get() == as { // If this happens to be active,
- c.BounceToKernel() // ... force a kernel transition.
- }
- })
-}
-
// Invalidate interrupts all dirty contexts.
func (as *addressSpace) Invalidate() {
as.mu.Lock()
diff --git a/pkg/sentry/platform/kvm/address_space_amd64.go b/pkg/sentry/platform/kvm/address_space_amd64.go
new file mode 100644
index 000000000..d11d38679
--- /dev/null
+++ b/pkg/sentry/platform/kvm/address_space_amd64.go
@@ -0,0 +1,24 @@
+// Copyright 2021 The gVisor Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package kvm
+
+// invalidate is the implementation for Invalidate.
+func (as *addressSpace) invalidate() {
+ as.dirtySet.forEach(as.machine, func(c *vCPU) {
+ if c.active.get() == as { // If this happens to be active,
+ c.BounceToKernel() // ... force a kernel transition.
+ }
+ })
+}
diff --git a/pkg/sentry/platform/kvm/address_space_arm64.go b/pkg/sentry/platform/kvm/address_space_arm64.go
new file mode 100644
index 000000000..fb954418b
--- /dev/null
+++ b/pkg/sentry/platform/kvm/address_space_arm64.go
@@ -0,0 +1,25 @@
+// Copyright 2021 The gVisor Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package kvm
+
+import (
+ "gvisor.dev/gvisor/pkg/ring0"
+)
+
+// invalidate is the implementation for Invalidate.
+func (as *addressSpace) invalidate() {
+ bluepill(as.pageTables.Allocator.(*allocator).cpu)
+ ring0.FlushTlbAll()
+}
diff --git a/pkg/sentry/platform/kvm/bluepill_arm64.go b/pkg/sentry/platform/kvm/bluepill_arm64.go
index 578852c3f..9e5c52923 100644
--- a/pkg/sentry/platform/kvm/bluepill_arm64.go
+++ b/pkg/sentry/platform/kvm/bluepill_arm64.go
@@ -25,29 +25,6 @@ import (
var (
// The action for bluepillSignal is changed by sigaction().
bluepillSignal = unix.SIGILL
-
- // vcpuSErrBounce is the event of system error for bouncing KVM.
- vcpuSErrBounce = kvmVcpuEvents{
- exception: exception{
- sErrPending: 1,
- },
- }
-
- // vcpuSErrNMI is the event of system error to trigger sigbus.
- vcpuSErrNMI = kvmVcpuEvents{
- exception: exception{
- sErrPending: 1,
- sErrHasEsr: 1,
- sErrEsr: _ESR_ELx_SERR_NMI,
- },
- }
-
- // vcpuExtDabt is the event of ext_dabt.
- vcpuExtDabt = kvmVcpuEvents{
- exception: exception{
- extDabtPending: 1,
- },
- }
)
// getTLS returns the value of TPIDR_EL0 register.
diff --git a/pkg/sentry/platform/kvm/bluepill_arm64_unsafe.go b/pkg/sentry/platform/kvm/bluepill_arm64_unsafe.go
index 07fc4f216..f105fdbd0 100644
--- a/pkg/sentry/platform/kvm/bluepill_arm64_unsafe.go
+++ b/pkg/sentry/platform/kvm/bluepill_arm64_unsafe.go
@@ -80,11 +80,18 @@ func getHypercallID(addr uintptr) int {
//
//go:nosplit
func bluepillStopGuest(c *vCPU) {
+ // vcpuSErrBounce is the event of system error for bouncing KVM.
+ vcpuSErrBounce := &kvmVcpuEvents{
+ exception: exception{
+ sErrPending: 1,
+ },
+ }
+
if _, _, errno := unix.RawSyscall( // escapes: no.
unix.SYS_IOCTL,
uintptr(c.fd),
_KVM_SET_VCPU_EVENTS,
- uintptr(unsafe.Pointer(&vcpuSErrBounce))); errno != 0 {
+ uintptr(unsafe.Pointer(vcpuSErrBounce))); errno != 0 {
throw("bounce sErr injection failed")
}
}
@@ -93,12 +100,21 @@ func bluepillStopGuest(c *vCPU) {
//
//go:nosplit
func bluepillSigBus(c *vCPU) {
+ // vcpuSErrNMI is the event of system error to trigger sigbus.
+ vcpuSErrNMI := &kvmVcpuEvents{
+ exception: exception{
+ sErrPending: 1,
+ sErrHasEsr: 1,
+ sErrEsr: _ESR_ELx_SERR_NMI,
+ },
+ }
+
// Host must support ARM64_HAS_RAS_EXTN.
if _, _, errno := unix.RawSyscall( // escapes: no.
unix.SYS_IOCTL,
uintptr(c.fd),
_KVM_SET_VCPU_EVENTS,
- uintptr(unsafe.Pointer(&vcpuSErrNMI))); errno != 0 {
+ uintptr(unsafe.Pointer(vcpuSErrNMI))); errno != 0 {
if errno == unix.EINVAL {
throw("No ARM64_HAS_RAS_EXTN feature in host.")
}
@@ -110,11 +126,18 @@ func bluepillSigBus(c *vCPU) {
//
//go:nosplit
func bluepillExtDabt(c *vCPU) {
+ // vcpuExtDabt is the event of ext_dabt.
+ vcpuExtDabt := &kvmVcpuEvents{
+ exception: exception{
+ extDabtPending: 1,
+ },
+ }
+
if _, _, errno := unix.RawSyscall( // escapes: no.
unix.SYS_IOCTL,
uintptr(c.fd),
_KVM_SET_VCPU_EVENTS,
- uintptr(unsafe.Pointer(&vcpuExtDabt))); errno != 0 {
+ uintptr(unsafe.Pointer(vcpuExtDabt))); errno != 0 {
throw("ext_dabt injection failed")
}
}
diff --git a/pkg/sentry/platform/kvm/context.go b/pkg/sentry/platform/kvm/context.go
index f4d4473a8..183e741ea 100644
--- a/pkg/sentry/platform/kvm/context.go
+++ b/pkg/sentry/platform/kvm/context.go
@@ -17,6 +17,7 @@ package kvm
import (
"sync/atomic"
+ "gvisor.dev/gvisor/pkg/abi/linux"
pkgcontext "gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/ring0"
@@ -32,15 +33,15 @@ type context struct {
// machine is the parent machine, and is immutable.
machine *machine
- // info is the arch.SignalInfo cached for this context.
- info arch.SignalInfo
+ // info is the linux.SignalInfo cached for this context.
+ info linux.SignalInfo
// interrupt is the interrupt context.
interrupt interrupt.Forwarder
}
// Switch runs the provided context in the given address space.
-func (c *context) Switch(ctx pkgcontext.Context, mm platform.MemoryManager, ac arch.Context, _ int32) (*arch.SignalInfo, hostarch.AccessType, error) {
+func (c *context) Switch(ctx pkgcontext.Context, mm platform.MemoryManager, ac arch.Context, _ int32) (*linux.SignalInfo, hostarch.AccessType, error) {
as := mm.AddressSpace()
localAS := as.(*addressSpace)
diff --git a/pkg/sentry/platform/kvm/kvm_amd64_test.go b/pkg/sentry/platform/kvm/kvm_amd64_test.go
index b8dd1e4a5..b1cab89a0 100644
--- a/pkg/sentry/platform/kvm/kvm_amd64_test.go
+++ b/pkg/sentry/platform/kvm/kvm_amd64_test.go
@@ -19,6 +19,7 @@ package kvm
import (
"testing"
+ "gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/ring0"
"gvisor.dev/gvisor/pkg/ring0/pagetables"
"gvisor.dev/gvisor/pkg/sentry/arch"
@@ -30,7 +31,7 @@ func TestSegments(t *testing.T) {
applicationTest(t, true, testutil.TwiddleSegments, func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool {
testutil.SetTestSegments(regs)
for {
- var si arch.SignalInfo
+ var si linux.SignalInfo
if _, err := c.SwitchToUser(ring0.SwitchOpts{
Registers: regs,
FloatingPointState: &dummyFPState,
@@ -55,7 +56,7 @@ func stmxcsr(addr *uint32)
func TestMXCSR(t *testing.T) {
applicationTest(t, true, testutil.SyscallLoop, func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool {
- var si arch.SignalInfo
+ var si linux.SignalInfo
switchOpts := ring0.SwitchOpts{
Registers: regs,
FloatingPointState: &dummyFPState,
diff --git a/pkg/sentry/platform/kvm/kvm_test.go b/pkg/sentry/platform/kvm/kvm_test.go
index ceff09a60..fe570aff9 100644
--- a/pkg/sentry/platform/kvm/kvm_test.go
+++ b/pkg/sentry/platform/kvm/kvm_test.go
@@ -22,6 +22,7 @@ import (
"time"
"golang.org/x/sys/unix"
+ "gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/ring0"
"gvisor.dev/gvisor/pkg/ring0/pagetables"
@@ -157,7 +158,7 @@ func applicationTest(t testHarness, useHostMappings bool, target func(), fn func
func TestApplicationSyscall(t *testing.T) {
applicationTest(t, true, testutil.SyscallLoop, func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool {
- var si arch.SignalInfo
+ var si linux.SignalInfo
if _, err := c.SwitchToUser(ring0.SwitchOpts{
Registers: regs,
FloatingPointState: &dummyFPState,
@@ -171,7 +172,7 @@ func TestApplicationSyscall(t *testing.T) {
return false
})
applicationTest(t, true, testutil.SyscallLoop, func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool {
- var si arch.SignalInfo
+ var si linux.SignalInfo
if _, err := c.SwitchToUser(ring0.SwitchOpts{
Registers: regs,
FloatingPointState: &dummyFPState,
@@ -188,7 +189,7 @@ func TestApplicationSyscall(t *testing.T) {
func TestApplicationFault(t *testing.T) {
applicationTest(t, true, testutil.Touch, func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool {
testutil.SetTouchTarget(regs, nil) // Cause fault.
- var si arch.SignalInfo
+ var si linux.SignalInfo
if _, err := c.SwitchToUser(ring0.SwitchOpts{
Registers: regs,
FloatingPointState: &dummyFPState,
@@ -203,7 +204,7 @@ func TestApplicationFault(t *testing.T) {
})
applicationTest(t, true, testutil.Touch, func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool {
testutil.SetTouchTarget(regs, nil) // Cause fault.
- var si arch.SignalInfo
+ var si linux.SignalInfo
if _, err := c.SwitchToUser(ring0.SwitchOpts{
Registers: regs,
FloatingPointState: &dummyFPState,
@@ -221,7 +222,7 @@ func TestRegistersSyscall(t *testing.T) {
applicationTest(t, true, testutil.TwiddleRegsSyscall, func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool {
testutil.SetTestRegs(regs) // Fill values for all registers.
for {
- var si arch.SignalInfo
+ var si linux.SignalInfo
if _, err := c.SwitchToUser(ring0.SwitchOpts{
Registers: regs,
FloatingPointState: &dummyFPState,
@@ -244,7 +245,7 @@ func TestRegistersFault(t *testing.T) {
applicationTest(t, true, testutil.TwiddleRegsFault, func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool {
testutil.SetTestRegs(regs) // Fill values for all registers.
for {
- var si arch.SignalInfo
+ var si linux.SignalInfo
if _, err := c.SwitchToUser(ring0.SwitchOpts{
Registers: regs,
FloatingPointState: &dummyFPState,
@@ -270,7 +271,7 @@ func TestBounce(t *testing.T) {
time.Sleep(time.Millisecond)
c.BounceToKernel()
}()
- var si arch.SignalInfo
+ var si linux.SignalInfo
if _, err := c.SwitchToUser(ring0.SwitchOpts{
Registers: regs,
FloatingPointState: &dummyFPState,
@@ -285,7 +286,7 @@ func TestBounce(t *testing.T) {
time.Sleep(time.Millisecond)
c.BounceToKernel()
}()
- var si arch.SignalInfo
+ var si linux.SignalInfo
if _, err := c.SwitchToUser(ring0.SwitchOpts{
Registers: regs,
FloatingPointState: &dummyFPState,
@@ -317,7 +318,7 @@ func TestBounceStress(t *testing.T) {
c.BounceToKernel()
}()
randomSleep()
- var si arch.SignalInfo
+ var si linux.SignalInfo
if _, err := c.SwitchToUser(ring0.SwitchOpts{
Registers: regs,
FloatingPointState: &dummyFPState,
@@ -338,7 +339,7 @@ func TestInvalidate(t *testing.T) {
applicationTest(t, true, testutil.Touch, func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool {
testutil.SetTouchTarget(regs, &data) // Read legitimate value.
for {
- var si arch.SignalInfo
+ var si linux.SignalInfo
if _, err := c.SwitchToUser(ring0.SwitchOpts{
Registers: regs,
FloatingPointState: &dummyFPState,
@@ -353,7 +354,7 @@ func TestInvalidate(t *testing.T) {
// Unmap the page containing data & invalidate.
pt.Unmap(hostarch.Addr(reflect.ValueOf(&data).Pointer() & ^uintptr(hostarch.PageSize-1)), hostarch.PageSize)
for {
- var si arch.SignalInfo
+ var si linux.SignalInfo
if _, err := c.SwitchToUser(ring0.SwitchOpts{
Registers: regs,
FloatingPointState: &dummyFPState,
@@ -371,13 +372,13 @@ func TestInvalidate(t *testing.T) {
}
// IsFault returns true iff the given signal represents a fault.
-func IsFault(err error, si *arch.SignalInfo) bool {
+func IsFault(err error, si *linux.SignalInfo) bool {
return err == platform.ErrContextSignal && si.Signo == int32(unix.SIGSEGV)
}
func TestEmptyAddressSpace(t *testing.T) {
applicationTest(t, false, testutil.SyscallLoop, func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool {
- var si arch.SignalInfo
+ var si linux.SignalInfo
if _, err := c.SwitchToUser(ring0.SwitchOpts{
Registers: regs,
FloatingPointState: &dummyFPState,
@@ -391,7 +392,7 @@ func TestEmptyAddressSpace(t *testing.T) {
return false
})
applicationTest(t, false, testutil.SyscallLoop, func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool {
- var si arch.SignalInfo
+ var si linux.SignalInfo
if _, err := c.SwitchToUser(ring0.SwitchOpts{
Registers: regs,
FloatingPointState: &dummyFPState,
@@ -467,7 +468,7 @@ func BenchmarkApplicationSyscall(b *testing.B) {
a int // Count for ErrContextInterrupt.
)
applicationTest(b, true, testutil.SyscallLoop, func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool {
- var si arch.SignalInfo
+ var si linux.SignalInfo
if _, err := c.SwitchToUser(ring0.SwitchOpts{
Registers: regs,
FloatingPointState: &dummyFPState,
@@ -504,7 +505,7 @@ func BenchmarkWorldSwitchToUserRoundtrip(b *testing.B) {
a int
)
applicationTest(b, true, testutil.SyscallLoop, func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool {
- var si arch.SignalInfo
+ var si linux.SignalInfo
if _, err := c.SwitchToUser(ring0.SwitchOpts{
Registers: regs,
FloatingPointState: &dummyFPState,
diff --git a/pkg/sentry/platform/kvm/machine_amd64.go b/pkg/sentry/platform/kvm/machine_amd64.go
index 9a2337654..7a10fd812 100644
--- a/pkg/sentry/platform/kvm/machine_amd64.go
+++ b/pkg/sentry/platform/kvm/machine_amd64.go
@@ -23,11 +23,11 @@ import (
"runtime/debug"
"golang.org/x/sys/unix"
+ "gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/cpuid"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/ring0"
"gvisor.dev/gvisor/pkg/ring0/pagetables"
- "gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/arch/fpu"
"gvisor.dev/gvisor/pkg/sentry/platform"
ktime "gvisor.dev/gvisor/pkg/sentry/time"
@@ -264,10 +264,10 @@ func (c *vCPU) setSystemTime() error {
// nonCanonical generates a canonical address return.
//
//go:nosplit
-func nonCanonical(addr uint64, signal int32, info *arch.SignalInfo) (hostarch.AccessType, error) {
- *info = arch.SignalInfo{
+func nonCanonical(addr uint64, signal int32, info *linux.SignalInfo) (hostarch.AccessType, error) {
+ *info = linux.SignalInfo{
Signo: signal,
- Code: arch.SignalInfoKernel,
+ Code: linux.SI_KERNEL,
}
info.SetAddr(addr) // Include address.
return hostarch.NoAccess, platform.ErrContextSignal
@@ -276,7 +276,7 @@ func nonCanonical(addr uint64, signal int32, info *arch.SignalInfo) (hostarch.Ac
// fault generates an appropriate fault return.
//
//go:nosplit
-func (c *vCPU) fault(signal int32, info *arch.SignalInfo) (hostarch.AccessType, error) {
+func (c *vCPU) fault(signal int32, info *linux.SignalInfo) (hostarch.AccessType, error) {
bluepill(c) // Probably no-op, but may not be.
faultAddr := ring0.ReadCR2()
code, user := c.ErrorCode()
@@ -287,7 +287,7 @@ func (c *vCPU) fault(signal int32, info *arch.SignalInfo) (hostarch.AccessType,
return hostarch.NoAccess, platform.ErrContextInterrupt
}
// Reset the pointed SignalInfo.
- *info = arch.SignalInfo{Signo: signal}
+ *info = linux.SignalInfo{Signo: signal}
info.SetAddr(uint64(faultAddr))
accessType := hostarch.AccessType{
Read: code&(1<<1) == 0,
@@ -325,7 +325,7 @@ func prefaultFloatingPointState(data *fpu.State) {
}
// SwitchToUser unpacks architectural-details.
-func (c *vCPU) SwitchToUser(switchOpts ring0.SwitchOpts, info *arch.SignalInfo) (hostarch.AccessType, error) {
+func (c *vCPU) SwitchToUser(switchOpts ring0.SwitchOpts, info *linux.SignalInfo) (hostarch.AccessType, error) {
// Check for canonical addresses.
if regs := switchOpts.Registers; !ring0.IsCanonical(regs.Rip) {
return nonCanonical(regs.Rip, int32(unix.SIGSEGV), info)
@@ -371,7 +371,7 @@ func (c *vCPU) SwitchToUser(switchOpts ring0.SwitchOpts, info *arch.SignalInfo)
return c.fault(int32(unix.SIGSEGV), info)
case ring0.Debug, ring0.Breakpoint:
- *info = arch.SignalInfo{
+ *info = linux.SignalInfo{
Signo: int32(unix.SIGTRAP),
Code: 1, // TRAP_BRKPT (breakpoint).
}
@@ -383,9 +383,9 @@ func (c *vCPU) SwitchToUser(switchOpts ring0.SwitchOpts, info *arch.SignalInfo)
ring0.BoundRangeExceeded,
ring0.InvalidTSS,
ring0.StackSegmentFault:
- *info = arch.SignalInfo{
+ *info = linux.SignalInfo{
Signo: int32(unix.SIGSEGV),
- Code: arch.SignalInfoKernel,
+ Code: linux.SI_KERNEL,
}
info.SetAddr(switchOpts.Registers.Rip) // Include address.
if vector == ring0.GeneralProtectionFault {
@@ -397,7 +397,7 @@ func (c *vCPU) SwitchToUser(switchOpts ring0.SwitchOpts, info *arch.SignalInfo)
return hostarch.AccessType{}, platform.ErrContextSignal
case ring0.InvalidOpcode:
- *info = arch.SignalInfo{
+ *info = linux.SignalInfo{
Signo: int32(unix.SIGILL),
Code: 1, // ILL_ILLOPC (illegal opcode).
}
@@ -405,7 +405,7 @@ func (c *vCPU) SwitchToUser(switchOpts ring0.SwitchOpts, info *arch.SignalInfo)
return hostarch.AccessType{}, platform.ErrContextSignal
case ring0.DivideByZero:
- *info = arch.SignalInfo{
+ *info = linux.SignalInfo{
Signo: int32(unix.SIGFPE),
Code: 1, // FPE_INTDIV (divide by zero).
}
@@ -413,7 +413,7 @@ func (c *vCPU) SwitchToUser(switchOpts ring0.SwitchOpts, info *arch.SignalInfo)
return hostarch.AccessType{}, platform.ErrContextSignal
case ring0.Overflow:
- *info = arch.SignalInfo{
+ *info = linux.SignalInfo{
Signo: int32(unix.SIGFPE),
Code: 2, // FPE_INTOVF (integer overflow).
}
@@ -422,7 +422,7 @@ func (c *vCPU) SwitchToUser(switchOpts ring0.SwitchOpts, info *arch.SignalInfo)
case ring0.X87FloatingPointException,
ring0.SIMDFloatingPointException:
- *info = arch.SignalInfo{
+ *info = linux.SignalInfo{
Signo: int32(unix.SIGFPE),
Code: 7, // FPE_FLTINV (invalid operation).
}
@@ -433,7 +433,7 @@ func (c *vCPU) SwitchToUser(switchOpts ring0.SwitchOpts, info *arch.SignalInfo)
return hostarch.NoAccess, platform.ErrContextInterrupt
case ring0.AlignmentCheck:
- *info = arch.SignalInfo{
+ *info = linux.SignalInfo{
Signo: int32(unix.SIGBUS),
Code: 2, // BUS_ADRERR (physical address does not exist).
}
@@ -469,7 +469,7 @@ func availableRegionsForSetMem() (phyRegions []physicalRegion) {
}
func (m *machine) mapUpperHalf(pageTable *pagetables.PageTables) {
- // Map all the executible regions so that all the entry functions
+ // Map all the executable regions so that all the entry functions
// are mapped in the upper half.
applyVirtualRegions(func(vr virtualRegion) {
if excludeVirtualRegion(vr) || vr.filename == "[vsyscall]" {
@@ -485,7 +485,7 @@ func (m *machine) mapUpperHalf(pageTable *pagetables.PageTables) {
pageTable.Map(
hostarch.Addr(ring0.KernelStartAddress|r.virtual),
r.length,
- pagetables.MapOpts{AccessType: hostarch.Execute},
+ pagetables.MapOpts{AccessType: hostarch.Execute, Global: true},
physical)
}
})
@@ -498,7 +498,7 @@ func (m *machine) mapUpperHalf(pageTable *pagetables.PageTables) {
pageTable.Map(
hostarch.Addr(ring0.KernelStartAddress|start),
regionLen,
- pagetables.MapOpts{AccessType: hostarch.ReadWrite},
+ pagetables.MapOpts{AccessType: hostarch.ReadWrite, Global: true},
physical)
}
}
diff --git a/pkg/sentry/platform/kvm/machine_arm64.go b/pkg/sentry/platform/kvm/machine_arm64.go
index 8926b1d9f..edaccf9bc 100644
--- a/pkg/sentry/platform/kvm/machine_arm64.go
+++ b/pkg/sentry/platform/kvm/machine_arm64.go
@@ -21,10 +21,10 @@ import (
"sync/atomic"
"golang.org/x/sys/unix"
+ "gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/ring0"
"gvisor.dev/gvisor/pkg/ring0/pagetables"
- "gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/arch/fpu"
"gvisor.dev/gvisor/pkg/sentry/platform"
)
@@ -126,10 +126,10 @@ func availableRegionsForSetMem() (phyRegions []physicalRegion) {
// nonCanonical generates a canonical address return.
//
//go:nosplit
-func nonCanonical(addr uint64, signal int32, info *arch.SignalInfo) (hostarch.AccessType, error) {
- *info = arch.SignalInfo{
+func nonCanonical(addr uint64, signal int32, info *linux.SignalInfo) (hostarch.AccessType, error) {
+ *info = linux.SignalInfo{
Signo: signal,
- Code: arch.SignalInfoKernel,
+ Code: linux.SI_KERNEL,
}
info.SetAddr(addr) // Include address.
return hostarch.NoAccess, platform.ErrContextSignal
@@ -157,7 +157,7 @@ func isWriteFault(code uint64) bool {
// fault generates an appropriate fault return.
//
//go:nosplit
-func (c *vCPU) fault(signal int32, info *arch.SignalInfo) (hostarch.AccessType, error) {
+func (c *vCPU) fault(signal int32, info *linux.SignalInfo) (hostarch.AccessType, error) {
bluepill(c) // Probably no-op, but may not be.
faultAddr := c.GetFaultAddr()
code, user := c.ErrorCode()
@@ -170,7 +170,7 @@ func (c *vCPU) fault(signal int32, info *arch.SignalInfo) (hostarch.AccessType,
}
// Reset the pointed SignalInfo.
- *info = arch.SignalInfo{Signo: signal}
+ *info = linux.SignalInfo{Signo: signal}
info.SetAddr(uint64(faultAddr))
ret := code & _ESR_ELx_FSC
diff --git a/pkg/sentry/platform/kvm/machine_arm64_unsafe.go b/pkg/sentry/platform/kvm/machine_arm64_unsafe.go
index 92edc992b..f6aa519b1 100644
--- a/pkg/sentry/platform/kvm/machine_arm64_unsafe.go
+++ b/pkg/sentry/platform/kvm/machine_arm64_unsafe.go
@@ -23,10 +23,10 @@ import (
"unsafe"
"golang.org/x/sys/unix"
+ "gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/ring0"
"gvisor.dev/gvisor/pkg/ring0/pagetables"
- "gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/arch/fpu"
"gvisor.dev/gvisor/pkg/sentry/platform"
ktime "gvisor.dev/gvisor/pkg/sentry/time"
@@ -140,22 +140,15 @@ func (c *vCPU) initArchState() error {
// vbar_el1
reg.id = _KVM_ARM64_REGS_VBAR_EL1
-
- fromLocation := reflect.ValueOf(ring0.Vectors).Pointer()
- offset := fromLocation & (1<<11 - 1)
- if offset != 0 {
- offset = 1<<11 - offset
- }
-
- toLocation := fromLocation + offset
- data = uint64(ring0.KernelStartAddress | toLocation)
+ vectorLocation := reflect.ValueOf(ring0.Vectors).Pointer()
+ data = uint64(ring0.KernelStartAddress | vectorLocation)
if err := c.setOneRegister(&reg); err != nil {
return err
}
// Use the address of the exception vector table as
// the MMIO address base.
- arm64HypercallMMIOBase = toLocation
+ arm64HypercallMMIOBase = vectorLocation
// Initialize the PCID database.
if hasGuestPCID {
@@ -272,7 +265,7 @@ func (c *vCPU) getOneRegister(reg *kvmOneReg) error {
}
// SwitchToUser unpacks architectural-details.
-func (c *vCPU) SwitchToUser(switchOpts ring0.SwitchOpts, info *arch.SignalInfo) (hostarch.AccessType, error) {
+func (c *vCPU) SwitchToUser(switchOpts ring0.SwitchOpts, info *linux.SignalInfo) (hostarch.AccessType, error) {
// Check for canonical addresses.
if regs := switchOpts.Registers; !ring0.IsCanonical(regs.Pc) {
return nonCanonical(regs.Pc, int32(unix.SIGSEGV), info)
@@ -319,14 +312,14 @@ func (c *vCPU) SwitchToUser(switchOpts ring0.SwitchOpts, info *arch.SignalInfo)
case ring0.El0SyncUndef:
return c.fault(int32(unix.SIGILL), info)
case ring0.El0SyncDbg:
- *info = arch.SignalInfo{
+ *info = linux.SignalInfo{
Signo: int32(unix.SIGTRAP),
Code: 1, // TRAP_BRKPT (breakpoint).
}
info.SetAddr(switchOpts.Registers.Pc) // Include address.
return hostarch.AccessType{}, platform.ErrContextSignal
case ring0.El0SyncSpPc:
- *info = arch.SignalInfo{
+ *info = linux.SignalInfo{
Signo: int32(unix.SIGBUS),
Code: 2, // BUS_ADRERR (physical address does not exist).
}
diff --git a/pkg/sentry/platform/platform.go b/pkg/sentry/platform/platform.go
index ef7814a6f..a26bc2316 100644
--- a/pkg/sentry/platform/platform.go
+++ b/pkg/sentry/platform/platform.go
@@ -195,8 +195,8 @@ type Context interface {
// - nil: The Context invoked a system call.
//
// - ErrContextSignal: The Context was interrupted by a signal. The
- // returned *arch.SignalInfo contains information about the signal. If
- // arch.SignalInfo.Signo == SIGSEGV, the returned hostarch.AccessType
+ // returned *linux.SignalInfo contains information about the signal. If
+ // linux.SignalInfo.Signo == SIGSEGV, the returned hostarch.AccessType
// contains the access type of the triggering fault. The caller owns
// the returned SignalInfo.
//
@@ -207,7 +207,7 @@ type Context interface {
// concurrent call to Switch().
//
// - ErrContextCPUPreempted: See the definition of that error for details.
- Switch(ctx context.Context, mm MemoryManager, ac arch.Context, cpu int32) (*arch.SignalInfo, hostarch.AccessType, error)
+ Switch(ctx context.Context, mm MemoryManager, ac arch.Context, cpu int32) (*linux.SignalInfo, hostarch.AccessType, error)
// PullFullState() pulls a full state of the application thread.
//
diff --git a/pkg/sentry/platform/ptrace/ptrace.go b/pkg/sentry/platform/ptrace/ptrace.go
index 828458ce2..319b0cf1d 100644
--- a/pkg/sentry/platform/ptrace/ptrace.go
+++ b/pkg/sentry/platform/ptrace/ptrace.go
@@ -73,7 +73,7 @@ var (
type context struct {
// signalInfo is the signal info, if and when a signal is received.
- signalInfo arch.SignalInfo
+ signalInfo linux.SignalInfo
// interrupt is the interrupt context.
interrupt interrupt.Forwarder
@@ -96,7 +96,7 @@ type context struct {
}
// Switch runs the provided context in the given address space.
-func (c *context) Switch(ctx pkgcontext.Context, mm platform.MemoryManager, ac arch.Context, cpu int32) (*arch.SignalInfo, hostarch.AccessType, error) {
+func (c *context) Switch(ctx pkgcontext.Context, mm platform.MemoryManager, ac arch.Context, cpu int32) (*linux.SignalInfo, hostarch.AccessType, error) {
as := mm.AddressSpace()
s := as.(*subprocess)
isSyscall := s.switchToApp(c, ac)
diff --git a/pkg/sentry/platform/ptrace/ptrace_unsafe.go b/pkg/sentry/platform/ptrace/ptrace_unsafe.go
index facb96011..cc93396a9 100644
--- a/pkg/sentry/platform/ptrace/ptrace_unsafe.go
+++ b/pkg/sentry/platform/ptrace/ptrace_unsafe.go
@@ -101,7 +101,7 @@ func (t *thread) setFPRegs(fpState *fpu.State, fpLen uint64, useXsave bool) erro
}
// getSignalInfo retrieves information about the signal that caused the stop.
-func (t *thread) getSignalInfo(si *arch.SignalInfo) error {
+func (t *thread) getSignalInfo(si *linux.SignalInfo) error {
_, _, errno := unix.RawSyscall6(
unix.SYS_PTRACE,
unix.PTRACE_GETSIGINFO,
diff --git a/pkg/sentry/platform/ptrace/subprocess.go b/pkg/sentry/platform/ptrace/subprocess.go
index 9c73a725a..0931795c5 100644
--- a/pkg/sentry/platform/ptrace/subprocess.go
+++ b/pkg/sentry/platform/ptrace/subprocess.go
@@ -20,6 +20,7 @@ import (
"runtime"
"golang.org/x/sys/unix"
+ "gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/procid"
@@ -524,7 +525,7 @@ func (s *subprocess) switchToApp(c *context, ac arch.Context) bool {
// Check for interrupts, and ensure that future interrupts will signal t.
if !c.interrupt.Enable(t) {
// Pending interrupt; simulate.
- c.signalInfo = arch.SignalInfo{Signo: int32(platform.SignalInterrupt)}
+ c.signalInfo = linux.SignalInfo{Signo: int32(platform.SignalInterrupt)}
return false
}
defer c.interrupt.Disable()
diff --git a/pkg/sentry/platform/ptrace/subprocess_amd64.go b/pkg/sentry/platform/ptrace/subprocess_amd64.go
index 9252c0bd7..90b1ead56 100644
--- a/pkg/sentry/platform/ptrace/subprocess_amd64.go
+++ b/pkg/sentry/platform/ptrace/subprocess_amd64.go
@@ -155,7 +155,7 @@ func initChildProcessPPID(initregs *arch.Registers, ppid int32) {
//
// Note that this should only be called after verifying that the signalInfo has
// been generated by the kernel.
-func patchSignalInfo(regs *arch.Registers, signalInfo *arch.SignalInfo) {
+func patchSignalInfo(regs *arch.Registers, signalInfo *linux.SignalInfo) {
if linux.Signal(signalInfo.Signo) == linux.SIGSYS {
signalInfo.Signo = int32(linux.SIGSEGV)
diff --git a/pkg/sentry/platform/ptrace/subprocess_arm64.go b/pkg/sentry/platform/ptrace/subprocess_arm64.go
index c0cbc0686..e4257e3bf 100644
--- a/pkg/sentry/platform/ptrace/subprocess_arm64.go
+++ b/pkg/sentry/platform/ptrace/subprocess_arm64.go
@@ -138,7 +138,7 @@ func initChildProcessPPID(initregs *arch.Registers, ppid int32) {
//
// Note that this should only be called after verifying that the signalInfo has
// been generated by the kernel.
-func patchSignalInfo(regs *arch.Registers, signalInfo *arch.SignalInfo) {
+func patchSignalInfo(regs *arch.Registers, signalInfo *linux.SignalInfo) {
if linux.Signal(signalInfo.Signo) == linux.SIGSYS {
signalInfo.Signo = int32(linux.SIGSEGV)
diff --git a/pkg/sentry/sighandling/sighandling_unsafe.go b/pkg/sentry/sighandling/sighandling_unsafe.go
index d6a2fbe34..3fe5c6770 100644
--- a/pkg/sentry/sighandling/sighandling_unsafe.go
+++ b/pkg/sentry/sighandling/sighandling_unsafe.go
@@ -21,25 +21,16 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
)
-// FIXME(gvisor.dev/issue/214): Move to pkg/abi/linux along with definitions in
-// pkg/sentry/arch.
-type sigaction struct {
- handler uintptr
- flags uint64
- restorer uintptr
- mask uint64
-}
-
// IgnoreChildStop sets the SA_NOCLDSTOP flag, causing child processes to not
// generate SIGCHLD when they stop.
func IgnoreChildStop() error {
- var sa sigaction
+ var sa linux.SigAction
// Get the existing signal handler information, and set the flag.
if _, _, e := unix.RawSyscall6(unix.SYS_RT_SIGACTION, uintptr(unix.SIGCHLD), 0, uintptr(unsafe.Pointer(&sa)), linux.SignalSetSize, 0, 0); e != 0 {
return e
}
- sa.flags |= linux.SA_NOCLDSTOP
+ sa.Flags |= linux.SA_NOCLDSTOP
if _, _, e := unix.RawSyscall6(unix.SYS_RT_SIGACTION, uintptr(unix.SIGCHLD), uintptr(unsafe.Pointer(&sa)), 0, linux.SignalSetSize, 0, 0); e != 0 {
return e
}
diff --git a/pkg/sentry/socket/control/BUILD b/pkg/sentry/socket/control/BUILD
index 2029e7cf4..e1d310b1b 100644
--- a/pkg/sentry/socket/control/BUILD
+++ b/pkg/sentry/socket/control/BUILD
@@ -16,6 +16,7 @@ go_library(
"//pkg/abi/linux",
"//pkg/bits",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/hostarch",
"//pkg/marshal",
"//pkg/marshal/primitive",
diff --git a/pkg/sentry/socket/control/control.go b/pkg/sentry/socket/control/control.go
index 235b9c306..64958b6ec 100644
--- a/pkg/sentry/socket/control/control.go
+++ b/pkg/sentry/socket/control/control.go
@@ -20,6 +20,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/bits"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/marshal"
"gvisor.dev/gvisor/pkg/marshal/primitive"
@@ -473,17 +474,17 @@ func Parse(t *kernel.Task, socketOrEndpoint interface{}, buf []byte, width uint)
for i := 0; i < len(buf); {
if i+linux.SizeOfControlMessageHeader > len(buf) {
- return cmsgs, syserror.EINVAL
+ return cmsgs, linuxerr.EINVAL
}
var h linux.ControlMessageHeader
h.UnmarshalUnsafe(buf[i : i+linux.SizeOfControlMessageHeader])
if h.Length < uint64(linux.SizeOfControlMessageHeader) {
- return socket.ControlMessages{}, syserror.EINVAL
+ return socket.ControlMessages{}, linuxerr.EINVAL
}
if h.Length > uint64(len(buf)-i) {
- return socket.ControlMessages{}, syserror.EINVAL
+ return socket.ControlMessages{}, linuxerr.EINVAL
}
i += linux.SizeOfControlMessageHeader
@@ -497,7 +498,7 @@ func Parse(t *kernel.Task, socketOrEndpoint interface{}, buf []byte, width uint)
numRights := rightsSize / linux.SizeOfControlMessageRight
if len(fds)+numRights > linux.SCM_MAX_FD {
- return socket.ControlMessages{}, syserror.EINVAL
+ return socket.ControlMessages{}, linuxerr.EINVAL
}
for j := i; j < i+rightsSize; j += linux.SizeOfControlMessageRight {
@@ -508,7 +509,7 @@ func Parse(t *kernel.Task, socketOrEndpoint interface{}, buf []byte, width uint)
case linux.SCM_CREDENTIALS:
if length < linux.SizeOfControlMessageCredentials {
- return socket.ControlMessages{}, syserror.EINVAL
+ return socket.ControlMessages{}, linuxerr.EINVAL
}
var creds linux.ControlMessageCredentials
@@ -522,7 +523,7 @@ func Parse(t *kernel.Task, socketOrEndpoint interface{}, buf []byte, width uint)
case linux.SO_TIMESTAMP:
if length < linux.SizeOfTimeval {
- return socket.ControlMessages{}, syserror.EINVAL
+ return socket.ControlMessages{}, linuxerr.EINVAL
}
var ts linux.Timeval
ts.UnmarshalUnsafe(buf[i : i+linux.SizeOfTimeval])
@@ -532,13 +533,13 @@ func Parse(t *kernel.Task, socketOrEndpoint interface{}, buf []byte, width uint)
default:
// Unknown message type.
- return socket.ControlMessages{}, syserror.EINVAL
+ return socket.ControlMessages{}, linuxerr.EINVAL
}
case linux.SOL_IP:
switch h.Type {
case linux.IP_TOS:
if length < linux.SizeOfControlMessageTOS {
- return socket.ControlMessages{}, syserror.EINVAL
+ return socket.ControlMessages{}, linuxerr.EINVAL
}
cmsgs.IP.HasTOS = true
var tos primitive.Uint8
@@ -548,7 +549,7 @@ func Parse(t *kernel.Task, socketOrEndpoint interface{}, buf []byte, width uint)
case linux.IP_PKTINFO:
if length < linux.SizeOfControlMessageIPPacketInfo {
- return socket.ControlMessages{}, syserror.EINVAL
+ return socket.ControlMessages{}, linuxerr.EINVAL
}
cmsgs.IP.HasIPPacketInfo = true
@@ -561,7 +562,7 @@ func Parse(t *kernel.Task, socketOrEndpoint interface{}, buf []byte, width uint)
case linux.IP_RECVORIGDSTADDR:
var addr linux.SockAddrInet
if length < addr.SizeBytes() {
- return socket.ControlMessages{}, syserror.EINVAL
+ return socket.ControlMessages{}, linuxerr.EINVAL
}
addr.UnmarshalUnsafe(buf[i : i+addr.SizeBytes()])
cmsgs.IP.OriginalDstAddress = &addr
@@ -570,7 +571,7 @@ func Parse(t *kernel.Task, socketOrEndpoint interface{}, buf []byte, width uint)
case linux.IP_RECVERR:
var errCmsg linux.SockErrCMsgIPv4
if length < errCmsg.SizeBytes() {
- return socket.ControlMessages{}, syserror.EINVAL
+ return socket.ControlMessages{}, linuxerr.EINVAL
}
errCmsg.UnmarshalBytes(buf[i : i+errCmsg.SizeBytes()])
@@ -578,13 +579,13 @@ func Parse(t *kernel.Task, socketOrEndpoint interface{}, buf []byte, width uint)
i += bits.AlignUp(length, width)
default:
- return socket.ControlMessages{}, syserror.EINVAL
+ return socket.ControlMessages{}, linuxerr.EINVAL
}
case linux.SOL_IPV6:
switch h.Type {
case linux.IPV6_TCLASS:
if length < linux.SizeOfControlMessageTClass {
- return socket.ControlMessages{}, syserror.EINVAL
+ return socket.ControlMessages{}, linuxerr.EINVAL
}
cmsgs.IP.HasTClass = true
var tclass primitive.Uint32
@@ -595,7 +596,7 @@ func Parse(t *kernel.Task, socketOrEndpoint interface{}, buf []byte, width uint)
case linux.IPV6_RECVORIGDSTADDR:
var addr linux.SockAddrInet6
if length < addr.SizeBytes() {
- return socket.ControlMessages{}, syserror.EINVAL
+ return socket.ControlMessages{}, linuxerr.EINVAL
}
addr.UnmarshalUnsafe(buf[i : i+addr.SizeBytes()])
cmsgs.IP.OriginalDstAddress = &addr
@@ -604,7 +605,7 @@ func Parse(t *kernel.Task, socketOrEndpoint interface{}, buf []byte, width uint)
case linux.IPV6_RECVERR:
var errCmsg linux.SockErrCMsgIPv6
if length < errCmsg.SizeBytes() {
- return socket.ControlMessages{}, syserror.EINVAL
+ return socket.ControlMessages{}, linuxerr.EINVAL
}
errCmsg.UnmarshalBytes(buf[i : i+errCmsg.SizeBytes()])
@@ -612,10 +613,10 @@ func Parse(t *kernel.Task, socketOrEndpoint interface{}, buf []byte, width uint)
i += bits.AlignUp(length, width)
default:
- return socket.ControlMessages{}, syserror.EINVAL
+ return socket.ControlMessages{}, linuxerr.EINVAL
}
default:
- return socket.ControlMessages{}, syserror.EINVAL
+ return socket.ControlMessages{}, linuxerr.EINVAL
}
}
diff --git a/pkg/sentry/socket/hostinet/BUILD b/pkg/sentry/socket/hostinet/BUILD
index 3c6511ead..3950caa0f 100644
--- a/pkg/sentry/socket/hostinet/BUILD
+++ b/pkg/sentry/socket/hostinet/BUILD
@@ -18,6 +18,7 @@ go_library(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/fdnotifier",
"//pkg/hostarch",
"//pkg/log",
diff --git a/pkg/sentry/socket/hostinet/socket.go b/pkg/sentry/socket/hostinet/socket.go
index 52ae4bc9c..38cb2c99c 100644
--- a/pkg/sentry/socket/hostinet/socket.go
+++ b/pkg/sentry/socket/hostinet/socket.go
@@ -20,6 +20,7 @@ import (
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fdnotifier"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/log"
@@ -67,23 +68,6 @@ type socketOperations struct {
socketOpsCommon
}
-// socketOpsCommon contains the socket operations common to VFS1 and VFS2.
-//
-// +stateify savable
-type socketOpsCommon struct {
- socket.SendReceiveTimeout
-
- family int // Read-only.
- stype linux.SockType // Read-only.
- protocol int // Read-only.
- queue waiter.Queue
-
- // fd is the host socket fd. It must have O_NONBLOCK, so that operations
- // will return EWOULDBLOCK instead of blocking on the host. This allows us to
- // handle blocking behavior independently in the sentry.
- fd int
-}
-
var _ = socket.Socket(&socketOperations{})
func newSocketFile(ctx context.Context, family int, stype linux.SockType, protocol int, fd int, nonblock bool) (*fs.File, *syserr.Error) {
@@ -103,29 +87,6 @@ func newSocketFile(ctx context.Context, family int, stype linux.SockType, protoc
return fs.NewFile(ctx, dirent, fs.FileFlags{NonBlocking: nonblock, Read: true, Write: true, NonSeekable: true}, s), nil
}
-// Release implements fs.FileOperations.Release.
-func (s *socketOpsCommon) Release(context.Context) {
- fdnotifier.RemoveFD(int32(s.fd))
- unix.Close(s.fd)
-}
-
-// Readiness implements waiter.Waitable.Readiness.
-func (s *socketOpsCommon) Readiness(mask waiter.EventMask) waiter.EventMask {
- return fdnotifier.NonBlockingPoll(int32(s.fd), mask)
-}
-
-// EventRegister implements waiter.Waitable.EventRegister.
-func (s *socketOpsCommon) EventRegister(e *waiter.Entry, mask waiter.EventMask) {
- s.queue.EventRegister(e, mask)
- fdnotifier.UpdateFD(int32(s.fd))
-}
-
-// EventUnregister implements waiter.Waitable.EventUnregister.
-func (s *socketOpsCommon) EventUnregister(e *waiter.Entry) {
- s.queue.EventUnregister(e)
- fdnotifier.UpdateFD(int32(s.fd))
-}
-
// Ioctl implements fs.FileOperations.Ioctl.
func (s *socketOperations) Ioctl(ctx context.Context, _ *fs.File, io usermem.IO, args arch.SyscallArguments) (uintptr, error) {
return ioctl(ctx, s.fd, io, args)
@@ -177,6 +138,96 @@ func (s *socketOperations) Write(ctx context.Context, _ *fs.File, src usermem.IO
return int64(n), err
}
+// Socket implements socket.Provider.Socket.
+func (p *socketProvider) Socket(t *kernel.Task, stypeflags linux.SockType, protocol int) (*fs.File, *syserr.Error) {
+ // Check that we are using the host network stack.
+ stack := t.NetworkContext()
+ if stack == nil {
+ return nil, nil
+ }
+ if _, ok := stack.(*Stack); !ok {
+ return nil, nil
+ }
+
+ // Only accept TCP and UDP.
+ stype := stypeflags & linux.SOCK_TYPE_MASK
+ switch stype {
+ case unix.SOCK_STREAM:
+ switch protocol {
+ case 0, unix.IPPROTO_TCP:
+ // ok
+ default:
+ return nil, nil
+ }
+ case unix.SOCK_DGRAM:
+ switch protocol {
+ case 0, unix.IPPROTO_UDP:
+ // ok
+ default:
+ return nil, nil
+ }
+ default:
+ return nil, nil
+ }
+
+ // Conservatively ignore all flags specified by the application and add
+ // SOCK_NONBLOCK since socketOperations requires it. Pass a protocol of 0
+ // to simplify the syscall filters, since 0 and IPPROTO_* are equivalent.
+ fd, err := unix.Socket(p.family, int(stype)|unix.SOCK_NONBLOCK|unix.SOCK_CLOEXEC, 0)
+ if err != nil {
+ return nil, syserr.FromError(err)
+ }
+ return newSocketFile(t, p.family, stype, protocol, fd, stypeflags&unix.SOCK_NONBLOCK != 0)
+}
+
+// Pair implements socket.Provider.Pair.
+func (p *socketProvider) Pair(t *kernel.Task, stype linux.SockType, protocol int) (*fs.File, *fs.File, *syserr.Error) {
+ // Not supported by AF_INET/AF_INET6.
+ return nil, nil, nil
+}
+
+// LINT.ThenChange(./socket_vfs2.go)
+
+// socketOpsCommon contains the socket operations common to VFS1 and VFS2.
+//
+// +stateify savable
+type socketOpsCommon struct {
+ socket.SendReceiveTimeout
+
+ family int // Read-only.
+ stype linux.SockType // Read-only.
+ protocol int // Read-only.
+ queue waiter.Queue
+
+ // fd is the host socket fd. It must have O_NONBLOCK, so that operations
+ // will return EWOULDBLOCK instead of blocking on the host. This allows us to
+ // handle blocking behavior independently in the sentry.
+ fd int
+}
+
+// Release implements fs.FileOperations.Release.
+func (s *socketOpsCommon) Release(context.Context) {
+ fdnotifier.RemoveFD(int32(s.fd))
+ unix.Close(s.fd)
+}
+
+// Readiness implements waiter.Waitable.Readiness.
+func (s *socketOpsCommon) Readiness(mask waiter.EventMask) waiter.EventMask {
+ return fdnotifier.NonBlockingPoll(int32(s.fd), mask)
+}
+
+// EventRegister implements waiter.Waitable.EventRegister.
+func (s *socketOpsCommon) EventRegister(e *waiter.Entry, mask waiter.EventMask) {
+ s.queue.EventRegister(e, mask)
+ fdnotifier.UpdateFD(int32(s.fd))
+}
+
+// EventUnregister implements waiter.Waitable.EventUnregister.
+func (s *socketOpsCommon) EventUnregister(e *waiter.Entry) {
+ s.queue.EventUnregister(e)
+ fdnotifier.UpdateFD(int32(s.fd))
+}
+
// Connect implements socket.Socket.Connect.
func (s *socketOpsCommon) Connect(t *kernel.Task, sockaddr []byte, blocking bool) *syserr.Error {
if len(sockaddr) > sizeofSockaddr {
@@ -596,6 +647,17 @@ func (s *socketOpsCommon) SendMsg(t *kernel.Task, src usermem.IOSequence, to []b
return 0, syserr.ErrInvalidArgument
}
+ // If the src is zero-length, call SENDTO directly with a null buffer in
+ // order to generate poll/epoll notifications.
+ if src.NumBytes() == 0 {
+ sysflags := flags | unix.MSG_DONTWAIT
+ n, _, errno := unix.Syscall6(unix.SYS_SENDTO, uintptr(s.fd), 0, 0, uintptr(sysflags), uintptr(firstBytePtr(to)), uintptr(len(to)))
+ if errno != 0 {
+ return 0, syserr.FromError(errno)
+ }
+ return int(n), nil
+ }
+
space := uint64(control.CmsgsSpace(t, controlMessages))
if space > maxControlLen {
space = maxControlLen
@@ -653,7 +715,7 @@ func (s *socketOpsCommon) SendMsg(t *kernel.Task, src usermem.IOSequence, to []b
}
if ch != nil {
if err = t.BlockWithDeadline(ch, haveDeadline, deadline); err != nil {
- if err == syserror.ETIMEDOUT {
+ if linuxerr.Equals(linuxerr.ETIMEDOUT, err) {
err = syserror.ErrWouldBlock
}
break
@@ -709,56 +771,6 @@ type socketProvider struct {
family int
}
-// Socket implements socket.Provider.Socket.
-func (p *socketProvider) Socket(t *kernel.Task, stypeflags linux.SockType, protocol int) (*fs.File, *syserr.Error) {
- // Check that we are using the host network stack.
- stack := t.NetworkContext()
- if stack == nil {
- return nil, nil
- }
- if _, ok := stack.(*Stack); !ok {
- return nil, nil
- }
-
- // Only accept TCP and UDP.
- stype := stypeflags & linux.SOCK_TYPE_MASK
- switch stype {
- case unix.SOCK_STREAM:
- switch protocol {
- case 0, unix.IPPROTO_TCP:
- // ok
- default:
- return nil, nil
- }
- case unix.SOCK_DGRAM:
- switch protocol {
- case 0, unix.IPPROTO_UDP:
- // ok
- default:
- return nil, nil
- }
- default:
- return nil, nil
- }
-
- // Conservatively ignore all flags specified by the application and add
- // SOCK_NONBLOCK since socketOperations requires it. Pass a protocol of 0
- // to simplify the syscall filters, since 0 and IPPROTO_* are equivalent.
- fd, err := unix.Socket(p.family, int(stype)|unix.SOCK_NONBLOCK|unix.SOCK_CLOEXEC, 0)
- if err != nil {
- return nil, syserr.FromError(err)
- }
- return newSocketFile(t, p.family, stype, protocol, fd, stypeflags&unix.SOCK_NONBLOCK != 0)
-}
-
-// Pair implements socket.Provider.Pair.
-func (p *socketProvider) Pair(t *kernel.Task, stype linux.SockType, protocol int) (*fs.File, *fs.File, *syserr.Error) {
- // Not supported by AF_INET/AF_INET6.
- return nil, nil, nil
-}
-
-// LINT.ThenChange(./socket_vfs2.go)
-
func init() {
for _, family := range []int{unix.AF_INET, unix.AF_INET6} {
socket.RegisterProvider(family, &socketProvider{family})
diff --git a/pkg/sentry/socket/hostinet/socket_unsafe.go b/pkg/sentry/socket/hostinet/socket_unsafe.go
index d3be2d825..86dc879d5 100644
--- a/pkg/sentry/socket/hostinet/socket_unsafe.go
+++ b/pkg/sentry/socket/hostinet/socket_unsafe.go
@@ -67,7 +67,23 @@ func ioctl(ctx context.Context, fd int, io usermem.IO, args arch.SyscallArgument
AddressSpaceActive: true,
})
return 0, err
-
+ case unix.SIOCGIFFLAGS:
+ cc := &usermem.IOCopyContext{
+ Ctx: ctx,
+ IO: io,
+ Opts: usermem.IOOpts{
+ AddressSpaceActive: true,
+ },
+ }
+ var ifr linux.IFReq
+ if _, err := ifr.CopyIn(cc, args[2].Pointer()); err != nil {
+ return 0, err
+ }
+ if _, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(fd), cmd, uintptr(unsafe.Pointer(&ifr))); errno != 0 {
+ return 0, translateIOSyscallError(errno)
+ }
+ _, err := ifr.CopyOut(cc, args[2].Pointer())
+ return 0, err
default:
return 0, syserror.ENOTTY
}
diff --git a/pkg/sentry/socket/netfilter/BUILD b/pkg/sentry/socket/netfilter/BUILD
index 61b2c9755..608474fa1 100644
--- a/pkg/sentry/socket/netfilter/BUILD
+++ b/pkg/sentry/socket/netfilter/BUILD
@@ -25,6 +25,7 @@ go_library(
"//pkg/log",
"//pkg/marshal",
"//pkg/sentry/kernel",
+ "//pkg/sentry/kernel/auth",
"//pkg/syserr",
"//pkg/tcpip",
"//pkg/tcpip/header",
diff --git a/pkg/sentry/socket/netfilter/extensions.go b/pkg/sentry/socket/netfilter/extensions.go
index 6fc7781ad..3f1b4a17b 100644
--- a/pkg/sentry/socket/netfilter/extensions.go
+++ b/pkg/sentry/socket/netfilter/extensions.go
@@ -19,20 +19,12 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/bits"
+ "gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/syserr"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
-// TODO(gvisor.dev/issue/170): The following per-matcher params should be
-// supported:
-// - Table name
-// - Match size
-// - User size
-// - Hooks
-// - Proto
-// - Family
-
// matchMaker knows how to (un)marshal the matcher named name().
type matchMaker interface {
// name is the matcher name as stored in the xt_entry_match struct.
@@ -43,7 +35,7 @@ type matchMaker interface {
// unmarshal converts from the ABI matcher struct to an
// stack.Matcher.
- unmarshal(buf []byte, filter stack.IPHeaderFilter) (stack.Matcher, error)
+ unmarshal(task *kernel.Task, buf []byte, filter stack.IPHeaderFilter) (stack.Matcher, error)
}
type matcher interface {
@@ -94,12 +86,12 @@ func marshalEntryMatch(name string, data []byte) []byte {
return buf
}
-func unmarshalMatcher(match linux.XTEntryMatch, filter stack.IPHeaderFilter, buf []byte) (stack.Matcher, error) {
+func unmarshalMatcher(task *kernel.Task, match linux.XTEntryMatch, filter stack.IPHeaderFilter, buf []byte) (stack.Matcher, error) {
matchMaker, ok := matchMakers[match.Name.String()]
if !ok {
return nil, fmt.Errorf("unsupported matcher with name %q", match.Name.String())
}
- return matchMaker.unmarshal(buf, filter)
+ return matchMaker.unmarshal(task, buf, filter)
}
// targetMaker knows how to (un)marshal a target. Once registered,
diff --git a/pkg/sentry/socket/netfilter/ipv4.go b/pkg/sentry/socket/netfilter/ipv4.go
index cb78ef60b..d8bd86292 100644
--- a/pkg/sentry/socket/netfilter/ipv4.go
+++ b/pkg/sentry/socket/netfilter/ipv4.go
@@ -18,6 +18,7 @@ import (
"fmt"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/syserr"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/header"
@@ -123,7 +124,7 @@ func getEntries4(table stack.Table, tablename linux.TableName) (linux.KernelIPTG
return entries, info
}
-func modifyEntries4(stk *stack.Stack, optVal []byte, replace *linux.IPTReplace, table *stack.Table) (map[uint32]int, *syserr.Error) {
+func modifyEntries4(task *kernel.Task, stk *stack.Stack, optVal []byte, replace *linux.IPTReplace, table *stack.Table) (map[uint32]int, *syserr.Error) {
nflog("set entries: setting entries in table %q", replace.Name.String())
// Convert input into a list of rules and their offsets.
@@ -148,23 +149,19 @@ func modifyEntries4(stk *stack.Stack, optVal []byte, replace *linux.IPTReplace,
return nil, syserr.ErrInvalidArgument
}
- // TODO(gvisor.dev/issue/170): We should support more IPTIP
- // filtering fields.
filter, err := filterFromIPTIP(entry.IP)
if err != nil {
nflog("bad iptip: %v", err)
return nil, syserr.ErrInvalidArgument
}
- // TODO(gvisor.dev/issue/170): Matchers and targets can specify
- // that they only work for certain protocols, hooks, tables.
// Get matchers.
matchersSize := entry.TargetOffset - linux.SizeOfIPTEntry
if len(optVal) < int(matchersSize) {
nflog("entry doesn't have enough room for its matchers (only %d bytes remain)", len(optVal))
return nil, syserr.ErrInvalidArgument
}
- matchers, err := parseMatchers(filter, optVal[:matchersSize])
+ matchers, err := parseMatchers(task, filter, optVal[:matchersSize])
if err != nil {
nflog("failed to parse matchers: %v", err)
return nil, syserr.ErrInvalidArgument
diff --git a/pkg/sentry/socket/netfilter/ipv6.go b/pkg/sentry/socket/netfilter/ipv6.go
index 5cb7fe4aa..c68230847 100644
--- a/pkg/sentry/socket/netfilter/ipv6.go
+++ b/pkg/sentry/socket/netfilter/ipv6.go
@@ -18,6 +18,7 @@ import (
"fmt"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/syserr"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/header"
@@ -126,7 +127,7 @@ func getEntries6(table stack.Table, tablename linux.TableName) (linux.KernelIP6T
return entries, info
}
-func modifyEntries6(stk *stack.Stack, optVal []byte, replace *linux.IPTReplace, table *stack.Table) (map[uint32]int, *syserr.Error) {
+func modifyEntries6(task *kernel.Task, stk *stack.Stack, optVal []byte, replace *linux.IPTReplace, table *stack.Table) (map[uint32]int, *syserr.Error) {
nflog("set entries: setting entries in table %q", replace.Name.String())
// Convert input into a list of rules and their offsets.
@@ -151,23 +152,19 @@ func modifyEntries6(stk *stack.Stack, optVal []byte, replace *linux.IPTReplace,
return nil, syserr.ErrInvalidArgument
}
- // TODO(gvisor.dev/issue/170): We should support more IPTIP
- // filtering fields.
filter, err := filterFromIP6TIP(entry.IPv6)
if err != nil {
nflog("bad iptip: %v", err)
return nil, syserr.ErrInvalidArgument
}
- // TODO(gvisor.dev/issue/170): Matchers and targets can specify
- // that they only work for certain protocols, hooks, tables.
// Get matchers.
matchersSize := entry.TargetOffset - linux.SizeOfIP6TEntry
if len(optVal) < int(matchersSize) {
nflog("entry doesn't have enough room for its matchers (only %d bytes remain)", len(optVal))
return nil, syserr.ErrInvalidArgument
}
- matchers, err := parseMatchers(filter, optVal[:matchersSize])
+ matchers, err := parseMatchers(task, filter, optVal[:matchersSize])
if err != nil {
nflog("failed to parse matchers: %v", err)
return nil, syserr.ErrInvalidArgument
diff --git a/pkg/sentry/socket/netfilter/netfilter.go b/pkg/sentry/socket/netfilter/netfilter.go
index f42d73178..e3eade180 100644
--- a/pkg/sentry/socket/netfilter/netfilter.go
+++ b/pkg/sentry/socket/netfilter/netfilter.go
@@ -58,8 +58,8 @@ var nameToID = map[string]stack.TableID{
// DefaultLinuxTables returns the rules of stack.DefaultTables() wrapped for
// compatibility with netfilter extensions.
-func DefaultLinuxTables() *stack.IPTables {
- tables := stack.DefaultTables()
+func DefaultLinuxTables(seed uint32) *stack.IPTables {
+ tables := stack.DefaultTables(seed)
tables.VisitTargets(func(oldTarget stack.Target) stack.Target {
switch val := oldTarget.(type) {
case *stack.AcceptTarget:
@@ -174,13 +174,12 @@ func setHooksAndUnderflow(info *linux.IPTGetinfo, table stack.Table, offset uint
// SetEntries sets iptables rules for a single table. See
// net/ipv4/netfilter/ip_tables.c:translate_table for reference.
-func SetEntries(stk *stack.Stack, optVal []byte, ipv6 bool) *syserr.Error {
+func SetEntries(task *kernel.Task, stk *stack.Stack, optVal []byte, ipv6 bool) *syserr.Error {
var replace linux.IPTReplace
replaceBuf := optVal[:linux.SizeOfIPTReplace]
optVal = optVal[linux.SizeOfIPTReplace:]
replace.UnmarshalBytes(replaceBuf)
- // TODO(gvisor.dev/issue/170): Support other tables.
var table stack.Table
switch replace.Name.String() {
case filterTable:
@@ -188,16 +187,16 @@ func SetEntries(stk *stack.Stack, optVal []byte, ipv6 bool) *syserr.Error {
case natTable:
table = stack.EmptyNATTable()
default:
- nflog("we don't yet support writing to the %q table (gvisor.dev/issue/170)", replace.Name.String())
+ nflog("unknown iptables table %q", replace.Name.String())
return syserr.ErrInvalidArgument
}
var err *syserr.Error
var offsets map[uint32]int
if ipv6 {
- offsets, err = modifyEntries6(stk, optVal, &replace, &table)
+ offsets, err = modifyEntries6(task, stk, optVal, &replace, &table)
} else {
- offsets, err = modifyEntries4(stk, optVal, &replace, &table)
+ offsets, err = modifyEntries4(task, stk, optVal, &replace, &table)
}
if err != nil {
return err
@@ -272,7 +271,6 @@ func SetEntries(stk *stack.Stack, optVal []byte, ipv6 bool) *syserr.Error {
table.Rules[ruleIdx] = rule
}
- // TODO(gvisor.dev/issue/170): Support other chains.
// Since we don't support FORWARD, yet, make sure all other chains point to
// ACCEPT rules.
for hook, ruleIdx := range table.BuiltinChains {
@@ -287,7 +285,7 @@ func SetEntries(stk *stack.Stack, optVal []byte, ipv6 bool) *syserr.Error {
}
}
- // TODO(gvisor.dev/issue/170): Check the following conditions:
+ // TODO(gvisor.dev/issue/6167): Check the following conditions:
// - There are no loops.
// - There are no chains without an unconditional final rule.
// - There are no chains without an unconditional underflow rule.
@@ -297,7 +295,7 @@ func SetEntries(stk *stack.Stack, optVal []byte, ipv6 bool) *syserr.Error {
// parseMatchers parses 0 or more matchers from optVal. optVal should contain
// only the matchers.
-func parseMatchers(filter stack.IPHeaderFilter, optVal []byte) ([]stack.Matcher, error) {
+func parseMatchers(task *kernel.Task, filter stack.IPHeaderFilter, optVal []byte) ([]stack.Matcher, error) {
nflog("set entries: parsing matchers of size %d", len(optVal))
var matchers []stack.Matcher
for len(optVal) > 0 {
@@ -321,13 +319,13 @@ func parseMatchers(filter stack.IPHeaderFilter, optVal []byte) ([]stack.Matcher,
}
// Parse the specific matcher.
- matcher, err := unmarshalMatcher(match, filter, optVal[linux.SizeOfXTEntryMatch:match.MatchSize])
+ matcher, err := unmarshalMatcher(task, match, filter, optVal[linux.SizeOfXTEntryMatch:match.MatchSize])
if err != nil {
return nil, fmt.Errorf("failed to create matcher: %v", err)
}
matchers = append(matchers, matcher)
- // TODO(gvisor.dev/issue/170): Check the revision field.
+ // TODO(gvisor.dev/issue/6167): Check the revision field.
optVal = optVal[match.MatchSize:]
}
diff --git a/pkg/sentry/socket/netfilter/owner_matcher.go b/pkg/sentry/socket/netfilter/owner_matcher.go
index 60845cab3..6eff2ae65 100644
--- a/pkg/sentry/socket/netfilter/owner_matcher.go
+++ b/pkg/sentry/socket/netfilter/owner_matcher.go
@@ -19,6 +19,8 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/marshal"
+ "gvisor.dev/gvisor/pkg/sentry/kernel"
+ "gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
@@ -40,8 +42,8 @@ func (ownerMarshaler) name() string {
func (ownerMarshaler) marshal(mr matcher) []byte {
matcher := mr.(*OwnerMatcher)
iptOwnerInfo := linux.IPTOwnerInfo{
- UID: matcher.uid,
- GID: matcher.gid,
+ UID: uint32(matcher.uid),
+ GID: uint32(matcher.gid),
}
// Support for UID and GID match.
@@ -63,7 +65,7 @@ func (ownerMarshaler) marshal(mr matcher) []byte {
}
// unmarshal implements matchMaker.unmarshal.
-func (ownerMarshaler) unmarshal(buf []byte, filter stack.IPHeaderFilter) (stack.Matcher, error) {
+func (ownerMarshaler) unmarshal(task *kernel.Task, buf []byte, filter stack.IPHeaderFilter) (stack.Matcher, error) {
if len(buf) < linux.SizeOfIPTOwnerInfo {
return nil, fmt.Errorf("buf has insufficient size for owner match: %d", len(buf))
}
@@ -72,11 +74,12 @@ func (ownerMarshaler) unmarshal(buf []byte, filter stack.IPHeaderFilter) (stack.
// exceed what's strictly necessary to hold matchData.
var matchData linux.IPTOwnerInfo
matchData.UnmarshalUnsafe(buf[:linux.SizeOfIPTOwnerInfo])
- nflog("parseMatchers: parsed IPTOwnerInfo: %+v", matchData)
+ nflog("parsed IPTOwnerInfo: %+v", matchData)
var owner OwnerMatcher
- owner.uid = matchData.UID
- owner.gid = matchData.GID
+ creds := task.Credentials()
+ owner.uid = creds.UserNamespace.MapToKUID(auth.UID(matchData.UID))
+ owner.gid = creds.UserNamespace.MapToKGID(auth.GID(matchData.GID))
// Check flags.
if matchData.Match&linux.XT_OWNER_UID != 0 {
@@ -97,8 +100,8 @@ func (ownerMarshaler) unmarshal(buf []byte, filter stack.IPHeaderFilter) (stack.
// OwnerMatcher matches against a UID and/or GID.
type OwnerMatcher struct {
- uid uint32
- gid uint32
+ uid auth.KUID
+ gid auth.KGID
matchUID bool
matchGID bool
invertUID bool
@@ -113,7 +116,6 @@ func (*OwnerMatcher) name() string {
// Match implements Matcher.Match.
func (om *OwnerMatcher) Match(hook stack.Hook, pkt *stack.PacketBuffer, _, _ string) (bool, bool) {
// Support only for OUTPUT chain.
- // TODO(gvisor.dev/issue/170): Need to support for POSTROUTING chain also.
if hook != stack.Output {
return false, true
}
@@ -126,7 +128,7 @@ func (om *OwnerMatcher) Match(hook stack.Hook, pkt *stack.PacketBuffer, _, _ str
var matches bool
// Check for UID match.
if om.matchUID {
- if pkt.Owner.UID() == om.uid {
+ if auth.KUID(pkt.Owner.KUID()) == om.uid {
matches = true
}
if matches == om.invertUID {
@@ -137,7 +139,7 @@ func (om *OwnerMatcher) Match(hook stack.Hook, pkt *stack.PacketBuffer, _, _ str
// Check for GID match.
if om.matchGID {
matches = false
- if pkt.Owner.GID() == om.gid {
+ if auth.KGID(pkt.Owner.KGID()) == om.gid {
matches = true
}
if matches == om.invertGID {
diff --git a/pkg/sentry/socket/netfilter/targets.go b/pkg/sentry/socket/netfilter/targets.go
index fa5456eee..ea56f39c1 100644
--- a/pkg/sentry/socket/netfilter/targets.go
+++ b/pkg/sentry/socket/netfilter/targets.go
@@ -331,7 +331,6 @@ func (*redirectTargetMaker) unmarshal(buf []byte, filter stack.IPHeaderFilter) (
return nil, syserr.ErrInvalidArgument
}
- // TODO(gvisor.dev/issue/170): Check if the flags are valid.
// Also check if we need to map ports or IP.
// For now, redirect target only supports destination port change.
// Port range and IP range are not supported yet.
@@ -340,7 +339,6 @@ func (*redirectTargetMaker) unmarshal(buf []byte, filter stack.IPHeaderFilter) (
return nil, syserr.ErrInvalidArgument
}
- // TODO(gvisor.dev/issue/170): Port range is not supported yet.
if nfRange.RangeIPV4.MinPort != nfRange.RangeIPV4.MaxPort {
nflog("redirectTargetMaker: MinPort != MaxPort (%d, %d)", nfRange.RangeIPV4.MinPort, nfRange.RangeIPV4.MaxPort)
return nil, syserr.ErrInvalidArgument
@@ -420,7 +418,6 @@ func (*nfNATTargetMaker) unmarshal(buf []byte, filter stack.IPHeaderFilter) (tar
return nil, syserr.ErrInvalidArgument
}
- // TODO(gvisor.dev/issue/3549): Check for other flags.
// For now, redirect target only supports destination change.
if natRange.Flags != linux.NF_NAT_RANGE_PROTO_SPECIFIED {
nflog("nfNATTargetMaker: invalid range flags %d", natRange.Flags)
@@ -502,7 +499,6 @@ func (*snatTargetMakerV4) unmarshal(buf []byte, filter stack.IPHeaderFilter) (ta
return nil, syserr.ErrInvalidArgument
}
- // TODO(gvisor.dev/issue/170): Port range is not supported yet.
if nfRange.RangeIPV4.MinPort != nfRange.RangeIPV4.MaxPort {
nflog("snatTargetMakerV4: MinPort != MaxPort (%d, %d)", nfRange.RangeIPV4.MinPort, nfRange.RangeIPV4.MaxPort)
return nil, syserr.ErrInvalidArgument
@@ -594,7 +590,6 @@ func (*snatTargetMakerV6) unmarshal(buf []byte, filter stack.IPHeaderFilter) (ta
// translateToStandardTarget translates from the value in a
// linux.XTStandardTarget to an stack.Verdict.
func translateToStandardTarget(val int32, netProto tcpip.NetworkProtocolNumber) (target, *syserr.Error) {
- // TODO(gvisor.dev/issue/170): Support other verdicts.
switch val {
case -linux.NF_ACCEPT - 1:
return &acceptTarget{stack.AcceptTarget{
diff --git a/pkg/sentry/socket/netfilter/tcp_matcher.go b/pkg/sentry/socket/netfilter/tcp_matcher.go
index 95bb9826e..e5b73a976 100644
--- a/pkg/sentry/socket/netfilter/tcp_matcher.go
+++ b/pkg/sentry/socket/netfilter/tcp_matcher.go
@@ -19,6 +19,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/marshal"
+ "gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
@@ -50,7 +51,7 @@ func (tcpMarshaler) marshal(mr matcher) []byte {
}
// unmarshal implements matchMaker.unmarshal.
-func (tcpMarshaler) unmarshal(buf []byte, filter stack.IPHeaderFilter) (stack.Matcher, error) {
+func (tcpMarshaler) unmarshal(_ *kernel.Task, buf []byte, filter stack.IPHeaderFilter) (stack.Matcher, error) {
if len(buf) < linux.SizeOfXTTCP {
return nil, fmt.Errorf("buf has insufficient size for TCP match: %d", len(buf))
}
@@ -95,8 +96,6 @@ func (*TCPMatcher) name() string {
// Match implements Matcher.Match.
func (tm *TCPMatcher) Match(hook stack.Hook, pkt *stack.PacketBuffer, _, _ string) (bool, bool) {
- // TODO(gvisor.dev/issue/170): Proto checks should ultimately be moved
- // into the stack.Check codepath as matchers are added.
switch pkt.NetworkProtocolNumber {
case header.IPv4ProtocolNumber:
netHeader := header.IPv4(pkt.NetworkHeader().View())
diff --git a/pkg/sentry/socket/netfilter/udp_matcher.go b/pkg/sentry/socket/netfilter/udp_matcher.go
index fb8be27e6..aa72ee70c 100644
--- a/pkg/sentry/socket/netfilter/udp_matcher.go
+++ b/pkg/sentry/socket/netfilter/udp_matcher.go
@@ -19,6 +19,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/marshal"
+ "gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
@@ -50,7 +51,7 @@ func (udpMarshaler) marshal(mr matcher) []byte {
}
// unmarshal implements matchMaker.unmarshal.
-func (udpMarshaler) unmarshal(buf []byte, filter stack.IPHeaderFilter) (stack.Matcher, error) {
+func (udpMarshaler) unmarshal(_ *kernel.Task, buf []byte, filter stack.IPHeaderFilter) (stack.Matcher, error) {
if len(buf) < linux.SizeOfXTUDP {
return nil, fmt.Errorf("buf has insufficient size for UDP match: %d", len(buf))
}
@@ -92,8 +93,6 @@ func (*UDPMatcher) name() string {
// Match implements Matcher.Match.
func (um *UDPMatcher) Match(hook stack.Hook, pkt *stack.PacketBuffer, _, _ string) (bool, bool) {
- // TODO(gvisor.dev/issue/170): Proto checks should ultimately be moved
- // into the stack.Check codepath as matchers are added.
switch pkt.NetworkProtocolNumber {
case header.IPv4ProtocolNumber:
netHeader := header.IPv4(pkt.NetworkHeader().View())
diff --git a/pkg/sentry/socket/netlink/BUILD b/pkg/sentry/socket/netlink/BUILD
index 64cd263da..ed85404da 100644
--- a/pkg/sentry/socket/netlink/BUILD
+++ b/pkg/sentry/socket/netlink/BUILD
@@ -14,8 +14,10 @@ go_library(
visibility = ["//pkg/sentry:internal"],
deps = [
"//pkg/abi/linux",
+ "//pkg/abi/linux/errno",
"//pkg/bits",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/hostarch",
"//pkg/marshal",
"//pkg/marshal/primitive",
diff --git a/pkg/sentry/socket/netlink/socket.go b/pkg/sentry/socket/netlink/socket.go
index 280563d09..d53f23a9a 100644
--- a/pkg/sentry/socket/netlink/socket.go
+++ b/pkg/sentry/socket/netlink/socket.go
@@ -20,7 +20,9 @@ import (
"math"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/abi/linux/errno"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/marshal"
"gvisor.dev/gvisor/pkg/marshal/primitive"
@@ -56,7 +58,7 @@ const (
maxSendBufferSize = 4 << 20 // 4MB
)
-var errNoFilter = syserr.New("no filter attached", linux.ENOENT)
+var errNoFilter = syserr.New("no filter attached", errno.ENOENT)
// netlinkSocketDevice is the netlink socket virtual device.
var netlinkSocketDevice = device.NewAnonDevice()
@@ -558,7 +560,7 @@ func (s *socketOpsCommon) RecvMsg(t *kernel.Task, dst usermem.IOSequence, flags
}
if err := t.BlockWithDeadline(ch, haveDeadline, deadline); err != nil {
- if err == syserror.ETIMEDOUT {
+ if linuxerr.Equals(linuxerr.ETIMEDOUT, err) {
return 0, 0, nil, 0, socket.ControlMessages{}, syserr.ErrTryAgain
}
return 0, 0, nil, 0, socket.ControlMessages{}, syserr.FromError(err)
diff --git a/pkg/sentry/socket/netstack/BUILD b/pkg/sentry/socket/netstack/BUILD
index 9561b7c25..e828982eb 100644
--- a/pkg/sentry/socket/netstack/BUILD
+++ b/pkg/sentry/socket/netstack/BUILD
@@ -19,7 +19,9 @@ go_library(
],
deps = [
"//pkg/abi/linux",
+ "//pkg/abi/linux/errno",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/hostarch",
"//pkg/log",
"//pkg/marshal",
diff --git a/pkg/sentry/socket/netstack/netstack.go b/pkg/sentry/socket/netstack/netstack.go
index 0b64a24c3..11f75628c 100644
--- a/pkg/sentry/socket/netstack/netstack.go
+++ b/pkg/sentry/socket/netstack/netstack.go
@@ -36,7 +36,9 @@ import (
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/abi/linux/errno"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/marshal"
@@ -77,41 +79,59 @@ func mustCreateGauge(name, description string) *tcpip.StatCounter {
// Metrics contains metrics exported by netstack.
var Metrics = tcpip.Stats{
- UnknownProtocolRcvdPackets: mustCreateMetric("/netstack/unknown_protocol_received_packets", "Number of packets received by netstack that were for an unknown or unsupported protocol."),
- MalformedRcvdPackets: mustCreateMetric("/netstack/malformed_received_packets", "Number of packets received by netstack that were deemed malformed."),
- DroppedPackets: mustCreateMetric("/netstack/dropped_packets", "Number of packets dropped by netstack due to full queues."),
+ DroppedPackets: mustCreateMetric("/netstack/dropped_packets", "Number of packets dropped at the transport layer."),
+ NICs: tcpip.NICStats{
+ UnknownL3ProtocolRcvdPackets: mustCreateMetric("/netstack/nic/unknown_l3_protocol_received_packets", "Number of packets received that were for an unknown or unsupported L3 protocol."),
+ UnknownL4ProtocolRcvdPackets: mustCreateMetric("/netstack/nic/unknown_l4_protocol_received_packets", "Number of packets received that were for an unknown or unsupported L4 protocol."),
+ MalformedL4RcvdPackets: mustCreateMetric("/netstack/nic/malformed_l4_received_packets", "Number of packets received that failed L4 header parsing."),
+ Tx: tcpip.NICPacketStats{
+ Packets: mustCreateMetric("/netstack/nic/tx/packets", "Number of packets transmitted."),
+ Bytes: mustCreateMetric("/netstack/nic/tx/bytes", "Number of bytes transmitted."),
+ },
+ Rx: tcpip.NICPacketStats{
+ Packets: mustCreateMetric("/netstack/nic/rx/packets", "Number of packets received."),
+ Bytes: mustCreateMetric("/netstack/nic/rx/bytes", "Number of bytes received."),
+ },
+ DisabledRx: tcpip.NICPacketStats{
+ Packets: mustCreateMetric("/netstack/nic/disabled_rx/packets", "Number of packets received on disabled NICs."),
+ Bytes: mustCreateMetric("/netstack/nic/disabled_rx/bytes", "Number of bytes received on disabled NICs."),
+ },
+ Neighbor: tcpip.NICNeighborStats{
+ UnreachableEntryLookups: mustCreateMetric("/netstack/nic/neighbor/unreachable_entry_loopups", "Number of lookups performed on a neighbor entry in Unreachable state."),
+ },
+ },
ICMP: tcpip.ICMPStats{
V4: tcpip.ICMPv4Stats{
PacketsSent: tcpip.ICMPv4SentPacketStats{
ICMPv4PacketStats: tcpip.ICMPv4PacketStats{
- EchoRequest: mustCreateMetric("/netstack/icmp/v4/packets_sent/echo_request", "Number of ICMPv4 echo request packets sent by netstack."),
- EchoReply: mustCreateMetric("/netstack/icmp/v4/packets_sent/echo_reply", "Number of ICMPv4 echo reply packets sent by netstack."),
- DstUnreachable: mustCreateMetric("/netstack/icmp/v4/packets_sent/dst_unreachable", "Number of ICMPv4 destination unreachable packets sent by netstack."),
- SrcQuench: mustCreateMetric("/netstack/icmp/v4/packets_sent/src_quench", "Number of ICMPv4 source quench packets sent by netstack."),
- Redirect: mustCreateMetric("/netstack/icmp/v4/packets_sent/redirect", "Number of ICMPv4 redirect packets sent by netstack."),
- TimeExceeded: mustCreateMetric("/netstack/icmp/v4/packets_sent/time_exceeded", "Number of ICMPv4 time exceeded packets sent by netstack."),
- ParamProblem: mustCreateMetric("/netstack/icmp/v4/packets_sent/param_problem", "Number of ICMPv4 parameter problem packets sent by netstack."),
- Timestamp: mustCreateMetric("/netstack/icmp/v4/packets_sent/timestamp", "Number of ICMPv4 timestamp packets sent by netstack."),
- TimestampReply: mustCreateMetric("/netstack/icmp/v4/packets_sent/timestamp_reply", "Number of ICMPv4 timestamp reply packets sent by netstack."),
- InfoRequest: mustCreateMetric("/netstack/icmp/v4/packets_sent/info_request", "Number of ICMPv4 information request packets sent by netstack."),
- InfoReply: mustCreateMetric("/netstack/icmp/v4/packets_sent/info_reply", "Number of ICMPv4 information reply packets sent by netstack."),
+ EchoRequest: mustCreateMetric("/netstack/icmp/v4/packets_sent/echo_request", "Number of ICMPv4 echo request packets sent."),
+ EchoReply: mustCreateMetric("/netstack/icmp/v4/packets_sent/echo_reply", "Number of ICMPv4 echo reply packets sent."),
+ DstUnreachable: mustCreateMetric("/netstack/icmp/v4/packets_sent/dst_unreachable", "Number of ICMPv4 destination unreachable packets sent."),
+ SrcQuench: mustCreateMetric("/netstack/icmp/v4/packets_sent/src_quench", "Number of ICMPv4 source quench packets sent."),
+ Redirect: mustCreateMetric("/netstack/icmp/v4/packets_sent/redirect", "Number of ICMPv4 redirect packets sent."),
+ TimeExceeded: mustCreateMetric("/netstack/icmp/v4/packets_sent/time_exceeded", "Number of ICMPv4 time exceeded packets sent."),
+ ParamProblem: mustCreateMetric("/netstack/icmp/v4/packets_sent/param_problem", "Number of ICMPv4 parameter problem packets sent."),
+ Timestamp: mustCreateMetric("/netstack/icmp/v4/packets_sent/timestamp", "Number of ICMPv4 timestamp packets sent."),
+ TimestampReply: mustCreateMetric("/netstack/icmp/v4/packets_sent/timestamp_reply", "Number of ICMPv4 timestamp reply packets sent."),
+ InfoRequest: mustCreateMetric("/netstack/icmp/v4/packets_sent/info_request", "Number of ICMPv4 information request packets sent."),
+ InfoReply: mustCreateMetric("/netstack/icmp/v4/packets_sent/info_reply", "Number of ICMPv4 information reply packets sent."),
},
- Dropped: mustCreateMetric("/netstack/icmp/v4/packets_sent/dropped", "Number of ICMPv4 packets dropped by netstack due to link layer errors."),
- RateLimited: mustCreateMetric("/netstack/icmp/v4/packets_sent/rate_limited", "Number of ICMPv4 packets dropped by netstack due to rate limit being exceeded."),
+ Dropped: mustCreateMetric("/netstack/icmp/v4/packets_sent/dropped", "Number of ICMPv4 packets dropped due to link layer errors."),
+ RateLimited: mustCreateMetric("/netstack/icmp/v4/packets_sent/rate_limited", "Number of ICMPv4 packets dropped due to rate limit being exceeded."),
},
PacketsReceived: tcpip.ICMPv4ReceivedPacketStats{
ICMPv4PacketStats: tcpip.ICMPv4PacketStats{
- EchoRequest: mustCreateMetric("/netstack/icmp/v4/packets_received/echo_request", "Number of ICMPv4 echo request packets received by netstack."),
- EchoReply: mustCreateMetric("/netstack/icmp/v4/packets_received/echo_reply", "Number of ICMPv4 echo reply packets received by netstack."),
- DstUnreachable: mustCreateMetric("/netstack/icmp/v4/packets_received/dst_unreachable", "Number of ICMPv4 destination unreachable packets received by netstack."),
- SrcQuench: mustCreateMetric("/netstack/icmp/v4/packets_received/src_quench", "Number of ICMPv4 source quench packets received by netstack."),
- Redirect: mustCreateMetric("/netstack/icmp/v4/packets_received/redirect", "Number of ICMPv4 redirect packets received by netstack."),
- TimeExceeded: mustCreateMetric("/netstack/icmp/v4/packets_received/time_exceeded", "Number of ICMPv4 time exceeded packets received by netstack."),
- ParamProblem: mustCreateMetric("/netstack/icmp/v4/packets_received/param_problem", "Number of ICMPv4 parameter problem packets received by netstack."),
- Timestamp: mustCreateMetric("/netstack/icmp/v4/packets_received/timestamp", "Number of ICMPv4 timestamp packets received by netstack."),
- TimestampReply: mustCreateMetric("/netstack/icmp/v4/packets_received/timestamp_reply", "Number of ICMPv4 timestamp reply packets received by netstack."),
- InfoRequest: mustCreateMetric("/netstack/icmp/v4/packets_received/info_request", "Number of ICMPv4 information request packets received by netstack."),
- InfoReply: mustCreateMetric("/netstack/icmp/v4/packets_received/info_reply", "Number of ICMPv4 information reply packets received by netstack."),
+ EchoRequest: mustCreateMetric("/netstack/icmp/v4/packets_received/echo_request", "Number of ICMPv4 echo request packets received."),
+ EchoReply: mustCreateMetric("/netstack/icmp/v4/packets_received/echo_reply", "Number of ICMPv4 echo reply packets received."),
+ DstUnreachable: mustCreateMetric("/netstack/icmp/v4/packets_received/dst_unreachable", "Number of ICMPv4 destination unreachable packets received."),
+ SrcQuench: mustCreateMetric("/netstack/icmp/v4/packets_received/src_quench", "Number of ICMPv4 source quench packets received."),
+ Redirect: mustCreateMetric("/netstack/icmp/v4/packets_received/redirect", "Number of ICMPv4 redirect packets received."),
+ TimeExceeded: mustCreateMetric("/netstack/icmp/v4/packets_received/time_exceeded", "Number of ICMPv4 time exceeded packets received."),
+ ParamProblem: mustCreateMetric("/netstack/icmp/v4/packets_received/param_problem", "Number of ICMPv4 parameter problem packets received."),
+ Timestamp: mustCreateMetric("/netstack/icmp/v4/packets_received/timestamp", "Number of ICMPv4 timestamp packets received."),
+ TimestampReply: mustCreateMetric("/netstack/icmp/v4/packets_received/timestamp_reply", "Number of ICMPv4 timestamp reply packets received."),
+ InfoRequest: mustCreateMetric("/netstack/icmp/v4/packets_received/info_request", "Number of ICMPv4 information request packets received."),
+ InfoReply: mustCreateMetric("/netstack/icmp/v4/packets_received/info_reply", "Number of ICMPv4 information reply packets received."),
},
Invalid: mustCreateMetric("/netstack/icmp/v4/packets_received/invalid", "Number of ICMPv4 packets received that the transport layer could not parse."),
},
@@ -119,40 +139,40 @@ var Metrics = tcpip.Stats{
V6: tcpip.ICMPv6Stats{
PacketsSent: tcpip.ICMPv6SentPacketStats{
ICMPv6PacketStats: tcpip.ICMPv6PacketStats{
- EchoRequest: mustCreateMetric("/netstack/icmp/v6/packets_sent/echo_request", "Number of ICMPv6 echo request packets sent by netstack."),
- EchoReply: mustCreateMetric("/netstack/icmp/v6/packets_sent/echo_reply", "Number of ICMPv6 echo reply packets sent by netstack."),
- DstUnreachable: mustCreateMetric("/netstack/icmp/v6/packets_sent/dst_unreachable", "Number of ICMPv6 destination unreachable packets sent by netstack."),
- PacketTooBig: mustCreateMetric("/netstack/icmp/v6/packets_sent/packet_too_big", "Number of ICMPv6 packet too big packets sent by netstack."),
- TimeExceeded: mustCreateMetric("/netstack/icmp/v6/packets_sent/time_exceeded", "Number of ICMPv6 time exceeded packets sent by netstack."),
- ParamProblem: mustCreateMetric("/netstack/icmp/v6/packets_sent/param_problem", "Number of ICMPv6 parameter problem packets sent by netstack."),
- RouterSolicit: mustCreateMetric("/netstack/icmp/v6/packets_sent/router_solicit", "Number of ICMPv6 router solicit packets sent by netstack."),
- RouterAdvert: mustCreateMetric("/netstack/icmp/v6/packets_sent/router_advert", "Number of ICMPv6 router advert packets sent by netstack."),
- NeighborSolicit: mustCreateMetric("/netstack/icmp/v6/packets_sent/neighbor_solicit", "Number of ICMPv6 neighbor solicit packets sent by netstack."),
- NeighborAdvert: mustCreateMetric("/netstack/icmp/v6/packets_sent/neighbor_advert", "Number of ICMPv6 neighbor advert packets sent by netstack."),
- RedirectMsg: mustCreateMetric("/netstack/icmp/v6/packets_sent/redirect_msg", "Number of ICMPv6 redirect message packets sent by netstack."),
- MulticastListenerQuery: mustCreateMetric("/netstack/icmp/v6/packets_sent/multicast_listener_query", "Number of ICMPv6 multicast listener query packets sent by netstack."),
- MulticastListenerReport: mustCreateMetric("/netstack/icmp/v6/packets_sent/multicast_listener_report", "Number of ICMPv6 multicast listener report packets sent by netstack."),
- MulticastListenerDone: mustCreateMetric("/netstack/icmp/v6/packets_sent/multicast_listener_done", "Number of ICMPv6 multicast listener done packets sent by netstack."),
+ EchoRequest: mustCreateMetric("/netstack/icmp/v6/packets_sent/echo_request", "Number of ICMPv6 echo request packets sent."),
+ EchoReply: mustCreateMetric("/netstack/icmp/v6/packets_sent/echo_reply", "Number of ICMPv6 echo reply packets sent."),
+ DstUnreachable: mustCreateMetric("/netstack/icmp/v6/packets_sent/dst_unreachable", "Number of ICMPv6 destination unreachable packets sent."),
+ PacketTooBig: mustCreateMetric("/netstack/icmp/v6/packets_sent/packet_too_big", "Number of ICMPv6 packet too big packets sent."),
+ TimeExceeded: mustCreateMetric("/netstack/icmp/v6/packets_sent/time_exceeded", "Number of ICMPv6 time exceeded packets sent."),
+ ParamProblem: mustCreateMetric("/netstack/icmp/v6/packets_sent/param_problem", "Number of ICMPv6 parameter problem packets sent."),
+ RouterSolicit: mustCreateMetric("/netstack/icmp/v6/packets_sent/router_solicit", "Number of ICMPv6 router solicit packets sent."),
+ RouterAdvert: mustCreateMetric("/netstack/icmp/v6/packets_sent/router_advert", "Number of ICMPv6 router advert packets sent."),
+ NeighborSolicit: mustCreateMetric("/netstack/icmp/v6/packets_sent/neighbor_solicit", "Number of ICMPv6 neighbor solicit packets sent."),
+ NeighborAdvert: mustCreateMetric("/netstack/icmp/v6/packets_sent/neighbor_advert", "Number of ICMPv6 neighbor advert packets sent."),
+ RedirectMsg: mustCreateMetric("/netstack/icmp/v6/packets_sent/redirect_msg", "Number of ICMPv6 redirect message packets sent."),
+ MulticastListenerQuery: mustCreateMetric("/netstack/icmp/v6/packets_sent/multicast_listener_query", "Number of ICMPv6 multicast listener query packets sent."),
+ MulticastListenerReport: mustCreateMetric("/netstack/icmp/v6/packets_sent/multicast_listener_report", "Number of ICMPv6 multicast listener report packets sent."),
+ MulticastListenerDone: mustCreateMetric("/netstack/icmp/v6/packets_sent/multicast_listener_done", "Number of ICMPv6 multicast listener done packets sent."),
},
- Dropped: mustCreateMetric("/netstack/icmp/v6/packets_sent/dropped", "Number of ICMPv6 packets dropped by netstack due to link layer errors."),
- RateLimited: mustCreateMetric("/netstack/icmp/v6/packets_sent/rate_limited", "Number of ICMPv6 packets dropped by netstack due to rate limit being exceeded."),
+ Dropped: mustCreateMetric("/netstack/icmp/v6/packets_sent/dropped", "Number of ICMPv6 packets dropped due to link layer errors."),
+ RateLimited: mustCreateMetric("/netstack/icmp/v6/packets_sent/rate_limited", "Number of ICMPv6 packets dropped due to rate limit being exceeded."),
},
PacketsReceived: tcpip.ICMPv6ReceivedPacketStats{
ICMPv6PacketStats: tcpip.ICMPv6PacketStats{
- EchoRequest: mustCreateMetric("/netstack/icmp/v6/packets_received/echo_request", "Number of ICMPv6 echo request packets received by netstack."),
- EchoReply: mustCreateMetric("/netstack/icmp/v6/packets_received/echo_reply", "Number of ICMPv6 echo reply packets received by netstack."),
- DstUnreachable: mustCreateMetric("/netstack/icmp/v6/packets_received/dst_unreachable", "Number of ICMPv6 destination unreachable packets received by netstack."),
- PacketTooBig: mustCreateMetric("/netstack/icmp/v6/packets_received/packet_too_big", "Number of ICMPv6 packet too big packets received by netstack."),
- TimeExceeded: mustCreateMetric("/netstack/icmp/v6/packets_received/time_exceeded", "Number of ICMPv6 time exceeded packets received by netstack."),
- ParamProblem: mustCreateMetric("/netstack/icmp/v6/packets_received/param_problem", "Number of ICMPv6 parameter problem packets received by netstack."),
- RouterSolicit: mustCreateMetric("/netstack/icmp/v6/packets_received/router_solicit", "Number of ICMPv6 router solicit packets received by netstack."),
- RouterAdvert: mustCreateMetric("/netstack/icmp/v6/packets_received/router_advert", "Number of ICMPv6 router advert packets received by netstack."),
- NeighborSolicit: mustCreateMetric("/netstack/icmp/v6/packets_received/neighbor_solicit", "Number of ICMPv6 neighbor solicit packets received by netstack."),
- NeighborAdvert: mustCreateMetric("/netstack/icmp/v6/packets_received/neighbor_advert", "Number of ICMPv6 neighbor advert packets received by netstack."),
- RedirectMsg: mustCreateMetric("/netstack/icmp/v6/packets_received/redirect_msg", "Number of ICMPv6 redirect message packets received by netstack."),
- MulticastListenerQuery: mustCreateMetric("/netstack/icmp/v6/packets_received/multicast_listener_query", "Number of ICMPv6 multicast listener query packets received by netstack."),
- MulticastListenerReport: mustCreateMetric("/netstack/icmp/v6/packets_received/multicast_listener_report", "Number of ICMPv6 multicast listener report packets sent by netstack."),
- MulticastListenerDone: mustCreateMetric("/netstack/icmp/v6/packets_received/multicast_listener_done", "Number of ICMPv6 multicast listener done packets sent by netstack."),
+ EchoRequest: mustCreateMetric("/netstack/icmp/v6/packets_received/echo_request", "Number of ICMPv6 echo request packets received."),
+ EchoReply: mustCreateMetric("/netstack/icmp/v6/packets_received/echo_reply", "Number of ICMPv6 echo reply packets received."),
+ DstUnreachable: mustCreateMetric("/netstack/icmp/v6/packets_received/dst_unreachable", "Number of ICMPv6 destination unreachable packets received."),
+ PacketTooBig: mustCreateMetric("/netstack/icmp/v6/packets_received/packet_too_big", "Number of ICMPv6 packet too big packets received."),
+ TimeExceeded: mustCreateMetric("/netstack/icmp/v6/packets_received/time_exceeded", "Number of ICMPv6 time exceeded packets received."),
+ ParamProblem: mustCreateMetric("/netstack/icmp/v6/packets_received/param_problem", "Number of ICMPv6 parameter problem packets received."),
+ RouterSolicit: mustCreateMetric("/netstack/icmp/v6/packets_received/router_solicit", "Number of ICMPv6 router solicit packets received."),
+ RouterAdvert: mustCreateMetric("/netstack/icmp/v6/packets_received/router_advert", "Number of ICMPv6 router advert packets received."),
+ NeighborSolicit: mustCreateMetric("/netstack/icmp/v6/packets_received/neighbor_solicit", "Number of ICMPv6 neighbor solicit packets received."),
+ NeighborAdvert: mustCreateMetric("/netstack/icmp/v6/packets_received/neighbor_advert", "Number of ICMPv6 neighbor advert packets received."),
+ RedirectMsg: mustCreateMetric("/netstack/icmp/v6/packets_received/redirect_msg", "Number of ICMPv6 redirect message packets received."),
+ MulticastListenerQuery: mustCreateMetric("/netstack/icmp/v6/packets_received/multicast_listener_query", "Number of ICMPv6 multicast listener query packets received."),
+ MulticastListenerReport: mustCreateMetric("/netstack/icmp/v6/packets_received/multicast_listener_report", "Number of ICMPv6 multicast listener report packets sent."),
+ MulticastListenerDone: mustCreateMetric("/netstack/icmp/v6/packets_received/multicast_listener_done", "Number of ICMPv6 multicast listener done packets sent."),
},
Unrecognized: mustCreateMetric("/netstack/icmp/v6/packets_received/unrecognized", "Number of ICMPv6 packets received that the transport layer does not know how to parse."),
Invalid: mustCreateMetric("/netstack/icmp/v6/packets_received/invalid", "Number of ICMPv6 packets received that the transport layer could not parse."),
@@ -163,23 +183,23 @@ var Metrics = tcpip.Stats{
IGMP: tcpip.IGMPStats{
PacketsSent: tcpip.IGMPSentPacketStats{
IGMPPacketStats: tcpip.IGMPPacketStats{
- MembershipQuery: mustCreateMetric("/netstack/igmp/packets_sent/membership_query", "Number of IGMP Membership Query messages sent by netstack."),
- V1MembershipReport: mustCreateMetric("/netstack/igmp/packets_sent/v1_membership_report", "Number of IGMPv1 Membership Report messages sent by netstack."),
- V2MembershipReport: mustCreateMetric("/netstack/igmp/packets_sent/v2_membership_report", "Number of IGMPv2 Membership Report messages sent by netstack."),
- LeaveGroup: mustCreateMetric("/netstack/igmp/packets_sent/leave_group", "Number of IGMP Leave Group messages sent by netstack."),
+ MembershipQuery: mustCreateMetric("/netstack/igmp/packets_sent/membership_query", "Number of IGMP Membership Query messages sent."),
+ V1MembershipReport: mustCreateMetric("/netstack/igmp/packets_sent/v1_membership_report", "Number of IGMPv1 Membership Report messages sent."),
+ V2MembershipReport: mustCreateMetric("/netstack/igmp/packets_sent/v2_membership_report", "Number of IGMPv2 Membership Report messages sent."),
+ LeaveGroup: mustCreateMetric("/netstack/igmp/packets_sent/leave_group", "Number of IGMP Leave Group messages sent."),
},
- Dropped: mustCreateMetric("/netstack/igmp/packets_sent/dropped", "Number of IGMP packets dropped by netstack due to link layer errors."),
+ Dropped: mustCreateMetric("/netstack/igmp/packets_sent/dropped", "Number of IGMP packets dropped due to link layer errors."),
},
PacketsReceived: tcpip.IGMPReceivedPacketStats{
IGMPPacketStats: tcpip.IGMPPacketStats{
- MembershipQuery: mustCreateMetric("/netstack/igmp/packets_received/membership_query", "Number of IGMP Membership Query messages received by netstack."),
- V1MembershipReport: mustCreateMetric("/netstack/igmp/packets_received/v1_membership_report", "Number of IGMPv1 Membership Report messages received by netstack."),
- V2MembershipReport: mustCreateMetric("/netstack/igmp/packets_received/v2_membership_report", "Number of IGMPv2 Membership Report messages received by netstack."),
- LeaveGroup: mustCreateMetric("/netstack/igmp/packets_received/leave_group", "Number of IGMP Leave Group messages received by netstack."),
+ MembershipQuery: mustCreateMetric("/netstack/igmp/packets_received/membership_query", "Number of IGMP Membership Query messages received."),
+ V1MembershipReport: mustCreateMetric("/netstack/igmp/packets_received/v1_membership_report", "Number of IGMPv1 Membership Report messages received."),
+ V2MembershipReport: mustCreateMetric("/netstack/igmp/packets_received/v2_membership_report", "Number of IGMPv2 Membership Report messages received."),
+ LeaveGroup: mustCreateMetric("/netstack/igmp/packets_received/leave_group", "Number of IGMP Leave Group messages received."),
},
- Invalid: mustCreateMetric("/netstack/igmp/packets_received/invalid", "Number of IGMP packets received by netstack that could not be parsed."),
+ Invalid: mustCreateMetric("/netstack/igmp/packets_received/invalid", "Number of IGMP packets received that could not be parsed."),
ChecksumErrors: mustCreateMetric("/netstack/igmp/packets_received/checksum_errors", "Number of received IGMP packets with bad checksums."),
- Unrecognized: mustCreateMetric("/netstack/igmp/packets_received/unrecognized", "Number of unrecognized IGMP packets received by netstack."),
+ Unrecognized: mustCreateMetric("/netstack/igmp/packets_received/unrecognized", "Number of unrecognized IGMP packets received."),
},
},
IP: tcpip.IPStats{
@@ -205,7 +225,8 @@ var Metrics = tcpip.Stats{
LinkLocalSource: mustCreateMetric("/netstack/ip/forwarding/link_local_source_address", "Number of IP packets received which could not be forwarded due to a link-local source address."),
LinkLocalDestination: mustCreateMetric("/netstack/ip/forwarding/link_local_destination_address", "Number of IP packets received which could not be forwarded due to a link-local destination address."),
ExtensionHeaderProblem: mustCreateMetric("/netstack/ip/forwarding/extension_header_problem", "Number of IP packets received which could not be forwarded due to a problem processing their IPv6 extension headers."),
- PacketTooBig: mustCreateMetric("/netstack/ip/forwarding/packet_too_big", "Number of IP packets received which could not fit within the outgoing MTU."),
+ PacketTooBig: mustCreateMetric("/netstack/ip/forwarding/packet_too_big", "Number of IP packets received which could not be forwarded because they could not fit within the outgoing MTU."),
+ HostUnreachable: mustCreateMetric("/netstack/ip/forwarding/host_unreachable", "Number of IP packets received which could not be forwarded due to unresolvable next hop."),
Errors: mustCreateMetric("/netstack/ip/forwarding/errors", "Number of IP packets which couldn't be forwarded."),
},
},
@@ -270,7 +291,7 @@ const DefaultTTL = 64
const sizeOfInt32 int = 4
-var errStackType = syserr.New("expected but did not receive a netstack.Stack", linux.EINVAL)
+var errStackType = syserr.New("expected but did not receive a netstack.Stack", errno.EINVAL)
// commonEndpoint represents the intersection of a tcpip.Endpoint and a
// transport.Endpoint.
@@ -1126,7 +1147,14 @@ func getSockOptTCP(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, name,
// TODO(b/64800844): Translate fields once they are added to
// tcpip.TCPInfoOption.
- info := linux.TCPInfo{}
+ info := linux.TCPInfo{
+ State: uint8(v.State),
+ RTO: uint32(v.RTO / time.Microsecond),
+ RTT: uint32(v.RTT / time.Microsecond),
+ RTTVar: uint32(v.RTTVar / time.Microsecond),
+ SndSsthresh: v.SndSsthresh,
+ SndCwnd: v.SndCwnd,
+ }
switch v.CcState {
case tcpip.RTORecovery:
info.CaState = linux.TCP_CA_Loss
@@ -1137,11 +1165,6 @@ func getSockOptTCP(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, name,
case tcpip.Open:
info.CaState = linux.TCP_CA_Open
}
- info.RTO = uint32(v.RTO / time.Microsecond)
- info.RTT = uint32(v.RTT / time.Microsecond)
- info.RTTVar = uint32(v.RTTVar / time.Microsecond)
- info.SndSsthresh = v.SndSsthresh
- info.SndCwnd = v.SndCwnd
// In netstack reorderSeen is updated only when RACK is enabled.
// We only track whether the reordering is seen, which is
@@ -1777,11 +1800,6 @@ func setSockOptSocket(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, nam
}
v := hostarch.ByteOrder.Uint32(optVal)
-
- if v == 0 {
- socket.SetSockOptEmitUnimplementedEvent(t, name)
- }
-
ep.SocketOptions().SetOutOfBandInline(v != 0)
return nil
@@ -2089,10 +2107,10 @@ func setSockOptIPv6(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, name
return syserr.ErrNoDevice
}
// Stack must be a netstack stack.
- return netfilter.SetEntries(stack.(*Stack).Stack, optVal, true)
+ return netfilter.SetEntries(t, stack.(*Stack).Stack, optVal, true)
case linux.IP6T_SO_SET_ADD_COUNTERS:
- // TODO(gvisor.dev/issue/170): Counter support.
+ log.Infof("IP6T_SO_SET_ADD_COUNTERS is not supported")
return nil
default:
@@ -2332,10 +2350,10 @@ func setSockOptIP(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, name in
return syserr.ErrNoDevice
}
// Stack must be a netstack stack.
- return netfilter.SetEntries(stack.(*Stack).Stack, optVal, false)
+ return netfilter.SetEntries(t, stack.(*Stack).Stack, optVal, false)
case linux.IPT_SO_SET_ADD_COUNTERS:
- // TODO(gvisor.dev/issue/170): Counter support.
+ log.Infof("IPT_SO_SET_ADD_COUNTERS is not supported")
return nil
case linux.IP_ADD_SOURCE_MEMBERSHIP,
@@ -2792,7 +2810,7 @@ func (s *socketOpsCommon) RecvMsg(t *kernel.Task, dst usermem.IOSequence, flags
if n > 0 {
return n, msgFlags, senderAddr, senderAddrLen, controlMessages, nil
}
- if err == syserror.ETIMEDOUT {
+ if linuxerr.Equals(linuxerr.ETIMEDOUT, err) {
return 0, 0, nil, 0, socket.ControlMessages{}, syserr.ErrTryAgain
}
return 0, 0, nil, 0, socket.ControlMessages{}, syserr.FromError(err)
@@ -2860,7 +2878,7 @@ func (s *socketOpsCommon) SendMsg(t *kernel.Task, src usermem.IOSequence, to []b
// became available between when we last checked and when we setup
// the notification.
if err := t.BlockWithDeadline(ch, haveDeadline, deadline); err != nil {
- if err == syserror.ETIMEDOUT {
+ if linuxerr.Equals(linuxerr.ETIMEDOUT, err) {
return int(total), syserr.ErrTryAgain
}
// handleIOError will consume errors from t.Block if needed.
diff --git a/pkg/sentry/socket/netstack/stack.go b/pkg/sentry/socket/netstack/stack.go
index eef5e6519..9d343b671 100644
--- a/pkg/sentry/socket/netstack/stack.go
+++ b/pkg/sentry/socket/netstack/stack.go
@@ -18,6 +18,7 @@ import (
"fmt"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/sentry/inet"
"gvisor.dev/gvisor/pkg/syserr"
@@ -110,19 +111,19 @@ func convertAddr(addr inet.InterfaceAddr) (tcpip.ProtocolAddress, error) {
switch addr.Family {
case linux.AF_INET:
if len(addr.Addr) != header.IPv4AddressSize {
- return protocolAddress, syserror.EINVAL
+ return protocolAddress, linuxerr.EINVAL
}
if addr.PrefixLen > header.IPv4AddressSize*8 {
- return protocolAddress, syserror.EINVAL
+ return protocolAddress, linuxerr.EINVAL
}
protocol = ipv4.ProtocolNumber
address = tcpip.Address(addr.Addr)
case linux.AF_INET6:
if len(addr.Addr) != header.IPv6AddressSize {
- return protocolAddress, syserror.EINVAL
+ return protocolAddress, linuxerr.EINVAL
}
if addr.PrefixLen > header.IPv6AddressSize*8 {
- return protocolAddress, syserror.EINVAL
+ return protocolAddress, linuxerr.EINVAL
}
protocol = ipv6.ProtocolNumber
address = tcpip.Address(addr.Addr)
diff --git a/pkg/sentry/socket/netstack/tun.go b/pkg/sentry/socket/netstack/tun.go
index 288dd0c9e..e67fe9700 100644
--- a/pkg/sentry/socket/netstack/tun.go
+++ b/pkg/sentry/socket/netstack/tun.go
@@ -16,7 +16,7 @@ package netstack
import (
"gvisor.dev/gvisor/pkg/abi/linux"
- "gvisor.dev/gvisor/pkg/syserror"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/tcpip/link/tun"
)
@@ -40,8 +40,8 @@ func LinuxToTUNFlags(flags uint16) (tun.Flags, error) {
// Linux adds IFF_NOFILTER (the same value as IFF_NO_PI unfortunately)
// when there is no sk_filter. See __tun_chr_ioctl() in
// net/drivers/tun.c.
- if flags&^uint16(linux.IFF_TUN|linux.IFF_TAP|linux.IFF_NO_PI) != 0 {
- return tun.Flags{}, syserror.EINVAL
+ if flags&^uint16(linux.IFF_TUN|linux.IFF_TAP|linux.IFF_NO_PI|linux.IFF_ONE_QUEUE) != 0 {
+ return tun.Flags{}, linuxerr.EINVAL
}
return tun.Flags{
TUN: flags&linux.IFF_TUN != 0,
diff --git a/pkg/sentry/socket/socket.go b/pkg/sentry/socket/socket.go
index 353f4ade0..f5da3c509 100644
--- a/pkg/sentry/socket/socket.go
+++ b/pkg/sentry/socket/socket.go
@@ -659,7 +659,6 @@ func ConvertAddress(family int, addr tcpip.FullAddress) (linux.SockAddr, uint32)
return &out, uint32(sockAddrInet6Size)
case linux.AF_PACKET:
- // TODO(gvisor.dev/issue/173): Return protocol too.
var out linux.SockAddrLink
out.Family = linux.AF_PACKET
out.InterfaceIndex = int32(addr.NIC)
@@ -749,7 +748,6 @@ func AddressAndFamily(addr []byte) (tcpip.FullAddress, uint16, *syserr.Error) {
return tcpip.FullAddress{}, family, syserr.ErrInvalidArgument
}
- // TODO(gvisor.dev/issue/173): Return protocol too.
return tcpip.FullAddress{
NIC: tcpip.NICID(a.InterfaceIndex),
Addr: tcpip.Address(a.HardwareAddr[:header.EthernetAddressSize]),
diff --git a/pkg/sentry/socket/unix/BUILD b/pkg/sentry/socket/unix/BUILD
index c9cbefb3a..5c3cdef6a 100644
--- a/pkg/sentry/socket/unix/BUILD
+++ b/pkg/sentry/socket/unix/BUILD
@@ -39,6 +39,7 @@ go_library(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/fspath",
"//pkg/hostarch",
"//pkg/log",
diff --git a/pkg/sentry/socket/unix/unix.go b/pkg/sentry/socket/unix/unix.go
index db7b1affe..8ccdadae9 100644
--- a/pkg/sentry/socket/unix/unix.go
+++ b/pkg/sentry/socket/unix/unix.go
@@ -23,6 +23,7 @@ import (
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fspath"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/marshal"
@@ -518,7 +519,7 @@ func (s *socketOpsCommon) SendMsg(t *kernel.Task, src usermem.IOSequence, to []b
}
if err = t.BlockWithDeadline(ch, haveDeadline, deadline); err != nil {
- if err == syserror.ETIMEDOUT {
+ if linuxerr.Equals(linuxerr.ETIMEDOUT, err) {
err = syserror.ErrWouldBlock
}
break
@@ -719,7 +720,7 @@ func (s *socketOpsCommon) RecvMsg(t *kernel.Task, dst usermem.IOSequence, flags
if total > 0 {
err = nil
}
- if err == syserror.ETIMEDOUT {
+ if linuxerr.Equals(linuxerr.ETIMEDOUT, err) {
return int(total), msgFlags, nil, 0, socket.ControlMessages{}, syserr.ErrTryAgain
}
return int(total), msgFlags, nil, 0, socket.ControlMessages{}, syserr.FromError(err)
diff --git a/pkg/sentry/socket/unix/unix_vfs2.go b/pkg/sentry/socket/unix/unix_vfs2.go
index c39e317ff..08a00a12f 100644
--- a/pkg/sentry/socket/unix/unix_vfs2.go
+++ b/pkg/sentry/socket/unix/unix_vfs2.go
@@ -17,6 +17,7 @@ package unix
import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fspath"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/marshal"
@@ -236,7 +237,7 @@ func (s *SocketVFS2) Bind(t *kernel.Task, sockaddr []byte) *syserr.Error {
Mode: linux.FileMode(linux.S_IFSOCK | uint(stat.Mode)&^t.FSContext().Umask()),
Endpoint: bep,
})
- if err == syserror.EEXIST {
+ if linuxerr.Equals(linuxerr.EEXIST, err) {
return syserr.ErrAddressInUse
}
return syserr.FromError(err)
diff --git a/pkg/sentry/state/BUILD b/pkg/sentry/state/BUILD
index 3e801182c..7f02807c5 100644
--- a/pkg/sentry/state/BUILD
+++ b/pkg/sentry/state/BUILD
@@ -13,6 +13,7 @@ go_library(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/log",
"//pkg/sentry/inet",
"//pkg/sentry/kernel",
@@ -20,7 +21,6 @@ go_library(
"//pkg/sentry/vfs",
"//pkg/sentry/watchdog",
"//pkg/state/statefile",
- "//pkg/syserror",
"@org_golang_x_sys//unix:go_default_library",
],
)
diff --git a/pkg/sentry/state/state.go b/pkg/sentry/state/state.go
index 167754537..e9d544f3d 100644
--- a/pkg/sentry/state/state.go
+++ b/pkg/sentry/state/state.go
@@ -20,6 +20,7 @@ import (
"io"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/sentry/inet"
"gvisor.dev/gvisor/pkg/sentry/kernel"
@@ -27,7 +28,6 @@ import (
"gvisor.dev/gvisor/pkg/sentry/vfs"
"gvisor.dev/gvisor/pkg/sentry/watchdog"
"gvisor.dev/gvisor/pkg/state/statefile"
- "gvisor.dev/gvisor/pkg/syserror"
)
var previousMetadata map[string]string
@@ -88,7 +88,7 @@ func (opts SaveOpts) Save(ctx context.Context, k *kernel.Kernel, w *watchdog.Wat
// ENOSPC is a state file error. This error can only come from
// writing the state file, and not from fs.FileOperations.Fsync
// because we wrap those in kernel.TaskSet.flushWritesToFiles.
- if err == syserror.ENOSPC {
+ if linuxerr.Equals(linuxerr.ENOSPC, err) {
err = ErrStateFile{err}
}
@@ -110,7 +110,7 @@ type LoadOpts struct {
}
// Load loads the given kernel, setting the provided platform and stack.
-func (opts LoadOpts) Load(ctx context.Context, k *kernel.Kernel, n inet.Stack, clocks time.Clocks, vfsOpts *vfs.CompleteRestoreOptions) error {
+func (opts LoadOpts) Load(ctx context.Context, k *kernel.Kernel, timeReady chan struct{}, n inet.Stack, clocks time.Clocks, vfsOpts *vfs.CompleteRestoreOptions) error {
// Open the file.
r, m, err := statefile.NewReader(opts.Source, opts.Key)
if err != nil {
@@ -120,5 +120,5 @@ func (opts LoadOpts) Load(ctx context.Context, k *kernel.Kernel, n inet.Stack, c
previousMetadata = m
// Restore the Kernel object graph.
- return k.LoadFrom(ctx, r, n, clocks, vfsOpts)
+ return k.LoadFrom(ctx, r, timeReady, n, clocks, vfsOpts)
}
diff --git a/pkg/sentry/strace/BUILD b/pkg/sentry/strace/BUILD
index 1fbbd133c..369541c7a 100644
--- a/pkg/sentry/strace/BUILD
+++ b/pkg/sentry/strace/BUILD
@@ -11,6 +11,7 @@ go_library(
"futex.go",
"linux64_amd64.go",
"linux64_arm64.go",
+ "mmap.go",
"open.go",
"poll.go",
"ptrace.go",
@@ -35,7 +36,6 @@ go_library(
"//pkg/sentry/socket",
"//pkg/sentry/socket/netlink",
"//pkg/sentry/syscalls/linux",
- "@org_golang_x_sys//unix:go_default_library",
],
)
diff --git a/pkg/sentry/strace/clone.go b/pkg/sentry/strace/clone.go
index ab1060426..bfb4d7f5c 100644
--- a/pkg/sentry/strace/clone.go
+++ b/pkg/sentry/strace/clone.go
@@ -15,98 +15,98 @@
package strace
import (
- "golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi"
+ "gvisor.dev/gvisor/pkg/abi/linux"
)
// CloneFlagSet is the set of clone(2) flags.
var CloneFlagSet = abi.FlagSet{
{
- Flag: unix.CLONE_VM,
+ Flag: linux.CLONE_VM,
Name: "CLONE_VM",
},
{
- Flag: unix.CLONE_FS,
+ Flag: linux.CLONE_FS,
Name: "CLONE_FS",
},
{
- Flag: unix.CLONE_FILES,
+ Flag: linux.CLONE_FILES,
Name: "CLONE_FILES",
},
{
- Flag: unix.CLONE_SIGHAND,
+ Flag: linux.CLONE_SIGHAND,
Name: "CLONE_SIGHAND",
},
{
- Flag: unix.CLONE_PTRACE,
+ Flag: linux.CLONE_PTRACE,
Name: "CLONE_PTRACE",
},
{
- Flag: unix.CLONE_VFORK,
+ Flag: linux.CLONE_VFORK,
Name: "CLONE_VFORK",
},
{
- Flag: unix.CLONE_PARENT,
+ Flag: linux.CLONE_PARENT,
Name: "CLONE_PARENT",
},
{
- Flag: unix.CLONE_THREAD,
+ Flag: linux.CLONE_THREAD,
Name: "CLONE_THREAD",
},
{
- Flag: unix.CLONE_NEWNS,
+ Flag: linux.CLONE_NEWNS,
Name: "CLONE_NEWNS",
},
{
- Flag: unix.CLONE_SYSVSEM,
+ Flag: linux.CLONE_SYSVSEM,
Name: "CLONE_SYSVSEM",
},
{
- Flag: unix.CLONE_SETTLS,
+ Flag: linux.CLONE_SETTLS,
Name: "CLONE_SETTLS",
},
{
- Flag: unix.CLONE_PARENT_SETTID,
+ Flag: linux.CLONE_PARENT_SETTID,
Name: "CLONE_PARENT_SETTID",
},
{
- Flag: unix.CLONE_CHILD_CLEARTID,
+ Flag: linux.CLONE_CHILD_CLEARTID,
Name: "CLONE_CHILD_CLEARTID",
},
{
- Flag: unix.CLONE_DETACHED,
+ Flag: linux.CLONE_DETACHED,
Name: "CLONE_DETACHED",
},
{
- Flag: unix.CLONE_UNTRACED,
+ Flag: linux.CLONE_UNTRACED,
Name: "CLONE_UNTRACED",
},
{
- Flag: unix.CLONE_CHILD_SETTID,
+ Flag: linux.CLONE_CHILD_SETTID,
Name: "CLONE_CHILD_SETTID",
},
{
- Flag: unix.CLONE_NEWUTS,
+ Flag: linux.CLONE_NEWUTS,
Name: "CLONE_NEWUTS",
},
{
- Flag: unix.CLONE_NEWIPC,
+ Flag: linux.CLONE_NEWIPC,
Name: "CLONE_NEWIPC",
},
{
- Flag: unix.CLONE_NEWUSER,
+ Flag: linux.CLONE_NEWUSER,
Name: "CLONE_NEWUSER",
},
{
- Flag: unix.CLONE_NEWPID,
+ Flag: linux.CLONE_NEWPID,
Name: "CLONE_NEWPID",
},
{
- Flag: unix.CLONE_NEWNET,
+ Flag: linux.CLONE_NEWNET,
Name: "CLONE_NEWNET",
},
{
- Flag: unix.CLONE_IO,
+ Flag: linux.CLONE_IO,
Name: "CLONE_IO",
},
}
diff --git a/pkg/sentry/strace/linux64_amd64.go b/pkg/sentry/strace/linux64_amd64.go
index d66befe81..6ce1bb592 100644
--- a/pkg/sentry/strace/linux64_amd64.go
+++ b/pkg/sentry/strace/linux64_amd64.go
@@ -33,7 +33,7 @@ var linuxAMD64 = SyscallMap{
6: makeSyscallInfo("lstat", Path, Stat),
7: makeSyscallInfo("poll", PollFDs, Hex, Hex),
8: makeSyscallInfo("lseek", Hex, Hex, Hex),
- 9: makeSyscallInfo("mmap", Hex, Hex, Hex, Hex, FD, Hex),
+ 9: makeSyscallInfo("mmap", Hex, Hex, MmapProt, MmapFlags, FD, Hex),
10: makeSyscallInfo("mprotect", Hex, Hex, Hex),
11: makeSyscallInfo("munmap", Hex, Hex),
12: makeSyscallInfo("brk", Hex),
diff --git a/pkg/sentry/strace/linux64_arm64.go b/pkg/sentry/strace/linux64_arm64.go
index 1a2d7d75f..ce5594301 100644
--- a/pkg/sentry/strace/linux64_arm64.go
+++ b/pkg/sentry/strace/linux64_arm64.go
@@ -246,7 +246,7 @@ var linuxARM64 = SyscallMap{
219: makeSyscallInfo("keyctl", Hex, Hex, Hex, Hex, Hex),
220: makeSyscallInfo("clone", CloneFlags, Hex, Hex, Hex, Hex),
221: makeSyscallInfo("execve", Path, ExecveStringVector, ExecveStringVector),
- 222: makeSyscallInfo("mmap", Hex, Hex, Hex, Hex, FD, Hex),
+ 222: makeSyscallInfo("mmap", Hex, Hex, MmapProt, MmapFlags, FD, Hex),
223: makeSyscallInfo("fadvise64", FD, Hex, Hex, Hex),
224: makeSyscallInfo("swapon", Hex, Hex),
225: makeSyscallInfo("swapoff", Hex),
diff --git a/pkg/sentry/strace/mmap.go b/pkg/sentry/strace/mmap.go
new file mode 100644
index 000000000..0035be586
--- /dev/null
+++ b/pkg/sentry/strace/mmap.go
@@ -0,0 +1,92 @@
+// Copyright 2021 The gVisor Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package strace
+
+import (
+ "gvisor.dev/gvisor/pkg/abi"
+ "gvisor.dev/gvisor/pkg/abi/linux"
+)
+
+// ProtectionFlagSet represents the protection to mmap(2).
+var ProtectionFlagSet = abi.FlagSet{
+ {
+ Flag: linux.PROT_READ,
+ Name: "PROT_READ",
+ },
+ {
+ Flag: linux.PROT_WRITE,
+ Name: "PROT_WRITE",
+ },
+ {
+ Flag: linux.PROT_EXEC,
+ Name: "PROT_EXEC",
+ },
+}
+
+// MmapFlagSet is the set of mmap(2) flags.
+var MmapFlagSet = abi.FlagSet{
+ {
+ Flag: linux.MAP_SHARED,
+ Name: "MAP_SHARED",
+ },
+ {
+ Flag: linux.MAP_PRIVATE,
+ Name: "MAP_PRIVATE",
+ },
+ {
+ Flag: linux.MAP_FIXED,
+ Name: "MAP_FIXED",
+ },
+ {
+ Flag: linux.MAP_ANONYMOUS,
+ Name: "MAP_ANONYMOUS",
+ },
+ {
+ Flag: linux.MAP_GROWSDOWN,
+ Name: "MAP_GROWSDOWN",
+ },
+ {
+ Flag: linux.MAP_DENYWRITE,
+ Name: "MAP_DENYWRITE",
+ },
+ {
+ Flag: linux.MAP_EXECUTABLE,
+ Name: "MAP_EXECUTABLE",
+ },
+ {
+ Flag: linux.MAP_LOCKED,
+ Name: "MAP_LOCKED",
+ },
+ {
+ Flag: linux.MAP_NORESERVE,
+ Name: "MAP_NORESERVE",
+ },
+ {
+ Flag: linux.MAP_POPULATE,
+ Name: "MAP_POPULATE",
+ },
+ {
+ Flag: linux.MAP_NONBLOCK,
+ Name: "MAP_NONBLOCK",
+ },
+ {
+ Flag: linux.MAP_STACK,
+ Name: "MAP_STACK",
+ },
+ {
+ Flag: linux.MAP_HUGETLB,
+ Name: "MAP_HUGETLB",
+ },
+}
diff --git a/pkg/sentry/strace/open.go b/pkg/sentry/strace/open.go
index 5769360da..e7c7649f4 100644
--- a/pkg/sentry/strace/open.go
+++ b/pkg/sentry/strace/open.go
@@ -15,61 +15,61 @@
package strace
import (
- "golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi"
+ "gvisor.dev/gvisor/pkg/abi/linux"
)
// OpenMode represents the mode to open(2) a file.
var OpenMode = abi.ValueSet{
- unix.O_RDWR: "O_RDWR",
- unix.O_WRONLY: "O_WRONLY",
- unix.O_RDONLY: "O_RDONLY",
+ linux.O_RDWR: "O_RDWR",
+ linux.O_WRONLY: "O_WRONLY",
+ linux.O_RDONLY: "O_RDONLY",
}
// OpenFlagSet is the set of open(2) flags.
var OpenFlagSet = abi.FlagSet{
{
- Flag: unix.O_APPEND,
+ Flag: linux.O_APPEND,
Name: "O_APPEND",
},
{
- Flag: unix.O_ASYNC,
+ Flag: linux.O_ASYNC,
Name: "O_ASYNC",
},
{
- Flag: unix.O_CLOEXEC,
+ Flag: linux.O_CLOEXEC,
Name: "O_CLOEXEC",
},
{
- Flag: unix.O_CREAT,
+ Flag: linux.O_CREAT,
Name: "O_CREAT",
},
{
- Flag: unix.O_DIRECT,
+ Flag: linux.O_DIRECT,
Name: "O_DIRECT",
},
{
- Flag: unix.O_DIRECTORY,
+ Flag: linux.O_DIRECTORY,
Name: "O_DIRECTORY",
},
{
- Flag: unix.O_EXCL,
+ Flag: linux.O_EXCL,
Name: "O_EXCL",
},
{
- Flag: unix.O_NOATIME,
+ Flag: linux.O_NOATIME,
Name: "O_NOATIME",
},
{
- Flag: unix.O_NOCTTY,
+ Flag: linux.O_NOCTTY,
Name: "O_NOCTTY",
},
{
- Flag: unix.O_NOFOLLOW,
+ Flag: linux.O_NOFOLLOW,
Name: "O_NOFOLLOW",
},
{
- Flag: unix.O_NONBLOCK,
+ Flag: linux.O_NONBLOCK,
Name: "O_NONBLOCK",
},
{
@@ -77,18 +77,22 @@ var OpenFlagSet = abi.FlagSet{
Name: "O_PATH",
},
{
- Flag: unix.O_SYNC,
+ Flag: linux.O_SYNC,
Name: "O_SYNC",
},
{
- Flag: unix.O_TRUNC,
+ Flag: linux.O_TMPFILE,
+ Name: "O_TMPFILE",
+ },
+ {
+ Flag: linux.O_TRUNC,
Name: "O_TRUNC",
},
}
func open(val uint64) string {
- s := OpenMode.Parse(val & unix.O_ACCMODE)
- if flags := OpenFlagSet.Parse(val &^ unix.O_ACCMODE); flags != "" {
+ s := OpenMode.Parse(val & linux.O_ACCMODE)
+ if flags := OpenFlagSet.Parse(val &^ linux.O_ACCMODE); flags != "" {
s += "|" + flags
}
return s
diff --git a/pkg/sentry/strace/signal.go b/pkg/sentry/strace/signal.go
index e5b379a20..5afc9525b 100644
--- a/pkg/sentry/strace/signal.go
+++ b/pkg/sentry/strace/signal.go
@@ -130,8 +130,8 @@ func sigAction(t *kernel.Task, addr hostarch.Addr) string {
return "null"
}
- sa, err := t.CopyInSignalAct(addr)
- if err != nil {
+ var sa linux.SigAction
+ if _, err := sa.CopyIn(t, addr); err != nil {
return fmt.Sprintf("%#x (error copying sigaction: %v)", addr, err)
}
diff --git a/pkg/sentry/strace/strace.go b/pkg/sentry/strace/strace.go
index ec5d5f846..af7088847 100644
--- a/pkg/sentry/strace/strace.go
+++ b/pkg/sentry/strace/strace.go
@@ -489,6 +489,10 @@ func (i *SyscallInfo) pre(t *kernel.Task, args arch.SyscallArguments, maximumBlo
output = append(output, epollEvents(t, args[arg].Pointer(), 0 /* numEvents */, uint64(maximumBlobSize)))
case SelectFDSet:
output = append(output, fdSet(t, int(args[0].Int()), args[arg].Pointer()))
+ case MmapProt:
+ output = append(output, ProtectionFlagSet.Parse(uint64(args[arg].Uint())))
+ case MmapFlags:
+ output = append(output, MmapFlagSet.Parse(uint64(args[arg].Uint())))
case Oct:
output = append(output, "0o"+strconv.FormatUint(args[arg].Uint64(), 8))
case Hex:
diff --git a/pkg/sentry/strace/syscalls.go b/pkg/sentry/strace/syscalls.go
index 7e69b9279..5893443a7 100644
--- a/pkg/sentry/strace/syscalls.go
+++ b/pkg/sentry/strace/syscalls.go
@@ -238,6 +238,12 @@ const (
// EpollEvents is an array of struct epoll_event. It is the events
// argument in epoll_wait(2)/epoll_pwait(2).
EpollEvents
+
+ // MmapProt is the protection argument in mmap(2).
+ MmapProt
+
+ // MmapFlags is the flags argument in mmap(2).
+ MmapFlags
)
// defaultFormat is the syscall argument format to use if the actual format is
diff --git a/pkg/sentry/syscalls/BUILD b/pkg/sentry/syscalls/BUILD
index b8d1bd415..f2c55588f 100644
--- a/pkg/sentry/syscalls/BUILD
+++ b/pkg/sentry/syscalls/BUILD
@@ -11,6 +11,7 @@ go_library(
visibility = ["//:sandbox"],
deps = [
"//pkg/abi/linux",
+ "//pkg/errors/linuxerr",
"//pkg/sentry/arch",
"//pkg/sentry/kernel",
"//pkg/sentry/kernel/epoll",
diff --git a/pkg/sentry/syscalls/epoll.go b/pkg/sentry/syscalls/epoll.go
index 3b4d79889..02debfc7e 100644
--- a/pkg/sentry/syscalls/epoll.go
+++ b/pkg/sentry/syscalls/epoll.go
@@ -18,6 +18,7 @@ import (
"time"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/kernel/epoll"
ktime "gvisor.dev/gvisor/pkg/sentry/kernel/time"
@@ -163,7 +164,7 @@ func WaitEpoll(t *kernel.Task, fd int32, max int, timeoutInNanos int64) ([]linux
}
if err := t.BlockWithDeadline(ch, haveDeadline, deadline); err != nil {
- if err == syserror.ETIMEDOUT {
+ if linuxerr.Equals(linuxerr.ETIMEDOUT, err) {
return nil, nil
}
diff --git a/pkg/sentry/syscalls/linux/BUILD b/pkg/sentry/syscalls/linux/BUILD
index 408a6c422..a2f612f45 100644
--- a/pkg/sentry/syscalls/linux/BUILD
+++ b/pkg/sentry/syscalls/linux/BUILD
@@ -64,6 +64,7 @@ go_library(
"//pkg/abi/linux",
"//pkg/bpf",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/hostarch",
"//pkg/log",
"//pkg/marshal",
diff --git a/pkg/sentry/syscalls/linux/error.go b/pkg/sentry/syscalls/linux/error.go
index 6eabfd219..165922332 100644
--- a/pkg/sentry/syscalls/linux/error.go
+++ b/pkg/sentry/syscalls/linux/error.go
@@ -19,6 +19,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/metric"
"gvisor.dev/gvisor/pkg/sentry/fs"
@@ -94,13 +95,13 @@ func handleIOErrorImpl(ctx context.Context, partialResult bool, errOrig, intr er
if errno, ok := syserror.TranslateError(errOrig); ok {
translatedErr = errno
}
- switch translatedErr {
- case io.EOF:
+ switch {
+ case translatedErr == io.EOF:
// EOF is always consumed. If this is a partial read/write
// (result != 0), the application will see that, otherwise
// they will see 0.
return true, nil
- case syserror.EFBIG:
+ case linuxerr.Equals(linuxerr.EFBIG, translatedErr):
t := kernel.TaskFromContext(ctx)
if t == nil {
panic("I/O error should only occur from a context associated with a Task")
@@ -113,7 +114,7 @@ func handleIOErrorImpl(ctx context.Context, partialResult bool, errOrig, intr er
// Simultaneously send a SIGXFSZ per setrlimit(2).
t.SendSignal(kernel.SignalInfoNoInfo(linux.SIGXFSZ, t, t))
return true, syserror.EFBIG
- case syserror.EINTR:
+ case linuxerr.Equals(linuxerr.EINTR, translatedErr):
// The syscall was interrupted. Return nil if it completed
// partially, otherwise return the error code that the syscall
// needs (to indicate to the kernel what it should do).
@@ -128,21 +129,21 @@ func handleIOErrorImpl(ctx context.Context, partialResult bool, errOrig, intr er
return true, errOrig
}
- switch translatedErr {
- case syserror.EINTR:
+ switch {
+ case linuxerr.Equals(linuxerr.EINTR, translatedErr):
// Syscall interrupted, but completed a partial
// read/write. Like ErrWouldBlock, since we have a
// partial read/write, we consume the error and return
// the partial result.
return true, nil
- case syserror.EFAULT:
+ case linuxerr.Equals(linuxerr.EFAULT, translatedErr):
// EFAULT is only shown the user if nothing was
// read/written. If we read something (this case), they see
// a partial read/write. They will then presumably try again
// with an incremented buffer, which will EFAULT with
// result == 0.
return true, nil
- case syserror.EPIPE:
+ case linuxerr.Equals(linuxerr.EPIPE, translatedErr):
// Writes to a pipe or socket will return EPIPE if the other
// side is gone. The partial write is returned. EPIPE will be
// returned on the next call.
@@ -150,15 +151,17 @@ func handleIOErrorImpl(ctx context.Context, partialResult bool, errOrig, intr er
// TODO(gvisor.dev/issue/161): In some cases SIGPIPE should
// also be sent to the application.
return true, nil
- case syserror.ENOSPC:
+ case linuxerr.Equals(linuxerr.ENOSPC, translatedErr):
// Similar to EPIPE. Return what we wrote this time, and let
// ENOSPC be returned on the next call.
return true, nil
- case syserror.ECONNRESET, syserror.ETIMEDOUT:
+ case linuxerr.Equals(linuxerr.ECONNRESET, translatedErr):
+ fallthrough
+ case linuxerr.Equals(linuxerr.ETIMEDOUT, translatedErr):
// For TCP sendfile connections, we may have a reset or timeout. But we
// should just return n as the result.
return true, nil
- case syserror.EWOULDBLOCK:
+ case linuxerr.Equals(linuxerr.EWOULDBLOCK, translatedErr):
// Syscall would block, but completed a partial read/write.
// This case should only be returned by IssueIO for nonblocking
// files. Since we have a partial read/write, we consume
diff --git a/pkg/sentry/syscalls/linux/linux64.go b/pkg/sentry/syscalls/linux/linux64.go
index 090c5ffcb..1732064ef 100644
--- a/pkg/sentry/syscalls/linux/linux64.go
+++ b/pkg/sentry/syscalls/linux/linux64.go
@@ -18,6 +18,7 @@ package linux
import (
"gvisor.dev/gvisor/pkg/abi"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
@@ -187,7 +188,7 @@ var AMD64 = &kernel.SyscallTable{
132: syscalls.Supported("utime", Utime),
133: syscalls.PartiallySupported("mknod", Mknod, "Device creation is not generally supported. Only regular file and FIFO creation are supported.", nil),
134: syscalls.Error("uselib", syserror.ENOSYS, "Obsolete", nil),
- 135: syscalls.ErrorWithEvent("personality", syserror.EINVAL, "Unable to change personality.", nil),
+ 135: syscalls.ErrorWithEvent("personality", linuxerr.EINVAL, "Unable to change personality.", nil),
136: syscalls.ErrorWithEvent("ustat", syserror.ENOSYS, "Needs filesystem support.", nil),
137: syscalls.PartiallySupported("statfs", Statfs, "Depends on the backing file system implementation.", nil),
138: syscalls.PartiallySupported("fstatfs", Fstatfs, "Depends on the backing file system implementation.", nil),
@@ -521,7 +522,7 @@ var ARM64 = &kernel.SyscallTable{
89: syscalls.CapError("acct", linux.CAP_SYS_PACCT, "", nil),
90: syscalls.Supported("capget", Capget),
91: syscalls.Supported("capset", Capset),
- 92: syscalls.ErrorWithEvent("personality", syserror.EINVAL, "Unable to change personality.", nil),
+ 92: syscalls.ErrorWithEvent("personality", linuxerr.EINVAL, "Unable to change personality.", nil),
93: syscalls.Supported("exit", Exit),
94: syscalls.Supported("exit_group", ExitGroup),
95: syscalls.Supported("waitid", Waitid),
diff --git a/pkg/sentry/syscalls/linux/sigset.go b/pkg/sentry/syscalls/linux/sigset.go
index e8c2d8f9e..9dea78085 100644
--- a/pkg/sentry/syscalls/linux/sigset.go
+++ b/pkg/sentry/syscalls/linux/sigset.go
@@ -16,6 +16,7 @@ package linux
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/syserror"
@@ -29,7 +30,7 @@ import (
// syscalls are moved into this package, then they can be unexported.
func CopyInSigSet(t *kernel.Task, sigSetAddr hostarch.Addr, size uint) (linux.SignalSet, error) {
if size != linux.SignalSetSize {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
b := t.CopyScratchBuffer(8)
if _, err := t.CopyInBytes(sigSetAddr, b); err != nil {
diff --git a/pkg/sentry/syscalls/linux/sys_aio.go b/pkg/sentry/syscalls/linux/sys_aio.go
index 70e8569a8..a93fc635b 100644
--- a/pkg/sentry/syscalls/linux/sys_aio.go
+++ b/pkg/sentry/syscalls/linux/sys_aio.go
@@ -17,6 +17,7 @@ package linux
import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/marshal/primitive"
"gvisor.dev/gvisor/pkg/sentry/arch"
@@ -42,7 +43,7 @@ func IoSetup(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
return 0, nil, err
}
if idIn != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
id, err := t.MemoryManager().NewAIOContext(t, uint32(nrEvents))
@@ -66,7 +67,7 @@ func IoDestroy(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
ctx := t.MemoryManager().DestroyAIOContext(t, id)
if ctx == nil {
// Does not exist.
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Drain completed requests amd wait for pending requests until there are no
@@ -97,12 +98,12 @@ func IoGetevents(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.S
// Sanity check arguments.
if minEvents < 0 || minEvents > events {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
ctx, ok := t.MemoryManager().LookupAIOContext(t, id)
if !ok {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Setup the timeout.
@@ -114,7 +115,7 @@ func IoGetevents(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.S
return 0, nil, err
}
if !d.Valid() {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
deadline = t.Kernel().MonotonicClock().Now().Add(d.ToDuration())
haveDeadline = true
@@ -134,7 +135,7 @@ func IoGetevents(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.S
var err error
v, err = waitForRequest(ctx, t, haveDeadline, deadline)
if err != nil {
- if count > 0 || err == syserror.ETIMEDOUT {
+ if count > 0 || linuxerr.Equals(linuxerr.ETIMEDOUT, err) {
return uintptr(count), nil, nil
}
return 0, nil, syserror.ConvertIntr(err, syserror.EINTR)
@@ -171,7 +172,7 @@ func waitForRequest(ctx *mm.AIOContext, t *kernel.Task, haveDeadline bool, deadl
done := ctx.WaitChannel()
if done == nil {
// Context has been destroyed.
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
if err := t.BlockWithDeadline(done, haveDeadline, deadline); err != nil {
return nil, err
@@ -184,7 +185,7 @@ func memoryFor(t *kernel.Task, cb *linux.IOCallback) (usermem.IOSequence, error)
bytes := int(cb.Bytes)
if bytes < 0 {
// Linux also requires that this field fit in ssize_t.
- return usermem.IOSequence{}, syserror.EINVAL
+ return usermem.IOSequence{}, linuxerr.EINVAL
}
// Since this I/O will be asynchronous with respect to t's task goroutine,
@@ -206,7 +207,7 @@ func memoryFor(t *kernel.Task, cb *linux.IOCallback) (usermem.IOSequence, error)
default:
// Not a supported command.
- return usermem.IOSequence{}, syserror.EINVAL
+ return usermem.IOSequence{}, linuxerr.EINVAL
}
}
@@ -286,7 +287,7 @@ func submitCallback(t *kernel.Task, id uint64, cb *linux.IOCallback, cbAddr host
// Check that it is an eventfd.
if _, ok := eventFile.FileOperations.(*eventfd.EventOperations); !ok {
// Not an event FD.
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
}
@@ -299,14 +300,14 @@ func submitCallback(t *kernel.Task, id uint64, cb *linux.IOCallback, cbAddr host
switch cb.OpCode {
case linux.IOCB_CMD_PREAD, linux.IOCB_CMD_PREADV, linux.IOCB_CMD_PWRITE, linux.IOCB_CMD_PWRITEV:
if cb.Offset < 0 {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
}
// Prepare the request.
ctx, ok := t.MemoryManager().LookupAIOContext(t, id)
if !ok {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if err := ctx.Prepare(); err != nil {
return err
@@ -335,7 +336,7 @@ func IoSubmit(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
addr := args[2].Pointer()
if nrEvents < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
for i := int32(0); i < nrEvents; i++ {
diff --git a/pkg/sentry/syscalls/linux/sys_capability.go b/pkg/sentry/syscalls/linux/sys_capability.go
index d3b85e11b..782bcb94f 100644
--- a/pkg/sentry/syscalls/linux/sys_capability.go
+++ b/pkg/sentry/syscalls/linux/sys_capability.go
@@ -16,6 +16,7 @@ package linux
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
@@ -24,7 +25,7 @@ import (
func lookupCaps(t *kernel.Task, tid kernel.ThreadID) (permitted, inheritable, effective auth.CapabilitySet, err error) {
if tid < 0 {
- err = syserror.EINVAL
+ err = linuxerr.EINVAL
return
}
if tid > 0 {
@@ -97,7 +98,7 @@ func Capget(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
return 0, nil, err
}
if dataAddr != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
return 0, nil, nil
}
@@ -144,6 +145,6 @@ func Capset(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
if _, err := hdr.CopyOut(t, hdrAddr); err != nil {
return 0, nil, err
}
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
}
diff --git a/pkg/sentry/syscalls/linux/sys_epoll.go b/pkg/sentry/syscalls/linux/sys_epoll.go
index 69cbc98d0..daa151bb4 100644
--- a/pkg/sentry/syscalls/linux/sys_epoll.go
+++ b/pkg/sentry/syscalls/linux/sys_epoll.go
@@ -16,6 +16,7 @@ package linux
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
@@ -31,7 +32,7 @@ import (
func EpollCreate1(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) {
flags := args[0].Int()
if flags & ^linux.EPOLL_CLOEXEC != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
closeOnExec := flags&linux.EPOLL_CLOEXEC != 0
@@ -48,7 +49,7 @@ func EpollCreate(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.S
size := args[0].Int()
if size <= 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
fd, err := syscalls.CreateEpoll(t, false)
@@ -101,7 +102,7 @@ func EpollCtl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
mask |= waiter.EventHUp | waiter.EventErr
return 0, nil, syscalls.UpdateEpoll(t, epfd, fd, flags, mask, data)
default:
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
}
diff --git a/pkg/sentry/syscalls/linux/sys_eventfd.go b/pkg/sentry/syscalls/linux/sys_eventfd.go
index 3b4f879e4..7ba9a755e 100644
--- a/pkg/sentry/syscalls/linux/sys_eventfd.go
+++ b/pkg/sentry/syscalls/linux/sys_eventfd.go
@@ -16,11 +16,11 @@ package linux
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/kernel/eventfd"
- "gvisor.dev/gvisor/pkg/syserror"
)
// Eventfd2 implements linux syscall eventfd2(2).
@@ -30,7 +30,7 @@ func Eventfd2(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
allOps := uint(linux.EFD_SEMAPHORE | linux.EFD_NONBLOCK | linux.EFD_CLOEXEC)
if flags & ^allOps != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
event := eventfd.New(t, uint64(initVal), flags&linux.EFD_SEMAPHORE != 0)
diff --git a/pkg/sentry/syscalls/linux/sys_file.go b/pkg/sentry/syscalls/linux/sys_file.go
index 9cd238efd..3d45341f2 100644
--- a/pkg/sentry/syscalls/linux/sys_file.go
+++ b/pkg/sentry/syscalls/linux/sys_file.go
@@ -18,6 +18,7 @@ import (
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/marshal/primitive"
"gvisor.dev/gvisor/pkg/sentry/arch"
@@ -275,7 +276,7 @@ func mknodAt(t *kernel.Task, dirFD int32, addr hostarch.Addr, mode linux.FileMod
default:
// "EINVAL - mode requested creation of something other than a
// regular file, device special file, FIFO or socket." - mknod(2)
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
})
}
@@ -394,8 +395,8 @@ func createAt(t *kernel.Task, dirFD int32, addr hostarch.Addr, flags uint, mode
}
var newFile *fs.File
- switch err {
- case nil:
+ switch {
+ case err == nil:
// Like sys_open, check for a few things about the
// filesystem before trying to get a reference to the
// fs.File. The same constraints on Check apply.
@@ -418,7 +419,7 @@ func createAt(t *kernel.Task, dirFD int32, addr hostarch.Addr, flags uint, mode
return syserror.ConvertIntr(err, syserror.ERESTARTSYS)
}
defer newFile.DecRef(t)
- case syserror.ENOENT:
+ case linuxerr.Equals(linuxerr.ENOENT, err):
// File does not exist. Proceed with creation.
// Do we have write permissions on the parent?
@@ -527,7 +528,7 @@ func accessAt(t *kernel.Task, dirFD int32, addr hostarch.Addr, mode uint) error
// Sanity check the mode.
if mode&^(rOK|wOK|xOK) != 0 {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
return fileOpOn(t, dirFD, path, true /* resolve */, func(root *fs.Dirent, d *fs.Dirent, _ uint) error {
@@ -843,7 +844,7 @@ func Dup3(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallC
flags := args[2].Uint()
if oldfd == newfd {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
oldFile := t.GetFile(oldfd)
@@ -905,7 +906,7 @@ func fSetOwn(t *kernel.Task, fd int, file *fs.File, who int32) error {
if who < 0 {
// Check for overflow before flipping the sign.
if who-1 > who {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
pg := t.PIDNamespace().ProcessGroupWithID(kernel.ProcessGroupID(-who))
a.SetOwnerProcessGroup(t, pg)
@@ -976,7 +977,7 @@ func Fcntl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
case 2:
sw = fs.SeekEnd
default:
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Compute the lock offset.
@@ -995,7 +996,7 @@ func Fcntl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
}
off = uattr.Size
default:
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Compute the lock range.
@@ -1043,7 +1044,7 @@ func Fcntl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
file.Dirent.Inode.LockCtx.Posix.UnlockRegion(t.FDTable(), rng)
return 0, nil, nil
default:
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
case linux.F_GETOWN:
return uintptr(fGetOwn(t, file)), nil, nil
@@ -1085,7 +1086,7 @@ func Fcntl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
a.SetOwnerProcessGroup(t, pg)
return 0, nil, nil
default:
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
case linux.F_GET_SEALS:
val, err := tmpfs.GetSeals(file.Dirent.Inode)
@@ -1099,14 +1100,14 @@ func Fcntl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
case linux.F_GETPIPE_SZ:
sz, ok := file.FileOperations.(fs.FifoSizer)
if !ok {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
size, err := sz.FifoSize(t, file)
return uintptr(size), nil, err
case linux.F_SETPIPE_SZ:
sz, ok := file.FileOperations.(fs.FifoSizer)
if !ok {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
n, err := sz.SetFifoSize(int64(args[2].Int()))
return uintptr(n), nil, err
@@ -1118,7 +1119,7 @@ func Fcntl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
return 0, nil, a.SetSignal(linux.Signal(args[2].Int()))
default:
// Everything else is not yet supported.
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
}
@@ -1131,7 +1132,7 @@ func Fadvise64(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
// Note: offset is allowed to be negative.
if length < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
file := t.GetFile(fd)
@@ -1153,7 +1154,7 @@ func Fadvise64(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
case linux.POSIX_FADV_DONTNEED:
case linux.POSIX_FADV_NOREUSE:
default:
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Sure, whatever.
@@ -1178,12 +1179,12 @@ func mkdirAt(t *kernel.Task, dirFD int32, addr hostarch.Addr, mode linux.FileMod
// Does this directory exist already?
remainingTraversals := uint(linux.MaxSymlinkTraversals)
f, err := t.MountNamespace().FindInode(t, root, d, name, &remainingTraversals)
- switch err {
- case nil:
+ switch {
+ case err == nil:
// The directory existed.
defer f.DecRef(t)
return syserror.EEXIST
- case syserror.EACCES:
+ case linuxerr.Equals(linuxerr.EACCES, err):
// Permission denied while walking to the directory.
return err
default:
@@ -1236,7 +1237,7 @@ func rmdirAt(t *kernel.Task, dirFD int32, addr hostarch.Addr) error {
// dot vs. double dots.
switch name {
case ".":
- return syserror.EINVAL
+ return linuxerr.EINVAL
case "..":
return syserror.ENOTEMPTY
}
@@ -1431,7 +1432,7 @@ func Linkat(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
// Sanity check flags.
if flags&^(linux.AT_SYMLINK_FOLLOW|linux.AT_EMPTY_PATH) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
resolve := flags&linux.AT_SYMLINK_FOLLOW == linux.AT_SYMLINK_FOLLOW
@@ -1464,8 +1465,8 @@ func readlinkAt(t *kernel.Task, dirFD int32, addr hostarch.Addr, bufAddr hostarc
}
s, err := d.Inode.Readlink(t)
- if err == syserror.ENOLINK {
- return syserror.EINVAL
+ if linuxerr.Equals(linuxerr.ENOLINK, err) {
+ return linuxerr.EINVAL
}
if err != nil {
return err
@@ -1557,7 +1558,7 @@ func Truncate(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
length := args[1].Int64()
if length < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
path, dirPath, err := copyInPath(t, addr, false /* allowEmpty */)
@@ -1565,13 +1566,13 @@ func Truncate(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
return 0, nil, err
}
if dirPath {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if uint64(length) >= t.ThreadGroup().Limits().Get(limits.FileSize).Cur {
- t.SendSignal(&arch.SignalInfo{
+ t.SendSignal(&linux.SignalInfo{
Signo: int32(linux.SIGXFSZ),
- Code: arch.SignalInfoUser,
+ Code: linux.SI_USER,
})
return 0, nil, syserror.EFBIG
}
@@ -1583,7 +1584,7 @@ func Truncate(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
// In contrast to open(O_TRUNC), truncate(2) is only valid for file
// types.
if !fs.IsFile(d.Inode.StableAttr) {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
// Reject truncation if the access permissions do not allow truncation.
@@ -1617,24 +1618,24 @@ func Ftruncate(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
// Reject truncation if the file flags do not permit this operation.
// This is different from truncate(2) above.
if !file.Flags().Write {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// In contrast to open(O_TRUNC), truncate(2) is only valid for file
// types. Note that this is different from truncate(2) above, where a
// directory returns EISDIR.
if !fs.IsFile(file.Dirent.Inode.StableAttr) {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if length < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if uint64(length) >= t.ThreadGroup().Limits().Get(limits.FileSize).Cur {
- t.SendSignal(&arch.SignalInfo{
+ t.SendSignal(&linux.SignalInfo{
Signo: int32(linux.SIGXFSZ),
- Code: arch.SignalInfoUser,
+ Code: linux.SI_USER,
})
return 0, nil, syserror.EFBIG
}
@@ -1673,14 +1674,16 @@ func chown(t *kernel.Task, d *fs.Dirent, uid auth.UID, gid auth.GID) error {
if err != nil {
return err
}
+
c := t.Credentials()
hasCap := d.Inode.CheckCapability(t, linux.CAP_CHOWN)
isOwner := uattr.Owner.UID == c.EffectiveKUID
+ var clearPrivilege bool
if uid.Ok() {
kuid := c.UserNamespace.MapToKUID(uid)
// Valid UID must be supplied if UID is to be changed.
if !kuid.Ok() {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
// "Only a privileged process (CAP_CHOWN) may change the owner
@@ -1693,13 +1696,18 @@ func chown(t *kernel.Task, d *fs.Dirent, uid auth.UID, gid auth.GID) error {
return syserror.EPERM
}
+ // The setuid and setgid bits are cleared during a chown.
+ if uattr.Owner.UID != kuid {
+ clearPrivilege = true
+ }
+
owner.UID = kuid
}
if gid.Ok() {
kgid := c.UserNamespace.MapToKGID(gid)
// Valid GID must be supplied if GID is to be changed.
if !kgid.Ok() {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
// "The owner of a file may change the group of the file to any
@@ -1711,6 +1719,11 @@ func chown(t *kernel.Task, d *fs.Dirent, uid auth.UID, gid auth.GID) error {
return syserror.EPERM
}
+ // The setuid and setgid bits are cleared during a chown.
+ if uattr.Owner.GID != kgid {
+ clearPrivilege = true
+ }
+
owner.GID = kgid
}
@@ -1721,10 +1734,14 @@ func chown(t *kernel.Task, d *fs.Dirent, uid auth.UID, gid auth.GID) error {
if err := d.Inode.SetOwner(t, d, owner); err != nil {
return err
}
+ // Clear privilege bits if needed and they are set.
+ if clearPrivilege && uattr.Perms.HasSetUIDOrGID() && !fs.IsDir(d.Inode.StableAttr) {
+ uattr.Perms.DropSetUIDAndMaybeGID()
+ if !d.Inode.SetPermissions(t, d, uattr.Perms) {
+ return syserror.EPERM
+ }
+ }
- // When the owner or group are changed by an unprivileged user,
- // chown(2) also clears the set-user-ID and set-group-ID bits, but
- // we do not support them.
return nil
}
@@ -1792,7 +1809,7 @@ func Fchownat(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
flags := args[4].Int()
if flags&^(linux.AT_EMPTY_PATH|linux.AT_SYMLINK_NOFOLLOW) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
return 0, nil, chownAt(t, dirFD, addr, flags&linux.AT_SYMLINK_NOFOLLOW == 0, flags&linux.AT_EMPTY_PATH != 0, uid, gid)
@@ -1897,7 +1914,7 @@ func utimes(t *kernel.Task, dirFD int32, addr hostarch.Addr, ts fs.TimeSpec, res
if addr == 0 && dirFD != linux.AT_FDCWD {
if !resolve {
// Linux returns EINVAL in this case. See utimes.c.
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
f := t.GetFile(dirFD)
if f == nil {
@@ -1980,7 +1997,7 @@ func Utimensat(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
return 0, nil, err
}
if !timespecIsValid(times[0]) || !timespecIsValid(times[1]) {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// If both are UTIME_OMIT, this is a noop.
@@ -2015,7 +2032,7 @@ func Futimesat(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
}
if times[0].Usec >= 1e6 || times[0].Usec < 0 ||
times[1].Usec >= 1e6 || times[1].Usec < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
ts = fs.TimeSpec{
@@ -2101,7 +2118,7 @@ func Fallocate(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
defer file.DecRef(t)
if offset < 0 || length <= 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if mode != 0 {
t.Kernel().EmitUnimplementedEvent(t)
@@ -2124,9 +2141,9 @@ func Fallocate(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
return 0, nil, syserror.EFBIG
}
if uint64(size) >= t.ThreadGroup().Limits().Get(limits.FileSize).Cur {
- t.SendSignal(&arch.SignalInfo{
+ t.SendSignal(&linux.SignalInfo{
Signo: int32(linux.SIGXFSZ),
- Code: arch.SignalInfoUser,
+ Code: linux.SI_USER,
})
return 0, nil, syserror.EFBIG
}
@@ -2191,7 +2208,7 @@ func Flock(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
file.Dirent.Inode.LockCtx.BSD.UnlockRegion(file, rng)
default:
// flock(2): EINVAL operation is invalid.
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
return 0, nil, nil
@@ -2210,7 +2227,7 @@ func MemfdCreate(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.S
if flags&^memfdAllFlags != 0 {
// Unknown bits in flags.
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
allowSeals := flags&linux.MFD_ALLOW_SEALING != 0
@@ -2221,7 +2238,7 @@ func MemfdCreate(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.S
return 0, nil, err
}
if len(name) > memfdMaxNameLen {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
name = memfdPrefix + name
diff --git a/pkg/sentry/syscalls/linux/sys_futex.go b/pkg/sentry/syscalls/linux/sys_futex.go
index eeea1613b..a9e9126cc 100644
--- a/pkg/sentry/syscalls/linux/sys_futex.go
+++ b/pkg/sentry/syscalls/linux/sys_futex.go
@@ -18,6 +18,7 @@ import (
"time"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
@@ -210,7 +211,7 @@ func Futex(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
// WAIT_BITSET uses an absolute timeout which is either
// CLOCK_MONOTONIC or CLOCK_REALTIME.
if mask == 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
n, err := futexWaitAbsolute(t, clockRealtime, timespec, forever, addr, private, uint32(val), mask)
return n, nil, err
@@ -224,7 +225,7 @@ func Futex(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
case linux.FUTEX_WAKE_BITSET:
if mask == 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if val <= 0 {
// The Linux kernel wakes one waiter even if val is
@@ -295,7 +296,7 @@ func SetRobustList(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel
length := args[1].SizeT()
if length != uint(linux.SizeOfRobustListHead) {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
t.SetRobustList(head)
return 0, nil, nil
@@ -310,7 +311,7 @@ func GetRobustList(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel
sizeAddr := args[2].Pointer()
if tid < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
ot := t
diff --git a/pkg/sentry/syscalls/linux/sys_getdents.go b/pkg/sentry/syscalls/linux/sys_getdents.go
index bbba71d8f..355fbd766 100644
--- a/pkg/sentry/syscalls/linux/sys_getdents.go
+++ b/pkg/sentry/syscalls/linux/sys_getdents.go
@@ -19,6 +19,7 @@ import (
"io"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fs"
@@ -38,7 +39,7 @@ func Getdents(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
minSize := int(smallestDirent(t.Arch()))
if size < minSize {
// size is smaller than smallest possible dirent.
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
n, err := getdents(t, fd, addr, size, (*dirent).Serialize)
@@ -54,7 +55,7 @@ func Getdents64(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sy
minSize := int(smallestDirent64(t.Arch()))
if size < minSize {
// size is smaller than smallest possible dirent.
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
n, err := getdents(t, fd, addr, size, (*dirent).Serialize64)
diff --git a/pkg/sentry/syscalls/linux/sys_identity.go b/pkg/sentry/syscalls/linux/sys_identity.go
index a29d307e5..50fcadb58 100644
--- a/pkg/sentry/syscalls/linux/sys_identity.go
+++ b/pkg/sentry/syscalls/linux/sys_identity.go
@@ -15,10 +15,10 @@
package linux
import (
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
- "gvisor.dev/gvisor/pkg/syserror"
)
const (
@@ -142,7 +142,7 @@ func Setresgid(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
func Getgroups(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) {
size := int(args[0].Int())
if size < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
kgids := t.Credentials().ExtraKGIDs
// "If size is zero, list is not modified, but the total number of
@@ -151,7 +151,7 @@ func Getgroups(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
return uintptr(len(kgids)), nil, nil
}
if size < len(kgids) {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
gids := make([]auth.GID, len(kgids))
for i, kgid := range kgids {
@@ -167,7 +167,7 @@ func Getgroups(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
func Setgroups(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) {
size := args[0].Int()
if size < 0 || size > maxNGroups {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if size == 0 {
return 0, nil, t.SetExtraGIDs(nil)
diff --git a/pkg/sentry/syscalls/linux/sys_inotify.go b/pkg/sentry/syscalls/linux/sys_inotify.go
index cf47bb9dd..48c8dbdca 100644
--- a/pkg/sentry/syscalls/linux/sys_inotify.go
+++ b/pkg/sentry/syscalls/linux/sys_inotify.go
@@ -16,6 +16,7 @@ package linux
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/fs/anon"
@@ -30,7 +31,7 @@ func InotifyInit1(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.
flags := int(args[0].Int())
if flags&^allFlags != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
dirent := fs.NewDirent(t, anon.NewInode(t), "inotify")
@@ -72,7 +73,7 @@ func fdToInotify(t *kernel.Task, fd int32) (*fs.Inotify, *fs.File, error) {
if !ok {
// Not an inotify fd.
file.DecRef(t)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
return ino, file, nil
@@ -91,7 +92,7 @@ func InotifyAddWatch(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kern
// "EINVAL: The given event mask contains no valid events."
// -- inotify_add_watch(2)
if validBits := mask & linux.ALL_INOTIFY_BITS; validBits == 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
ino, file, err := fdToInotify(t, fd)
diff --git a/pkg/sentry/syscalls/linux/sys_lseek.go b/pkg/sentry/syscalls/linux/sys_lseek.go
index 0046347cb..c16c63ecc 100644
--- a/pkg/sentry/syscalls/linux/sys_lseek.go
+++ b/pkg/sentry/syscalls/linux/sys_lseek.go
@@ -15,6 +15,7 @@
package linux
import (
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/kernel"
@@ -44,7 +45,7 @@ func Lseek(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
case 2:
sw = fs.SeekEnd
default:
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
offset, serr := file.Seek(t, sw, offset)
diff --git a/pkg/sentry/syscalls/linux/sys_membarrier.go b/pkg/sentry/syscalls/linux/sys_membarrier.go
index 63ee5d435..4b67f2536 100644
--- a/pkg/sentry/syscalls/linux/sys_membarrier.go
+++ b/pkg/sentry/syscalls/linux/sys_membarrier.go
@@ -16,6 +16,7 @@ package linux
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/syserror"
@@ -29,7 +30,7 @@ func Membarrier(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sy
switch cmd {
case linux.MEMBARRIER_CMD_QUERY:
if flags != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
var supportedCommands uintptr
if t.Kernel().Platform.HaveGlobalMemoryBarrier() {
@@ -46,10 +47,10 @@ func Membarrier(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sy
return supportedCommands, nil, nil
case linux.MEMBARRIER_CMD_GLOBAL, linux.MEMBARRIER_CMD_GLOBAL_EXPEDITED, linux.MEMBARRIER_CMD_PRIVATE_EXPEDITED:
if flags != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if !t.Kernel().Platform.HaveGlobalMemoryBarrier() {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if cmd == linux.MEMBARRIER_CMD_PRIVATE_EXPEDITED && !t.MemoryManager().IsMembarrierPrivateEnabled() {
return 0, nil, syserror.EPERM
@@ -57,28 +58,28 @@ func Membarrier(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sy
return 0, nil, t.Kernel().Platform.GlobalMemoryBarrier()
case linux.MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED:
if flags != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if !t.Kernel().Platform.HaveGlobalMemoryBarrier() {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// no-op
return 0, nil, nil
case linux.MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED:
if flags != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if !t.Kernel().Platform.HaveGlobalMemoryBarrier() {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
t.MemoryManager().EnableMembarrierPrivate()
return 0, nil, nil
case linux.MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ:
if flags&^linux.MEMBARRIER_CMD_FLAG_CPU != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if !t.RSeqAvailable() {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if !t.MemoryManager().IsMembarrierRSeqEnabled() {
return 0, nil, syserror.EPERM
@@ -88,16 +89,16 @@ func Membarrier(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sy
return 0, nil, t.Kernel().Platform.PreemptAllCPUs()
case linux.MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ:
if flags != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if !t.RSeqAvailable() {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
t.MemoryManager().EnableMembarrierRSeq()
return 0, nil, nil
default:
// Probably a command we don't implement.
t.Kernel().EmitUnimplementedEvent(t)
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
}
diff --git a/pkg/sentry/syscalls/linux/sys_mempolicy.go b/pkg/sentry/syscalls/linux/sys_mempolicy.go
index 6d27f4292..62ec3e27f 100644
--- a/pkg/sentry/syscalls/linux/sys_mempolicy.go
+++ b/pkg/sentry/syscalls/linux/sys_mempolicy.go
@@ -18,6 +18,7 @@ import (
"fmt"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
@@ -43,7 +44,7 @@ func copyInNodemask(t *kernel.Task, addr hostarch.Addr, maxnode uint32) (uint64,
// maxnode-1, not maxnode, as the number of bits.
bits := maxnode - 1
if bits > hostarch.PageSize*8 { // also handles overflow from maxnode == 0
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
if bits == 0 {
return 0, nil
@@ -58,12 +59,12 @@ func copyInNodemask(t *kernel.Task, addr hostarch.Addr, maxnode uint32) (uint64,
// Check that only allowed bits in the first unsigned long in the nodemask
// are set.
if val&^allowedNodemask != 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// Check that all remaining bits in the nodemask are 0.
for i := 8; i < len(buf); i++ {
if buf[i] != 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
}
return val, nil
@@ -74,7 +75,7 @@ func copyOutNodemask(t *kernel.Task, addr hostarch.Addr, maxnode uint32, val uin
// bits.
bits := maxnode - 1
if bits > hostarch.PageSize*8 { // also handles overflow from maxnode == 0
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if bits == 0 {
return nil
@@ -110,7 +111,7 @@ func GetMempolicy(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.
flags := args[4].Uint()
if flags&^(linux.MPOL_F_NODE|linux.MPOL_F_ADDR|linux.MPOL_F_MEMS_ALLOWED) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
nodeFlag := flags&linux.MPOL_F_NODE != 0
addrFlag := flags&linux.MPOL_F_ADDR != 0
@@ -119,7 +120,7 @@ func GetMempolicy(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.
// "EINVAL: The value specified by maxnode is less than the number of node
// IDs supported by the system." - get_mempolicy(2)
if nodemask != 0 && maxnode < maxNodes {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// "If flags specifies MPOL_F_MEMS_ALLOWED [...], the mode argument is
@@ -130,7 +131,7 @@ func GetMempolicy(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.
// "It is not permitted to combine MPOL_F_MEMS_ALLOWED with either
// MPOL_F_ADDR or MPOL_F_NODE."
if nodeFlag || addrFlag {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if err := copyOutNodemask(t, nodemask, maxnode, allowedNodemask); err != nil {
return 0, nil, err
@@ -184,7 +185,7 @@ func GetMempolicy(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.
// mm/mempolicy.c:do_get_mempolicy() doesn't special-case NULL; it will
// just (usually) fail to find a VMA at address 0 and return EFAULT.
if addr != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// "If flags is specified as 0, then information about the calling thread's
@@ -198,7 +199,7 @@ func GetMempolicy(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.
policy, nodemaskVal := t.NumaPolicy()
if nodeFlag {
if policy&^linux.MPOL_MODE_FLAGS != linux.MPOL_INTERLEAVE {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
policy = linux.MPOL_DEFAULT // maxNodes == 1
}
@@ -240,7 +241,7 @@ func Mbind(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
flags := args[5].Uint()
if flags&^linux.MPOL_MF_VALID != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// "If MPOL_MF_MOVE_ALL is passed in flags ... [the] calling thread must be
// privileged (CAP_SYS_NICE) to use this flag." - mbind(2)
@@ -264,11 +265,11 @@ func copyInMempolicyNodemask(t *kernel.Task, modeWithFlags linux.NumaPolicy, nod
mode := linux.NumaPolicy(modeWithFlags &^ linux.MPOL_MODE_FLAGS)
if flags == linux.MPOL_MODE_FLAGS {
// Can't specify both mode flags simultaneously.
- return 0, 0, syserror.EINVAL
+ return 0, 0, linuxerr.EINVAL
}
if mode < 0 || mode >= linux.MPOL_MAX {
// Must specify a valid mode.
- return 0, 0, syserror.EINVAL
+ return 0, 0, linuxerr.EINVAL
}
var nodemaskVal uint64
@@ -285,22 +286,22 @@ func copyInMempolicyNodemask(t *kernel.Task, modeWithFlags linux.NumaPolicy, nod
// "nodemask must be specified as NULL." - set_mempolicy(2). This is inaccurate;
// Linux allows a nodemask to be specified, as long as it is empty.
if nodemaskVal != 0 {
- return 0, 0, syserror.EINVAL
+ return 0, 0, linuxerr.EINVAL
}
case linux.MPOL_BIND, linux.MPOL_INTERLEAVE:
// These require a non-empty nodemask.
if nodemaskVal == 0 {
- return 0, 0, syserror.EINVAL
+ return 0, 0, linuxerr.EINVAL
}
case linux.MPOL_PREFERRED:
// This permits an empty nodemask, as long as no flags are set.
if nodemaskVal == 0 && flags != 0 {
- return 0, 0, syserror.EINVAL
+ return 0, 0, linuxerr.EINVAL
}
case linux.MPOL_LOCAL:
// This requires an empty nodemask and no flags set ...
if nodemaskVal != 0 || flags != 0 {
- return 0, 0, syserror.EINVAL
+ return 0, 0, linuxerr.EINVAL
}
// ... and is implemented as MPOL_PREFERRED.
mode = linux.MPOL_PREFERRED
diff --git a/pkg/sentry/syscalls/linux/sys_mmap.go b/pkg/sentry/syscalls/linux/sys_mmap.go
index 70da0707d..74279c82b 100644
--- a/pkg/sentry/syscalls/linux/sys_mmap.go
+++ b/pkg/sentry/syscalls/linux/sys_mmap.go
@@ -18,13 +18,13 @@ import (
"bytes"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
+ "gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/memmap"
"gvisor.dev/gvisor/pkg/sentry/mm"
"gvisor.dev/gvisor/pkg/syserror"
-
- "gvisor.dev/gvisor/pkg/hostarch"
)
// Brk implements linux syscall brk(2).
@@ -51,7 +51,7 @@ func Mmap(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallC
// Require exactly one of MAP_PRIVATE and MAP_SHARED.
if private == shared {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
opts := memmap.MMapOpts{
@@ -132,7 +132,7 @@ func Mremap(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
newAddr := args[4].Pointer()
if flags&^(linux.MREMAP_MAYMOVE|linux.MREMAP_FIXED) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
mayMove := flags&linux.MREMAP_MAYMOVE != 0
fixed := flags&linux.MREMAP_FIXED != 0
@@ -147,7 +147,7 @@ func Mremap(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
case !mayMove && fixed:
// "If MREMAP_FIXED is specified, then MREMAP_MAYMOVE must also be
// specified." - mremap(2)
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
rv, err := t.MemoryManager().MRemap(t, oldAddr, oldSize, newSize, mm.MRemapOpts{
@@ -178,7 +178,7 @@ func Madvise(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
// "The Linux implementation requires that the address addr be
// page-aligned, and allows length to be zero." - madvise(2)
if addr.RoundDown() != addr {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if length == 0 {
return 0, nil, nil
@@ -186,7 +186,7 @@ func Madvise(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
// Not explicitly stated: length need not be page-aligned.
lenAddr, ok := hostarch.Addr(length).RoundUp()
if !ok {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
length = uint64(lenAddr)
@@ -217,7 +217,7 @@ func Madvise(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
return 0, nil, syserror.EPERM
default:
// If adv is not a valid value tell the caller.
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
}
@@ -228,7 +228,7 @@ func Mincore(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
vec := args[2].Pointer()
if addr != addr.RoundDown() {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// "The length argument need not be a multiple of the page size, but since
// residency information is returned for whole pages, length is effectively
@@ -265,11 +265,11 @@ func Msync(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
// semantics that are (currently) equivalent to specifying MS_ASYNC." -
// msync(2)
if flags&^(linux.MS_ASYNC|linux.MS_SYNC|linux.MS_INVALIDATE) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
sync := flags&linux.MS_SYNC != 0
if sync && flags&linux.MS_ASYNC != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
err := t.MemoryManager().MSync(t, addr, uint64(length), mm.MSyncOpts{
Sync: sync,
@@ -295,7 +295,7 @@ func Mlock2(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
flags := args[2].Int()
if flags&^(linux.MLOCK_ONFAULT) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
mode := memmap.MLockEager
@@ -318,7 +318,7 @@ func Mlockall(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
flags := args[0].Int()
if flags&^(linux.MCL_CURRENT|linux.MCL_FUTURE|linux.MCL_ONFAULT) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
mode := memmap.MLockEager
diff --git a/pkg/sentry/syscalls/linux/sys_mount.go b/pkg/sentry/syscalls/linux/sys_mount.go
index 864d2138c..8bf4e9f06 100644
--- a/pkg/sentry/syscalls/linux/sys_mount.go
+++ b/pkg/sentry/syscalls/linux/sys_mount.go
@@ -16,12 +16,12 @@ package linux
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
+ "gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/syserror"
-
- "gvisor.dev/gvisor/pkg/hostarch"
)
// Mount implements Linux syscall mount(2).
@@ -83,7 +83,7 @@ func Mount(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
// unknown or unsupported flags are passed. Since we don't implement
// everything, we fail explicitly on flags that are unimplemented.
if flags&(unsupportedOps|unsupportedFlags) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
rsys, ok := fs.FindFilesystem(fsType)
@@ -107,7 +107,7 @@ func Mount(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
rootInode, err := rsys.Mount(t, sourcePath, superFlags, data, nil)
if err != nil {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if err := fileOpOn(t, linux.AT_FDCWD, targetPath, true /* resolve */, func(root *fs.Dirent, d *fs.Dirent, _ uint) error {
@@ -130,7 +130,7 @@ func Umount2(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
const unsupported = linux.MNT_FORCE | linux.MNT_EXPIRE
if flags&unsupported != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
path, _, err := copyInPath(t, addr, false /* allowEmpty */)
diff --git a/pkg/sentry/syscalls/linux/sys_pipe.go b/pkg/sentry/syscalls/linux/sys_pipe.go
index d95034347..5925c2263 100644
--- a/pkg/sentry/syscalls/linux/sys_pipe.go
+++ b/pkg/sentry/syscalls/linux/sys_pipe.go
@@ -16,13 +16,13 @@ package linux
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/marshal/primitive"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/kernel/pipe"
- "gvisor.dev/gvisor/pkg/syserror"
)
// LINT.IfChange
@@ -30,7 +30,7 @@ import (
// pipe2 implements the actual system call with flags.
func pipe2(t *kernel.Task, addr hostarch.Addr, flags uint) (uintptr, error) {
if flags&^(linux.O_NONBLOCK|linux.O_CLOEXEC) != 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
r, w := pipe.NewConnectedPipe(t, pipe.DefaultPipeSize)
diff --git a/pkg/sentry/syscalls/linux/sys_poll.go b/pkg/sentry/syscalls/linux/sys_poll.go
index da548a14a..f2056d850 100644
--- a/pkg/sentry/syscalls/linux/sys_poll.go
+++ b/pkg/sentry/syscalls/linux/sys_poll.go
@@ -18,6 +18,7 @@ import (
"time"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fs"
@@ -128,7 +129,7 @@ func pollBlock(t *kernel.Task, pfd []linux.PollFD, timeout time.Duration) (time.
// Wait for a notification.
timeout, err = t.BlockWithTimeout(ch, !forever, timeout)
if err != nil {
- if err == syserror.ETIMEDOUT {
+ if linuxerr.Equals(linuxerr.ETIMEDOUT, err) {
err = nil
}
return timeout, 0, err
@@ -157,7 +158,7 @@ func pollBlock(t *kernel.Task, pfd []linux.PollFD, timeout time.Duration) (time.
// CopyInPollFDs copies an array of struct pollfd unless nfds exceeds the max.
func CopyInPollFDs(t *kernel.Task, addr hostarch.Addr, nfds uint) ([]linux.PollFD, error) {
if uint64(nfds) > t.ThreadGroup().Limits().GetCapped(limits.NumberOfFiles, fileCap) {
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
pfd := make([]linux.PollFD, nfds)
@@ -217,7 +218,7 @@ func CopyInFDSet(t *kernel.Task, addr hostarch.Addr, nBytes, nBitsInLastPartialB
func doSelect(t *kernel.Task, nfds int, readFDs, writeFDs, exceptFDs hostarch.Addr, timeout time.Duration) (uintptr, error) {
if nfds < 0 || nfds > fileCap {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// Calculate the size of the fd sets (one bit per fd).
@@ -404,7 +405,7 @@ func (p *pollRestartBlock) Restart(t *kernel.Task) (uintptr, error) {
func poll(t *kernel.Task, pfdAddr hostarch.Addr, nfds uint, timeout time.Duration) (uintptr, error) {
remainingTimeout, n, err := doPoll(t, pfdAddr, nfds, timeout)
// On an interrupt poll(2) is restarted with the remaining timeout.
- if err == syserror.EINTR {
+ if linuxerr.Equals(linuxerr.EINTR, err) {
t.SetSyscallRestartBlock(&pollRestartBlock{
pfdAddr: pfdAddr,
nfds: nfds,
@@ -463,7 +464,7 @@ func Ppoll(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
//
// Note that this means that if err is nil but copyErr is not, copyErr is
// ignored. This is consistent with Linux.
- if err == syserror.EINTR && copyErr == nil {
+ if linuxerr.Equals(linuxerr.EINTR, err) && copyErr == nil {
err = syserror.ERESTARTNOHAND
}
return n, nil, err
@@ -485,7 +486,7 @@ func Select(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
return 0, nil, err
}
if timeval.Sec < 0 || timeval.Usec < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
timeout = time.Duration(timeval.ToNsecCapped())
}
@@ -493,7 +494,7 @@ func Select(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
n, err := doSelect(t, nfds, readFDs, writeFDs, exceptFDs, timeout)
copyErr := copyOutTimevalRemaining(t, startNs, timeout, timevalAddr)
// See comment in Ppoll.
- if err == syserror.EINTR && copyErr == nil {
+ if linuxerr.Equals(linuxerr.EINTR, err) && copyErr == nil {
err = syserror.ERESTARTNOHAND
}
return n, nil, err
@@ -538,7 +539,7 @@ func Pselect(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
n, err := doSelect(t, nfds, readFDs, writeFDs, exceptFDs, timeout)
copyErr := copyOutTimespecRemaining(t, startNs, timeout, timespecAddr)
// See comment in Ppoll.
- if err == syserror.EINTR && copyErr == nil {
+ if linuxerr.Equals(linuxerr.EINTR, err) && copyErr == nil {
err = syserror.ERESTARTNOHAND
}
return n, nil, err
diff --git a/pkg/sentry/syscalls/linux/sys_prctl.go b/pkg/sentry/syscalls/linux/sys_prctl.go
index 9890dd946..534f1e632 100644
--- a/pkg/sentry/syscalls/linux/sys_prctl.go
+++ b/pkg/sentry/syscalls/linux/sys_prctl.go
@@ -18,6 +18,7 @@ import (
"fmt"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/marshal/primitive"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fs"
@@ -38,7 +39,7 @@ func Prctl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
case linux.PR_SET_PDEATHSIG:
sig := linux.Signal(args[1].Int())
if sig != 0 && !sig.IsValid() {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
t.SetParentDeathSignal(sig)
return 0, nil, nil
@@ -69,7 +70,7 @@ func Prctl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
d = mm.UserDumpable
default:
// N.B. Userspace may not pass SUID_DUMP_ROOT.
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
t.MemoryManager().SetDumpability(d)
return 0, nil, nil
@@ -90,7 +91,7 @@ func Prctl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
} else if val == 1 {
t.SetKeepCaps(true)
} else {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
return 0, nil, nil
@@ -98,7 +99,7 @@ func Prctl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
case linux.PR_SET_NAME:
addr := args[1].Pointer()
name, err := t.CopyInString(addr, linux.TASK_COMM_LEN-1)
- if err != nil && err != syserror.ENAMETOOLONG {
+ if err != nil && !linuxerr.Equals(linuxerr.ENAMETOOLONG, err) {
return 0, nil, err
}
t.SetName(name)
@@ -155,12 +156,12 @@ func Prctl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
t.Kernel().EmitUnimplementedEvent(t)
fallthrough
default:
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
case linux.PR_SET_NO_NEW_PRIVS:
if args[1].Int() != 1 || args[2].Int() != 0 || args[3].Int() != 0 || args[4].Int() != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// PR_SET_NO_NEW_PRIVS is assumed to always be set.
// See kernel.Task.updateCredsForExecLocked.
@@ -168,7 +169,7 @@ func Prctl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
case linux.PR_GET_NO_NEW_PRIVS:
if args[1].Int() != 0 || args[2].Int() != 0 || args[3].Int() != 0 || args[4].Int() != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
return 1, nil, nil
@@ -184,7 +185,7 @@ func Prctl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
default:
tracer := t.PIDNamespace().TaskWithID(kernel.ThreadID(pid))
if tracer == nil {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
t.SetYAMAException(tracer)
return 0, nil, nil
@@ -193,7 +194,7 @@ func Prctl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
case linux.PR_SET_SECCOMP:
if args[1].Int() != linux.SECCOMP_MODE_FILTER {
// Unsupported mode.
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
return 0, nil, seccomp(t, linux.SECCOMP_SET_MODE_FILTER, 0, args[2].Pointer())
@@ -204,7 +205,7 @@ func Prctl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
case linux.PR_CAPBSET_READ:
cp := linux.Capability(args[1].Uint64())
if !cp.Ok() {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
var rv uintptr
if auth.CapabilitySetOf(cp)&t.Credentials().BoundingCaps != 0 {
@@ -215,7 +216,7 @@ func Prctl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
case linux.PR_CAPBSET_DROP:
cp := linux.Capability(args[1].Uint64())
if !cp.Ok() {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
return 0, nil, t.DropBoundingCapability(cp)
@@ -240,7 +241,7 @@ func Prctl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
t.Kernel().EmitUnimplementedEvent(t)
fallthrough
default:
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
return 0, nil, nil
diff --git a/pkg/sentry/syscalls/linux/sys_random.go b/pkg/sentry/syscalls/linux/sys_random.go
index ae545f80f..ec6c80de5 100644
--- a/pkg/sentry/syscalls/linux/sys_random.go
+++ b/pkg/sentry/syscalls/linux/sys_random.go
@@ -18,14 +18,14 @@ import (
"io"
"math"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
+ "gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/rand"
"gvisor.dev/gvisor/pkg/safemem"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/syserror"
"gvisor.dev/gvisor/pkg/usermem"
-
- "gvisor.dev/gvisor/pkg/hostarch"
)
const (
@@ -47,7 +47,7 @@ func GetRandom(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
// Flags are checked for validity but otherwise ignored. See above.
if flags & ^(_GRND_NONBLOCK|_GRND_RANDOM) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if length > math.MaxInt32 {
diff --git a/pkg/sentry/syscalls/linux/sys_read.go b/pkg/sentry/syscalls/linux/sys_read.go
index 13e5e3a51..4064467a9 100644
--- a/pkg/sentry/syscalls/linux/sys_read.go
+++ b/pkg/sentry/syscalls/linux/sys_read.go
@@ -18,6 +18,7 @@ import (
"time"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/kernel"
@@ -58,7 +59,7 @@ func Read(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallC
// Check that the size is legitimate.
si := int(size)
if si < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Get the destination of the read.
@@ -93,18 +94,18 @@ func Readahead(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
// Check that the size is valid.
if int(size) < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Check that the offset is legitimate and does not overflow.
if offset < 0 || offset+int64(size) < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Return EINVAL; if the underlying file type does not support readahead,
// then Linux will return EINVAL to indicate as much. In the future, we
// may extend this function to actually support readahead hints.
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Pread64 implements linux syscall pread64(2).
@@ -122,7 +123,7 @@ func Pread64(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
// Check that the offset is legitimate and does not overflow.
if offset < 0 || offset+int64(size) < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Is reading at an offset supported?
@@ -138,7 +139,7 @@ func Pread64(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
// Check that the size is legitimate.
si := int(size)
if si < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Get the destination of the read.
@@ -199,7 +200,7 @@ func Preadv(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
// Check that the offset is legitimate.
if offset < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Is reading at an offset supported?
@@ -248,7 +249,7 @@ func Preadv2(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
// Check that the offset is legitimate.
if offset < -1 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Is reading at an offset supported?
@@ -331,7 +332,7 @@ func readv(t *kernel.Task, f *fs.File, dst usermem.IOSequence) (int64, error) {
// Wait for a notification that we should retry.
if err = t.BlockWithDeadline(ch, haveDeadline, deadline); err != nil {
- if err == syserror.ETIMEDOUT {
+ if linuxerr.Equals(linuxerr.ETIMEDOUT, err) {
err = syserror.ErrWouldBlock
}
break
diff --git a/pkg/sentry/syscalls/linux/sys_rlimit.go b/pkg/sentry/syscalls/linux/sys_rlimit.go
index e64246d57..ca78c2ab2 100644
--- a/pkg/sentry/syscalls/linux/sys_rlimit.go
+++ b/pkg/sentry/syscalls/linux/sys_rlimit.go
@@ -16,6 +16,7 @@ package linux
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/marshal"
"gvisor.dev/gvisor/pkg/sentry/arch"
@@ -129,7 +130,7 @@ func Getrlimit(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
resource, ok := limits.FromLinuxResource[int(args[0].Int())]
if !ok {
// Return err; unknown limit.
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
addr := args[1].Pointer()
rlim, err := newRlimit(t)
@@ -150,7 +151,7 @@ func Setrlimit(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
resource, ok := limits.FromLinuxResource[int(args[0].Int())]
if !ok {
// Return err; unknown limit.
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
addr := args[1].Pointer()
rlim, err := newRlimit(t)
@@ -170,7 +171,7 @@ func Prlimit64(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
resource, ok := limits.FromLinuxResource[int(args[1].Int())]
if !ok {
// Return err; unknown limit.
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
newRlimAddr := args[2].Pointer()
oldRlimAddr := args[3].Pointer()
@@ -185,7 +186,7 @@ func Prlimit64(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
}
if tid < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
ot := t
if tid > 0 {
diff --git a/pkg/sentry/syscalls/linux/sys_rseq.go b/pkg/sentry/syscalls/linux/sys_rseq.go
index 90db10ea6..5fe196647 100644
--- a/pkg/sentry/syscalls/linux/sys_rseq.go
+++ b/pkg/sentry/syscalls/linux/sys_rseq.go
@@ -16,6 +16,7 @@ package linux
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/syserror"
@@ -43,6 +44,6 @@ func RSeq(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallC
return 0, nil, t.ClearRSeq(addr, length, signature)
default:
// Unknown flag.
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
}
diff --git a/pkg/sentry/syscalls/linux/sys_rusage.go b/pkg/sentry/syscalls/linux/sys_rusage.go
index ac5c98a54..a689abcc9 100644
--- a/pkg/sentry/syscalls/linux/sys_rusage.go
+++ b/pkg/sentry/syscalls/linux/sys_rusage.go
@@ -16,11 +16,11 @@ package linux
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
ktime "gvisor.dev/gvisor/pkg/sentry/kernel/time"
"gvisor.dev/gvisor/pkg/sentry/usage"
- "gvisor.dev/gvisor/pkg/syserror"
)
func getrusage(t *kernel.Task, which int32) linux.Rusage {
@@ -76,7 +76,7 @@ func Getrusage(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
addr := args[1].Pointer()
if which != linux.RUSAGE_SELF && which != linux.RUSAGE_CHILDREN && which != linux.RUSAGE_THREAD {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
ru := getrusage(t, which)
diff --git a/pkg/sentry/syscalls/linux/sys_sched.go b/pkg/sentry/syscalls/linux/sys_sched.go
index bfcf44b6f..b5e7b70b5 100644
--- a/pkg/sentry/syscalls/linux/sys_sched.go
+++ b/pkg/sentry/syscalls/linux/sys_sched.go
@@ -16,6 +16,7 @@ package linux
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/syserror"
@@ -38,10 +39,10 @@ func SchedGetparam(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel
pid := args[0].Int()
param := args[1].Pointer()
if param == 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if pid < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if pid != 0 && t.PIDNamespace().TaskWithID(kernel.ThreadID(pid)) == nil {
return 0, nil, syserror.ESRCH
@@ -58,7 +59,7 @@ func SchedGetparam(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel
func SchedGetscheduler(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) {
pid := args[0].Int()
if pid < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if pid != 0 && t.PIDNamespace().TaskWithID(kernel.ThreadID(pid)) == nil {
return 0, nil, syserror.ESRCH
@@ -72,20 +73,20 @@ func SchedSetscheduler(t *kernel.Task, args arch.SyscallArguments) (uintptr, *ke
policy := args[1].Int()
param := args[2].Pointer()
if pid < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if policy != onlyScheduler {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if pid != 0 && t.PIDNamespace().TaskWithID(kernel.ThreadID(pid)) == nil {
return 0, nil, syserror.ESRCH
}
var r SchedParam
if _, err := r.CopyIn(t, param); err != nil {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if r.schedPriority != onlyPriority {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
return 0, nil, nil
}
diff --git a/pkg/sentry/syscalls/linux/sys_seccomp.go b/pkg/sentry/syscalls/linux/sys_seccomp.go
index e16d6ff3f..b0dc84b8d 100644
--- a/pkg/sentry/syscalls/linux/sys_seccomp.go
+++ b/pkg/sentry/syscalls/linux/sys_seccomp.go
@@ -17,10 +17,10 @@ package linux
import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/bpf"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
- "gvisor.dev/gvisor/pkg/syserror"
)
// userSockFprog is equivalent to Linux's struct sock_fprog on amd64.
@@ -44,7 +44,7 @@ func seccomp(t *kernel.Task, mode, flags uint64, addr hostarch.Addr) error {
// We only support SECCOMP_SET_MODE_FILTER at the moment.
if mode != linux.SECCOMP_SET_MODE_FILTER {
// Unsupported mode.
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
tsync := flags&linux.SECCOMP_FILTER_FLAG_TSYNC != 0
@@ -52,7 +52,7 @@ func seccomp(t *kernel.Task, mode, flags uint64, addr hostarch.Addr) error {
// The only flag we support now is SECCOMP_FILTER_FLAG_TSYNC.
if flags&^linux.SECCOMP_FILTER_FLAG_TSYNC != 0 {
// Unsupported flag.
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
var fprog userSockFprog
@@ -66,7 +66,7 @@ func seccomp(t *kernel.Task, mode, flags uint64, addr hostarch.Addr) error {
compiledFilter, err := bpf.Compile(filter)
if err != nil {
t.Debugf("Invalid seccomp-bpf filter: %v", err)
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
return t.AppendSyscallFilter(compiledFilter, tsync)
diff --git a/pkg/sentry/syscalls/linux/sys_sem.go b/pkg/sentry/syscalls/linux/sys_sem.go
index c84260080..d12a4303b 100644
--- a/pkg/sentry/syscalls/linux/sys_sem.go
+++ b/pkg/sentry/syscalls/linux/sys_sem.go
@@ -19,6 +19,7 @@ import (
"time"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/marshal/primitive"
"gvisor.dev/gvisor/pkg/sentry/arch"
@@ -61,10 +62,10 @@ func Semtimedop(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sy
nsops := args[2].SizeT()
timespecAddr := args[3].Pointer()
if nsops <= 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if nsops > opsMax {
- return 0, nil, syserror.E2BIG
+ return 0, nil, linuxerr.E2BIG
}
ops := make([]linux.Sembuf, nsops)
@@ -77,11 +78,11 @@ func Semtimedop(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sy
return 0, nil, err
}
if timeout.Sec < 0 || timeout.Nsec < 0 || timeout.Nsec >= 1e9 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if err := semTimedOp(t, id, ops, true, timeout.ToDuration()); err != nil {
- if err == syserror.ETIMEDOUT {
+ if linuxerr.Equals(linuxerr.ETIMEDOUT, err) {
return 0, nil, syserror.EAGAIN
}
return 0, nil, err
@@ -96,10 +97,10 @@ func Semop(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
nsops := args[2].SizeT()
if nsops <= 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if nsops > opsMax {
- return 0, nil, syserror.E2BIG
+ return 0, nil, linuxerr.E2BIG
}
ops := make([]linux.Sembuf, nsops)
@@ -113,7 +114,7 @@ func semTimedOp(t *kernel.Task, id int32, ops []linux.Sembuf, haveTimeout bool,
set := t.IPCNamespace().SemaphoreRegistry().FindByID(id)
if set == nil {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
creds := auth.CredentialsFromContext(t)
pid := t.Kernel().GlobalInit().PIDNamespace().IDOfThreadGroup(t.ThreadGroup())
@@ -232,7 +233,7 @@ func Semctl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
return uintptr(semid), nil, err
default:
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
}
@@ -246,17 +247,17 @@ func ipcSet(t *kernel.Task, id int32, uid auth.UID, gid auth.GID, perms fs.FileP
r := t.IPCNamespace().SemaphoreRegistry()
set := r.FindByID(id)
if set == nil {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
creds := auth.CredentialsFromContext(t)
kuid := creds.UserNamespace.MapToKUID(uid)
if !kuid.Ok() {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
kgid := creds.UserNamespace.MapToKGID(gid)
if !kgid.Ok() {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
owner := fs.FileOwner{UID: kuid, GID: kgid}
return set.Change(t, creds, owner, perms)
@@ -266,7 +267,7 @@ func ipcStat(t *kernel.Task, id int32) (*linux.SemidDS, error) {
r := t.IPCNamespace().SemaphoreRegistry()
set := r.FindByID(id)
if set == nil {
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
creds := auth.CredentialsFromContext(t)
return set.GetStat(creds)
@@ -276,7 +277,7 @@ func semStat(t *kernel.Task, index int32) (int32, *linux.SemidDS, error) {
r := t.IPCNamespace().SemaphoreRegistry()
set := r.FindByIndex(index)
if set == nil {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
creds := auth.CredentialsFromContext(t)
ds, err := set.GetStat(creds)
@@ -289,7 +290,7 @@ func semStat(t *kernel.Task, index int32) (int32, *linux.SemidDS, error) {
func semStatAny(t *kernel.Task, index int32) (int32, *linux.SemidDS, error) {
set := t.IPCNamespace().SemaphoreRegistry().FindByIndex(index)
if set == nil {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
creds := auth.CredentialsFromContext(t)
ds, err := set.GetStatAny(creds)
@@ -303,7 +304,7 @@ func setVal(t *kernel.Task, id int32, num int32, val int16) error {
r := t.IPCNamespace().SemaphoreRegistry()
set := r.FindByID(id)
if set == nil {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
creds := auth.CredentialsFromContext(t)
pid := t.Kernel().GlobalInit().PIDNamespace().IDOfThreadGroup(t.ThreadGroup())
@@ -314,7 +315,7 @@ func setValAll(t *kernel.Task, id int32, array hostarch.Addr) error {
r := t.IPCNamespace().SemaphoreRegistry()
set := r.FindByID(id)
if set == nil {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
vals := make([]uint16, set.Size())
if _, err := primitive.CopyUint16SliceIn(t, array, vals); err != nil {
@@ -329,7 +330,7 @@ func getVal(t *kernel.Task, id int32, num int32) (int16, error) {
r := t.IPCNamespace().SemaphoreRegistry()
set := r.FindByID(id)
if set == nil {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
creds := auth.CredentialsFromContext(t)
return set.GetVal(num, creds)
@@ -339,7 +340,7 @@ func getValAll(t *kernel.Task, id int32, array hostarch.Addr) error {
r := t.IPCNamespace().SemaphoreRegistry()
set := r.FindByID(id)
if set == nil {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
creds := auth.CredentialsFromContext(t)
vals, err := set.GetValAll(creds)
@@ -354,7 +355,7 @@ func getPID(t *kernel.Task, id int32, num int32) (int32, error) {
r := t.IPCNamespace().SemaphoreRegistry()
set := r.FindByID(id)
if set == nil {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
creds := auth.CredentialsFromContext(t)
gpid, err := set.GetPID(num, creds)
@@ -373,7 +374,7 @@ func getZCnt(t *kernel.Task, id int32, num int32) (uint16, error) {
r := t.IPCNamespace().SemaphoreRegistry()
set := r.FindByID(id)
if set == nil {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
creds := auth.CredentialsFromContext(t)
return set.CountZeroWaiters(num, creds)
@@ -383,7 +384,7 @@ func getNCnt(t *kernel.Task, id int32, num int32) (uint16, error) {
r := t.IPCNamespace().SemaphoreRegistry()
set := r.FindByID(id)
if set == nil {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
creds := auth.CredentialsFromContext(t)
return set.CountNegativeWaiters(num, creds)
diff --git a/pkg/sentry/syscalls/linux/sys_shm.go b/pkg/sentry/syscalls/linux/sys_shm.go
index 584064143..3e3a952ce 100644
--- a/pkg/sentry/syscalls/linux/sys_shm.go
+++ b/pkg/sentry/syscalls/linux/sys_shm.go
@@ -16,10 +16,10 @@ package linux
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/kernel/shm"
- "gvisor.dev/gvisor/pkg/syserror"
)
// Shmget implements shmget(2).
@@ -51,7 +51,7 @@ func findSegment(t *kernel.Task, id shm.ID) (*shm.Shm, error) {
segment := r.FindByID(id)
if segment == nil {
// No segment with provided id.
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
return segment, nil
}
@@ -64,7 +64,7 @@ func Shmat(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
segment, err := findSegment(t, id)
if err != nil {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
defer segment.DecRef(t)
@@ -106,7 +106,7 @@ func Shmctl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
case linux.IPC_STAT:
segment, err := findSegment(t, id)
if err != nil {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
defer segment.DecRef(t)
@@ -130,7 +130,7 @@ func Shmctl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
// Remaining commands refer to a specific segment.
segment, err := findSegment(t, id)
if err != nil {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
defer segment.DecRef(t)
@@ -155,6 +155,6 @@ func Shmctl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
return 0, nil, nil
default:
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
}
diff --git a/pkg/sentry/syscalls/linux/sys_signal.go b/pkg/sentry/syscalls/linux/sys_signal.go
index 53b12dc41..4d659e5cf 100644
--- a/pkg/sentry/syscalls/linux/sys_signal.go
+++ b/pkg/sentry/syscalls/linux/sys_signal.go
@@ -19,6 +19,7 @@ import (
"time"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fs"
@@ -84,13 +85,13 @@ func Kill(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallC
if !mayKill(t, target, sig) {
return 0, nil, syserror.EPERM
}
- info := &arch.SignalInfo{
+ info := &linux.SignalInfo{
Signo: int32(sig),
- Code: arch.SignalInfoUser,
+ Code: linux.SI_USER,
}
info.SetPID(int32(target.PIDNamespace().IDOfTask(t)))
info.SetUID(int32(t.Credentials().RealKUID.In(target.UserNamespace()).OrOverflow()))
- if err := target.SendGroupSignal(info); err != syserror.ESRCH {
+ if err := target.SendGroupSignal(info); !linuxerr.Equals(linuxerr.ESRCH, err) {
return 0, nil, err
}
}
@@ -123,14 +124,14 @@ func Kill(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallC
// depend on the iteration order. We at least implement the
// semantics documented by the man page: "On success (at least
// one signal was sent), zero is returned."
- info := &arch.SignalInfo{
+ info := &linux.SignalInfo{
Signo: int32(sig),
- Code: arch.SignalInfoUser,
+ Code: linux.SI_USER,
}
info.SetPID(int32(tg.PIDNamespace().IDOfTask(t)))
info.SetUID(int32(t.Credentials().RealKUID.In(tg.Leader().UserNamespace()).OrOverflow()))
err := tg.SendSignal(info)
- if err == syserror.ESRCH {
+ if linuxerr.Equals(linuxerr.ESRCH, err) {
// ESRCH is ignored because it means the task
// exited while we were iterating. This is a
// race which would not normally exist on
@@ -167,14 +168,14 @@ func Kill(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallC
continue
}
- info := &arch.SignalInfo{
+ info := &linux.SignalInfo{
Signo: int32(sig),
- Code: arch.SignalInfoUser,
+ Code: linux.SI_USER,
}
info.SetPID(int32(tg.PIDNamespace().IDOfTask(t)))
info.SetUID(int32(t.Credentials().RealKUID.In(tg.Leader().UserNamespace()).OrOverflow()))
// See note above regarding ESRCH race above.
- if err := tg.SendSignal(info); err != syserror.ESRCH {
+ if err := tg.SendSignal(info); !linuxerr.Equals(linuxerr.ESRCH, err) {
lastErr = err
}
}
@@ -184,10 +185,10 @@ func Kill(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallC
}
}
-func tkillSigInfo(sender, receiver *kernel.Task, sig linux.Signal) *arch.SignalInfo {
- info := &arch.SignalInfo{
+func tkillSigInfo(sender, receiver *kernel.Task, sig linux.Signal) *linux.SignalInfo {
+ info := &linux.SignalInfo{
Signo: int32(sig),
- Code: arch.SignalInfoTkill,
+ Code: linux.SI_TKILL,
}
info.SetPID(int32(receiver.PIDNamespace().IDOfThreadGroup(sender.ThreadGroup())))
info.SetUID(int32(sender.Credentials().RealKUID.In(receiver.UserNamespace()).OrOverflow()))
@@ -202,7 +203,7 @@ func Tkill(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
// N.B. Inconsistent with man page, linux actually rejects calls with
// tid <=0 by EINVAL. This isn't the same for all signal calls.
if tid <= 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
target := t.PIDNamespace().TaskWithID(tid)
@@ -225,7 +226,7 @@ func Tgkill(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
// N.B. Inconsistent with man page, linux actually rejects calls with
// tgid/tid <=0 by EINVAL. This isn't the same for all signal calls.
if tgid <= 0 || tid <= 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
targetTG := t.PIDNamespace().ThreadGroupWithID(tgid)
@@ -248,23 +249,23 @@ func RtSigaction(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.S
sigsetsize := args[3].SizeT()
if sigsetsize != linux.SignalSetSize {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
- var newactptr *arch.SignalAct
+ var newactptr *linux.SigAction
if newactarg != 0 {
- newact, err := t.CopyInSignalAct(newactarg)
- if err != nil {
+ var newact linux.SigAction
+ if _, err := newact.CopyIn(t, newactarg); err != nil {
return 0, nil, err
}
newactptr = &newact
}
- oldact, err := t.ThreadGroup().SetSignalAct(sig, newactptr)
+ oldact, err := t.ThreadGroup().SetSigAction(sig, newactptr)
if err != nil {
return 0, nil, err
}
if oldactarg != 0 {
- if err := t.CopyOutSignalAct(oldactarg, &oldact); err != nil {
+ if _, err := oldact.CopyOut(t, oldactarg); err != nil {
return 0, nil, err
}
}
@@ -291,7 +292,7 @@ func RtSigprocmask(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel
sigsetsize := args[3].SizeT()
if sigsetsize != linux.SignalSetSize {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
oldmask := t.SignalMask()
if setaddr != 0 {
@@ -308,7 +309,7 @@ func RtSigprocmask(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel
case linux.SIG_SETMASK:
t.SetSignalMask(mask)
default:
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
}
if oldaddr != 0 {
@@ -325,13 +326,12 @@ func Sigaltstack(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.S
alt := t.SignalStack()
if oldaddr != 0 {
- if err := t.CopyOutSignalStack(oldaddr, &alt); err != nil {
+ if _, err := alt.CopyOut(t, oldaddr); err != nil {
return 0, nil, err
}
}
if setaddr != 0 {
- alt, err := t.CopyInSignalStack(setaddr)
- if err != nil {
+ if _, err := alt.CopyIn(t, setaddr); err != nil {
return 0, nil, err
}
// The signal stack cannot be changed if the task is currently
@@ -378,7 +378,7 @@ func RtSigtimedwait(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kerne
return 0, nil, err
}
if !d.Valid() {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
timeout = time.Duration(d.ToNsecCapped())
} else {
@@ -410,7 +410,7 @@ func RtSigqueueinfo(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kerne
// We must ensure that the Signo is set (Linux overrides this in the
// same way), and that the code is in the allowed set. This same logic
// appears below in RtSigtgqueueinfo and should be kept in sync.
- var info arch.SignalInfo
+ var info linux.SignalInfo
if _, err := info.CopyIn(t, infoAddr); err != nil {
return 0, nil, err
}
@@ -426,7 +426,7 @@ func RtSigqueueinfo(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kerne
// If the sender is not the receiver, it can't use si_codes used by the
// kernel or SI_TKILL.
- if (info.Code >= 0 || info.Code == arch.SignalInfoTkill) && target != t {
+ if (info.Code >= 0 || info.Code == linux.SI_TKILL) && target != t {
return 0, nil, syserror.EPERM
}
@@ -434,7 +434,7 @@ func RtSigqueueinfo(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kerne
return 0, nil, syserror.EPERM
}
- if err := target.SendGroupSignal(&info); err != syserror.ESRCH {
+ if err := target.SendGroupSignal(&info); !linuxerr.Equals(linuxerr.ESRCH, err) {
return 0, nil, err
}
}
@@ -450,11 +450,11 @@ func RtTgsigqueueinfo(t *kernel.Task, args arch.SyscallArguments) (uintptr, *ker
// N.B. Inconsistent with man page, linux actually rejects calls with
// tgid/tid <=0 by EINVAL. This isn't the same for all signal calls.
if tgid <= 0 || tid <= 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Copy in the info. See RtSigqueueinfo above.
- var info arch.SignalInfo
+ var info linux.SignalInfo
if _, err := info.CopyIn(t, infoAddr); err != nil {
return 0, nil, err
}
@@ -469,7 +469,7 @@ func RtTgsigqueueinfo(t *kernel.Task, args arch.SyscallArguments) (uintptr, *ker
// If the sender is not the receiver, it can't use si_codes used by the
// kernel or SI_TKILL.
- if (info.Code >= 0 || info.Code == arch.SignalInfoTkill) && target != t {
+ if (info.Code >= 0 || info.Code == linux.SI_TKILL) && target != t {
return 0, nil, syserror.EPERM
}
@@ -525,7 +525,7 @@ func sharedSignalfd(t *kernel.Task, fd int32, sigset hostarch.Addr, sigsetsize u
// Always check for valid flags, even if not creating.
if flags&^(linux.SFD_NONBLOCK|linux.SFD_CLOEXEC) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Is this a change to an existing signalfd?
@@ -545,7 +545,7 @@ func sharedSignalfd(t *kernel.Task, fd int32, sigset hostarch.Addr, sigsetsize u
}
// Not a signalfd.
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Create a new file.
diff --git a/pkg/sentry/syscalls/linux/sys_socket.go b/pkg/sentry/syscalls/linux/sys_socket.go
index e07917613..6638ad60f 100644
--- a/pkg/sentry/syscalls/linux/sys_socket.go
+++ b/pkg/sentry/syscalls/linux/sys_socket.go
@@ -18,6 +18,7 @@ import (
"time"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/marshal"
"gvisor.dev/gvisor/pkg/marshal/primitive"
@@ -117,7 +118,7 @@ type multipleMessageHeader64 struct {
// from the untrusted address space range.
func CaptureAddress(t *kernel.Task, addr hostarch.Addr, addrlen uint32) ([]byte, error) {
if addrlen > maxAddrLen {
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
addrBuf := make([]byte, addrlen)
@@ -139,7 +140,7 @@ func writeAddress(t *kernel.Task, addr linux.SockAddr, addrLen uint32, addrPtr h
}
if int32(bufLen) < 0 {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
// Write the length unconditionally.
@@ -173,7 +174,7 @@ func Socket(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
// Check and initialize the flags.
if stype & ^(0xf|linux.SOCK_NONBLOCK|linux.SOCK_CLOEXEC) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Create the new socket.
@@ -205,7 +206,7 @@ func SocketPair(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sy
// Check and initialize the flags.
if stype & ^(0xf|linux.SOCK_NONBLOCK|linux.SOCK_CLOEXEC) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
fileFlags := fs.SettableFileFlags{
@@ -277,7 +278,7 @@ func Connect(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
func accept(t *kernel.Task, fd int32, addr hostarch.Addr, addrLen hostarch.Addr, flags int) (uintptr, error) {
// Check that no unsupported flags are passed in.
if flags & ^(linux.SOCK_NONBLOCK|linux.SOCK_CLOEXEC) != 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// Get socket from the file descriptor.
@@ -305,7 +306,7 @@ func accept(t *kernel.Task, fd int32, addr hostarch.Addr, addrLen hostarch.Addr,
if peerRequested {
// NOTE(magi): Linux does not give you an error if it can't
// write the data back out so neither do we.
- if err := writeAddress(t, peer, peerLen, addr, addrLen); err == syserror.EINVAL {
+ if err := writeAddress(t, peer, peerLen, addr, addrLen); linuxerr.Equals(linuxerr.EINVAL, err) {
return 0, err
}
}
@@ -421,7 +422,7 @@ func Shutdown(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
switch how {
case linux.SHUT_RD, linux.SHUT_WR, linux.SHUT_RDWR:
default:
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
return 0, nil, s.Shutdown(t, int(how)).ToError()
@@ -454,7 +455,7 @@ func GetSockOpt(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sy
return 0, nil, err
}
if optLen < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Call syscall implementation then copy both value and value len out.
@@ -530,10 +531,10 @@ func SetSockOpt(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sy
}
if optLen < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if optLen > maxOptLen {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
buf := t.CopyScratchBuffer(int(optLen))
if _, err := t.CopyInBytes(optValAddr, buf); err != nil {
@@ -612,7 +613,7 @@ func RecvMsg(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
if t.Arch().Width() != 8 {
// We only handle 64-bit for now.
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Get socket from the file descriptor.
@@ -630,7 +631,7 @@ func RecvMsg(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
// Reject flags that we don't handle yet.
if flags & ^(baseRecvFlags|linux.MSG_PEEK|linux.MSG_CMSG_CLOEXEC|linux.MSG_ERRQUEUE) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if file.Flags().NonBlocking {
@@ -660,7 +661,7 @@ func RecvMMsg(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
if t.Arch().Width() != 8 {
// We only handle 64-bit for now.
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if vlen > linux.UIO_MAXIOV {
@@ -669,7 +670,7 @@ func RecvMMsg(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
// Reject flags that we don't handle yet.
if flags & ^(baseRecvFlags|linux.MSG_CMSG_CLOEXEC|linux.MSG_ERRQUEUE) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Get socket from the file descriptor.
@@ -697,7 +698,7 @@ func RecvMMsg(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
return 0, nil, err
}
if !ts.Valid() {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
deadline = t.Kernel().MonotonicClock().Now().Add(ts.ToDuration())
haveDeadline = true
@@ -829,12 +830,12 @@ func recvSingleMsg(t *kernel.Task, s socket.Socket, msgPtr hostarch.Addr, flags
// recvfrom and recv syscall handlers.
func recvFrom(t *kernel.Task, fd int32, bufPtr hostarch.Addr, bufLen uint64, flags int32, namePtr hostarch.Addr, nameLenPtr hostarch.Addr) (uintptr, error) {
if int(bufLen) < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// Reject flags that we don't handle yet.
if flags & ^(baseRecvFlags|linux.MSG_PEEK|linux.MSG_CONFIRM) != 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// Get socket from the file descriptor.
@@ -907,7 +908,7 @@ func SendMsg(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
if t.Arch().Width() != 8 {
// We only handle 64-bit for now.
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Get socket from the file descriptor.
@@ -925,7 +926,7 @@ func SendMsg(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
// Reject flags that we don't handle yet.
if flags & ^(linux.MSG_DONTWAIT|linux.MSG_EOR|linux.MSG_MORE|linux.MSG_NOSIGNAL) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if file.Flags().NonBlocking {
@@ -945,7 +946,7 @@ func SendMMsg(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
if t.Arch().Width() != 8 {
// We only handle 64-bit for now.
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if vlen > linux.UIO_MAXIOV {
@@ -967,7 +968,7 @@ func SendMMsg(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
// Reject flags that we don't handle yet.
if flags & ^(linux.MSG_DONTWAIT|linux.MSG_EOR|linux.MSG_MORE|linux.MSG_NOSIGNAL) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if file.Flags().NonBlocking {
@@ -1073,7 +1074,7 @@ func sendSingleMsg(t *kernel.Task, s socket.Socket, file *fs.File, msgPtr hostar
func sendTo(t *kernel.Task, fd int32, bufPtr hostarch.Addr, bufLen uint64, flags int32, namePtr hostarch.Addr, nameLen uint32) (uintptr, error) {
bl := int(bufLen)
if bl < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// Get socket from the file descriptor.
diff --git a/pkg/sentry/syscalls/linux/sys_splice.go b/pkg/sentry/syscalls/linux/sys_splice.go
index 134051124..88bee61ef 100644
--- a/pkg/sentry/syscalls/linux/sys_splice.go
+++ b/pkg/sentry/syscalls/linux/sys_splice.go
@@ -16,6 +16,7 @@ package linux
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/marshal/primitive"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fs"
@@ -27,7 +28,7 @@ import (
// doSplice implements a blocking splice operation.
func doSplice(t *kernel.Task, outFile, inFile *fs.File, opts fs.SpliceOpts, nonBlocking bool) (int64, error) {
if opts.Length < 0 || opts.SrcStart < 0 || opts.DstStart < 0 || (opts.SrcStart+opts.Length < 0) {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
if opts.Length == 0 {
return 0, nil
@@ -125,13 +126,13 @@ func Sendfile(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
// Verify that the outfile Append flag is not set.
if outFile.Flags().Append {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Verify that we have a regular infile. This is a requirement; the
// same check appears in Linux (fs/splice.c:splice_direct_to_actor).
if !fs.IsRegular(inFile.Dirent.Inode.StableAttr) {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
var (
@@ -190,7 +191,7 @@ func Splice(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
// Check for invalid flags.
if flags&^(linux.SPLICE_F_MOVE|linux.SPLICE_F_NONBLOCK|linux.SPLICE_F_MORE|linux.SPLICE_F_GIFT) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Get files.
@@ -230,7 +231,7 @@ func Splice(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
}
if outOffset != 0 {
if !outFile.Flags().Pwrite {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
var offset int64
@@ -248,7 +249,7 @@ func Splice(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
}
if inOffset != 0 {
if !inFile.Flags().Pread {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
var offset int64
@@ -267,10 +268,10 @@ func Splice(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
// We may not refer to the same pipe; otherwise it's a continuous loop.
if inFileAttr.InodeID == outFileAttr.InodeID {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
default:
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Splice data.
@@ -298,7 +299,7 @@ func Tee(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallCo
// Check for invalid flags.
if flags&^(linux.SPLICE_F_MOVE|linux.SPLICE_F_NONBLOCK|linux.SPLICE_F_MORE|linux.SPLICE_F_GIFT) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Get files.
@@ -316,12 +317,12 @@ func Tee(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallCo
// All files must be pipes.
if !fs.IsPipe(inFile.Dirent.Inode.StableAttr) || !fs.IsPipe(outFile.Dirent.Inode.StableAttr) {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// We may not refer to the same pipe; see above.
if inFile.Dirent.Inode.StableAttr.InodeID == outFile.Dirent.Inode.StableAttr.InodeID {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// The operation is non-blocking if anything is non-blocking.
diff --git a/pkg/sentry/syscalls/linux/sys_stat.go b/pkg/sentry/syscalls/linux/sys_stat.go
index 2338ba44b..103b13c10 100644
--- a/pkg/sentry/syscalls/linux/sys_stat.go
+++ b/pkg/sentry/syscalls/linux/sys_stat.go
@@ -16,6 +16,7 @@ package linux
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fs"
@@ -139,13 +140,13 @@ func Statx(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
statxAddr := args[4].Pointer()
if mask&linux.STATX__RESERVED != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if flags&^(linux.AT_SYMLINK_NOFOLLOW|linux.AT_EMPTY_PATH|linux.AT_STATX_SYNC_TYPE) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if flags&linux.AT_STATX_SYNC_TYPE == linux.AT_STATX_SYNC_TYPE {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
path, dirPath, err := copyInPath(t, pathAddr, flags&linux.AT_EMPTY_PATH != 0)
diff --git a/pkg/sentry/syscalls/linux/sys_sync.go b/pkg/sentry/syscalls/linux/sys_sync.go
index 5ebd4461f..3f0e6c02e 100644
--- a/pkg/sentry/syscalls/linux/sys_sync.go
+++ b/pkg/sentry/syscalls/linux/sys_sync.go
@@ -16,6 +16,7 @@ package linux
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/kernel"
@@ -86,13 +87,13 @@ func SyncFileRange(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel
uflags := args[3].Uint()
if offset < 0 || offset+nbytes < offset {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if uflags&^(linux.SYNC_FILE_RANGE_WAIT_BEFORE|
linux.SYNC_FILE_RANGE_WRITE|
linux.SYNC_FILE_RANGE_WAIT_AFTER) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if nbytes == 0 {
diff --git a/pkg/sentry/syscalls/linux/sys_syslog.go b/pkg/sentry/syscalls/linux/sys_syslog.go
index 40c8bb061..ba372f9e3 100644
--- a/pkg/sentry/syscalls/linux/sys_syslog.go
+++ b/pkg/sentry/syscalls/linux/sys_syslog.go
@@ -15,6 +15,7 @@
package linux
import (
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/syserror"
@@ -40,7 +41,7 @@ func Syslog(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
switch command {
case _SYSLOG_ACTION_READ_ALL:
if size < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if size > logBufLen {
size = logBufLen
diff --git a/pkg/sentry/syscalls/linux/sys_thread.go b/pkg/sentry/syscalls/linux/sys_thread.go
index 3185ea527..d99dd5131 100644
--- a/pkg/sentry/syscalls/linux/sys_thread.go
+++ b/pkg/sentry/syscalls/linux/sys_thread.go
@@ -19,6 +19,7 @@ import (
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/marshal/primitive"
"gvisor.dev/gvisor/pkg/sentry/arch"
@@ -112,7 +113,7 @@ func execveat(t *kernel.Task, dirFD int32, pathnameAddr, argvAddr, envvAddr host
}
if flags&^(linux.AT_EMPTY_PATH|linux.AT_SYMLINK_NOFOLLOW) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
atEmptyPath := flags&linux.AT_EMPTY_PATH != 0
if !atEmptyPath && len(pathname) == 0 {
@@ -260,7 +261,7 @@ func parseCommonWaitOptions(wopts *kernel.WaitOptions, options int) error {
wopts.NonCloneTasks = true
wopts.CloneTasks = true
default:
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if options&linux.WCONTINUED != 0 {
wopts.Events |= kernel.EventGroupContinue
@@ -277,7 +278,7 @@ func parseCommonWaitOptions(wopts *kernel.WaitOptions, options int) error {
// wait4 waits for the given child process to exit.
func wait4(t *kernel.Task, pid int, statusAddr hostarch.Addr, options int, rusageAddr hostarch.Addr) (uintptr, error) {
if options&^(linux.WNOHANG|linux.WUNTRACED|linux.WCONTINUED|linux.WNOTHREAD|linux.WALL|linux.WCLONE) != 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
wopts := kernel.WaitOptions{
Events: kernel.EventExit | kernel.EventTraceeStop,
@@ -358,10 +359,10 @@ func Waitid(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
rusageAddr := args[4].Pointer()
if options&^(linux.WNOHANG|linux.WEXITED|linux.WSTOPPED|linux.WCONTINUED|linux.WNOWAIT|linux.WNOTHREAD|linux.WALL|linux.WCLONE) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if options&(linux.WEXITED|linux.WSTOPPED|linux.WCONTINUED) == 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
wopts := kernel.WaitOptions{
Events: kernel.EventTraceeStop,
@@ -374,7 +375,7 @@ func Waitid(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
case linux.P_PGID:
wopts.SpecificPGID = kernel.ProcessGroupID(id)
default:
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if err := parseCommonWaitOptions(&wopts, options); err != nil {
@@ -398,7 +399,7 @@ func Waitid(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
// out the fields it would set for a successful waitid in this case
// as well.
if infop != 0 {
- var si arch.SignalInfo
+ var si linux.SignalInfo
_, err = si.CopyOut(t, infop)
}
}
@@ -413,7 +414,7 @@ func Waitid(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
if infop == 0 {
return 0, nil, nil
}
- si := arch.SignalInfo{
+ si := linux.SignalInfo{
Signo: int32(linux.SIGCHLD),
}
si.SetPID(int32(wr.TID))
@@ -423,24 +424,24 @@ func Waitid(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
s := unix.WaitStatus(wr.Status)
switch {
case s.Exited():
- si.Code = arch.CLD_EXITED
+ si.Code = linux.CLD_EXITED
si.SetStatus(int32(s.ExitStatus()))
case s.Signaled():
- si.Code = arch.CLD_KILLED
+ si.Code = linux.CLD_KILLED
si.SetStatus(int32(s.Signal()))
case s.CoreDump():
- si.Code = arch.CLD_DUMPED
+ si.Code = linux.CLD_DUMPED
si.SetStatus(int32(s.Signal()))
case s.Stopped():
if wr.Event == kernel.EventTraceeStop {
- si.Code = arch.CLD_TRAPPED
+ si.Code = linux.CLD_TRAPPED
si.SetStatus(int32(s.TrapCause()))
} else {
- si.Code = arch.CLD_STOPPED
+ si.Code = linux.CLD_STOPPED
si.SetStatus(int32(s.StopSignal()))
}
case s.Continued():
- si.Code = arch.CLD_CONTINUED
+ si.Code = linux.CLD_CONTINUED
si.SetStatus(int32(linux.SIGCONT))
default:
t.Warningf("waitid got incomprehensible wait status %d", s)
@@ -528,7 +529,7 @@ func SchedGetaffinity(t *kernel.Task, args arch.SyscallArguments) (uintptr, *ker
// in an array of "unsigned long" so the buffer needs to
// be a multiple of the word size.
if size&(t.Arch().Width()-1) > 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
var task *kernel.Task
@@ -545,7 +546,7 @@ func SchedGetaffinity(t *kernel.Task, args arch.SyscallArguments) (uintptr, *ker
// The buffer needs to be big enough to hold a cpumask with
// all possible cpus.
if size < mask.Size() {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
_, err := t.CopyOutBytes(maskAddr, mask)
@@ -594,7 +595,7 @@ func Setpgid(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
}
tg = ot.ThreadGroup()
if tg.Leader() != ot {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Setpgid only operates on child threadgroups.
@@ -609,7 +610,7 @@ func Setpgid(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
if pgid == 0 {
pgid = defaultPGID
} else if pgid < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// If the pgid is the same as the group, then create a new one. Otherwise,
@@ -712,7 +713,7 @@ func Getpriority(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.S
// PRIO_USER and PRIO_PGRP have no further implementation yet.
return 0, nil, nil
default:
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
}
@@ -754,7 +755,7 @@ func Setpriority(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.S
// PRIO_USER and PRIO_PGRP have no further implementation yet.
return 0, nil, nil
default:
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
return 0, nil, nil
diff --git a/pkg/sentry/syscalls/linux/sys_time.go b/pkg/sentry/syscalls/linux/sys_time.go
index 83b777bbd..d75bb9c4f 100644
--- a/pkg/sentry/syscalls/linux/sys_time.go
+++ b/pkg/sentry/syscalls/linux/sys_time.go
@@ -19,6 +19,7 @@ import (
"time"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/marshal/primitive"
"gvisor.dev/gvisor/pkg/sentry/arch"
@@ -75,7 +76,7 @@ func ClockGetres(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.S
}
if _, err := getClock(t, clockID); err != nil {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if addr == 0 {
@@ -94,12 +95,12 @@ type cpuClocker interface {
func getClock(t *kernel.Task, clockID int32) (ktime.Clock, error) {
if clockID < 0 {
if !isValidCPUClock(clockID) {
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
targetTask := targetTask(t, clockID)
if targetTask == nil {
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
var target cpuClocker
@@ -116,7 +117,7 @@ func getClock(t *kernel.Task, clockID int32) (ktime.Clock, error) {
// CPUCLOCK_SCHED is approximated by CPUCLOCK_PROF.
return target.CPUClock(), nil
default:
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
}
@@ -138,7 +139,7 @@ func getClock(t *kernel.Task, clockID int32) (ktime.Clock, error) {
case linux.CLOCK_THREAD_CPUTIME_ID:
return t.CPUClock(), nil
default:
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
}
@@ -180,21 +181,21 @@ func Time(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallC
//
// +stateify savable
type clockNanosleepRestartBlock struct {
- c ktime.Clock
- duration time.Duration
- rem hostarch.Addr
+ c ktime.Clock
+ end ktime.Time
+ rem hostarch.Addr
}
// Restart implements kernel.SyscallRestartBlock.Restart.
func (n *clockNanosleepRestartBlock) Restart(t *kernel.Task) (uintptr, error) {
- return 0, clockNanosleepFor(t, n.c, n.duration, n.rem)
+ return 0, clockNanosleepUntil(t, n.c, n.end, n.rem, true)
}
// clockNanosleepUntil blocks until a specified time.
//
// If blocking is interrupted, the syscall is restarted with the original
// arguments.
-func clockNanosleepUntil(t *kernel.Task, c ktime.Clock, ts linux.Timespec) error {
+func clockNanosleepUntil(t *kernel.Task, c ktime.Clock, end ktime.Time, rem hostarch.Addr, needRestartBlock bool) error {
notifier, tchan := ktime.NewChannelNotifier()
timer := ktime.NewTimer(c, notifier)
@@ -202,43 +203,22 @@ func clockNanosleepUntil(t *kernel.Task, c ktime.Clock, ts linux.Timespec) error
timer.Swap(ktime.Setting{
Period: 0,
Enabled: true,
- Next: ktime.FromTimespec(ts),
+ Next: end,
})
err := t.BlockWithTimer(nil, tchan)
timer.Destroy()
- // Did we just block until the timeout happened?
- if err == syserror.ETIMEDOUT {
- return nil
- }
-
- return syserror.ConvertIntr(err, syserror.ERESTARTNOHAND)
-}
-
-// clockNanosleepFor blocks for a specified duration.
-//
-// If blocking is interrupted, the syscall is restarted with the remaining
-// duration timeout.
-func clockNanosleepFor(t *kernel.Task, c ktime.Clock, dur time.Duration, rem hostarch.Addr) error {
- timer, start, tchan := ktime.After(c, dur)
-
- err := t.BlockWithTimer(nil, tchan)
-
- after := c.Now()
-
- timer.Destroy()
-
- switch err {
- case syserror.ETIMEDOUT:
+ switch {
+ case linuxerr.Equals(linuxerr.ETIMEDOUT, err):
// Slept for entire timeout.
return nil
- case syserror.ErrInterrupted:
+ case err == syserror.ErrInterrupted:
// Interrupted.
- remaining := dur - after.Sub(start)
- if remaining < 0 {
- remaining = time.Duration(0)
+ remaining := end.Sub(c.Now())
+ if remaining <= 0 {
+ return nil
}
// Copy out remaining time.
@@ -248,14 +228,16 @@ func clockNanosleepFor(t *kernel.Task, c ktime.Clock, dur time.Duration, rem hos
return err
}
}
-
- // Arrange for a restart with the remaining duration.
- t.SetSyscallRestartBlock(&clockNanosleepRestartBlock{
- c: c,
- duration: remaining,
- rem: rem,
- })
- return syserror.ERESTART_RESTARTBLOCK
+ if needRestartBlock {
+ // Arrange for a restart with the remaining duration.
+ t.SetSyscallRestartBlock(&clockNanosleepRestartBlock{
+ c: c,
+ end: end,
+ rem: rem,
+ })
+ return syserror.ERESTART_RESTARTBLOCK
+ }
+ return syserror.ERESTARTNOHAND
default:
panic(fmt.Sprintf("Impossible BlockWithTimer error %v", err))
}
@@ -272,13 +254,14 @@ func Nanosleep(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
}
if !ts.Valid() {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Just like linux, we cap the timeout with the max number that int64 can
// represent which is roughly 292 years.
dur := time.Duration(ts.ToNsecCapped()) * time.Nanosecond
- return 0, nil, clockNanosleepFor(t, t.Kernel().MonotonicClock(), dur, rem)
+ c := t.Kernel().MonotonicClock()
+ return 0, nil, clockNanosleepUntil(t, c, c.Now().Add(dur), rem, true)
}
// ClockNanosleep implements linux syscall clock_nanosleep(2).
@@ -294,7 +277,7 @@ func ClockNanosleep(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kerne
}
if !req.Valid() {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Only allow clock constants also allowed by Linux.
@@ -302,7 +285,7 @@ func ClockNanosleep(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kerne
if clockID != linux.CLOCK_REALTIME &&
clockID != linux.CLOCK_MONOTONIC &&
clockID != linux.CLOCK_PROCESS_CPUTIME_ID {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
}
@@ -312,11 +295,11 @@ func ClockNanosleep(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kerne
}
if flags&linux.TIMER_ABSTIME != 0 {
- return 0, nil, clockNanosleepUntil(t, c, req)
+ return 0, nil, clockNanosleepUntil(t, c, ktime.FromTimespec(req), 0, false)
}
dur := time.Duration(req.ToNsecCapped()) * time.Nanosecond
- return 0, nil, clockNanosleepFor(t, c, dur, rem)
+ return 0, nil, clockNanosleepUntil(t, c, c.Now().Add(dur), rem, true)
}
// Gettimeofday implements linux syscall gettimeofday(2).
diff --git a/pkg/sentry/syscalls/linux/sys_timerfd.go b/pkg/sentry/syscalls/linux/sys_timerfd.go
index cadd9d348..a8e88b814 100644
--- a/pkg/sentry/syscalls/linux/sys_timerfd.go
+++ b/pkg/sentry/syscalls/linux/sys_timerfd.go
@@ -16,6 +16,7 @@ package linux
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/fs/timerfd"
@@ -30,7 +31,7 @@ func TimerfdCreate(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel
flags := args[1].Int()
if flags&^(linux.TFD_CLOEXEC|linux.TFD_NONBLOCK) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
var c ktime.Clock
@@ -40,7 +41,7 @@ func TimerfdCreate(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel
case linux.CLOCK_MONOTONIC, linux.CLOCK_BOOTTIME:
c = t.Kernel().MonotonicClock()
default:
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
f := timerfd.NewFile(t, c)
defer f.DecRef(t)
@@ -66,7 +67,7 @@ func TimerfdSettime(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kerne
oldValAddr := args[3].Pointer()
if flags&^(linux.TFD_TIMER_ABSTIME) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
f := t.GetFile(fd)
@@ -77,7 +78,7 @@ func TimerfdSettime(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kerne
tf, ok := f.FileOperations.(*timerfd.TimerOperations)
if !ok {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
var newVal linux.Itimerspec
@@ -111,7 +112,7 @@ func TimerfdGettime(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kerne
tf, ok := f.FileOperations.(*timerfd.TimerOperations)
if !ok {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
tm, s := tf.GetTime()
diff --git a/pkg/sentry/syscalls/linux/sys_tls_amd64.go b/pkg/sentry/syscalls/linux/sys_tls_amd64.go
index 6ddd30d5c..32272c267 100644
--- a/pkg/sentry/syscalls/linux/sys_tls_amd64.go
+++ b/pkg/sentry/syscalls/linux/sys_tls_amd64.go
@@ -18,6 +18,7 @@ package linux
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/marshal/primitive"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
@@ -48,7 +49,7 @@ func ArchPrctl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
t.Kernel().EmitUnimplementedEvent(t)
fallthrough
default:
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
return 0, nil, nil
diff --git a/pkg/sentry/syscalls/linux/sys_utsname.go b/pkg/sentry/syscalls/linux/sys_utsname.go
index 66c5974f5..7fffb189e 100644
--- a/pkg/sentry/syscalls/linux/sys_utsname.go
+++ b/pkg/sentry/syscalls/linux/sys_utsname.go
@@ -16,6 +16,7 @@ package linux
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/syserror"
@@ -60,7 +61,7 @@ func Setdomainname(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel
return 0, nil, syserror.EPERM
}
if size < 0 || size > linux.UTSLen {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
name, err := t.CopyInString(nameAddr, int(size))
@@ -82,7 +83,7 @@ func Sethostname(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.S
return 0, nil, syserror.EPERM
}
if size < 0 || size > linux.UTSLen {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
name := make([]byte, size)
diff --git a/pkg/sentry/syscalls/linux/sys_write.go b/pkg/sentry/syscalls/linux/sys_write.go
index 95bfe6606..998b5fde6 100644
--- a/pkg/sentry/syscalls/linux/sys_write.go
+++ b/pkg/sentry/syscalls/linux/sys_write.go
@@ -18,6 +18,7 @@ import (
"time"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/kernel"
@@ -58,7 +59,7 @@ func Write(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
// Check that the size is legitimate.
si := int(size)
if si < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Get the source of the write.
@@ -89,7 +90,7 @@ func Pwrite64(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
// Check that the offset is legitimate and does not overflow.
if offset < 0 || offset+int64(size) < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Is writing at an offset supported?
@@ -105,7 +106,7 @@ func Pwrite64(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
// Check that the size is legitimate.
si := int(size)
if si < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Get the source of the write.
@@ -166,7 +167,7 @@ func Pwritev(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
// Check that the offset is legitimate.
if offset < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Is writing at an offset supported?
@@ -219,7 +220,7 @@ func Pwritev2(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
// Check that the offset is legitimate.
if offset < -1 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Is writing at an offset supported?
@@ -301,7 +302,7 @@ func writev(t *kernel.Task, f *fs.File, src usermem.IOSequence) (int64, error) {
// Wait for a notification that we should retry.
if err = t.BlockWithDeadline(ch, haveDeadline, deadline); err != nil {
- if err == syserror.ETIMEDOUT {
+ if linuxerr.Equals(linuxerr.ETIMEDOUT, err) {
err = syserror.ErrWouldBlock
}
break
diff --git a/pkg/sentry/syscalls/linux/sys_xattr.go b/pkg/sentry/syscalls/linux/sys_xattr.go
index 28ad6a60e..da6651062 100644
--- a/pkg/sentry/syscalls/linux/sys_xattr.go
+++ b/pkg/sentry/syscalls/linux/sys_xattr.go
@@ -18,6 +18,7 @@ import (
"strings"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fs"
@@ -182,7 +183,7 @@ func setXattrFromPath(t *kernel.Task, args arch.SyscallArguments, resolveSymlink
// setXattr implements setxattr(2) from the given *fs.Dirent.
func setXattr(t *kernel.Task, d *fs.Dirent, nameAddr, valueAddr hostarch.Addr, size uint64, flags uint32) error {
if flags&^(linux.XATTR_CREATE|linux.XATTR_REPLACE) != 0 {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
name, err := copyInXattrName(t, nameAddr)
@@ -195,7 +196,7 @@ func setXattr(t *kernel.Task, d *fs.Dirent, nameAddr, valueAddr hostarch.Addr, s
}
if size > linux.XATTR_SIZE_MAX {
- return syserror.E2BIG
+ return linuxerr.E2BIG
}
buf := make([]byte, size)
if _, err := t.CopyInBytes(valueAddr, buf); err != nil {
@@ -217,7 +218,7 @@ func setXattr(t *kernel.Task, d *fs.Dirent, nameAddr, valueAddr hostarch.Addr, s
func copyInXattrName(t *kernel.Task, nameAddr hostarch.Addr) (string, error) {
name, err := t.CopyInString(nameAddr, linux.XATTR_NAME_MAX+1)
if err != nil {
- if err == syserror.ENAMETOOLONG {
+ if linuxerr.Equals(linuxerr.ENAMETOOLONG, err) {
return "", syserror.ERANGE
}
return "", err
@@ -333,7 +334,7 @@ func listXattr(t *kernel.Task, d *fs.Dirent, addr hostarch.Addr, size uint64) (i
listSize := xattrListSize(xattrs)
if listSize > linux.XATTR_SIZE_MAX {
- return 0, syserror.E2BIG
+ return 0, linuxerr.E2BIG
}
if uint64(listSize) > requestedSize {
return 0, syserror.ERANGE
diff --git a/pkg/sentry/syscalls/linux/timespec.go b/pkg/sentry/syscalls/linux/timespec.go
index 3edc922eb..b327e27d6 100644
--- a/pkg/sentry/syscalls/linux/timespec.go
+++ b/pkg/sentry/syscalls/linux/timespec.go
@@ -18,6 +18,7 @@ import (
"time"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/syserror"
@@ -103,7 +104,7 @@ func copyTimespecInToDuration(t *kernel.Task, timespecAddr hostarch.Addr) (time.
return 0, err
}
if !timespec.Valid() {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
timeout = time.Duration(timespec.ToNsecCapped())
}
diff --git a/pkg/sentry/syscalls/linux/vfs2/BUILD b/pkg/sentry/syscalls/linux/vfs2/BUILD
index 5ce0bc714..a73f096ff 100644
--- a/pkg/sentry/syscalls/linux/vfs2/BUILD
+++ b/pkg/sentry/syscalls/linux/vfs2/BUILD
@@ -41,6 +41,7 @@ go_library(
"//pkg/abi/linux",
"//pkg/bits",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/fspath",
"//pkg/gohacks",
"//pkg/hostarch",
diff --git a/pkg/sentry/syscalls/linux/vfs2/aio.go b/pkg/sentry/syscalls/linux/vfs2/aio.go
index fd1863ef3..d81df637f 100644
--- a/pkg/sentry/syscalls/linux/vfs2/aio.go
+++ b/pkg/sentry/syscalls/linux/vfs2/aio.go
@@ -17,6 +17,8 @@ package vfs2
import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
+ "gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/marshal/primitive"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/eventfd"
@@ -26,8 +28,6 @@ import (
"gvisor.dev/gvisor/pkg/sentry/vfs"
"gvisor.dev/gvisor/pkg/syserror"
"gvisor.dev/gvisor/pkg/usermem"
-
- "gvisor.dev/gvisor/pkg/hostarch"
)
// IoSubmit implements linux syscall io_submit(2).
@@ -37,7 +37,7 @@ func IoSubmit(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
addr := args[2].Pointer()
if nrEvents < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
for i := int32(0); i < nrEvents; i++ {
@@ -90,7 +90,7 @@ func IoSubmit(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
// submitCallback processes a single callback.
func submitCallback(t *kernel.Task, id uint64, cb *linux.IOCallback, cbAddr hostarch.Addr) error {
if cb.Reserved2 != 0 {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
fd := t.GetFileVFS2(cb.FD)
@@ -110,7 +110,7 @@ func submitCallback(t *kernel.Task, id uint64, cb *linux.IOCallback, cbAddr host
// Check that it is an eventfd.
if _, ok := eventFD.Impl().(*eventfd.EventFileDescription); !ok {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
}
@@ -123,14 +123,14 @@ func submitCallback(t *kernel.Task, id uint64, cb *linux.IOCallback, cbAddr host
switch cb.OpCode {
case linux.IOCB_CMD_PREAD, linux.IOCB_CMD_PREADV, linux.IOCB_CMD_PWRITE, linux.IOCB_CMD_PWRITEV:
if cb.Offset < 0 {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
}
// Prepare the request.
aioCtx, ok := t.MemoryManager().LookupAIOContext(t, id)
if !ok {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if err := aioCtx.Prepare(); err != nil {
return err
@@ -200,7 +200,7 @@ func memoryFor(t *kernel.Task, cb *linux.IOCallback) (usermem.IOSequence, error)
bytes := int(cb.Bytes)
if bytes < 0 {
// Linux also requires that this field fit in ssize_t.
- return usermem.IOSequence{}, syserror.EINVAL
+ return usermem.IOSequence{}, linuxerr.EINVAL
}
// Since this I/O will be asynchronous with respect to t's task goroutine,
@@ -222,6 +222,6 @@ func memoryFor(t *kernel.Task, cb *linux.IOCallback) (usermem.IOSequence, error)
default:
// Not a supported command.
- return usermem.IOSequence{}, syserror.EINVAL
+ return usermem.IOSequence{}, linuxerr.EINVAL
}
}
diff --git a/pkg/sentry/syscalls/linux/vfs2/epoll.go b/pkg/sentry/syscalls/linux/vfs2/epoll.go
index 047d955b6..d3bb3a3e1 100644
--- a/pkg/sentry/syscalls/linux/vfs2/epoll.go
+++ b/pkg/sentry/syscalls/linux/vfs2/epoll.go
@@ -19,6 +19,7 @@ import (
"time"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
@@ -34,7 +35,7 @@ var sizeofEpollEvent = (*linux.EpollEvent)(nil).SizeBytes()
func EpollCreate1(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) {
flags := args[0].Int()
if flags&^linux.EPOLL_CLOEXEC != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
file, err := t.Kernel().VFS().NewEpollInstanceFD(t)
@@ -59,7 +60,7 @@ func EpollCreate(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.S
// "Since Linux 2.6.8, the size argument is ignored, but must be greater
// than zero" - epoll_create(2)
if size <= 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
file, err := t.Kernel().VFS().NewEpollInstanceFD(t)
@@ -89,7 +90,7 @@ func EpollCtl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
defer epfile.DecRef(t)
ep, ok := epfile.Impl().(*vfs.EpollInstance)
if !ok {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
file := t.GetFileVFS2(fd)
if file == nil {
@@ -97,7 +98,7 @@ func EpollCtl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
}
defer file.DecRef(t)
if epfile == file {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
var event linux.EpollEvent
@@ -115,14 +116,14 @@ func EpollCtl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
}
return 0, nil, ep.ModifyInterest(file, fd, event)
default:
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
}
func waitEpoll(t *kernel.Task, epfd int32, eventsAddr hostarch.Addr, maxEvents int, timeoutInNanos int64) (uintptr, *kernel.SyscallControl, error) {
var _EP_MAX_EVENTS = math.MaxInt32 / sizeofEpollEvent // Linux: fs/eventpoll.c:EP_MAX_EVENTS
if maxEvents <= 0 || maxEvents > _EP_MAX_EVENTS {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
epfile := t.GetFileVFS2(epfd)
@@ -132,7 +133,7 @@ func waitEpoll(t *kernel.Task, epfd int32, eventsAddr hostarch.Addr, maxEvents i
defer epfile.DecRef(t)
ep, ok := epfile.Impl().(*vfs.EpollInstance)
if !ok {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Allocate space for a few events on the stack for the common case in
@@ -174,7 +175,7 @@ func waitEpoll(t *kernel.Task, epfd int32, eventsAddr hostarch.Addr, maxEvents i
haveDeadline = true
}
if err := t.BlockWithDeadline(ch, haveDeadline, deadline); err != nil {
- if err == syserror.ETIMEDOUT {
+ if linuxerr.Equals(linuxerr.ETIMEDOUT, err) {
err = nil
}
return 0, nil, err
diff --git a/pkg/sentry/syscalls/linux/vfs2/eventfd.go b/pkg/sentry/syscalls/linux/vfs2/eventfd.go
index 807f909da..0dcf1fbff 100644
--- a/pkg/sentry/syscalls/linux/vfs2/eventfd.go
+++ b/pkg/sentry/syscalls/linux/vfs2/eventfd.go
@@ -16,10 +16,10 @@ package vfs2
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/eventfd"
"gvisor.dev/gvisor/pkg/sentry/kernel"
- "gvisor.dev/gvisor/pkg/syserror"
)
// Eventfd2 implements linux syscall eventfd2(2).
@@ -29,7 +29,7 @@ func Eventfd2(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
allOps := uint(linux.EFD_SEMAPHORE | linux.EFD_NONBLOCK | linux.EFD_CLOEXEC)
if flags & ^allOps != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
vfsObj := t.Kernel().VFS()
diff --git a/pkg/sentry/syscalls/linux/vfs2/execve.go b/pkg/sentry/syscalls/linux/vfs2/execve.go
index 3315398a4..7b1e1da78 100644
--- a/pkg/sentry/syscalls/linux/vfs2/execve.go
+++ b/pkg/sentry/syscalls/linux/vfs2/execve.go
@@ -16,7 +16,9 @@ package vfs2
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fspath"
+ "gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fsbridge"
"gvisor.dev/gvisor/pkg/sentry/kernel"
@@ -24,8 +26,6 @@ import (
slinux "gvisor.dev/gvisor/pkg/sentry/syscalls/linux"
"gvisor.dev/gvisor/pkg/sentry/vfs"
"gvisor.dev/gvisor/pkg/syserror"
-
- "gvisor.dev/gvisor/pkg/hostarch"
)
// Execve implements linux syscall execve(2).
@@ -48,7 +48,7 @@ func Execveat(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
func execveat(t *kernel.Task, dirfd int32, pathnameAddr, argvAddr, envvAddr hostarch.Addr, flags int32) (uintptr, *kernel.SyscallControl, error) {
if flags&^(linux.AT_EMPTY_PATH|linux.AT_SYMLINK_NOFOLLOW) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
pathname, err := t.CopyInString(pathnameAddr, linux.PATH_MAX)
diff --git a/pkg/sentry/syscalls/linux/vfs2/fd.go b/pkg/sentry/syscalls/linux/vfs2/fd.go
index 1a31898e8..ea34ff471 100644
--- a/pkg/sentry/syscalls/linux/vfs2/fd.go
+++ b/pkg/sentry/syscalls/linux/vfs2/fd.go
@@ -16,6 +16,7 @@ package vfs2
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fs/lock"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/tmpfs"
@@ -86,7 +87,7 @@ func Dup3(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallC
flags := args[2].Uint()
if oldfd == newfd {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
return dup3(t, oldfd, newfd, flags)
@@ -94,7 +95,7 @@ func Dup3(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallC
func dup3(t *kernel.Task, oldfd, newfd int32, flags uint32) (uintptr, *kernel.SyscallControl, error) {
if flags&^linux.O_CLOEXEC != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
file := t.GetFileVFS2(oldfd)
@@ -169,7 +170,7 @@ func Fcntl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
if who < 0 {
// Check for overflow before flipping the sign.
if who-1 > who {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
ownerType = linux.F_OWNER_PGRP
who = -who
@@ -232,7 +233,7 @@ func Fcntl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
return 0, nil, a.SetSignal(linux.Signal(args[2].Int()))
default:
// Everything else is not yet supported.
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
}
@@ -269,7 +270,7 @@ func setAsyncOwner(t *kernel.Task, fd int, file *vfs.FileDescription, ownerType,
case linux.F_OWNER_TID, linux.F_OWNER_PID, linux.F_OWNER_PGRP:
// Acceptable type.
default:
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
a := file.SetAsyncHandler(fasync.NewVFS2(fd)).(*fasync.FileAsync)
@@ -301,7 +302,7 @@ func setAsyncOwner(t *kernel.Task, fd int, file *vfs.FileDescription, ownerType,
a.SetOwnerProcessGroup(t, pg)
return nil
default:
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
}
@@ -319,7 +320,7 @@ func posixTestLock(t *kernel.Task, args arch.SyscallArguments, file *vfs.FileDes
case linux.F_WRLCK:
typ = lock.WriteLock
default:
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
r, err := file.ComputeLockRange(t, uint64(flock.Start), uint64(flock.Len), flock.Whence)
if err != nil {
@@ -382,7 +383,7 @@ func posixLock(t *kernel.Task, args arch.SyscallArguments, file *vfs.FileDescrip
return file.UnlockPOSIX(t, t.FDTable(), r)
default:
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
}
@@ -395,7 +396,7 @@ func Fadvise64(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
// Note: offset is allowed to be negative.
if length < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
file := t.GetFileVFS2(fd)
@@ -421,7 +422,7 @@ func Fadvise64(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
case linux.POSIX_FADV_DONTNEED:
case linux.POSIX_FADV_NOREUSE:
default:
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Sure, whatever.
diff --git a/pkg/sentry/syscalls/linux/vfs2/filesystem.go b/pkg/sentry/syscalls/linux/vfs2/filesystem.go
index 36aa1d3ae..534355237 100644
--- a/pkg/sentry/syscalls/linux/vfs2/filesystem.go
+++ b/pkg/sentry/syscalls/linux/vfs2/filesystem.go
@@ -16,12 +16,12 @@ package vfs2
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
+ "gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/vfs"
"gvisor.dev/gvisor/pkg/syserror"
-
- "gvisor.dev/gvisor/pkg/hostarch"
)
// Link implements Linux syscall link(2).
@@ -43,7 +43,7 @@ func Linkat(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
func linkat(t *kernel.Task, olddirfd int32, oldpathAddr hostarch.Addr, newdirfd int32, newpathAddr hostarch.Addr, flags int32) error {
if flags&^(linux.AT_EMPTY_PATH|linux.AT_SYMLINK_FOLLOW) != 0 {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if flags&linux.AT_EMPTY_PATH != 0 && !t.HasCapability(linux.CAP_DAC_READ_SEARCH) {
return syserror.ENOENT
@@ -290,7 +290,7 @@ func Unlinkat(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
flags := args[2].Int()
if flags&^linux.AT_REMOVEDIR != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if flags&linux.AT_REMOVEDIR != 0 {
diff --git a/pkg/sentry/syscalls/linux/vfs2/getdents.go b/pkg/sentry/syscalls/linux/vfs2/getdents.go
index b41a3056a..8ace31af3 100644
--- a/pkg/sentry/syscalls/linux/vfs2/getdents.go
+++ b/pkg/sentry/syscalls/linux/vfs2/getdents.go
@@ -17,13 +17,13 @@ package vfs2
import (
"fmt"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
+ "gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/vfs"
"gvisor.dev/gvisor/pkg/sync"
"gvisor.dev/gvisor/pkg/syserror"
-
- "gvisor.dev/gvisor/pkg/hostarch"
)
// Getdents implements Linux syscall getdents(2).
@@ -100,7 +100,7 @@ func (cb *getdentsCallback) Handle(dirent vfs.Dirent) error {
size := 8 + 8 + 2 + 1 + 1 + len(dirent.Name)
size = (size + 7) &^ 7 // round up to multiple of 8
if size > cb.remaining {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
buf = cb.t.CopyScratchBuffer(size)
hostarch.ByteOrder.PutUint64(buf[0:8], dirent.Ino)
@@ -134,7 +134,7 @@ func (cb *getdentsCallback) Handle(dirent vfs.Dirent) error {
size := 8 + 8 + 2 + 1 + 1 + len(dirent.Name)
size = (size + 7) &^ 7 // round up to multiple of sizeof(long)
if size > cb.remaining {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
buf = cb.t.CopyScratchBuffer(size)
hostarch.ByteOrder.PutUint64(buf[0:8], dirent.Ino)
diff --git a/pkg/sentry/syscalls/linux/vfs2/inotify.go b/pkg/sentry/syscalls/linux/vfs2/inotify.go
index 11753d8e5..7a2e9e75d 100644
--- a/pkg/sentry/syscalls/linux/vfs2/inotify.go
+++ b/pkg/sentry/syscalls/linux/vfs2/inotify.go
@@ -16,6 +16,7 @@ package vfs2
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/vfs"
@@ -28,7 +29,7 @@ const allFlags = linux.IN_NONBLOCK | linux.IN_CLOEXEC
func InotifyInit1(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) {
flags := args[0].Int()
if flags&^allFlags != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
ino, err := vfs.NewInotifyFD(t, t.Kernel().VFS(), uint32(flags))
@@ -67,7 +68,7 @@ func fdToInotify(t *kernel.Task, fd int32) (*vfs.Inotify, *vfs.FileDescription,
if !ok {
// Not an inotify fd.
f.DecRef(t)
- return nil, nil, syserror.EINVAL
+ return nil, nil, linuxerr.EINVAL
}
return ino, f, nil
@@ -82,7 +83,7 @@ func InotifyAddWatch(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kern
// "EINVAL: The given event mask contains no valid events."
// -- inotify_add_watch(2)
if mask&linux.ALL_INOTIFY_BITS == 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// "IN_DONT_FOLLOW: Don't dereference pathname if it is a symbolic link."
diff --git a/pkg/sentry/syscalls/linux/vfs2/ioctl.go b/pkg/sentry/syscalls/linux/vfs2/ioctl.go
index c7c3fed57..9852e3fe4 100644
--- a/pkg/sentry/syscalls/linux/vfs2/ioctl.go
+++ b/pkg/sentry/syscalls/linux/vfs2/ioctl.go
@@ -16,6 +16,7 @@ package vfs2
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/marshal/primitive"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
@@ -99,7 +100,7 @@ func Ioctl(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
if who < 0 {
// Check for overflow before flipping the sign.
if who-1 > who {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
ownerType = linux.F_OWNER_PGRP
who = -who
diff --git a/pkg/sentry/syscalls/linux/vfs2/lock.go b/pkg/sentry/syscalls/linux/vfs2/lock.go
index d1452a04d..80cb3ba09 100644
--- a/pkg/sentry/syscalls/linux/vfs2/lock.go
+++ b/pkg/sentry/syscalls/linux/vfs2/lock.go
@@ -16,6 +16,7 @@ package vfs2
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fs/lock"
"gvisor.dev/gvisor/pkg/sentry/kernel"
@@ -57,7 +58,7 @@ func Flock(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
}
default:
// flock(2): EINVAL operation is invalid.
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
return 0, nil, nil
diff --git a/pkg/sentry/syscalls/linux/vfs2/memfd.go b/pkg/sentry/syscalls/linux/vfs2/memfd.go
index c4c0f9e0a..70c2cf5a5 100644
--- a/pkg/sentry/syscalls/linux/vfs2/memfd.go
+++ b/pkg/sentry/syscalls/linux/vfs2/memfd.go
@@ -16,10 +16,10 @@ package vfs2
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/tmpfs"
"gvisor.dev/gvisor/pkg/sentry/kernel"
- "gvisor.dev/gvisor/pkg/syserror"
)
const (
@@ -35,7 +35,7 @@ func MemfdCreate(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.S
if flags&^memfdAllFlags != 0 {
// Unknown bits in flags.
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
allowSeals := flags&linux.MFD_ALLOW_SEALING != 0
diff --git a/pkg/sentry/syscalls/linux/vfs2/mmap.go b/pkg/sentry/syscalls/linux/vfs2/mmap.go
index c961545f6..db8d59899 100644
--- a/pkg/sentry/syscalls/linux/vfs2/mmap.go
+++ b/pkg/sentry/syscalls/linux/vfs2/mmap.go
@@ -16,13 +16,13 @@ package vfs2
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
+ "gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/tmpfs"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/memmap"
"gvisor.dev/gvisor/pkg/syserror"
-
- "gvisor.dev/gvisor/pkg/hostarch"
)
// Mmap implements Linux syscall mmap(2).
@@ -38,7 +38,7 @@ func Mmap(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallC
// Require exactly one of MAP_PRIVATE and MAP_SHARED.
if private == shared {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
opts := memmap.MMapOpts{
diff --git a/pkg/sentry/syscalls/linux/vfs2/mount.go b/pkg/sentry/syscalls/linux/vfs2/mount.go
index dd93430e2..667e48744 100644
--- a/pkg/sentry/syscalls/linux/vfs2/mount.go
+++ b/pkg/sentry/syscalls/linux/vfs2/mount.go
@@ -16,12 +16,12 @@ package vfs2
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
+ "gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/vfs"
"gvisor.dev/gvisor/pkg/syserror"
-
- "gvisor.dev/gvisor/pkg/hostarch"
)
// Mount implements Linux syscall mount(2).
@@ -84,7 +84,7 @@ func Mount(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
// unknown or unsupported flags are passed. Since we don't implement
// everything, we fail explicitly on flags that are unimplemented.
if flags&(unsupportedOps|unsupportedFlags) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
var opts vfs.MountOptions
@@ -130,7 +130,7 @@ func Umount2(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
const unsupported = linux.MNT_FORCE | linux.MNT_EXPIRE
if flags&unsupported != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
path, err := copyInPath(t, addr)
diff --git a/pkg/sentry/syscalls/linux/vfs2/pipe.go b/pkg/sentry/syscalls/linux/vfs2/pipe.go
index c6fc1954c..07a89cf4e 100644
--- a/pkg/sentry/syscalls/linux/vfs2/pipe.go
+++ b/pkg/sentry/syscalls/linux/vfs2/pipe.go
@@ -16,14 +16,13 @@ package vfs2
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
+ "gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/marshal/primitive"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/pipefs"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/vfs"
- "gvisor.dev/gvisor/pkg/syserror"
-
- "gvisor.dev/gvisor/pkg/hostarch"
)
// Pipe implements Linux syscall pipe(2).
@@ -41,7 +40,7 @@ func Pipe2(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
func pipe2(t *kernel.Task, addr hostarch.Addr, flags int32) error {
if flags&^(linux.O_NONBLOCK|linux.O_CLOEXEC) != 0 {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
r, w, err := pipefs.NewConnectedPipeFDs(t, t.Kernel().PipeMount(), uint32(flags&linux.O_NONBLOCK))
if err != nil {
diff --git a/pkg/sentry/syscalls/linux/vfs2/poll.go b/pkg/sentry/syscalls/linux/vfs2/poll.go
index a69c80edd..ea95dd78c 100644
--- a/pkg/sentry/syscalls/linux/vfs2/poll.go
+++ b/pkg/sentry/syscalls/linux/vfs2/poll.go
@@ -19,6 +19,7 @@ import (
"time"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
ktime "gvisor.dev/gvisor/pkg/sentry/kernel/time"
@@ -132,7 +133,7 @@ func pollBlock(t *kernel.Task, pfd []linux.PollFD, timeout time.Duration) (time.
// Wait for a notification.
timeout, err = t.BlockWithTimeout(ch, haveTimeout, timeout)
if err != nil {
- if err == syserror.ETIMEDOUT {
+ if linuxerr.Equals(linuxerr.ETIMEDOUT, err) {
err = nil
}
return timeout, 0, err
@@ -161,7 +162,7 @@ func pollBlock(t *kernel.Task, pfd []linux.PollFD, timeout time.Duration) (time.
// copyInPollFDs copies an array of struct pollfd unless nfds exceeds the max.
func copyInPollFDs(t *kernel.Task, addr hostarch.Addr, nfds uint) ([]linux.PollFD, error) {
if uint64(nfds) > t.ThreadGroup().Limits().GetCapped(limits.NumberOfFiles, fileCap) {
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
pfd := make([]linux.PollFD, nfds)
@@ -221,7 +222,7 @@ func CopyInFDSet(t *kernel.Task, addr hostarch.Addr, nBytes, nBitsInLastPartialB
func doSelect(t *kernel.Task, nfds int, readFDs, writeFDs, exceptFDs hostarch.Addr, timeout time.Duration) (uintptr, error) {
if nfds < 0 || nfds > fileCap {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// Calculate the size of the fd sets (one bit per fd).
@@ -410,7 +411,7 @@ func (p *pollRestartBlock) Restart(t *kernel.Task) (uintptr, error) {
func poll(t *kernel.Task, pfdAddr hostarch.Addr, nfds uint, timeout time.Duration) (uintptr, error) {
remainingTimeout, n, err := doPoll(t, pfdAddr, nfds, timeout)
// On an interrupt poll(2) is restarted with the remaining timeout.
- if err == syserror.EINTR {
+ if linuxerr.Equals(linuxerr.EINTR, err) {
t.SetSyscallRestartBlock(&pollRestartBlock{
pfdAddr: pfdAddr,
nfds: nfds,
@@ -462,7 +463,7 @@ func Ppoll(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
//
// Note that this means that if err is nil but copyErr is not, copyErr is
// ignored. This is consistent with Linux.
- if err == syserror.EINTR && copyErr == nil {
+ if linuxerr.Equals(linuxerr.EINTR, err) && copyErr == nil {
err = syserror.ERESTARTNOHAND
}
return n, nil, err
@@ -484,7 +485,7 @@ func Select(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
return 0, nil, err
}
if timeval.Sec < 0 || timeval.Usec < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
timeout = time.Duration(timeval.ToNsecCapped())
}
@@ -492,7 +493,7 @@ func Select(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
n, err := doSelect(t, nfds, readFDs, writeFDs, exceptFDs, timeout)
copyErr := copyOutTimevalRemaining(t, startNs, timeout, timevalAddr)
// See comment in Ppoll.
- if err == syserror.EINTR && copyErr == nil {
+ if linuxerr.Equals(linuxerr.EINTR, err) && copyErr == nil {
err = syserror.ERESTARTNOHAND
}
return n, nil, err
@@ -539,7 +540,7 @@ func Pselect(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
n, err := doSelect(t, nfds, readFDs, writeFDs, exceptFDs, timeout)
copyErr := copyOutTimespecRemaining(t, startNs, timeout, timespecAddr)
// See comment in Ppoll.
- if err == syserror.EINTR && copyErr == nil {
+ if linuxerr.Equals(linuxerr.EINTR, err) && copyErr == nil {
err = syserror.ERESTARTNOHAND
}
return n, nil, err
@@ -561,7 +562,7 @@ func copyTimespecInToDuration(t *kernel.Task, timespecAddr hostarch.Addr) (time.
return 0, err
}
if !timespec.Valid() {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
timeout = time.Duration(timespec.ToNsecCapped())
}
@@ -573,7 +574,7 @@ func setTempSignalSet(t *kernel.Task, maskAddr hostarch.Addr, maskSize uint) err
return nil
}
if maskSize != linux.SignalSetSize {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
var mask linux.SignalSet
if _, err := mask.CopyIn(t, maskAddr); err != nil {
diff --git a/pkg/sentry/syscalls/linux/vfs2/read_write.go b/pkg/sentry/syscalls/linux/vfs2/read_write.go
index b863d7b84..3e515f6fd 100644
--- a/pkg/sentry/syscalls/linux/vfs2/read_write.go
+++ b/pkg/sentry/syscalls/linux/vfs2/read_write.go
@@ -18,6 +18,7 @@ import (
"time"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
ktime "gvisor.dev/gvisor/pkg/sentry/kernel/time"
@@ -49,7 +50,7 @@ func Read(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallC
// Check that the size is legitimate.
si := int(size)
if si < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Get the destination of the read.
@@ -120,7 +121,7 @@ func read(t *kernel.Task, file *vfs.FileDescription, dst usermem.IOSequence, opt
// Wait for a notification that we should retry.
if err = t.BlockWithDeadline(ch, hasDeadline, deadline); err != nil {
- if err == syserror.ETIMEDOUT {
+ if linuxerr.Equals(linuxerr.ETIMEDOUT, err) {
err = syserror.ErrWouldBlock
}
break
@@ -146,13 +147,13 @@ func Pread64(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
// Check that the offset is legitimate and does not overflow.
if offset < 0 || offset+int64(size) < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Check that the size is legitimate.
si := int(size)
if si < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Get the destination of the read.
@@ -183,7 +184,7 @@ func Preadv(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
// Check that the offset is legitimate.
if offset < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Get the destination of the read.
@@ -221,7 +222,7 @@ func Preadv2(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
// Check that the offset is legitimate.
if offset < -1 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Get the destination of the read.
@@ -275,7 +276,7 @@ func pread(t *kernel.Task, file *vfs.FileDescription, dst usermem.IOSequence, of
// Wait for a notification that we should retry.
if err = t.BlockWithDeadline(ch, hasDeadline, deadline); err != nil {
- if err == syserror.ETIMEDOUT {
+ if linuxerr.Equals(linuxerr.ETIMEDOUT, err) {
err = syserror.ErrWouldBlock
}
break
@@ -300,7 +301,7 @@ func Write(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
// Check that the size is legitimate.
si := int(size)
if si < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Get the source of the write.
@@ -371,7 +372,7 @@ func write(t *kernel.Task, file *vfs.FileDescription, src usermem.IOSequence, op
// Wait for a notification that we should retry.
if err = t.BlockWithDeadline(ch, hasDeadline, deadline); err != nil {
- if err == syserror.ETIMEDOUT {
+ if linuxerr.Equals(linuxerr.ETIMEDOUT, err) {
err = syserror.ErrWouldBlock
}
break
@@ -396,13 +397,13 @@ func Pwrite64(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
// Check that the offset is legitimate and does not overflow.
if offset < 0 || offset+int64(size) < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Check that the size is legitimate.
si := int(size)
if si < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Get the source of the write.
@@ -433,7 +434,7 @@ func Pwritev(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
// Check that the offset is legitimate.
if offset < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Get the source of the write.
@@ -471,7 +472,7 @@ func Pwritev2(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
// Check that the offset is legitimate.
if offset < -1 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Get the source of the write.
@@ -525,7 +526,7 @@ func pwrite(t *kernel.Task, file *vfs.FileDescription, src usermem.IOSequence, o
// Wait for a notification that we should retry.
if err = t.BlockWithDeadline(ch, hasDeadline, deadline); err != nil {
- if err == syserror.ETIMEDOUT {
+ if linuxerr.Equals(linuxerr.ETIMEDOUT, err) {
err = syserror.ErrWouldBlock
}
break
@@ -587,16 +588,16 @@ func Readahead(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
// Check that the size is valid.
if int(size) < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Check that the offset is legitimate and does not overflow.
if offset < 0 || offset+int64(size) < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Return EINVAL; if the underlying file type does not support readahead,
// then Linux will return EINVAL to indicate as much. In the future, we
// may extend this function to actually support readahead hints.
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
diff --git a/pkg/sentry/syscalls/linux/vfs2/setstat.go b/pkg/sentry/syscalls/linux/vfs2/setstat.go
index c6330c21a..0fbafd6f6 100644
--- a/pkg/sentry/syscalls/linux/vfs2/setstat.go
+++ b/pkg/sentry/syscalls/linux/vfs2/setstat.go
@@ -16,15 +16,15 @@ package vfs2
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fspath"
+ "gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/limits"
"gvisor.dev/gvisor/pkg/sentry/vfs"
"gvisor.dev/gvisor/pkg/syserror"
-
- "gvisor.dev/gvisor/pkg/hostarch"
)
const chmodMask = 0777 | linux.S_ISUID | linux.S_ISGID | linux.S_ISVTX
@@ -105,7 +105,7 @@ func Fchownat(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
func fchownat(t *kernel.Task, dirfd int32, pathAddr hostarch.Addr, owner, group, flags int32) error {
if flags&^(linux.AT_EMPTY_PATH|linux.AT_SYMLINK_NOFOLLOW) != 0 {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
path, err := copyInPath(t, pathAddr)
@@ -126,7 +126,7 @@ func populateSetStatOptionsForChown(t *kernel.Task, owner, group int32, opts *vf
if owner != -1 {
kuid := userns.MapToKUID(auth.UID(owner))
if !kuid.Ok() {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
opts.Stat.Mask |= linux.STATX_UID
opts.Stat.UID = uint32(kuid)
@@ -134,7 +134,7 @@ func populateSetStatOptionsForChown(t *kernel.Task, owner, group int32, opts *vf
if group != -1 {
kgid := userns.MapToKGID(auth.GID(group))
if !kgid.Ok() {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
opts.Stat.Mask |= linux.STATX_GID
opts.Stat.GID = uint32(kgid)
@@ -167,7 +167,7 @@ func Truncate(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
length := args[1].Int64()
if length < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
path, err := copyInPath(t, addr)
@@ -191,7 +191,7 @@ func Ftruncate(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
length := args[1].Int64()
if length < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
file := t.GetFileVFS2(fd)
@@ -201,7 +201,7 @@ func Ftruncate(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
defer file.DecRef(t)
if !file.IsWritable() {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
err := file.SetStat(t, vfs.SetStatOptions{
@@ -233,7 +233,7 @@ func Fallocate(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
return 0, nil, syserror.ENOTSUP
}
if offset < 0 || length <= 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
size := offset + length
@@ -242,9 +242,9 @@ func Fallocate(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
}
limit := limits.FromContext(t).Get(limits.FileSize).Cur
if uint64(size) >= limit {
- t.SendSignal(&arch.SignalInfo{
+ t.SendSignal(&linux.SignalInfo{
Signo: int32(linux.SIGXFSZ),
- Code: arch.SignalInfoUser,
+ Code: linux.SI_USER,
})
return 0, nil, syserror.EFBIG
}
@@ -340,7 +340,7 @@ func populateSetStatOptionsForUtimes(t *kernel.Task, timesAddr hostarch.Addr, op
return err
}
if times[0].Usec < 0 || times[0].Usec > 999999 || times[1].Usec < 0 || times[1].Usec > 999999 {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
opts.Stat.Mask = linux.STATX_ATIME | linux.STATX_MTIME
opts.Stat.Atime = linux.StatxTimestamp{
@@ -372,7 +372,7 @@ func Utimensat(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
}
if flags&^linux.AT_SYMLINK_NOFOLLOW != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// "If filename is NULL and dfd refers to an open file, then operate on the
@@ -405,7 +405,7 @@ func populateSetStatOptionsForUtimens(t *kernel.Task, timesAddr hostarch.Addr, o
}
if times[0].Nsec != linux.UTIME_OMIT {
if times[0].Nsec != linux.UTIME_NOW && (times[0].Nsec < 0 || times[0].Nsec > 999999999) {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
opts.Stat.Mask |= linux.STATX_ATIME
opts.Stat.Atime = linux.StatxTimestamp{
@@ -415,7 +415,7 @@ func populateSetStatOptionsForUtimens(t *kernel.Task, timesAddr hostarch.Addr, o
}
if times[1].Nsec != linux.UTIME_OMIT {
if times[1].Nsec != linux.UTIME_NOW && (times[1].Nsec < 0 || times[1].Nsec > 999999999) {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
opts.Stat.Mask |= linux.STATX_MTIME
opts.Stat.Mtime = linux.StatxTimestamp{
diff --git a/pkg/sentry/syscalls/linux/vfs2/signal.go b/pkg/sentry/syscalls/linux/vfs2/signal.go
index 6163da103..8b219cba7 100644
--- a/pkg/sentry/syscalls/linux/vfs2/signal.go
+++ b/pkg/sentry/syscalls/linux/vfs2/signal.go
@@ -16,13 +16,13 @@ package vfs2
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
+ "gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/signalfd"
"gvisor.dev/gvisor/pkg/sentry/kernel"
slinux "gvisor.dev/gvisor/pkg/sentry/syscalls/linux"
"gvisor.dev/gvisor/pkg/syserror"
-
- "gvisor.dev/gvisor/pkg/hostarch"
)
// sharedSignalfd is shared between the two calls.
@@ -35,7 +35,7 @@ func sharedSignalfd(t *kernel.Task, fd int32, sigset hostarch.Addr, sigsetsize u
// Always check for valid flags, even if not creating.
if flags&^(linux.SFD_NONBLOCK|linux.SFD_CLOEXEC) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Is this a change to an existing signalfd?
@@ -55,7 +55,7 @@ func sharedSignalfd(t *kernel.Task, fd int32, sigset hostarch.Addr, sigsetsize u
}
// Not a signalfd.
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
fileFlags := uint32(linux.O_RDWR)
diff --git a/pkg/sentry/syscalls/linux/vfs2/socket.go b/pkg/sentry/syscalls/linux/vfs2/socket.go
index 69f69e3af..c78c7d951 100644
--- a/pkg/sentry/syscalls/linux/vfs2/socket.go
+++ b/pkg/sentry/syscalls/linux/vfs2/socket.go
@@ -18,6 +18,7 @@ import (
"time"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/marshal"
"gvisor.dev/gvisor/pkg/marshal/primitive"
"gvisor.dev/gvisor/pkg/sentry/arch"
@@ -117,7 +118,7 @@ type multipleMessageHeader64 struct {
// from the untrusted address space range.
func CaptureAddress(t *kernel.Task, addr hostarch.Addr, addrlen uint32) ([]byte, error) {
if addrlen > maxAddrLen {
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
addrBuf := make([]byte, addrlen)
@@ -139,7 +140,7 @@ func writeAddress(t *kernel.Task, addr linux.SockAddr, addrLen uint32, addrPtr h
}
if int32(bufLen) < 0 {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
// Write the length unconditionally.
@@ -173,7 +174,7 @@ func Socket(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
// Check and initialize the flags.
if stype & ^(0xf|linux.SOCK_NONBLOCK|linux.SOCK_CLOEXEC) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Create the new socket.
@@ -206,7 +207,7 @@ func SocketPair(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sy
// Check and initialize the flags.
if stype & ^(0xf|linux.SOCK_NONBLOCK|linux.SOCK_CLOEXEC) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Create the socket pair.
@@ -281,7 +282,7 @@ func Connect(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
func accept(t *kernel.Task, fd int32, addr hostarch.Addr, addrLen hostarch.Addr, flags int) (uintptr, error) {
// Check that no unsupported flags are passed in.
if flags & ^(linux.SOCK_NONBLOCK|linux.SOCK_CLOEXEC) != 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// Get socket from the file descriptor.
@@ -309,7 +310,7 @@ func accept(t *kernel.Task, fd int32, addr hostarch.Addr, addrLen hostarch.Addr,
if peerRequested {
// NOTE(magi): Linux does not give you an error if it can't
// write the data back out so neither do we.
- if err := writeAddress(t, peer, peerLen, addr, addrLen); err == syserror.EINVAL {
+ if err := writeAddress(t, peer, peerLen, addr, addrLen); linuxerr.Equals(linuxerr.EINVAL, err) {
return 0, err
}
}
@@ -425,7 +426,7 @@ func Shutdown(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
switch how {
case linux.SHUT_RD, linux.SHUT_WR, linux.SHUT_RDWR:
default:
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
return 0, nil, s.Shutdown(t, int(how)).ToError()
@@ -458,7 +459,7 @@ func GetSockOpt(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sy
return 0, nil, err
}
if optLen < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Call syscall implementation then copy both value and value len out.
@@ -534,10 +535,10 @@ func SetSockOpt(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sy
}
if optLen < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if optLen > maxOptLen {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
buf := t.CopyScratchBuffer(int(optLen))
if _, err := t.CopyInBytes(optValAddr, buf); err != nil {
@@ -616,7 +617,7 @@ func RecvMsg(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
if t.Arch().Width() != 8 {
// We only handle 64-bit for now.
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Get socket from the file descriptor.
@@ -634,7 +635,7 @@ func RecvMsg(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
// Reject flags that we don't handle yet.
if flags & ^(baseRecvFlags|linux.MSG_PEEK|linux.MSG_CMSG_CLOEXEC|linux.MSG_ERRQUEUE) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if (file.StatusFlags() & linux.SOCK_NONBLOCK) != 0 {
@@ -664,7 +665,7 @@ func RecvMMsg(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
if t.Arch().Width() != 8 {
// We only handle 64-bit for now.
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if vlen > linux.UIO_MAXIOV {
@@ -673,7 +674,7 @@ func RecvMMsg(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
// Reject flags that we don't handle yet.
if flags & ^(baseRecvFlags|linux.MSG_CMSG_CLOEXEC|linux.MSG_ERRQUEUE) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Get socket from the file descriptor.
@@ -701,7 +702,7 @@ func RecvMMsg(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
return 0, nil, err
}
if !ts.Valid() {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
deadline = t.Kernel().MonotonicClock().Now().Add(ts.ToDuration())
haveDeadline = true
@@ -833,12 +834,12 @@ func recvSingleMsg(t *kernel.Task, s socket.SocketVFS2, msgPtr hostarch.Addr, fl
// recvfrom and recv syscall handlers.
func recvFrom(t *kernel.Task, fd int32, bufPtr hostarch.Addr, bufLen uint64, flags int32, namePtr hostarch.Addr, nameLenPtr hostarch.Addr) (uintptr, error) {
if int(bufLen) < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// Reject flags that we don't handle yet.
if flags & ^(baseRecvFlags|linux.MSG_PEEK|linux.MSG_CONFIRM) != 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// Get socket from the file descriptor.
@@ -911,7 +912,7 @@ func SendMsg(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
if t.Arch().Width() != 8 {
// We only handle 64-bit for now.
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Get socket from the file descriptor.
@@ -929,7 +930,7 @@ func SendMsg(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysca
// Reject flags that we don't handle yet.
if flags & ^(linux.MSG_DONTWAIT|linux.MSG_EOR|linux.MSG_MORE|linux.MSG_NOSIGNAL) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if (file.StatusFlags() & linux.SOCK_NONBLOCK) != 0 {
@@ -949,7 +950,7 @@ func SendMMsg(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
if t.Arch().Width() != 8 {
// We only handle 64-bit for now.
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if vlen > linux.UIO_MAXIOV {
@@ -971,7 +972,7 @@ func SendMMsg(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
// Reject flags that we don't handle yet.
if flags & ^(linux.MSG_DONTWAIT|linux.MSG_EOR|linux.MSG_MORE|linux.MSG_NOSIGNAL) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if (file.StatusFlags() & linux.SOCK_NONBLOCK) != 0 {
@@ -1077,7 +1078,7 @@ func sendSingleMsg(t *kernel.Task, s socket.SocketVFS2, file *vfs.FileDescriptio
func sendTo(t *kernel.Task, fd int32, bufPtr hostarch.Addr, bufLen uint64, flags int32, namePtr hostarch.Addr, nameLen uint32) (uintptr, error) {
bl := int(bufLen)
if bl < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// Get socket from the file descriptor.
diff --git a/pkg/sentry/syscalls/linux/vfs2/splice.go b/pkg/sentry/syscalls/linux/vfs2/splice.go
index 19e175203..6ddc72999 100644
--- a/pkg/sentry/syscalls/linux/vfs2/splice.go
+++ b/pkg/sentry/syscalls/linux/vfs2/splice.go
@@ -18,6 +18,7 @@ import (
"io"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/marshal/primitive"
"gvisor.dev/gvisor/pkg/sentry/arch"
@@ -46,12 +47,12 @@ func Splice(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
count = int64(kernel.MAX_RW_COUNT)
}
if count < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Check for invalid flags.
if flags&^(linux.SPLICE_F_MOVE|linux.SPLICE_F_NONBLOCK|linux.SPLICE_F_MORE|linux.SPLICE_F_GIFT) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Get file descriptions.
@@ -82,7 +83,7 @@ func Splice(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
inPipeFD, inIsPipe := inFile.Impl().(*pipe.VFSPipeFD)
outPipeFD, outIsPipe := outFile.Impl().(*pipe.VFSPipeFD)
if !inIsPipe && !outIsPipe {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Copy in offsets.
@@ -92,13 +93,13 @@ func Splice(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
return 0, nil, syserror.ESPIPE
}
if inFile.Options().DenyPRead {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if _, err := primitive.CopyInt64In(t, inOffsetPtr, &inOffset); err != nil {
return 0, nil, err
}
if inOffset < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
}
outOffset := int64(-1)
@@ -107,13 +108,13 @@ func Splice(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscal
return 0, nil, syserror.ESPIPE
}
if outFile.Options().DenyPWrite {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if _, err := primitive.CopyInt64In(t, outOffsetPtr, &outOffset); err != nil {
return 0, nil, err
}
if outOffset < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
}
@@ -189,12 +190,12 @@ func Tee(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallCo
count = int64(kernel.MAX_RW_COUNT)
}
if count < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Check for invalid flags.
if flags&^(linux.SPLICE_F_MOVE|linux.SPLICE_F_NONBLOCK|linux.SPLICE_F_MORE|linux.SPLICE_F_GIFT) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Get file descriptions.
@@ -225,7 +226,7 @@ func Tee(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallCo
inPipeFD, inIsPipe := inFile.Impl().(*pipe.VFSPipeFD)
outPipeFD, outIsPipe := outFile.Impl().(*pipe.VFSPipeFD)
if !inIsPipe || !outIsPipe {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Copy data.
@@ -288,7 +289,7 @@ func Sendfile(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
// Verify that the outFile Append flag is not set.
if outFile.StatusFlags()&linux.O_APPEND != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Verify that inFile is a regular file or block device. This is a
@@ -298,7 +299,7 @@ func Sendfile(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
return 0, nil, err
} else if stat.Mask&linux.STATX_TYPE == 0 ||
(stat.Mode&linux.S_IFMT != linux.S_IFREG && stat.Mode&linux.S_IFMT != linux.S_IFBLK) {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Copy offset if it exists.
@@ -314,16 +315,16 @@ func Sendfile(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sysc
offset = int64(offsetP)
if offset < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if offset+count < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
}
// Validate count. This must come after offset checks.
if count < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if count == 0 {
return 0, nil, nil
diff --git a/pkg/sentry/syscalls/linux/vfs2/stat.go b/pkg/sentry/syscalls/linux/vfs2/stat.go
index 69e77fa99..8a22ed8a5 100644
--- a/pkg/sentry/syscalls/linux/vfs2/stat.go
+++ b/pkg/sentry/syscalls/linux/vfs2/stat.go
@@ -17,15 +17,15 @@ package vfs2
import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/bits"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fspath"
"gvisor.dev/gvisor/pkg/gohacks"
+ "gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/vfs"
"gvisor.dev/gvisor/pkg/syserror"
-
- "gvisor.dev/gvisor/pkg/hostarch"
)
// Stat implements Linux syscall stat(2).
@@ -53,7 +53,7 @@ func Newfstatat(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sy
func fstatat(t *kernel.Task, dirfd int32, pathAddr, statAddr hostarch.Addr, flags int32) error {
if flags&^(linux.AT_EMPTY_PATH|linux.AT_SYMLINK_NOFOLLOW) != 0 {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
opts := vfs.StatOptions{
@@ -156,15 +156,15 @@ func Statx(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Syscall
statxAddr := args[4].Pointer()
if flags&^(linux.AT_EMPTY_PATH|linux.AT_SYMLINK_NOFOLLOW|linux.AT_STATX_SYNC_TYPE) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Make sure that only one sync type option is set.
syncType := uint32(flags & linux.AT_STATX_SYNC_TYPE)
if syncType != 0 && !bits.IsPowerOfTwo32(syncType) {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if mask&linux.STATX__RESERVED != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
opts := vfs.StatOptions{
@@ -272,7 +272,7 @@ func accessAt(t *kernel.Task, dirfd int32, pathAddr hostarch.Addr, mode uint) er
// Sanity check the mode.
if mode&^(rOK|wOK|xOK) != 0 {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
path, err := copyInPath(t, pathAddr)
@@ -315,7 +315,7 @@ func Readlinkat(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sy
func readlinkat(t *kernel.Task, dirfd int32, pathAddr, bufAddr hostarch.Addr, size uint) (uintptr, *kernel.SyscallControl, error) {
if int(size) <= 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
path, err := copyInPath(t, pathAddr)
diff --git a/pkg/sentry/syscalls/linux/vfs2/sync.go b/pkg/sentry/syscalls/linux/vfs2/sync.go
index 1f8a5878c..9344a81ce 100644
--- a/pkg/sentry/syscalls/linux/vfs2/sync.go
+++ b/pkg/sentry/syscalls/linux/vfs2/sync.go
@@ -16,6 +16,7 @@ package vfs2
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/syserror"
@@ -71,10 +72,10 @@ func SyncFileRange(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel
// Check for negative values and overflow.
if offset < 0 || offset+nbytes < 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
if flags&^(linux.SYNC_FILE_RANGE_WAIT_BEFORE|linux.SYNC_FILE_RANGE_WRITE|linux.SYNC_FILE_RANGE_WAIT_AFTER) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
file := t.GetFileVFS2(fd)
diff --git a/pkg/sentry/syscalls/linux/vfs2/timerfd.go b/pkg/sentry/syscalls/linux/vfs2/timerfd.go
index 250870c03..0794330c6 100644
--- a/pkg/sentry/syscalls/linux/vfs2/timerfd.go
+++ b/pkg/sentry/syscalls/linux/vfs2/timerfd.go
@@ -16,6 +16,7 @@ package vfs2
import (
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/timerfd"
"gvisor.dev/gvisor/pkg/sentry/kernel"
@@ -29,7 +30,7 @@ func TimerfdCreate(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel
flags := args[1].Int()
if flags&^(linux.TFD_CLOEXEC|linux.TFD_NONBLOCK) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
// Timerfds aren't writable per se (their implementation of Write just
@@ -47,7 +48,7 @@ func TimerfdCreate(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel
case linux.CLOCK_MONOTONIC, linux.CLOCK_BOOTTIME:
clock = t.Kernel().MonotonicClock()
default:
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
vfsObj := t.Kernel().VFS()
file, err := timerfd.New(t, vfsObj, clock, fileFlags)
@@ -72,7 +73,7 @@ func TimerfdSettime(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kerne
oldValAddr := args[3].Pointer()
if flags&^(linux.TFD_TIMER_ABSTIME) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
file := t.GetFileVFS2(fd)
@@ -83,7 +84,7 @@ func TimerfdSettime(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kerne
tfd, ok := file.Impl().(*timerfd.TimerFileDescription)
if !ok {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
var newVal linux.Itimerspec
@@ -117,7 +118,7 @@ func TimerfdGettime(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kerne
tfd, ok := file.Impl().(*timerfd.TimerFileDescription)
if !ok {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
tm, s := tfd.GetTime()
diff --git a/pkg/sentry/syscalls/linux/vfs2/xattr.go b/pkg/sentry/syscalls/linux/vfs2/xattr.go
index c261050c6..33209a8d0 100644
--- a/pkg/sentry/syscalls/linux/vfs2/xattr.go
+++ b/pkg/sentry/syscalls/linux/vfs2/xattr.go
@@ -18,6 +18,7 @@ import (
"bytes"
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/gohacks"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
@@ -178,7 +179,7 @@ func setxattr(t *kernel.Task, args arch.SyscallArguments, shouldFollowFinalSymli
flags := args[4].Int()
if flags&^(linux.XATTR_CREATE|linux.XATTR_REPLACE) != 0 {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
path, err := copyInPath(t, pathAddr)
@@ -216,7 +217,7 @@ func Fsetxattr(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.Sys
flags := args[4].Int()
if flags&^(linux.XATTR_CREATE|linux.XATTR_REPLACE) != 0 {
- return 0, nil, syserror.EINVAL
+ return 0, nil, linuxerr.EINVAL
}
file := t.GetFileVFS2(fd)
@@ -295,7 +296,7 @@ func Fremovexattr(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.
func copyInXattrName(t *kernel.Task, nameAddr hostarch.Addr) (string, error) {
name, err := t.CopyInString(nameAddr, linux.XATTR_NAME_MAX+1)
if err != nil {
- if err == syserror.ENAMETOOLONG {
+ if linuxerr.Equals(linuxerr.ENAMETOOLONG, err) {
return "", syserror.ERANGE
}
return "", err
@@ -321,7 +322,7 @@ func copyOutXattrNameList(t *kernel.Task, listAddr hostarch.Addr, size uint, nam
}
if buf.Len() > int(size) {
if size >= linux.XATTR_LIST_MAX {
- return 0, syserror.E2BIG
+ return 0, linuxerr.E2BIG
}
return 0, syserror.ERANGE
}
@@ -330,7 +331,7 @@ func copyOutXattrNameList(t *kernel.Task, listAddr hostarch.Addr, size uint, nam
func copyInXattrValue(t *kernel.Task, valueAddr hostarch.Addr, size uint) (string, error) {
if size > linux.XATTR_SIZE_MAX {
- return "", syserror.E2BIG
+ return "", linuxerr.E2BIG
}
buf := make([]byte, size)
if _, err := t.CopyInBytes(valueAddr, buf); err != nil {
@@ -349,7 +350,7 @@ func copyOutXattrValue(t *kernel.Task, valueAddr hostarch.Addr, size uint, value
}
if len(value) > int(size) {
if size >= linux.XATTR_SIZE_MAX {
- return 0, syserror.E2BIG
+ return 0, linuxerr.E2BIG
}
return 0, syserror.ERANGE
}
diff --git a/pkg/sentry/time/BUILD b/pkg/sentry/time/BUILD
index 1f617ca8f..36d999c47 100644
--- a/pkg/sentry/time/BUILD
+++ b/pkg/sentry/time/BUILD
@@ -8,7 +8,7 @@ go_template_instance(
out = "seqatomic_parameters_unsafe.go",
package = "time",
suffix = "Parameters",
- template = "//pkg/sync:generic_seqatomic",
+ template = "//pkg/sync/seqatomic:generic_seqatomic",
types = {
"Value": "Parameters",
},
@@ -25,6 +25,8 @@ go_library(
"muldiv_arm64.s",
"parameters.go",
"sampler.go",
+ "sampler_amd64.go",
+ "sampler_arm64.go",
"sampler_unsafe.go",
"seqatomic_parameters_unsafe.go",
"tsc_amd64.s",
@@ -32,6 +34,7 @@ go_library(
],
visibility = ["//:sandbox"],
deps = [
+ "//pkg/errors/linuxerr",
"//pkg/gohacks",
"//pkg/log",
"//pkg/metric",
diff --git a/pkg/sentry/time/calibrated_clock.go b/pkg/sentry/time/calibrated_clock.go
index 39bf1e0de..eed74f6bd 100644
--- a/pkg/sentry/time/calibrated_clock.go
+++ b/pkg/sentry/time/calibrated_clock.go
@@ -19,10 +19,10 @@ package time
import (
"time"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/metric"
"gvisor.dev/gvisor/pkg/sync"
- "gvisor.dev/gvisor/pkg/syserror"
)
// CalibratedClock implements a clock that tracks a reference clock.
@@ -259,6 +259,6 @@ func (c *CalibratedClocks) GetTime(id ClockID) (int64, error) {
case Realtime:
return c.realtime.GetTime()
default:
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
}
diff --git a/pkg/sentry/time/sampler.go b/pkg/sentry/time/sampler.go
index 4ac9c4474..24a47f5d5 100644
--- a/pkg/sentry/time/sampler.go
+++ b/pkg/sentry/time/sampler.go
@@ -21,13 +21,6 @@ import (
)
const (
- // defaultOverheadTSC is the default estimated syscall overhead in TSC cycles.
- // It is further refined as syscalls are made.
- defaultOverheadCycles = 1 * 1000
-
- // maxOverheadCycles is the maximum allowed syscall overhead in TSC cycles.
- maxOverheadCycles = 100 * defaultOverheadCycles
-
// maxSampleLoops is the maximum number of times to try to get a clock sample
// under the expected overhead.
maxSampleLoops = 5
diff --git a/pkg/sentry/time/sampler_amd64.go b/pkg/sentry/time/sampler_amd64.go
new file mode 100644
index 000000000..9f1b4b2fb
--- /dev/null
+++ b/pkg/sentry/time/sampler_amd64.go
@@ -0,0 +1,26 @@
+// Copyright 2018 The gVisor Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//+build amd64
+
+package time
+
+const (
+ // defaultOverheadTSC is the default estimated syscall overhead in TSC cycles.
+ // It is further refined as syscalls are made.
+ defaultOverheadCycles = 1 * 1000
+
+ // maxOverheadCycles is the maximum allowed syscall overhead in TSC cycles.
+ maxOverheadCycles = 100 * defaultOverheadCycles
+)
diff --git a/pkg/sentry/time/sampler_arm64.go b/pkg/sentry/time/sampler_arm64.go
new file mode 100644
index 000000000..4c8d33ae4
--- /dev/null
+++ b/pkg/sentry/time/sampler_arm64.go
@@ -0,0 +1,42 @@
+// Copyright 2018 The gVisor Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//+build arm64
+
+package time
+
+// getCNTFRQ get ARM counter-timer frequency
+func getCNTFRQ() TSCValue
+
+// getDefaultArchOverheadCycles get default OverheadCycles based on
+// ARM counter-timer frequency. Usually ARM counter-timer frequency
+// is range from 1-50Mhz which is much less than that on x86, so we
+// calibrate defaultOverheadCycles for ARM.
+func getDefaultArchOverheadCycles() TSCValue {
+ // estimated the clock frequency on x86 is 1Ghz.
+ // 1Ghz devided by counter-timer frequency of ARM to get
+ // frqRatio. defaultOverheadCycles of ARM equals to that on
+ // x86 devided by frqRatio
+ cntfrq := getCNTFRQ()
+ frqRatio := 1000000000 / cntfrq
+ overheadCycles := (1 * 1000) / frqRatio
+ return overheadCycles
+}
+
+// defaultOverheadTSC is the default estimated syscall overhead in TSC cycles.
+// It is further refined as syscalls are made.
+var defaultOverheadCycles = getDefaultArchOverheadCycles()
+
+// maxOverheadCycles is the maximum allowed syscall overhead in TSC cycles.
+var maxOverheadCycles = 100 * defaultOverheadCycles
diff --git a/pkg/sentry/time/tsc_arm64.s b/pkg/sentry/time/tsc_arm64.s
index da9fa4112..711349fa1 100644
--- a/pkg/sentry/time/tsc_arm64.s
+++ b/pkg/sentry/time/tsc_arm64.s
@@ -20,3 +20,9 @@ TEXT ·Rdtsc(SB),NOSPLIT,$0-8
WORD $0xd53be040 //MRS CNTVCT_EL0, R0
MOVD R0, ret+0(FP)
RET
+
+TEXT ·getCNTFRQ(SB),NOSPLIT,$0-8
+ // Get the virtual counter frequency.
+ WORD $0xd53be000 //MRS CNTFRQ_EL0, R0
+ MOVD R0, ret+0(FP)
+ RET
diff --git a/pkg/sentry/usage/memory.go b/pkg/sentry/usage/memory.go
index 581862ee2..e7073ec87 100644
--- a/pkg/sentry/usage/memory.go
+++ b/pkg/sentry/usage/memory.go
@@ -132,7 +132,7 @@ func Init() error {
// always be the case for a newly mapped page from /dev/shm. If we obtain
// the shared memory through some other means in the future, we may have to
// explicitly zero the page.
- mmap, err := unix.Mmap(int(file.Fd()), 0, int(RTMemoryStatsSize), unix.PROT_READ|unix.PROT_WRITE, unix.MAP_SHARED)
+ mmap, err := memutil.MapFile(0, RTMemoryStatsSize, unix.PROT_READ|unix.PROT_WRITE, unix.MAP_SHARED, file.Fd(), 0)
if err != nil {
return fmt.Errorf("error mapping usage file: %v", err)
}
diff --git a/pkg/sentry/usage/memory_unsafe.go b/pkg/sentry/usage/memory_unsafe.go
index 9e0014ca0..bc1531b91 100644
--- a/pkg/sentry/usage/memory_unsafe.go
+++ b/pkg/sentry/usage/memory_unsafe.go
@@ -21,7 +21,7 @@ import (
// RTMemoryStatsSize is the size of the RTMemoryStats struct.
var RTMemoryStatsSize = unsafe.Sizeof(RTMemoryStats{})
-// RTMemoryStatsPointer casts the address of the byte slice into a RTMemoryStats pointer.
-func RTMemoryStatsPointer(b []byte) *RTMemoryStats {
- return (*RTMemoryStats)(unsafe.Pointer(&b[0]))
+// RTMemoryStatsPointer casts addr to a RTMemoryStats pointer.
+func RTMemoryStatsPointer(addr uintptr) *RTMemoryStats {
+ return (*RTMemoryStats)(unsafe.Pointer(addr))
}
diff --git a/pkg/sentry/vfs/BUILD b/pkg/sentry/vfs/BUILD
index ac60fe8bf..a2032162d 100644
--- a/pkg/sentry/vfs/BUILD
+++ b/pkg/sentry/vfs/BUILD
@@ -95,6 +95,7 @@ go_library(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/fd",
"//pkg/fdnotifier",
"//pkg/fspath",
@@ -133,6 +134,7 @@ go_test(
deps = [
"//pkg/abi/linux",
"//pkg/context",
+ "//pkg/errors/linuxerr",
"//pkg/sentry/contexttest",
"//pkg/sync",
"//pkg/syserror",
diff --git a/pkg/sentry/vfs/anonfs.go b/pkg/sentry/vfs/anonfs.go
index f48817132..8b3612200 100644
--- a/pkg/sentry/vfs/anonfs.go
+++ b/pkg/sentry/vfs/anonfs.go
@@ -19,6 +19,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fspath"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
@@ -164,7 +165,7 @@ func (fs *anonFilesystem) ReadlinkAt(ctx context.Context, rp *ResolvingPath) (st
if !rp.Done() {
return "", syserror.ENOTDIR
}
- return "", syserror.EINVAL
+ return "", linuxerr.EINVAL
}
// RenameAt implements FilesystemImpl.RenameAt.
diff --git a/pkg/sentry/vfs/file_description.go b/pkg/sentry/vfs/file_description.go
index ef8d8a813..63ee0aab3 100644
--- a/pkg/sentry/vfs/file_description.go
+++ b/pkg/sentry/vfs/file_description.go
@@ -20,6 +20,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fs/lock"
"gvisor.dev/gvisor/pkg/sentry/fsmetric"
@@ -273,7 +274,7 @@ func (fd *FileDescription) SetStatusFlags(ctx context.Context, creds *auth.Crede
}
}
if flags&linux.O_DIRECT != 0 && !fd.opts.AllowDirectIO {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
// TODO(gvisor.dev/issue/1035): FileDescriptionImpl.SetOAsync()?
const settableFlags = linux.O_APPEND | linux.O_ASYNC | linux.O_DIRECT | linux.O_NOATIME | linux.O_NONBLOCK
@@ -708,8 +709,8 @@ func (fd *FileDescription) ListXattr(ctx context.Context, size uint64) ([]string
return names, err
}
names, err := fd.impl.ListXattr(ctx, size)
- if err == syserror.ENOTSUP {
- // Linux doesn't actually return ENOTSUP in this case; instead,
+ if linuxerr.Equals(linuxerr.EOPNOTSUPP, err) {
+ // Linux doesn't actually return EOPNOTSUPP in this case; instead,
// fs/xattr.c:vfs_listxattr() falls back to allowing the security
// subsystem to return security extended attributes, which by default
// don't exist.
@@ -873,7 +874,7 @@ func (fd *FileDescription) ComputeLockRange(ctx context.Context, start uint64, l
}
off = int64(stat.Size)
default:
- return lock.LockRange{}, syserror.EINVAL
+ return lock.LockRange{}, linuxerr.EINVAL
}
return lock.ComputeRange(int64(start), int64(length), off)
diff --git a/pkg/sentry/vfs/file_description_impl_util.go b/pkg/sentry/vfs/file_description_impl_util.go
index 2b6f47b4b..cffb46aab 100644
--- a/pkg/sentry/vfs/file_description_impl_util.go
+++ b/pkg/sentry/vfs/file_description_impl_util.go
@@ -20,6 +20,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/arch"
fslock "gvisor.dev/gvisor/pkg/sentry/fs/lock"
"gvisor.dev/gvisor/pkg/sentry/memmap"
@@ -88,25 +89,25 @@ func (FileDescriptionDefaultImpl) EventUnregister(e *waiter.Entry) {
// PRead implements FileDescriptionImpl.PRead analogously to
// file_operations::read == file_operations::read_iter == NULL in Linux.
func (FileDescriptionDefaultImpl) PRead(ctx context.Context, dst usermem.IOSequence, offset int64, opts ReadOptions) (int64, error) {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// Read implements FileDescriptionImpl.Read analogously to
// file_operations::read == file_operations::read_iter == NULL in Linux.
func (FileDescriptionDefaultImpl) Read(ctx context.Context, dst usermem.IOSequence, opts ReadOptions) (int64, error) {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// PWrite implements FileDescriptionImpl.PWrite analogously to
// file_operations::write == file_operations::write_iter == NULL in Linux.
func (FileDescriptionDefaultImpl) PWrite(ctx context.Context, src usermem.IOSequence, offset int64, opts WriteOptions) (int64, error) {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// Write implements FileDescriptionImpl.Write analogously to
// file_operations::write == file_operations::write_iter == NULL in Linux.
func (FileDescriptionDefaultImpl) Write(ctx context.Context, src usermem.IOSequence, opts WriteOptions) (int64, error) {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// IterDirents implements FileDescriptionImpl.IterDirents analogously to
@@ -125,7 +126,7 @@ func (FileDescriptionDefaultImpl) Seek(ctx context.Context, offset int64, whence
// Sync implements FileDescriptionImpl.Sync analogously to
// file_operations::fsync == NULL in Linux.
func (FileDescriptionDefaultImpl) Sync(ctx context.Context) error {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
// ConfigureMMap implements FileDescriptionImpl.ConfigureMMap analogously to
@@ -333,10 +334,10 @@ func (fd *DynamicBytesFileDescriptionImpl) Seek(ctx context.Context, offset int6
offset += fd.off
default:
// fs/seq_file:seq_lseek() rejects SEEK_END etc.
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
if offset < 0 {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
if offset != fd.lastRead {
// Regenerate the file's contents immediately. Compare
diff --git a/pkg/sentry/vfs/file_description_impl_util_test.go b/pkg/sentry/vfs/file_description_impl_util_test.go
index 1cd607c0a..566ad856a 100644
--- a/pkg/sentry/vfs/file_description_impl_util_test.go
+++ b/pkg/sentry/vfs/file_description_impl_util_test.go
@@ -23,6 +23,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/sentry/contexttest"
"gvisor.dev/gvisor/pkg/syserror"
"gvisor.dev/gvisor/pkg/usermem"
@@ -155,10 +156,10 @@ func TestGenCountFD(t *testing.T) {
}
// Write and PWrite fails.
- if _, err := fd.Write(ctx, ioseq, WriteOptions{}); err != syserror.EIO {
+ if _, err := fd.Write(ctx, ioseq, WriteOptions{}); !linuxerr.Equals(linuxerr.EIO, err) {
t.Errorf("Write: got err %v, wanted %v", err, syserror.EIO)
}
- if _, err := fd.PWrite(ctx, ioseq, 0, WriteOptions{}); err != syserror.EIO {
+ if _, err := fd.PWrite(ctx, ioseq, 0, WriteOptions{}); !linuxerr.Equals(linuxerr.EIO, err) {
t.Errorf("Write: got err %v, wanted %v", err, syserror.EIO)
}
}
@@ -215,10 +216,10 @@ func TestWritable(t *testing.T) {
if n, err := fd.Seek(ctx, 1, linux.SEEK_SET); n != 0 && err != nil {
t.Errorf("Seek: got err (%v, %v), wanted (0, nil)", n, err)
}
- if n, err := fd.Write(ctx, writeIOSeq, WriteOptions{}); n != 0 && err != syserror.EINVAL {
+ if n, err := fd.Write(ctx, writeIOSeq, WriteOptions{}); n != 0 && !linuxerr.Equals(linuxerr.EINVAL, err) {
t.Errorf("Write: got err (%v, %v), wanted (0, EINVAL)", n, err)
}
- if n, err := fd.PWrite(ctx, writeIOSeq, 2, WriteOptions{}); n != 0 && err != syserror.EINVAL {
+ if n, err := fd.PWrite(ctx, writeIOSeq, 2, WriteOptions{}); n != 0 && !linuxerr.Equals(linuxerr.EINVAL, err) {
t.Errorf("PWrite: got err (%v, %v), wanted (0, EINVAL)", n, err)
}
}
diff --git a/pkg/sentry/vfs/inotify.go b/pkg/sentry/vfs/inotify.go
index 49d29e20b..a7655bbb5 100644
--- a/pkg/sentry/vfs/inotify.go
+++ b/pkg/sentry/vfs/inotify.go
@@ -21,6 +21,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/uniqueid"
@@ -98,7 +99,7 @@ func NewInotifyFD(ctx context.Context, vfsObj *VirtualFilesystem, flags uint32)
// O_CLOEXEC affects file descriptors, so it must be handled outside of vfs.
flags &^= linux.O_CLOEXEC
if flags&^linux.O_NONBLOCK != 0 {
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
id := uniqueid.GlobalFromContext(ctx)
@@ -200,7 +201,7 @@ func (*Inotify) Write(ctx context.Context, src usermem.IOSequence, opts WriteOpt
// Read implements FileDescriptionImpl.Read.
func (i *Inotify) Read(ctx context.Context, dst usermem.IOSequence, opts ReadOptions) (int64, error) {
if dst.NumBytes() < inotifyEventBaseSize {
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
i.evMu.Lock()
@@ -226,7 +227,7 @@ func (i *Inotify) Read(ctx context.Context, dst usermem.IOSequence, opts ReadOpt
// write some events out.
return writeLen, nil
}
- return 0, syserror.EINVAL
+ return 0, linuxerr.EINVAL
}
// Linux always dequeues an available event as long as there's enough
@@ -360,7 +361,7 @@ func (i *Inotify) RmWatch(ctx context.Context, wd int32) error {
w, ok := i.watches[wd]
if !ok {
i.mu.Unlock()
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
// Remove the watch from this instance.
diff --git a/pkg/sentry/vfs/memxattr/BUILD b/pkg/sentry/vfs/memxattr/BUILD
index d8c4d27b9..ea82f4987 100644
--- a/pkg/sentry/vfs/memxattr/BUILD
+++ b/pkg/sentry/vfs/memxattr/BUILD
@@ -8,6 +8,7 @@ go_library(
visibility = ["//pkg/sentry:internal"],
deps = [
"//pkg/abi/linux",
+ "//pkg/sentry/kernel/auth",
"//pkg/sentry/vfs",
"//pkg/sync",
"//pkg/syserror",
diff --git a/pkg/sentry/vfs/memxattr/xattr.go b/pkg/sentry/vfs/memxattr/xattr.go
index 638b5d830..9b7953fa3 100644
--- a/pkg/sentry/vfs/memxattr/xattr.go
+++ b/pkg/sentry/vfs/memxattr/xattr.go
@@ -17,7 +17,10 @@
package memxattr
import (
+ "strings"
+
"gvisor.dev/gvisor/pkg/abi/linux"
+ "gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/vfs"
"gvisor.dev/gvisor/pkg/sync"
"gvisor.dev/gvisor/pkg/syserror"
@@ -26,6 +29,9 @@ import (
// SimpleExtendedAttributes implements extended attributes using a map of
// names to values.
//
+// SimpleExtendedAttributes calls vfs.CheckXattrPermissions, so callers are not
+// required to do so.
+//
// +stateify savable
type SimpleExtendedAttributes struct {
// mu protects the below fields.
@@ -34,7 +40,11 @@ type SimpleExtendedAttributes struct {
}
// GetXattr returns the value at 'name'.
-func (x *SimpleExtendedAttributes) GetXattr(opts *vfs.GetXattrOptions) (string, error) {
+func (x *SimpleExtendedAttributes) GetXattr(creds *auth.Credentials, mode linux.FileMode, kuid auth.KUID, opts *vfs.GetXattrOptions) (string, error) {
+ if err := vfs.CheckXattrPermissions(creds, vfs.MayRead, mode, kuid, opts.Name); err != nil {
+ return "", err
+ }
+
x.mu.RLock()
value, ok := x.xattrs[opts.Name]
x.mu.RUnlock()
@@ -50,7 +60,11 @@ func (x *SimpleExtendedAttributes) GetXattr(opts *vfs.GetXattrOptions) (string,
}
// SetXattr sets 'value' at 'name'.
-func (x *SimpleExtendedAttributes) SetXattr(opts *vfs.SetXattrOptions) error {
+func (x *SimpleExtendedAttributes) SetXattr(creds *auth.Credentials, mode linux.FileMode, kuid auth.KUID, opts *vfs.SetXattrOptions) error {
+ if err := vfs.CheckXattrPermissions(creds, vfs.MayWrite, mode, kuid, opts.Name); err != nil {
+ return err
+ }
+
x.mu.Lock()
defer x.mu.Unlock()
if x.xattrs == nil {
@@ -73,12 +87,19 @@ func (x *SimpleExtendedAttributes) SetXattr(opts *vfs.SetXattrOptions) error {
}
// ListXattr returns all names in xattrs.
-func (x *SimpleExtendedAttributes) ListXattr(size uint64) ([]string, error) {
+func (x *SimpleExtendedAttributes) ListXattr(creds *auth.Credentials, size uint64) ([]string, error) {
// Keep track of the size of the buffer needed in listxattr(2) for the list.
listSize := 0
x.mu.RLock()
names := make([]string, 0, len(x.xattrs))
+ haveCap := creds.HasCapability(linux.CAP_SYS_ADMIN)
for n := range x.xattrs {
+ // Hide extended attributes in the "trusted" namespace from
+ // non-privileged users. This is consistent with Linux's
+ // fs/xattr.c:simple_xattr_list().
+ if !haveCap && strings.HasPrefix(n, linux.XATTR_TRUSTED_PREFIX) {
+ continue
+ }
names = append(names, n)
// Add one byte per null terminator.
listSize += len(n) + 1
@@ -91,7 +112,11 @@ func (x *SimpleExtendedAttributes) ListXattr(size uint64) ([]string, error) {
}
// RemoveXattr removes the xattr at 'name'.
-func (x *SimpleExtendedAttributes) RemoveXattr(name string) error {
+func (x *SimpleExtendedAttributes) RemoveXattr(creds *auth.Credentials, mode linux.FileMode, kuid auth.KUID, name string) error {
+ if err := vfs.CheckXattrPermissions(creds, vfs.MayWrite, mode, kuid, name); err != nil {
+ return err
+ }
+
x.mu.Lock()
defer x.mu.Unlock()
if _, ok := x.xattrs[name]; !ok {
diff --git a/pkg/sentry/vfs/mount.go b/pkg/sentry/vfs/mount.go
index 82fd382c2..03857dfc8 100644
--- a/pkg/sentry/vfs/mount.go
+++ b/pkg/sentry/vfs/mount.go
@@ -24,6 +24,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/refsvfs2"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/syserror"
@@ -220,7 +221,7 @@ func (vfs *VirtualFilesystem) ConnectMountAt(ctx context.Context, creds *auth.Cr
vdDentry := vd.dentry
vdDentry.mu.Lock()
for {
- if vdDentry.dead {
+ if vd.mount.umounted || vdDentry.dead {
vdDentry.mu.Unlock()
vfs.mountMu.Unlock()
vd.DecRef(ctx)
@@ -284,7 +285,7 @@ func (vfs *VirtualFilesystem) MountAt(ctx context.Context, creds *auth.Credentia
// UmountAt removes the Mount at the given path.
func (vfs *VirtualFilesystem) UmountAt(ctx context.Context, creds *auth.Credentials, pop *PathOperation, opts *UmountOptions) error {
if opts.Flags&^(linux.MNT_FORCE|linux.MNT_DETACH) != 0 {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
// MNT_FORCE is currently unimplemented except for the permission check.
@@ -301,19 +302,19 @@ func (vfs *VirtualFilesystem) UmountAt(ctx context.Context, creds *auth.Credenti
}
defer vd.DecRef(ctx)
if vd.dentry != vd.mount.root {
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
vfs.mountMu.Lock()
if mntns := MountNamespaceFromContext(ctx); mntns != nil {
defer mntns.DecRef(ctx)
if mntns != vd.mount.ns {
vfs.mountMu.Unlock()
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
if vd.mount == vd.mount.ns.root {
vfs.mountMu.Unlock()
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
}
diff --git a/pkg/sentry/vfs/vfs.go b/pkg/sentry/vfs/vfs.go
index 87fdcf403..f2aabb905 100644
--- a/pkg/sentry/vfs/vfs.go
+++ b/pkg/sentry/vfs/vfs.go
@@ -42,6 +42,7 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
+ "gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fspath"
"gvisor.dev/gvisor/pkg/sentry/fsmetric"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
@@ -285,7 +286,7 @@ func (vfs *VirtualFilesystem) LinkAt(ctx context.Context, creds *auth.Credential
if newpop.FollowFinalSymlink {
oldVD.DecRef(ctx)
ctx.Warningf("VirtualFilesystem.LinkAt: file creation paths can't follow final symlink")
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
rp := vfs.getResolvingPath(creds, newpop)
@@ -321,7 +322,7 @@ func (vfs *VirtualFilesystem) MkdirAt(ctx context.Context, creds *auth.Credentia
}
if pop.FollowFinalSymlink {
ctx.Warningf("VirtualFilesystem.MkdirAt: file creation paths can't follow final symlink")
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
// "Under Linux, apart from the permission bits, the S_ISVTX mode bit is
// also honored." - mkdir(2)
@@ -359,7 +360,7 @@ func (vfs *VirtualFilesystem) MknodAt(ctx context.Context, creds *auth.Credentia
}
if pop.FollowFinalSymlink {
ctx.Warningf("VirtualFilesystem.MknodAt: file creation paths can't follow final symlink")
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
rp := vfs.getResolvingPath(creds, pop)
@@ -402,13 +403,13 @@ func (vfs *VirtualFilesystem) OpenAt(ctx context.Context, creds *auth.Credential
// filesystem implementations that do not support it).
if opts.Flags&linux.O_TMPFILE != 0 {
if opts.Flags&linux.O_DIRECTORY == 0 {
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
if opts.Flags&linux.O_CREAT != 0 {
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
if opts.Flags&linux.O_ACCMODE == linux.O_RDONLY {
- return nil, syserror.EINVAL
+ return nil, linuxerr.EINVAL
}
}
// O_PATH causes most other flags to be ignored.
@@ -499,7 +500,7 @@ func (vfs *VirtualFilesystem) RenameAt(ctx context.Context, creds *auth.Credenti
}
if oldpop.FollowFinalSymlink {
ctx.Warningf("VirtualFilesystem.RenameAt: source path can't follow final symlink")
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
oldParentVD, oldName, err := vfs.getParentDirAndName(ctx, creds, oldpop)
@@ -521,7 +522,7 @@ func (vfs *VirtualFilesystem) RenameAt(ctx context.Context, creds *auth.Credenti
if newpop.FollowFinalSymlink {
oldParentVD.DecRef(ctx)
ctx.Warningf("VirtualFilesystem.RenameAt: destination path can't follow final symlink")
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
rp := vfs.getResolvingPath(creds, newpop)
@@ -561,7 +562,7 @@ func (vfs *VirtualFilesystem) RmdirAt(ctx context.Context, creds *auth.Credentia
}
if pop.FollowFinalSymlink {
ctx.Warningf("VirtualFilesystem.RmdirAt: file deletion paths can't follow final symlink")
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
rp := vfs.getResolvingPath(creds, pop)
@@ -644,7 +645,7 @@ func (vfs *VirtualFilesystem) SymlinkAt(ctx context.Context, creds *auth.Credent
}
if pop.FollowFinalSymlink {
ctx.Warningf("VirtualFilesystem.SymlinkAt: file creation paths can't follow final symlink")
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
rp := vfs.getResolvingPath(creds, pop)
@@ -678,7 +679,7 @@ func (vfs *VirtualFilesystem) UnlinkAt(ctx context.Context, creds *auth.Credenti
}
if pop.FollowFinalSymlink {
ctx.Warningf("VirtualFilesystem.UnlinkAt: file deletion paths can't follow final symlink")
- return syserror.EINVAL
+ return linuxerr.EINVAL
}
rp := vfs.getResolvingPath(creds, pop)
@@ -731,8 +732,8 @@ func (vfs *VirtualFilesystem) ListXattrAt(ctx context.Context, creds *auth.Crede
rp.Release(ctx)
return names, nil
}
- if err == syserror.ENOTSUP {
- // Linux doesn't actually return ENOTSUP in this case; instead,
+ if linuxerr.Equals(linuxerr.EOPNOTSUPP, err) {
+ // Linux doesn't actually return EOPNOTSUPP in this case; instead,
// fs/xattr.c:vfs_listxattr() falls back to allowing the security
// subsystem to return security extended attributes, which by
// default don't exist.
@@ -830,14 +831,14 @@ func (vfs *VirtualFilesystem) MkdirAllAt(ctx context.Context, currentPath string
Path: fspath.Parse(currentPath),
}
stat, err := vfs.StatAt(ctx, creds, pop, &StatOptions{Mask: linux.STATX_TYPE})
- switch err {
- case nil:
+ switch {
+ case err == nil:
if stat.Mask&linux.STATX_TYPE == 0 || stat.Mode&linux.FileTypeMask != linux.ModeDirectory {
return syserror.ENOTDIR
}
// Directory already exists.
return nil
- case syserror.ENOENT:
+ case linuxerr.Equals(linuxerr.ENOENT, err):
// Expected, we will create the dir.
default:
return fmt.Errorf("stat failed for %q during directory creation: %w", currentPath, err)
@@ -871,7 +872,7 @@ func (vfs *VirtualFilesystem) MakeSyntheticMountpoint(ctx context.Context, targe
Root: root,
Start: root,
Path: fspath.Parse(target),
- }, mkdirOpts); err != nil && err != syserror.EEXIST {
+ }, mkdirOpts); err != nil && !linuxerr.Equals(linuxerr.EEXIST, err) {
return fmt.Errorf("failed to create mountpoint %q: %w", target, err)
}
return nil
diff --git a/pkg/sentry/watchdog/watchdog.go b/pkg/sentry/watchdog/watchdog.go
index dfe85f31d..e8f7d1f01 100644
--- a/pkg/sentry/watchdog/watchdog.go
+++ b/pkg/sentry/watchdog/watchdog.go
@@ -77,11 +77,6 @@ var DefaultOpts = Opts{
// trigger it.
const descheduleThreshold = 1 * time.Second
-var (
- stuckStartup = metric.MustCreateNewUint64Metric("/watchdog/stuck_startup_detected", true /* sync */, "Incremented once on startup watchdog timeout")
- stuckTasks = metric.MustCreateNewUint64Metric("/watchdog/stuck_tasks_detected", true /* sync */, "Cumulative count of stuck tasks detected")
-)
-
// Amount of time to wait before dumping the stack to the log again when the same task(s) remains stuck.
var stackDumpSameTaskPeriod = time.Minute
@@ -115,14 +110,14 @@ func (a *Action) Get() interface{} {
}
// String returns Action's string representation.
-func (a *Action) String() string {
- switch *a {
+func (a Action) String() string {
+ switch a {
case LogWarning:
return "logWarning"
case Panic:
return "panic"
default:
- panic(fmt.Sprintf("Invalid watchdog action: %d", *a))
+ panic(fmt.Sprintf("Invalid watchdog action: %d", a))
}
}
@@ -242,7 +237,6 @@ func (w *Watchdog) waitForStart() {
return
}
- stuckStartup.Increment()
metric.WeirdnessMetric.Increment("watchdog_stuck_startup")
var buf bytes.Buffer
@@ -316,7 +310,6 @@ func (w *Watchdog) runTurn() {
// unless they are surrounded by
// Task.UninterruptibleSleepStart/Finish.
tc = &offender{lastUpdateTime: lastUpdateTime}
- stuckTasks.Increment()
metric.WeirdnessMetric.Increment("watchdog_stuck_tasks")
newTaskFound = true
}