diff options
author | Zach Koopmans <zkoopmans@google.com> | 2021-08-30 15:32:22 -0700 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2021-08-30 15:35:02 -0700 |
commit | dfbcb8903ae8bd0d1ff984889f1b5cf1e041865e (patch) | |
tree | f38c3de45bb102e17971f428fed0099ac69b6a2c | |
parent | a247e227b1f629392d0a9132dc490a6ef9ee2519 (diff) |
[syserr] Fix SIGBUS on syserr.FromError
Fix syzcaller panic SIGBUS on error handling. Done by
adding an interface, errors.GuestError, which errors can
implement in order to be compared against each other.
PiperOrigin-RevId: 393867554
-rw-r--r-- | pkg/syserr/BUILD | 1 | ||||
-rw-r--r-- | pkg/syserr/syserr.go | 16 | ||||
-rw-r--r-- | test/syscalls/linux/BUILD | 3 | ||||
-rw-r--r-- | test/syscalls/linux/socket_unix.cc | 15 |
4 files changed, 29 insertions, 6 deletions
diff --git a/pkg/syserr/BUILD b/pkg/syserr/BUILD index 1cd5d641d..d8c4c9613 100644 --- a/pkg/syserr/BUILD +++ b/pkg/syserr/BUILD @@ -14,6 +14,7 @@ go_library( "//pkg/abi/linux/errno", "//pkg/errors", "//pkg/errors/linuxerr", + "//pkg/safecopy", "//pkg/tcpip", "@org_golang_x_sys//unix:go_default_library", ], diff --git a/pkg/syserr/syserr.go b/pkg/syserr/syserr.go index a5e386e38..b679f3046 100644 --- a/pkg/syserr/syserr.go +++ b/pkg/syserr/syserr.go @@ -24,6 +24,7 @@ import ( "gvisor.dev/gvisor/pkg/abi/linux/errno" "gvisor.dev/gvisor/pkg/errors" "gvisor.dev/gvisor/pkg/errors/linuxerr" + "gvisor.dev/gvisor/pkg/safecopy" ) // Error represents an internal error. @@ -278,15 +279,18 @@ func FromError(err error) *Error { if err == nil { return nil } - if errno, ok := err.(unix.Errno); ok { - return FromHost(errno) - } - if linuxErr, ok := err.(*errors.Error); ok { - return FromHost(unix.Errno(linuxErr.Errno())) + switch e := err.(type) { + case unix.Errno: + return FromHost(e) + case *errors.Error: + return FromHost(unix.Errno(e.Errno())) + case safecopy.SegvError, safecopy.BusError, safecopy.AlignmentError: + return FromHost(unix.EFAULT) } - panic("unknown error: " + err.Error()) + msg := fmt.Sprintf("err: %s type: %T", err.Error(), err) + panic(msg) } // ConvertIntr converts the provided error code (err) to another one (intr) if diff --git a/test/syscalls/linux/BUILD b/test/syscalls/linux/BUILD index 01ee432cb..b06b3d233 100644 --- a/test/syscalls/linux/BUILD +++ b/test/syscalls/linux/BUILD @@ -3293,9 +3293,12 @@ cc_library( ], deps = [ ":unix_domain_socket_test_util", + "//test/util:file_descriptor", + "//test/util:memory_util", "//test/util:socket_util", "@com_google_absl//absl/strings", gtest, + "//test/util:temp_path", "//test/util:test_util", "//test/util:thread_util", ], diff --git a/test/syscalls/linux/socket_unix.cc b/test/syscalls/linux/socket_unix.cc index cf96b2075..43433eaae 100644 --- a/test/syscalls/linux/socket_unix.cc +++ b/test/syscalls/linux/socket_unix.cc @@ -27,7 +27,10 @@ #include "gtest/gtest.h" #include "absl/strings/string_view.h" #include "test/syscalls/linux/unix_domain_socket_test_util.h" +#include "test/util/file_descriptor.h" +#include "test/util/memory_util.h" #include "test/util/socket_util.h" +#include "test/util/temp_path.h" #include "test/util/test_util.h" #include "test/util/thread_util.h" @@ -268,6 +271,18 @@ TEST_P(UnixSocketPairTest, SocketReopenFromProcfs) { } } +// Repro for b/196804997. +TEST_P(UnixSocketPairTest, SendFromMmapBeyondEof) { + TempPath file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); + FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDONLY)); + Mapping m = ASSERT_NO_ERRNO_AND_VALUE( + Mmap(nullptr, kPageSize, PROT_READ, MAP_SHARED, fd.get(), 0)); + + auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); + ASSERT_THAT(send(sockets->first_fd(), m.ptr(), m.len(), 0), + SyscallFailsWithErrno(EFAULT)); +} + } // namespace } // namespace testing |