github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/syserr/syserr.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 syserr contains sandbox-internal errors. These errors are distinct 16 // from both the errors returned by host system calls and the errors returned 17 // to sandboxed applications. 18 package syserr 19 20 import ( 21 "fmt" 22 23 "golang.org/x/sys/unix" 24 "github.com/SagerNet/gvisor/pkg/abi/linux/errno" 25 "github.com/SagerNet/gvisor/pkg/errors" 26 "github.com/SagerNet/gvisor/pkg/errors/linuxerr" 27 "github.com/SagerNet/gvisor/pkg/syserror" 28 ) 29 30 // Error represents an internal error. 31 type Error struct { 32 // message is the human readable form of this Error. 33 message string 34 35 // noTranslation indicates that this Error cannot be translated to a 36 // errno.Errno. 37 noTranslation bool 38 39 // errno is the errno.Errno this Error should be translated to. 40 errno errno.Errno 41 } 42 43 // New creates a new Error and adds a translation for it. 44 // 45 // New must only be called at init. 46 func New(message string, linuxTranslation errno.Errno) *Error { 47 err := &Error{message: message, errno: linuxTranslation} 48 49 // TODO(b/34162363): Remove this. 50 if int(err.errno) >= len(linuxBackwardsTranslations) { 51 panic(fmt.Sprint("invalid errno: ", err.errno)) 52 } 53 54 e := error(unix.Errno(err.errno)) 55 // syserror.ErrWouldBlock gets translated to linuxerr.EWOULDBLOCK and 56 // enables proper blocking semantics. This should temporary address the 57 // class of blocking bugs that keep popping up with the current state of 58 // the error space. 59 if err.errno == linuxerr.EWOULDBLOCK.Errno() { 60 e = syserror.ErrWouldBlock 61 } 62 linuxBackwardsTranslations[err.errno] = linuxBackwardsTranslation{err: e, ok: true} 63 64 return err 65 } 66 67 // NewDynamic creates a new error with a dynamic error message and an errno 68 // translation. 69 // 70 // NewDynamic should only be used sparingly and not be used for static error 71 // messages. Errors with static error messages should be declared with New as 72 // global variables. 73 func NewDynamic(message string, linuxTranslation errno.Errno) *Error { 74 return &Error{message: message, errno: linuxTranslation} 75 } 76 77 // NewWithoutTranslation creates a new Error. If translation is attempted on 78 // the error, translation will fail. 79 // 80 // NewWithoutTranslation may be called at any time, but static errors should 81 // be declared as global variables and dynamic errors should be used sparingly. 82 func NewWithoutTranslation(message string) *Error { 83 return &Error{message: message, noTranslation: true} 84 } 85 86 func newWithHost(message string, linuxTranslation errno.Errno, hostErrno unix.Errno) *Error { 87 e := New(message, linuxTranslation) 88 addLinuxHostTranslation(hostErrno, e) 89 return e 90 } 91 92 // String implements fmt.Stringer.String. 93 func (e *Error) String() string { 94 if e == nil { 95 return "<nil>" 96 } 97 return e.message 98 } 99 100 type linuxBackwardsTranslation struct { 101 err error 102 ok bool 103 } 104 105 // TODO(b/34162363): Remove this. 106 var linuxBackwardsTranslations [maxErrno]linuxBackwardsTranslation 107 108 // ToError translates an Error to a corresponding error value. 109 // 110 // TODO(b/34162363): Remove this. 111 func (e *Error) ToError() error { 112 if e == nil { 113 return nil 114 } 115 if e.noTranslation { 116 panic(fmt.Sprintf("error %q does not support translation", e.message)) 117 } 118 err := int(e.errno) 119 if err == errno.NOERRNO { 120 return nil 121 } 122 if err >= len(linuxBackwardsTranslations) || !linuxBackwardsTranslations[err].ok { 123 panic(fmt.Sprintf("unknown error %q (%d)", e.message, err)) 124 } 125 return linuxBackwardsTranslations[err].err 126 } 127 128 // ToLinux converts the Error to a Linux ABI error that can be returned to the 129 // application. 130 func (e *Error) ToLinux() errno.Errno { 131 if e.noTranslation { 132 panic(fmt.Sprintf("No Linux ABI translation available for %q", e.message)) 133 } 134 return e.errno 135 } 136 137 // TODO(b/34162363): Remove or replace most of these errors. 138 // 139 // Some of the errors should be replaced with package specific errors and 140 // others should be removed entirely. 141 var ( 142 ErrNotPermitted = newWithHost("operation not permitted", errno.EPERM, unix.EPERM) 143 ErrNoFileOrDir = newWithHost("no such file or directory", errno.ENOENT, unix.ENOENT) 144 ErrNoProcess = newWithHost("no such process", errno.ESRCH, unix.ESRCH) 145 ErrInterrupted = newWithHost("interrupted system call", errno.EINTR, unix.EINTR) 146 ErrIO = newWithHost("I/O error", errno.EIO, unix.EIO) 147 ErrDeviceOrAddress = newWithHost("no such device or address", errno.ENXIO, unix.ENXIO) 148 ErrTooManyArgs = newWithHost("argument list too long", errno.E2BIG, unix.E2BIG) 149 ErrEcec = newWithHost("exec format error", errno.ENOEXEC, unix.ENOEXEC) 150 ErrBadFD = newWithHost("bad file number", errno.EBADF, unix.EBADF) 151 ErrNoChild = newWithHost("no child processes", errno.ECHILD, unix.ECHILD) 152 ErrTryAgain = newWithHost("try again", errno.EAGAIN, unix.EAGAIN) 153 ErrNoMemory = newWithHost("out of memory", errno.ENOMEM, unix.ENOMEM) 154 ErrPermissionDenied = newWithHost("permission denied", errno.EACCES, unix.EACCES) 155 ErrBadAddress = newWithHost("bad address", errno.EFAULT, unix.EFAULT) 156 ErrNotBlockDevice = newWithHost("block device required", errno.ENOTBLK, unix.ENOTBLK) 157 ErrBusy = newWithHost("device or resource busy", errno.EBUSY, unix.EBUSY) 158 ErrExists = newWithHost("file exists", errno.EEXIST, unix.EEXIST) 159 ErrCrossDeviceLink = newWithHost("cross-device link", errno.EXDEV, unix.EXDEV) 160 ErrNoDevice = newWithHost("no such device", errno.ENODEV, unix.ENODEV) 161 ErrNotDir = newWithHost("not a directory", errno.ENOTDIR, unix.ENOTDIR) 162 ErrIsDir = newWithHost("is a directory", errno.EISDIR, unix.EISDIR) 163 ErrInvalidArgument = newWithHost("invalid argument", errno.EINVAL, unix.EINVAL) 164 ErrFileTableOverflow = newWithHost("file table overflow", errno.ENFILE, unix.ENFILE) 165 ErrTooManyOpenFiles = newWithHost("too many open files", errno.EMFILE, unix.EMFILE) 166 ErrNotTTY = newWithHost("not a typewriter", errno.ENOTTY, unix.ENOTTY) 167 ErrTestFileBusy = newWithHost("text file busy", errno.ETXTBSY, unix.ETXTBSY) 168 ErrFileTooBig = newWithHost("file too large", errno.EFBIG, unix.EFBIG) 169 ErrNoSpace = newWithHost("no space left on device", errno.ENOSPC, unix.ENOSPC) 170 ErrIllegalSeek = newWithHost("illegal seek", errno.ESPIPE, unix.ESPIPE) 171 ErrReadOnlyFS = newWithHost("read-only file system", errno.EROFS, unix.EROFS) 172 ErrTooManyLinks = newWithHost("too many links", errno.EMLINK, unix.EMLINK) 173 ErrBrokenPipe = newWithHost("broken pipe", errno.EPIPE, unix.EPIPE) 174 ErrDomain = newWithHost("math argument out of domain of func", errno.EDOM, unix.EDOM) 175 ErrRange = newWithHost("math result not representable", errno.ERANGE, unix.ERANGE) 176 ErrDeadlock = newWithHost("resource deadlock would occur", errno.EDEADLOCK, unix.EDEADLOCK) 177 ErrNameTooLong = newWithHost("file name too long", errno.ENAMETOOLONG, unix.ENAMETOOLONG) 178 ErrNoLocksAvailable = newWithHost("no record locks available", errno.ENOLCK, unix.ENOLCK) 179 ErrInvalidSyscall = newWithHost("invalid system call number", errno.ENOSYS, unix.ENOSYS) 180 ErrDirNotEmpty = newWithHost("directory not empty", errno.ENOTEMPTY, unix.ENOTEMPTY) 181 ErrLinkLoop = newWithHost("too many symbolic links encountered", errno.ELOOP, unix.ELOOP) 182 ErrNoMessage = newWithHost("no message of desired type", errno.ENOMSG, unix.ENOMSG) 183 ErrIdentifierRemoved = newWithHost("identifier removed", errno.EIDRM, unix.EIDRM) 184 ErrChannelOutOfRange = newWithHost("channel number out of range", errno.ECHRNG, unix.ECHRNG) 185 ErrLevelTwoNotSynced = newWithHost("level 2 not synchronized", errno.EL2NSYNC, unix.EL2NSYNC) 186 ErrLevelThreeHalted = newWithHost("level 3 halted", errno.EL3HLT, unix.EL3HLT) 187 ErrLevelThreeReset = newWithHost("level 3 reset", errno.EL3RST, unix.EL3RST) 188 ErrLinkNumberOutOfRange = newWithHost("link number out of range", errno.ELNRNG, unix.ELNRNG) 189 ErrProtocolDriverNotAttached = newWithHost("protocol driver not attached", errno.EUNATCH, unix.EUNATCH) 190 ErrNoCSIAvailable = newWithHost("no CSI structure available", errno.ENOCSI, unix.ENOCSI) 191 ErrLevelTwoHalted = newWithHost("level 2 halted", errno.EL2HLT, unix.EL2HLT) 192 ErrInvalidExchange = newWithHost("invalid exchange", errno.EBADE, unix.EBADE) 193 ErrInvalidRequestDescriptor = newWithHost("invalid request descriptor", errno.EBADR, unix.EBADR) 194 ErrExchangeFull = newWithHost("exchange full", errno.EXFULL, unix.EXFULL) 195 ErrNoAnode = newWithHost("no anode", errno.ENOANO, unix.ENOANO) 196 ErrInvalidRequestCode = newWithHost("invalid request code", errno.EBADRQC, unix.EBADRQC) 197 ErrInvalidSlot = newWithHost("invalid slot", errno.EBADSLT, unix.EBADSLT) 198 ErrBadFontFile = newWithHost("bad font file format", errno.EBFONT, unix.EBFONT) 199 ErrNotStream = newWithHost("device not a stream", errno.ENOSTR, unix.ENOSTR) 200 ErrNoDataAvailable = newWithHost("no data available", errno.ENODATA, unix.ENODATA) 201 ErrTimerExpired = newWithHost("timer expired", errno.ETIME, unix.ETIME) 202 ErrStreamsResourceDepleted = newWithHost("out of streams resources", errno.ENOSR, unix.ENOSR) 203 ErrMachineNotOnNetwork = newWithHost("machine is not on the network", errno.ENONET, unix.ENONET) 204 ErrPackageNotInstalled = newWithHost("package not installed", errno.ENOPKG, unix.ENOPKG) 205 ErrIsRemote = newWithHost("object is remote", errno.EREMOTE, unix.EREMOTE) 206 ErrNoLink = newWithHost("link has been severed", errno.ENOLINK, unix.ENOLINK) 207 ErrAdvertise = newWithHost("advertise error", errno.EADV, unix.EADV) 208 ErrSRMount = newWithHost("srmount error", errno.ESRMNT, unix.ESRMNT) 209 ErrSendCommunication = newWithHost("communication error on send", errno.ECOMM, unix.ECOMM) 210 ErrProtocol = newWithHost("protocol error", errno.EPROTO, unix.EPROTO) 211 ErrMultihopAttempted = newWithHost("multihop attempted", errno.EMULTIHOP, unix.EMULTIHOP) 212 ErrRFS = newWithHost("RFS specific error", errno.EDOTDOT, unix.EDOTDOT) 213 ErrInvalidDataMessage = newWithHost("not a data message", errno.EBADMSG, unix.EBADMSG) 214 ErrOverflow = newWithHost("value too large for defined data type", errno.EOVERFLOW, unix.EOVERFLOW) 215 ErrNetworkNameNotUnique = newWithHost("name not unique on network", errno.ENOTUNIQ, unix.ENOTUNIQ) 216 ErrFDInBadState = newWithHost("file descriptor in bad state", errno.EBADFD, unix.EBADFD) 217 ErrRemoteAddressChanged = newWithHost("remote address changed", errno.EREMCHG, unix.EREMCHG) 218 ErrSharedLibraryInaccessible = newWithHost("can not access a needed shared library", errno.ELIBACC, unix.ELIBACC) 219 ErrCorruptedSharedLibrary = newWithHost("accessing a corrupted shared library", errno.ELIBBAD, unix.ELIBBAD) 220 ErrLibSectionCorrupted = newWithHost(".lib section in a.out corrupted", errno.ELIBSCN, unix.ELIBSCN) 221 ErrTooManySharedLibraries = newWithHost("attempting to link in too many shared libraries", errno.ELIBMAX, unix.ELIBMAX) 222 ErrSharedLibraryExeced = newWithHost("cannot exec a shared library directly", errno.ELIBEXEC, unix.ELIBEXEC) 223 ErrIllegalByteSequence = newWithHost("illegal byte sequence", errno.EILSEQ, unix.EILSEQ) 224 ErrShouldRestart = newWithHost("interrupted system call should be restarted", errno.ERESTART, unix.ERESTART) 225 ErrStreamPipe = newWithHost("streams pipe error", errno.ESTRPIPE, unix.ESTRPIPE) 226 ErrTooManyUsers = newWithHost("too many users", errno.EUSERS, unix.EUSERS) 227 ErrNotASocket = newWithHost("socket operation on non-socket", errno.ENOTSOCK, unix.ENOTSOCK) 228 ErrDestinationAddressRequired = newWithHost("destination address required", errno.EDESTADDRREQ, unix.EDESTADDRREQ) 229 ErrMessageTooLong = newWithHost("message too long", errno.EMSGSIZE, unix.EMSGSIZE) 230 ErrWrongProtocolForSocket = newWithHost("protocol wrong type for socket", errno.EPROTOTYPE, unix.EPROTOTYPE) 231 ErrProtocolNotAvailable = newWithHost("protocol not available", errno.ENOPROTOOPT, unix.ENOPROTOOPT) 232 ErrProtocolNotSupported = newWithHost("protocol not supported", errno.EPROTONOSUPPORT, unix.EPROTONOSUPPORT) 233 ErrSocketNotSupported = newWithHost("socket type not supported", errno.ESOCKTNOSUPPORT, unix.ESOCKTNOSUPPORT) 234 ErrEndpointOperation = newWithHost("operation not supported on transport endpoint", errno.EOPNOTSUPP, unix.EOPNOTSUPP) 235 ErrProtocolFamilyNotSupported = newWithHost("protocol family not supported", errno.EPFNOSUPPORT, unix.EPFNOSUPPORT) 236 ErrAddressFamilyNotSupported = newWithHost("address family not supported by protocol", errno.EAFNOSUPPORT, unix.EAFNOSUPPORT) 237 ErrAddressInUse = newWithHost("address already in use", errno.EADDRINUSE, unix.EADDRINUSE) 238 ErrAddressNotAvailable = newWithHost("cannot assign requested address", errno.EADDRNOTAVAIL, unix.EADDRNOTAVAIL) 239 ErrNetworkDown = newWithHost("network is down", errno.ENETDOWN, unix.ENETDOWN) 240 ErrNetworkUnreachable = newWithHost("network is unreachable", errno.ENETUNREACH, unix.ENETUNREACH) 241 ErrNetworkReset = newWithHost("network dropped connection because of reset", errno.ENETRESET, unix.ENETRESET) 242 ErrConnectionAborted = newWithHost("software caused connection abort", errno.ECONNABORTED, unix.ECONNABORTED) 243 ErrConnectionReset = newWithHost("connection reset by peer", errno.ECONNRESET, unix.ECONNRESET) 244 ErrNoBufferSpace = newWithHost("no buffer space available", errno.ENOBUFS, unix.ENOBUFS) 245 ErrAlreadyConnected = newWithHost("transport endpoint is already connected", errno.EISCONN, unix.EISCONN) 246 ErrNotConnected = newWithHost("transport endpoint is not connected", errno.ENOTCONN, unix.ENOTCONN) 247 ErrShutdown = newWithHost("cannot send after transport endpoint shutdown", errno.ESHUTDOWN, unix.ESHUTDOWN) 248 ErrTooManyRefs = newWithHost("too many references: cannot splice", errno.ETOOMANYREFS, unix.ETOOMANYREFS) 249 ErrTimedOut = newWithHost("connection timed out", errno.ETIMEDOUT, unix.ETIMEDOUT) 250 ErrConnectionRefused = newWithHost("connection refused", errno.ECONNREFUSED, unix.ECONNREFUSED) 251 ErrHostDown = newWithHost("host is down", errno.EHOSTDOWN, unix.EHOSTDOWN) 252 ErrNoRoute = newWithHost("no route to host", errno.EHOSTUNREACH, unix.EHOSTUNREACH) 253 ErrAlreadyInProgress = newWithHost("operation already in progress", errno.EALREADY, unix.EALREADY) 254 ErrInProgress = newWithHost("operation now in progress", errno.EINPROGRESS, unix.EINPROGRESS) 255 ErrStaleFileHandle = newWithHost("stale file handle", errno.ESTALE, unix.ESTALE) 256 ErrStructureNeedsCleaning = newWithHost("structure needs cleaning", errno.EUCLEAN, unix.EUCLEAN) 257 ErrIsNamedFile = newWithHost("is a named type file", errno.ENOTNAM, unix.ENOTNAM) 258 ErrRemoteIO = newWithHost("remote I/O error", errno.EREMOTEIO, unix.EREMOTEIO) 259 ErrQuotaExceeded = newWithHost("quota exceeded", errno.EDQUOT, unix.EDQUOT) 260 ErrNoMedium = newWithHost("no medium found", errno.ENOMEDIUM, unix.ENOMEDIUM) 261 ErrWrongMediumType = newWithHost("wrong medium type", errno.EMEDIUMTYPE, unix.EMEDIUMTYPE) 262 ErrCanceled = newWithHost("operation canceled", errno.ECANCELED, unix.ECANCELED) 263 ErrNoKey = newWithHost("required key not available", errno.ENOKEY, unix.ENOKEY) 264 ErrKeyExpired = newWithHost("key has expired", errno.EKEYEXPIRED, unix.EKEYEXPIRED) 265 ErrKeyRevoked = newWithHost("key has been revoked", errno.EKEYREVOKED, unix.EKEYREVOKED) 266 ErrKeyRejected = newWithHost("key was rejected by service", errno.EKEYREJECTED, unix.EKEYREJECTED) 267 ErrOwnerDied = newWithHost("owner died", errno.EOWNERDEAD, unix.EOWNERDEAD) 268 ErrNotRecoverable = newWithHost("state not recoverable", errno.ENOTRECOVERABLE, unix.ENOTRECOVERABLE) 269 270 // ErrWouldBlock translates to EWOULDBLOCK which is the same as EAGAIN 271 // on Linux. 272 ErrWouldBlock = New("operation would block", errno.EWOULDBLOCK) 273 ) 274 275 // FromError converts a generic error to an *Error. 276 // 277 // TODO(b/34162363): Remove this function. 278 func FromError(err error) *Error { 279 if err == nil { 280 return nil 281 } 282 if errno, ok := err.(unix.Errno); ok { 283 return FromHost(errno) 284 } 285 286 if linuxErr, ok := err.(*errors.Error); ok { 287 return FromHost(unix.Errno(linuxErr.Errno())) 288 } 289 290 if errno, ok := syserror.TranslateError(err); ok { 291 return FromHost(errno) 292 } 293 panic("unknown error: " + err.Error()) 294 }