mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
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:
committed by
gVisor bot
parent
619801c72a
commit
536a924f1a
+120
-7
@@ -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
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user