Adding more trace point integration tests for the following syscalls:

- chroot
 - dup
 - dup2
 - dup3
 - prlimit64
 - eventfd
 - eventfd2
 - bind
 - accept
 - accept4

Updates #4805

PiperOrigin-RevId: 489526376
This commit is contained in:
Shambhavi Srivastava
2022-11-18 11:48:42 -08:00
committed by gVisor bot
parent 619801c72a
commit 536a924f1a
4 changed files with 335 additions and 8 deletions
+120 -7
View File
@@ -75,7 +75,7 @@ func TestAll(t *testing.T) {
cutoffTime = time.Now()
cmd := exec.Command(
runsc,
"--debug", "--strace", "--alsologtostderr", // Debug logging for troubleshooting
"--debug", "--alsologtostderr", // Debug logging for troubleshooting
"--rootless", "--network=none", "--TESTONLY-unsafe-nonroot", // Disable features that we don't care
"--pod-init-config", cfgFile.Name(),
"do", workload)
@@ -112,14 +112,16 @@ func matchPoints(t *testing.T, msgs []test.Message) {
pb.MessageType_MESSAGE_SYSCALL_CHDIR: {checker: checkSyscallChdir},
pb.MessageType_MESSAGE_SYSCALL_SETID: {checker: checkSyscallSetid},
pb.MessageType_MESSAGE_SYSCALL_SETRESID: {checker: checkSyscallSetresid},
pb.MessageType_MESSAGE_SYSCALL_CHROOT: {checker: checkSyscallChroot},
pb.MessageType_MESSAGE_SYSCALL_DUP: {checker: checkSyscallDup},
pb.MessageType_MESSAGE_SYSCALL_PRLIMIT64: {checker: checkSyscallPrlimit64},
pb.MessageType_MESSAGE_SYSCALL_EVENTFD: {checker: checkSyscallEventfd},
pb.MessageType_MESSAGE_SYSCALL_BIND: {checker: checkSyscallBind},
pb.MessageType_MESSAGE_SYSCALL_ACCEPT: {checker: checkSyscallAccept},
// TODO(gvisor.dev/issue/4805): Add validation for these messages.
pb.MessageType_MESSAGE_SYSCALL_ACCEPT: {checker: checkTODO},
pb.MessageType_MESSAGE_SYSCALL_BIND: {checker: checkTODO},
pb.MessageType_MESSAGE_SYSCALL_CLONE: {checker: checkTODO},
pb.MessageType_MESSAGE_SYSCALL_DUP: {checker: checkTODO},
pb.MessageType_MESSAGE_SYSCALL_PIPE: {checker: checkTODO},
pb.MessageType_MESSAGE_SYSCALL_PRLIMIT64: {checker: checkTODO},
pb.MessageType_MESSAGE_SYSCALL_CLONE: {checker: checkTODO},
pb.MessageType_MESSAGE_SYSCALL_PIPE: {checker: checkTODO},
}
for _, msg := range msgs {
t.Logf("Processing message type %v", msg.MsgType)
@@ -540,6 +542,117 @@ func checkSyscallChdir(msg test.Message) error {
return nil
}
func checkSyscallDup(msg test.Message) error {
p := pb.Dup{}
if err := proto.Unmarshal(msg.Msg, &p); err != nil {
return err
}
if err := checkContextData(p.ContextData); err != nil {
return err
}
if p.OldFd < 0 {
return fmt.Errorf("invalid FD: %d", p.OldFd)
}
if p.NewFd < 0 {
return fmt.Errorf("invalid FD: %d", p.NewFd)
}
if p.Flags != unix.O_CLOEXEC && p.Flags != 0 {
return fmt.Errorf("invalid flag got: %v", p.Flags)
}
return nil
}
func checkSyscallPrlimit64(msg test.Message) error {
p := pb.Prlimit{}
if err := proto.Unmarshal(msg.Msg, &p); err != nil {
return err
}
if err := checkContextData(p.ContextData); err != nil {
return err
}
if p.Pid < 0 {
return fmt.Errorf("invalid PID: %d", p.Pid)
}
return nil
}
func checkSyscallEventfd(msg test.Message) error {
p := pb.Eventfd{}
if err := proto.Unmarshal(msg.Msg, &p); err != nil {
return err
}
if err := checkContextData(p.ContextData); err != nil {
return err
}
if p.Val < 0 {
return fmt.Errorf("invalid PID: %d", p.Val)
}
if p.Flags != unix.EFD_NONBLOCK && p.Flags != 0 {
return fmt.Errorf("invalid Flag got: %d, ", p.Flags)
}
return nil
}
func checkSyscallBind(msg test.Message) error {
p := pb.Bind{}
if err := proto.Unmarshal(msg.Msg, &p); err != nil {
return err
}
if err := checkContextData(p.ContextData); err != nil {
return err
}
if p.Fd < 0 {
return fmt.Errorf("invalid FD: %d", p.Fd)
}
if p.FdPath == " " {
return fmt.Errorf("invalid Path: %v", p.FdPath)
}
if len(p.Address) == 0 {
return fmt.Errorf("invalid address: %d", p.Address)
}
return nil
}
func checkSyscallAccept(msg test.Message) error {
p := pb.Accept{}
if err := proto.Unmarshal(msg.Msg, &p); err != nil {
return err
}
if err := checkContextData(p.ContextData); err != nil {
return err
}
if p.Fd < 0 {
return fmt.Errorf("invalid FD: %d", p.Fd)
}
if p.FdPath == "" {
return fmt.Errorf("invalid Path: %v", p.FdPath)
}
if len(p.Address) != 0 {
return fmt.Errorf("invalid address: %d, %v", p.Address, p.Sysno)
}
if p.Flags != 0 && p.Flags != unix.SOCK_CLOEXEC {
return fmt.Errorf("invalid flag got: %d", p.Flags)
}
return nil
}
func checkSyscallChroot(msg test.Message) error {
p := pb.Chroot{}
if err := proto.Unmarshal(msg.Msg, &p); err != nil {
return err
}
if err := checkContextData(p.ContextData); err != nil {
return err
}
if want := "trace_test.abc"; !strings.Contains(p.Pathname, want) {
return fmt.Errorf("wrong Pathname, want: %q, got: %q", want, p.Pathname)
}
return nil
}
func checkTODO(_ test.Message) error {
return nil
}
+1
View File
@@ -10,6 +10,7 @@ cc_binary(
],
visibility = ["//test/trace:__pkg__"],
deps = [
"//test/util:eventfd_util",
"//test/util:file_descriptor",
"//test/util:multiprocess_util",
"//test/util:posix_error",
+208
View File
@@ -14,18 +14,22 @@
#include <err.h>
#include <fcntl.h>
#include <sys/eventfd.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/un.h>
#include <unistd.h>
#include <csignal>
#include <iostream>
#include <ostream>
#include "absl/cleanup/cleanup.h"
#include "absl/strings/str_cat.h"
#include "absl/time/clock.h"
#include "test/util/eventfd_util.h"
#include "test/util/file_descriptor.h"
#include "test/util/multiprocess_util.h"
#include "test/util/posix_error.h"
@@ -261,6 +265,199 @@ void runSetresgid() {
}
}
void runChroot() {
const auto pathname = "trace_test.abc";
static constexpr mode_t kDefaultDirMode = 0755;
int path_or_error = mkdir(pathname, kDefaultDirMode);
if (path_or_error != 0) {
err(1, "mkdir");
}
if (chroot(pathname)) {
err(1, "chroot");
}
}
void runDup() {
const auto pathname = "trace_test.abc";
static constexpr mode_t kDefaultDirMode = 0755;
int path_or_error = mkdir(pathname, kDefaultDirMode);
if (path_or_error != 0) {
err(1, "mkdir");
}
int fd = open(pathname, O_DIRECTORY | O_RDONLY);
if (fd < 0) {
err(1, "open");
}
int res = dup(fd);
if (res < 0) {
err(1, "dup");
}
rmdir(pathname);
}
void runDup2() {
const auto pathname = "trace_test.abc";
static constexpr mode_t kDefaultDirMode = 0755;
int path_or_error = mkdir(pathname, kDefaultDirMode);
if (path_or_error != 0) {
err(1, "mkdir");
}
int oldfd = open(pathname, O_DIRECTORY | O_RDONLY);
if (oldfd < 0) {
err(1, "open");
}
int newfd = open(pathname, O_DIRECTORY | O_RDONLY);
if (newfd < 0) {
err(1, "open");
}
int res = dup2(oldfd, newfd);
if (res != newfd) {
err(1, "dup2");
}
rmdir(pathname);
}
void runDup3() {
const auto pathname = "trace_test.abc";
static constexpr mode_t kDefaultDirMode = 0755;
int path_or_error = mkdir(pathname, kDefaultDirMode);
if (path_or_error != 0) {
err(1, "mkdir");
}
int oldfd = open(pathname, O_DIRECTORY | O_RDONLY);
if (oldfd < 0) {
err(1, "open");
}
int newfd = open(pathname, O_DIRECTORY | O_RDONLY);
if (newfd < 0) {
err(1, "open");
}
int res = dup3(oldfd, newfd, O_CLOEXEC);
if (res != newfd) {
err(1, "dup3");
}
rmdir(pathname);
}
void runPrlimit64() {
struct rlimit setlim;
setlim.rlim_cur = 0;
setlim.rlim_max = RLIM_INFINITY;
int res = prlimit(0, RLIMIT_DATA, &setlim, nullptr);
if (res != 0) {
err(1, "prlimit64");
}
}
void runEventfd() {
int res = eventfd(0, EFD_NONBLOCK);
if (res < 0) {
err(1, "eventfd");
}
}
void runEventfd2() {
int res = Eventdfd2Setup(0, EFD_NONBLOCK);
if (res < 0) {
err(1, "eventfd2");
}
}
void runBind() {
auto path = absl::StrCat(std::string("\0", 1), "trace_test.abc");
struct sockaddr_un addr;
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, path.c_str(), path.size() + 1);
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd < 0) {
err(1, "socket");
}
auto sock_closer = absl::MakeCleanup([fd] { close(fd); });
if (bind(fd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr))) {
err(1, "bind");
}
}
void runAccept() {
auto path = absl::StrCat(std::string("\0", 1), "trace_test.abc");
struct sockaddr_un addr;
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, path.c_str(), path.size() + 1);
int server = socket(AF_UNIX, SOCK_STREAM, 0);
if (server < 0) {
err(1, "socket");
}
auto sock_closer = absl::MakeCleanup([server] { close(server); });
if (bind(server, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) < 0) {
err(1, "bind");
}
if (listen(server, 5) < 0) {
err(1, "listen");
}
int client = socket(AF_UNIX, SOCK_STREAM, 0);
if (client < 0) {
err(1, "socket");
}
auto client_closer = absl::MakeCleanup([client] { close(client); });
if (connect(client, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) <
0) {
err(1, "connect");
}
int fd = RetryEINTR(accept)(server, nullptr, nullptr);
if (fd < 0) {
err(1, "accept");
}
close(fd);
}
void runAccept4() {
auto path = absl::StrCat(std::string("\0", 1), "trace_test.abc");
struct sockaddr_un addr;
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, path.c_str(), path.size() + 1);
int server = socket(AF_UNIX, SOCK_STREAM, 0);
if (server < 0) {
err(1, "socket");
}
auto sock_closer = absl::MakeCleanup([server] { close(server); });
if (bind(server, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) < 0) {
err(1, "bind");
}
if (listen(server, 5) < 0) {
err(1, "listen");
}
int client = socket(AF_UNIX, SOCK_STREAM, 0);
if (client < 0) {
err(1, "socket");
}
auto client_closer = absl::MakeCleanup([client] { close(client); });
if (connect(client, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) <
0) {
err(1, "connect");
}
int fd = RetryEINTR(accept4)(server, nullptr, nullptr, SOCK_CLOEXEC);
if (fd < 0) {
err(1, "accept4");
}
close(fd);
}
} // namespace testing
} // namespace gvisor
@@ -275,5 +472,16 @@ int main(int argc, char** argv) {
::gvisor::testing::runSetsid();
::gvisor::testing::runSetresuid();
::gvisor::testing::runSetresgid();
::gvisor::testing::runDup();
::gvisor::testing::runDup2();
::gvisor::testing::runDup3();
::gvisor::testing::runPrlimit64();
::gvisor::testing::runEventfd();
::gvisor::testing::runEventfd2();
::gvisor::testing::runBind();
::gvisor::testing::runAccept();
::gvisor::testing::runAccept4();
// Run chroot at the end since it changes the root for all other tests.
::gvisor::testing::runChroot();
return 0;
}
+6 -1
View File
@@ -14,7 +14,7 @@
#ifndef GVISOR_TEST_UTIL_EVENTFD_UTIL_H_
#define GVISOR_TEST_UTIL_EVENTFD_UTIL_H_
#include <asm/unistd.h>
#include <sys/eventfd.h>
#include <cerrno>
@@ -37,6 +37,11 @@ inline PosixErrorOr<FileDescriptor> NewEventFD(unsigned int initval = 0,
return FileDescriptor(fd);
}
// This is a wrapper for the eventfd2(2) system call.
inline int Eventdfd2Setup(unsigned int initval, int flags) {
return syscall(__NR_eventfd2, initval, flags);
}
} // namespace testing
} // namespace gvisor