Commit 55d9ad97 authored by Christian Brauner's avatar Christian Brauner

tests: add CLONE_NEWTIME setns tests

Now that pidfds support CLONE_NEWTIME as well enable testing them in the
setns() testuite.
Signed-off-by: default avatarChristian Brauner <christian.brauner@ubuntu.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Michael Kerrisk <mtk.manpages@gmail.com>
Cc: Dmitry Safonov <dima@arista.com>
Cc: Andrei Vagin <avagin@gmail.com>
Link: https://lore.kernel.org/r/20200706154912.3248030-5-christian.brauner@ubuntu.com
parent 76c12881
...@@ -22,6 +22,10 @@ ...@@ -22,6 +22,10 @@
#define P_PIDFD 3 #define P_PIDFD 3
#endif #endif
#ifndef CLONE_NEWTIME
#define CLONE_NEWTIME 0x00000080
#endif
#ifndef CLONE_PIDFD #ifndef CLONE_PIDFD
#define CLONE_PIDFD 0x00001000 #define CLONE_PIDFD 0x00001000
#endif #endif
......
...@@ -32,6 +32,7 @@ enum { ...@@ -32,6 +32,7 @@ enum {
PIDFD_NS_NET, PIDFD_NS_NET,
PIDFD_NS_CGROUP, PIDFD_NS_CGROUP,
PIDFD_NS_PIDCLD, PIDFD_NS_PIDCLD,
PIDFD_NS_TIME,
PIDFD_NS_MAX PIDFD_NS_MAX
}; };
...@@ -47,6 +48,7 @@ const struct ns_info { ...@@ -47,6 +48,7 @@ const struct ns_info {
[PIDFD_NS_NET] = { "net", CLONE_NEWNET, }, [PIDFD_NS_NET] = { "net", CLONE_NEWNET, },
[PIDFD_NS_CGROUP] = { "cgroup", CLONE_NEWCGROUP, }, [PIDFD_NS_CGROUP] = { "cgroup", CLONE_NEWCGROUP, },
[PIDFD_NS_PIDCLD] = { "pid_for_children", 0, }, [PIDFD_NS_PIDCLD] = { "pid_for_children", 0, },
[PIDFD_NS_TIME] = { "time", CLONE_NEWTIME, },
}; };
FIXTURE(current_nsset) FIXTURE(current_nsset)
...@@ -83,9 +85,49 @@ pid_t create_child(int *pidfd, unsigned flags) ...@@ -83,9 +85,49 @@ pid_t create_child(int *pidfd, unsigned flags)
return sys_clone3(&args, sizeof(struct clone_args)); return sys_clone3(&args, sizeof(struct clone_args));
} }
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;
}
static ssize_t read_nointr(int fd, void *buf, size_t count)
{
ssize_t ret;
do {
ret = read(fd, buf, count);
} while (ret < 0 && errno == EINTR);
return ret;
}
static ssize_t write_nointr(int fd, const void *buf, size_t count)
{
ssize_t ret;
do {
ret = write(fd, buf, count);
} while (ret < 0 && errno == EINTR);
return ret;
}
FIXTURE_SETUP(current_nsset) FIXTURE_SETUP(current_nsset)
{ {
int i, proc_fd, ret; int i, proc_fd, ret;
int ipc_sockets[2];
char c;
for (i = 0; i < PIDFD_NS_MAX; i++) { for (i = 0; i < PIDFD_NS_MAX; i++) {
self->nsfds[i] = -EBADF; self->nsfds[i] = -EBADF;
...@@ -130,6 +172,9 @@ FIXTURE_SETUP(current_nsset) ...@@ -130,6 +172,9 @@ FIXTURE_SETUP(current_nsset)
TH_LOG("%m - Failed to open pidfd for process %d", self->pid); 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. */ /* Create tasks that will be stopped. */
self->child_pid1 = create_child(&self->child_pidfd1, self->child_pid1 = create_child(&self->child_pidfd1,
CLONE_NEWUSER | CLONE_NEWNS | CLONE_NEWUSER | CLONE_NEWNS |
...@@ -139,10 +184,27 @@ FIXTURE_SETUP(current_nsset) ...@@ -139,10 +184,27 @@ FIXTURE_SETUP(current_nsset)
EXPECT_GE(self->child_pid1, 0); EXPECT_GE(self->child_pid1, 0);
if (self->child_pid1 == 0) { if (self->child_pid1 == 0) {
close(ipc_sockets[0]);
if (!switch_timens())
_exit(EXIT_FAILURE);
if (write_nointr(ipc_sockets[1], "1", 1) < 0)
_exit(EXIT_FAILURE);
close(ipc_sockets[1]);
pause(); pause();
_exit(EXIT_SUCCESS); _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);
self->child_pid2 = create_child(&self->child_pidfd2, self->child_pid2 = create_child(&self->child_pidfd2,
CLONE_NEWUSER | CLONE_NEWNS | CLONE_NEWUSER | CLONE_NEWNS |
CLONE_NEWCGROUP | CLONE_NEWIPC | CLONE_NEWCGROUP | CLONE_NEWIPC |
...@@ -151,10 +213,24 @@ FIXTURE_SETUP(current_nsset) ...@@ -151,10 +213,24 @@ FIXTURE_SETUP(current_nsset)
EXPECT_GE(self->child_pid2, 0); EXPECT_GE(self->child_pid2, 0);
if (self->child_pid2 == 0) { if (self->child_pid2 == 0) {
close(ipc_sockets[0]);
if (!switch_timens())
_exit(EXIT_FAILURE);
if (write_nointr(ipc_sockets[1], "1", 1) < 0)
_exit(EXIT_FAILURE);
close(ipc_sockets[1]);
pause(); pause();
_exit(EXIT_SUCCESS); _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++) { for (i = 0; i < PIDFD_NS_MAX; i++) {
char p[100]; char p[100];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment