diff options
Diffstat (limited to 'test/syscalls/linux/socket.cc')
-rw-r--r-- | test/syscalls/linux/socket.cc | 75 |
1 files changed, 73 insertions, 2 deletions
diff --git a/test/syscalls/linux/socket.cc b/test/syscalls/linux/socket.cc index 32f583581..b616c2c87 100644 --- a/test/syscalls/linux/socket.cc +++ b/test/syscalls/linux/socket.cc @@ -16,6 +16,7 @@ #include <sys/stat.h> #include <sys/statfs.h> #include <sys/types.h> +#include <sys/wait.h> #include <unistd.h> #include "gtest/gtest.h" @@ -90,8 +91,7 @@ TEST(SocketTest, UnixSocketStat) { EXPECT_EQ(statbuf.st_mode, S_IFSOCK | (sock_perm & ~mask)); // Timestamps should be equal and non-zero. - // TODO(b/158882152): Sockets currently don't implement timestamps. - if (!IsRunningOnGvisor()) { + if (!IsRunningWithVFS1()) { EXPECT_NE(statbuf.st_atime, 0); EXPECT_EQ(statbuf.st_atime, statbuf.st_mtime); EXPECT_EQ(statbuf.st_atime, statbuf.st_ctime); @@ -111,6 +111,77 @@ TEST(SocketTest, UnixSocketStatFS) { EXPECT_EQ(st.f_namelen, NAME_MAX); } +TEST(SocketTest, UnixSCMRightsOnlyPassedOnce_NoRandomSave) { + const DisableSave ds; + + int sockets[2]; + ASSERT_THAT(socketpair(AF_UNIX, SOCK_STREAM, 0, sockets), SyscallSucceeds()); + // Send more than what will fit inside the send/receive buffers, so that it is + // split into multiple messages. + constexpr int kBufSize = 0x100000; + + pid_t pid = fork(); + if (pid == 0) { + TEST_PCHECK(close(sockets[0]) == 0); + + // Construct a message with some control message. + struct msghdr msg = {}; + char control[CMSG_SPACE(sizeof(int))] = {}; + std::vector<char> buf(kBufSize); + struct iovec iov = {}; + msg.msg_control = control; + msg.msg_controllen = sizeof(control); + + struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + ((int*)CMSG_DATA(cmsg))[0] = sockets[1]; + + iov.iov_base = buf.data(); + iov.iov_len = kBufSize; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + int n = sendmsg(sockets[1], &msg, 0); + TEST_PCHECK(n == kBufSize); + TEST_PCHECK(shutdown(sockets[1], SHUT_RDWR) == 0); + TEST_PCHECK(close(sockets[1]) == 0); + _exit(0); + } + + close(sockets[1]); + + struct msghdr msg = {}; + char control[CMSG_SPACE(sizeof(int))] = {}; + std::vector<char> buf(kBufSize); + struct iovec iov = {}; + msg.msg_control = &control; + msg.msg_controllen = sizeof(control); + + iov.iov_base = buf.data(); + iov.iov_len = kBufSize; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + // The control message should only be present in the first message received. + int n; + ASSERT_THAT(n = recvmsg(sockets[0], &msg, 0), SyscallSucceeds()); + ASSERT_GT(n, 0); + ASSERT_EQ(msg.msg_controllen, CMSG_SPACE(sizeof(int))); + + while (n > 0) { + ASSERT_THAT(n = recvmsg(sockets[0], &msg, 0), SyscallSucceeds()); + ASSERT_EQ(msg.msg_controllen, 0); + } + + close(sockets[0]); + + int status; + ASSERT_THAT(waitpid(pid, &status, 0), SyscallSucceedsWithValue(pid)); + ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0); +} + using SocketOpenTest = ::testing::TestWithParam<int>; // UDS cannot be opened. |