Unverified Commit 55d9ad97 authored by Christian Brauner's avatar Christian Brauner
Browse files

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
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -22,6 +22,10 @@
#define P_PIDFD 3
#endif

#ifndef CLONE_NEWTIME
#define CLONE_NEWTIME 0x00000080
#endif

#ifndef CLONE_PIDFD
#define CLONE_PIDFD 0x00001000
#endif
+76 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ enum {
	PIDFD_NS_NET,
	PIDFD_NS_CGROUP,
	PIDFD_NS_PIDCLD,
	PIDFD_NS_TIME,
	PIDFD_NS_MAX
};

@@ -47,6 +48,7 @@ const struct ns_info {
	[PIDFD_NS_NET]    = { "net",              CLONE_NEWNET,    },
	[PIDFD_NS_CGROUP] = { "cgroup",           CLONE_NEWCGROUP, },
	[PIDFD_NS_PIDCLD] = { "pid_for_children", 0,               },
	[PIDFD_NS_TIME]	  = { "time",             CLONE_NEWTIME,   },
};

FIXTURE(current_nsset)
@@ -83,9 +85,49 @@ pid_t create_child(int *pidfd, unsigned flags)
	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)
{
	int i, proc_fd, ret;
	int ipc_sockets[2];
	char c;

	for (i = 0; i < PIDFD_NS_MAX; i++) {
		self->nsfds[i]		= -EBADF;
@@ -130,6 +172,9 @@ FIXTURE_SETUP(current_nsset)
		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. */
	self->child_pid1 = create_child(&self->child_pidfd1,
					CLONE_NEWUSER | CLONE_NEWNS |
@@ -139,10 +184,27 @@ FIXTURE_SETUP(current_nsset)
	EXPECT_GE(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();
		_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,
					CLONE_NEWUSER | CLONE_NEWNS |
					CLONE_NEWCGROUP | CLONE_NEWIPC |
@@ -151,10 +213,24 @@ FIXTURE_SETUP(current_nsset)
	EXPECT_GE(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();
		_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];