summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--WORKSPACE2
-rw-r--r--go.mod8
-rw-r--r--pkg/abi/linux/capability.go84
-rw-r--r--pkg/sentry/kernel/syscalls.go60
-rw-r--r--pkg/sentry/kernel/table_test.go8
-rw-r--r--pkg/sentry/syscalls/linux/linux64.go755
-rw-r--r--pkg/sentry/syscalls/syscalls.go88
-rw-r--r--runsc/cmd/BUILD3
-rw-r--r--runsc/cmd/help.go126
-rw-r--r--runsc/cmd/syscalls.go347
-rw-r--r--runsc/main.go4
11 files changed, 1032 insertions, 453 deletions
diff --git a/WORKSPACE b/WORKSPACE
index 421453a87..5155dc527 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -62,7 +62,7 @@ go_repository(
go_repository(
name = "com_github_google_subcommands",
- commit = "ce3d4cfc062f",
+ commit = "636abe8753b8",
importpath = "github.com/google/subcommands",
)
diff --git a/go.mod b/go.mod
index 9a6b27c6b..e58b84cfb 100644
--- a/go.mod
+++ b/go.mod
@@ -3,19 +3,19 @@ module gvisor.googlesource.com/gvisor
go 1.12
require (
- github.com/cenkalti/backoff v2.2.0
+ github.com/cenkalti/backoff v0.0.0-20190506075156-2146c9339422
github.com/gofrs/flock v0.6.1-0.20180915234121-886344bea079
github.com/golang/mock v1.3.1
github.com/golang/protobuf v1.3.1
github.com/google/btree v1.0.0
github.com/google/go-cmp v0.2.0
- github.com/google/subcommands v0.0.0-20170224175846-ce3d4cfc062f
+ github.com/google/subcommands v0.0.0-20190508160503-636abe8753b8
github.com/google/uuid v0.0.0-20171129191014-dec09d789f3d
github.com/kr/pty v1.1.1
github.com/opencontainers/runtime-spec v0.1.2-0.20171211145439-b2d941ef6a78
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2
github.com/vishvananda/netlink v1.0.1-0.20190318003149-adb577d4a45e
github.com/vishvananda/netns v0.0.0-20171111001504-be1fbeda1936
- golang.org/x/net v0.0.0-20180404174746-b3c676e531a6
- golang.org/x/sys v0.0.0-20171117071000-0dd5e194bbf5
+ golang.org/x/net v0.0.0-20190311183353-d8887717615a
+ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a
)
diff --git a/pkg/abi/linux/capability.go b/pkg/abi/linux/capability.go
index c120cac64..65dd77e6e 100644
--- a/pkg/abi/linux/capability.go
+++ b/pkg/abi/linux/capability.go
@@ -69,6 +69,90 @@ func (cp Capability) Ok() bool {
return cp >= 0 && cp <= MaxCapability
}
+// String returns the capability name.
+func (cp Capability) String() string {
+ switch cp {
+ case CAP_CHOWN:
+ return "CAP_CHOWN"
+ case CAP_DAC_OVERRIDE:
+ return "CAP_DAC_OVERRIDE"
+ case CAP_DAC_READ_SEARCH:
+ return "CAP_DAC_READ_SEARCH"
+ case CAP_FOWNER:
+ return "CAP_FOWNER"
+ case CAP_FSETID:
+ return "CAP_FSETID"
+ case CAP_KILL:
+ return "CAP_KILL"
+ case CAP_SETGID:
+ return "CAP_SETGID"
+ case CAP_SETUID:
+ return "CAP_SETUID"
+ case CAP_SETPCAP:
+ return "CAP_SETPCAP"
+ case CAP_LINUX_IMMUTABLE:
+ return "CAP_LINUX_IMMUTABLE"
+ case CAP_NET_BIND_SERVICE:
+ return "CAP_NET_BIND_SERVICE"
+ case CAP_NET_BROADCAST:
+ return "CAP_NET_BROADCAST"
+ case CAP_NET_ADMIN:
+ return "CAP_NET_ADMIN"
+ case CAP_NET_RAW:
+ return "CAP_NET_RAW"
+ case CAP_IPC_LOCK:
+ return "CAP_IPC_LOCK"
+ case CAP_IPC_OWNER:
+ return "CAP_IPC_OWNER"
+ case CAP_SYS_MODULE:
+ return "CAP_SYS_MODULE"
+ case CAP_SYS_RAWIO:
+ return "CAP_SYS_RAWIO"
+ case CAP_SYS_CHROOT:
+ return "CAP_SYS_CHROOT"
+ case CAP_SYS_PTRACE:
+ return "CAP_SYS_PTRACE"
+ case CAP_SYS_PACCT:
+ return "CAP_SYS_PACCT"
+ case CAP_SYS_ADMIN:
+ return "CAP_SYS_ADMIN"
+ case CAP_SYS_BOOT:
+ return "CAP_SYS_BOOT"
+ case CAP_SYS_NICE:
+ return "CAP_SYS_NICE"
+ case CAP_SYS_RESOURCE:
+ return "CAP_SYS_RESOURCE"
+ case CAP_SYS_TIME:
+ return "CAP_SYS_TIME"
+ case CAP_SYS_TTY_CONFIG:
+ return "CAP_SYS_TTY_CONFIG"
+ case CAP_MKNOD:
+ return "CAP_MKNOD"
+ case CAP_LEASE:
+ return "CAP_LEASE"
+ case CAP_AUDIT_WRITE:
+ return "CAP_AUDIT_WRITE"
+ case CAP_AUDIT_CONTROL:
+ return "CAP_AUDIT_CONTROL"
+ case CAP_SETFCAP:
+ return "CAP_SETFCAP"
+ case CAP_MAC_OVERRIDE:
+ return "CAP_MAC_OVERRIDE"
+ case CAP_MAC_ADMIN:
+ return "CAP_MAC_ADMIN"
+ case CAP_SYSLOG:
+ return "CAP_SYSLOG"
+ case CAP_WAKE_ALARM:
+ return "CAP_WAKE_ALARM"
+ case CAP_BLOCK_SUSPEND:
+ return "CAP_BLOCK_SUSPEND"
+ case CAP_AUDIT_READ:
+ return "CAP_AUDIT_READ"
+ default:
+ return "UNKNOWN"
+ }
+}
+
// Version numbers used by the capget/capset syscalls, defined in Linux's
// include/uapi/linux/capability.h.
const (
diff --git a/pkg/sentry/kernel/syscalls.go b/pkg/sentry/kernel/syscalls.go
index 0572053db..27cd3728b 100644
--- a/pkg/sentry/kernel/syscalls.go
+++ b/pkg/sentry/kernel/syscalls.go
@@ -32,6 +32,51 @@ import (
// syscall.
const maxSyscallNum = 2000
+// SyscallSupportLevel is a syscall support levels.
+type SyscallSupportLevel int
+
+// String returns a human readable represetation of the support level.
+func (l SyscallSupportLevel) String() string {
+ switch l {
+ case SupportUnimplemented:
+ return "Unimplemented"
+ case SupportPartial:
+ return "Partial Support"
+ case SupportFull:
+ return "Full Support"
+ default:
+ return "Undocumented"
+ }
+}
+
+const (
+ // SupportUndocumented indicates the syscall is not documented yet.
+ SupportUndocumented = iota
+
+ // SupportUnimplemented indicates the syscall is unimplemented.
+ SupportUnimplemented
+
+ // SupportPartial indicates the syscall is partially supported.
+ SupportPartial
+
+ // SupportFull indicates the syscall is fully supported.
+ SupportFull
+)
+
+// Syscall includes the syscall implementation and compatibility information.
+type Syscall struct {
+ // Name is the syscall name.
+ Name string
+ // Fn is the implementation of the syscall.
+ Fn SyscallFn
+ // SupportLevel is the level of support implemented in gVisor.
+ SupportLevel SyscallSupportLevel
+ // Note describes the compatibility of the syscall.
+ Note string
+ // URLs is set of URLs to any relevant bugs or issues.
+ URLs []string
+}
+
// SyscallFn is a syscall implementation.
type SyscallFn func(t *Task, args arch.SyscallArguments) (uintptr, *SyscallControl, error)
@@ -83,7 +128,7 @@ type SyscallFlagsTable struct {
// Init initializes the struct, with all syscalls in table set to enable.
//
// max is the largest syscall number in table.
-func (e *SyscallFlagsTable) init(table map[uintptr]SyscallFn, max uintptr) {
+func (e *SyscallFlagsTable) init(table map[uintptr]Syscall, max uintptr) {
e.enable = make([]uint32, max+1)
for num := range table {
e.enable[num] = syscallPresent
@@ -194,7 +239,7 @@ type SyscallTable struct {
AuditNumber uint32 `state:"manual"`
// Table is the collection of functions.
- Table map[uintptr]SyscallFn `state:"manual"`
+ Table map[uintptr]Syscall `state:"manual"`
// lookup is a fixed-size array that holds the syscalls (indexed by
// their numbers). It is used for fast look ups.
@@ -247,7 +292,7 @@ func LookupSyscallTable(os abi.OS, a arch.Arch) (*SyscallTable, bool) {
func RegisterSyscallTable(s *SyscallTable) {
if s.Table == nil {
// Ensure non-nil lookup table.
- s.Table = make(map[uintptr]SyscallFn)
+ s.Table = make(map[uintptr]Syscall)
}
if s.Emulate == nil {
// Ensure non-nil emulate table.
@@ -268,8 +313,8 @@ func RegisterSyscallTable(s *SyscallTable) {
s.lookup = make([]SyscallFn, max+1)
// Initialize the fast-lookup table.
- for num, fn := range s.Table {
- s.lookup[num] = fn
+ for num, sc := range s.Table {
+ s.lookup[num] = sc.Fn
}
s.FeatureEnable.init(s.Table, max)
@@ -303,5 +348,8 @@ func (s *SyscallTable) LookupEmulate(addr usermem.Addr) (uintptr, bool) {
// mapLookup is similar to Lookup, except that it only uses the syscall table,
// that is, it skips the fast look array. This is available for benchmarking.
func (s *SyscallTable) mapLookup(sysno uintptr) SyscallFn {
- return s.Table[sysno]
+ if sc, ok := s.Table[sysno]; ok {
+ return sc.Fn
+ }
+ return nil
}
diff --git a/pkg/sentry/kernel/table_test.go b/pkg/sentry/kernel/table_test.go
index 8f7cdb9f3..3f2b042c8 100644
--- a/pkg/sentry/kernel/table_test.go
+++ b/pkg/sentry/kernel/table_test.go
@@ -26,11 +26,13 @@ const (
)
func createSyscallTable() *SyscallTable {
- m := make(map[uintptr]SyscallFn)
+ m := make(map[uintptr]Syscall)
for i := uintptr(0); i <= maxTestSyscall; i++ {
j := i
- m[i] = func(*Task, arch.SyscallArguments) (uintptr, *SyscallControl, error) {
- return j, nil, nil
+ m[i] = Syscall{
+ Fn: func(*Task, arch.SyscallArguments) (uintptr, *SyscallControl, error) {
+ return j, nil, nil
+ },
}
}
diff --git a/pkg/sentry/syscalls/linux/linux64.go b/pkg/sentry/syscalls/linux/linux64.go
index ad88b1391..5251c2463 100644
--- a/pkg/sentry/syscalls/linux/linux64.go
+++ b/pkg/sentry/syscalls/linux/linux64.go
@@ -34,33 +34,6 @@ const _AUDIT_ARCH_X86_64 = 0xc000003e
// AMD64 is a table of Linux amd64 syscall API with the corresponding syscall
// numbers from Linux 4.4. The entries commented out are those syscalls we
// don't currently support.
-//
-// Syscall support is documented as annotations in Go comments of the form:
-// @Syscall(<name>, <key:value>, ...)
-//
-// Supported args and values are:
-//
-// - arg: A syscall option. This entry only applies to the syscall when given
-// this option.
-// - support: Indicates support level
-// - UNIMPLEMENTED: Unimplemented (default, implies returns:ENOSYS)
-// - PARTIAL: Partial support. Details should be provided in note.
-// - FULL: Full support
-// - returns: Indicates a known return value. Values are syscall errors. This
-// is treated as a string so you can use something like
-// "returns:EPERM or ENOSYS".
-// - issue: A Github issue number.
-// - note: A note
-//
-// Example:
-// // @Syscall(mmap, arg:MAP_PRIVATE, support:FULL, note:Private memory fully supported)
-// // @Syscall(mmap, arg:MAP_SHARED, issue:123, note:Shared memory not supported)
-// // @Syscall(setxattr, returns:ENOTSUP, note:Requires file system support)
-//
-// Annotations should be placed as close to their implementation as possible
-// (preferrably as part of a supporting function's Godoc) and should be
-// updated as syscall support changes. Unimplemented syscalls are documented
-// here due to their lack of a supporting function or method.
var AMD64 = &kernel.SyscallTable{
OS: abi.Linux,
Arch: arch.AMD64,
@@ -74,404 +47,338 @@ var AMD64 = &kernel.SyscallTable{
Version: "#1 SMP Sun Jan 10 15:06:54 PST 2016",
},
AuditNumber: _AUDIT_ARCH_X86_64,
- Table: map[uintptr]kernel.SyscallFn{
- 0: Read,
- 1: Write,
- 2: Open,
- 3: Close,
- 4: Stat,
- 5: Fstat,
- 6: Lstat,
- 7: Poll,
- 8: Lseek,
- 9: Mmap,
- 10: Mprotect,
- 11: Munmap,
- 12: Brk,
- 13: RtSigaction,
- 14: RtSigprocmask,
- 15: RtSigreturn,
- 16: Ioctl,
- 17: Pread64,
- 18: Pwrite64,
- 19: Readv,
- 20: Writev,
- 21: Access,
- 22: Pipe,
- 23: Select,
- 24: SchedYield,
- 25: Mremap,
- 26: Msync,
- 27: Mincore,
- 28: Madvise,
- 29: Shmget,
- 30: Shmat,
- 31: Shmctl,
- 32: Dup,
- 33: Dup2,
- 34: Pause,
- 35: Nanosleep,
- 36: Getitimer,
- 37: Alarm,
- 38: Setitimer,
- 39: Getpid,
- 40: Sendfile,
- 41: Socket,
- 42: Connect,
- 43: Accept,
- 44: SendTo,
- 45: RecvFrom,
- 46: SendMsg,
- 47: RecvMsg,
- 48: Shutdown,
- 49: Bind,
- 50: Listen,
- 51: GetSockName,
- 52: GetPeerName,
- 53: SocketPair,
- 54: SetSockOpt,
- 55: GetSockOpt,
- 56: Clone,
- 57: Fork,
- 58: Vfork,
- 59: Execve,
- 60: Exit,
- 61: Wait4,
- 62: Kill,
- 63: Uname,
- 64: Semget,
- 65: Semop,
- 66: Semctl,
- 67: Shmdt,
- // 68: @Syscall(Msgget), TODO(b/29354921)
- // 69: @Syscall(Msgsnd), TODO(b/29354921)
- // 70: @Syscall(Msgrcv), TODO(b/29354921)
- // 71: @Syscall(Msgctl), TODO(b/29354921)
- 72: Fcntl,
- 73: Flock,
- 74: Fsync,
- 75: Fdatasync,
- 76: Truncate,
- 77: Ftruncate,
- 78: Getdents,
- 79: Getcwd,
- 80: Chdir,
- 81: Fchdir,
- 82: Rename,
- 83: Mkdir,
- 84: Rmdir,
- 85: Creat,
- 86: Link,
- 87: Unlink,
- 88: Symlink,
- 89: Readlink,
- 90: Chmod,
- 91: Fchmod,
- 92: Chown,
- 93: Fchown,
- 94: Lchown,
- 95: Umask,
- 96: Gettimeofday,
- 97: Getrlimit,
- 98: Getrusage,
- 99: Sysinfo,
- 100: Times,
- 101: Ptrace,
- 102: Getuid,
- 103: Syslog,
- 104: Getgid,
- 105: Setuid,
- 106: Setgid,
- 107: Geteuid,
- 108: Getegid,
- 109: Setpgid,
- 110: Getppid,
- 111: Getpgrp,
- 112: Setsid,
- 113: Setreuid,
- 114: Setregid,
- 115: Getgroups,
- 116: Setgroups,
- 117: Setresuid,
- 118: Getresuid,
- 119: Setresgid,
- 120: Getresgid,
- 121: Getpgid,
- // 122: @Syscall(Setfsuid), TODO(b/112851702)
- // 123: @Syscall(Setfsgid), TODO(b/112851702)
- 124: Getsid,
- 125: Capget,
- 126: Capset,
- 127: RtSigpending,
- 128: RtSigtimedwait,
- 129: RtSigqueueinfo,
- 130: RtSigsuspend,
- 131: Sigaltstack,
- 132: Utime,
- 133: Mknod,
- // @Syscall(Uselib, note:Obsolete)
- 134: syscalls.Error(syscall.ENOSYS),
- // @Syscall(SetPersonality, returns:EINVAL, note:Unable to change personality)
- 135: syscalls.ErrorWithEvent(syscall.EINVAL),
- // @Syscall(Ustat, note:Needs filesystem support)
- 136: syscalls.ErrorWithEvent(syscall.ENOSYS),
- 137: Statfs,
- 138: Fstatfs,
- // 139: @Syscall(Sysfs), TODO(gvisor.dev/issue/165)
- 140: Getpriority,
- 141: Setpriority,
- // @Syscall(SchedSetparam, returns:EPERM or ENOSYS, note:Returns EPERM if the process does not have cap_sys_nice; ENOSYS otherwise)
- 142: syscalls.CapError(linux.CAP_SYS_NICE), // requires cap_sys_nice
- 143: SchedGetparam,
- 144: SchedSetscheduler,
- 145: SchedGetscheduler,
- 146: SchedGetPriorityMax,
- 147: SchedGetPriorityMin,
- // @Syscall(SchedRrGetInterval, returns:EPERM)
- 148: syscalls.ErrorWithEvent(syscall.EPERM),
- 149: Mlock,
- 150: Munlock,
- 151: Mlockall,
- 152: Munlockall,
- // @Syscall(Vhangup, returns:EPERM)
- 153: syscalls.CapError(linux.CAP_SYS_TTY_CONFIG),
- // @Syscall(ModifyLdt, returns:EPERM)
- 154: syscalls.Error(syscall.EPERM),
- // @Syscall(PivotRoot, returns:EPERM)
- 155: syscalls.Error(syscall.EPERM),
- // @Syscall(Sysctl, returns:EPERM)
- 156: syscalls.Error(syscall.EPERM), // syscall is "worthless"
- 157: Prctl,
- 158: ArchPrctl,
- // @Syscall(Adjtimex, returns:EPERM or ENOSYS, note:Returns EPERM if the process does not have cap_sys_time; ENOSYS otherwise)
- 159: syscalls.CapError(linux.CAP_SYS_TIME), // requires cap_sys_time
- 160: Setrlimit,
- 161: Chroot,
- 162: Sync,
- // @Syscall(Acct, returns:EPERM or ENOSYS, note:Returns EPERM if the process does not have cap_sys_pacct; ENOSYS otherwise)
- 163: syscalls.CapError(linux.CAP_SYS_PACCT), // requires cap_sys_pacct
- // @Syscall(Settimeofday, returns:EPERM or ENOSYS, note:Returns EPERM if the process does not have cap_sys_time; ENOSYS otherwise)
- 164: syscalls.CapError(linux.CAP_SYS_TIME), // requires cap_sys_time
- 165: Mount,
- 166: Umount2,
- // @Syscall(Swapon, returns:EPERM or ENOSYS, note:Returns EPERM if the process does not have cap_sys_admin; ENOSYS otherwise)
- 167: syscalls.CapError(linux.CAP_SYS_ADMIN), // requires cap_sys_admin
- // @Syscall(Swapoff, returns:EPERM or ENOSYS, note:Returns EPERM if the process does not have cap_sys_admin; ENOSYS otherwise)
- 168: syscalls.CapError(linux.CAP_SYS_ADMIN), // requires cap_sys_admin
- // @Syscall(Reboot, returns:EPERM or ENOSYS, note:Returns EPERM if the process does not have cap_sys_boot; ENOSYS otherwise)
- 169: syscalls.CapError(linux.CAP_SYS_BOOT), // requires cap_sys_boot
- 170: Sethostname,
- 171: Setdomainname,
- // @Syscall(Iopl, returns:EPERM or ENOSYS, note:Returns EPERM if the process does not have cap_sys_rawio; ENOSYS otherwise)
- 172: syscalls.CapError(linux.CAP_SYS_RAWIO), // requires cap_sys_rawio
- // @Syscall(Ioperm, returns:EPERM or ENOSYS, note:Returns EPERM if the process does not have cap_sys_rawio; ENOSYS otherwise)
- 173: syscalls.CapError(linux.CAP_SYS_RAWIO), // requires cap_sys_rawio
- // @Syscall(CreateModule, returns:EPERM or ENOSYS, note:Returns EPERM if the process does not have cap_sys_module; ENOSYS otherwise)
- 174: syscalls.CapError(linux.CAP_SYS_MODULE), // CreateModule, requires cap_sys_module
- // @Syscall(InitModule, returns:EPERM or ENOSYS, note:Returns EPERM if the process does not have cap_sys_module; ENOSYS otherwise)
- 175: syscalls.CapError(linux.CAP_SYS_MODULE), // requires cap_sys_module
- // @Syscall(DeleteModule, returns:EPERM or ENOSYS, note:Returns EPERM if the process does not have cap_sys_module; ENOSYS otherwise)
- 176: syscalls.CapError(linux.CAP_SYS_MODULE), // requires cap_sys_module
- // @Syscall(GetKernelSyms, note:Not supported in > 2.6)
- 177: syscalls.Error(syscall.ENOSYS),
- // @Syscall(QueryModule, note:Not supported in > 2.6)
- 178: syscalls.Error(syscall.ENOSYS),
- // @Syscall(Quotactl, returns:EPERM or ENOSYS, note:Returns EPERM if the process does not have cap_sys_admin; ENOSYS otherwise)
- 179: syscalls.CapError(linux.CAP_SYS_ADMIN), // requires cap_sys_admin (most operations)
- // @Syscall(Nfsservctl, note:Does not exist > 3.1)
- 180: syscalls.Error(syscall.ENOSYS),
- // @Syscall(Getpmsg, note:Not implemented in Linux)
- 181: syscalls.Error(syscall.ENOSYS),
- // @Syscall(Putpmsg, note:Not implemented in Linux)
- 182: syscalls.Error(syscall.ENOSYS),
- // @Syscall(AfsSyscall, note:Not implemented in Linux)
- 183: syscalls.Error(syscall.ENOSYS),
- // @Syscall(Tuxcall, note:Not implemented in Linux)
- 184: syscalls.Error(syscall.ENOSYS),
- // @Syscall(Security, note:Not implemented in Linux)
- 185: syscalls.Error(syscall.ENOSYS),
- 186: Gettid,
- 187: nil, // @Syscall(Readahead), TODO(b/29351341)
- // @Syscall(Setxattr, returns:ENOTSUP, note:Requires filesystem support)
- 188: syscalls.ErrorWithEvent(syscall.ENOTSUP),
- // @Syscall(Lsetxattr, returns:ENOTSUP, note:Requires filesystem support)
- 189: syscalls.ErrorWithEvent(syscall.ENOTSUP),
- // @Syscall(Fsetxattr, returns:ENOTSUP, note:Requires filesystem support)
- 190: syscalls.ErrorWithEvent(syscall.ENOTSUP),
- // @Syscall(Getxattr, returns:ENOTSUP, note:Requires filesystem support)
- 191: syscalls.ErrorWithEvent(syscall.ENOTSUP),
- // @Syscall(Lgetxattr, returns:ENOTSUP, note:Requires filesystem support)
- 192: syscalls.ErrorWithEvent(syscall.ENOTSUP),
- // @Syscall(Fgetxattr, returns:ENOTSUP, note:Requires filesystem support)
- 193: syscalls.ErrorWithEvent(syscall.ENOTSUP),
- // @Syscall(Listxattr, returns:ENOTSUP, note:Requires filesystem support)
- 194: syscalls.ErrorWithEvent(syscall.ENOTSUP),
- // @Syscall(Llistxattr, returns:ENOTSUP, note:Requires filesystem support)
- 195: syscalls.ErrorWithEvent(syscall.ENOTSUP),
- // @Syscall(Flistxattr, returns:ENOTSUP, note:Requires filesystem support)
- 196: syscalls.ErrorWithEvent(syscall.ENOTSUP),
- // @Syscall(Removexattr, returns:ENOTSUP, note:Requires filesystem support)
- 197: syscalls.ErrorWithEvent(syscall.ENOTSUP),
- // @Syscall(Lremovexattr, returns:ENOTSUP, note:Requires filesystem support)
- 198: syscalls.ErrorWithEvent(syscall.ENOTSUP),
- // @Syscall(Fremovexattr, returns:ENOTSUP, note:Requires filesystem support)
- 199: syscalls.ErrorWithEvent(syscall.ENOTSUP),
- 200: Tkill,
- 201: Time,
- 202: Futex,
- 203: SchedSetaffinity,
- 204: SchedGetaffinity,
- // @Syscall(SetThreadArea, note:Expected to return ENOSYS on 64-bit)
- 205: syscalls.Error(syscall.ENOSYS),
- 206: IoSetup,
- 207: IoDestroy,
- 208: IoGetevents,
- 209: IoSubmit,
- 210: IoCancel,
- // @Syscall(GetThreadArea, note:Expected to return ENOSYS on 64-bit)
- 211: syscalls.Error(syscall.ENOSYS),
- // @Syscall(LookupDcookie, returns:EPERM or ENOSYS, note:Returns EPERM if the process does not have cap_sys_admin; ENOSYS otherwise)
- 212: syscalls.CapError(linux.CAP_SYS_ADMIN), // requires cap_sys_admin
- 213: EpollCreate,
- // @Syscall(EpollCtlOld, note:Deprecated)
- 214: syscalls.ErrorWithEvent(syscall.ENOSYS), // deprecated (afaik, unused)
- // @Syscall(EpollWaitOld, note:Deprecated)
- 215: syscalls.ErrorWithEvent(syscall.ENOSYS), // deprecated (afaik, unused)
- // @Syscall(RemapFilePages, note:Deprecated)
- 216: syscalls.ErrorWithEvent(syscall.ENOSYS), // deprecated since 3.16
- 217: Getdents64,
- 218: SetTidAddress,
- 219: RestartSyscall,
- // 220: @Syscall(Semtimedop), TODO(b/29354920)
- 221: Fadvise64,
- 222: TimerCreate,
- 223: TimerSettime,
- 224: TimerGettime,
- 225: TimerGetoverrun,
- 226: TimerDelete,
- 227: ClockSettime,
- 228: ClockGettime,
- 229: ClockGetres,
- 230: ClockNanosleep,
- 231: ExitGroup,
- 232: EpollWait,
- 233: EpollCtl,
- 234: Tgkill,
- 235: Utimes,
- // @Syscall(Vserver, note:Not implemented by Linux)
- 236: syscalls.Error(syscall.ENOSYS), // Vserver, not implemented by Linux
- 237: Mbind,
- 238: SetMempolicy,
- 239: GetMempolicy,
- // 240: @Syscall(MqOpen), TODO(b/29354921)
- // 241: @Syscall(MqUnlink), TODO(b/29354921)
- // 242: @Syscall(MqTimedsend), TODO(b/29354921)
- // 243: @Syscall(MqTimedreceive), TODO(b/29354921)
- // 244: @Syscall(MqNotify), TODO(b/29354921)
- // 245: @Syscall(MqGetsetattr), TODO(b/29354921)
- 246: syscalls.CapError(linux.CAP_SYS_BOOT), // kexec_load, requires cap_sys_boot
- 247: Waitid,
- // @Syscall(AddKey, returns:EACCES, note:Not available to user)
- 248: syscalls.Error(syscall.EACCES),
- // @Syscall(RequestKey, returns:EACCES, note:Not available to user)
- 249: syscalls.Error(syscall.EACCES),
- // @Syscall(Keyctl, returns:EACCES, note:Not available to user)
- 250: syscalls.Error(syscall.EACCES),
- // @Syscall(IoprioSet, returns:EPERM or ENOSYS, note:Returns EPERM if the process does not have cap_sys_admin; ENOSYS otherwise)
- 251: syscalls.CapError(linux.CAP_SYS_ADMIN), // requires cap_sys_nice or cap_sys_admin (depending)
- // @Syscall(IoprioGet, returns:EPERM or ENOSYS, note:Returns EPERM if the process does not have cap_sys_admin; ENOSYS otherwise)
- 252: syscalls.CapError(linux.CAP_SYS_ADMIN), // requires cap_sys_nice or cap_sys_admin (depending)
- 253: InotifyInit,
- 254: InotifyAddWatch,
- 255: InotifyRmWatch,
- // @Syscall(MigratePages, returns:EPERM or ENOSYS, note:Returns EPERM if the process does not have cap_sys_nice; ENOSYS otherwise)
- 256: syscalls.CapError(linux.CAP_SYS_NICE),
- 257: Openat,
- 258: Mkdirat,
- 259: Mknodat,
- 260: Fchownat,
- 261: Futimesat,
- 262: Fstatat,
- 263: Unlinkat,
- 264: Renameat,
- 265: Linkat,
- 266: Symlinkat,
- 267: Readlinkat,
- 268: Fchmodat,
- 269: Faccessat,
- 270: Pselect,
- 271: Ppoll,
- 272: Unshare,
- // @Syscall(SetRobustList, note:Obsolete)
- 273: syscalls.Error(syscall.ENOSYS),
- // @Syscall(GetRobustList, note:Obsolete)
- 274: syscalls.Error(syscall.ENOSYS),
- 275: Splice,
- // 276: @Syscall(Tee), TODO(b/29354098)
- 277: SyncFileRange,
- // 278: @Syscall(Vmsplice), TODO(b/29354098)
- // @Syscall(MovePages, returns:EPERM or ENOSYS, note:Returns EPERM if the process does not have cap_sys_nice; ENOSYS otherwise)
- 279: syscalls.CapError(linux.CAP_SYS_NICE), // requires cap_sys_nice (mostly)
- 280: Utimensat,
- 281: EpollPwait,
- // 282: @Syscall(Signalfd), TODO(b/19846426)
- 283: TimerfdCreate,
- 284: Eventfd,
- 285: Fallocate,
- 286: TimerfdSettime,
- 287: TimerfdGettime,
- 288: Accept4,
- // 289: @Syscall(Signalfd4), TODO(b/19846426)
- 290: Eventfd2,
- 291: EpollCreate1,
- 292: Dup3,
- 293: Pipe2,
- 294: InotifyInit1,
- 295: Preadv,
- 296: Pwritev,
- 297: RtTgsigqueueinfo,
- // @Syscall(PerfEventOpen, returns:ENODEV, note:No support for perf counters)
- 298: syscalls.ErrorWithEvent(syscall.ENODEV),
- 299: RecvMMsg,
- // @Syscall(FanotifyInit, note:Needs CONFIG_FANOTIFY)
- 300: syscalls.ErrorWithEvent(syscall.ENOSYS),
- // @Syscall(FanotifyMark, note:Needs CONFIG_FANOTIFY)
- 301: syscalls.ErrorWithEvent(syscall.ENOSYS),
- 302: Prlimit64,
- // @Syscall(NameToHandleAt, returns:EOPNOTSUPP, note:Needs filesystem support)
- 303: syscalls.ErrorWithEvent(syscall.EOPNOTSUPP),
- // @Syscall(OpenByHandleAt, returns:EOPNOTSUPP, note:Needs filesystem support)
- 304: syscalls.ErrorWithEvent(syscall.EOPNOTSUPP),
- // @Syscall(ClockAdjtime, returns:EPERM or ENOSYS, note:Returns EPERM if the process does not have cap_sys_module; ENOSYS otherwise)
- 305: syscalls.CapError(linux.CAP_SYS_TIME), // requires cap_sys_time
- 306: Syncfs,
- 307: SendMMsg,
- // 308: @Syscall(Setns), TODO(b/29354995)
- 309: Getcpu,
- // 310: @Syscall(ProcessVmReadv), TODO(gvisor.dev/issue/158) may require cap_sys_ptrace
- // 311: @Syscall(ProcessVmWritev), TODO(gvisor.dev/issue/158) may require cap_sys_ptrace
- // @Syscall(Kcmp, returns:EPERM or ENOSYS, note:Requires cap_sys_ptrace)
- 312: syscalls.CapError(linux.CAP_SYS_PTRACE),
- // @Syscall(FinitModule, returns:EPERM or ENOSYS, note:Returns EPERM if the process does not have cap_sys_module; ENOSYS otherwise)
- 313: syscalls.CapError(linux.CAP_SYS_MODULE),
- // 314: @Syscall(SchedSetattr), TODO(b/118902272), we have no scheduler
- // 315: @Syscall(SchedGetattr), TODO(b/118902272), we have no scheduler
- // 316: @Syscall(Renameat2), TODO(b/118902772)
- 317: Seccomp,
- 318: GetRandom,
- 319: MemfdCreate,
- // @Syscall(KexecFileLoad, EPERM or ENOSYS, note:Infeasible to support. Returns EPERM if the process does not have cap_sys_boot; ENOSYS otherwise)
- 320: syscalls.CapError(linux.CAP_SYS_BOOT),
- // @Syscall(Bpf, returns:EPERM or ENOSYS, note:Returns EPERM if the process does not have cap_sys_boot; ENOSYS otherwise)
- 321: syscalls.CapError(linux.CAP_SYS_ADMIN), // requires cap_sys_admin for all commands
- // 322: @Syscall(Execveat), TODO(b/118901836)
- // 323: @Syscall(Userfaultfd), TODO(b/118906345)
- // 324: @Syscall(Membarrier), TODO(b/118904897)
- 325: Mlock2,
+ Table: map[uintptr]kernel.Syscall{
+ 0: syscalls.Supported("read", Read),
+ 1: syscalls.Supported("write", Write),
+ 2: syscalls.Supported("open", Open),
+ 3: syscalls.Supported("close", Close),
+ 4: syscalls.Undocumented("stat", Stat),
+ 5: syscalls.Undocumented("fstat", Fstat),
+ 6: syscalls.Undocumented("lstat", Lstat),
+ 7: syscalls.Undocumented("poll", Poll),
+ 8: syscalls.Undocumented("lseek", Lseek),
+ 9: syscalls.Undocumented("mmap", Mmap),
+ 10: syscalls.Undocumented("mprotect", Mprotect),
+ 11: syscalls.Undocumented("munmap", Munmap),
+ 12: syscalls.Undocumented("brk", Brk),
+ 13: syscalls.Undocumented("rt_sigaction", RtSigaction),
+ 14: syscalls.Undocumented("rt_sigprocmask", RtSigprocmask),
+ 15: syscalls.Undocumented("rt_sigreturn", RtSigreturn),
+ 16: syscalls.Undocumented("ioctl", Ioctl),
+ 17: syscalls.Undocumented("pread64", Pread64),
+ 18: syscalls.Undocumented("pwrite64", Pwrite64),
+ 19: syscalls.Undocumented("readv", Readv),
+ 20: syscalls.Undocumented("writev", Writev),
+ 21: syscalls.Undocumented("access", Access),
+ 22: syscalls.Undocumented("pipe", Pipe),
+ 23: syscalls.Undocumented("select", Select),
+ 24: syscalls.Undocumented("sched_yield", SchedYield),
+ 25: syscalls.Undocumented("mremap", Mremap),
+ 26: syscalls.Undocumented("msync", Msync),
+ 27: syscalls.Undocumented("mincore", Mincore),
+ 28: syscalls.Undocumented("madvise", Madvise),
+ 29: syscalls.Undocumented("shmget", Shmget),
+ 30: syscalls.Undocumented("shmat", Shmat),
+ 31: syscalls.Undocumented("shmctl", Shmctl),
+ 32: syscalls.Undocumented("dup", Dup),
+ 33: syscalls.Undocumented("dup2", Dup2),
+ 34: syscalls.Undocumented("pause", Pause),
+ 35: syscalls.Undocumented("nanosleep", Nanosleep),
+ 36: syscalls.Undocumented("getitimer", Getitimer),
+ 37: syscalls.Undocumented("alarm", Alarm),
+ 38: syscalls.Undocumented("setitimer", Setitimer),
+ 39: syscalls.Undocumented("getpid", Getpid),
+ 40: syscalls.Undocumented("sendfile", Sendfile),
+ 41: syscalls.Undocumented("socket", Socket),
+ 42: syscalls.Undocumented("connect", Connect),
+ 43: syscalls.Undocumented("accept", Accept),
+ 44: syscalls.Undocumented("sendto", SendTo),
+ 45: syscalls.Undocumented("recvfrom", RecvFrom),
+ 46: syscalls.Undocumented("sendmsg", SendMsg),
+ 47: syscalls.Undocumented("recvmsg", RecvMsg),
+ 48: syscalls.Undocumented("shutdown", Shutdown),
+ 49: syscalls.Undocumented("bind", Bind),
+ 50: syscalls.Undocumented("listen", Listen),
+ 51: syscalls.Undocumented("getsockname", GetSockName),
+ 52: syscalls.Undocumented("getpeername", GetPeerName),
+ 53: syscalls.Undocumented("socketpair", SocketPair),
+ 54: syscalls.Undocumented("setsockopt", SetSockOpt),
+ 55: syscalls.Undocumented("getsockopt", GetSockOpt),
+ 56: syscalls.Undocumented("clone", Clone),
+ 57: syscalls.Undocumented("fork", Fork),
+ 58: syscalls.Undocumented("vfork", Vfork),
+ 59: syscalls.Undocumented("execve", Execve),
+ 60: syscalls.Undocumented("exit", Exit),
+ 61: syscalls.Undocumented("wait4", Wait4),
+ 62: syscalls.Undocumented("kill", Kill),
+ 63: syscalls.Undocumented("uname", Uname),
+ 64: syscalls.Undocumented("semget", Semget),
+ 65: syscalls.Undocumented("semop", Semop),
+ 66: syscalls.Undocumented("semctl", Semctl),
+ 67: syscalls.Undocumented("shmdt", Shmdt),
+ 68: syscalls.ErrorWithEvent("msgget", syscall.ENOSYS, "", []string{"gvisor.dev/issue/135"}), // TODO(b/29354921)
+ 69: syscalls.ErrorWithEvent("msgsnd", syscall.ENOSYS, "", []string{"gvisor.dev/issue/135"}), // TODO(b/29354921)
+ 70: syscalls.ErrorWithEvent("msgrcv", syscall.ENOSYS, "", []string{"gvisor.dev/issue/135"}), // TODO(b/29354921)
+ 71: syscalls.ErrorWithEvent("msgctl", syscall.ENOSYS, "", []string{"gvisor.dev/issue/135"}), // TODO(b/29354921)
+ 72: syscalls.Undocumented("fcntl", Fcntl),
+ 73: syscalls.Undocumented("flock", Flock),
+ 74: syscalls.Undocumented("fsync", Fsync),
+ 75: syscalls.Undocumented("fdatasync", Fdatasync),
+ 76: syscalls.Undocumented("truncate", Truncate),
+ 77: syscalls.Undocumented("ftruncate", Ftruncate),
+ 78: syscalls.Undocumented("getdents", Getdents),
+ 79: syscalls.Undocumented("getcwd", Getcwd),
+ 80: syscalls.Undocumented("chdir", Chdir),
+ 81: syscalls.Undocumented("fchdir", Fchdir),
+ 82: syscalls.Undocumented("rename", Rename),
+ 83: syscalls.Undocumented("mkdir", Mkdir),
+ 84: syscalls.Undocumented("rmdir", Rmdir),
+ 85: syscalls.Undocumented("creat", Creat),
+ 86: syscalls.Undocumented("link", Link),
+ 87: syscalls.Undocumented("link", Unlink),
+ 88: syscalls.Undocumented("symlink", Symlink),
+ 89: syscalls.Undocumented("readlink", Readlink),
+ 90: syscalls.Undocumented("chmod", Chmod),
+ 91: syscalls.Undocumented("fchmod", Fchmod),
+ 92: syscalls.Undocumented("chown", Chown),
+ 93: syscalls.Undocumented("fchown", Fchown),
+ 94: syscalls.Undocumented("lchown", Lchown),
+ 95: syscalls.Undocumented("umask", Umask),
+ 96: syscalls.Undocumented("gettimeofday", Gettimeofday),
+ 97: syscalls.Undocumented("getrlimit", Getrlimit),
+ 98: syscalls.Undocumented("getrusage", Getrusage),
+ 99: syscalls.Undocumented("sysinfo", Sysinfo),
+ 100: syscalls.Undocumented("times", Times),
+ 101: syscalls.Undocumented("ptrace", Ptrace),
+ 102: syscalls.Undocumented("getuid", Getuid),
+ 103: syscalls.Undocumented("syslog", Syslog),
+ 104: syscalls.Undocumented("getgid", Getgid),
+ 105: syscalls.Undocumented("setuid", Setuid),
+ 106: syscalls.Undocumented("setgid", Setgid),
+ 107: syscalls.Undocumented("geteuid", Geteuid),
+ 108: syscalls.Undocumented("getegid", Getegid),
+ 109: syscalls.Undocumented("setpgid", Setpgid),
+ 110: syscalls.Undocumented("getppid", Getppid),
+ 111: syscalls.Undocumented("getpgrp", Getpgrp),
+ 112: syscalls.Undocumented("setsid", Setsid),
+ 113: syscalls.Undocumented("setreuid", Setreuid),
+ 114: syscalls.Undocumented("setregid", Setregid),
+ 115: syscalls.Undocumented("getgroups", Getgroups),
+ 116: syscalls.Undocumented("setgroups", Setgroups),
+ 117: syscalls.Undocumented("setresuid", Setresuid),
+ 118: syscalls.Undocumented("getresuid", Getresuid),
+ 119: syscalls.Undocumented("setresgid", Setresgid),
+ 120: syscalls.Undocumented("setresgid", Getresgid),
+ 121: syscalls.Undocumented("getpgid", Getpgid),
+ 122: syscalls.ErrorWithEvent("setfsuid", syscall.ENOSYS, "", []string{"gvisor.dev/issue/260"}), // TODO(b/112851702)
+ 123: syscalls.ErrorWithEvent("setfsgid", syscall.ENOSYS, "", []string{"gvisor.dev/issue/260"}), // TODO(b/112851702)
+ 124: syscalls.Undocumented("getsid", Getsid),
+ 125: syscalls.Undocumented("capget", Capget),
+ 126: syscalls.Undocumented("capset", Capset),
+ 127: syscalls.Undocumented("rt_sigpending", RtSigpending),
+ 128: syscalls.Undocumented("rt_sigtimedwait", RtSigtimedwait),
+ 129: syscalls.Undocumented("rt_sigqueueinfo", RtSigqueueinfo),
+ 130: syscalls.Undocumented("rt_sigsuspend", RtSigsuspend),
+ 131: syscalls.Undocumented("sigaltstack", Sigaltstack),
+ 132: syscalls.Undocumented("utime", Utime),
+ 133: syscalls.Undocumented("mknod", Mknod),
+ 134: syscalls.Error("uselib", syscall.ENOSYS, "Obsolete", nil),
+ 135: syscalls.ErrorWithEvent("personality", syscall.EINVAL, "Unable to change personality.", nil),
+ 136: syscalls.ErrorWithEvent("ustat", syscall.ENOSYS, "Needs filesystem support.", nil),
+ 137: syscalls.Undocumented("statfs", Statfs),
+ 138: syscalls.Undocumented("fstatfs", Fstatfs),
+ 139: syscalls.ErrorWithEvent("sysfs", syscall.ENOSYS, "", []string{"gvisor.dev/issue/165"}),
+ 140: syscalls.Undocumented("getpriority", Getpriority),
+ 141: syscalls.Undocumented("setpriority", Setpriority),
+ 142: syscalls.CapError("sched_setparam", linux.CAP_SYS_NICE, "", nil),
+ 143: syscalls.Undocumented("sched_getparam", SchedGetparam),
+ 144: syscalls.Undocumented("sched_setscheduler", SchedSetscheduler),
+ 145: syscalls.Undocumented("sched_getscheduler", SchedGetscheduler),
+ 146: syscalls.Undocumented("sched_get_priority_max", SchedGetPriorityMax),
+ 147: syscalls.Undocumented("sched_get_priority_min", SchedGetPriorityMin),
+ 148: syscalls.ErrorWithEvent("sched_rr_get_interval", syscall.EPERM, "", nil),
+ 149: syscalls.Undocumented("mlock", Mlock),
+ 150: syscalls.Undocumented("munlock", Munlock),
+ 151: syscalls.Undocumented("mlockall", Mlockall),
+ 152: syscalls.Undocumented("munlockall", Munlockall),
+ 153: syscalls.CapError("vhangup", linux.CAP_SYS_TTY_CONFIG, "", nil),
+ 154: syscalls.Error("modify_ldt", syscall.EPERM, "", nil),
+ 155: syscalls.Error("pivot_root", syscall.EPERM, "", nil),
+ 156: syscalls.Error("sysctl", syscall.EPERM, `syscall is "worthless"`, nil),
+ 157: syscalls.Undocumented("prctl", Prctl),
+ 158: syscalls.Undocumented("arch_prctl", ArchPrctl),
+ 159: syscalls.CapError("adjtimex", linux.CAP_SYS_TIME, "", nil),
+ 160: syscalls.Undocumented("setrlimit", Setrlimit),
+ 161: syscalls.Undocumented("chroot", Chroot),
+ 162: syscalls.Undocumented("sync", Sync),
+ 163: syscalls.CapError("acct", linux.CAP_SYS_PACCT, "", nil),
+ 164: syscalls.CapError("settimeofday", linux.CAP_SYS_TIME, "", nil),
+ 165: syscalls.Undocumented("mount", Mount),
+ 166: syscalls.Undocumented("umount2", Umount2),
+ 167: syscalls.CapError("swapon", linux.CAP_SYS_ADMIN, "", nil),
+ 168: syscalls.CapError("swapoff", linux.CAP_SYS_ADMIN, "", nil),
+ 169: syscalls.CapError("reboot", linux.CAP_SYS_BOOT, "", nil),
+ 170: syscalls.Undocumented("sethostname", Sethostname),
+ 171: syscalls.Undocumented("setdomainname", Setdomainname),
+ 172: syscalls.CapError("iopl", linux.CAP_SYS_RAWIO, "", nil),
+ 173: syscalls.CapError("ioperm", linux.CAP_SYS_RAWIO, "", nil),
+ 174: syscalls.CapError("create_module", linux.CAP_SYS_MODULE, "", nil),
+ 175: syscalls.CapError("init_module", linux.CAP_SYS_MODULE, "", nil),
+ 176: syscalls.CapError("delete_module", linux.CAP_SYS_MODULE, "", nil),
+ 177: syscalls.Error("get_kernel_syms", syscall.ENOSYS, "Not supported in > 2.6", nil),
+ 178: syscalls.Error("query_module", syscall.ENOSYS, "Not supported in > 2.6", nil),
+ 179: syscalls.CapError("quotactl", linux.CAP_SYS_ADMIN, "", nil), // requires cap_sys_admin for most operations
+ 180: syscalls.Error("nfsservctl", syscall.ENOSYS, "Does not exist > 3.1", nil),
+ 181: syscalls.Error("getpmsg", syscall.ENOSYS, "Not implemented in Linux", nil),
+ 182: syscalls.Error("putpmsg", syscall.ENOSYS, "Not implemented in Linux", nil),
+ 183: syscalls.Error("afs_syscall", syscall.ENOSYS, "Not implemented in Linux", nil),
+ 184: syscalls.Error("tuxcall", syscall.ENOSYS, "Not implemented in Linux", nil),
+ 185: syscalls.Error("security", syscall.ENOSYS, "Not implemented in Linux", nil),
+ 186: syscalls.Undocumented("gettid", Gettid),
+ 187: syscalls.ErrorWithEvent("readahead", syscall.ENOSYS, "", []string{"gvisor.dev/issue/261"}), // TODO(b/29351341)
+ 188: syscalls.ErrorWithEvent("setxattr", syscall.ENOTSUP, "Requires filesystem support", nil),
+ 189: syscalls.ErrorWithEvent("lsetxattr", syscall.ENOTSUP, "Requires filesystem support", nil),
+ 190: syscalls.ErrorWithEvent("fsetxattr", syscall.ENOTSUP, "Requires filesystem support", nil),
+ 191: syscalls.ErrorWithEvent("getxattr", syscall.ENOTSUP, "Requires filesystem support", nil),
+ 192: syscalls.ErrorWithEvent("lgetxattr", syscall.ENOTSUP, "Requires filesystem support", nil),
+ 193: syscalls.ErrorWithEvent("fgetxattr", syscall.ENOTSUP, "Requires filesystem support", nil),
+ 194: syscalls.ErrorWithEvent("listxattr", syscall.ENOTSUP, "Requires filesystem support", nil),
+ 195: syscalls.ErrorWithEvent("llistxattr", syscall.ENOTSUP, "Requires filesystem support", nil),
+ 196: syscalls.ErrorWithEvent("flistxattr", syscall.ENOTSUP, "Requires filesystem support", nil),
+ 197: syscalls.ErrorWithEvent("removexattr", syscall.ENOTSUP, "Requires filesystem support", nil),
+ 198: syscalls.ErrorWithEvent("lremovexattr", syscall.ENOTSUP, "Requires filesystem support", nil),
+ 199: syscalls.ErrorWithEvent("fremovexattr", syscall.ENOTSUP, "Requires filesystem support", nil),
+ 200: syscalls.Undocumented("tkill", Tkill),
+ 201: syscalls.Undocumented("time", Time),
+ 202: syscalls.Undocumented("futex", Futex),
+ 203: syscalls.Undocumented("sched_setaffinity", SchedSetaffinity),
+ 204: syscalls.Undocumented("sched_getaffinity", SchedGetaffinity),
+ 205: syscalls.Error("set_thread_area", syscall.ENOSYS, "Expected to return ENOSYS on 64-bit", nil),
+ 206: syscalls.Undocumented("io_setup", IoSetup),
+ 207: syscalls.Undocumented("io_destroy", IoDestroy),
+ 208: syscalls.Undocumented("io_getevents", IoGetevents),
+ 209: syscalls.Undocumented("io_submit", IoSubmit),
+ 210: syscalls.Undocumented("io_cancel", IoCancel),
+ 211: syscalls.Error("get_thread_area", syscall.ENOSYS, "Expected to return ENOSYS on 64-bit", nil),
+ 212: syscalls.CapError("lookup_dcookie", linux.CAP_SYS_ADMIN, "", nil),
+ 213: syscalls.Undocumented("epoll_create", EpollCreate),
+ 214: syscalls.ErrorWithEvent("epoll_ctl_old", syscall.ENOSYS, "Deprecated", nil),
+ 215: syscalls.ErrorWithEvent("epoll_wait_old", syscall.ENOSYS, "Deprecated", nil),
+ 216: syscalls.ErrorWithEvent("remap_file_pages", syscall.ENOSYS, "Deprecated since 3.16", nil),
+ 217: syscalls.Undocumented("getdents64", Getdents64),
+ 218: syscalls.Undocumented("set_tid_address", SetTidAddress),
+ 219: syscalls.Undocumented("restart_syscall", RestartSyscall),
+ 220: syscalls.ErrorWithEvent("semtimedop", syscall.ENOSYS, "", []string{"gvisor.dev/issue/137"}), // TODO(b/29354920)
+ 221: syscalls.Undocumented("fadvise64", Fadvise64),
+ 222: syscalls.Undocumented("timer_create", TimerCreate),
+ 223: syscalls.Undocumented("timer_settime", TimerSettime),
+ 224: syscalls.Undocumented("timer_gettime", TimerGettime),
+ 225: syscalls.Undocumented("timer_getoverrun", TimerGetoverrun),
+ 226: syscalls.Undocumented("timer_delete", TimerDelete),
+ 227: syscalls.Undocumented("clock_settime", ClockSettime),
+ 228: syscalls.Undocumented("clock_gettime", ClockGettime),
+ 229: syscalls.Undocumented("clock_getres", ClockGetres),
+ 230: syscalls.Undocumented("clock_nanosleep", ClockNanosleep),
+ 231: syscalls.Undocumented("exit_group", ExitGroup),
+ 232: syscalls.Undocumented("epoll_wait", EpollWait),
+ 233: syscalls.Undocumented("epoll_ctl", EpollCtl),
+ 234: syscalls.Undocumented("tgkill", Tgkill),
+ 235: syscalls.Undocumented("utimes", Utimes),
+ 236: syscalls.Error("vserver", syscall.ENOSYS, "Not implemented by Linux", nil),
+ 237: syscalls.PartiallySupported("mbind", Mbind, "Stub implementation. Only a single NUMA node is advertised, and mempolicy is ignored accordingly, but mbind() will succeed and has effects reflected by get_mempolicy.", []string{"gvisor.dev/issue/262"}),
+ 238: syscalls.Undocumented("set_mempolicy", SetMempolicy),
+ 239: syscalls.Undocumented("get_mempolicy", GetMempolicy),
+ 240: syscalls.ErrorWithEvent("mq_open", syscall.ENOSYS, "", []string{"gvisor.dev/issue/136"}), // TODO(b/29354921)
+ 241: syscalls.ErrorWithEvent("mq_unlink", syscall.ENOSYS, "", []string{"gvisor.dev/issue/136"}), // TODO(b/29354921)
+ 242: syscalls.ErrorWithEvent("mq_timedsend", syscall.ENOSYS, "", []string{"gvisor.dev/issue/136"}), // TODO(b/29354921)
+ 243: syscalls.ErrorWithEvent("mq_timedreceive", syscall.ENOSYS, "", []string{"gvisor.dev/issue/136"}), // TODO(b/29354921)
+ 244: syscalls.ErrorWithEvent("mq_notify", syscall.ENOSYS, "", []string{"gvisor.dev/issue/136"}), // TODO(b/29354921)
+ 245: syscalls.ErrorWithEvent("mq_getsetattr", syscall.ENOSYS, "", []string{"gvisor.dev/issue/136"}), // TODO(b/29354921)
+ 246: syscalls.CapError("kexec_load", linux.CAP_SYS_BOOT, "", nil),
+ 247: syscalls.Undocumented("waitid", Waitid),
+ 248: syscalls.Error("add_key", syscall.EACCES, "Not available to user", nil),
+ 249: syscalls.Error("request_key", syscall.EACCES, "Not available to user", nil),
+ 250: syscalls.Error("keyctl", syscall.EACCES, "Not available to user", nil),
+ 251: syscalls.CapError("ioprio_set", linux.CAP_SYS_ADMIN, "", nil), // requires cap_sys_nice or cap_sys_admin (depending)
+ 252: syscalls.CapError("ioprio_get", linux.CAP_SYS_ADMIN, "", nil), // requires cap_sys_nice or cap_sys_admin (depending)
+ 253: syscalls.Undocumented("inotify_init", InotifyInit),
+ 254: syscalls.Undocumented("inotify_add_watch", InotifyAddWatch),
+ 255: syscalls.Undocumented("inotify_rm_watch", InotifyRmWatch),
+ 256: syscalls.CapError("migrate_pages", linux.CAP_SYS_NICE, "", nil),
+ 257: syscalls.Undocumented("openat", Openat),
+ 258: syscalls.Undocumented("mkdirat", Mkdirat),
+ 259: syscalls.Undocumented("mknodat", Mknodat),
+ 260: syscalls.Undocumented("fchownat", Fchownat),
+ 261: syscalls.Undocumented("futimesat", Futimesat),
+ 262: syscalls.Undocumented("fstatat", Fstatat),
+ 263: syscalls.Undocumented("unlinkat", Unlinkat),
+ 264: syscalls.Undocumented("renameat", Renameat),
+ 265: syscalls.Undocumented("linkat", Linkat),
+ 266: syscalls.Undocumented("symlinkat", Symlinkat),
+ 267: syscalls.Undocumented("readlinkat", Readlinkat),
+ 268: syscalls.Undocumented("fchmodat", Fchmodat),
+ 269: syscalls.Undocumented("faccessat", Faccessat),
+ 270: syscalls.Undocumented("pselect", Pselect),
+ 271: syscalls.Undocumented("ppoll", Ppoll),
+ 272: syscalls.Undocumented("unshare", Unshare),
+ 273: syscalls.Error("set_robust_list", syscall.ENOSYS, "Obsolete", nil),
+ 274: syscalls.Error("get_robust_list", syscall.ENOSYS, "Obsolete", nil),
+ 275: syscalls.PartiallySupported("splice", Splice, "Stub implementation", []string{"gvisor.dev/issue/138"}), // TODO(b/29354098)
+ 276: syscalls.ErrorWithEvent("tee", syscall.ENOSYS, "", []string{"gvisor.dev/issue/138"}), // TODO(b/29354098)
+ 277: syscalls.Undocumented("sync_file_range", SyncFileRange),
+ 278: syscalls.ErrorWithEvent("vmsplice", syscall.ENOSYS, "", []string{"gvisor.dev/issue/138"}), // TODO(b/29354098)
+ 279: syscalls.CapError("move_pages", linux.CAP_SYS_NICE, "", nil), // requires cap_sys_nice (mostly)
+ 280: syscalls.Undocumented("utimensat", Utimensat),
+ 281: syscalls.Undocumented("epoll_pwait", EpollPwait),
+ 282: syscalls.ErrorWithEvent("signalfd", syscall.ENOSYS, "", []string{"gvisor.dev/issue/139"}), // TODO(b/19846426)
+ 283: syscalls.Undocumented("timerfd_create", TimerfdCreate),
+ 284: syscalls.Undocumented("eventfd", Eventfd),
+ 285: syscalls.Undocumented("fallocate", Fallocate),
+ 286: syscalls.Undocumented("timerfd_settime", TimerfdSettime),
+ 287: syscalls.Undocumented("timerfd_gettime", TimerfdGettime),
+ 288: syscalls.Undocumented("accept4", Accept4),
+ 289: syscalls.ErrorWithEvent("signalfd4", syscall.ENOSYS, "", []string{"gvisor.dev/issue/139"}), // TODO(b/19846426)
+ 290: syscalls.Undocumented("eventfd2", Eventfd2),
+ 291: syscalls.Undocumented("epoll_create1", EpollCreate1),
+ 292: syscalls.Undocumented("dup3", Dup3),
+ 293: syscalls.Undocumented("pipe2", Pipe2),
+ 294: syscalls.Undocumented("inotify_init1", InotifyInit1),
+ 295: syscalls.Undocumented("preadv", Preadv),
+ 296: syscalls.Undocumented("pwritev", Pwritev),
+ 297: syscalls.Undocumented("rt_tgsigqueueinfo", RtTgsigqueueinfo),
+ 298: syscalls.ErrorWithEvent("perf_event_open", syscall.ENODEV, "No support for perf counters", nil),
+ 299: syscalls.Undocumented("recvmmsg", RecvMMsg),
+ 300: syscalls.ErrorWithEvent("fanotify_init", syscall.ENOSYS, "Needs CONFIG_FANOTIFY", nil),
+ 301: syscalls.ErrorWithEvent("fanotify_mark", syscall.ENOSYS, "Needs CONFIG_FANOTIFY", nil),
+ 302: syscalls.Undocumented("prlimit64", Prlimit64),
+ 303: syscalls.ErrorWithEvent("name_to_handle_at", syscall.EOPNOTSUPP, "Needs filesystem support", nil),
+ 304: syscalls.ErrorWithEvent("open_by_handle_at", syscall.EOPNOTSUPP, "Needs filesystem support", nil),
+ 305: syscalls.CapError("clock_adjtime", linux.CAP_SYS_TIME, "", nil),
+ 306: syscalls.Undocumented("syncfs", Syncfs),
+ 307: syscalls.Undocumented("sendmmsg", SendMMsg),
+ 308: syscalls.ErrorWithEvent("setns", syscall.EOPNOTSUPP, "Needs filesystem support", []string{"gvisor.dev/issue/140"}), // TODO(b/29354995)
+ 309: syscalls.Undocumented("getcpu", Getcpu),
+ 310: syscalls.ErrorWithEvent("process_vm_readv", syscall.ENOSYS, "", []string{"gvisor.dev/issue/158"}),
+ 311: syscalls.ErrorWithEvent("process_vm_writev", syscall.ENOSYS, "", []string{"gvisor.dev/issue/158"}),
+ 312: syscalls.CapError("kcmp", linux.CAP_SYS_PTRACE, "", nil),
+ 313: syscalls.CapError("finit_module", linux.CAP_SYS_MODULE, "", nil),
+ 314: syscalls.ErrorWithEvent("sched_setattr", syscall.ENOSYS, "gVisor does not implement a scheduler.", []string{"gvisor.dev/issue/264"}), // TODO(b/118902272)
+ 315: syscalls.ErrorWithEvent("sched_getattr", syscall.ENOSYS, "gVisor does not implement a scheduler.", []string{"gvisor.dev/issue/264"}), // TODO(b/118902272)
+ 316: syscalls.ErrorWithEvent("renameat2", syscall.ENOSYS, "", []string{"gvisor.dev/issue/263"}), // TODO(b/118902772)
+ 317: syscalls.Undocumented("seccomp", Seccomp),
+ 318: syscalls.Undocumented("getrandom", GetRandom),
+ 319: syscalls.Undocumented("memfd_create", MemfdCreate),
+ 320: syscalls.CapError("kexec_file_load", linux.CAP_SYS_BOOT, "", nil),
+ 321: syscalls.CapError("bpf", linux.CAP_SYS_ADMIN, "", nil),
+ 322: syscalls.ErrorWithEvent("execveat", syscall.ENOSYS, "", []string{"gvisor.dev/issue/265"}), // TODO(b/118901836)
+ 323: syscalls.ErrorWithEvent("userfaultfd", syscall.ENOSYS, "", []string{"gvisor.dev/issue/266"}), // TODO(b/118906345)
+ 324: syscalls.ErrorWithEvent("membarrier", syscall.ENOSYS, "", []string{"gvisor.dev/issue/267"}), // TODO(b/118904897)
+ 325: syscalls.Undocumented("mlock2", Mlock2),
+
// Syscalls after 325 are "backports" from versions of Linux after 4.4.
- // 326: @Syscall(CopyFileRange),
- 327: Preadv2,
- 328: Pwritev2,
+ 326: syscalls.ErrorWithEvent("copy_file_range", syscall.ENOSYS, "", nil),
+ 327: syscalls.Undocumented("preadv2", Preadv2),
+ 328: syscalls.Undocumented("pwritev2", Pwritev2),
},
Emulate: map[usermem.Addr]uintptr{
diff --git a/pkg/sentry/syscalls/syscalls.go b/pkg/sentry/syscalls/syscalls.go
index 5d10b3824..48c114232 100644
--- a/pkg/sentry/syscalls/syscalls.go
+++ b/pkg/sentry/syscalls/syscalls.go
@@ -25,37 +25,97 @@
package syscalls
import (
+ "fmt"
+ "syscall"
+
"gvisor.googlesource.com/gvisor/pkg/abi/linux"
"gvisor.googlesource.com/gvisor/pkg/sentry/arch"
"gvisor.googlesource.com/gvisor/pkg/sentry/kernel"
"gvisor.googlesource.com/gvisor/pkg/syserror"
)
+// Supported returns a syscall that is fully supported.
+func Supported(name string, fn kernel.SyscallFn) kernel.Syscall {
+ return kernel.Syscall{
+ Name: name,
+ Fn: fn,
+ SupportLevel: kernel.SupportFull,
+ Note: "Full Support",
+ }
+}
+
+// Undocumented returns a syscall that is undocumented.
+func Undocumented(name string, fn kernel.SyscallFn) kernel.Syscall {
+ return kernel.Syscall{
+ Name: name,
+ Fn: fn,
+ SupportLevel: kernel.SupportUndocumented,
+ }
+}
+
+// PartiallySupported returns a syscall that has a partial implementation.
+func PartiallySupported(name string, fn kernel.SyscallFn, note string, urls []string) kernel.Syscall {
+ return kernel.Syscall{
+ Name: name,
+ Fn: fn,
+ SupportLevel: kernel.SupportPartial,
+ Note: note,
+ URLs: urls,
+ }
+}
+
// Error returns a syscall handler that will always give the passed error.
-func Error(err error) kernel.SyscallFn {
- return func(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) {
- return 0, nil, err
+func Error(name string, err syscall.Errno, note string, urls []string) kernel.Syscall {
+ if note != "" {
+ note = note + "; "
+ }
+ return kernel.Syscall{
+ Name: name,
+ Fn: func(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) {
+ return 0, nil, err
+ },
+ SupportLevel: kernel.SupportUnimplemented,
+ Note: fmt.Sprintf("%sReturns %q", note, err.Error()),
+ URLs: urls,
}
}
// ErrorWithEvent gives a syscall function that sends an unimplemented
// syscall event via the event channel and returns the passed error.
-func ErrorWithEvent(err error) kernel.SyscallFn {
- return func(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) {
- t.Kernel().EmitUnimplementedEvent(t)
- return 0, nil, err
+func ErrorWithEvent(name string, err syscall.Errno, note string, urls []string) kernel.Syscall {
+ if note != "" {
+ note = note + "; "
+ }
+ return kernel.Syscall{
+ Name: name,
+ Fn: func(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) {
+ t.Kernel().EmitUnimplementedEvent(t)
+ return 0, nil, err
+ },
+ SupportLevel: kernel.SupportUnimplemented,
+ Note: fmt.Sprintf("%sReturns %q", note, err.Error()),
+ URLs: urls,
}
}
// CapError gives a syscall function that checks for capability c. If the task
// has the capability, it returns ENOSYS, otherwise EPERM. To unprivileged
// tasks, it will seem like there is an implementation.
-func CapError(c linux.Capability) kernel.SyscallFn {
- return func(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) {
- if !t.HasCapability(c) {
- return 0, nil, syserror.EPERM
- }
- t.Kernel().EmitUnimplementedEvent(t)
- return 0, nil, syserror.ENOSYS
+func CapError(name string, c linux.Capability, note string, urls []string) kernel.Syscall {
+ if note != "" {
+ note = note + "; "
+ }
+ return kernel.Syscall{
+ Name: name,
+ Fn: func(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) {
+ if !t.HasCapability(c) {
+ return 0, nil, syserror.EPERM
+ }
+ t.Kernel().EmitUnimplementedEvent(t)
+ return 0, nil, syserror.ENOSYS
+ },
+ SupportLevel: kernel.SupportUnimplemented,
+ Note: fmt.Sprintf("%sReturns %q if the process does not have %s; %q otherwise", note, syserror.EPERM, c.String(), syserror.ENOSYS),
+ URLs: urls,
}
}
diff --git a/runsc/cmd/BUILD b/runsc/cmd/BUILD
index 173b7671e..df6af0ced 100644
--- a/runsc/cmd/BUILD
+++ b/runsc/cmd/BUILD
@@ -18,6 +18,7 @@ go_library(
"events.go",
"exec.go",
"gofer.go",
+ "help.go",
"kill.go",
"list.go",
"path.go",
@@ -29,6 +30,7 @@ go_library(
"spec.go",
"start.go",
"state.go",
+ "syscalls.go",
"wait.go",
],
importpath = "gvisor.googlesource.com/gvisor/runsc/cmd",
@@ -39,6 +41,7 @@ go_library(
"//pkg/log",
"//pkg/p9",
"//pkg/sentry/control",
+ "//pkg/sentry/kernel",
"//pkg/sentry/kernel/auth",
"//pkg/unet",
"//pkg/urpc",
diff --git a/runsc/cmd/help.go b/runsc/cmd/help.go
new file mode 100644
index 000000000..ff4f901cb
--- /dev/null
+++ b/runsc/cmd/help.go
@@ -0,0 +1,126 @@
+// Copyright 2018 Google LLC
+//
+// 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 cmd
+
+import (
+ "context"
+ "fmt"
+
+ "flag"
+ "github.com/google/subcommands"
+)
+
+// NewHelp returns a help command for the given commander.
+func NewHelp(cdr *subcommands.Commander) *Help {
+ return &Help{
+ cdr: cdr,
+ }
+}
+
+// Help implements subcommands.Command for the "help" command. The 'help'
+// command prints help for commands registered to a Commander but also allows for
+// registering additional help commands that print other documentation.
+type Help struct {
+ cdr *subcommands.Commander
+ commands []subcommands.Command
+ help bool
+}
+
+// Name implements subcommands.Command.Name.
+func (*Help) Name() string {
+ return "help"
+}
+
+// Synopsis implements subcommands.Command.Synopsis.
+func (*Help) Synopsis() string {
+ return "Print help documentation."
+}
+
+// Usage implements subcommands.Command.Usage.
+func (*Help) Usage() string {
+ return `help [<subcommand>]:
+ With an argument, prints detailed information on the use of
+ the specified topic or subcommand. With no argument, print a list of
+ all commands and a brief description of each.
+`
+}
+
+// SetFlags implements subcommands.Command.SetFlags.
+func (h *Help) SetFlags(f *flag.FlagSet) {}
+
+// Execute implements subcommands.Command.Execute.
+func (h *Help) Execute(ctx context.Context, f *flag.FlagSet, args ...interface{}) subcommands.ExitStatus {
+ switch f.NArg() {
+ case 0:
+ fmt.Fprintf(h.cdr.Output, "Usage: %s <flags> <subcommand> <subcommand args>\n\n", h.cdr.Name())
+ fmt.Fprintf(h.cdr.Output, `runsc is a command line client for running applications packaged in the Open
+Container Initiative (OCI) format. Applications run by runsc are run in an
+isolated gVisor sandbox that emulates a Linux environment.
+
+gVisor is a user-space kernel, written in Go, that implements a substantial
+portion of the Linux system call interface. It provides an additional layer
+of isolation between running applications and the host operating system.
+
+Functionality is provided by subcommands. For additonal help on individual
+subcommands use "%s %s <subcommand>".
+
+`, h.cdr.Name(), h.Name())
+ h.cdr.VisitGroups(func(g *subcommands.CommandGroup) {
+ h.cdr.ExplainGroup(h.cdr.Output, g)
+ })
+
+ fmt.Fprintf(h.cdr.Output, "Additional help topics (Use \"%s %s <topic>\" to see help on the topic):\n", h.cdr.Name(), h.Name())
+ for _, cmd := range h.commands {
+ fmt.Fprintf(h.cdr.Output, "\t%-15s %s\n", cmd.Name(), cmd.Synopsis())
+ }
+ fmt.Fprintf(h.cdr.Output, "\nUse \"%s flags\" for a list of top-level flags\n", h.cdr.Name())
+ return subcommands.ExitSuccess
+ default:
+ // Look for commands registered to the commander and print help explanation if found.
+ found := false
+ h.cdr.VisitCommands(func(g *subcommands.CommandGroup, cmd subcommands.Command) {
+ if f.Arg(0) == cmd.Name() {
+ h.cdr.ExplainCommand(h.cdr.Output, cmd)
+ found = true
+ }
+ })
+ if found {
+ return subcommands.ExitSuccess
+ }
+
+ // Next check commands registered to the help command.
+ for _, cmd := range h.commands {
+ if f.Arg(0) == cmd.Name() {
+ fs := flag.NewFlagSet(f.Arg(0), flag.ContinueOnError)
+ fs.Usage = func() { h.cdr.ExplainCommand(h.cdr.Error, cmd) }
+ cmd.SetFlags(fs)
+ if fs.Parse(f.Args()[1:]) != nil {
+ return subcommands.ExitUsageError
+ }
+ return cmd.Execute(ctx, f, args...)
+ }
+ }
+
+ fmt.Fprintf(h.cdr.Error, "Subcommand %s not understood\n", f.Arg(0))
+ }
+
+ f.Usage()
+ return subcommands.ExitUsageError
+}
+
+// Register registers a new help command.
+func (h *Help) Register(cmd subcommands.Command) {
+ h.commands = append(h.commands, cmd)
+}
diff --git a/runsc/cmd/syscalls.go b/runsc/cmd/syscalls.go
new file mode 100644
index 000000000..9c8a66490
--- /dev/null
+++ b/runsc/cmd/syscalls.go
@@ -0,0 +1,347 @@
+// Copyright 2019 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 cmd
+
+import (
+ "context"
+ "encoding/csv"
+ "encoding/json"
+ "fmt"
+ "io"
+ "os"
+ "sort"
+ "strconv"
+ "text/tabwriter"
+
+ "flag"
+ "github.com/google/subcommands"
+ "gvisor.googlesource.com/gvisor/pkg/sentry/kernel"
+)
+
+// Syscalls implements subcommands.Command for the "syscalls" command.
+type Syscalls struct {
+ output string
+ os string
+ arch string
+}
+
+// CompatibilityInfo is a map of system and architecture to compatibility doc.
+// Maps operating system to architecture to ArchInfo.
+type CompatibilityInfo map[string]map[string]ArchInfo
+
+// ArchInfo is compatbility doc for an architecture.
+type ArchInfo struct {
+ // Syscalls maps syscall number for the architecture to the doc.
+ Syscalls map[uintptr]SyscallDoc `json:"syscalls"`
+}
+
+// SyscallDoc represents a single item of syscall documentation.
+type SyscallDoc struct {
+ Name string `json:"name"`
+ num uintptr
+
+ Support string `json:"support"`
+ Note string `json:"note,omitempty"`
+ URLs []string `json:"urls,omitempty"`
+}
+
+type outputFunc func(io.Writer, CompatibilityInfo) error
+
+var (
+ // The string name to use for printing compatibility for all OSes.
+ osAll = "all"
+
+ // The string name to use for printing compatibility for all architectures.
+ archAll = "all"
+
+ // A map of OS name to map of architecture name to syscall table.
+ syscallTableMap = make(map[string]map[string]*kernel.SyscallTable)
+
+ // A map of output type names to output functions.
+ outputMap = map[string]outputFunc{
+ "table": outputTable,
+ "json": outputJSON,
+ "csv": outputCSV,
+ }
+)
+
+// Name implements subcommands.Command.Name.
+func (*Syscalls) Name() string {
+ return "syscalls"
+}
+
+// Synopsis implements subcommands.Command.Synopsis.
+func (*Syscalls) Synopsis() string {
+ return "Print compatibility information for syscalls."
+}
+
+// Usage implements subcommands.Command.Usage.
+func (*Syscalls) Usage() string {
+ return `syscalls [options] - Print compatibility information for syscalls.
+`
+}
+
+// SetFlags implements subcommands.Command.SetFlags.
+func (s *Syscalls) SetFlags(f *flag.FlagSet) {
+ f.StringVar(&s.output, "o", "table", "Output format (table, csv, json).")
+ f.StringVar(&s.os, "os", osAll, "The OS (e.g. linux)")
+ f.StringVar(&s.arch, "arch", archAll, "The CPU architecture (e.g. amd64).")
+}
+
+// Execute implements subcommands.Command.Execute.
+func (s *Syscalls) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) subcommands.ExitStatus {
+ out, ok := outputMap[s.output]
+ if !ok {
+ Fatalf("Unsupported output format %q", s.output)
+ }
+
+ // Build map of all supported architectures.
+ tables := kernel.SyscallTables()
+ for _, t := range tables {
+ osMap, ok := syscallTableMap[t.OS.String()]
+ if !ok {
+ osMap = make(map[string]*kernel.SyscallTable)
+ syscallTableMap[t.OS.String()] = osMap
+ }
+ osMap[t.Arch.String()] = t
+ }
+
+ // Build a map of the architectures we want to output.
+ info, err := getCompatibilityInfo(s.os, s.arch)
+ if err != nil {
+ Fatalf("%v", err)
+ }
+
+ if err := out(os.Stdout, info); err != nil {
+ Fatalf("Error writing output: %v", err)
+ }
+
+ return subcommands.ExitSuccess
+}
+
+// getCompatibilityInfo returns compatibility info for the given OS name and
+// architecture name. Supports the special name 'all' for OS and architecture that
+// specifies that all supported OSes or architectures should be included.
+func getCompatibilityInfo(osName string, archName string) (CompatibilityInfo, error) {
+ info := CompatibilityInfo(make(map[string]map[string]ArchInfo))
+ if osName == osAll {
+ // Special processing for the 'all' OS name.
+ for osName, _ := range syscallTableMap {
+ info[osName] = make(map[string]ArchInfo)
+ // osName is a specific OS name.
+ if err := addToCompatibilityInfo(info, osName, archName); err != nil {
+ return info, err
+ }
+ }
+ } else {
+ // osName is a specific OS name.
+ info[osName] = make(map[string]ArchInfo)
+ if err := addToCompatibilityInfo(info, osName, archName); err != nil {
+ return info, err
+ }
+ }
+
+ return info, nil
+}
+
+// addToCompatibilityInfo adds ArchInfo for the given specific OS name and
+// architecture name. Supports the special architecture name 'all' to specify
+// that all supported architectures for the OS should be included.
+func addToCompatibilityInfo(info CompatibilityInfo, osName string, archName string) error {
+ if archName == archAll {
+ // Special processing for the 'all' architecture name.
+ for archName, _ := range syscallTableMap[osName] {
+ archInfo, err := getArchInfo(osName, archName)
+ if err != nil {
+ return err
+ }
+ info[osName][archName] = archInfo
+ }
+ } else {
+ // archName is a specific architecture name.
+ archInfo, err := getArchInfo(osName, archName)
+ if err != nil {
+ return err
+ }
+ info[osName][archName] = archInfo
+ }
+
+ return nil
+}
+
+// getArchInfo returns compatibility info for a specific OS and architecture.
+func getArchInfo(osName string, archName string) (ArchInfo, error) {
+ info := ArchInfo{}
+ info.Syscalls = make(map[uintptr]SyscallDoc)
+
+ t, ok := syscallTableMap[osName][archName]
+ if !ok {
+ return info, fmt.Errorf("syscall table for %s/%s not found", osName, archName)
+ }
+
+ for num, sc := range t.Table {
+ info.Syscalls[num] = SyscallDoc{
+ Name: sc.Name,
+ num: num,
+ Support: sc.SupportLevel.String(),
+ Note: sc.Note,
+ URLs: sc.URLs,
+ }
+ }
+
+ return info, nil
+}
+
+// outputTable outputs the syscall info in tabular format.
+func outputTable(w io.Writer, info CompatibilityInfo) error {
+ tw := tabwriter.NewWriter(w, 0, 0, 2, ' ', 0)
+
+ // Linux
+ for osName, osInfo := range info {
+ for archName, archInfo := range osInfo {
+ // Print the OS/arch
+ fmt.Fprintf(w, "%s/%s:\n\n", osName, archName)
+
+ // Sort the syscalls for output in the table.
+ sortedCalls := []SyscallDoc{}
+ for _, sc := range archInfo.Syscalls {
+ sortedCalls = append(sortedCalls, sc)
+ }
+ sort.Slice(sortedCalls, func(i, j int) bool {
+ return sortedCalls[i].num < sortedCalls[j].num
+ })
+
+ // Write the header
+ _, err := fmt.Fprintf(tw, "%s\t%s\t%s\t%s\n",
+ "NUM",
+ "NAME",
+ "SUPPORT",
+ "NOTE",
+ )
+ if err != nil {
+ return err
+ }
+
+ // Write each syscall entry
+ for _, sc := range sortedCalls {
+ _, err = fmt.Fprintf(tw, "%s\t%s\t%s\t%s\n",
+ strconv.FormatInt(int64(sc.num), 10),
+ sc.Name,
+ sc.Support,
+ sc.Note,
+ )
+ if err != nil {
+ return err
+ }
+ // Add issue urls to note.
+ for _, url := range sc.URLs {
+ _, err = fmt.Fprintf(tw, "%s\t%s\t%s\tSee: %s\t\n",
+ "",
+ "",
+ "",
+ url,
+ )
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ err = tw.Flush()
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ return nil
+}
+
+// outputJSON outputs the syscall info in JSON format.
+func outputJSON(w io.Writer, info CompatibilityInfo) error {
+ e := json.NewEncoder(w)
+ e.SetIndent("", " ")
+ return e.Encode(info)
+}
+
+// numberedRow is aCSV row annotated by syscall number (used for sorting)
+type numberedRow struct {
+ num uintptr
+ row []string
+}
+
+// outputCSV outputs the syscall info in tabular format.
+func outputCSV(w io.Writer, info CompatibilityInfo) error {
+ csvWriter := csv.NewWriter(w)
+
+ // Linux
+ for osName, osInfo := range info {
+ for archName, archInfo := range osInfo {
+ // Sort the syscalls for output in the table.
+ sortedCalls := []numberedRow{}
+ for _, sc := range archInfo.Syscalls {
+ // Add issue urls to note.
+ note := sc.Note
+ for _, url := range sc.URLs {
+ note = fmt.Sprintf("%s\nSee: %s", note, url)
+ }
+
+ sortedCalls = append(sortedCalls, numberedRow{
+ num: sc.num,
+ row: []string{
+ osName,
+ archName,
+ strconv.FormatInt(int64(sc.num), 10),
+ sc.Name,
+ sc.Support,
+ note,
+ },
+ })
+ }
+ sort.Slice(sortedCalls, func(i, j int) bool {
+ return sortedCalls[i].num < sortedCalls[j].num
+ })
+
+ // Write the header
+ err := csvWriter.Write([]string{
+ "OS",
+ "Arch",
+ "Num",
+ "Name",
+ "Support",
+ "Note",
+ })
+ if err != nil {
+ return err
+ }
+
+ // Write each syscall entry
+ for _, sc := range sortedCalls {
+ err = csvWriter.Write(sc.row)
+ if err != nil {
+ return err
+ }
+ }
+
+ csvWriter.Flush()
+ err = csvWriter.Error()
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ return nil
+}
diff --git a/runsc/main.go b/runsc/main.go
index 6f8e6e378..a214f6ba0 100644
--- a/runsc/main.go
+++ b/runsc/main.go
@@ -76,7 +76,9 @@ var (
func main() {
// Help and flags commands are generated automatically.
- subcommands.Register(subcommands.HelpCommand(), "")
+ help := cmd.NewHelp(subcommands.DefaultCommander)
+ help.Register(new(cmd.Syscalls))
+ subcommands.Register(help, "")
subcommands.Register(subcommands.FlagsCommand(), "")
// Register user-facing runsc commands.