1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * User Events ABI Test Program 4 * 5 * Copyright (c) 2022 Beau Belgrave <beaub@linux.microsoft.com> 6 */ 7 8 #define _GNU_SOURCE 9 #include <sched.h> 10 11 #include <errno.h> 12 #include <linux/user_events.h> 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <fcntl.h> 16 #include <sys/ioctl.h> 17 #include <sys/stat.h> 18 #include <unistd.h> 19 #include <asm/unistd.h> 20 21 #include "../kselftest_harness.h" 22 #include "user_events_selftests.h" 23 24 const char *data_file = "/sys/kernel/tracing/user_events_data"; 25 const char *enable_file = "/sys/kernel/tracing/events/user_events/__abi_event/enable"; 26 27 static bool event_exists(void) 28 { 29 int fd = open(enable_file, O_RDWR); 30 31 if (fd < 0) 32 return false; 33 34 close(fd); 35 36 return true; 37 } 38 39 static int change_event(bool enable) 40 { 41 int fd = open(enable_file, O_RDWR); 42 int ret; 43 44 if (fd < 0) 45 return -1; 46 47 if (enable) 48 ret = write(fd, "1", 1); 49 else 50 ret = write(fd, "0", 1); 51 52 close(fd); 53 54 if (ret == 1) 55 ret = 0; 56 else 57 ret = -1; 58 59 return ret; 60 } 61 62 static int event_delete(void) 63 { 64 int fd = open(data_file, O_RDWR); 65 int ret; 66 67 if (fd < 0) 68 return -1; 69 70 ret = ioctl(fd, DIAG_IOCSDEL, "__abi_event"); 71 72 close(fd); 73 74 return ret; 75 } 76 77 static int reg_enable_flags(void *enable, int size, int bit, int flags) 78 { 79 struct user_reg reg = {0}; 80 int fd = open(data_file, O_RDWR); 81 int ret; 82 83 if (fd < 0) 84 return -1; 85 86 reg.size = sizeof(reg); 87 reg.name_args = (__u64)"__abi_event"; 88 reg.flags = flags; 89 reg.enable_bit = bit; 90 reg.enable_addr = (__u64)enable; 91 reg.enable_size = size; 92 93 ret = ioctl(fd, DIAG_IOCSREG, ®); 94 95 close(fd); 96 97 return ret; 98 } 99 100 static int reg_enable(void *enable, int size, int bit) 101 { 102 return reg_enable_flags(enable, size, bit, 0); 103 } 104 105 static int reg_disable(void *enable, int bit) 106 { 107 struct user_unreg reg = {0}; 108 int fd = open(data_file, O_RDWR); 109 int ret; 110 111 if (fd < 0) 112 return -1; 113 114 reg.size = sizeof(reg); 115 reg.disable_bit = bit; 116 reg.disable_addr = (__u64)enable; 117 118 ret = ioctl(fd, DIAG_IOCSUNREG, ®); 119 120 close(fd); 121 122 return ret; 123 } 124 125 FIXTURE(user) { 126 int check; 127 long check_long; 128 bool umount; 129 }; 130 131 FIXTURE_SETUP(user) { 132 USER_EVENT_FIXTURE_SETUP(return, self->umount); 133 134 change_event(false); 135 self->check = 0; 136 self->check_long = 0; 137 } 138 139 FIXTURE_TEARDOWN(user) { 140 USER_EVENT_FIXTURE_TEARDOWN(self->umount); 141 } 142 143 TEST_F(user, enablement) { 144 /* Changes should be reflected immediately */ 145 ASSERT_EQ(0, self->check); 146 ASSERT_EQ(0, reg_enable(&self->check, sizeof(int), 0)); 147 ASSERT_EQ(0, change_event(true)); 148 ASSERT_EQ(1, self->check); 149 ASSERT_EQ(0, change_event(false)); 150 ASSERT_EQ(0, self->check); 151 152 /* Ensure kernel clears bit after disable */ 153 ASSERT_EQ(0, change_event(true)); 154 ASSERT_EQ(1, self->check); 155 ASSERT_EQ(0, reg_disable(&self->check, 0)); 156 ASSERT_EQ(0, self->check); 157 158 /* Ensure doesn't change after unreg */ 159 ASSERT_EQ(0, change_event(true)); 160 ASSERT_EQ(0, self->check); 161 ASSERT_EQ(0, change_event(false)); 162 } 163 164 TEST_F(user, flags) { 165 /* USER_EVENT_REG_PERSIST is allowed */ 166 ASSERT_EQ(0, reg_enable_flags(&self->check, sizeof(int), 0, 167 USER_EVENT_REG_PERSIST)); 168 ASSERT_EQ(0, reg_disable(&self->check, 0)); 169 170 /* Ensure it exists after close and disable */ 171 ASSERT_TRUE(event_exists()); 172 173 /* Ensure we can delete it */ 174 ASSERT_EQ(0, event_delete()); 175 176 /* USER_EVENT_REG_MAX or above is not allowed */ 177 ASSERT_EQ(-1, reg_enable_flags(&self->check, sizeof(int), 0, 178 USER_EVENT_REG_MAX)); 179 180 /* Ensure it does not exist after invalid flags */ 181 ASSERT_FALSE(event_exists()); 182 } 183 184 TEST_F(user, bit_sizes) { 185 /* Allow 0-31 bits for 32-bit */ 186 ASSERT_EQ(0, reg_enable(&self->check, sizeof(int), 0)); 187 ASSERT_EQ(0, reg_enable(&self->check, sizeof(int), 31)); 188 ASSERT_NE(0, reg_enable(&self->check, sizeof(int), 32)); 189 ASSERT_EQ(0, reg_disable(&self->check, 0)); 190 ASSERT_EQ(0, reg_disable(&self->check, 31)); 191 192 #if BITS_PER_LONG == 8 193 /* Allow 0-64 bits for 64-bit */ 194 ASSERT_EQ(0, reg_enable(&self->check_long, sizeof(long), 63)); 195 ASSERT_NE(0, reg_enable(&self->check_long, sizeof(long), 64)); 196 ASSERT_EQ(0, reg_disable(&self->check_long, 63)); 197 #endif 198 199 /* Disallowed sizes (everything beside 4 and 8) */ 200 ASSERT_NE(0, reg_enable(&self->check, 1, 0)); 201 ASSERT_NE(0, reg_enable(&self->check, 2, 0)); 202 ASSERT_NE(0, reg_enable(&self->check, 3, 0)); 203 ASSERT_NE(0, reg_enable(&self->check, 5, 0)); 204 ASSERT_NE(0, reg_enable(&self->check, 6, 0)); 205 ASSERT_NE(0, reg_enable(&self->check, 7, 0)); 206 ASSERT_NE(0, reg_enable(&self->check, 9, 0)); 207 ASSERT_NE(0, reg_enable(&self->check, 128, 0)); 208 } 209 210 TEST_F(user, forks) { 211 int i; 212 213 /* Ensure COW pages get updated after fork */ 214 ASSERT_EQ(0, reg_enable(&self->check, sizeof(int), 0)); 215 ASSERT_EQ(0, self->check); 216 217 if (fork() == 0) { 218 /* Force COW */ 219 self->check = 0; 220 221 /* Up to 1 sec for enablement */ 222 for (i = 0; i < 10; ++i) { 223 usleep(100000); 224 225 if (self->check) 226 exit(0); 227 } 228 229 exit(1); 230 } 231 232 /* Allow generous time for COW, then enable */ 233 usleep(100000); 234 ASSERT_EQ(0, change_event(true)); 235 236 ASSERT_NE(-1, wait(&i)); 237 ASSERT_EQ(0, WEXITSTATUS(i)); 238 239 /* Ensure child doesn't disable parent */ 240 if (fork() == 0) 241 exit(reg_disable(&self->check, 0)); 242 243 ASSERT_NE(-1, wait(&i)); 244 ASSERT_EQ(0, WEXITSTATUS(i)); 245 ASSERT_EQ(1, self->check); 246 ASSERT_EQ(0, change_event(false)); 247 ASSERT_EQ(0, self->check); 248 } 249 250 /* Waits up to 1 sec for enablement */ 251 static int clone_check(void *check) 252 { 253 int i; 254 255 for (i = 0; i < 10; ++i) { 256 usleep(100000); 257 258 if (*(int *)check) 259 return 0; 260 } 261 262 return 1; 263 } 264 265 TEST_F(user, clones) { 266 int i, stack_size = 4096; 267 void *stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, 268 MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, 269 -1, 0); 270 271 ASSERT_NE(MAP_FAILED, stack); 272 ASSERT_EQ(0, reg_enable(&self->check, sizeof(int), 0)); 273 ASSERT_EQ(0, self->check); 274 275 /* Shared VM should see enablements */ 276 ASSERT_NE(-1, clone(&clone_check, stack + stack_size, 277 CLONE_VM | SIGCHLD, &self->check)); 278 279 ASSERT_EQ(0, change_event(true)); 280 ASSERT_NE(-1, wait(&i)); 281 ASSERT_EQ(0, WEXITSTATUS(i)); 282 munmap(stack, stack_size); 283 ASSERT_EQ(0, change_event(false)); 284 } 285 286 int main(int argc, char **argv) 287 { 288 return test_harness_run(argc, argv); 289 } 290