Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

user_events: Add self-test for validator boundaries

Tests to ensure validator boundary cases are working correctly within
close and far bounds. Ensures __data_loc and __rel_loc strings are
null terminated and within range. Ensures min size checks work as
expected.

Link: https://lkml.kernel.org/r/20220118204326.2169-11-beaub@linux.microsoft.com

Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Beau Belgrave <beaub@linux.microsoft.com>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>

authored by

Beau Belgrave and committed by
Steven Rostedt (Google)
7640e770 3a616389

+65
+65
tools/testing/selftests/user_events/ftrace_test.c
··· 309 309 ASSERT_EQ(0, munmap(anon, l)); 310 310 } 311 311 312 + TEST_F(user, write_validator) { 313 + struct user_reg reg = {0}; 314 + struct iovec io[3]; 315 + int loc, bytes; 316 + char data[8]; 317 + int before = 0, after = 0; 318 + 319 + reg.size = sizeof(reg); 320 + reg.name_args = (__u64)"__test_event __rel_loc char[] data"; 321 + 322 + /* Register should work */ 323 + ASSERT_EQ(0, ioctl(self->data_fd, DIAG_IOCSREG, &reg)); 324 + ASSERT_EQ(0, reg.write_index); 325 + ASSERT_NE(0, reg.status_index); 326 + 327 + io[0].iov_base = &reg.write_index; 328 + io[0].iov_len = sizeof(reg.write_index); 329 + io[1].iov_base = &loc; 330 + io[1].iov_len = sizeof(loc); 331 + io[2].iov_base = data; 332 + bytes = snprintf(data, sizeof(data), "Test") + 1; 333 + io[2].iov_len = bytes; 334 + 335 + /* Undersized write should fail */ 336 + ASSERT_EQ(-1, writev(self->data_fd, (const struct iovec *)io, 1)); 337 + ASSERT_EQ(EINVAL, errno); 338 + 339 + /* Enable event */ 340 + self->enable_fd = open(enable_file, O_RDWR); 341 + ASSERT_NE(-1, write(self->enable_fd, "1", sizeof("1"))) 342 + 343 + /* Full in-bounds write should work */ 344 + before = trace_bytes(); 345 + loc = DYN_LOC(0, bytes); 346 + ASSERT_NE(-1, writev(self->data_fd, (const struct iovec *)io, 3)); 347 + after = trace_bytes(); 348 + ASSERT_GT(after, before); 349 + 350 + /* Out of bounds write should fault (offset way out) */ 351 + loc = DYN_LOC(1024, bytes); 352 + ASSERT_EQ(-1, writev(self->data_fd, (const struct iovec *)io, 3)); 353 + ASSERT_EQ(EFAULT, errno); 354 + 355 + /* Out of bounds write should fault (offset 1 byte out) */ 356 + loc = DYN_LOC(1, bytes); 357 + ASSERT_EQ(-1, writev(self->data_fd, (const struct iovec *)io, 3)); 358 + ASSERT_EQ(EFAULT, errno); 359 + 360 + /* Out of bounds write should fault (size way out) */ 361 + loc = DYN_LOC(0, bytes + 1024); 362 + ASSERT_EQ(-1, writev(self->data_fd, (const struct iovec *)io, 3)); 363 + ASSERT_EQ(EFAULT, errno); 364 + 365 + /* Out of bounds write should fault (size 1 byte out) */ 366 + loc = DYN_LOC(0, bytes + 1); 367 + ASSERT_EQ(-1, writev(self->data_fd, (const struct iovec *)io, 3)); 368 + ASSERT_EQ(EFAULT, errno); 369 + 370 + /* Non-Null should fault */ 371 + memset(data, 'A', sizeof(data)); 372 + loc = DYN_LOC(0, bytes); 373 + ASSERT_EQ(-1, writev(self->data_fd, (const struct iovec *)io, 3)); 374 + ASSERT_EQ(EFAULT, errno); 375 + } 376 + 312 377 TEST_F(user, print_fmt) { 313 378 int ret; 314 379