Unverified Commit 67fc7000 authored by Christian Brauner's avatar Christian Brauner
Browse files

test: verify fdinfo for pidfd of reaped process



Test that the fdinfo field of a pidfd referring to a dead process
correctly shows Pid: -1 and NSpid: -1.

Cc: Christian Kellner <christian@kellner.me>
Cc: linux-kselftest@vger.kernel.org
Reviewed-by: default avatarChristian Kellner <christian@kellner.me>
Signed-off-by: default avatarChristian Brauner <christian.brauner@ubuntu.com>
Link: https://lore.kernel.org/r/20191017101832.5985-2-christian.brauner@ubuntu.com
parent 3d6d8da4
Loading
Loading
Loading
Loading
+45 −14
Original line number Diff line number Diff line
@@ -113,11 +113,15 @@ static struct child clone_newns(int (*fn)(void *), void *args,
	return ret;
}

static inline void child_close(struct child *child)
{
	close(child->fd);
}

static inline int child_join(struct child *child, struct error *err)
{
	int r;

	(void)close(child->fd);
	r = wait_for_pid(child->pid);
	if (r < 0)
		error_set(err, PIDFD_ERROR, "waitpid failed (ret %d, errno %d)",
@@ -128,6 +132,12 @@ static inline int child_join(struct child *child, struct error *err)
	return r;
}

static inline int child_join_close(struct child *child, struct error *err)
{
	child_close(child);
	return child_join(child, err);
}

static inline void trim_newline(char *str)
{
	char *pos = strrchr(str, '\n');
@@ -136,8 +146,8 @@ static inline void trim_newline(char *str)
		*pos = '\0';
}

static int verify_fdinfo_nspid(int pidfd, struct error *err,
			       const char *expect, ...)
static int verify_fdinfo(int pidfd, struct error *err, const char *prefix,
			 size_t prefix_len, const char *expect, ...)
{
	char buffer[512] = {0, };
	char path[512] = {0, };
@@ -160,17 +170,20 @@ static int verify_fdinfo_nspid(int pidfd, struct error *err,
				 pidfd);

	while (getline(&line, &n, f) != -1) {
		if (strncmp(line, "NSpid:", 6))
		char *val;

		if (strncmp(line, prefix, prefix_len))
			continue;

		found = 1;

		r = strcmp(line + 6, buffer);
		val = line + prefix_len;
		r = strcmp(val, buffer);
		if (r != 0) {
			trim_newline(line);
			trim_newline(buffer);
			error_set(err, PIDFD_FAIL, "NSpid: '%s' != '%s'",
				  line + 6, buffer);
			error_set(err, PIDFD_FAIL, "%s '%s' != '%s'",
				  prefix, val, buffer);
		}
		break;
	}
@@ -179,8 +192,8 @@ static int verify_fdinfo_nspid(int pidfd, struct error *err,
	fclose(f);

	if (found == 0)
		return error_set(err, PIDFD_FAIL, "NSpid not found for fd %d",
				 pidfd);
		return error_set(err, PIDFD_FAIL, "%s not found for fd %d",
				 prefix, pidfd);

	return PIDFD_PASS;
}
@@ -213,7 +226,7 @@ static int child_fdinfo_nspid_test(void *args)
	}

	pidfd = *(int *)args;
	r = verify_fdinfo_nspid(pidfd, &err, "\t0\n");
	r = verify_fdinfo(pidfd, &err, "NSpid:", 6, "\t0\n");

	if (r != PIDFD_PASS)
		ksft_print_msg("NSpid fdinfo check failed: %s\n", err.msg);
@@ -242,24 +255,42 @@ static void test_pidfd_fdinfo_nspid(void)
	/* The children will have pid 1 in the new pid namespace,
	 * so the line must be 'NSPid:\t<pid>\t1'.
	 */
	verify_fdinfo_nspid(a.fd, &err, "\t%d\t%d\n", a.pid, 1);
	verify_fdinfo_nspid(b.fd, &err, "\t%d\t%d\n", b.pid, 1);
	verify_fdinfo(a.fd, &err, "NSpid:", 6, "\t%d\t%d\n", a.pid, 1);
	verify_fdinfo(b.fd, &err, "NSpid:", 6, "\t%d\t%d\n", b.pid, 1);

	/* wait for the process, check the exit status and set
	 * 'err' accordingly, if it is not already set.
	 */
	child_join_close(&a, &err);
	child_join_close(&b, &err);

	error_report(&err, test_name);
}

static void test_pidfd_dead_fdinfo(void)
{
	struct child a;
	struct error err = {0, };
	const char *test_name = "pidfd check fdinfo for dead process";

	/* Create a new child in a new pid and mount namespace */
	a = clone_newns(child_fdinfo_nspid_test, NULL, &err);
	error_check(&err, test_name);
	child_join(&a, &err);
	child_join(&b, &err);

	verify_fdinfo(a.fd, &err, "Pid:", 4, "\t-1\n");
	verify_fdinfo(a.fd, &err, "NSpid:", 6, "\t-1\n");
	child_close(&a);
	error_report(&err, test_name);
}

int main(int argc, char **argv)
{
	ksft_print_header();
	ksft_set_plan(1);
	ksft_set_plan(2);

	test_pidfd_fdinfo_nspid();
	test_pidfd_dead_fdinfo();

	return ksft_exit_pass();
}