diff options
author | Zach Koopmans <zkoopmans@google.com> | 2021-06-16 14:06:01 -0700 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2021-06-16 14:08:52 -0700 |
commit | 63b4f6e296a8f131ec969a685f0e31663be58385 (patch) | |
tree | 2bf10bff66a654b1bca5d27598a142fc68ca9430 | |
parent | 47149b7c4275ddd4404d86eddab6feab4f059ed3 (diff) |
[syserror] Refactor linuxerr and error package.
Move Error struct to pkg/errors package for use in multiple places.
Move linuxerr static definitions under pkg/errors/linuxerr.
Add a lookup list for quick lookup of *errors.Error by errno. This is useful
when converting syserror errors and unix.Errno/syscall.Errrno values to
*errors.Error.
Update benchmarks routines to include conversions.
The below benchmarks show *errors.Error usage to be comparable to using
unix.Errno.
BenchmarkAssignUnix
BenchmarkAssignUnix-32 787875022 1.284 ns/op
BenchmarkAssignLinuxerr
BenchmarkAssignLinuxerr-32 1000000000 1.209 ns/op
BenchmarkAssignSyserror
BenchmarkAssignSyserror-32 759269229 1.429 ns/op
BenchmarkCompareUnix
BenchmarkCompareUnix-32 1000000000 1.310 ns/op
BenchmarkCompareLinuxerr
BenchmarkCompareLinuxerr-32 1000000000 1.241 ns/op
BenchmarkCompareSyserror
BenchmarkCompareSyserror-32 147196165 8.248 ns/op
BenchmarkSwitchUnix
BenchmarkSwitchUnix-32 373233556 3.664 ns/op
BenchmarkSwitchLinuxerr
BenchmarkSwitchLinuxerr-32 476323929 3.294 ns/op
BenchmarkSwitchSyserror
BenchmarkSwitchSyserror-32 39293408 29.62 ns/op
BenchmarkReturnUnix
BenchmarkReturnUnix-32 1000000000 0.5042 ns/op
BenchmarkReturnLinuxerr
BenchmarkReturnLinuxerr-32 1000000000 0.8152 ns/op
BenchmarkConvertUnixLinuxerr
BenchmarkConvertUnixLinuxerr-32 739948875 1.547 ns/op
BenchmarkConvertUnixLinuxerrZero
BenchmarkConvertUnixLinuxerrZero-32 977733974 1.489 ns/op
PiperOrigin-RevId: 379806801
-rw-r--r-- | pkg/abi/linux/BUILD | 1 | ||||
-rw-r--r-- | pkg/abi/linux/errno/BUILD | 9 | ||||
-rw-r--r-- | pkg/abi/linux/errno/errno.go (renamed from pkg/abi/linux/errors.go) | 14 | ||||
-rw-r--r-- | pkg/errors/BUILD | 10 | ||||
-rw-r--r-- | pkg/errors/errors.go | 40 | ||||
-rw-r--r-- | pkg/errors/linuxerr/BUILD (renamed from pkg/linuxerr/BUILD) | 7 | ||||
-rw-r--r-- | pkg/errors/linuxerr/linuxerr.go | 326 | ||||
-rw-r--r-- | pkg/errors/linuxerr/linuxerr_test.go (renamed from pkg/linuxerr/linuxerr_test.go) | 101 | ||||
-rw-r--r-- | pkg/linuxerr/linuxerr.go | 184 | ||||
-rw-r--r-- | pkg/sentry/kernel/BUILD | 1 | ||||
-rw-r--r-- | pkg/sentry/kernel/task_image.go | 4 | ||||
-rw-r--r-- | pkg/sentry/loader/BUILD | 1 | ||||
-rw-r--r-- | pkg/sentry/loader/loader.go | 3 | ||||
-rw-r--r-- | pkg/sentry/socket/netlink/BUILD | 1 | ||||
-rw-r--r-- | pkg/sentry/socket/netlink/socket.go | 3 | ||||
-rw-r--r-- | pkg/sentry/socket/netstack/BUILD | 1 | ||||
-rw-r--r-- | pkg/sentry/socket/netstack/netstack.go | 3 | ||||
-rw-r--r-- | pkg/syserr/BUILD | 2 | ||||
-rw-r--r-- | pkg/syserr/netstack.go | 56 | ||||
-rw-r--r-- | pkg/syserr/syserr.go | 291 |
20 files changed, 676 insertions, 382 deletions
diff --git a/pkg/abi/linux/BUILD b/pkg/abi/linux/BUILD index 38288bdb7..eb004a7f6 100644 --- a/pkg/abi/linux/BUILD +++ b/pkg/abi/linux/BUILD @@ -21,7 +21,6 @@ go_library( "epoll.go", "epoll_amd64.go", "epoll_arm64.go", - "errors.go", "errqueue.go", "eventfd.go", "exec.go", diff --git a/pkg/abi/linux/errno/BUILD b/pkg/abi/linux/errno/BUILD new file mode 100644 index 000000000..d003342d5 --- /dev/null +++ b/pkg/abi/linux/errno/BUILD @@ -0,0 +1,9 @@ +load("//tools:defs.bzl", "go_library") + +package(licenses = ["notice"]) + +go_library( + name = "errno", + srcs = ["errno.go"], + visibility = ["//visibility:public"], +) diff --git a/pkg/abi/linux/errors.go b/pkg/abi/linux/errno/errno.go index b08b2687e..5a09c6605 100644 --- a/pkg/abi/linux/errors.go +++ b/pkg/abi/linux/errno/errno.go @@ -12,10 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -package linux +// Package errno holds errno codes for abi/linux. +package errno // Errno represents a Linux errno value. -type Errno int +type Errno uint32 // Errno values from include/uapi/asm-generic/errno-base.h. const ( @@ -60,8 +61,8 @@ const ( ENOLCK ENOSYS ENOTEMPTY - ELOOP //40 - _ // Skip for EWOULDBLOCK = EAGAIN + ELOOP // 40 + _ // Skip for EWOULDBLOCK = EAGAIN. ENOMSG //42 EIDRM ECHRNG @@ -78,13 +79,13 @@ const ( ENOANO EBADRQC EBADSLT - _ // Skip for EDEADLOCK = EDEADLK + _ // Skip for EDEADLOCK = EDEADLK. EBFONT ENOSTR // 60 ENODATA ETIME ENOSR - ENONET + _ // Skip for ENOENT = ENONET. ENOPKG EREMOTE ENOLINK @@ -160,4 +161,5 @@ const ( const ( EWOULDBLOCK = EAGAIN EDEADLOCK = EDEADLK + ENONET = ENOENT ) diff --git a/pkg/errors/BUILD b/pkg/errors/BUILD new file mode 100644 index 000000000..36ea5da0c --- /dev/null +++ b/pkg/errors/BUILD @@ -0,0 +1,10 @@ +load("//tools:defs.bzl", "go_library") + +package(licenses = ["notice"]) + +go_library( + name = "errors", + srcs = ["errors.go"], + visibility = ["//:sandbox"], + deps = ["//pkg/abi/linux/errno"], +) diff --git a/pkg/errors/errors.go b/pkg/errors/errors.go new file mode 100644 index 000000000..7984a770e --- /dev/null +++ b/pkg/errors/errors.go @@ -0,0 +1,40 @@ +// 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 errors holds the standardized error definition for gVisor. +package errors + +import ( + "gvisor.dev/gvisor/pkg/abi/linux/errno" +) + +// Error represents a syscall errno with a descriptive message. +type Error struct { + errno errno.Errno + message string +} + +// New creates a new *Error. +func New(err errno.Errno, message string) *Error { + return &Error{ + errno: err, + message: message, + } +} + +// Error implements error.Error. +func (e *Error) Error() string { return e.message } + +// Errno returns the underlying errno.Errno value. +func (e *Error) Errno() errno.Errno { return e.errno } diff --git a/pkg/linuxerr/BUILD b/pkg/errors/linuxerr/BUILD index c5abbd34f..8afc9688c 100644 --- a/pkg/linuxerr/BUILD +++ b/pkg/errors/linuxerr/BUILD @@ -6,7 +6,10 @@ go_library( name = "linuxerr", srcs = ["linuxerr.go"], visibility = ["//visibility:public"], - deps = ["//pkg/abi/linux"], + deps = [ + "//pkg/abi/linux/errno", + "//pkg/errors", + ], ) go_test( @@ -14,6 +17,8 @@ go_test( srcs = ["linuxerr_test.go"], deps = [ ":linuxerr", + "//pkg/abi/linux/errno", + "//pkg/errors", "//pkg/syserror", "@org_golang_x_sys//unix:go_default_library", ], diff --git a/pkg/errors/linuxerr/linuxerr.go b/pkg/errors/linuxerr/linuxerr.go new file mode 100644 index 000000000..23d9f9f75 --- /dev/null +++ b/pkg/errors/linuxerr/linuxerr.go @@ -0,0 +1,326 @@ +// 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 linuxerr contains syscall error codes exported as an error interface +// pointers. This allows for fast comparison and return operations comperable +// to unix.Errno constants. +package linuxerr + +import ( + "fmt" + + "gvisor.dev/gvisor/pkg/abi/linux/errno" + "gvisor.dev/gvisor/pkg/errors" +) + +const maxErrno uint32 = errno.EHWPOISON + 1 + +var ( + EPERM = errors.New(errno.EPERM, "operation not permitted") + ENOENT = errors.New(errno.ENOENT, "no such file or directory") + ESRCH = errors.New(errno.ESRCH, "no such process") + EINTR = errors.New(errno.EINTR, "interrupted system call") + EIO = errors.New(errno.EIO, "I/O error") + ENXIO = errors.New(errno.ENXIO, "no such device or address") + E2BIG = errors.New(errno.E2BIG, "argument list too long") + ENOEXEC = errors.New(errno.ENOEXEC, "exec format error") + EBADF = errors.New(errno.EBADF, "bad file number") + ECHILD = errors.New(errno.ECHILD, "no child processes") + EAGAIN = errors.New(errno.EAGAIN, "try again") + ENOMEM = errors.New(errno.ENOMEM, "out of memory") + EACCES = errors.New(errno.EACCES, "permission denied") + EFAULT = errors.New(errno.EFAULT, "bad address") + ENOTBLK = errors.New(errno.ENOTBLK, "block device required") + EBUSY = errors.New(errno.EBUSY, "device or resource busy") + EEXIST = errors.New(errno.EEXIST, "file exists") + EXDEV = errors.New(errno.EXDEV, "cross-device link") + ENODEV = errors.New(errno.ENODEV, "no such device") + ENOTDIR = errors.New(errno.ENOTDIR, "not a directory") + EISDIR = errors.New(errno.EISDIR, "is a directory") + EINVAL = errors.New(errno.EINVAL, "invalid argument") + ENFILE = errors.New(errno.ENFILE, "file table overflow") + EMFILE = errors.New(errno.EMFILE, "too many open files") + ENOTTY = errors.New(errno.ENOTTY, "not a typewriter") + ETXTBSY = errors.New(errno.ETXTBSY, "text file busy") + EFBIG = errors.New(errno.EFBIG, "file too large") + ENOSPC = errors.New(errno.ENOSPC, "no space left on device") + ESPIPE = errors.New(errno.ESPIPE, "illegal seek") + EROFS = errors.New(errno.EROFS, "read-only file system") + EMLINK = errors.New(errno.EMLINK, "too many links") + EPIPE = errors.New(errno.EPIPE, "broken pipe") + EDOM = errors.New(errno.EDOM, "math argument out of domain of func") + ERANGE = errors.New(errno.ERANGE, "math result not representable") + + // Errno values from include/uapi/asm-generic/errno.h. + EDEADLK = errors.New(errno.EDEADLK, "resource deadlock would occur") + ENAMETOOLONG = errors.New(errno.ENAMETOOLONG, "file name too long") + ENOLCK = errors.New(errno.ENOLCK, "no record locks available") + ENOSYS = errors.New(errno.ENOSYS, "invalid system call number") + ENOTEMPTY = errors.New(errno.ENOTEMPTY, "directory not empty") + ELOOP = errors.New(errno.ELOOP, "too many symbolic links encountered") + ENOMSG = errors.New(errno.ENOMSG, "no message of desired type") + EIDRM = errors.New(errno.EIDRM, "identifier removed") + ECHRNG = errors.New(errno.ECHRNG, "channel number out of range") + EL2NSYNC = errors.New(errno.EL2NSYNC, "level 2 not synchronized") + EL3HLT = errors.New(errno.EL3HLT, "level 3 halted") + EL3RST = errors.New(errno.EL3RST, "level 3 reset") + ELNRNG = errors.New(errno.ELNRNG, "link number out of range") + EUNATCH = errors.New(errno.EUNATCH, "protocol driver not attached") + ENOCSI = errors.New(errno.ENOCSI, "no CSI structure available") + EL2HLT = errors.New(errno.EL2HLT, "level 2 halted") + EBADE = errors.New(errno.EBADE, "invalid exchange") + EBADR = errors.New(errno.EBADR, "invalid request descriptor") + EXFULL = errors.New(errno.EXFULL, "exchange full") + ENOANO = errors.New(errno.ENOANO, "no anode") + EBADRQC = errors.New(errno.EBADRQC, "invalid request code") + EBADSLT = errors.New(errno.EBADSLT, "invalid slot") + EBFONT = errors.New(errno.EBFONT, "bad font file format") + ENOSTR = errors.New(errno.ENOSTR, "device not a stream") + ENODATA = errors.New(errno.ENODATA, "no data available") + ETIME = errors.New(errno.ETIME, "timer expired") + ENOSR = errors.New(errno.ENOSR, "out of streams resources") + ENOPKG = errors.New(errno.ENOPKG, "package not installed") + EREMOTE = errors.New(errno.EREMOTE, "object is remote") + ENOLINK = errors.New(errno.ENOLINK, "link has been severed") + EADV = errors.New(errno.EADV, "advertise error") + ESRMNT = errors.New(errno.ESRMNT, "srmount error") + ECOMM = errors.New(errno.ECOMM, "communication error on send") + EPROTO = errors.New(errno.EPROTO, "protocol error") + EMULTIHOP = errors.New(errno.EMULTIHOP, "multihop attempted") + EDOTDOT = errors.New(errno.EDOTDOT, "RFS specific error") + EBADMSG = errors.New(errno.EBADMSG, "not a data message") + EOVERFLOW = errors.New(errno.EOVERFLOW, "value too large for defined data type") + ENOTUNIQ = errors.New(errno.ENOTUNIQ, "name not unique on network") + EBADFD = errors.New(errno.EBADFD, "file descriptor in bad state") + EREMCHG = errors.New(errno.EREMCHG, "remote address changed") + ELIBACC = errors.New(errno.ELIBACC, "can not access a needed shared library") + ELIBBAD = errors.New(errno.ELIBBAD, "accessing a corrupted shared library") + ELIBSCN = errors.New(errno.ELIBSCN, ".lib section in a.out corrupted") + ELIBMAX = errors.New(errno.ELIBMAX, "attempting to link in too many shared libraries") + ELIBEXEC = errors.New(errno.ELIBEXEC, "cannot exec a shared library directly") + EILSEQ = errors.New(errno.EILSEQ, "illegal byte sequence") + ERESTART = errors.New(errno.ERESTART, "interrupted system call should be restarted") + ESTRPIPE = errors.New(errno.ESTRPIPE, "streams pipe error") + EUSERS = errors.New(errno.EUSERS, "too many users") + ENOTSOCK = errors.New(errno.ENOTSOCK, "socket operation on non-socket") + EDESTADDRREQ = errors.New(errno.EDESTADDRREQ, "destination address required") + EMSGSIZE = errors.New(errno.EMSGSIZE, "message too long") + EPROTOTYPE = errors.New(errno.EPROTOTYPE, "protocol wrong type for socket") + ENOPROTOOPT = errors.New(errno.ENOPROTOOPT, "protocol not available") + EPROTONOSUPPORT = errors.New(errno.EPROTONOSUPPORT, "protocol not supported") + ESOCKTNOSUPPORT = errors.New(errno.ESOCKTNOSUPPORT, "socket type not supported") + EOPNOTSUPP = errors.New(errno.EOPNOTSUPP, "operation not supported on transport endpoint") + EPFNOSUPPORT = errors.New(errno.EPFNOSUPPORT, "protocol family not supported") + EAFNOSUPPORT = errors.New(errno.EAFNOSUPPORT, "address family not supported by protocol") + EADDRINUSE = errors.New(errno.EADDRINUSE, "address already in use") + EADDRNOTAVAIL = errors.New(errno.EADDRNOTAVAIL, "cannot assign requested address") + ENETDOWN = errors.New(errno.ENETDOWN, "network is down") + ENETUNREACH = errors.New(errno.ENETUNREACH, "network is unreachable") + ENETRESET = errors.New(errno.ENETRESET, "network dropped connection because of reset") + ECONNABORTED = errors.New(errno.ECONNABORTED, "software caused connection abort") + ECONNRESET = errors.New(errno.ECONNRESET, "connection reset by peer") + ENOBUFS = errors.New(errno.ENOBUFS, "no buffer space available") + EISCONN = errors.New(errno.EISCONN, "transport endpoint is already connected") + ENOTCONN = errors.New(errno.ENOTCONN, "transport endpoint is not connected") + ESHUTDOWN = errors.New(errno.ESHUTDOWN, "cannot send after transport endpoint shutdown") + ETOOMANYREFS = errors.New(errno.ETOOMANYREFS, "too many references: cannot splice") + ETIMEDOUT = errors.New(errno.ETIMEDOUT, "connection timed out") + ECONNREFUSED = errors.New(errno.ECONNREFUSED, "connection refused") + EHOSTDOWN = errors.New(errno.EHOSTDOWN, "host is down") + EHOSTUNREACH = errors.New(errno.EHOSTUNREACH, "no route to host") + EALREADY = errors.New(errno.EALREADY, "operation already in progress") + EINPROGRESS = errors.New(errno.EINPROGRESS, "operation now in progress") + ESTALE = errors.New(errno.ESTALE, "stale file handle") + EUCLEAN = errors.New(errno.EUCLEAN, "structure needs cleaning") + ENOTNAM = errors.New(errno.ENOTNAM, "not a XENIX named type file") + ENAVAIL = errors.New(errno.ENAVAIL, "no XENIX semaphores available") + EISNAM = errors.New(errno.EISNAM, "is a named type file") + EREMOTEIO = errors.New(errno.EREMOTEIO, "remote I/O error") + EDQUOT = errors.New(errno.EDQUOT, "quota exceeded") + ENOMEDIUM = errors.New(errno.ENOMEDIUM, "no medium found") + EMEDIUMTYPE = errors.New(errno.EMEDIUMTYPE, "wrong medium type") + ECANCELED = errors.New(errno.ECANCELED, "operation Canceled") + ENOKEY = errors.New(errno.ENOKEY, "required key not available") + EKEYEXPIRED = errors.New(errno.EKEYEXPIRED, "key has expired") + EKEYREVOKED = errors.New(errno.EKEYREVOKED, "key has been revoked") + EKEYREJECTED = errors.New(errno.EKEYREJECTED, "key was rejected by service") + EOWNERDEAD = errors.New(errno.EOWNERDEAD, "owner died") + ENOTRECOVERABLE = errors.New(errno.ENOTRECOVERABLE, "state not recoverable") + ERFKILL = errors.New(errno.ERFKILL, "operation not possible due to RF-kill") + EHWPOISON = errors.New(errno.EHWPOISON, "memory page has hardware error") + + // Errors equivalent to other errors. + EWOULDBLOCK = EAGAIN + EDEADLOCK = EDEADLK + ENONET = ENOENT +) + +// A nil *errors.Error denotes no error and is placed at the 0 index of +// errorSlice. Thus, any other empty index should not be nil or a valid error. +// This marks that index as an invalid error so any comparison to nil or a +// valid linuxerr fails. +var errNotValidError = errors.New(errno.Errno(maxErrno), "not a valid error") + +// The following errorSlice holds errors by errno for fast translation between +// errnos (especially uint32(sycall.Errno)) and *Error. +var errorSlice = []*errors.Error{ + // Errno values from include/uapi/asm-generic/errno-base.h. + errno.NOERRNO: nil, + errno.EPERM: EPERM, + errno.ENOENT: ENOENT, + errno.ESRCH: ESRCH, + errno.EINTR: EINTR, + errno.EIO: EIO, + errno.ENXIO: ENXIO, + errno.E2BIG: E2BIG, + errno.ENOEXEC: ENOEXEC, + errno.EBADF: EBADF, + errno.ECHILD: ECHILD, + errno.EAGAIN: EAGAIN, + errno.ENOMEM: ENOMEM, + errno.EACCES: EACCES, + errno.EFAULT: EFAULT, + errno.ENOTBLK: ENOTBLK, + errno.EBUSY: EBUSY, + errno.EEXIST: EEXIST, + errno.EXDEV: EXDEV, + errno.ENODEV: ENODEV, + errno.ENOTDIR: ENOTDIR, + errno.EISDIR: EISDIR, + errno.EINVAL: EINVAL, + errno.ENFILE: ENFILE, + errno.EMFILE: EMFILE, + errno.ENOTTY: ENOTTY, + errno.ETXTBSY: ETXTBSY, + errno.EFBIG: EFBIG, + errno.ENOSPC: ENOSPC, + errno.ESPIPE: ESPIPE, + errno.EROFS: EROFS, + errno.EMLINK: EMLINK, + errno.EPIPE: EPIPE, + errno.EDOM: EDOM, + errno.ERANGE: ERANGE, + + // Errno values from include/uapi/asm-generic/errno.h. + errno.EDEADLK: EDEADLK, + errno.ENAMETOOLONG: ENAMETOOLONG, + errno.ENOLCK: ENOLCK, + errno.ENOSYS: ENOSYS, + errno.ENOTEMPTY: ENOTEMPTY, + errno.ELOOP: ELOOP, + errno.ELOOP + 1: errNotValidError, // No valid errno between ELOOP and ENOMSG. + errno.ENOMSG: ENOMSG, + errno.EIDRM: EIDRM, + errno.ECHRNG: ECHRNG, + errno.EL2NSYNC: EL2NSYNC, + errno.EL3HLT: EL3HLT, + errno.EL3RST: EL3RST, + errno.ELNRNG: ELNRNG, + errno.EUNATCH: EUNATCH, + errno.ENOCSI: ENOCSI, + errno.EL2HLT: EL2HLT, + errno.EBADE: EBADE, + errno.EBADR: EBADR, + errno.EXFULL: EXFULL, + errno.ENOANO: ENOANO, + errno.EBADRQC: EBADRQC, + errno.EBADSLT: EBADSLT, + errno.EBADSLT + 1: errNotValidError, // No valid errno between EBADSLT and ENOPKG. + errno.EBFONT: EBFONT, + errno.ENOSTR: ENOSTR, + errno.ENODATA: ENODATA, + errno.ETIME: ETIME, + errno.ENOSR: ENOSR, + errno.ENOSR + 1: errNotValidError, // No valid errno betweeen ENOSR and ENOPKG. + errno.ENOPKG: ENOPKG, + errno.EREMOTE: EREMOTE, + errno.ENOLINK: ENOLINK, + errno.EADV: EADV, + errno.ESRMNT: ESRMNT, + errno.ECOMM: ECOMM, + errno.EPROTO: EPROTO, + errno.EMULTIHOP: EMULTIHOP, + errno.EDOTDOT: EDOTDOT, + errno.EBADMSG: EBADMSG, + errno.EOVERFLOW: EOVERFLOW, + errno.ENOTUNIQ: ENOTUNIQ, + errno.EBADFD: EBADFD, + errno.EREMCHG: EREMCHG, + errno.ELIBACC: ELIBACC, + errno.ELIBBAD: ELIBBAD, + errno.ELIBSCN: ELIBSCN, + errno.ELIBMAX: ELIBMAX, + errno.ELIBEXEC: ELIBEXEC, + errno.EILSEQ: EILSEQ, + errno.ERESTART: ERESTART, + errno.ESTRPIPE: ESTRPIPE, + errno.EUSERS: EUSERS, + errno.ENOTSOCK: ENOTSOCK, + errno.EDESTADDRREQ: EDESTADDRREQ, + errno.EMSGSIZE: EMSGSIZE, + errno.EPROTOTYPE: EPROTOTYPE, + errno.ENOPROTOOPT: ENOPROTOOPT, + errno.EPROTONOSUPPORT: EPROTONOSUPPORT, + errno.ESOCKTNOSUPPORT: ESOCKTNOSUPPORT, + errno.EOPNOTSUPP: EOPNOTSUPP, + errno.EPFNOSUPPORT: EPFNOSUPPORT, + errno.EAFNOSUPPORT: EAFNOSUPPORT, + errno.EADDRINUSE: EADDRINUSE, + errno.EADDRNOTAVAIL: EADDRNOTAVAIL, + errno.ENETDOWN: ENETDOWN, + errno.ENETUNREACH: ENETUNREACH, + errno.ENETRESET: ENETRESET, + errno.ECONNABORTED: ECONNABORTED, + errno.ECONNRESET: ECONNRESET, + errno.ENOBUFS: ENOBUFS, + errno.EISCONN: EISCONN, + errno.ENOTCONN: ENOTCONN, + errno.ESHUTDOWN: ESHUTDOWN, + errno.ETOOMANYREFS: ETOOMANYREFS, + errno.ETIMEDOUT: ETIMEDOUT, + errno.ECONNREFUSED: ECONNREFUSED, + errno.EHOSTDOWN: EHOSTDOWN, + errno.EHOSTUNREACH: EHOSTUNREACH, + errno.EALREADY: EALREADY, + errno.EINPROGRESS: EINPROGRESS, + errno.ESTALE: ESTALE, + errno.EUCLEAN: EUCLEAN, + errno.ENOTNAM: ENOTNAM, + errno.ENAVAIL: ENAVAIL, + errno.EISNAM: EISNAM, + errno.EREMOTEIO: EREMOTEIO, + errno.EDQUOT: EDQUOT, + errno.ENOMEDIUM: ENOMEDIUM, + errno.EMEDIUMTYPE: EMEDIUMTYPE, + errno.ECANCELED: ECANCELED, + errno.ENOKEY: ENOKEY, + errno.EKEYEXPIRED: EKEYEXPIRED, + errno.EKEYREVOKED: EKEYREVOKED, + errno.EKEYREJECTED: EKEYREJECTED, + errno.EOWNERDEAD: EOWNERDEAD, + errno.ENOTRECOVERABLE: ENOTRECOVERABLE, + errno.ERFKILL: ERFKILL, + errno.EHWPOISON: EHWPOISON, +} + +// ErrorFromErrno gets an error from the list and panics if an invalid entry is requested. +func ErrorFromErrno(e errno.Errno) *errors.Error { + err := errorSlice[e] + // Done this way because a single comparison in benchmarks is 2-3 faster + // than something like ( if err == nil && err > 0 ). + if err != errNotValidError { + return err + } + panic(fmt.Sprintf("invalid error requested with errno: %d", e)) +} diff --git a/pkg/linuxerr/linuxerr_test.go b/pkg/errors/linuxerr/linuxerr_test.go index d34937e93..a81dd9560 100644 --- a/pkg/linuxerr/linuxerr_test.go +++ b/pkg/errors/linuxerr/linuxerr_test.go @@ -16,34 +16,37 @@ package syserror_test import ( "errors" + "syscall" "testing" "golang.org/x/sys/unix" - "gvisor.dev/gvisor/pkg/linuxerr" + "gvisor.dev/gvisor/pkg/abi/linux/errno" + gErrors "gvisor.dev/gvisor/pkg/errors" + "gvisor.dev/gvisor/pkg/errors/linuxerr" "gvisor.dev/gvisor/pkg/syserror" ) var globalError error -func BenchmarkAssignErrno(b *testing.B) { +func BenchmarkAssignUnix(b *testing.B) { for i := b.N; i > 0; i-- { globalError = unix.EINVAL } } -func BenchmarkLinuxerrAssignError(b *testing.B) { +func BenchmarkAssignLinuxerr(b *testing.B) { for i := b.N; i > 0; i-- { globalError = linuxerr.EINVAL } } -func BenchmarkAssignSyserrorError(b *testing.B) { +func BenchmarkAssignSyserror(b *testing.B) { for i := b.N; i > 0; i-- { globalError = syserror.EINVAL } } -func BenchmarkCompareErrno(b *testing.B) { +func BenchmarkCompareUnix(b *testing.B) { globalError = unix.EAGAIN j := 0 for i := b.N; i > 0; i-- { @@ -53,7 +56,7 @@ func BenchmarkCompareErrno(b *testing.B) { } } -func BenchmarkCompareLinuxerrError(b *testing.B) { +func BenchmarkCompareLinuxerr(b *testing.B) { globalError = linuxerr.E2BIG j := 0 for i := b.N; i > 0; i-- { @@ -63,7 +66,7 @@ func BenchmarkCompareLinuxerrError(b *testing.B) { } } -func BenchmarkCompareSyserrorError(b *testing.B) { +func BenchmarkCompareSyserror(b *testing.B) { globalError = syserror.EAGAIN j := 0 for i := b.N; i > 0; i-- { @@ -73,7 +76,7 @@ func BenchmarkCompareSyserrorError(b *testing.B) { } } -func BenchmarkSwitchErrno(b *testing.B) { +func BenchmarkSwitchUnix(b *testing.B) { globalError = unix.EPERM j := 0 for i := b.N; i > 0; i-- { @@ -88,7 +91,7 @@ func BenchmarkSwitchErrno(b *testing.B) { } } -func BenchmarkSwitchLinuxerrError(b *testing.B) { +func BenchmarkSwitchLinuxerr(b *testing.B) { globalError = linuxerr.EPERM j := 0 for i := b.N; i > 0; i-- { @@ -103,7 +106,7 @@ func BenchmarkSwitchLinuxerrError(b *testing.B) { } } -func BenchmarkSwitchSyserrorError(b *testing.B) { +func BenchmarkSwitchSyserror(b *testing.B) { globalError = syserror.EPERM j := 0 for i := b.N; i > 0; i-- { @@ -118,6 +121,52 @@ func BenchmarkSwitchSyserrorError(b *testing.B) { } } +func BenchmarkReturnUnix(b *testing.B) { + var localError error + f := func() error { + return unix.EINVAL + } + for i := b.N; i > 0; i-- { + localError = f() + } + if localError != nil { + return + } +} + +func BenchmarkReturnLinuxerr(b *testing.B) { + var localError error + f := func() error { + return linuxerr.EINVAL + } + for i := b.N; i > 0; i-- { + localError = f() + } + if localError != nil { + return + } +} + +func BenchmarkConvertUnixLinuxerr(b *testing.B) { + var localError error + for i := b.N; i > 0; i-- { + localError = linuxerr.ErrorFromErrno(errno.Errno(unix.EINVAL)) + } + if localError != nil { + return + } +} + +func BenchmarkConvertUnixLinuxerrZero(b *testing.B) { + var localError error + for i := b.N; i > 0; i-- { + localError = linuxerr.ErrorFromErrno(errno.Errno(0)) + } + if localError != nil { + return + } +} + type translationTestTable struct { fn string errIn error @@ -162,3 +211,35 @@ func TestErrorTranslation(t *testing.T) { } } } + +func TestSyscallErrnoToErrors(t *testing.T) { + for _, tc := range []struct { + errno syscall.Errno + err *gErrors.Error + }{ + {errno: syscall.EACCES, err: linuxerr.EACCES}, + {errno: syscall.EAGAIN, err: linuxerr.EAGAIN}, + {errno: syscall.EBADF, err: linuxerr.EBADF}, + {errno: syscall.EBUSY, err: linuxerr.EBUSY}, + {errno: syscall.EDOM, err: linuxerr.EDOM}, + {errno: syscall.EEXIST, err: linuxerr.EEXIST}, + {errno: syscall.EFAULT, err: linuxerr.EFAULT}, + {errno: syscall.EFBIG, err: linuxerr.EFBIG}, + {errno: syscall.EINTR, err: linuxerr.EINTR}, + {errno: syscall.EINVAL, err: linuxerr.EINVAL}, + {errno: syscall.EIO, err: linuxerr.EIO}, + {errno: syscall.ENOTDIR, err: linuxerr.ENOTDIR}, + {errno: syscall.ENOTTY, err: linuxerr.ENOTTY}, + {errno: syscall.EPERM, err: linuxerr.EPERM}, + {errno: syscall.EPIPE, err: linuxerr.EPIPE}, + {errno: syscall.ESPIPE, err: linuxerr.ESPIPE}, + {errno: syscall.EWOULDBLOCK, err: linuxerr.EAGAIN}, + } { + t.Run(tc.errno.Error(), func(t *testing.T) { + e := linuxerr.ErrorFromErrno(errno.Errno(tc.errno)) + if e != tc.err { + t.Fatalf("Mismatch errors: want: %+v (%d) got: %+v %d", tc.err, tc.err.Errno(), e, e.Errno()) + } + }) + } +} diff --git a/pkg/linuxerr/linuxerr.go b/pkg/linuxerr/linuxerr.go deleted file mode 100644 index f45caaadf..000000000 --- a/pkg/linuxerr/linuxerr.go +++ /dev/null @@ -1,184 +0,0 @@ -// 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 linuxerr contains syscall error codes exported as an error interface -// pointers. This allows for fast comparison and return operations comperable -// to unix.Errno constants. -package linuxerr - -import ( - "gvisor.dev/gvisor/pkg/abi/linux" -) - -// Error represents a syscall errno with a descriptive message. -type Error struct { - errno linux.Errno - message string -} - -func new(err linux.Errno, message string) *Error { - return &Error{ - errno: err, - message: message, - } -} - -// Error implements error.Error. -func (e *Error) Error() string { return e.message } - -// Errno returns the underlying linux.Errno value. -func (e *Error) Errno() linux.Errno { return e.errno } - -// The following varables have the same meaning as their errno equivalent. - -// Errno values from include/uapi/asm-generic/errno-base.h. -var ( - EPERM = new(linux.EPERM, "operation not permitted") - ENOENT = new(linux.ENOENT, "no such file or directory") - ESRCH = new(linux.ESRCH, "no such process") - EINTR = new(linux.EINTR, "interrupted system call") - EIO = new(linux.EIO, "I/O error") - ENXIO = new(linux.ENXIO, "no such device or address") - E2BIG = new(linux.E2BIG, "argument list too long") - ENOEXEC = new(linux.ENOEXEC, "exec format error") - EBADF = new(linux.EBADF, "bad file number") - ECHILD = new(linux.ECHILD, "no child processes") - EAGAIN = new(linux.EAGAIN, "try again") - ENOMEM = new(linux.ENOMEM, "out of memory") - EACCES = new(linux.EACCES, "permission denied") - EFAULT = new(linux.EFAULT, "bad address") - ENOTBLK = new(linux.ENOTBLK, "block device required") - EBUSY = new(linux.EBUSY, "device or resource busy") - EEXIST = new(linux.EEXIST, "file exists") - EXDEV = new(linux.EXDEV, "cross-device link") - ENODEV = new(linux.ENODEV, "no such device") - ENOTDIR = new(linux.ENOTDIR, "not a directory") - EISDIR = new(linux.EISDIR, "is a directory") - EINVAL = new(linux.EINVAL, "invalid argument") - ENFILE = new(linux.ENFILE, "file table overflow") - EMFILE = new(linux.EMFILE, "too many open files") - ENOTTY = new(linux.ENOTTY, "not a typewriter") - ETXTBSY = new(linux.ETXTBSY, "text file busy") - EFBIG = new(linux.EFBIG, "file too large") - ENOSPC = new(linux.ENOSPC, "no space left on device") - ESPIPE = new(linux.ESPIPE, "illegal seek") - EROFS = new(linux.EROFS, "read-only file system") - EMLINK = new(linux.EMLINK, "too many links") - EPIPE = new(linux.EPIPE, "broken pipe") - EDOM = new(linux.EDOM, "math argument out of domain of func") - ERANGE = new(linux.ERANGE, "math result not representable") -) - -// Errno values from include/uapi/asm-generic/errno.h. -var ( - EDEADLK = new(linux.EDEADLK, "resource deadlock would occur") - ENAMETOOLONG = new(linux.ENAMETOOLONG, "file name too long") - ENOLCK = new(linux.ENOLCK, "no record locks available") - ENOSYS = new(linux.ENOSYS, "invalid system call number") - ENOTEMPTY = new(linux.ENOTEMPTY, "directory not empty") - ELOOP = new(linux.ELOOP, "too many symbolic links encountered") - EWOULDBLOCK = new(linux.EWOULDBLOCK, "operation would block") - ENOMSG = new(linux.ENOMSG, "no message of desired type") - EIDRM = new(linux.EIDRM, "identifier removed") - ECHRNG = new(linux.ECHRNG, "channel number out of range") - EL2NSYNC = new(linux.EL2NSYNC, "level 2 not synchronized") - EL3HLT = new(linux.EL3HLT, "level 3 halted") - EL3RST = new(linux.EL3RST, "level 3 reset") - ELNRNG = new(linux.ELNRNG, "link number out of range") - EUNATCH = new(linux.EUNATCH, "protocol driver not attached") - ENOCSI = new(linux.ENOCSI, "no CSI structure available") - EL2HLT = new(linux.EL2HLT, "level 2 halted") - EBADE = new(linux.EBADE, "invalid exchange") - EBADR = new(linux.EBADR, "invalid request descriptor") - EXFULL = new(linux.EXFULL, "exchange full") - ENOANO = new(linux.ENOANO, "no anode") - EBADRQC = new(linux.EBADRQC, "invalid request code") - EBADSLT = new(linux.EBADSLT, "invalid slot") - EDEADLOCK = new(linux.EDEADLOCK, EDEADLK.message) - EBFONT = new(linux.EBFONT, "bad font file format") - ENOSTR = new(linux.ENOSTR, "device not a stream") - ENODATA = new(linux.ENODATA, "no data available") - ETIME = new(linux.ETIME, "timer expired") - ENOSR = new(linux.ENOSR, "out of streams resources") - ENONET = new(linux.ENOENT, "machine is not on the network") - ENOPKG = new(linux.ENOPKG, "package not installed") - EREMOTE = new(linux.EREMOTE, "object is remote") - ENOLINK = new(linux.ENOLINK, "link has been severed") - EADV = new(linux.EADV, "advertise error") - ESRMNT = new(linux.ESRMNT, "srmount error") - ECOMM = new(linux.ECOMM, "communication error on send") - EPROTO = new(linux.EPROTO, "protocol error") - EMULTIHOP = new(linux.EMULTIHOP, "multihop attempted") - EDOTDOT = new(linux.EDOTDOT, "RFS specific error") - EBADMSG = new(linux.EBADMSG, "not a data message") - EOVERFLOW = new(linux.EOVERFLOW, "value too large for defined data type") - ENOTUNIQ = new(linux.ENOTUNIQ, "name not unique on network") - EBADFD = new(linux.EBADFD, "file descriptor in bad state") - EREMCHG = new(linux.EREMCHG, "remote address changed") - ELIBACC = new(linux.ELIBACC, "can not access a needed shared library") - ELIBBAD = new(linux.ELIBBAD, "accessing a corrupted shared library") - ELIBSCN = new(linux.ELIBSCN, ".lib section in a.out corrupted") - ELIBMAX = new(linux.ELIBMAX, "attempting to link in too many shared libraries") - ELIBEXEC = new(linux.ELIBEXEC, "cannot exec a shared library directly") - EILSEQ = new(linux.EILSEQ, "illegal byte sequence") - ERESTART = new(linux.ERESTART, "interrupted system call should be restarted") - ESTRPIPE = new(linux.ESTRPIPE, "streams pipe error") - EUSERS = new(linux.EUSERS, "too many users") - ENOTSOCK = new(linux.ENOTSOCK, "socket operation on non-socket") - EDESTADDRREQ = new(linux.EDESTADDRREQ, "destination address required") - EMSGSIZE = new(linux.EMSGSIZE, "message too long") - EPROTOTYPE = new(linux.EPROTOTYPE, "protocol wrong type for socket") - ENOPROTOOPT = new(linux.ENOPROTOOPT, "protocol not available") - EPROTONOSUPPORT = new(linux.EPROTONOSUPPORT, "protocol not supported") - ESOCKTNOSUPPORT = new(linux.ESOCKTNOSUPPORT, "socket type not supported") - EOPNOTSUPP = new(linux.EOPNOTSUPP, "operation not supported on transport endpoint") - EPFNOSUPPORT = new(linux.EPFNOSUPPORT, "protocol family not supported") - EAFNOSUPPORT = new(linux.EAFNOSUPPORT, "address family not supported by protocol") - EADDRINUSE = new(linux.EADDRINUSE, "address already in use") - EADDRNOTAVAIL = new(linux.EADDRNOTAVAIL, "cannot assign requested address") - ENETDOWN = new(linux.ENETDOWN, "network is down") - ENETUNREACH = new(linux.ENETUNREACH, "network is unreachable") - ENETRESET = new(linux.ENETRESET, "network dropped connection because of reset") - ECONNABORTED = new(linux.ECONNABORTED, "software caused connection abort") - ECONNRESET = new(linux.ECONNRESET, "connection reset by peer") - ENOBUFS = new(linux.ENOBUFS, "no buffer space available") - EISCONN = new(linux.EISCONN, "transport endpoint is already connected") - ENOTCONN = new(linux.ENOTCONN, "transport endpoint is not connected") - ESHUTDOWN = new(linux.ESHUTDOWN, "cannot send after transport endpoint shutdown") - ETOOMANYREFS = new(linux.ETOOMANYREFS, "too many references: cannot splice") - ETIMEDOUT = new(linux.ETIMEDOUT, "connection timed out") - ECONNREFUSED = new(linux.ECONNREFUSED, "connection refused") - EHOSTDOWN = new(linux.EHOSTDOWN, "host is down") - EHOSTUNREACH = new(linux.EHOSTUNREACH, "no route to host") - EALREADY = new(linux.EALREADY, "operation already in progress") - EINPROGRESS = new(linux.EINPROGRESS, "operation now in progress") - ESTALE = new(linux.ESTALE, "stale file handle") - EUCLEAN = new(linux.EUCLEAN, "structure needs cleaning") - ENOTNAM = new(linux.ENOTNAM, "not a XENIX named type file") - ENAVAIL = new(linux.ENAVAIL, "no XENIX semaphores available") - EISNAM = new(linux.EISNAM, "is a named type file") - EREMOTEIO = new(linux.EREMOTEIO, "remote I/O error") - EDQUOT = new(linux.EDQUOT, "quota exceeded") - ENOMEDIUM = new(linux.ENOMEDIUM, "no medium found") - EMEDIUMTYPE = new(linux.EMEDIUMTYPE, "wrong medium type") - ECANCELED = new(linux.ECANCELED, "operation Canceled") - ENOKEY = new(linux.ENOKEY, "required key not available") - EKEYEXPIRED = new(linux.EKEYEXPIRED, "key has expired") - EKEYREVOKED = new(linux.EKEYREVOKED, "key has been revoked") - EKEYREJECTED = new(linux.EKEYREJECTED, "key was rejected by service") - EOWNERDEAD = new(linux.EOWNERDEAD, "owner died") - ENOTRECOVERABLE = new(linux.ENOTRECOVERABLE, "state not recoverable") - ERFKILL = new(linux.ERFKILL, "operation not possible due to RF-kill") - EHWPOISON = new(linux.EHWPOISON, "memory page has hardware error") -) diff --git a/pkg/sentry/kernel/BUILD b/pkg/sentry/kernel/BUILD index 188c0ebff..a82d641da 100644 --- a/pkg/sentry/kernel/BUILD +++ b/pkg/sentry/kernel/BUILD @@ -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", 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/loader/BUILD b/pkg/sentry/loader/BUILD index 4c65215fa..80f862628 100644 --- a/pkg/sentry/loader/BUILD +++ b/pkg/sentry/loader/BUILD @@ -17,6 +17,7 @@ go_library( deps = [ "//pkg/abi", "//pkg/abi/linux", + "//pkg/abi/linux/errno", "//pkg/context", "//pkg/cpuid", "//pkg/hostarch", 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/socket/netlink/BUILD b/pkg/sentry/socket/netlink/BUILD index 64cd263da..6b83698ad 100644 --- a/pkg/sentry/socket/netlink/BUILD +++ b/pkg/sentry/socket/netlink/BUILD @@ -14,6 +14,7 @@ go_library( visibility = ["//pkg/sentry:internal"], deps = [ "//pkg/abi/linux", + "//pkg/abi/linux/errno", "//pkg/bits", "//pkg/context", "//pkg/hostarch", diff --git a/pkg/sentry/socket/netlink/socket.go b/pkg/sentry/socket/netlink/socket.go index 280563d09..c9f784cf4 100644 --- a/pkg/sentry/socket/netlink/socket.go +++ b/pkg/sentry/socket/netlink/socket.go @@ -20,6 +20,7 @@ import ( "math" "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/marshal" @@ -56,7 +57,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() diff --git a/pkg/sentry/socket/netstack/BUILD b/pkg/sentry/socket/netstack/BUILD index 9561b7c25..96c425619 100644 --- a/pkg/sentry/socket/netstack/BUILD +++ b/pkg/sentry/socket/netstack/BUILD @@ -19,6 +19,7 @@ go_library( ], deps = [ "//pkg/abi/linux", + "//pkg/abi/linux/errno", "//pkg/context", "//pkg/hostarch", "//pkg/log", diff --git a/pkg/sentry/socket/netstack/netstack.go b/pkg/sentry/socket/netstack/netstack.go index 11ba80497..66d0fcb47 100644 --- a/pkg/sentry/socket/netstack/netstack.go +++ b/pkg/sentry/socket/netstack/netstack.go @@ -36,6 +36,7 @@ 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/hostarch" "gvisor.dev/gvisor/pkg/log" @@ -289,7 +290,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. diff --git a/pkg/syserr/BUILD b/pkg/syserr/BUILD index 9cc9e3bf2..7b3160309 100644 --- a/pkg/syserr/BUILD +++ b/pkg/syserr/BUILD @@ -11,7 +11,7 @@ go_library( ], visibility = ["//visibility:public"], deps = [ - "//pkg/abi/linux", + "//pkg/abi/linux/errno", "//pkg/syserror", "//pkg/tcpip", "@org_golang_x_sys//unix:go_default_library", diff --git a/pkg/syserr/netstack.go b/pkg/syserr/netstack.go index 90be24e15..eb44f1254 100644 --- a/pkg/syserr/netstack.go +++ b/pkg/syserr/netstack.go @@ -17,7 +17,7 @@ package syserr import ( "fmt" - "gvisor.dev/gvisor/pkg/abi/linux" + "gvisor.dev/gvisor/pkg/abi/linux/errno" "gvisor.dev/gvisor/pkg/tcpip" ) @@ -25,33 +25,33 @@ import ( // Mapping for tcpip.Error types. var ( - ErrUnknownProtocol = New((&tcpip.ErrUnknownProtocol{}).String(), linux.EINVAL) - ErrUnknownNICID = New((&tcpip.ErrUnknownNICID{}).String(), linux.ENODEV) - ErrUnknownDevice = New((&tcpip.ErrUnknownDevice{}).String(), linux.ENODEV) - ErrUnknownProtocolOption = New((&tcpip.ErrUnknownProtocolOption{}).String(), linux.ENOPROTOOPT) - ErrDuplicateNICID = New((&tcpip.ErrDuplicateNICID{}).String(), linux.EEXIST) - ErrDuplicateAddress = New((&tcpip.ErrDuplicateAddress{}).String(), linux.EEXIST) - ErrAlreadyBound = New((&tcpip.ErrAlreadyBound{}).String(), linux.EINVAL) - ErrInvalidEndpointState = New((&tcpip.ErrInvalidEndpointState{}).String(), linux.EINVAL) - ErrAlreadyConnecting = New((&tcpip.ErrAlreadyConnecting{}).String(), linux.EALREADY) - ErrNoPortAvailable = New((&tcpip.ErrNoPortAvailable{}).String(), linux.EAGAIN) - ErrPortInUse = New((&tcpip.ErrPortInUse{}).String(), linux.EADDRINUSE) - ErrBadLocalAddress = New((&tcpip.ErrBadLocalAddress{}).String(), linux.EADDRNOTAVAIL) - ErrClosedForSend = New((&tcpip.ErrClosedForSend{}).String(), linux.EPIPE) - ErrClosedForReceive = New((&tcpip.ErrClosedForReceive{}).String(), linux.NOERRNO) - ErrTimeout = New((&tcpip.ErrTimeout{}).String(), linux.ETIMEDOUT) - ErrAborted = New((&tcpip.ErrAborted{}).String(), linux.EPIPE) - ErrConnectStarted = New((&tcpip.ErrConnectStarted{}).String(), linux.EINPROGRESS) - ErrDestinationRequired = New((&tcpip.ErrDestinationRequired{}).String(), linux.EDESTADDRREQ) - ErrNotSupported = New((&tcpip.ErrNotSupported{}).String(), linux.EOPNOTSUPP) - ErrQueueSizeNotSupported = New((&tcpip.ErrQueueSizeNotSupported{}).String(), linux.ENOTTY) - ErrNoSuchFile = New((&tcpip.ErrNoSuchFile{}).String(), linux.ENOENT) - ErrInvalidOptionValue = New((&tcpip.ErrInvalidOptionValue{}).String(), linux.EINVAL) - ErrBroadcastDisabled = New((&tcpip.ErrBroadcastDisabled{}).String(), linux.EACCES) - ErrNotPermittedNet = New((&tcpip.ErrNotPermitted{}).String(), linux.EPERM) - ErrBadBuffer = New((&tcpip.ErrBadBuffer{}).String(), linux.EFAULT) - ErrMalformedHeader = New((&tcpip.ErrMalformedHeader{}).String(), linux.EINVAL) - ErrInvalidPortRange = New((&tcpip.ErrInvalidPortRange{}).String(), linux.EINVAL) + ErrUnknownProtocol = New((&tcpip.ErrUnknownProtocol{}).String(), errno.EINVAL) + ErrUnknownNICID = New((&tcpip.ErrUnknownNICID{}).String(), errno.ENODEV) + ErrUnknownDevice = New((&tcpip.ErrUnknownDevice{}).String(), errno.ENODEV) + ErrUnknownProtocolOption = New((&tcpip.ErrUnknownProtocolOption{}).String(), errno.ENOPROTOOPT) + ErrDuplicateNICID = New((&tcpip.ErrDuplicateNICID{}).String(), errno.EEXIST) + ErrDuplicateAddress = New((&tcpip.ErrDuplicateAddress{}).String(), errno.EEXIST) + ErrAlreadyBound = New((&tcpip.ErrAlreadyBound{}).String(), errno.EINVAL) + ErrInvalidEndpointState = New((&tcpip.ErrInvalidEndpointState{}).String(), errno.EINVAL) + ErrAlreadyConnecting = New((&tcpip.ErrAlreadyConnecting{}).String(), errno.EALREADY) + ErrNoPortAvailable = New((&tcpip.ErrNoPortAvailable{}).String(), errno.EAGAIN) + ErrPortInUse = New((&tcpip.ErrPortInUse{}).String(), errno.EADDRINUSE) + ErrBadLocalAddress = New((&tcpip.ErrBadLocalAddress{}).String(), errno.EADDRNOTAVAIL) + ErrClosedForSend = New((&tcpip.ErrClosedForSend{}).String(), errno.EPIPE) + ErrClosedForReceive = New((&tcpip.ErrClosedForReceive{}).String(), errno.NOERRNO) + ErrTimeout = New((&tcpip.ErrTimeout{}).String(), errno.ETIMEDOUT) + ErrAborted = New((&tcpip.ErrAborted{}).String(), errno.EPIPE) + ErrConnectStarted = New((&tcpip.ErrConnectStarted{}).String(), errno.EINPROGRESS) + ErrDestinationRequired = New((&tcpip.ErrDestinationRequired{}).String(), errno.EDESTADDRREQ) + ErrNotSupported = New((&tcpip.ErrNotSupported{}).String(), errno.EOPNOTSUPP) + ErrQueueSizeNotSupported = New((&tcpip.ErrQueueSizeNotSupported{}).String(), errno.ENOTTY) + ErrNoSuchFile = New((&tcpip.ErrNoSuchFile{}).String(), errno.ENOENT) + ErrInvalidOptionValue = New((&tcpip.ErrInvalidOptionValue{}).String(), errno.EINVAL) + ErrBroadcastDisabled = New((&tcpip.ErrBroadcastDisabled{}).String(), errno.EACCES) + ErrNotPermittedNet = New((&tcpip.ErrNotPermitted{}).String(), errno.EPERM) + ErrBadBuffer = New((&tcpip.ErrBadBuffer{}).String(), errno.EFAULT) + ErrMalformedHeader = New((&tcpip.ErrMalformedHeader{}).String(), errno.EINVAL) + ErrInvalidPortRange = New((&tcpip.ErrInvalidPortRange{}).String(), errno.EINVAL) ) // TranslateNetstackError converts an error from the tcpip package to a sentry diff --git a/pkg/syserr/syserr.go b/pkg/syserr/syserr.go index d70521f32..fb77ac8bd 100644 --- a/pkg/syserr/syserr.go +++ b/pkg/syserr/syserr.go @@ -21,7 +21,7 @@ import ( "fmt" "golang.org/x/sys/unix" - "gvisor.dev/gvisor/pkg/abi/linux" + "gvisor.dev/gvisor/pkg/abi/linux/errno" "gvisor.dev/gvisor/pkg/syserror" ) @@ -31,26 +31,25 @@ type Error struct { message string // noTranslation indicates that this Error cannot be translated to a - // linux.Errno. + // errno.Errno. noTranslation bool - // errno is the linux.Errno this Error should be translated to. - errno linux.Errno + // errno is the errno.Errno this Error should be translated to. + errno errno.Errno } // New creates a new Error and adds a translation for it. // // New must only be called at init. -func New(message string, linuxTranslation linux.Errno) *Error { +func New(message string, linuxTranslation errno.Errno) *Error { err := &Error{message: message, errno: linuxTranslation} // TODO(b/34162363): Remove this. - errno := linuxTranslation - if errno < 0 || int(errno) >= len(linuxBackwardsTranslations) { - panic(fmt.Sprint("invalid errno: ", errno)) + if int(err.errno) >= len(linuxBackwardsTranslations) { + panic(fmt.Sprint("invalid errno: ", err.errno)) } - e := error(unix.Errno(errno)) + e := error(unix.Errno(err.errno)) // syserror.ErrWouldBlock gets translated to syserror.EWOULDBLOCK and // enables proper blocking semantics. This should temporary address the // class of blocking bugs that keep popping up with the current state of @@ -58,7 +57,7 @@ func New(message string, linuxTranslation linux.Errno) *Error { if e == syserror.EWOULDBLOCK { e = syserror.ErrWouldBlock } - linuxBackwardsTranslations[errno] = linuxBackwardsTranslation{err: e, ok: true} + linuxBackwardsTranslations[err.errno] = linuxBackwardsTranslation{err: e, ok: true} return err } @@ -69,7 +68,7 @@ func New(message string, linuxTranslation linux.Errno) *Error { // NewDynamic should only be used sparingly and not be used for static error // messages. Errors with static error messages should be declared with New as // global variables. -func NewDynamic(message string, linuxTranslation linux.Errno) *Error { +func NewDynamic(message string, linuxTranslation errno.Errno) *Error { return &Error{message: message, errno: linuxTranslation} } @@ -82,7 +81,7 @@ func NewWithoutTranslation(message string) *Error { return &Error{message: message, noTranslation: true} } -func newWithHost(message string, linuxTranslation linux.Errno, hostErrno unix.Errno) *Error { +func newWithHost(message string, linuxTranslation errno.Errno, hostErrno unix.Errno) *Error { e := New(message, linuxTranslation) addLinuxHostTranslation(hostErrno, e) return e @@ -114,19 +113,19 @@ func (e *Error) ToError() error { if e.noTranslation { panic(fmt.Sprintf("error %q does not support translation", e.message)) } - errno := int(e.errno) - if errno == linux.NOERRNO { + err := int(e.errno) + if err == errno.NOERRNO { return nil } - if errno <= 0 || errno >= len(linuxBackwardsTranslations) || !linuxBackwardsTranslations[errno].ok { - panic(fmt.Sprintf("unknown error %q (%d)", e.message, errno)) + if err >= len(linuxBackwardsTranslations) || !linuxBackwardsTranslations[err].ok { + panic(fmt.Sprintf("unknown error %q (%d)", e.message, err)) } - return linuxBackwardsTranslations[errno].err + return linuxBackwardsTranslations[err].err } // ToLinux converts the Error to a Linux ABI error that can be returned to the // application. -func (e *Error) ToLinux() linux.Errno { +func (e *Error) ToLinux() errno.Errno { if e.noTranslation { panic(fmt.Sprintf("No Linux ABI translation available for %q", e.message)) } @@ -138,137 +137,137 @@ func (e *Error) ToLinux() linux.Errno { // Some of the errors should be replaced with package specific errors and // others should be removed entirely. var ( - ErrNotPermitted = newWithHost("operation not permitted", linux.EPERM, unix.EPERM) - ErrNoFileOrDir = newWithHost("no such file or directory", linux.ENOENT, unix.ENOENT) - ErrNoProcess = newWithHost("no such process", linux.ESRCH, unix.ESRCH) - ErrInterrupted = newWithHost("interrupted system call", linux.EINTR, unix.EINTR) - ErrIO = newWithHost("I/O error", linux.EIO, unix.EIO) - ErrDeviceOrAddress = newWithHost("no such device or address", linux.ENXIO, unix.ENXIO) - ErrTooManyArgs = newWithHost("argument list too long", linux.E2BIG, unix.E2BIG) - ErrEcec = newWithHost("exec format error", linux.ENOEXEC, unix.ENOEXEC) - ErrBadFD = newWithHost("bad file number", linux.EBADF, unix.EBADF) - ErrNoChild = newWithHost("no child processes", linux.ECHILD, unix.ECHILD) - ErrTryAgain = newWithHost("try again", linux.EAGAIN, unix.EAGAIN) - ErrNoMemory = newWithHost("out of memory", linux.ENOMEM, unix.ENOMEM) - ErrPermissionDenied = newWithHost("permission denied", linux.EACCES, unix.EACCES) - ErrBadAddress = newWithHost("bad address", linux.EFAULT, unix.EFAULT) - ErrNotBlockDevice = newWithHost("block device required", linux.ENOTBLK, unix.ENOTBLK) - ErrBusy = newWithHost("device or resource busy", linux.EBUSY, unix.EBUSY) - ErrExists = newWithHost("file exists", linux.EEXIST, unix.EEXIST) - ErrCrossDeviceLink = newWithHost("cross-device link", linux.EXDEV, unix.EXDEV) - ErrNoDevice = newWithHost("no such device", linux.ENODEV, unix.ENODEV) - ErrNotDir = newWithHost("not a directory", linux.ENOTDIR, unix.ENOTDIR) - ErrIsDir = newWithHost("is a directory", linux.EISDIR, unix.EISDIR) - ErrInvalidArgument = newWithHost("invalid argument", linux.EINVAL, unix.EINVAL) - ErrFileTableOverflow = newWithHost("file table overflow", linux.ENFILE, unix.ENFILE) - ErrTooManyOpenFiles = newWithHost("too many open files", linux.EMFILE, unix.EMFILE) - ErrNotTTY = newWithHost("not a typewriter", linux.ENOTTY, unix.ENOTTY) - ErrTestFileBusy = newWithHost("text file busy", linux.ETXTBSY, unix.ETXTBSY) - ErrFileTooBig = newWithHost("file too large", linux.EFBIG, unix.EFBIG) - ErrNoSpace = newWithHost("no space left on device", linux.ENOSPC, unix.ENOSPC) - ErrIllegalSeek = newWithHost("illegal seek", linux.ESPIPE, unix.ESPIPE) - ErrReadOnlyFS = newWithHost("read-only file system", linux.EROFS, unix.EROFS) - ErrTooManyLinks = newWithHost("too many links", linux.EMLINK, unix.EMLINK) - ErrBrokenPipe = newWithHost("broken pipe", linux.EPIPE, unix.EPIPE) - ErrDomain = newWithHost("math argument out of domain of func", linux.EDOM, unix.EDOM) - ErrRange = newWithHost("math result not representable", linux.ERANGE, unix.ERANGE) - ErrDeadlock = newWithHost("resource deadlock would occur", linux.EDEADLOCK, unix.EDEADLOCK) - ErrNameTooLong = newWithHost("file name too long", linux.ENAMETOOLONG, unix.ENAMETOOLONG) - ErrNoLocksAvailable = newWithHost("no record locks available", linux.ENOLCK, unix.ENOLCK) - ErrInvalidSyscall = newWithHost("invalid system call number", linux.ENOSYS, unix.ENOSYS) - ErrDirNotEmpty = newWithHost("directory not empty", linux.ENOTEMPTY, unix.ENOTEMPTY) - ErrLinkLoop = newWithHost("too many symbolic links encountered", linux.ELOOP, unix.ELOOP) - ErrNoMessage = newWithHost("no message of desired type", linux.ENOMSG, unix.ENOMSG) - ErrIdentifierRemoved = newWithHost("identifier removed", linux.EIDRM, unix.EIDRM) - ErrChannelOutOfRange = newWithHost("channel number out of range", linux.ECHRNG, unix.ECHRNG) - ErrLevelTwoNotSynced = newWithHost("level 2 not synchronized", linux.EL2NSYNC, unix.EL2NSYNC) - ErrLevelThreeHalted = newWithHost("level 3 halted", linux.EL3HLT, unix.EL3HLT) - ErrLevelThreeReset = newWithHost("level 3 reset", linux.EL3RST, unix.EL3RST) - ErrLinkNumberOutOfRange = newWithHost("link number out of range", linux.ELNRNG, unix.ELNRNG) - ErrProtocolDriverNotAttached = newWithHost("protocol driver not attached", linux.EUNATCH, unix.EUNATCH) - ErrNoCSIAvailable = newWithHost("no CSI structure available", linux.ENOCSI, unix.ENOCSI) - ErrLevelTwoHalted = newWithHost("level 2 halted", linux.EL2HLT, unix.EL2HLT) - ErrInvalidExchange = newWithHost("invalid exchange", linux.EBADE, unix.EBADE) - ErrInvalidRequestDescriptor = newWithHost("invalid request descriptor", linux.EBADR, unix.EBADR) - ErrExchangeFull = newWithHost("exchange full", linux.EXFULL, unix.EXFULL) - ErrNoAnode = newWithHost("no anode", linux.ENOANO, unix.ENOANO) - ErrInvalidRequestCode = newWithHost("invalid request code", linux.EBADRQC, unix.EBADRQC) - ErrInvalidSlot = newWithHost("invalid slot", linux.EBADSLT, unix.EBADSLT) - ErrBadFontFile = newWithHost("bad font file format", linux.EBFONT, unix.EBFONT) - ErrNotStream = newWithHost("device not a stream", linux.ENOSTR, unix.ENOSTR) - ErrNoDataAvailable = newWithHost("no data available", linux.ENODATA, unix.ENODATA) - ErrTimerExpired = newWithHost("timer expired", linux.ETIME, unix.ETIME) - ErrStreamsResourceDepleted = newWithHost("out of streams resources", linux.ENOSR, unix.ENOSR) - ErrMachineNotOnNetwork = newWithHost("machine is not on the network", linux.ENONET, unix.ENONET) - ErrPackageNotInstalled = newWithHost("package not installed", linux.ENOPKG, unix.ENOPKG) - ErrIsRemote = newWithHost("object is remote", linux.EREMOTE, unix.EREMOTE) - ErrNoLink = newWithHost("link has been severed", linux.ENOLINK, unix.ENOLINK) - ErrAdvertise = newWithHost("advertise error", linux.EADV, unix.EADV) - ErrSRMount = newWithHost("srmount error", linux.ESRMNT, unix.ESRMNT) - ErrSendCommunication = newWithHost("communication error on send", linux.ECOMM, unix.ECOMM) - ErrProtocol = newWithHost("protocol error", linux.EPROTO, unix.EPROTO) - ErrMultihopAttempted = newWithHost("multihop attempted", linux.EMULTIHOP, unix.EMULTIHOP) - ErrRFS = newWithHost("RFS specific error", linux.EDOTDOT, unix.EDOTDOT) - ErrInvalidDataMessage = newWithHost("not a data message", linux.EBADMSG, unix.EBADMSG) - ErrOverflow = newWithHost("value too large for defined data type", linux.EOVERFLOW, unix.EOVERFLOW) - ErrNetworkNameNotUnique = newWithHost("name not unique on network", linux.ENOTUNIQ, unix.ENOTUNIQ) - ErrFDInBadState = newWithHost("file descriptor in bad state", linux.EBADFD, unix.EBADFD) - ErrRemoteAddressChanged = newWithHost("remote address changed", linux.EREMCHG, unix.EREMCHG) - ErrSharedLibraryInaccessible = newWithHost("can not access a needed shared library", linux.ELIBACC, unix.ELIBACC) - ErrCorruptedSharedLibrary = newWithHost("accessing a corrupted shared library", linux.ELIBBAD, unix.ELIBBAD) - ErrLibSectionCorrupted = newWithHost(".lib section in a.out corrupted", linux.ELIBSCN, unix.ELIBSCN) - ErrTooManySharedLibraries = newWithHost("attempting to link in too many shared libraries", linux.ELIBMAX, unix.ELIBMAX) - ErrSharedLibraryExeced = newWithHost("cannot exec a shared library directly", linux.ELIBEXEC, unix.ELIBEXEC) - ErrIllegalByteSequence = newWithHost("illegal byte sequence", linux.EILSEQ, unix.EILSEQ) - ErrShouldRestart = newWithHost("interrupted system call should be restarted", linux.ERESTART, unix.ERESTART) - ErrStreamPipe = newWithHost("streams pipe error", linux.ESTRPIPE, unix.ESTRPIPE) - ErrTooManyUsers = newWithHost("too many users", linux.EUSERS, unix.EUSERS) - ErrNotASocket = newWithHost("socket operation on non-socket", linux.ENOTSOCK, unix.ENOTSOCK) - ErrDestinationAddressRequired = newWithHost("destination address required", linux.EDESTADDRREQ, unix.EDESTADDRREQ) - ErrMessageTooLong = newWithHost("message too long", linux.EMSGSIZE, unix.EMSGSIZE) - ErrWrongProtocolForSocket = newWithHost("protocol wrong type for socket", linux.EPROTOTYPE, unix.EPROTOTYPE) - ErrProtocolNotAvailable = newWithHost("protocol not available", linux.ENOPROTOOPT, unix.ENOPROTOOPT) - ErrProtocolNotSupported = newWithHost("protocol not supported", linux.EPROTONOSUPPORT, unix.EPROTONOSUPPORT) - ErrSocketNotSupported = newWithHost("socket type not supported", linux.ESOCKTNOSUPPORT, unix.ESOCKTNOSUPPORT) - ErrEndpointOperation = newWithHost("operation not supported on transport endpoint", linux.EOPNOTSUPP, unix.EOPNOTSUPP) - ErrProtocolFamilyNotSupported = newWithHost("protocol family not supported", linux.EPFNOSUPPORT, unix.EPFNOSUPPORT) - ErrAddressFamilyNotSupported = newWithHost("address family not supported by protocol", linux.EAFNOSUPPORT, unix.EAFNOSUPPORT) - ErrAddressInUse = newWithHost("address already in use", linux.EADDRINUSE, unix.EADDRINUSE) - ErrAddressNotAvailable = newWithHost("cannot assign requested address", linux.EADDRNOTAVAIL, unix.EADDRNOTAVAIL) - ErrNetworkDown = newWithHost("network is down", linux.ENETDOWN, unix.ENETDOWN) - ErrNetworkUnreachable = newWithHost("network is unreachable", linux.ENETUNREACH, unix.ENETUNREACH) - ErrNetworkReset = newWithHost("network dropped connection because of reset", linux.ENETRESET, unix.ENETRESET) - ErrConnectionAborted = newWithHost("software caused connection abort", linux.ECONNABORTED, unix.ECONNABORTED) - ErrConnectionReset = newWithHost("connection reset by peer", linux.ECONNRESET, unix.ECONNRESET) - ErrNoBufferSpace = newWithHost("no buffer space available", linux.ENOBUFS, unix.ENOBUFS) - ErrAlreadyConnected = newWithHost("transport endpoint is already connected", linux.EISCONN, unix.EISCONN) - ErrNotConnected = newWithHost("transport endpoint is not connected", linux.ENOTCONN, unix.ENOTCONN) - ErrShutdown = newWithHost("cannot send after transport endpoint shutdown", linux.ESHUTDOWN, unix.ESHUTDOWN) - ErrTooManyRefs = newWithHost("too many references: cannot splice", linux.ETOOMANYREFS, unix.ETOOMANYREFS) - ErrTimedOut = newWithHost("connection timed out", linux.ETIMEDOUT, unix.ETIMEDOUT) - ErrConnectionRefused = newWithHost("connection refused", linux.ECONNREFUSED, unix.ECONNREFUSED) - ErrHostDown = newWithHost("host is down", linux.EHOSTDOWN, unix.EHOSTDOWN) - ErrNoRoute = newWithHost("no route to host", linux.EHOSTUNREACH, unix.EHOSTUNREACH) - ErrAlreadyInProgress = newWithHost("operation already in progress", linux.EALREADY, unix.EALREADY) - ErrInProgress = newWithHost("operation now in progress", linux.EINPROGRESS, unix.EINPROGRESS) - ErrStaleFileHandle = newWithHost("stale file handle", linux.ESTALE, unix.ESTALE) - ErrStructureNeedsCleaning = newWithHost("structure needs cleaning", linux.EUCLEAN, unix.EUCLEAN) - ErrIsNamedFile = newWithHost("is a named type file", linux.ENOTNAM, unix.ENOTNAM) - ErrRemoteIO = newWithHost("remote I/O error", linux.EREMOTEIO, unix.EREMOTEIO) - ErrQuotaExceeded = newWithHost("quota exceeded", linux.EDQUOT, unix.EDQUOT) - ErrNoMedium = newWithHost("no medium found", linux.ENOMEDIUM, unix.ENOMEDIUM) - ErrWrongMediumType = newWithHost("wrong medium type", linux.EMEDIUMTYPE, unix.EMEDIUMTYPE) - ErrCanceled = newWithHost("operation canceled", linux.ECANCELED, unix.ECANCELED) - ErrNoKey = newWithHost("required key not available", linux.ENOKEY, unix.ENOKEY) - ErrKeyExpired = newWithHost("key has expired", linux.EKEYEXPIRED, unix.EKEYEXPIRED) - ErrKeyRevoked = newWithHost("key has been revoked", linux.EKEYREVOKED, unix.EKEYREVOKED) - ErrKeyRejected = newWithHost("key was rejected by service", linux.EKEYREJECTED, unix.EKEYREJECTED) - ErrOwnerDied = newWithHost("owner died", linux.EOWNERDEAD, unix.EOWNERDEAD) - ErrNotRecoverable = newWithHost("state not recoverable", linux.ENOTRECOVERABLE, unix.ENOTRECOVERABLE) + ErrNotPermitted = newWithHost("operation not permitted", errno.EPERM, unix.EPERM) + ErrNoFileOrDir = newWithHost("no such file or directory", errno.ENOENT, unix.ENOENT) + ErrNoProcess = newWithHost("no such process", errno.ESRCH, unix.ESRCH) + ErrInterrupted = newWithHost("interrupted system call", errno.EINTR, unix.EINTR) + ErrIO = newWithHost("I/O error", errno.EIO, unix.EIO) + ErrDeviceOrAddress = newWithHost("no such device or address", errno.ENXIO, unix.ENXIO) + ErrTooManyArgs = newWithHost("argument list too long", errno.E2BIG, unix.E2BIG) + ErrEcec = newWithHost("exec format error", errno.ENOEXEC, unix.ENOEXEC) + ErrBadFD = newWithHost("bad file number", errno.EBADF, unix.EBADF) + ErrNoChild = newWithHost("no child processes", errno.ECHILD, unix.ECHILD) + ErrTryAgain = newWithHost("try again", errno.EAGAIN, unix.EAGAIN) + ErrNoMemory = newWithHost("out of memory", errno.ENOMEM, unix.ENOMEM) + ErrPermissionDenied = newWithHost("permission denied", errno.EACCES, unix.EACCES) + ErrBadAddress = newWithHost("bad address", errno.EFAULT, unix.EFAULT) + ErrNotBlockDevice = newWithHost("block device required", errno.ENOTBLK, unix.ENOTBLK) + ErrBusy = newWithHost("device or resource busy", errno.EBUSY, unix.EBUSY) + ErrExists = newWithHost("file exists", errno.EEXIST, unix.EEXIST) + ErrCrossDeviceLink = newWithHost("cross-device link", errno.EXDEV, unix.EXDEV) + ErrNoDevice = newWithHost("no such device", errno.ENODEV, unix.ENODEV) + ErrNotDir = newWithHost("not a directory", errno.ENOTDIR, unix.ENOTDIR) + ErrIsDir = newWithHost("is a directory", errno.EISDIR, unix.EISDIR) + ErrInvalidArgument = newWithHost("invalid argument", errno.EINVAL, unix.EINVAL) + ErrFileTableOverflow = newWithHost("file table overflow", errno.ENFILE, unix.ENFILE) + ErrTooManyOpenFiles = newWithHost("too many open files", errno.EMFILE, unix.EMFILE) + ErrNotTTY = newWithHost("not a typewriter", errno.ENOTTY, unix.ENOTTY) + ErrTestFileBusy = newWithHost("text file busy", errno.ETXTBSY, unix.ETXTBSY) + ErrFileTooBig = newWithHost("file too large", errno.EFBIG, unix.EFBIG) + ErrNoSpace = newWithHost("no space left on device", errno.ENOSPC, unix.ENOSPC) + ErrIllegalSeek = newWithHost("illegal seek", errno.ESPIPE, unix.ESPIPE) + ErrReadOnlyFS = newWithHost("read-only file system", errno.EROFS, unix.EROFS) + ErrTooManyLinks = newWithHost("too many links", errno.EMLINK, unix.EMLINK) + ErrBrokenPipe = newWithHost("broken pipe", errno.EPIPE, unix.EPIPE) + ErrDomain = newWithHost("math argument out of domain of func", errno.EDOM, unix.EDOM) + ErrRange = newWithHost("math result not representable", errno.ERANGE, unix.ERANGE) + ErrDeadlock = newWithHost("resource deadlock would occur", errno.EDEADLOCK, unix.EDEADLOCK) + ErrNameTooLong = newWithHost("file name too long", errno.ENAMETOOLONG, unix.ENAMETOOLONG) + ErrNoLocksAvailable = newWithHost("no record locks available", errno.ENOLCK, unix.ENOLCK) + ErrInvalidSyscall = newWithHost("invalid system call number", errno.ENOSYS, unix.ENOSYS) + ErrDirNotEmpty = newWithHost("directory not empty", errno.ENOTEMPTY, unix.ENOTEMPTY) + ErrLinkLoop = newWithHost("too many symbolic links encountered", errno.ELOOP, unix.ELOOP) + ErrNoMessage = newWithHost("no message of desired type", errno.ENOMSG, unix.ENOMSG) + ErrIdentifierRemoved = newWithHost("identifier removed", errno.EIDRM, unix.EIDRM) + ErrChannelOutOfRange = newWithHost("channel number out of range", errno.ECHRNG, unix.ECHRNG) + ErrLevelTwoNotSynced = newWithHost("level 2 not synchronized", errno.EL2NSYNC, unix.EL2NSYNC) + ErrLevelThreeHalted = newWithHost("level 3 halted", errno.EL3HLT, unix.EL3HLT) + ErrLevelThreeReset = newWithHost("level 3 reset", errno.EL3RST, unix.EL3RST) + ErrLinkNumberOutOfRange = newWithHost("link number out of range", errno.ELNRNG, unix.ELNRNG) + ErrProtocolDriverNotAttached = newWithHost("protocol driver not attached", errno.EUNATCH, unix.EUNATCH) + ErrNoCSIAvailable = newWithHost("no CSI structure available", errno.ENOCSI, unix.ENOCSI) + ErrLevelTwoHalted = newWithHost("level 2 halted", errno.EL2HLT, unix.EL2HLT) + ErrInvalidExchange = newWithHost("invalid exchange", errno.EBADE, unix.EBADE) + ErrInvalidRequestDescriptor = newWithHost("invalid request descriptor", errno.EBADR, unix.EBADR) + ErrExchangeFull = newWithHost("exchange full", errno.EXFULL, unix.EXFULL) + ErrNoAnode = newWithHost("no anode", errno.ENOANO, unix.ENOANO) + ErrInvalidRequestCode = newWithHost("invalid request code", errno.EBADRQC, unix.EBADRQC) + ErrInvalidSlot = newWithHost("invalid slot", errno.EBADSLT, unix.EBADSLT) + ErrBadFontFile = newWithHost("bad font file format", errno.EBFONT, unix.EBFONT) + ErrNotStream = newWithHost("device not a stream", errno.ENOSTR, unix.ENOSTR) + ErrNoDataAvailable = newWithHost("no data available", errno.ENODATA, unix.ENODATA) + ErrTimerExpired = newWithHost("timer expired", errno.ETIME, unix.ETIME) + ErrStreamsResourceDepleted = newWithHost("out of streams resources", errno.ENOSR, unix.ENOSR) + ErrMachineNotOnNetwork = newWithHost("machine is not on the network", errno.ENONET, unix.ENONET) + ErrPackageNotInstalled = newWithHost("package not installed", errno.ENOPKG, unix.ENOPKG) + ErrIsRemote = newWithHost("object is remote", errno.EREMOTE, unix.EREMOTE) + ErrNoLink = newWithHost("link has been severed", errno.ENOLINK, unix.ENOLINK) + ErrAdvertise = newWithHost("advertise error", errno.EADV, unix.EADV) + ErrSRMount = newWithHost("srmount error", errno.ESRMNT, unix.ESRMNT) + ErrSendCommunication = newWithHost("communication error on send", errno.ECOMM, unix.ECOMM) + ErrProtocol = newWithHost("protocol error", errno.EPROTO, unix.EPROTO) + ErrMultihopAttempted = newWithHost("multihop attempted", errno.EMULTIHOP, unix.EMULTIHOP) + ErrRFS = newWithHost("RFS specific error", errno.EDOTDOT, unix.EDOTDOT) + ErrInvalidDataMessage = newWithHost("not a data message", errno.EBADMSG, unix.EBADMSG) + ErrOverflow = newWithHost("value too large for defined data type", errno.EOVERFLOW, unix.EOVERFLOW) + ErrNetworkNameNotUnique = newWithHost("name not unique on network", errno.ENOTUNIQ, unix.ENOTUNIQ) + ErrFDInBadState = newWithHost("file descriptor in bad state", errno.EBADFD, unix.EBADFD) + ErrRemoteAddressChanged = newWithHost("remote address changed", errno.EREMCHG, unix.EREMCHG) + ErrSharedLibraryInaccessible = newWithHost("can not access a needed shared library", errno.ELIBACC, unix.ELIBACC) + ErrCorruptedSharedLibrary = newWithHost("accessing a corrupted shared library", errno.ELIBBAD, unix.ELIBBAD) + ErrLibSectionCorrupted = newWithHost(".lib section in a.out corrupted", errno.ELIBSCN, unix.ELIBSCN) + ErrTooManySharedLibraries = newWithHost("attempting to link in too many shared libraries", errno.ELIBMAX, unix.ELIBMAX) + ErrSharedLibraryExeced = newWithHost("cannot exec a shared library directly", errno.ELIBEXEC, unix.ELIBEXEC) + ErrIllegalByteSequence = newWithHost("illegal byte sequence", errno.EILSEQ, unix.EILSEQ) + ErrShouldRestart = newWithHost("interrupted system call should be restarted", errno.ERESTART, unix.ERESTART) + ErrStreamPipe = newWithHost("streams pipe error", errno.ESTRPIPE, unix.ESTRPIPE) + ErrTooManyUsers = newWithHost("too many users", errno.EUSERS, unix.EUSERS) + ErrNotASocket = newWithHost("socket operation on non-socket", errno.ENOTSOCK, unix.ENOTSOCK) + ErrDestinationAddressRequired = newWithHost("destination address required", errno.EDESTADDRREQ, unix.EDESTADDRREQ) + ErrMessageTooLong = newWithHost("message too long", errno.EMSGSIZE, unix.EMSGSIZE) + ErrWrongProtocolForSocket = newWithHost("protocol wrong type for socket", errno.EPROTOTYPE, unix.EPROTOTYPE) + ErrProtocolNotAvailable = newWithHost("protocol not available", errno.ENOPROTOOPT, unix.ENOPROTOOPT) + ErrProtocolNotSupported = newWithHost("protocol not supported", errno.EPROTONOSUPPORT, unix.EPROTONOSUPPORT) + ErrSocketNotSupported = newWithHost("socket type not supported", errno.ESOCKTNOSUPPORT, unix.ESOCKTNOSUPPORT) + ErrEndpointOperation = newWithHost("operation not supported on transport endpoint", errno.EOPNOTSUPP, unix.EOPNOTSUPP) + ErrProtocolFamilyNotSupported = newWithHost("protocol family not supported", errno.EPFNOSUPPORT, unix.EPFNOSUPPORT) + ErrAddressFamilyNotSupported = newWithHost("address family not supported by protocol", errno.EAFNOSUPPORT, unix.EAFNOSUPPORT) + ErrAddressInUse = newWithHost("address already in use", errno.EADDRINUSE, unix.EADDRINUSE) + ErrAddressNotAvailable = newWithHost("cannot assign requested address", errno.EADDRNOTAVAIL, unix.EADDRNOTAVAIL) + ErrNetworkDown = newWithHost("network is down", errno.ENETDOWN, unix.ENETDOWN) + ErrNetworkUnreachable = newWithHost("network is unreachable", errno.ENETUNREACH, unix.ENETUNREACH) + ErrNetworkReset = newWithHost("network dropped connection because of reset", errno.ENETRESET, unix.ENETRESET) + ErrConnectionAborted = newWithHost("software caused connection abort", errno.ECONNABORTED, unix.ECONNABORTED) + ErrConnectionReset = newWithHost("connection reset by peer", errno.ECONNRESET, unix.ECONNRESET) + ErrNoBufferSpace = newWithHost("no buffer space available", errno.ENOBUFS, unix.ENOBUFS) + ErrAlreadyConnected = newWithHost("transport endpoint is already connected", errno.EISCONN, unix.EISCONN) + ErrNotConnected = newWithHost("transport endpoint is not connected", errno.ENOTCONN, unix.ENOTCONN) + ErrShutdown = newWithHost("cannot send after transport endpoint shutdown", errno.ESHUTDOWN, unix.ESHUTDOWN) + ErrTooManyRefs = newWithHost("too many references: cannot splice", errno.ETOOMANYREFS, unix.ETOOMANYREFS) + ErrTimedOut = newWithHost("connection timed out", errno.ETIMEDOUT, unix.ETIMEDOUT) + ErrConnectionRefused = newWithHost("connection refused", errno.ECONNREFUSED, unix.ECONNREFUSED) + ErrHostDown = newWithHost("host is down", errno.EHOSTDOWN, unix.EHOSTDOWN) + ErrNoRoute = newWithHost("no route to host", errno.EHOSTUNREACH, unix.EHOSTUNREACH) + ErrAlreadyInProgress = newWithHost("operation already in progress", errno.EALREADY, unix.EALREADY) + ErrInProgress = newWithHost("operation now in progress", errno.EINPROGRESS, unix.EINPROGRESS) + ErrStaleFileHandle = newWithHost("stale file handle", errno.ESTALE, unix.ESTALE) + ErrStructureNeedsCleaning = newWithHost("structure needs cleaning", errno.EUCLEAN, unix.EUCLEAN) + ErrIsNamedFile = newWithHost("is a named type file", errno.ENOTNAM, unix.ENOTNAM) + ErrRemoteIO = newWithHost("remote I/O error", errno.EREMOTEIO, unix.EREMOTEIO) + ErrQuotaExceeded = newWithHost("quota exceeded", errno.EDQUOT, unix.EDQUOT) + ErrNoMedium = newWithHost("no medium found", errno.ENOMEDIUM, unix.ENOMEDIUM) + ErrWrongMediumType = newWithHost("wrong medium type", errno.EMEDIUMTYPE, unix.EMEDIUMTYPE) + ErrCanceled = newWithHost("operation canceled", errno.ECANCELED, unix.ECANCELED) + ErrNoKey = newWithHost("required key not available", errno.ENOKEY, unix.ENOKEY) + ErrKeyExpired = newWithHost("key has expired", errno.EKEYEXPIRED, unix.EKEYEXPIRED) + ErrKeyRevoked = newWithHost("key has been revoked", errno.EKEYREVOKED, unix.EKEYREVOKED) + ErrKeyRejected = newWithHost("key was rejected by service", errno.EKEYREJECTED, unix.EKEYREJECTED) + ErrOwnerDied = newWithHost("owner died", errno.EOWNERDEAD, unix.EOWNERDEAD) + ErrNotRecoverable = newWithHost("state not recoverable", errno.ENOTRECOVERABLE, unix.ENOTRECOVERABLE) // ErrWouldBlock translates to EWOULDBLOCK which is the same as EAGAIN // on Linux. - ErrWouldBlock = New("operation would block", linux.EWOULDBLOCK) + ErrWouldBlock = New("operation would block", errno.EWOULDBLOCK) ) // FromError converts a generic error to an *Error. |