Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/tools/testing/selftests/pidfd/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 19 kB image not shown  

Quelle  pidfd_setns_test.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0

#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <linux/types.h>
#include <sched.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syscall.h>
#include <sys/prctl.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/stat.h>

#include "pidfd.h"
#include "../kselftest_harness.h"

enum {
 PIDFD_NS_USER,
 PIDFD_NS_MNT,
 PIDFD_NS_PID,
 PIDFD_NS_UTS,
 PIDFD_NS_IPC,
 PIDFD_NS_NET,
 PIDFD_NS_CGROUP,
 PIDFD_NS_PIDCLD,
 PIDFD_NS_TIME,
 PIDFD_NS_TIMECLD,
 PIDFD_NS_MAX
};

const struct ns_info {
 const char *name;
 int flag;
 unsigned int pidfd_ioctl;
} ns_info[] = {
 [PIDFD_NS_USER]    = { "user",              CLONE_NEWUSER,   PIDFD_GET_USER_NAMESPACE,              },
 [PIDFD_NS_MNT]     = { "mnt",               CLONE_NEWNS,     PIDFD_GET_MNT_NAMESPACE,               },
 [PIDFD_NS_PID]     = { "pid",               CLONE_NEWPID,    PIDFD_GET_PID_NAMESPACE,               },
 [PIDFD_NS_UTS]     = { "uts",               CLONE_NEWUTS,    PIDFD_GET_UTS_NAMESPACE,               },
 [PIDFD_NS_IPC]     = { "ipc",               CLONE_NEWIPC,    PIDFD_GET_IPC_NAMESPACE,               },
 [PIDFD_NS_NET]     = { "net",               CLONE_NEWNET,    PIDFD_GET_NET_NAMESPACE,               },
 [PIDFD_NS_CGROUP]  = { "cgroup",            CLONE_NEWCGROUP, PIDFD_GET_CGROUP_NAMESPACE,            },
 [PIDFD_NS_TIME]    = { "time",              CLONE_NEWTIME,   PIDFD_GET_TIME_NAMESPACE,              },
 [PIDFD_NS_PIDCLD]  = { "pid_for_children",  0,               PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE,  },
 [PIDFD_NS_TIMECLD] = { "time_for_children", 0,               PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE, },
};

FIXTURE(current_nsset)
{
 pid_t pid;
 int pidfd;
 int nsfds[PIDFD_NS_MAX];
 int child_pidfd_derived_nsfds[PIDFD_NS_MAX];

 pid_t child_pid_exited;
 int child_pidfd_exited;

 pid_t child_pid1;
 int child_pidfd1;
 int child_nsfds1[PIDFD_NS_MAX];
 int child_pidfd_derived_nsfds1[PIDFD_NS_MAX];

 pid_t child_pid2;
 int child_pidfd2;
 int child_nsfds2[PIDFD_NS_MAX];
 int child_pidfd_derived_nsfds2[PIDFD_NS_MAX];
};

static bool switch_timens(void)
{
 int fd, ret;

 if (unshare(CLONE_NEWTIME))
  return false;

 fd = open("/proc/self/ns/time_for_children", O_RDONLY | O_CLOEXEC);
 if (fd < 0)
  return false;

 ret = setns(fd, CLONE_NEWTIME);
 close(fd);
 return ret == 0;
}

FIXTURE_SETUP(current_nsset)
{
 int i, proc_fd, ret;
 int ipc_sockets[2];
 char c;

 for (i = 0; i < PIDFD_NS_MAX; i++) {
  self->nsfds[i]    = -EBADF;
  self->child_nsfds1[i]   = -EBADF;
  self->child_nsfds2[i]   = -EBADF;
  self->child_pidfd_derived_nsfds[i] = -EBADF;
  self->child_pidfd_derived_nsfds1[i] = -EBADF;
  self->child_pidfd_derived_nsfds2[i] = -EBADF;
 }

 proc_fd = open("/proc/self/ns", O_DIRECTORY | O_CLOEXEC);
 ASSERT_GE(proc_fd, 0) {
  TH_LOG("%m - Failed to open /proc/self/ns");
 }

 self->pid = getpid();
 self->pidfd = sys_pidfd_open(self->pid, 0);
 EXPECT_GT(self->pidfd, 0) {
  TH_LOG("%m - Failed to open pidfd for process %d", self->pid);
 }

 for (i = 0; i < PIDFD_NS_MAX; i++) {
  const struct ns_info *info = &ns_info[i];
  self->nsfds[i] = openat(proc_fd, info->name, O_RDONLY | O_CLOEXEC);
  if (self->nsfds[i] < 0) {
   EXPECT_EQ(errno, ENOENT) {
    TH_LOG("%m - Failed to open %s namespace for process %d",
           info->name, self->pid);
   }
  }

  self->child_pidfd_derived_nsfds[i] = ioctl(self->pidfd, info->pidfd_ioctl, 0);
  if (self->child_pidfd_derived_nsfds[i] < 0) {
   EXPECT_EQ(errno, EOPNOTSUPP) {
    TH_LOG("%m - Failed to derive %s namespace from pidfd of process %d",
           info->name, self->pid);
   }
  }
 }

 /* Create task that exits right away. */
 self->child_pid_exited = create_child(&self->child_pidfd_exited, 0);
 EXPECT_GE(self->child_pid_exited, 0);

 if (self->child_pid_exited == 0) {
  if (self->nsfds[PIDFD_NS_USER] >= 0 && unshare(CLONE_NEWUSER) < 0)
   _exit(EXIT_FAILURE);
  if (self->nsfds[PIDFD_NS_NET] >= 0 && unshare(CLONE_NEWNET) < 0)
   _exit(EXIT_FAILURE);
  _exit(EXIT_SUCCESS);
 }

 ASSERT_EQ(sys_waitid(P_PID, self->child_pid_exited, NULL, WEXITED | WNOWAIT), 0);

 self->pidfd = sys_pidfd_open(self->pid, 0);
 EXPECT_GE(self->pidfd, 0) {
  TH_LOG("%m - Failed to open pidfd for process %d", self->pid);
 }

 ret = socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
 EXPECT_EQ(ret, 0);

 /* Create tasks that will be stopped. */
 if (self->nsfds[PIDFD_NS_USER] >= 0 && self->nsfds[PIDFD_NS_PID] >= 0)
  self->child_pid1 = create_child(&self->child_pidfd1, CLONE_NEWUSER | CLONE_NEWPID);
 else if (self->nsfds[PIDFD_NS_PID] >= 0)
  self->child_pid1 = create_child(&self->child_pidfd1, CLONE_NEWPID);
 else if (self->nsfds[PIDFD_NS_USER] >= 0)
  self->child_pid1 = create_child(&self->child_pidfd1, CLONE_NEWUSER);
 else
  self->child_pid1 = create_child(&self->child_pidfd1, 0);
 EXPECT_GE(self->child_pid1, 0);

 if (self->child_pid1 == 0) {
  close(ipc_sockets[0]);

  if (self->nsfds[PIDFD_NS_MNT] >= 0 && unshare(CLONE_NEWNS) < 0) {
   TH_LOG("%m - Failed to unshare mount namespace for process %d", self->pid);
   _exit(EXIT_FAILURE);
  }
  if (self->nsfds[PIDFD_NS_CGROUP] >= 0 && unshare(CLONE_NEWCGROUP) < 0) {
   TH_LOG("%m - Failed to unshare cgroup namespace for process %d", self->pid);
   _exit(EXIT_FAILURE);
  }
  if (self->nsfds[PIDFD_NS_IPC] >= 0 && unshare(CLONE_NEWIPC) < 0) {
   TH_LOG("%m - Failed to unshare ipc namespace for process %d", self->pid);
   _exit(EXIT_FAILURE);
  }
  if (self->nsfds[PIDFD_NS_UTS] >= 0 && unshare(CLONE_NEWUTS) < 0) {
   TH_LOG("%m - Failed to unshare uts namespace for process %d", self->pid);
   _exit(EXIT_FAILURE);
  }
  if (self->nsfds[PIDFD_NS_NET] >= 0 && unshare(CLONE_NEWNET) < 0) {
   TH_LOG("%m - Failed to unshare net namespace for process %d", self->pid);
   _exit(EXIT_FAILURE);
  }
  if (self->nsfds[PIDFD_NS_TIME] >= 0 && !switch_timens()) {
   TH_LOG("%m - Failed to unshare time namespace for process %d", self->pid);
   _exit(EXIT_FAILURE);
  }

  if (write_nointr(ipc_sockets[1], "1", 1) < 0)
   _exit(EXIT_FAILURE);

  close(ipc_sockets[1]);

  pause();
  _exit(EXIT_SUCCESS);
 }

 close(ipc_sockets[1]);
 ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1);
 close(ipc_sockets[0]);

 ret = socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
 EXPECT_EQ(ret, 0);

 if (self->nsfds[PIDFD_NS_USER] >= 0 && self->nsfds[PIDFD_NS_PID] >= 0)
  self->child_pid2 = create_child(&self->child_pidfd2, CLONE_NEWUSER | CLONE_NEWPID);
 else if (self->nsfds[PIDFD_NS_PID] >= 0)
  self->child_pid2 = create_child(&self->child_pidfd2, CLONE_NEWPID);
 else if (self->nsfds[PIDFD_NS_USER] >= 0)
  self->child_pid2 = create_child(&self->child_pidfd2, CLONE_NEWUSER);
 else
  self->child_pid2 = create_child(&self->child_pidfd2, 0);
 EXPECT_GE(self->child_pid2, 0);

 if (self->child_pid2 == 0) {
  close(ipc_sockets[0]);

  if (self->nsfds[PIDFD_NS_MNT] >= 0 && unshare(CLONE_NEWNS) < 0) {
   TH_LOG("%m - Failed to unshare mount namespace for process %d", self->pid);
   _exit(EXIT_FAILURE);
  }
  if (self->nsfds[PIDFD_NS_CGROUP] >= 0 && unshare(CLONE_NEWCGROUP) < 0) {
   TH_LOG("%m - Failed to unshare cgroup namespace for process %d", self->pid);
   _exit(EXIT_FAILURE);
  }
  if (self->nsfds[PIDFD_NS_IPC] >= 0 && unshare(CLONE_NEWIPC) < 0) {
   TH_LOG("%m - Failed to unshare ipc namespace for process %d", self->pid);
   _exit(EXIT_FAILURE);
  }
  if (self->nsfds[PIDFD_NS_UTS] >= 0 && unshare(CLONE_NEWUTS) < 0) {
   TH_LOG("%m - Failed to unshare uts namespace for process %d", self->pid);
   _exit(EXIT_FAILURE);
  }
  if (self->nsfds[PIDFD_NS_NET] >= 0 && unshare(CLONE_NEWNET) < 0) {
   TH_LOG("%m - Failed to unshare net namespace for process %d", self->pid);
   _exit(EXIT_FAILURE);
  }
  if (self->nsfds[PIDFD_NS_TIME] >= 0 && !switch_timens()) {
   TH_LOG("%m - Failed to unshare time namespace for process %d", self->pid);
   _exit(EXIT_FAILURE);
  }

  if (write_nointr(ipc_sockets[1], "1", 1) < 0)
   _exit(EXIT_FAILURE);

  close(ipc_sockets[1]);

  pause();
  _exit(EXIT_SUCCESS);
 }

 close(ipc_sockets[1]);
 ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1);
 close(ipc_sockets[0]);

 for (i = 0; i < PIDFD_NS_MAX; i++) {
  char p[100];

  const struct ns_info *info = &ns_info[i];

  self->nsfds[i] = openat(proc_fd, info->name, O_RDONLY | O_CLOEXEC);
  if (self->nsfds[i] < 0) {
   EXPECT_EQ(errno, ENOENT) {
    TH_LOG("%m - Failed to open %s namespace for process %d",
           info->name, self->pid);
   }
  }

  ret = snprintf(p, sizeof(p), "/proc/%d/ns/%s",
          self->child_pid1, info->name);
  EXPECT_GT(ret, 0);
  EXPECT_LT(ret, sizeof(p));

  self->child_nsfds1[i] = open(p, O_RDONLY | O_CLOEXEC);
  if (self->child_nsfds1[i] < 0) {
   EXPECT_EQ(errno, ENOENT) {
    TH_LOG("%m - Failed to open %s namespace for process %d",
           info->name, self->child_pid1);
   }
  }

  ret = snprintf(p, sizeof(p), "/proc/%d/ns/%s",
          self->child_pid2, info->name);
  EXPECT_GT(ret, 0);
  EXPECT_LT(ret, sizeof(p));

  self->child_nsfds2[i] = open(p, O_RDONLY | O_CLOEXEC);
  if (self->child_nsfds2[i] < 0) {
   EXPECT_EQ(errno, ENOENT) {
    TH_LOG("%m - Failed to open %s namespace for process %d",
           info->name, self->child_pid1);
   }
  }

  self->child_pidfd_derived_nsfds1[i] = ioctl(self->child_pidfd1, info->pidfd_ioctl, 0);
  if (self->child_pidfd_derived_nsfds1[i] < 0) {
   EXPECT_EQ(errno, EOPNOTSUPP) {
    TH_LOG("%m - Failed to derive %s namespace from pidfd of process %d",
           info->name, self->child_pid1);
   }
  }

  self->child_pidfd_derived_nsfds2[i] = ioctl(self->child_pidfd2, info->pidfd_ioctl, 0);
  if (self->child_pidfd_derived_nsfds2[i] < 0) {
   EXPECT_EQ(errno, EOPNOTSUPP) {
    TH_LOG("%m - Failed to derive %s namespace from pidfd of process %d",
           info->name, self->child_pid2);
   }
  }
 }

 close(proc_fd);
}

FIXTURE_TEARDOWN(current_nsset)
{
 int i;

 ASSERT_EQ(sys_pidfd_send_signal(self->child_pidfd1,
     SIGKILL, NULL, 0), 0);
 ASSERT_EQ(sys_pidfd_send_signal(self->child_pidfd2,
     SIGKILL, NULL, 0), 0);

 for (i = 0; i < PIDFD_NS_MAX; i++) {
  if (self->nsfds[i] >= 0)
   close(self->nsfds[i]);
  if (self->child_nsfds1[i] >= 0)
   close(self->child_nsfds1[i]);
  if (self->child_nsfds2[i] >= 0)
   close(self->child_nsfds2[i]);
  if (self->child_pidfd_derived_nsfds[i] >= 0)
   close(self->child_pidfd_derived_nsfds[i]);
  if (self->child_pidfd_derived_nsfds1[i] >= 0)
   close(self->child_pidfd_derived_nsfds1[i]);
  if (self->child_pidfd_derived_nsfds2[i] >= 0)
   close(self->child_pidfd_derived_nsfds2[i]);
 }

 if (self->child_pidfd1 >= 0)
  EXPECT_EQ(0, close(self->child_pidfd1));
 if (self->child_pidfd2 >= 0)
  EXPECT_EQ(0, close(self->child_pidfd2));
 ASSERT_EQ(sys_waitid(P_PID, self->child_pid_exited, NULL, WEXITED), 0);
 ASSERT_EQ(sys_waitid(P_PID, self->child_pid1, NULL, WEXITED), 0);
 ASSERT_EQ(sys_waitid(P_PID, self->child_pid2, NULL, WEXITED), 0);
}

static int preserve_ns(const int pid, const char *ns)
{
 int ret;
 char path[50];

 ret = snprintf(path, sizeof(path), "/proc/%d/ns/%s", pid, ns);
 if (ret < 0 || (size_t)ret >= sizeof(path))
  return -EIO;

 return open(path, O_RDONLY | O_CLOEXEC);
}

static int in_same_namespace(int ns_fd1, pid_t pid2, const char *ns)
{
 int ns_fd2 = -EBADF;
 int ret = -1;
 struct stat ns_st1, ns_st2;

 ret = fstat(ns_fd1, &ns_st1);
 if (ret < 0)
  return -1;

 ns_fd2 = preserve_ns(pid2, ns);
 if (ns_fd2 < 0)
  return -1;

 ret = fstat(ns_fd2, &ns_st2);
 close(ns_fd2);
 if (ret < 0)
  return -1;

 /* processes are in the same namespace */
 if ((ns_st1.st_dev == ns_st2.st_dev) &&
     (ns_st1.st_ino == ns_st2.st_ino))
  return 1;

 /* processes are in different namespaces */
 return 0;
}

/* Test that we can't pass garbage to the kernel. */
TEST_F(current_nsset, invalid_flags)
{
 ASSERT_NE(setns(self->pidfd, 0), 0);
 EXPECT_EQ(errno, EINVAL);

 ASSERT_NE(setns(self->pidfd, -1), 0);
 EXPECT_EQ(errno, EINVAL);

 ASSERT_NE(setns(self->pidfd, CLONE_VM), 0);
 EXPECT_EQ(errno, EINVAL);

 ASSERT_NE(setns(self->pidfd, CLONE_NEWUSER | CLONE_VM), 0);
 EXPECT_EQ(errno, EINVAL);
}

/* Test that we can't attach to a task that has already exited. */
TEST_F(current_nsset, pidfd_exited_child)
{
 int i;
 pid_t pid;

 ASSERT_NE(setns(self->child_pidfd_exited, CLONE_NEWUSER | CLONE_NEWNET),
    0);
 EXPECT_EQ(errno, ESRCH);

 pid = getpid();
 for (i = 0; i < PIDFD_NS_MAX; i++) {
  const struct ns_info *info = &ns_info[i];
  /* Verify that we haven't changed any namespaces. */
  if (self->nsfds[i] >= 0)
   ASSERT_EQ(in_same_namespace(self->nsfds[i], pid, info->name), 1);
 }
}

TEST_F(current_nsset, pidfd_incremental_setns)
{
 int i;
 pid_t pid;

 pid = getpid();
 for (i = 0; i < PIDFD_NS_MAX; i++) {
  const struct ns_info *info = &ns_info[i];
  int nsfd;

  if (self->child_nsfds1[i] < 0)
   continue;

  if (info->flag) {
   ASSERT_EQ(setns(self->child_pidfd1, info->flag), 0) {
    TH_LOG("%m - Failed to setns to %s namespace of %d via pidfd %d",
           info->name, self->child_pid1,
           self->child_pidfd1);
   }
  }

  /* Verify that we have changed to the correct namespaces. */
  if (info->flag == CLONE_NEWPID)
   nsfd = self->nsfds[i];
  else
   nsfd = self->child_nsfds1[i];
  ASSERT_EQ(in_same_namespace(nsfd, pid, info->name), 1) {
   TH_LOG("setns failed to place us correctly into %s namespace of %d via pidfd %d",
          info->name, self->child_pid1,
          self->child_pidfd1);
  }
  TH_LOG("Managed to correctly setns to %s namespace of %d via pidfd %d",
         info->name, self->child_pid1, self->child_pidfd1);
 }
}

TEST_F(current_nsset, nsfd_incremental_setns)
{
 int i;
 pid_t pid;

 pid = getpid();
 for (i = 0; i < PIDFD_NS_MAX; i++) {
  const struct ns_info *info = &ns_info[i];
  int nsfd;

  if (self->child_nsfds1[i] < 0)
   continue;

  if (info->flag) {
   ASSERT_EQ(setns(self->child_nsfds1[i], info->flag), 0) {
    TH_LOG("%m - Failed to setns to %s namespace of %d via nsfd %d",
           info->name, self->child_pid1,
           self->child_nsfds1[i]);
   }
  }

  /* Verify that we have changed to the correct namespaces. */
  if (info->flag == CLONE_NEWPID)
   nsfd = self->nsfds[i];
  else
   nsfd = self->child_nsfds1[i];
  ASSERT_EQ(in_same_namespace(nsfd, pid, info->name), 1) {
   TH_LOG("setns failed to place us correctly into %s namespace of %d via nsfd %d",
          info->name, self->child_pid1,
          self->child_nsfds1[i]);
  }
  TH_LOG("Managed to correctly setns to %s namespace of %d via nsfd %d",
         info->name, self->child_pid1, self->child_nsfds1[i]);
 }
}

TEST_F(current_nsset, pidfd_derived_nsfd_incremental_setns)
{
 int i;
 pid_t pid;

 pid = getpid();
 for (i = 0; i < PIDFD_NS_MAX; i++) {
  const struct ns_info *info = &ns_info[i];
  int nsfd;

  if (self->child_pidfd_derived_nsfds1[i] < 0)
   continue;

  if (info->flag) {
   ASSERT_EQ(setns(self->child_pidfd_derived_nsfds1[i], info->flag), 0) {
    TH_LOG("%m - Failed to setns to %s namespace of %d via nsfd %d",
           info->name, self->child_pid1,
           self->child_pidfd_derived_nsfds1[i]);
   }
  }

  /* Verify that we have changed to the correct namespaces. */
  if (info->flag == CLONE_NEWPID)
   nsfd = self->child_pidfd_derived_nsfds[i];
  else
   nsfd = self->child_pidfd_derived_nsfds1[i];
  ASSERT_EQ(in_same_namespace(nsfd, pid, info->name), 1) {
   TH_LOG("setns failed to place us correctly into %s namespace of %d via nsfd %d",
          info->name, self->child_pid1,
          self->child_pidfd_derived_nsfds1[i]);
  }
  TH_LOG("Managed to correctly setns to %s namespace of %d via nsfd %d",
         info->name, self->child_pid1, self->child_pidfd_derived_nsfds1[i]);
 }
}

TEST_F(current_nsset, pidfd_one_shot_setns)
{
 unsigned flags = 0;
 int i;
 pid_t pid;

 for (i = 0; i < PIDFD_NS_MAX; i++) {
  const struct ns_info *info = &ns_info[i];

  if (self->child_nsfds1[i] < 0)
   continue;

  flags |= info->flag;
  TH_LOG("Adding %s namespace of %d to list of namespaces to attach to",
         info->name, self->child_pid1);
 }

 ASSERT_EQ(setns(self->child_pidfd1, flags), 0) {
  TH_LOG("%m - Failed to setns to namespaces of %d",
         self->child_pid1);
 }

 pid = getpid();
 for (i = 0; i < PIDFD_NS_MAX; i++) {
  const struct ns_info *info = &ns_info[i];
  int nsfd;

  if (self->child_nsfds1[i] < 0)
   continue;

  /* Verify that we have changed to the correct namespaces. */
  if (info->flag == CLONE_NEWPID)
   nsfd = self->nsfds[i];
  else
   nsfd = self->child_nsfds1[i];
  ASSERT_EQ(in_same_namespace(nsfd, pid, info->name), 1) {
   TH_LOG("setns failed to place us correctly into %s namespace of %d",
          info->name, self->child_pid1);
  }
  TH_LOG("Managed to correctly setns to %s namespace of %d",
         info->name, self->child_pid1);
 }
}

TEST_F(current_nsset, no_foul_play)
{
 unsigned flags = 0;
 int i;

 for (i = 0; i < PIDFD_NS_MAX; i++) {
  const struct ns_info *info = &ns_info[i];

  if (self->child_nsfds1[i] < 0)
   continue;

  flags |= info->flag;
  if (info->flag) /* No use logging pid_for_children. */
   TH_LOG("Adding %s namespace of %d to list of namespaces to attach to",
          info->name, self->child_pid1);
 }

 ASSERT_EQ(setns(self->child_pidfd1, flags), 0) {
  TH_LOG("%m - Failed to setns to namespaces of %d vid pidfd %d",
         self->child_pid1, self->child_pidfd1);
 }

 /*
 * Can't setns to a user namespace outside of our hierarchy since we
 * don't have caps in there and didn't create it. That means that under
 * no circumstances should we be able to setns to any of the other
 * ones since they aren't owned by our user namespace.
 */

 for (i = 0; i < PIDFD_NS_MAX; i++) {
  const struct ns_info *info = &ns_info[i];

  if (self->child_nsfds2[i] < 0 || !info->flag)
   continue;

  ASSERT_NE(setns(self->child_pidfd2, info->flag), 0) {
   TH_LOG("Managed to setns to %s namespace of %d via pidfd %d",
          info->name, self->child_pid2,
          self->child_pidfd2);
  }
  TH_LOG("%m - Correctly failed to setns to %s namespace of %d via pidfd %d",
         info->name, self->child_pid2,
         self->child_pidfd2);

  ASSERT_NE(setns(self->child_nsfds2[i], info->flag), 0) {
   TH_LOG("Managed to setns to %s namespace of %d via nsfd %d",
          info->name, self->child_pid2,
          self->child_nsfds2[i]);
  }
  TH_LOG("%m - Correctly failed to setns to %s namespace of %d via nsfd %d",
         info->name, self->child_pid2,
         self->child_nsfds2[i]);
 }

 /*
 * Can't setns to a user namespace outside of our hierarchy since we
 * don't have caps in there and didn't create it. That means that under
 * no circumstances should we be able to setns to any of the other
 * ones since they aren't owned by our user namespace.
 */

 for (i = 0; i < PIDFD_NS_MAX; i++) {
  const struct ns_info *info = &ns_info[i];

  if (self->child_pidfd_derived_nsfds2[i] < 0 || !info->flag)
   continue;

  ASSERT_NE(setns(self->child_pidfd_derived_nsfds2[i], info->flag), 0) {
   TH_LOG("Managed to setns to %s namespace of %d via nsfd %d",
          info->name, self->child_pid2,
          self->child_pidfd_derived_nsfds2[i]);
  }
  TH_LOG("%m - Correctly failed to setns to %s namespace of %d via nsfd %d",
         info->name, self->child_pid2,
         self->child_pidfd_derived_nsfds2[i]);
 }
}

TEST(setns_einval)
{
 int fd;

 fd = sys_memfd_create("rostock", 0);
 EXPECT_GT(fd, 0);

 ASSERT_NE(setns(fd, 0), 0);
 EXPECT_EQ(errno, EINVAL);
 close(fd);
}

TEST_HARNESS_MAIN

Messung V0.5
C=95 H=82 G=88

¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.