github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/syscalls/syscalls.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package syscalls is the interface from the application to the kernel. 16 // Traditionally, syscalls is the interface that is used by applications to 17 // request services from the kernel of a operating system. We provide a 18 // user-mode kernel that needs to handle those requests coming from unmodified 19 // applications. Therefore, we still use the term "syscalls" to denote this 20 // interface. 21 // 22 // Note that the stubs in this package may merely provide the interface, not 23 // the actual implementation. It just makes writing syscall stubs 24 // straightforward. 25 package syscalls 26 27 import ( 28 "fmt" 29 30 "github.com/SagerNet/gvisor/pkg/abi/linux" 31 "github.com/SagerNet/gvisor/pkg/errors/linuxerr" 32 "github.com/SagerNet/gvisor/pkg/sentry/arch" 33 "github.com/SagerNet/gvisor/pkg/sentry/kernel" 34 "github.com/SagerNet/gvisor/pkg/syserror" 35 ) 36 37 // Supported returns a syscall that is fully supported. 38 func Supported(name string, fn kernel.SyscallFn) kernel.Syscall { 39 return kernel.Syscall{ 40 Name: name, 41 Fn: fn, 42 SupportLevel: kernel.SupportFull, 43 Note: "Fully Supported.", 44 } 45 } 46 47 // PartiallySupported returns a syscall that has a partial implementation. 48 func PartiallySupported(name string, fn kernel.SyscallFn, note string, urls []string) kernel.Syscall { 49 return kernel.Syscall{ 50 Name: name, 51 Fn: fn, 52 SupportLevel: kernel.SupportPartial, 53 Note: note, 54 URLs: urls, 55 } 56 } 57 58 // Error returns a syscall handler that will always give the passed error. 59 func Error(name string, err error, note string, urls []string) kernel.Syscall { 60 if note != "" { 61 note = note + "; " 62 } 63 return kernel.Syscall{ 64 Name: name, 65 Fn: func(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 66 return 0, nil, err 67 }, 68 SupportLevel: kernel.SupportUnimplemented, 69 Note: fmt.Sprintf("%sReturns %q.", note, err.Error()), 70 URLs: urls, 71 } 72 } 73 74 // ErrorWithEvent gives a syscall function that sends an unimplemented 75 // syscall event via the event channel and returns the passed error. 76 func ErrorWithEvent(name string, err error, note string, urls []string) kernel.Syscall { 77 if note != "" { 78 note = note + "; " 79 } 80 return kernel.Syscall{ 81 Name: name, 82 Fn: func(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 83 t.Kernel().EmitUnimplementedEvent(t) 84 return 0, nil, err 85 }, 86 SupportLevel: kernel.SupportUnimplemented, 87 Note: fmt.Sprintf("%sReturns %q.", note, err.Error()), 88 URLs: urls, 89 } 90 } 91 92 // CapError gives a syscall function that checks for capability c. If the task 93 // has the capability, it returns ENOSYS, otherwise EPERM. To unprivileged 94 // tasks, it will seem like there is an implementation. 95 func CapError(name string, c linux.Capability, note string, urls []string) kernel.Syscall { 96 if note != "" { 97 note = note + "; " 98 } 99 return kernel.Syscall{ 100 Name: name, 101 Fn: func(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 102 if !t.HasCapability(c) { 103 return 0, nil, linuxerr.EPERM 104 } 105 t.Kernel().EmitUnimplementedEvent(t) 106 return 0, nil, syserror.ENOSYS 107 }, 108 SupportLevel: kernel.SupportUnimplemented, 109 Note: fmt.Sprintf("%sReturns %q if the process does not have %s; %q otherwise.", note, linuxerr.EPERM, c.String(), syserror.ENOSYS), 110 URLs: urls, 111 } 112 }