xref: /linux/tools/testing/selftests/pidfd/pidfd_xattr_test.c (revision 260f6f4fda93c8485c8037865c941b42b9cba5d2)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 #define _GNU_SOURCE
4 #include <errno.h>
5 #include <fcntl.h>
6 #include <limits.h>
7 #include <linux/types.h>
8 #include <poll.h>
9 #include <pthread.h>
10 #include <sched.h>
11 #include <signal.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <syscall.h>
16 #include <sys/prctl.h>
17 #include <sys/wait.h>
18 #include <unistd.h>
19 #include <sys/socket.h>
20 #include <linux/kcmp.h>
21 #include <sys/stat.h>
22 #include <sys/xattr.h>
23 
24 #include "pidfd.h"
25 #include "../kselftest_harness.h"
26 
27 FIXTURE(pidfs_xattr)
28 {
29 	pid_t child_pid;
30 	int child_pidfd;
31 };
32 
33 FIXTURE_SETUP(pidfs_xattr)
34 {
35 	self->child_pid = create_child(&self->child_pidfd, CLONE_NEWUSER | CLONE_NEWPID);
36 	EXPECT_GE(self->child_pid, 0);
37 
38 	if (self->child_pid == 0)
39 		_exit(EXIT_SUCCESS);
40 }
41 
42 FIXTURE_TEARDOWN(pidfs_xattr)
43 {
44 	sys_waitid(P_PID, self->child_pid, NULL, WEXITED);
45 }
46 
47 TEST_F(pidfs_xattr, set_get_list_xattr_multiple)
48 {
49 	int ret, i;
50 	char xattr_name[32];
51 	char xattr_value[32];
52 	char buf[32];
53 	const int num_xattrs = 10;
54 	char list[PATH_MAX] = {};
55 
56 	for (i = 0; i < num_xattrs; i++) {
57 		snprintf(xattr_name, sizeof(xattr_name), "trusted.testattr%d", i);
58 		snprintf(xattr_value, sizeof(xattr_value), "testvalue%d", i);
59 		ret = fsetxattr(self->child_pidfd, xattr_name, xattr_value, strlen(xattr_value), 0);
60 		ASSERT_EQ(ret, 0);
61 	}
62 
63 	for (i = 0; i < num_xattrs; i++) {
64 		snprintf(xattr_name, sizeof(xattr_name), "trusted.testattr%d", i);
65 		snprintf(xattr_value, sizeof(xattr_value), "testvalue%d", i);
66 		memset(buf, 0, sizeof(buf));
67 		ret = fgetxattr(self->child_pidfd, xattr_name, buf, sizeof(buf));
68 		ASSERT_EQ(ret, strlen(xattr_value));
69 		ASSERT_EQ(strcmp(buf, xattr_value), 0);
70 	}
71 
72 	ret = flistxattr(self->child_pidfd, list, sizeof(list));
73 	ASSERT_GT(ret, 0);
74 	for (i = 0; i < num_xattrs; i++) {
75 		snprintf(xattr_name, sizeof(xattr_name), "trusted.testattr%d", i);
76 		bool found = false;
77 		for (char *it = list; it < list + ret; it += strlen(it) + 1) {
78 			if (strcmp(it, xattr_name))
79 				continue;
80 			found = true;
81 			break;
82 		}
83 		ASSERT_TRUE(found);
84 	}
85 
86 	for (i = 0; i < num_xattrs; i++) {
87 		snprintf(xattr_name, sizeof(xattr_name), "trusted.testattr%d", i);
88 		ret = fremovexattr(self->child_pidfd, xattr_name);
89 		ASSERT_EQ(ret, 0);
90 
91 		ret = fgetxattr(self->child_pidfd, xattr_name, buf, sizeof(buf));
92 		ASSERT_EQ(ret, -1);
93 		ASSERT_EQ(errno, ENODATA);
94 	}
95 }
96 
97 TEST_F(pidfs_xattr, set_get_list_xattr_persistent)
98 {
99 	int ret;
100 	char buf[32];
101 	char list[PATH_MAX] = {};
102 
103 	ret = fsetxattr(self->child_pidfd, "trusted.persistent", "persistent value", strlen("persistent value"), 0);
104 	ASSERT_EQ(ret, 0);
105 
106 	memset(buf, 0, sizeof(buf));
107 	ret = fgetxattr(self->child_pidfd, "trusted.persistent", buf, sizeof(buf));
108 	ASSERT_EQ(ret, strlen("persistent value"));
109 	ASSERT_EQ(strcmp(buf, "persistent value"), 0);
110 
111 	ret = flistxattr(self->child_pidfd, list, sizeof(list));
112 	ASSERT_GT(ret, 0);
113 	ASSERT_EQ(strcmp(list, "trusted.persistent"), 0)
114 
115 	ASSERT_EQ(close(self->child_pidfd), 0);
116 	self->child_pidfd = -EBADF;
117 	sleep(2);
118 
119 	self->child_pidfd = sys_pidfd_open(self->child_pid, 0);
120 	ASSERT_GE(self->child_pidfd, 0);
121 
122 	memset(buf, 0, sizeof(buf));
123 	ret = fgetxattr(self->child_pidfd, "trusted.persistent", buf, sizeof(buf));
124 	ASSERT_EQ(ret, strlen("persistent value"));
125 	ASSERT_EQ(strcmp(buf, "persistent value"), 0);
126 
127 	ret = flistxattr(self->child_pidfd, list, sizeof(list));
128 	ASSERT_GT(ret, 0);
129 	ASSERT_EQ(strcmp(list, "trusted.persistent"), 0);
130 }
131 
132 TEST_HARNESS_MAIN
133