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