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
FIXTURE(pidfs_xattr)27 FIXTURE(pidfs_xattr)
28 {
29 pid_t child_pid;
30 int child_pidfd;
31 };
32
FIXTURE_SETUP(pidfs_xattr)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
FIXTURE_TEARDOWN(pidfs_xattr)42 FIXTURE_TEARDOWN(pidfs_xattr)
43 {
44 sys_waitid(P_PID, self->child_pid, NULL, WEXITED);
45 }
46
TEST_F(pidfs_xattr,set_get_list_xattr_multiple)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
TEST_F(pidfs_xattr,set_get_list_xattr_persistent)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