diff --git a/pkg/sighandling/BUILD b/pkg/sighandling/BUILD index 72f10f982..b0a6c8a9e 100644 --- a/pkg/sighandling/BUILD +++ b/pkg/sighandling/BUILD @@ -6,7 +6,8 @@ go_library( name = "sighandling", srcs = [ "sighandling.go", - "sighandling_unsafe.go", + "sighandling_darwin.go", + "sighandling_linux_unsafe.go", ], visibility = ["//:sandbox"], deps = [ diff --git a/pkg/sighandling/sighandling_darwin.go b/pkg/sighandling/sighandling_darwin.go new file mode 100644 index 000000000..e7f5ce54c --- /dev/null +++ b/pkg/sighandling/sighandling_darwin.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. + +//go:build darwin +// +build darwin + +package sighandling + +import ( + "errors" + + "golang.org/x/sys/unix" +) + +// IgnoreChildStop sets the SA_NOCLDSTOP flag, causing child processes to not +// generate SIGCHLD when they stop. +func IgnoreChildStop() error { + return errors.New("IgnoreChildStop not supported on Darwin") +} + +// ReplaceSignalHandler replaces the existing signal handler for the provided +// signal with the function pointer at `handler`. This bypasses the Go runtime +// signal handlers, and should only be used for low-level signal handlers where +// use of signal.Notify is not appropriate. +// +// It stores the value of the previously set handler in previous. +func ReplaceSignalHandler(sig unix.Signal, handler uintptr, previous *uintptr) error { + return errors.New("ReplaceSignalHandler not supported on Darwin") +} diff --git a/pkg/sighandling/sighandling_unsafe.go b/pkg/sighandling/sighandling_linux_unsafe.go similarity index 98% rename from pkg/sighandling/sighandling_unsafe.go rename to pkg/sighandling/sighandling_linux_unsafe.go index 7deeda042..68bdfac16 100644 --- a/pkg/sighandling/sighandling_unsafe.go +++ b/pkg/sighandling/sighandling_linux_unsafe.go @@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build linux +// +build linux + package sighandling import ( diff --git a/pkg/syserr/BUILD b/pkg/syserr/BUILD index 551fbb70f..e12193785 100644 --- a/pkg/syserr/BUILD +++ b/pkg/syserr/BUILD @@ -5,6 +5,7 @@ package(licenses = ["notice"]) go_library( name = "syserr", srcs = [ + "host_darwin.go", "host_linux.go", "syserr.go", ], diff --git a/pkg/syserr/host_darwin.go b/pkg/syserr/host_darwin.go new file mode 100644 index 000000000..f68728cde --- /dev/null +++ b/pkg/syserr/host_darwin.go @@ -0,0 +1,50 @@ +// 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. + +//go:build darwin +// +build darwin + +package syserr + +import ( + "fmt" + + "golang.org/x/sys/unix" +) + +const maxErrno = 107 + +type darwinHostTranslation struct { + err *Error + ok bool +} + +var darwinHostTranslations [maxErrno]darwinHostTranslation + +// FromHost translates a unix.Errno to a corresponding Error value. +func FromHost(err unix.Errno) *Error { + if int(err) >= len(darwinHostTranslations) || !darwinHostTranslations[err].ok { + panic(fmt.Sprintf("unknown host errno %q (%d)", err.Error(), err)) + } + return darwinHostTranslations[err].err +} + +// TODO(gvisor.dev/issue/1270): We currently only add translations for errors +// that exist both on Darwin and Linux. +func addHostTranslation(host unix.Errno, trans *Error) { + if darwinHostTranslations[host].ok { + panic(fmt.Sprintf("duplicate translation for host errno %q (%d)", host.Error(), host)) + } + darwinHostTranslations[host] = darwinHostTranslation{err: trans, ok: true} +} diff --git a/pkg/syserr/host_linux.go b/pkg/syserr/host_linux.go index fb92738af..2792e3101 100644 --- a/pkg/syserr/host_linux.go +++ b/pkg/syserr/host_linux.go @@ -21,6 +21,7 @@ import ( "fmt" "golang.org/x/sys/unix" + "gvisor.dev/gvisor/pkg/abi/linux/errno" ) const maxErrno = 134 @@ -40,9 +41,57 @@ func FromHost(err unix.Errno) *Error { return linuxHostTranslations[err].err } -func addLinuxHostTranslation(host unix.Errno, trans *Error) { +func addHostTranslation(host unix.Errno, trans *Error) { if linuxHostTranslations[host].ok { panic(fmt.Sprintf("duplicate translation for host errno %q (%d)", host.Error(), host)) } linuxHostTranslations[host] = linuxHostTranslation{err: trans, ok: true} } + +// TODO(b/34162363): Remove or replace most of these errors. +// +// Some of the errors should be replaced with package specific errors and +// others should be removed entirely. +var ( + ErrDeadlock = newWithHost("resource deadlock would occur", errno.EDEADLOCK, unix.EDEADLOCK) + 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) + ErrMachineNotOnNetwork = newWithHost("machine is not on the network", errno.ENONET, unix.ENONET) + ErrPackageNotInstalled = newWithHost("package not installed", errno.ENOPKG, unix.ENOPKG) + 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) + ErrRFS = newWithHost("RFS specific error", errno.EDOTDOT, unix.EDOTDOT) + 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) + ErrShouldRestart = newWithHost("interrupted system call should be restarted", errno.ERESTART, unix.ERESTART) + ErrStreamPipe = newWithHost("streams pipe error", errno.ESTRPIPE, unix.ESTRPIPE) + 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) + ErrNoMedium = newWithHost("no medium found", errno.ENOMEDIUM, unix.ENOMEDIUM) + ErrWrongMediumType = newWithHost("wrong medium type", errno.EMEDIUMTYPE, unix.EMEDIUMTYPE) + 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) +) diff --git a/pkg/syserr/syserr.go b/pkg/syserr/syserr.go index 17d0b3e1a..ca50f1239 100644 --- a/pkg/syserr/syserr.go +++ b/pkg/syserr/syserr.go @@ -76,7 +76,7 @@ func NewDynamic(message string, linuxTranslation errno.Errno) *Error { func newWithHost(message string, linuxTranslation errno.Errno, hostErrno unix.Errno) *Error { e := New(message, linuxTranslation) - addLinuxHostTranslation(hostErrno, e) + addHostTranslation(hostErrno, e) return e } @@ -129,6 +129,8 @@ func (e *Error) ToLinux() errno.Errno { // // Some of the errors should be replaced with package specific errors and // others should be removed entirely. +// +// Note that some errors are declared in platform-specific files. var ( ErrNotPermitted = newWithHost("operation not permitted", errno.EPERM, unix.EPERM) ErrNoFileOrDir = newWithHost("no such file or directory", errno.ENOENT, unix.ENOENT) @@ -164,7 +166,6 @@ var ( 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) @@ -172,48 +173,17 @@ var ( 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) @@ -244,17 +214,8 @@ var ( 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)