0001
0002
0003
0004
0005
0006
0007
0008 #include <errno.h>
0009 #include <linux/user_events.h>
0010 #include <stdio.h>
0011 #include <stdlib.h>
0012 #include <fcntl.h>
0013 #include <sys/ioctl.h>
0014 #include <sys/stat.h>
0015 #include <unistd.h>
0016
0017 #include "../kselftest_harness.h"
0018
0019 const char *data_file = "/sys/kernel/debug/tracing/user_events_data";
0020 const char *status_file = "/sys/kernel/debug/tracing/user_events_status";
0021 const char *enable_file = "/sys/kernel/debug/tracing/events/user_events/__test_event/enable";
0022 const char *trace_file = "/sys/kernel/debug/tracing/trace";
0023 const char *fmt_file = "/sys/kernel/debug/tracing/events/user_events/__test_event/format";
0024
0025 static int trace_bytes(void)
0026 {
0027 int fd = open(trace_file, O_RDONLY);
0028 char buf[256];
0029 int bytes = 0, got;
0030
0031 if (fd == -1)
0032 return -1;
0033
0034 while (true) {
0035 got = read(fd, buf, sizeof(buf));
0036
0037 if (got == -1)
0038 return -1;
0039
0040 if (got == 0)
0041 break;
0042
0043 bytes += got;
0044 }
0045
0046 close(fd);
0047
0048 return bytes;
0049 }
0050
0051 static int skip_until_empty_line(FILE *fp)
0052 {
0053 int c, last = 0;
0054
0055 while (true) {
0056 c = getc(fp);
0057
0058 if (c == EOF)
0059 break;
0060
0061 if (last == '\n' && c == '\n')
0062 return 0;
0063
0064 last = c;
0065 }
0066
0067 return -1;
0068 }
0069
0070 static int get_print_fmt(char *buffer, int len)
0071 {
0072 FILE *fp = fopen(fmt_file, "r");
0073 char *newline;
0074
0075 if (!fp)
0076 return -1;
0077
0078
0079 if (skip_until_empty_line(fp) < 0)
0080 goto err;
0081
0082
0083 if (skip_until_empty_line(fp) < 0)
0084 goto err;
0085
0086
0087 if (fgets(buffer, len, fp) == NULL)
0088 goto err;
0089
0090 newline = strchr(buffer, '\n');
0091
0092 if (newline)
0093 *newline = '\0';
0094
0095 fclose(fp);
0096
0097 return 0;
0098 err:
0099 fclose(fp);
0100
0101 return -1;
0102 }
0103
0104 static int clear(void)
0105 {
0106 int fd = open(data_file, O_RDWR);
0107
0108 if (fd == -1)
0109 return -1;
0110
0111 if (ioctl(fd, DIAG_IOCSDEL, "__test_event") == -1)
0112 if (errno != ENOENT)
0113 return -1;
0114
0115 close(fd);
0116
0117 return 0;
0118 }
0119
0120 static int check_print_fmt(const char *event, const char *expected)
0121 {
0122 struct user_reg reg = {0};
0123 char print_fmt[256];
0124 int ret;
0125 int fd;
0126
0127
0128 ret = clear();
0129
0130 if (ret != 0)
0131 return ret;
0132
0133 fd = open(data_file, O_RDWR);
0134
0135 if (fd == -1)
0136 return fd;
0137
0138 reg.size = sizeof(reg);
0139 reg.name_args = (__u64)event;
0140
0141
0142 ret = ioctl(fd, DIAG_IOCSREG, ®);
0143
0144 close(fd);
0145
0146 if (ret != 0)
0147 return ret;
0148
0149
0150 ret = get_print_fmt(print_fmt, sizeof(print_fmt));
0151
0152 if (ret != 0)
0153 return ret;
0154
0155 return strcmp(print_fmt, expected);
0156 }
0157
0158 FIXTURE(user) {
0159 int status_fd;
0160 int data_fd;
0161 int enable_fd;
0162 };
0163
0164 FIXTURE_SETUP(user) {
0165 self->status_fd = open(status_file, O_RDONLY);
0166 ASSERT_NE(-1, self->status_fd);
0167
0168 self->data_fd = open(data_file, O_RDWR);
0169 ASSERT_NE(-1, self->data_fd);
0170
0171 self->enable_fd = -1;
0172 }
0173
0174 FIXTURE_TEARDOWN(user) {
0175 close(self->status_fd);
0176 close(self->data_fd);
0177
0178 if (self->enable_fd != -1) {
0179 write(self->enable_fd, "0", sizeof("0"));
0180 close(self->enable_fd);
0181 }
0182
0183 ASSERT_EQ(0, clear());
0184 }
0185
0186 TEST_F(user, register_events) {
0187 struct user_reg reg = {0};
0188 int page_size = sysconf(_SC_PAGESIZE);
0189 char *status_page;
0190
0191 reg.size = sizeof(reg);
0192 reg.name_args = (__u64)"__test_event u32 field1; u32 field2";
0193
0194 status_page = mmap(NULL, page_size, PROT_READ, MAP_SHARED,
0195 self->status_fd, 0);
0196
0197
0198 ASSERT_EQ(0, ioctl(self->data_fd, DIAG_IOCSREG, ®));
0199 ASSERT_EQ(0, reg.write_index);
0200 ASSERT_NE(0, reg.status_index);
0201
0202
0203 ASSERT_EQ(0, ioctl(self->data_fd, DIAG_IOCSREG, ®));
0204 ASSERT_EQ(0, reg.write_index);
0205 ASSERT_NE(0, reg.status_index);
0206
0207
0208 self->enable_fd = open(enable_file, O_RDWR);
0209 ASSERT_NE(-1, self->enable_fd);
0210 ASSERT_NE(-1, write(self->enable_fd, "0", sizeof("0")))
0211
0212
0213 ASSERT_NE(MAP_FAILED, status_page);
0214 ASSERT_NE(NULL, status_page);
0215 ASSERT_EQ(0, status_page[reg.status_index]);
0216
0217
0218 ASSERT_NE(-1, write(self->enable_fd, "1", sizeof("1")))
0219 ASSERT_EQ(EVENT_STATUS_FTRACE, status_page[reg.status_index]);
0220
0221
0222 ASSERT_NE(-1, write(self->enable_fd, "0", sizeof("0")))
0223 ASSERT_EQ(0, status_page[reg.status_index]);
0224
0225
0226 ASSERT_EQ(-1, ioctl(self->data_fd, DIAG_IOCSDEL, "__test_event"));
0227 ASSERT_EQ(EBUSY, errno);
0228
0229
0230 close(self->data_fd);
0231 self->data_fd = open(data_file, O_RDWR);
0232 ASSERT_EQ(0, ioctl(self->data_fd, DIAG_IOCSDEL, "__test_event"));
0233
0234
0235 ASSERT_EQ(0, munmap(status_page, page_size));
0236 }
0237
0238 TEST_F(user, write_events) {
0239 struct user_reg reg = {0};
0240 struct iovec io[3];
0241 __u32 field1, field2;
0242 int before = 0, after = 0;
0243
0244 reg.size = sizeof(reg);
0245 reg.name_args = (__u64)"__test_event u32 field1; u32 field2";
0246
0247 field1 = 1;
0248 field2 = 2;
0249
0250 io[0].iov_base = ®.write_index;
0251 io[0].iov_len = sizeof(reg.write_index);
0252 io[1].iov_base = &field1;
0253 io[1].iov_len = sizeof(field1);
0254 io[2].iov_base = &field2;
0255 io[2].iov_len = sizeof(field2);
0256
0257
0258 ASSERT_EQ(0, ioctl(self->data_fd, DIAG_IOCSREG, ®));
0259 ASSERT_EQ(0, reg.write_index);
0260 ASSERT_NE(0, reg.status_index);
0261
0262
0263 io[0].iov_base = &field2;
0264 io[0].iov_len = sizeof(field2);
0265 ASSERT_EQ(-1, writev(self->data_fd, (const struct iovec *)io, 3));
0266 ASSERT_EQ(ENOENT, errno);
0267 io[0].iov_base = ®.write_index;
0268 io[0].iov_len = sizeof(reg.write_index);
0269
0270
0271 self->enable_fd = open(enable_file, O_RDWR);
0272 ASSERT_NE(-1, write(self->enable_fd, "1", sizeof("1")))
0273
0274
0275 before = trace_bytes();
0276 ASSERT_NE(-1, writev(self->data_fd, (const struct iovec *)io, 3));
0277 after = trace_bytes();
0278 ASSERT_GT(after, before);
0279 }
0280
0281 TEST_F(user, write_fault) {
0282 struct user_reg reg = {0};
0283 struct iovec io[2];
0284 int l = sizeof(__u64);
0285 void *anon;
0286
0287 reg.size = sizeof(reg);
0288 reg.name_args = (__u64)"__test_event u64 anon";
0289
0290 anon = mmap(NULL, l, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
0291 ASSERT_NE(MAP_FAILED, anon);
0292
0293 io[0].iov_base = ®.write_index;
0294 io[0].iov_len = sizeof(reg.write_index);
0295 io[1].iov_base = anon;
0296 io[1].iov_len = l;
0297
0298
0299 ASSERT_EQ(0, ioctl(self->data_fd, DIAG_IOCSREG, ®));
0300 ASSERT_EQ(0, reg.write_index);
0301 ASSERT_NE(0, reg.status_index);
0302
0303
0304 ASSERT_NE(-1, writev(self->data_fd, (const struct iovec *)io, 2));
0305
0306
0307 ASSERT_EQ(0, madvise(anon, l, MADV_DONTNEED));
0308 ASSERT_NE(-1, writev(self->data_fd, (const struct iovec *)io, 2));
0309 ASSERT_EQ(0, munmap(anon, l));
0310 }
0311
0312 TEST_F(user, write_validator) {
0313 struct user_reg reg = {0};
0314 struct iovec io[3];
0315 int loc, bytes;
0316 char data[8];
0317 int before = 0, after = 0;
0318
0319 reg.size = sizeof(reg);
0320 reg.name_args = (__u64)"__test_event __rel_loc char[] data";
0321
0322
0323 ASSERT_EQ(0, ioctl(self->data_fd, DIAG_IOCSREG, ®));
0324 ASSERT_EQ(0, reg.write_index);
0325 ASSERT_NE(0, reg.status_index);
0326
0327 io[0].iov_base = ®.write_index;
0328 io[0].iov_len = sizeof(reg.write_index);
0329 io[1].iov_base = &loc;
0330 io[1].iov_len = sizeof(loc);
0331 io[2].iov_base = data;
0332 bytes = snprintf(data, sizeof(data), "Test") + 1;
0333 io[2].iov_len = bytes;
0334
0335
0336 ASSERT_EQ(-1, writev(self->data_fd, (const struct iovec *)io, 1));
0337 ASSERT_EQ(EINVAL, errno);
0338
0339
0340 self->enable_fd = open(enable_file, O_RDWR);
0341 ASSERT_NE(-1, write(self->enable_fd, "1", sizeof("1")))
0342
0343
0344 before = trace_bytes();
0345 loc = DYN_LOC(0, bytes);
0346 ASSERT_NE(-1, writev(self->data_fd, (const struct iovec *)io, 3));
0347 after = trace_bytes();
0348 ASSERT_GT(after, before);
0349
0350
0351 loc = DYN_LOC(1024, bytes);
0352 ASSERT_EQ(-1, writev(self->data_fd, (const struct iovec *)io, 3));
0353 ASSERT_EQ(EFAULT, errno);
0354
0355
0356 loc = DYN_LOC(1, bytes);
0357 ASSERT_EQ(-1, writev(self->data_fd, (const struct iovec *)io, 3));
0358 ASSERT_EQ(EFAULT, errno);
0359
0360
0361 loc = DYN_LOC(0, bytes + 1024);
0362 ASSERT_EQ(-1, writev(self->data_fd, (const struct iovec *)io, 3));
0363 ASSERT_EQ(EFAULT, errno);
0364
0365
0366 loc = DYN_LOC(0, bytes + 1);
0367 ASSERT_EQ(-1, writev(self->data_fd, (const struct iovec *)io, 3));
0368 ASSERT_EQ(EFAULT, errno);
0369
0370
0371 memset(data, 'A', sizeof(data));
0372 loc = DYN_LOC(0, bytes);
0373 ASSERT_EQ(-1, writev(self->data_fd, (const struct iovec *)io, 3));
0374 ASSERT_EQ(EFAULT, errno);
0375 }
0376
0377 TEST_F(user, print_fmt) {
0378 int ret;
0379
0380 ret = check_print_fmt("__test_event __rel_loc char[] data",
0381 "print fmt: \"data=%s\", __get_rel_str(data)");
0382 ASSERT_EQ(0, ret);
0383
0384 ret = check_print_fmt("__test_event __data_loc char[] data",
0385 "print fmt: \"data=%s\", __get_str(data)");
0386 ASSERT_EQ(0, ret);
0387
0388 ret = check_print_fmt("__test_event s64 data",
0389 "print fmt: \"data=%lld\", REC->data");
0390 ASSERT_EQ(0, ret);
0391
0392 ret = check_print_fmt("__test_event u64 data",
0393 "print fmt: \"data=%llu\", REC->data");
0394 ASSERT_EQ(0, ret);
0395
0396 ret = check_print_fmt("__test_event s32 data",
0397 "print fmt: \"data=%d\", REC->data");
0398 ASSERT_EQ(0, ret);
0399
0400 ret = check_print_fmt("__test_event u32 data",
0401 "print fmt: \"data=%u\", REC->data");
0402 ASSERT_EQ(0, ret);
0403
0404 ret = check_print_fmt("__test_event int data",
0405 "print fmt: \"data=%d\", REC->data");
0406 ASSERT_EQ(0, ret);
0407
0408 ret = check_print_fmt("__test_event unsigned int data",
0409 "print fmt: \"data=%u\", REC->data");
0410 ASSERT_EQ(0, ret);
0411
0412 ret = check_print_fmt("__test_event s16 data",
0413 "print fmt: \"data=%d\", REC->data");
0414 ASSERT_EQ(0, ret);
0415
0416 ret = check_print_fmt("__test_event u16 data",
0417 "print fmt: \"data=%u\", REC->data");
0418 ASSERT_EQ(0, ret);
0419
0420 ret = check_print_fmt("__test_event short data",
0421 "print fmt: \"data=%d\", REC->data");
0422 ASSERT_EQ(0, ret);
0423
0424 ret = check_print_fmt("__test_event unsigned short data",
0425 "print fmt: \"data=%u\", REC->data");
0426 ASSERT_EQ(0, ret);
0427
0428 ret = check_print_fmt("__test_event s8 data",
0429 "print fmt: \"data=%d\", REC->data");
0430 ASSERT_EQ(0, ret);
0431
0432 ret = check_print_fmt("__test_event u8 data",
0433 "print fmt: \"data=%u\", REC->data");
0434 ASSERT_EQ(0, ret);
0435
0436 ret = check_print_fmt("__test_event char data",
0437 "print fmt: \"data=%d\", REC->data");
0438 ASSERT_EQ(0, ret);
0439
0440 ret = check_print_fmt("__test_event unsigned char data",
0441 "print fmt: \"data=%u\", REC->data");
0442 ASSERT_EQ(0, ret);
0443
0444 ret = check_print_fmt("__test_event char[4] data",
0445 "print fmt: \"data=%s\", REC->data");
0446 ASSERT_EQ(0, ret);
0447 }
0448
0449 int main(int argc, char **argv)
0450 {
0451 return test_harness_run(argc, argv);
0452 }