summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorZach Koopmans <zkoopmans@google.com>2021-08-30 15:32:22 -0700
committergVisor bot <gvisor-bot@google.com>2021-08-30 15:35:02 -0700
commitdfbcb8903ae8bd0d1ff984889f1b5cf1e041865e (patch)
treef38c3de45bb102e17971f428fed0099ac69b6a2c
parenta247e227b1f629392d0a9132dc490a6ef9ee2519 (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/BUILD1
-rw-r--r--pkg/syserr/syserr.go16
-rw-r--r--test/syscalls/linux/BUILD3
-rw-r--r--test/syscalls/linux/socket_unix.cc15
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