static void run_tests(void) { unsigned int i; struct results saved_results; if (!tst_test->test) { saved_results = *results; tst_test->test_all(); if (getpid() != main_pid) { exit(0); } tst_reap_children(); if (results_equal(&saved_results, results)) tst_brk(TBROK, "Test haven't reported results!"); return; } for (i = 0; i < tst_test->tcnt; i++) { saved_results = *results; tst_test->test(i); if (getpid() != main_pid) { exit(0); } tst_reap_children(); if (results_equal(&saved_results, results)) tst_brk(TBROK, "Test %i haven't reported results!", i); } }
static void thp_test(void) { long prev_left; int pid; while (bst->right - bst->left > 1) { pid_t pid = SAFE_FORK(); if (!pid) { /* We set mid to left assuming exec will succeed. If * exec fails with E2BIG (and thus returns) then we * restore left and set right to mid instead. */ prev_left = bst->left; bst->mid = (bst->left + bst->right) / 2; bst->left = bst->mid; args[bst->mid] = NULL; TEST(execvp("true", args)); if (TST_ERR != E2BIG) tst_brk(TBROK | TTERRNO, "execvp(\"true\", ...)"); bst->left = prev_left; bst->right = bst->mid; exit(0); } tst_reap_children(); tst_res(TINFO, "left: %ld, right: %ld, mid: %ld", bst->left, bst->right, bst->mid); } /* We end with mid == right or mid == left where right - left = * 1. Regardless we must use left because right is only set to values * which are too large. */ pid = SAFE_FORK(); if (pid == 0) { args[bst->left] = NULL; TEST(execvp("true", args)); if (TST_ERR != E2BIG) tst_brk(TBROK | TTERRNO, "execvp(\"true\", ...)"); exit(0); } tst_reap_children(); tst_res(TPASS, "system didn't crash."); }
static void run(void) { spawn_workers(); visit_dir(root_dir); stop_workers(); tst_reap_children(); tst_res(TPASS, "Finished reading files"); }
static void verify_mempolicy(unsigned int node, int mode) { struct bitmask *bm = numa_allocate_nodemask(); unsigned int i; numa_bitmask_setbit(bm, node); TEST(set_mempolicy(mode, bm->maskp, bm->size+1)); if (TST_RET) { tst_res(TFAIL | TTERRNO, "set_mempolicy(%s) node %u", tst_numa_mode_name(mode), node); return; } tst_res(TPASS, "set_mempolicy(%s) node %u", tst_numa_mode_name(mode), node); numa_free_nodemask(bm); const char *prefix = "child: "; if (SAFE_FORK()) { prefix = "parent: "; tst_reap_children(); } tst_nodemap_reset_counters(nodes); alloc_fault_count(nodes, NULL, PAGES_ALLOCATED * page_size); tst_nodemap_print_counters(nodes); for (i = 0; i < nodes->cnt; i++) { if (nodes->map[i] == node) { if (nodes->counters[i] == PAGES_ALLOCATED) { tst_res(TPASS, "%sNode %u allocated %u", prefix, node, PAGES_ALLOCATED); } else { tst_res(TFAIL, "%sNode %u allocated %u, expected %u", prefix, node, nodes->counters[i], PAGES_ALLOCATED); } continue; } if (nodes->counters[i]) { tst_res(TFAIL, "%sNode %u allocated %u, expected 0", prefix, i, nodes->counters[i]); } } }
static void do_shmat(unsigned int n) { pid_t pid; struct test_case_t *tc = &tcases[n]; if (!tc->exp_user) { verify_shmat(tc); } else { pid = SAFE_FORK(); if (pid) { tst_reap_children(); } else { SAFE_SETUID(pw->pw_uid); verify_shmat(tc); exit(0); } } }
static void setup(void) { struct passwd *pw; pid_t pid; pw = SAFE_GETPWNAM("nobody"); nobody_uid = pw->pw_uid; pw = SAFE_GETPWNAM("bin"); bin_uid = pw->pw_uid; pid = SAFE_FORK(); if (pid == 0) { SAFE_SETREUID(nobody_uid, nobody_uid); SAFE_MKDIR(TESTDIR, 0700); exit(0); } tst_reap_children(); SAFE_SETREUID(bin_uid, bin_uid); }
void dirtyc0w_test(void) { int i, fd, pid, fail = 0; char c; /* Create file */ fd = SAFE_OPEN(FNAME, O_WRONLY|O_CREAT|O_EXCL, 0444); SAFE_WRITE(1, fd, STR, sizeof(STR)-1); SAFE_CLOSE(fd); pid = SAFE_FORK(); if (!pid) { SAFE_SETGID(nobody_gid); SAFE_SETUID(nobody_uid); SAFE_EXECLP("dirtyc0w_child", "dirtyc0w_child", NULL); } TST_CHECKPOINT_WAIT(0); for (i = 0; i < 100; i++) { usleep(10000); SAFE_FILE_SCANF(FNAME, "%c", &c); if (c != 't') { fail = 1; break; } } SAFE_KILL(pid, SIGUSR1); tst_reap_children(); SAFE_UNLINK(FNAME); if (fail) tst_res(TFAIL, "Bug reproduced!"); else tst_res(TPASS, "Bug not reproduced"); }
/* * Try to update a key, racing with removing write permission. * This may crash buggy kernels. */ static void test_update_setperm_race(void) { static const char payload[] = "payload"; key_serial_t keyid; int i; new_session_keyring(); TEST(add_key("user", "desc", payload, sizeof(payload), KEY_SPEC_SESSION_KEYRING)); if (TEST_RETURN < 0) { tst_res(TBROK | TTERRNO, "failed to add 'user' key"); return; } keyid = TEST_RETURN; if (SAFE_FORK() == 0) { uint32_t perm = KEY_POS_ALL; for (i = 0; i < 10000; i++) { perm ^= KEY_POS_WRITE; TEST(keyctl(KEYCTL_SETPERM, keyid, perm)); if (TEST_RETURN != 0) tst_brk(TBROK | TTERRNO, "setperm failed"); } exit(0); } tst_res(TINFO, "Try to update the 'user' key..."); for (i = 0; i < 10000; i++) { TEST(keyctl(KEYCTL_UPDATE, keyid, payload, sizeof(payload))); if (TEST_RETURN != 0 && TEST_ERRNO != EACCES) { tst_res(TBROK | TTERRNO, "failed to update 'user' key"); return; } } tst_reap_children(); tst_res(TPASS, "didn't crash while racing to update 'user' key"); }
static void run(unsigned int test_case) { /* Work in child process - needed to undo unshare and chroot */ if (SAFE_FORK()) { tst_reap_children(); return; } /* pivot_root requires no shared mounts exist in process namespace */ TEST(unshare(CLONE_NEWNS | CLONE_FS)); if (TST_RET == -1) tst_brk(TFAIL | TERRNO, "unshare failed"); /* * Create an initial root dir. pivot_root doesn't work if the initial root * dir is a initramfs, so use chroot to create a safe environment */ SAFE_MOUNT("none", "/", NULL, MS_REC|MS_PRIVATE, NULL); SAFE_MOUNT("none", CHROOT_DIR, "tmpfs", 0, 0); SAFE_CHROOT(CHROOT_DIR); SAFE_MKDIR(NEW_ROOT, 0777); /* * pivot_root only works if new_root is a mount point, so mount a tmpfs * unless testing for that fail mode */ if (test_cases[test_case].test_case != NEW_ROOT_ON_CURRENT_ROOT) SAFE_MOUNT("none", NEW_ROOT, "tmpfs", 0, 0); /* * Create put_old under new_root, unless testing for that specific fail * mode */ const char* actual_put_old = NULL; if (test_cases[test_case].test_case == PUT_OLD_NOT_UNDERNEATH_NEW_ROOT) { actual_put_old = PUT_OLD_BAD; SAFE_MKDIR(PUT_OLD_FS, 0777); SAFE_MOUNT("none", PUT_OLD_FS, "tmpfs", 0, 0); SAFE_MKDIR(PUT_OLD_BAD, 0777); } else { actual_put_old = PUT_OLD; if (test_cases[test_case].test_case == PUT_OLD_NOT_DIR) SAFE_CREAT(PUT_OLD, 0777); else SAFE_MKDIR(PUT_OLD, 0777); } if (test_cases[test_case].test_case == NO_CAP_SYS_ADMIN) { #ifdef HAVE_LIBCAP drop_cap_sys_admin(); #else tst_res(TCONF, "System doesn't have POSIX capabilities support"); return; #endif } TEST(syscall(__NR_pivot_root, NEW_ROOT, actual_put_old)); if (test_cases[test_case].test_case == NORMAL) { if (TST_RET) tst_res(TFAIL | TERRNO, "pivot_root failed"); else tst_res(TPASS, "pivot_root succeeded"); return; } if (TST_RET == 0) { tst_res(TFAIL, "pivot_root succeeded unexpectedly"); return; } if (errno != test_cases[test_case].expected_error) { tst_res(TFAIL | TERRNO, "pivot_root failed with wrong errno"); return; } tst_res(TPASS | TERRNO, "pivot_root failed as expectedly"); }