summaryrefslogtreecommitdiffhomepage
path: root/test/syscalls
diff options
context:
space:
mode:
Diffstat (limited to 'test/syscalls')
-rw-r--r--test/syscalls/BUILD2
-rw-r--r--test/syscalls/build_defs.bzl6
-rw-r--r--test/syscalls/gtest/BUILD7
-rw-r--r--test/syscalls/linux/32bit.cc132
-rw-r--r--test/syscalls/linux/BUILD31
-rw-r--r--test/syscalls/linux/concurrency.cc2
-rw-r--r--test/syscalls/linux/connect_external.cc12
-rw-r--r--test/syscalls/linux/eventfd.cc25
-rw-r--r--test/syscalls/linux/exceptions.cc2
-rw-r--r--test/syscalls/linux/fault.cc3
-rw-r--r--test/syscalls/linux/fpsig_fork.cc4
-rw-r--r--test/syscalls/linux/fpsig_nested.cc8
-rw-r--r--test/syscalls/linux/getrusage.cc2
-rw-r--r--test/syscalls/linux/iptables.h2
-rw-r--r--test/syscalls/linux/link.cc3
-rw-r--r--test/syscalls/linux/madvise.cc12
-rw-r--r--test/syscalls/linux/mempolicy.cc10
-rw-r--r--test/syscalls/linux/mlock.cc1
-rw-r--r--test/syscalls/linux/msync.cc4
-rw-r--r--test/syscalls/linux/proc_net.cc20
-rw-r--r--test/syscalls/linux/ptrace.cc13
-rw-r--r--test/syscalls/linux/rseq/BUILD5
-rw-r--r--test/syscalls/linux/seccomp.cc9
-rw-r--r--test/syscalls/linux/sendfile_socket.cc8
-rw-r--r--test/syscalls/linux/sigaction.cc53
-rw-r--r--test/syscalls/linux/sigaltstack.cc6
-rw-r--r--test/syscalls/linux/sigiret.cc4
-rw-r--r--test/syscalls/linux/socket_bind_to_device_sequence.cc10
-rw-r--r--test/syscalls/linux/socket_inet_loopback.cc158
-rw-r--r--test/syscalls/linux/socket_ip_tcp_generic.cc33
-rw-r--r--test/syscalls/linux/socket_netdevice.cc10
-rw-r--r--test/syscalls/linux/socket_netlink_route.cc84
-rw-r--r--test/syscalls/linux/socket_netlink_util.cc38
-rw-r--r--test/syscalls/linux/socket_netlink_util.h11
-rw-r--r--test/syscalls/linux/socket_stream_blocking.cc64
-rw-r--r--test/syscalls/linux/splice.cc56
-rw-r--r--test/syscalls/linux/stat.cc4
-rw-r--r--test/syscalls/linux/tcp_socket.cc53
-rw-r--r--test/syscalls/linux/udp_socket_errqueue_test_case.cc5
-rw-r--r--test/syscalls/linux/utimes.cc21
-rw-r--r--test/syscalls/linux/xattr.cc2
41 files changed, 715 insertions, 220 deletions
diff --git a/test/syscalls/BUILD b/test/syscalls/BUILD
index 90d52e73b..40e974314 100644
--- a/test/syscalls/BUILD
+++ b/test/syscalls/BUILD
@@ -1,4 +1,4 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_binary")
+load("//tools:defs.bzl", "go_binary")
load("//test/syscalls:build_defs.bzl", "syscall_test")
package(licenses = ["notice"])
diff --git a/test/syscalls/build_defs.bzl b/test/syscalls/build_defs.bzl
index aaf77c65b..1df761dd0 100644
--- a/test/syscalls/build_defs.bzl
+++ b/test/syscalls/build_defs.bzl
@@ -1,5 +1,7 @@
"""Defines a rule for syscall test targets."""
+load("//tools:defs.bzl", "loopback")
+
# syscall_test is a macro that will create targets to run the given test target
# on the host (native) and runsc.
def syscall_test(
@@ -135,6 +137,7 @@ def _syscall_test(
name = name,
data = [
":syscall_test_runner",
+ loopback,
test,
],
args = args,
@@ -148,6 +151,3 @@ def sh_test(**kwargs):
native.sh_test(
**kwargs
)
-
-def select_for_linux(for_linux, for_others = []):
- return for_linux
diff --git a/test/syscalls/gtest/BUILD b/test/syscalls/gtest/BUILD
index 9293f25cb..de4b2727c 100644
--- a/test/syscalls/gtest/BUILD
+++ b/test/syscalls/gtest/BUILD
@@ -1,12 +1,9 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_library")
+load("//tools:defs.bzl", "go_library")
package(licenses = ["notice"])
go_library(
name = "gtest",
srcs = ["gtest.go"],
- importpath = "gvisor.dev/gvisor/test/syscalls/gtest",
- visibility = [
- "//test:__subpackages__",
- ],
+ visibility = ["//:sandbox"],
)
diff --git a/test/syscalls/linux/32bit.cc b/test/syscalls/linux/32bit.cc
index a7cbee06b..2751fb4e7 100644
--- a/test/syscalls/linux/32bit.cc
+++ b/test/syscalls/linux/32bit.cc
@@ -15,10 +15,12 @@
#include <string.h>
#include <sys/mman.h>
+#include "gtest/gtest.h"
+#include "absl/base/macros.h"
#include "test/util/memory_util.h"
+#include "test/util/platform_util.h"
#include "test/util/posix_error.h"
#include "test/util/test_util.h"
-#include "gtest/gtest.h"
#ifndef __x86_64__
#error "This test is x86-64 specific."
@@ -30,7 +32,6 @@ namespace testing {
namespace {
constexpr char kInt3 = '\xcc';
-
constexpr char kInt80[2] = {'\xcd', '\x80'};
constexpr char kSyscall[2] = {'\x0f', '\x05'};
constexpr char kSysenter[2] = {'\x0f', '\x34'};
@@ -43,6 +44,7 @@ void ExitGroup32(const char instruction[2], int code) {
// Fill with INT 3 in case we execute too far.
memset(m.ptr(), kInt3, m.len());
+ // Copy in the actual instruction.
memcpy(m.ptr(), instruction, 2);
// We're playing *extremely* fast-and-loose with the various syscall ABIs
@@ -71,77 +73,94 @@ void ExitGroup32(const char instruction[2], int code) {
"iretl\n"
"int $3\n"
:
- : [code] "m"(code), [ip] "d"(m.ptr())
+ : [ code ] "m"(code), [ ip ] "d"(m.ptr())
: "rax", "rbx", "rsp");
}
constexpr int kExitCode = 42;
TEST(Syscall32Bit, Int80) {
- switch (GvisorPlatform()) {
- case Platform::kKVM:
- // TODO(b/111805002): 32-bit segments are broken (but not explictly
- // disabled).
- return;
- case Platform::kPtrace:
- // TODO(gvisor.dev/issue/167): The ptrace platform does not have a
- // consistent story here.
- return;
- case Platform::kNative:
+ switch (PlatformSupport32Bit()) {
+ case PlatformSupport::NotSupported:
+ break;
+ case PlatformSupport::Segfault:
+ EXPECT_EXIT(ExitGroup32(kInt80, kExitCode),
+ ::testing::KilledBySignal(SIGSEGV), "");
break;
- }
- // Upstream Linux. 32-bit syscalls allowed.
- EXPECT_EXIT(ExitGroup32(kInt80, kExitCode), ::testing::ExitedWithCode(42),
- "");
-}
+ case PlatformSupport::Ignored:
+ // Since the call is ignored, we'll hit the int3 trap.
+ EXPECT_EXIT(ExitGroup32(kInt80, kExitCode),
+ ::testing::KilledBySignal(SIGTRAP), "");
+ break;
-TEST(Syscall32Bit, Sysenter) {
- switch (GvisorPlatform()) {
- case Platform::kKVM:
- // TODO(b/111805002): See above.
- return;
- case Platform::kPtrace:
- // TODO(gvisor.dev/issue/167): See above.
- return;
- case Platform::kNative:
+ case PlatformSupport::Allowed:
+ EXPECT_EXIT(ExitGroup32(kInt80, kExitCode), ::testing::ExitedWithCode(42),
+ "");
break;
}
+}
- if (GetCPUVendor() == CPUVendor::kAMD) {
+TEST(Syscall32Bit, Sysenter) {
+ if (PlatformSupport32Bit() == PlatformSupport::Allowed &&
+ GetCPUVendor() == CPUVendor::kAMD) {
// SYSENTER is an illegal instruction in compatibility mode on AMD.
EXPECT_EXIT(ExitGroup32(kSysenter, kExitCode),
::testing::KilledBySignal(SIGILL), "");
return;
}
- // Upstream Linux on !AMD, 32-bit syscalls allowed.
- EXPECT_EXIT(ExitGroup32(kSysenter, kExitCode), ::testing::ExitedWithCode(42),
- "");
-}
+ switch (PlatformSupport32Bit()) {
+ case PlatformSupport::NotSupported:
+ break;
-TEST(Syscall32Bit, Syscall) {
- switch (GvisorPlatform()) {
- case Platform::kKVM:
- // TODO(b/111805002): See above.
- return;
- case Platform::kPtrace:
- // TODO(gvisor.dev/issue/167): See above.
- return;
- case Platform::kNative:
+ case PlatformSupport::Segfault:
+ EXPECT_EXIT(ExitGroup32(kSysenter, kExitCode),
+ ::testing::KilledBySignal(SIGSEGV), "");
+ break;
+
+ case PlatformSupport::Ignored:
+ // See above, except expected code is SIGSEGV.
+ EXPECT_EXIT(ExitGroup32(kSysenter, kExitCode),
+ ::testing::KilledBySignal(SIGSEGV), "");
+ break;
+
+ case PlatformSupport::Allowed:
+ EXPECT_EXIT(ExitGroup32(kSysenter, kExitCode),
+ ::testing::ExitedWithCode(42), "");
break;
}
+}
- if (GetCPUVendor() == CPUVendor::kIntel) {
+TEST(Syscall32Bit, Syscall) {
+ if (PlatformSupport32Bit() == PlatformSupport::Allowed &&
+ GetCPUVendor() == CPUVendor::kIntel) {
// SYSCALL is an illegal instruction in compatibility mode on Intel.
EXPECT_EXIT(ExitGroup32(kSyscall, kExitCode),
::testing::KilledBySignal(SIGILL), "");
return;
}
- // Upstream Linux on !Intel, 32-bit syscalls allowed.
- EXPECT_EXIT(ExitGroup32(kSyscall, kExitCode), ::testing::ExitedWithCode(42),
- "");
+ switch (PlatformSupport32Bit()) {
+ case PlatformSupport::NotSupported:
+ break;
+
+ case PlatformSupport::Segfault:
+ EXPECT_EXIT(ExitGroup32(kSyscall, kExitCode),
+ ::testing::KilledBySignal(SIGSEGV), "");
+ break;
+
+ case PlatformSupport::Ignored:
+ // See above.
+ EXPECT_EXIT(ExitGroup32(kSyscall, kExitCode),
+ ::testing::KilledBySignal(SIGILL), "");
+ break;
+
+ case PlatformSupport::Allowed:
+ EXPECT_EXIT(ExitGroup32(kSyscall, kExitCode),
+ ::testing::ExitedWithCode(42), "");
+ break;
+ }
}
// Far call code called below.
@@ -205,19 +224,20 @@ void FarCall32() {
}
TEST(Call32Bit, Disallowed) {
- switch (GvisorPlatform()) {
- case Platform::kKVM:
- // TODO(b/111805002): See above.
- return;
- case Platform::kPtrace:
- // The ptrace platform cannot prevent switching to compatibility mode.
- ABSL_FALLTHROUGH_INTENDED;
- case Platform::kNative:
+ switch (PlatformSupport32Bit()) {
+ case PlatformSupport::NotSupported:
break;
- }
- // Shouldn't crash.
- FarCall32();
+ case PlatformSupport::Segfault:
+ EXPECT_EXIT(FarCall32(), ::testing::KilledBySignal(SIGSEGV), "");
+ break;
+
+ case PlatformSupport::Ignored:
+ ABSL_FALLTHROUGH_INTENDED;
+ case PlatformSupport::Allowed:
+ // Shouldn't crash.
+ FarCall32();
+ }
}
} // namespace
diff --git a/test/syscalls/linux/BUILD b/test/syscalls/linux/BUILD
index 4c7ec3f06..6f57c9755 100644
--- a/test/syscalls/linux/BUILD
+++ b/test/syscalls/linux/BUILD
@@ -1,5 +1,4 @@
-load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")
-load("//test/syscalls:build_defs.bzl", "select_for_linux")
+load("//tools:defs.bzl", "cc_binary", "cc_library", "default_net_util", "select_system")
package(
default_visibility = ["//:sandbox"],
@@ -126,13 +125,11 @@ cc_library(
testonly = 1,
srcs = [
"socket_test_util.cc",
- ] + select_for_linux(
- [
- "socket_test_util_impl.cc",
- ],
- ),
+ "socket_test_util_impl.cc",
+ ],
hdrs = ["socket_test_util.h"],
- deps = [
+ defines = select_system(),
+ deps = default_net_util() + [
"@com_google_googletest//:gtest",
"@com_google_absl//absl/memory",
"@com_google_absl//absl/strings",
@@ -143,8 +140,7 @@ cc_library(
"//test/util:temp_path",
"//test/util:test_util",
"//test/util:thread_util",
- ] + select_for_linux([
- ]),
+ ],
)
cc_library(
@@ -201,9 +197,11 @@ cc_binary(
linkstatic = 1,
deps = [
"//test/util:memory_util",
+ "//test/util:platform_util",
"//test/util:posix_error",
"//test/util:test_main",
"//test/util:test_util",
+ "@com_google_absl//absl/base:core_headers",
"@com_google_googletest//:gtest",
],
)
@@ -483,6 +481,7 @@ cc_binary(
srcs = ["concurrency.cc"],
linkstatic = 1,
deps = [
+ "//test/util:platform_util",
"//test/util:test_main",
"//test/util:test_util",
"//test/util:thread_util",
@@ -588,6 +587,7 @@ cc_binary(
linkstatic = 1,
deps = [
"//test/util:logging",
+ "//test/util:platform_util",
"//test/util:signal_util",
"//test/util:test_main",
"//test/util:test_util",
@@ -754,6 +754,7 @@ cc_binary(
":socket_test_util",
"//test/util:cleanup",
"//test/util:eventfd_util",
+ "//test/util:fs_util",
"//test/util:multiprocess_util",
"//test/util:posix_error",
"//test/util:save_util",
@@ -1391,6 +1392,7 @@ cc_binary(
linkstatic = 1,
deps = [
"//test/util:file_descriptor",
+ "//test/util:fs_util",
"//test/util:posix_error",
"//test/util:temp_path",
"//test/util:test_main",
@@ -1443,6 +1445,7 @@ cc_binary(
srcs = ["arch_prctl.cc"],
linkstatic = 1,
deps = [
+ "//test/util:file_descriptor",
"//test/util:test_main",
"//test/util:test_util",
"@com_google_googletest//:gtest",
@@ -1661,6 +1664,7 @@ cc_binary(
deps = [
"//test/util:logging",
"//test/util:multiprocess_util",
+ "//test/util:platform_util",
"//test/util:signal_util",
"//test/util:test_util",
"//test/util:thread_util",
@@ -2171,6 +2175,7 @@ cc_library(
":socket_test_util",
"//test/util:test_util",
"//test/util:thread_util",
+ "@com_google_absl//absl/memory",
"@com_google_absl//absl/time",
"@com_google_googletest//:gtest",
],
@@ -3383,11 +3388,11 @@ cc_library(
name = "udp_socket_test_cases",
testonly = 1,
srcs = [
- "udp_socket_test_cases.cc",
- ] + select_for_linux([
"udp_socket_errqueue_test_case.cc",
- ]),
+ "udp_socket_test_cases.cc",
+ ],
hdrs = ["udp_socket_test_cases.h"],
+ defines = select_system(),
deps = [
":socket_test_util",
":unix_domain_socket_test_util",
diff --git a/test/syscalls/linux/concurrency.cc b/test/syscalls/linux/concurrency.cc
index 00b96b34a..f41f99900 100644
--- a/test/syscalls/linux/concurrency.cc
+++ b/test/syscalls/linux/concurrency.cc
@@ -20,6 +20,7 @@
#include "absl/strings/string_view.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
+#include "test/util/platform_util.h"
#include "test/util/test_util.h"
#include "test/util/thread_util.h"
@@ -99,6 +100,7 @@ TEST(ConcurrencyTest, MultiProcessMultithreaded) {
// Test that multiple processes can execute concurrently, even if one process
// never yields.
TEST(ConcurrencyTest, MultiProcessConcurrency) {
+ SKIP_IF(PlatformSupportMultiProcess() == PlatformSupport::NotSupported);
pid_t child_pid = fork();
if (child_pid == 0) {
diff --git a/test/syscalls/linux/connect_external.cc b/test/syscalls/linux/connect_external.cc
index bfe1da82e..1edb50e47 100644
--- a/test/syscalls/linux/connect_external.cc
+++ b/test/syscalls/linux/connect_external.cc
@@ -56,7 +56,7 @@ TEST_P(GoferStreamSeqpacketTest, Echo) {
ProtocolSocket proto;
std::tie(env, proto) = GetParam();
- char *val = getenv(env.c_str());
+ char* val = getenv(env.c_str());
ASSERT_NE(val, nullptr);
std::string root(val);
@@ -69,7 +69,7 @@ TEST_P(GoferStreamSeqpacketTest, Echo) {
addr.sun_family = AF_UNIX;
memcpy(addr.sun_path, socket_path.c_str(), socket_path.length());
- ASSERT_THAT(connect(sock.get(), reinterpret_cast<struct sockaddr *>(&addr),
+ ASSERT_THAT(connect(sock.get(), reinterpret_cast<struct sockaddr*>(&addr),
sizeof(addr)),
SyscallSucceeds());
@@ -92,7 +92,7 @@ TEST_P(GoferStreamSeqpacketTest, NonListening) {
ProtocolSocket proto;
std::tie(env, proto) = GetParam();
- char *val = getenv(env.c_str());
+ char* val = getenv(env.c_str());
ASSERT_NE(val, nullptr);
std::string root(val);
@@ -105,7 +105,7 @@ TEST_P(GoferStreamSeqpacketTest, NonListening) {
addr.sun_family = AF_UNIX;
memcpy(addr.sun_path, socket_path.c_str(), socket_path.length());
- ASSERT_THAT(connect(sock.get(), reinterpret_cast<struct sockaddr *>(&addr),
+ ASSERT_THAT(connect(sock.get(), reinterpret_cast<struct sockaddr*>(&addr),
sizeof(addr)),
SyscallFailsWithErrno(ECONNREFUSED));
}
@@ -127,7 +127,7 @@ using GoferDgramTest = ::testing::TestWithParam<std::string>;
// unnamed. The server thus has no way to reply to us.
TEST_P(GoferDgramTest, Null) {
std::string env = GetParam();
- char *val = getenv(env.c_str());
+ char* val = getenv(env.c_str());
ASSERT_NE(val, nullptr);
std::string root(val);
@@ -140,7 +140,7 @@ TEST_P(GoferDgramTest, Null) {
addr.sun_family = AF_UNIX;
memcpy(addr.sun_path, socket_path.c_str(), socket_path.length());
- ASSERT_THAT(connect(sock.get(), reinterpret_cast<struct sockaddr *>(&addr),
+ ASSERT_THAT(connect(sock.get(), reinterpret_cast<struct sockaddr*>(&addr),
sizeof(addr)),
SyscallSucceeds());
diff --git a/test/syscalls/linux/eventfd.cc b/test/syscalls/linux/eventfd.cc
index 367682c3d..927001eee 100644
--- a/test/syscalls/linux/eventfd.cc
+++ b/test/syscalls/linux/eventfd.cc
@@ -132,6 +132,31 @@ TEST(EventfdTest, BigWriteBigRead) {
EXPECT_EQ(l[0], 1);
}
+TEST(EventfdTest, SpliceFromPipePartialSucceeds) {
+ int pipes[2];
+ ASSERT_THAT(pipe2(pipes, O_NONBLOCK), SyscallSucceeds());
+ const FileDescriptor pipe_rfd(pipes[0]);
+ const FileDescriptor pipe_wfd(pipes[1]);
+ constexpr uint64_t kVal{1};
+
+ FileDescriptor efd = ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(0, EFD_NONBLOCK));
+
+ uint64_t event_array[2];
+ event_array[0] = kVal;
+ event_array[1] = kVal;
+ ASSERT_THAT(write(pipe_wfd.get(), event_array, sizeof(event_array)),
+ SyscallSucceedsWithValue(sizeof(event_array)));
+ EXPECT_THAT(splice(pipe_rfd.get(), /*__offin=*/nullptr, efd.get(),
+ /*__offout=*/nullptr, sizeof(event_array[0]) + 1,
+ SPLICE_F_NONBLOCK),
+ SyscallSucceedsWithValue(sizeof(event_array[0])));
+
+ uint64_t val;
+ ASSERT_THAT(read(efd.get(), &val, sizeof(val)),
+ SyscallSucceedsWithValue(sizeof(val)));
+ EXPECT_EQ(val, kVal);
+}
+
// NotifyNonZero is inherently racy, so random save is disabled.
TEST(EventfdTest, NotifyNonZero_NoRandomSave) {
// Waits will time out at 10 seconds.
diff --git a/test/syscalls/linux/exceptions.cc b/test/syscalls/linux/exceptions.cc
index 3d564e720..420b9543f 100644
--- a/test/syscalls/linux/exceptions.cc
+++ b/test/syscalls/linux/exceptions.cc
@@ -16,6 +16,7 @@
#include "gtest/gtest.h"
#include "test/util/logging.h"
+#include "test/util/platform_util.h"
#include "test/util/signal_util.h"
#include "test/util/test_util.h"
@@ -324,6 +325,7 @@ TEST(ExceptionTest, AlignmentHalt) {
}
TEST(ExceptionTest, AlignmentCheck) {
+ SKIP_IF(PlatformSupportAlignmentCheck() != PlatformSupport::Allowed);
// See above.
struct sigaction sa = {};
diff --git a/test/syscalls/linux/fault.cc b/test/syscalls/linux/fault.cc
index f6e19026f..a85750382 100644
--- a/test/syscalls/linux/fault.cc
+++ b/test/syscalls/linux/fault.cc
@@ -37,6 +37,9 @@ int GetPcFromUcontext(ucontext_t* uc, uintptr_t* pc) {
#elif defined(__i386__)
*pc = uc->uc_mcontext.gregs[REG_EIP];
return 1;
+#elif defined(__aarch64__)
+ *pc = uc->uc_mcontext.pc;
+ return 1;
#else
return 0;
#endif
diff --git a/test/syscalls/linux/fpsig_fork.cc b/test/syscalls/linux/fpsig_fork.cc
index e7e9f06a1..a346f1f00 100644
--- a/test/syscalls/linux/fpsig_fork.cc
+++ b/test/syscalls/linux/fpsig_fork.cc
@@ -76,8 +76,8 @@ TEST(FPSigTest, Fork) {
"movl %[sig], %%edx;"
"syscall;"
:
- : [killnr] "i"(__NR_tgkill), [parent] "rm"(parent),
- [tid] "rm"(parent_tid), [sig] "i"(SIGUSR1)
+ : [ killnr ] "i"(__NR_tgkill), [ parent ] "rm"(parent),
+ [ tid ] "rm"(parent_tid), [ sig ] "i"(SIGUSR1)
: "rax", "rdi", "rsi", "rdx",
// Clobbered by syscall.
"rcx", "r11");
diff --git a/test/syscalls/linux/fpsig_nested.cc b/test/syscalls/linux/fpsig_nested.cc
index 395463aed..c476a8e7a 100644
--- a/test/syscalls/linux/fpsig_nested.cc
+++ b/test/syscalls/linux/fpsig_nested.cc
@@ -61,8 +61,8 @@ void sigusr1(int s, siginfo_t* siginfo, void* _uc) {
"movl %[sig], %%edx;"
"syscall;"
:
- : [killnr] "i"(__NR_tgkill), [pid] "rm"(pid), [tid] "rm"(tid),
- [sig] "i"(SIGUSR2)
+ : [ killnr ] "i"(__NR_tgkill), [ pid ] "rm"(pid), [ tid ] "rm"(tid),
+ [ sig ] "i"(SIGUSR2)
: "rax", "rdi", "rsi", "rdx",
// Clobbered by syscall.
"rcx", "r11");
@@ -107,8 +107,8 @@ TEST(FPSigTest, NestedSignals) {
"movl %[sig], %%edx;"
"syscall;"
:
- : [killnr] "i"(__NR_tgkill), [pid] "rm"(pid), [tid] "rm"(tid),
- [sig] "i"(SIGUSR1)
+ : [ killnr ] "i"(__NR_tgkill), [ pid ] "rm"(pid), [ tid ] "rm"(tid),
+ [ sig ] "i"(SIGUSR1)
: "rax", "rdi", "rsi", "rdx",
// Clobbered by syscall.
"rcx", "r11");
diff --git a/test/syscalls/linux/getrusage.cc b/test/syscalls/linux/getrusage.cc
index 9bdb1e4cd..0e51d42a8 100644
--- a/test/syscalls/linux/getrusage.cc
+++ b/test/syscalls/linux/getrusage.cc
@@ -67,7 +67,7 @@ TEST(GetrusageTest, Grandchild) {
pid = fork();
if (pid == 0) {
int flags = MAP_ANONYMOUS | MAP_POPULATE | MAP_PRIVATE;
- void *addr =
+ void* addr =
mmap(nullptr, kGrandchildSizeKb * 1024, PROT_WRITE, flags, -1, 0);
TEST_PCHECK(addr != MAP_FAILED);
} else {
diff --git a/test/syscalls/linux/iptables.h b/test/syscalls/linux/iptables.h
index 616bea550..0719c60a4 100644
--- a/test/syscalls/linux/iptables.h
+++ b/test/syscalls/linux/iptables.h
@@ -188,7 +188,7 @@ struct ipt_replace {
unsigned int num_counters;
// The unchanged values from each ipt_entry's counters.
- struct xt_counters *counters;
+ struct xt_counters* counters;
// The entries to write to the table. This will run past the size defined by
// sizeof(srtuct ipt_replace);
diff --git a/test/syscalls/linux/link.cc b/test/syscalls/linux/link.cc
index dd5352954..e74fa2ed5 100644
--- a/test/syscalls/linux/link.cc
+++ b/test/syscalls/linux/link.cc
@@ -55,7 +55,8 @@ TEST(LinkTest, CanCreateLinkFile) {
const std::string newname = NewTempAbsPath();
// Get the initial link count.
- uint64_t initial_link_count = ASSERT_NO_ERRNO_AND_VALUE(Links(oldfile.path()));
+ uint64_t initial_link_count =
+ ASSERT_NO_ERRNO_AND_VALUE(Links(oldfile.path()));
EXPECT_THAT(link(oldfile.path().c_str(), newname.c_str()), SyscallSucceeds());
diff --git a/test/syscalls/linux/madvise.cc b/test/syscalls/linux/madvise.cc
index 7fd0ea20c..5a1973f60 100644
--- a/test/syscalls/linux/madvise.cc
+++ b/test/syscalls/linux/madvise.cc
@@ -139,7 +139,7 @@ TEST(MadviseDontneedTest, IgnoresPermissions) {
TEST(MadviseDontforkTest, AddressLength) {
auto m =
ASSERT_NO_ERRNO_AND_VALUE(MmapAnon(kPageSize, PROT_NONE, MAP_PRIVATE));
- char *addr = static_cast<char *>(m.ptr());
+ char* addr = static_cast<char*>(m.ptr());
// Address must be page aligned.
EXPECT_THAT(madvise(addr + 1, kPageSize, MADV_DONTFORK),
@@ -168,9 +168,9 @@ TEST(MadviseDontforkTest, DontforkShared) {
Mapping m = ASSERT_NO_ERRNO_AND_VALUE(Mmap(
nullptr, kPageSize * 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd.get(), 0));
- const Mapping ms1 = Mapping(reinterpret_cast<void *>(m.addr()), kPageSize);
+ const Mapping ms1 = Mapping(reinterpret_cast<void*>(m.addr()), kPageSize);
const Mapping ms2 =
- Mapping(reinterpret_cast<void *>(m.addr() + kPageSize), kPageSize);
+ Mapping(reinterpret_cast<void*>(m.addr() + kPageSize), kPageSize);
m.release();
ASSERT_THAT(madvise(ms2.ptr(), kPageSize, MADV_DONTFORK), SyscallSucceeds());
@@ -197,11 +197,11 @@ TEST(MadviseDontforkTest, DontforkAnonPrivate) {
// Mmap three anonymous pages and MADV_DONTFORK the middle page.
Mapping m = ASSERT_NO_ERRNO_AND_VALUE(
MmapAnon(kPageSize * 3, PROT_READ | PROT_WRITE, MAP_PRIVATE));
- const Mapping mp1 = Mapping(reinterpret_cast<void *>(m.addr()), kPageSize);
+ const Mapping mp1 = Mapping(reinterpret_cast<void*>(m.addr()), kPageSize);
const Mapping mp2 =
- Mapping(reinterpret_cast<void *>(m.addr() + kPageSize), kPageSize);
+ Mapping(reinterpret_cast<void*>(m.addr() + kPageSize), kPageSize);
const Mapping mp3 =
- Mapping(reinterpret_cast<void *>(m.addr() + 2 * kPageSize), kPageSize);
+ Mapping(reinterpret_cast<void*>(m.addr() + 2 * kPageSize), kPageSize);
m.release();
ASSERT_THAT(madvise(mp2.ptr(), kPageSize, MADV_DONTFORK), SyscallSucceeds());
diff --git a/test/syscalls/linux/mempolicy.cc b/test/syscalls/linux/mempolicy.cc
index 9d5f47651..059fad598 100644
--- a/test/syscalls/linux/mempolicy.cc
+++ b/test/syscalls/linux/mempolicy.cc
@@ -43,17 +43,17 @@ namespace {
#define MPOL_MF_MOVE (1 << 1)
#define MPOL_MF_MOVE_ALL (1 << 2)
-int get_mempolicy(int *policy, uint64_t *nmask, uint64_t maxnode, void *addr,
+int get_mempolicy(int* policy, uint64_t* nmask, uint64_t maxnode, void* addr,
int flags) {
return syscall(SYS_get_mempolicy, policy, nmask, maxnode, addr, flags);
}
-int set_mempolicy(int mode, uint64_t *nmask, uint64_t maxnode) {
+int set_mempolicy(int mode, uint64_t* nmask, uint64_t maxnode) {
return syscall(SYS_set_mempolicy, mode, nmask, maxnode);
}
-int mbind(void *addr, unsigned long len, int mode,
- const unsigned long *nodemask, unsigned long maxnode,
+int mbind(void* addr, unsigned long len, int mode,
+ const unsigned long* nodemask, unsigned long maxnode,
unsigned flags) {
return syscall(SYS_mbind, addr, len, mode, nodemask, maxnode, flags);
}
@@ -68,7 +68,7 @@ Cleanup ScopedMempolicy() {
// Temporarily change the memory policy for the calling thread within the
// caller's scope.
-PosixErrorOr<Cleanup> ScopedSetMempolicy(int mode, uint64_t *nmask,
+PosixErrorOr<Cleanup> ScopedSetMempolicy(int mode, uint64_t* nmask,
uint64_t maxnode) {
if (set_mempolicy(mode, nmask, maxnode)) {
return PosixError(errno, "set_mempolicy");
diff --git a/test/syscalls/linux/mlock.cc b/test/syscalls/linux/mlock.cc
index 620b4f8b4..367a90fe1 100644
--- a/test/syscalls/linux/mlock.cc
+++ b/test/syscalls/linux/mlock.cc
@@ -60,7 +60,6 @@ bool IsPageMlocked(uintptr_t addr) {
return true;
}
-
TEST(MlockTest, Basic) {
SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(CanMlock()));
auto const mapping = ASSERT_NO_ERRNO_AND_VALUE(
diff --git a/test/syscalls/linux/msync.cc b/test/syscalls/linux/msync.cc
index ac7146017..2b2b6aef9 100644
--- a/test/syscalls/linux/msync.cc
+++ b/test/syscalls/linux/msync.cc
@@ -60,9 +60,7 @@ std::vector<std::function<PosixErrorOr<Mapping>()>> SyncableMappings() {
for (int const mflags : {MAP_PRIVATE, MAP_SHARED}) {
int const prot = PROT_READ | (writable ? PROT_WRITE : 0);
int const oflags = O_CREAT | (writable ? O_RDWR : O_RDONLY);
- funcs.push_back([=] {
- return MmapAnon(kPageSize, prot, mflags);
- });
+ funcs.push_back([=] { return MmapAnon(kPageSize, prot, mflags); });
funcs.push_back([=]() -> PosixErrorOr<Mapping> {
std::string const path = NewTempAbsPath();
ASSIGN_OR_RETURN_ERRNO(auto fd, Open(path, oflags, 0644));
diff --git a/test/syscalls/linux/proc_net.cc b/test/syscalls/linux/proc_net.cc
index 65bad06d4..3a611a86f 100644
--- a/test/syscalls/linux/proc_net.cc
+++ b/test/syscalls/linux/proc_net.cc
@@ -68,8 +68,8 @@ TEST(ProcSysNetIpv4Sack, CanReadAndWrite) {
}
PosixErrorOr<uint64_t> GetSNMPMetricFromProc(const std::string snmp,
- const std::string &type,
- const std::string &item) {
+ const std::string& type,
+ const std::string& item) {
std::vector<std::string> snmp_vec = absl::StrSplit(snmp, '\n');
// /proc/net/snmp prints a line of headers followed by a line of metrics.
@@ -127,7 +127,7 @@ TEST(ProcNetSnmp, TcpReset_NoRandomSave) {
};
ASSERT_EQ(inet_pton(AF_INET, "127.0.0.1", &(sin.sin_addr)), 1);
- ASSERT_THAT(connect(s.get(), (struct sockaddr *)&sin, sizeof(sin)),
+ ASSERT_THAT(connect(s.get(), (struct sockaddr*)&sin, sizeof(sin)),
SyscallFailsWithErrno(ECONNREFUSED));
uint64_t newAttemptFails;
@@ -172,19 +172,19 @@ TEST(ProcNetSnmp, TcpEstab_NoRandomSave) {
};
ASSERT_EQ(inet_pton(AF_INET, "127.0.0.1", &(sin.sin_addr)), 1);
- ASSERT_THAT(bind(s_listen.get(), (struct sockaddr *)&sin, sizeof(sin)),
+ ASSERT_THAT(bind(s_listen.get(), (struct sockaddr*)&sin, sizeof(sin)),
SyscallSucceeds());
ASSERT_THAT(listen(s_listen.get(), 1), SyscallSucceeds());
// Get the port bound by the listening socket.
socklen_t addrlen = sizeof(sin);
ASSERT_THAT(
- getsockname(s_listen.get(), reinterpret_cast<sockaddr *>(&sin), &addrlen),
+ getsockname(s_listen.get(), reinterpret_cast<sockaddr*>(&sin), &addrlen),
SyscallSucceeds());
FileDescriptor s_connect =
ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_STREAM, 0));
- ASSERT_THAT(connect(s_connect.get(), (struct sockaddr *)&sin, sizeof(sin)),
+ ASSERT_THAT(connect(s_connect.get(), (struct sockaddr*)&sin, sizeof(sin)),
SyscallSucceeds());
auto s_accept =
@@ -260,7 +260,7 @@ TEST(ProcNetSnmp, UdpNoPorts_NoRandomSave) {
.sin_port = htons(4444),
};
ASSERT_EQ(inet_pton(AF_INET, "127.0.0.1", &(sin.sin_addr)), 1);
- ASSERT_THAT(sendto(s.get(), "a", 1, 0, (struct sockaddr *)&sin, sizeof(sin)),
+ ASSERT_THAT(sendto(s.get(), "a", 1, 0, (struct sockaddr*)&sin, sizeof(sin)),
SyscallSucceedsWithValue(1));
uint64_t newOutDatagrams;
@@ -295,18 +295,18 @@ TEST(ProcNetSnmp, UdpIn) {
.sin_port = htons(0),
};
ASSERT_EQ(inet_pton(AF_INET, "127.0.0.1", &(sin.sin_addr)), 1);
- ASSERT_THAT(bind(server.get(), (struct sockaddr *)&sin, sizeof(sin)),
+ ASSERT_THAT(bind(server.get(), (struct sockaddr*)&sin, sizeof(sin)),
SyscallSucceeds());
// Get the port bound by the server socket.
socklen_t addrlen = sizeof(sin);
ASSERT_THAT(
- getsockname(server.get(), reinterpret_cast<sockaddr *>(&sin), &addrlen),
+ getsockname(server.get(), reinterpret_cast<sockaddr*>(&sin), &addrlen),
SyscallSucceeds());
FileDescriptor client =
ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_DGRAM, 0));
ASSERT_THAT(
- sendto(client.get(), "a", 1, 0, (struct sockaddr *)&sin, sizeof(sin)),
+ sendto(client.get(), "a", 1, 0, (struct sockaddr*)&sin, sizeof(sin)),
SyscallSucceedsWithValue(1));
char buf[128];
diff --git a/test/syscalls/linux/ptrace.cc b/test/syscalls/linux/ptrace.cc
index 8f3800380..4dd5cf27b 100644
--- a/test/syscalls/linux/ptrace.cc
+++ b/test/syscalls/linux/ptrace.cc
@@ -32,6 +32,7 @@
#include "absl/time/time.h"
#include "test/util/logging.h"
#include "test/util/multiprocess_util.h"
+#include "test/util/platform_util.h"
#include "test/util/signal_util.h"
#include "test/util/test_util.h"
#include "test/util/thread_util.h"
@@ -178,7 +179,8 @@ TEST(PtraceTest, GetSigMask) {
// Install a signal handler for kBlockSignal to avoid termination and block
// it.
- TEST_PCHECK(signal(kBlockSignal, +[](int signo) {}) != SIG_ERR);
+ TEST_PCHECK(signal(
+ kBlockSignal, +[](int signo) {}) != SIG_ERR);
MaybeSave();
TEST_PCHECK(sigprocmask(SIG_SETMASK, &blocked, nullptr) == 0);
MaybeSave();
@@ -823,13 +825,8 @@ TEST(PtraceTest,
// These tests requires knowledge of architecture-specific syscall convention.
#ifdef __x86_64__
TEST(PtraceTest, Int3) {
- switch (GvisorPlatform()) {
- case Platform::kKVM:
- // TODO(b/124248694): int3 isn't handled properly.
- return;
- default:
- break;
- }
+ SKIP_IF(PlatformSupportInt3() == PlatformSupport::NotSupported);
+
pid_t const child_pid = fork();
if (child_pid == 0) {
// In child process.
diff --git a/test/syscalls/linux/rseq/BUILD b/test/syscalls/linux/rseq/BUILD
index 5cfe4e56f..ed488dbc2 100644
--- a/test/syscalls/linux/rseq/BUILD
+++ b/test/syscalls/linux/rseq/BUILD
@@ -1,8 +1,7 @@
# This package contains a standalone rseq test binary. This binary must not
# depend on libc, which might use rseq itself.
-load("@bazel_tools//tools/cpp:cc_flags_supplier.bzl", "cc_flags_supplier")
-load("@rules_cc//cc:defs.bzl", "cc_library")
+load("//tools:defs.bzl", "cc_flags_supplier", "cc_library", "cc_toolchain")
package(licenses = ["notice"])
@@ -37,8 +36,8 @@ genrule(
"$(location start.S)",
]),
toolchains = [
+ cc_toolchain,
":no_pie_cc_flags",
- "@bazel_tools//tools/cpp:current_cc_toolchain",
],
visibility = ["//:sandbox"],
)
diff --git a/test/syscalls/linux/seccomp.cc b/test/syscalls/linux/seccomp.cc
index 7e41fe7d8..294ee6808 100644
--- a/test/syscalls/linux/seccomp.cc
+++ b/test/syscalls/linux/seccomp.cc
@@ -113,7 +113,8 @@ TEST(SeccompTest, RetKillCausesDeathBySIGSYS) {
pid_t const pid = fork();
if (pid == 0) {
// Register a signal handler for SIGSYS that we don't expect to be invoked.
- RegisterSignalHandler(SIGSYS, +[](int, siginfo_t*, void*) { _exit(1); });
+ RegisterSignalHandler(
+ SIGSYS, +[](int, siginfo_t*, void*) { _exit(1); });
ApplySeccompFilter(kFilteredSyscall, SECCOMP_RET_KILL);
syscall(kFilteredSyscall);
TEST_CHECK_MSG(false, "Survived invocation of test syscall");
@@ -132,7 +133,8 @@ TEST(SeccompTest, RetKillOnlyKillsOneThread) {
pid_t const pid = fork();
if (pid == 0) {
// Register a signal handler for SIGSYS that we don't expect to be invoked.
- RegisterSignalHandler(SIGSYS, +[](int, siginfo_t*, void*) { _exit(1); });
+ RegisterSignalHandler(
+ SIGSYS, +[](int, siginfo_t*, void*) { _exit(1); });
ApplySeccompFilter(kFilteredSyscall, SECCOMP_RET_KILL);
// Pass CLONE_VFORK to block the original thread in the child process until
// the clone thread exits with SIGSYS.
@@ -346,7 +348,8 @@ TEST(SeccompTest, LeastPermissiveFilterReturnValueApplies) {
// one that causes the kill that should be ignored.
pid_t const pid = fork();
if (pid == 0) {
- RegisterSignalHandler(SIGSYS, +[](int, siginfo_t*, void*) { _exit(1); });
+ RegisterSignalHandler(
+ SIGSYS, +[](int, siginfo_t*, void*) { _exit(1); });
ApplySeccompFilter(kFilteredSyscall, SECCOMP_RET_TRACE);
ApplySeccompFilter(kFilteredSyscall, SECCOMP_RET_KILL);
ApplySeccompFilter(kFilteredSyscall, SECCOMP_RET_ERRNO | ENOTNAM);
diff --git a/test/syscalls/linux/sendfile_socket.cc b/test/syscalls/linux/sendfile_socket.cc
index 3331288b7..8f7ee4163 100644
--- a/test/syscalls/linux/sendfile_socket.cc
+++ b/test/syscalls/linux/sendfile_socket.cc
@@ -41,15 +41,15 @@ class SendFileTest : public ::testing::TestWithParam<int> {
struct sockaddr server_addr = {};
switch (family) {
case AF_INET: {
- struct sockaddr_in *server_addr_in =
- reinterpret_cast<struct sockaddr_in *>(&server_addr);
+ struct sockaddr_in* server_addr_in =
+ reinterpret_cast<struct sockaddr_in*>(&server_addr);
server_addr_in->sin_family = family;
server_addr_in->sin_addr.s_addr = INADDR_ANY;
break;
}
case AF_UNIX: {
- struct sockaddr_un *server_addr_un =
- reinterpret_cast<struct sockaddr_un *>(&server_addr);
+ struct sockaddr_un* server_addr_un =
+ reinterpret_cast<struct sockaddr_un*>(&server_addr);
server_addr_un->sun_family = family;
server_addr_un->sun_path[0] = '\0';
break;
diff --git a/test/syscalls/linux/sigaction.cc b/test/syscalls/linux/sigaction.cc
index 9a53fd3e0..9d9dd57a8 100644
--- a/test/syscalls/linux/sigaction.cc
+++ b/test/syscalls/linux/sigaction.cc
@@ -13,6 +13,7 @@
// limitations under the License.
#include <signal.h>
+#include <sys/syscall.h>
#include "gtest/gtest.h"
#include "test/util/test_util.h"
@@ -23,45 +24,53 @@ namespace testing {
namespace {
TEST(SigactionTest, GetLessThanOrEqualToZeroFails) {
- struct sigaction act;
- memset(&act, 0, sizeof(act));
- ASSERT_THAT(sigaction(-1, NULL, &act), SyscallFailsWithErrno(EINVAL));
- ASSERT_THAT(sigaction(0, NULL, &act), SyscallFailsWithErrno(EINVAL));
+ struct sigaction act = {};
+ ASSERT_THAT(sigaction(-1, nullptr, &act), SyscallFailsWithErrno(EINVAL));
+ ASSERT_THAT(sigaction(0, nullptr, &act), SyscallFailsWithErrno(EINVAL));
}
TEST(SigactionTest, SetLessThanOrEqualToZeroFails) {
- struct sigaction act;
- memset(&act, 0, sizeof(act));
- ASSERT_THAT(sigaction(0, &act, NULL), SyscallFailsWithErrno(EINVAL));
- ASSERT_THAT(sigaction(0, &act, NULL), SyscallFailsWithErrno(EINVAL));
+ struct sigaction act = {};
+ ASSERT_THAT(sigaction(0, &act, nullptr), SyscallFailsWithErrno(EINVAL));
+ ASSERT_THAT(sigaction(0, &act, nullptr), SyscallFailsWithErrno(EINVAL));
}
TEST(SigactionTest, GetGreaterThanMaxFails) {
- struct sigaction act;
- memset(&act, 0, sizeof(act));
- ASSERT_THAT(sigaction(SIGRTMAX + 1, NULL, &act),
+ struct sigaction act = {};
+ ASSERT_THAT(sigaction(SIGRTMAX + 1, nullptr, &act),
SyscallFailsWithErrno(EINVAL));
}
TEST(SigactionTest, SetGreaterThanMaxFails) {
- struct sigaction act;
- memset(&act, 0, sizeof(act));
- ASSERT_THAT(sigaction(SIGRTMAX + 1, &act, NULL),
+ struct sigaction act = {};
+ ASSERT_THAT(sigaction(SIGRTMAX + 1, &act, nullptr),
SyscallFailsWithErrno(EINVAL));
}
TEST(SigactionTest, SetSigkillFails) {
- struct sigaction act;
- memset(&act, 0, sizeof(act));
- ASSERT_THAT(sigaction(SIGKILL, NULL, &act), SyscallSucceeds());
- ASSERT_THAT(sigaction(SIGKILL, &act, NULL), SyscallFailsWithErrno(EINVAL));
+ struct sigaction act = {};
+ ASSERT_THAT(sigaction(SIGKILL, nullptr, &act), SyscallSucceeds());
+ ASSERT_THAT(sigaction(SIGKILL, &act, nullptr), SyscallFailsWithErrno(EINVAL));
}
TEST(SigactionTest, SetSigstopFails) {
- struct sigaction act;
- memset(&act, 0, sizeof(act));
- ASSERT_THAT(sigaction(SIGSTOP, NULL, &act), SyscallSucceeds());
- ASSERT_THAT(sigaction(SIGSTOP, &act, NULL), SyscallFailsWithErrno(EINVAL));
+ struct sigaction act = {};
+ ASSERT_THAT(sigaction(SIGSTOP, nullptr, &act), SyscallSucceeds());
+ ASSERT_THAT(sigaction(SIGSTOP, &act, nullptr), SyscallFailsWithErrno(EINVAL));
+}
+
+TEST(SigactionTest, BadSigsetFails) {
+ constexpr size_t kWrongSigSetSize = 43;
+
+ struct sigaction act = {};
+
+ // The syscall itself (rather than the libc wrapper) takes the sigset_t size.
+ ASSERT_THAT(
+ syscall(SYS_rt_sigaction, SIGTERM, nullptr, &act, kWrongSigSetSize),
+ SyscallFailsWithErrno(EINVAL));
+ ASSERT_THAT(
+ syscall(SYS_rt_sigaction, SIGTERM, &act, nullptr, kWrongSigSetSize),
+ SyscallFailsWithErrno(EINVAL));
}
} // namespace
diff --git a/test/syscalls/linux/sigaltstack.cc b/test/syscalls/linux/sigaltstack.cc
index a778fa639..24e7c4960 100644
--- a/test/syscalls/linux/sigaltstack.cc
+++ b/test/syscalls/linux/sigaltstack.cc
@@ -114,7 +114,7 @@ TEST(SigaltstackTest, ResetByExecve) {
volatile bool badhandler_on_sigaltstack = true; // Set by the handler.
char* volatile badhandler_low_water_mark = nullptr; // Set by the handler.
-volatile uint8_t badhandler_recursive_faults = 0; // Consumed by the handler.
+volatile uint8_t badhandler_recursive_faults = 0; // Consumed by the handler.
void badhandler(int sig, siginfo_t* siginfo, void* arg) {
char stack_var = 0;
@@ -168,8 +168,8 @@ TEST(SigaltstackTest, WalksOffBottom) {
// Trigger a single fault.
badhandler_low_water_mark =
- static_cast<char*>(stack.ss_sp) + SIGSTKSZ; // Expected top.
- badhandler_recursive_faults = 0; // Disable refault.
+ static_cast<char*>(stack.ss_sp) + SIGSTKSZ; // Expected top.
+ badhandler_recursive_faults = 0; // Disable refault.
Fault();
EXPECT_TRUE(badhandler_on_sigaltstack);
EXPECT_THAT(sigaltstack(nullptr, &stack), SyscallSucceeds());
diff --git a/test/syscalls/linux/sigiret.cc b/test/syscalls/linux/sigiret.cc
index a47c781ea..4deb1ae95 100644
--- a/test/syscalls/linux/sigiret.cc
+++ b/test/syscalls/linux/sigiret.cc
@@ -78,8 +78,8 @@ TEST(SigIretTest, CheckRcxR11) {
"1: pause; cmpl $0, %[gotvtalrm]; je 1b;" // while (!gotvtalrm);
"movq %%rcx, %[rcx];" // rcx = %rcx
"movq %%r11, %[r11];" // r11 = %r11
- : [ready] "=m"(ready), [rcx] "+m"(rcx), [r11] "+m"(r11)
- : [gotvtalrm] "m"(gotvtalrm)
+ : [ ready ] "=m"(ready), [ rcx ] "+m"(rcx), [ r11 ] "+m"(r11)
+ : [ gotvtalrm ] "m"(gotvtalrm)
: "cc", "memory", "rcx", "r11");
// If sigreturn(2) returns via 'sysret' then %rcx and %r11 will be
diff --git a/test/syscalls/linux/socket_bind_to_device_sequence.cc b/test/syscalls/linux/socket_bind_to_device_sequence.cc
index 34b1058a9..637d1151a 100644
--- a/test/syscalls/linux/socket_bind_to_device_sequence.cc
+++ b/test/syscalls/linux/socket_bind_to_device_sequence.cc
@@ -66,7 +66,7 @@ class BindToDeviceSequenceTest : public ::testing::TestWithParam<SocketKind> {
// Gets a device by device_id. If the device_id has been seen before, returns
// the previously returned device. If not, finds or creates a new device.
// Returns an empty string on failure.
- void GetDevice(int device_id, string *device_name) {
+ void GetDevice(int device_id, string* device_name) {
auto device = devices_.find(device_id);
if (device != devices_.end()) {
*device_name = device->second;
@@ -112,7 +112,7 @@ class BindToDeviceSequenceTest : public ::testing::TestWithParam<SocketKind> {
// Sets the socket_id to uniquely identify the socket bound if it is not
// nullptr.
void BindSocket(bool reuse_port, bool reuse_addr, int device_id = 0,
- int want = 0, int *socket_id = nullptr) {
+ int want = 0, int* socket_id = nullptr) {
next_socket_id_++;
sockets_to_close_[next_socket_id_] = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
auto socket_fd = sockets_to_close_[next_socket_id_]->get();
@@ -154,12 +154,12 @@ class BindToDeviceSequenceTest : public ::testing::TestWithParam<SocketKind> {
addr.sin_port = port_;
if (want == 0) {
ASSERT_THAT(
- bind(socket_fd, reinterpret_cast<const struct sockaddr *>(&addr),
+ bind(socket_fd, reinterpret_cast<const struct sockaddr*>(&addr),
sizeof(addr)),
SyscallSucceeds());
} else {
ASSERT_THAT(
- bind(socket_fd, reinterpret_cast<const struct sockaddr *>(&addr),
+ bind(socket_fd, reinterpret_cast<const struct sockaddr*>(&addr),
sizeof(addr)),
SyscallFailsWithErrno(want));
}
@@ -169,7 +169,7 @@ class BindToDeviceSequenceTest : public ::testing::TestWithParam<SocketKind> {
// remember it for future commands.
socklen_t addr_size = sizeof(addr);
ASSERT_THAT(
- getsockname(socket_fd, reinterpret_cast<struct sockaddr *>(&addr),
+ getsockname(socket_fd, reinterpret_cast<struct sockaddr*>(&addr),
&addr_size),
SyscallSucceeds());
port_ = addr.sin_port;
diff --git a/test/syscalls/linux/socket_inet_loopback.cc b/test/syscalls/linux/socket_inet_loopback.cc
index 2f9821555..3bf7081b9 100644
--- a/test/syscalls/linux/socket_inet_loopback.cc
+++ b/test/syscalls/linux/socket_inet_loopback.cc
@@ -828,6 +828,164 @@ TEST_P(SocketInetLoopbackTest, AcceptedInheritsTCPUserTimeout) {
EXPECT_EQ(get, kUserTimeout);
}
+// TODO(gvisor.dev/issue/1688): Partially completed passive endpoints are not
+// saved. Enable S/R once issue is fixed.
+TEST_P(SocketInetLoopbackTest, TCPDeferAccept_NoRandomSave) {
+ // TODO(gvisor.dev/issue/1688): Partially completed passive endpoints are not
+ // saved. Enable S/R issue is fixed.
+ DisableSave ds;
+
+ auto const& param = GetParam();
+ TestAddress const& listener = param.listener;
+ TestAddress const& connector = param.connector;
+
+ // Create the listening socket.
+ const FileDescriptor listen_fd = ASSERT_NO_ERRNO_AND_VALUE(
+ Socket(listener.family(), SOCK_STREAM, IPPROTO_TCP));
+ sockaddr_storage listen_addr = listener.addr;
+ ASSERT_THAT(bind(listen_fd.get(), reinterpret_cast<sockaddr*>(&listen_addr),
+ listener.addr_len),
+ SyscallSucceeds());
+ ASSERT_THAT(listen(listen_fd.get(), SOMAXCONN), SyscallSucceeds());
+
+ // Get the port bound by the listening socket.
+ socklen_t addrlen = listener.addr_len;
+ ASSERT_THAT(getsockname(listen_fd.get(),
+ reinterpret_cast<sockaddr*>(&listen_addr), &addrlen),
+ SyscallSucceeds());
+
+ const uint16_t port =
+ ASSERT_NO_ERRNO_AND_VALUE(AddrPort(listener.family(), listen_addr));
+
+ // Set the TCP_DEFER_ACCEPT on the listening socket.
+ constexpr int kTCPDeferAccept = 3;
+ ASSERT_THAT(setsockopt(listen_fd.get(), IPPROTO_TCP, TCP_DEFER_ACCEPT,
+ &kTCPDeferAccept, sizeof(kTCPDeferAccept)),
+ SyscallSucceeds());
+
+ // Connect to the listening socket.
+ FileDescriptor conn_fd = ASSERT_NO_ERRNO_AND_VALUE(
+ Socket(connector.family(), SOCK_STREAM, IPPROTO_TCP));
+
+ sockaddr_storage conn_addr = connector.addr;
+ ASSERT_NO_ERRNO(SetAddrPort(connector.family(), &conn_addr, port));
+ ASSERT_THAT(RetryEINTR(connect)(conn_fd.get(),
+ reinterpret_cast<sockaddr*>(&conn_addr),
+ connector.addr_len),
+ SyscallSucceeds());
+
+ // Set the listening socket to nonblock so that we can verify that there is no
+ // connection in queue despite the connect above succeeding since the peer has
+ // sent no data and TCP_DEFER_ACCEPT is set on the listening socket. Set the
+ // FD to O_NONBLOCK.
+ int opts;
+ ASSERT_THAT(opts = fcntl(listen_fd.get(), F_GETFL), SyscallSucceeds());
+ opts |= O_NONBLOCK;
+ ASSERT_THAT(fcntl(listen_fd.get(), F_SETFL, opts), SyscallSucceeds());
+
+ ASSERT_THAT(accept(listen_fd.get(), nullptr, nullptr),
+ SyscallFailsWithErrno(EWOULDBLOCK));
+
+ // Set FD back to blocking.
+ opts &= ~O_NONBLOCK;
+ ASSERT_THAT(fcntl(listen_fd.get(), F_SETFL, opts), SyscallSucceeds());
+
+ // Now write some data to the socket.
+ int data = 0;
+ ASSERT_THAT(RetryEINTR(write)(conn_fd.get(), &data, sizeof(data)),
+ SyscallSucceedsWithValue(sizeof(data)));
+
+ // This should now cause the connection to complete and be delivered to the
+ // accept socket.
+
+ // Accept the connection.
+ auto accepted =
+ ASSERT_NO_ERRNO_AND_VALUE(Accept(listen_fd.get(), nullptr, nullptr));
+
+ // Verify that the accepted socket returns the data written.
+ int get = -1;
+ ASSERT_THAT(RetryEINTR(recv)(accepted.get(), &get, sizeof(get), 0),
+ SyscallSucceedsWithValue(sizeof(get)));
+
+ EXPECT_EQ(get, data);
+}
+
+// TODO(gvisor.dev/issue/1688): Partially completed passive endpoints are not
+// saved. Enable S/R once issue is fixed.
+TEST_P(SocketInetLoopbackTest, TCPDeferAcceptTimeout_NoRandomSave) {
+ // TODO(gvisor.dev/issue/1688): Partially completed passive endpoints are not
+ // saved. Enable S/R once issue is fixed.
+ DisableSave ds;
+
+ auto const& param = GetParam();
+ TestAddress const& listener = param.listener;
+ TestAddress const& connector = param.connector;
+
+ // Create the listening socket.
+ const FileDescriptor listen_fd = ASSERT_NO_ERRNO_AND_VALUE(
+ Socket(listener.family(), SOCK_STREAM, IPPROTO_TCP));
+ sockaddr_storage listen_addr = listener.addr;
+ ASSERT_THAT(bind(listen_fd.get(), reinterpret_cast<sockaddr*>(&listen_addr),
+ listener.addr_len),
+ SyscallSucceeds());
+ ASSERT_THAT(listen(listen_fd.get(), SOMAXCONN), SyscallSucceeds());
+
+ // Get the port bound by the listening socket.
+ socklen_t addrlen = listener.addr_len;
+ ASSERT_THAT(getsockname(listen_fd.get(),
+ reinterpret_cast<sockaddr*>(&listen_addr), &addrlen),
+ SyscallSucceeds());
+
+ const uint16_t port =
+ ASSERT_NO_ERRNO_AND_VALUE(AddrPort(listener.family(), listen_addr));
+
+ // Set the TCP_DEFER_ACCEPT on the listening socket.
+ constexpr int kTCPDeferAccept = 3;
+ ASSERT_THAT(setsockopt(listen_fd.get(), IPPROTO_TCP, TCP_DEFER_ACCEPT,
+ &kTCPDeferAccept, sizeof(kTCPDeferAccept)),
+ SyscallSucceeds());
+
+ // Connect to the listening socket.
+ FileDescriptor conn_fd = ASSERT_NO_ERRNO_AND_VALUE(
+ Socket(connector.family(), SOCK_STREAM, IPPROTO_TCP));
+
+ sockaddr_storage conn_addr = connector.addr;
+ ASSERT_NO_ERRNO(SetAddrPort(connector.family(), &conn_addr, port));
+ ASSERT_THAT(RetryEINTR(connect)(conn_fd.get(),
+ reinterpret_cast<sockaddr*>(&conn_addr),
+ connector.addr_len),
+ SyscallSucceeds());
+
+ // Set the listening socket to nonblock so that we can verify that there is no
+ // connection in queue despite the connect above succeeding since the peer has
+ // sent no data and TCP_DEFER_ACCEPT is set on the listening socket. Set the
+ // FD to O_NONBLOCK.
+ int opts;
+ ASSERT_THAT(opts = fcntl(listen_fd.get(), F_GETFL), SyscallSucceeds());
+ opts |= O_NONBLOCK;
+ ASSERT_THAT(fcntl(listen_fd.get(), F_SETFL, opts), SyscallSucceeds());
+
+ // Verify that there is no acceptable connection before TCP_DEFER_ACCEPT
+ // timeout is hit.
+ absl::SleepFor(absl::Seconds(kTCPDeferAccept - 1));
+ ASSERT_THAT(accept(listen_fd.get(), nullptr, nullptr),
+ SyscallFailsWithErrno(EWOULDBLOCK));
+
+ // Set FD back to blocking.
+ opts &= ~O_NONBLOCK;
+ ASSERT_THAT(fcntl(listen_fd.get(), F_SETFL, opts), SyscallSucceeds());
+
+ // Now sleep for a little over the TCP_DEFER_ACCEPT duration. When the timeout
+ // is hit a SYN-ACK should be retransmitted by the listener as a last ditch
+ // attempt to complete the connection with or without data.
+ absl::SleepFor(absl::Seconds(2));
+
+ // Verify that we have a connection that can be accepted even though no
+ // data was written.
+ auto accepted =
+ ASSERT_NO_ERRNO_AND_VALUE(Accept(listen_fd.get(), nullptr, nullptr));
+}
+
INSTANTIATE_TEST_SUITE_P(
All, SocketInetLoopbackTest,
::testing::Values(
diff --git a/test/syscalls/linux/socket_ip_tcp_generic.cc b/test/syscalls/linux/socket_ip_tcp_generic.cc
index 57ce8e169..27779e47c 100644
--- a/test/syscalls/linux/socket_ip_tcp_generic.cc
+++ b/test/syscalls/linux/socket_ip_tcp_generic.cc
@@ -24,6 +24,7 @@
#include <sys/un.h>
#include "gtest/gtest.h"
+#include "absl/memory/memory.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "test/syscalls/linux/socket_test_util.h"
@@ -875,5 +876,37 @@ TEST_P(TCPSocketPairTest, SetTCPUserTimeoutAboveZero) {
EXPECT_EQ(get, kAbove);
}
+TEST_P(TCPSocketPairTest, TCPResetDuringClose_NoRandomSave) {
+ DisableSave ds; // Too many syscalls.
+ constexpr int kThreadCount = 1000;
+ std::unique_ptr<ScopedThread> instances[kThreadCount];
+ for (int i = 0; i < kThreadCount; i++) {
+ instances[i] = absl::make_unique<ScopedThread>([&]() {
+ auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
+
+ ScopedThread t([&]() {
+ // Close one end to trigger sending of a FIN.
+ struct pollfd poll_fd = {sockets->second_fd(), POLLIN | POLLHUP, 0};
+ // Wait up to 20 seconds for the data.
+ constexpr int kPollTimeoutMs = 20000;
+ ASSERT_THAT(RetryEINTR(poll)(&poll_fd, 1, kPollTimeoutMs),
+ SyscallSucceedsWithValue(1));
+ ASSERT_THAT(close(sockets->release_second_fd()), SyscallSucceeds());
+ });
+
+ // Send some data then close.
+ constexpr char kStr[] = "abc";
+ ASSERT_THAT(write(sockets->first_fd(), kStr, 3),
+ SyscallSucceedsWithValue(3));
+ absl::SleepFor(absl::Milliseconds(10));
+ ASSERT_THAT(close(sockets->release_first_fd()), SyscallSucceeds());
+ t.Join();
+ });
+ }
+ for (int i = 0; i < kThreadCount; i++) {
+ instances[i]->Join();
+ }
+}
+
} // namespace testing
} // namespace gvisor
diff --git a/test/syscalls/linux/socket_netdevice.cc b/test/syscalls/linux/socket_netdevice.cc
index 405dbbd73..15d4b85a7 100644
--- a/test/syscalls/linux/socket_netdevice.cc
+++ b/test/syscalls/linux/socket_netdevice.cc
@@ -91,7 +91,7 @@ TEST(NetdeviceTest, Netmask) {
int prefixlen = -1;
ASSERT_NO_ERRNO(NetlinkRequestResponse(
fd, &req, sizeof(req),
- [&](const struct nlmsghdr *hdr) {
+ [&](const struct nlmsghdr* hdr) {
EXPECT_THAT(hdr->nlmsg_type, AnyOf(Eq(RTM_NEWADDR), Eq(NLMSG_DONE)));
EXPECT_TRUE((hdr->nlmsg_flags & NLM_F_MULTI) == NLM_F_MULTI)
@@ -107,8 +107,8 @@ TEST(NetdeviceTest, Netmask) {
// RTM_NEWADDR contains at least the header and ifaddrmsg.
EXPECT_GE(hdr->nlmsg_len, sizeof(*hdr) + sizeof(struct ifaddrmsg));
- struct ifaddrmsg *ifaddrmsg =
- reinterpret_cast<struct ifaddrmsg *>(NLMSG_DATA(hdr));
+ struct ifaddrmsg* ifaddrmsg =
+ reinterpret_cast<struct ifaddrmsg*>(NLMSG_DATA(hdr));
if (ifaddrmsg->ifa_index == static_cast<uint32_t>(ifr.ifr_ifindex) &&
ifaddrmsg->ifa_family == AF_INET) {
prefixlen = ifaddrmsg->ifa_prefixlen;
@@ -127,8 +127,8 @@ TEST(NetdeviceTest, Netmask) {
snprintf(ifr.ifr_name, IFNAMSIZ, "lo");
ASSERT_THAT(ioctl(sock.get(), SIOCGIFNETMASK, &ifr), SyscallSucceeds());
EXPECT_EQ(ifr.ifr_netmask.sa_family, AF_INET);
- struct sockaddr_in *sin =
- reinterpret_cast<struct sockaddr_in *>(&ifr.ifr_netmask);
+ struct sockaddr_in* sin =
+ reinterpret_cast<struct sockaddr_in*>(&ifr.ifr_netmask);
EXPECT_EQ(sin->sin_addr.s_addr, mask);
}
diff --git a/test/syscalls/linux/socket_netlink_route.cc b/test/syscalls/linux/socket_netlink_route.cc
index ef567f512..1e28e658d 100644
--- a/test/syscalls/linux/socket_netlink_route.cc
+++ b/test/syscalls/linux/socket_netlink_route.cc
@@ -442,6 +442,90 @@ TEST(NetlinkRouteTest, GetRouteDump) {
EXPECT_TRUE(dstFound);
}
+// GetRouteRequest tests a RTM_GETROUTE request with RTM_F_LOOKUP_TABLE flag.
+TEST(NetlinkRouteTest, GetRouteRequest) {
+ FileDescriptor fd =
+ ASSERT_NO_ERRNO_AND_VALUE(NetlinkBoundSocket(NETLINK_ROUTE));
+ uint32_t port = ASSERT_NO_ERRNO_AND_VALUE(NetlinkPortID(fd.get()));
+
+ struct __attribute__((__packed__)) request {
+ struct nlmsghdr hdr;
+ struct rtmsg rtm;
+ struct nlattr nla;
+ struct in_addr sin_addr;
+ };
+
+ constexpr uint32_t kSeq = 12345;
+
+ struct request req = {};
+ req.hdr.nlmsg_len = sizeof(req);
+ req.hdr.nlmsg_type = RTM_GETROUTE;
+ req.hdr.nlmsg_flags = NLM_F_REQUEST;
+ req.hdr.nlmsg_seq = kSeq;
+
+ req.rtm.rtm_family = AF_INET;
+ req.rtm.rtm_dst_len = 32;
+ req.rtm.rtm_src_len = 0;
+ req.rtm.rtm_tos = 0;
+ req.rtm.rtm_table = RT_TABLE_UNSPEC;
+ req.rtm.rtm_protocol = RTPROT_UNSPEC;
+ req.rtm.rtm_scope = RT_SCOPE_UNIVERSE;
+ req.rtm.rtm_type = RTN_UNSPEC;
+ req.rtm.rtm_flags = RTM_F_LOOKUP_TABLE;
+
+ req.nla.nla_len = 8;
+ req.nla.nla_type = RTA_DST;
+ inet_aton("127.0.0.2", &req.sin_addr);
+
+ bool rtDstFound = false;
+ ASSERT_NO_ERRNO(NetlinkRequestResponseSingle(
+ fd, &req, sizeof(req), [&](const struct nlmsghdr* hdr) {
+ // Validate the reponse to RTM_GETROUTE request with RTM_F_LOOKUP_TABLE
+ // flag.
+ EXPECT_THAT(hdr->nlmsg_type, RTM_NEWROUTE);
+
+ EXPECT_TRUE(hdr->nlmsg_flags == 0) << std::hex << hdr->nlmsg_flags;
+
+ EXPECT_EQ(hdr->nlmsg_seq, kSeq);
+ EXPECT_EQ(hdr->nlmsg_pid, port);
+
+ // RTM_NEWROUTE contains at least the header and rtmsg.
+ ASSERT_GE(hdr->nlmsg_len, NLMSG_SPACE(sizeof(struct rtmsg)));
+ const struct rtmsg* msg =
+ reinterpret_cast<const struct rtmsg*>(NLMSG_DATA(hdr));
+
+ // NOTE: rtmsg fields are char fields.
+ std::cout << "Found route table=" << static_cast<int>(msg->rtm_table)
+ << ", protocol=" << static_cast<int>(msg->rtm_protocol)
+ << ", scope=" << static_cast<int>(msg->rtm_scope)
+ << ", type=" << static_cast<int>(msg->rtm_type);
+
+ EXPECT_EQ(msg->rtm_family, AF_INET);
+ EXPECT_EQ(msg->rtm_dst_len, 32);
+ EXPECT_TRUE((msg->rtm_flags & RTM_F_CLONED) == RTM_F_CLONED)
+ << std::hex << msg->rtm_flags;
+
+ int len = RTM_PAYLOAD(hdr);
+ std::cout << ", len=" << len;
+ for (struct rtattr* attr = RTM_RTA(msg); RTA_OK(attr, len);
+ attr = RTA_NEXT(attr, len)) {
+ if (attr->rta_type == RTA_DST) {
+ char address[INET_ADDRSTRLEN] = {};
+ inet_ntop(AF_INET, RTA_DATA(attr), address, sizeof(address));
+ std::cout << ", dst=" << address;
+ rtDstFound = true;
+ } else if (attr->rta_type == RTA_OIF) {
+ const char* oif = reinterpret_cast<const char*>(RTA_DATA(attr));
+ std::cout << ", oif=" << oif;
+ }
+ }
+
+ std::cout << std::endl;
+ }));
+ // Found RTA_DST for RTM_F_LOOKUP_TABLE.
+ EXPECT_TRUE(rtDstFound);
+}
+
// RecvmsgTrunc tests the recvmsg MSG_TRUNC flag with zero length output
// buffer. MSG_TRUNC with a zero length buffer should consume subsequent
// messages off the socket.
diff --git a/test/syscalls/linux/socket_netlink_util.cc b/test/syscalls/linux/socket_netlink_util.cc
index 723f5d728..cd2212a1a 100644
--- a/test/syscalls/linux/socket_netlink_util.cc
+++ b/test/syscalls/linux/socket_netlink_util.cc
@@ -108,5 +108,43 @@ PosixError NetlinkRequestResponse(
return NoError();
}
+PosixError NetlinkRequestResponseSingle(
+ const FileDescriptor& fd, void* request, size_t len,
+ const std::function<void(const struct nlmsghdr* hdr)>& fn) {
+ struct iovec iov = {};
+ iov.iov_base = request;
+ iov.iov_len = len;
+
+ struct msghdr msg = {};
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ // No destination required; it defaults to pid 0, the kernel.
+
+ RETURN_ERROR_IF_SYSCALL_FAIL(RetryEINTR(sendmsg)(fd.get(), &msg, 0));
+
+ constexpr size_t kBufferSize = 4096;
+ std::vector<char> buf(kBufferSize);
+ iov.iov_base = buf.data();
+ iov.iov_len = buf.size();
+
+ int ret;
+ RETURN_ERROR_IF_SYSCALL_FAIL(ret = RetryEINTR(recvmsg)(fd.get(), &msg, 0));
+
+ // We don't bother with the complexity of dealing with truncated messages.
+ // We must allocate a large enough buffer up front.
+ if ((msg.msg_flags & MSG_TRUNC) == MSG_TRUNC) {
+ return PosixError(
+ EIO,
+ absl::StrCat("Received truncated message with flags: ", msg.msg_flags));
+ }
+
+ for (struct nlmsghdr* hdr = reinterpret_cast<struct nlmsghdr*>(buf.data());
+ NLMSG_OK(hdr, ret); hdr = NLMSG_NEXT(hdr, ret)) {
+ fn(hdr);
+ }
+
+ return NoError();
+}
+
} // namespace testing
} // namespace gvisor
diff --git a/test/syscalls/linux/socket_netlink_util.h b/test/syscalls/linux/socket_netlink_util.h
index 76e772c48..3678c0599 100644
--- a/test/syscalls/linux/socket_netlink_util.h
+++ b/test/syscalls/linux/socket_netlink_util.h
@@ -32,12 +32,21 @@ PosixErrorOr<FileDescriptor> NetlinkBoundSocket(int protocol);
// Returns the port ID of the passed socket.
PosixErrorOr<uint32_t> NetlinkPortID(int fd);
-// Send the passed request and call fn will all response netlink messages.
+// Send the passed request and call fn on all response netlink messages.
+//
+// To be used on requests with NLM_F_MULTI reponses.
PosixError NetlinkRequestResponse(
const FileDescriptor& fd, void* request, size_t len,
const std::function<void(const struct nlmsghdr* hdr)>& fn,
bool expect_nlmsgerr);
+// Send the passed request and call fn on all response netlink messages.
+//
+// To be used on requests without NLM_F_MULTI reponses.
+PosixError NetlinkRequestResponseSingle(
+ const FileDescriptor& fd, void* request, size_t len,
+ const std::function<void(const struct nlmsghdr* hdr)>& fn);
+
} // namespace testing
} // namespace gvisor
diff --git a/test/syscalls/linux/socket_stream_blocking.cc b/test/syscalls/linux/socket_stream_blocking.cc
index e9cc082bf..538ee2268 100644
--- a/test/syscalls/linux/socket_stream_blocking.cc
+++ b/test/syscalls/linux/socket_stream_blocking.cc
@@ -32,38 +32,38 @@ namespace gvisor {
namespace testing {
TEST_P(BlockingStreamSocketPairTest, BlockPartialWriteClosed) {
- // FIXME(b/35921550): gVisor doesn't support SO_SNDBUF on UDS, nor does it
- // enforce any limit; it will write arbitrary amounts of data without
- // blocking.
- SKIP_IF(IsRunningOnGvisor());
-
- auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
-
- int buffer_size;
- socklen_t length = sizeof(buffer_size);
- ASSERT_THAT(getsockopt(sockets->first_fd(), SOL_SOCKET, SO_SNDBUF,
- &buffer_size, &length),
- SyscallSucceeds());
-
- int wfd = sockets->first_fd();
- ScopedThread t([wfd, buffer_size]() {
- std::vector<char> buf(2 * buffer_size);
- // Write more than fits in the buffer. Blocks then returns partial write
- // when the other end is closed. The next call returns EPIPE.
- //
- // N.B. writes occur in chunks, so we may see less than buffer_size from
- // the first call.
- ASSERT_THAT(write(wfd, buf.data(), buf.size()),
- SyscallSucceedsWithValue(::testing::Gt(0)));
- ASSERT_THAT(write(wfd, buf.data(), buf.size()),
- ::testing::AnyOf(SyscallFailsWithErrno(EPIPE),
- SyscallFailsWithErrno(ECONNRESET)));
- });
-
- // Leave time for write to become blocked.
- absl::SleepFor(absl::Seconds(1));
-
- ASSERT_THAT(close(sockets->release_second_fd()), SyscallSucceeds());
+ // FIXME(b/35921550): gVisor doesn't support SO_SNDBUF on UDS, nor does it
+ // enforce any limit; it will write arbitrary amounts of data without
+ // blocking.
+ SKIP_IF(IsRunningOnGvisor());
+
+ auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
+
+ int buffer_size;
+ socklen_t length = sizeof(buffer_size);
+ ASSERT_THAT(getsockopt(sockets->first_fd(), SOL_SOCKET, SO_SNDBUF,
+ &buffer_size, &length),
+ SyscallSucceeds());
+
+ int wfd = sockets->first_fd();
+ ScopedThread t([wfd, buffer_size]() {
+ std::vector<char> buf(2 * buffer_size);
+ // Write more than fits in the buffer. Blocks then returns partial write
+ // when the other end is closed. The next call returns EPIPE.
+ //
+ // N.B. writes occur in chunks, so we may see less than buffer_size from
+ // the first call.
+ ASSERT_THAT(write(wfd, buf.data(), buf.size()),
+ SyscallSucceedsWithValue(::testing::Gt(0)));
+ ASSERT_THAT(write(wfd, buf.data(), buf.size()),
+ ::testing::AnyOf(SyscallFailsWithErrno(EPIPE),
+ SyscallFailsWithErrno(ECONNRESET)));
+ });
+
+ // Leave time for write to become blocked.
+ absl::SleepFor(absl::Seconds(1));
+
+ ASSERT_THAT(close(sockets->release_second_fd()), SyscallSucceeds());
}
// Random save may interrupt the call to sendmsg() in SendLargeSendMsg(),
diff --git a/test/syscalls/linux/splice.cc b/test/syscalls/linux/splice.cc
index 85232cb1f..faa1247f6 100644
--- a/test/syscalls/linux/splice.cc
+++ b/test/syscalls/linux/splice.cc
@@ -60,6 +60,62 @@ TEST(SpliceTest, TwoRegularFiles) {
SyscallFailsWithErrno(EINVAL));
}
+int memfd_create(const std::string& name, unsigned int flags) {
+ return syscall(__NR_memfd_create, name.c_str(), flags);
+}
+
+TEST(SpliceTest, NegativeOffset) {
+ // Create a new pipe.
+ int fds[2];
+ ASSERT_THAT(pipe(fds), SyscallSucceeds());
+ const FileDescriptor rfd(fds[0]);
+ const FileDescriptor wfd(fds[1]);
+
+ // Fill the pipe.
+ std::vector<char> buf(kPageSize);
+ RandomizeBuffer(buf.data(), buf.size());
+ ASSERT_THAT(write(wfd.get(), buf.data(), buf.size()),
+ SyscallSucceedsWithValue(kPageSize));
+
+ // Open the output file as write only.
+ int fd;
+ EXPECT_THAT(fd = memfd_create("negative", 0), SyscallSucceeds());
+ const FileDescriptor out_fd(fd);
+
+ loff_t out_offset = 0xffffffffffffffffull;
+ constexpr int kSize = 2;
+ EXPECT_THAT(splice(rfd.get(), nullptr, out_fd.get(), &out_offset, kSize, 0),
+ SyscallFailsWithErrno(EINVAL));
+}
+
+// Write offset + size overflows int64.
+//
+// This is a regression test for b/148041624.
+TEST(SpliceTest, WriteOverflow) {
+ // Create a new pipe.
+ int fds[2];
+ ASSERT_THAT(pipe(fds), SyscallSucceeds());
+ const FileDescriptor rfd(fds[0]);
+ const FileDescriptor wfd(fds[1]);
+
+ // Fill the pipe.
+ std::vector<char> buf(kPageSize);
+ RandomizeBuffer(buf.data(), buf.size());
+ ASSERT_THAT(write(wfd.get(), buf.data(), buf.size()),
+ SyscallSucceedsWithValue(kPageSize));
+
+ // Open the output file.
+ int fd;
+ EXPECT_THAT(fd = memfd_create("overflow", 0), SyscallSucceeds());
+ const FileDescriptor out_fd(fd);
+
+ // out_offset + kSize overflows INT64_MAX.
+ loff_t out_offset = 0x7ffffffffffffffeull;
+ constexpr int kSize = 3;
+ EXPECT_THAT(splice(rfd.get(), nullptr, out_fd.get(), &out_offset, kSize, 0),
+ SyscallFailsWithErrno(EINVAL));
+}
+
TEST(SpliceTest, SamePipe) {
// Create a new pipe.
int fds[2];
diff --git a/test/syscalls/linux/stat.cc b/test/syscalls/linux/stat.cc
index 30de2f8ff..388d75835 100644
--- a/test/syscalls/linux/stat.cc
+++ b/test/syscalls/linux/stat.cc
@@ -599,8 +599,8 @@ struct kernel_statx {
uint64_t __spare2[14];
};
-int statx(int dirfd, const char *pathname, int flags, unsigned int mask,
- struct kernel_statx *statxbuf) {
+int statx(int dirfd, const char* pathname, int flags, unsigned int mask,
+ struct kernel_statx* statxbuf) {
return syscall(SYS_statx, dirfd, pathname, flags, mask, statxbuf);
}
diff --git a/test/syscalls/linux/tcp_socket.cc b/test/syscalls/linux/tcp_socket.cc
index 33a5ac66c..525ccbd88 100644
--- a/test/syscalls/linux/tcp_socket.cc
+++ b/test/syscalls/linux/tcp_socket.cc
@@ -1286,6 +1286,59 @@ TEST_P(SimpleTcpSocketTest, SetTCPUserTimeout) {
EXPECT_EQ(get, kTCPUserTimeout);
}
+TEST_P(SimpleTcpSocketTest, SetTCPDeferAcceptNeg) {
+ FileDescriptor s =
+ ASSERT_NO_ERRNO_AND_VALUE(Socket(GetParam(), SOCK_STREAM, IPPROTO_TCP));
+
+ // -ve TCP_DEFER_ACCEPT is same as setting it to zero.
+ constexpr int kNeg = -1;
+ EXPECT_THAT(
+ setsockopt(s.get(), IPPROTO_TCP, TCP_DEFER_ACCEPT, &kNeg, sizeof(kNeg)),
+ SyscallSucceeds());
+ int get = -1;
+ socklen_t get_len = sizeof(get);
+ ASSERT_THAT(
+ getsockopt(s.get(), IPPROTO_TCP, TCP_USER_TIMEOUT, &get, &get_len),
+ SyscallSucceedsWithValue(0));
+ EXPECT_EQ(get_len, sizeof(get));
+ EXPECT_EQ(get, 0);
+}
+
+TEST_P(SimpleTcpSocketTest, GetTCPDeferAcceptDefault) {
+ FileDescriptor s =
+ ASSERT_NO_ERRNO_AND_VALUE(Socket(GetParam(), SOCK_STREAM, IPPROTO_TCP));
+
+ int get = -1;
+ socklen_t get_len = sizeof(get);
+ ASSERT_THAT(
+ getsockopt(s.get(), IPPROTO_TCP, TCP_USER_TIMEOUT, &get, &get_len),
+ SyscallSucceedsWithValue(0));
+ EXPECT_EQ(get_len, sizeof(get));
+ EXPECT_EQ(get, 0);
+}
+
+TEST_P(SimpleTcpSocketTest, SetTCPDeferAcceptGreaterThanZero) {
+ FileDescriptor s =
+ ASSERT_NO_ERRNO_AND_VALUE(Socket(GetParam(), SOCK_STREAM, IPPROTO_TCP));
+ // kTCPDeferAccept is in seconds.
+ // NOTE: linux translates seconds to # of retries and back from
+ // #of retries to seconds. Which means only certain values
+ // translate back exactly. That's why we use 3 here, a value of
+ // 5 will result in us getting back 7 instead of 5 in the
+ // getsockopt.
+ constexpr int kTCPDeferAccept = 3;
+ ASSERT_THAT(setsockopt(s.get(), IPPROTO_TCP, TCP_DEFER_ACCEPT,
+ &kTCPDeferAccept, sizeof(kTCPDeferAccept)),
+ SyscallSucceeds());
+ int get = -1;
+ socklen_t get_len = sizeof(get);
+ ASSERT_THAT(
+ getsockopt(s.get(), IPPROTO_TCP, TCP_DEFER_ACCEPT, &get, &get_len),
+ SyscallSucceeds());
+ EXPECT_EQ(get_len, sizeof(get));
+ EXPECT_EQ(get, kTCPDeferAccept);
+}
+
INSTANTIATE_TEST_SUITE_P(AllInetTests, SimpleTcpSocketTest,
::testing::Values(AF_INET, AF_INET6));
diff --git a/test/syscalls/linux/udp_socket_errqueue_test_case.cc b/test/syscalls/linux/udp_socket_errqueue_test_case.cc
index 147978f46..fcdba7279 100644
--- a/test/syscalls/linux/udp_socket_errqueue_test_case.cc
+++ b/test/syscalls/linux/udp_socket_errqueue_test_case.cc
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "test/syscalls/linux/udp_socket_test_cases.h"
+#ifndef __fuchsia__
#include <arpa/inet.h>
#include <fcntl.h>
@@ -27,6 +27,7 @@
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "test/syscalls/linux/socket_test_util.h"
+#include "test/syscalls/linux/udp_socket_test_cases.h"
#include "test/syscalls/linux/unix_domain_socket_test_util.h"
#include "test/util/test_util.h"
#include "test/util/thread_util.h"
@@ -52,3 +53,5 @@ TEST_P(UdpSocketTest, ErrorQueue) {
} // namespace testing
} // namespace gvisor
+
+#endif // __fuchsia__
diff --git a/test/syscalls/linux/utimes.cc b/test/syscalls/linux/utimes.cc
index 12b925a51..3a927a430 100644
--- a/test/syscalls/linux/utimes.cc
+++ b/test/syscalls/linux/utimes.cc
@@ -163,12 +163,12 @@ TEST(FutimesatTest, OnRelPath) {
TEST(FutimesatTest, InvalidNsec) {
auto f = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
struct timeval times[4][2] = {{
- {0, 1}, // Valid
+ {0, 1}, // Valid
{1, static_cast<int64_t>(1e7)} // Invalid
},
{
{1, static_cast<int64_t>(1e7)}, // Invalid
- {0, 1} // Valid
+ {0, 1} // Valid
},
{
{0, 1}, // Valid
@@ -288,14 +288,15 @@ TEST(UtimeTest, ZeroAtimeandMtime) {
TEST(UtimensatTest, InvalidNsec) {
auto f = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
- struct timespec times[2][2] = {{
- {0, UTIME_OMIT}, // Valid
- {2, static_cast<int64_t>(1e10)} // Invalid
- },
- {
- {2, static_cast<int64_t>(1e10)}, // Invalid
- {0, UTIME_OMIT} // Valid
- }};
+ struct timespec times[2][2] = {
+ {
+ {0, UTIME_OMIT}, // Valid
+ {2, static_cast<int64_t>(1e10)} // Invalid
+ },
+ {
+ {2, static_cast<int64_t>(1e10)}, // Invalid
+ {0, UTIME_OMIT} // Valid
+ }};
for (unsigned int i = 0; i < sizeof(times) / sizeof(times[0]); i++) {
std::cout << "test:" << i << "\n";
diff --git a/test/syscalls/linux/xattr.cc b/test/syscalls/linux/xattr.cc
index e77c355d7..ab21d68c6 100644
--- a/test/syscalls/linux/xattr.cc
+++ b/test/syscalls/linux/xattr.cc
@@ -131,7 +131,7 @@ TEST_F(XattrTest, XattrWriteOnly_NoRandomSave) {
}
TEST_F(XattrTest, XattrTrustedWithNonadmin) {
- // TODO(b/127675828): Support setxattr and getxattr with "trusted" prefix.
+ // TODO(b/148380782): Support setxattr and getxattr with "trusted" prefix.
SKIP_IF(IsRunningOnGvisor());
SKIP_IF(ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));