Пример #1
0
static void do_test(void)
{
	int i;

	if (!SAFE_FORK()) {
		SAFE_FILE_PRINTF(PATH_AUTOGROUP, "%d", 1);
		SAFE_SETSID();

		if (SAFE_FORK())
			pause();

		SAFE_KILL(getppid(), SIGKILL);
		usleep(1000);

		// The child has gone, the grandchild runs with kref == 1
		SAFE_FILE_PRINTF(PATH_AUTOGROUP, "%d", 0);
		SAFE_SETSID();

		// runs with the freed ag/tg
		for (i = 0; i < LOOPS; i++)
			usleep(10);

		TST_CHECKPOINT_WAKE(0);

		exit(0);
	}

	SAFE_WAIT(NULL); // destroy the child's ag/tg

	TST_CHECKPOINT_WAIT(0);

	tst_res(TPASS, "Bug not reproduced");
}
Пример #2
0
static void do_child_1(void)
{
	pid_t pid;
	int i;

	for (i = 0; i < MAXKIDS; i++) {
		pid = SAFE_FORK();
		if (pid == 0) {
			if (i == 0 || i == 1)
				do_exit(0);

			if (i == 2 || i == 3)
				do_compute();

			if (i == 4 || i == 5)
				do_fork();

			if (i == 6 || i == 7)
				do_sleep();
		}

		fork_kid_pid[i] = pid;
	}

	TST_CHECKPOINT_WAKE2(0, MAXKIDS);

	if (TST_TRACE(reap_children(0, 0, fork_kid_pid, MAXKIDS)))
		return;

	tst_res(TPASS, "Test PASSED");
}
Пример #3
0
static void do_child_1(void)
{
	pid_t pid, group;
	int i;

	group = SAFE_GETPGID(0);

	for (i = 0; i < MAXKIDS; i++) {
		if (i == (MAXKIDS / 2))
			SAFE_SETPGID(0, 0);

		pid = SAFE_FORK();
		if (pid == 0)
			do_exit(0);

		fork_kid_pid[i] = pid;
	}

	TST_CHECKPOINT_WAKE2(0, MAXKIDS);

	if (reap_children(0, 0, fork_kid_pid + (MAXKIDS / 2), MAXKIDS / 2))
		return;

	/* Make sure can pickup children in a diff. process group */
	if (reap_children(-group, 0, fork_kid_pid, MAXKIDS / 2))
		return;

	tst_res(TPASS, "Test PASSED");
}
Пример #4
0
static void run(void)
{
	pid_t pid;
	int status;

retry:
	pid = SAFE_FORK();

	if (!pid) {
		setup_cgroup_paths(getpid());
		child();
	}

	setup_cgroup_paths(pid);
	SAFE_WAIT(&status);
	cleanup();

	/*
	 * Rarely cgroup OOM kills both children not only the one that allocates
	 * memory in loop, hence we retry here if that happens.
	 */
	if (WIFSIGNALED(status)) {
		tst_res(TINFO, "Both children killed, retrying...");
		goto retry;
	}

	if (WIFEXITED(status) && WEXITSTATUS(status) == TCONF)
		tst_brk(TCONF, "MADV_FREE is not supported");

	if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
		tst_brk(TBROK, "Child %s", tst_strstatus(status));
}
Пример #5
0
Файл: creat07.c Проект: 1587/ltp
static void verify_creat(void)
{
	pid_t pid;

	pid = SAFE_FORK();
	if (pid == 0) {
		char *av[] = {TEST_APP, NULL};
		(void)execve(TEST_APP, av, tst_ipc_envp);
		perror("execve failed");
		exit(1);
	}

	TST_CHECKPOINT_WAIT(0);

	TEST(creat(TEST_APP, O_WRONLY));

	if (TEST_RETURN != -1) {
		tst_res(TFAIL, "creat() succeeded unexpectedly");
		return;
	}

	if (TEST_ERRNO == ETXTBSY)
		tst_res(TPASS, "creat() received EXTBSY");
	else
		tst_res(TFAIL | TTERRNO, "creat() failed unexpectedly");

	SAFE_KILL(pid, SIGKILL);
	SAFE_WAITPID(pid, NULL, 0);
}
Пример #6
0
Файл: thp01.c Проект: kraj/ltp
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.");
}
Пример #7
0
static void verify_setuid(void)
{
	pid_t pid;

	pid = SAFE_FORK();
	if (!pid)
		dosetuid();
	else
		dosetuid();
}
Пример #8
0
static void verify_execve(void)
{
	int i;

	for (i = 0; i < nchild; i++) {
		if (SAFE_FORK() == 0)
			do_child();
	}

	TST_CHECKPOINT_WAKE2(0, nchild);
}
Пример #9
0
static void mem_test(void)
{
	pid_t pid;
	int i = 0, pid_cntr = 0;
	unsigned long long alloc_bytes = alloc_maxbytes;
	const char *write_msg = "";

	if (dowrite)
		write_msg = "(and written to) ";

	/* to make mtest01 support -i N */
	children_done = 0;

	do {
		pid = SAFE_FORK();
		if (pid == 0) {
			alloc_bytes = MIN(ALLOC_THRESHOLD, alloc_bytes);
			child_loop_alloc(alloc_bytes);
		}

		pid_list[pid_cntr++] = pid;

		if (alloc_bytes <= ALLOC_THRESHOLD)
			break;

		alloc_bytes -= ALLOC_THRESHOLD;
	} while (pid_cntr < max_pids);

	/* wait in the loop for all children finish allocating */
	while (children_done < pid_cntr) {
		if (tst_timeout_remaining() < STOP_THRESHOLD) {
			tst_res(TWARN,
				"the remaininig time is not enough for testing");

			break;
		}

		usleep(100000);
	}

	if (children_done < pid_cntr) {
		tst_res(TFAIL, "kbytes allocated %sless than expected %llu",
				write_msg, alloc_maxbytes / 1024);
	} else {
		tst_res(TPASS, "%llu kbytes allocated %s",
				alloc_maxbytes / 1024, write_msg);
	}

	for (i = 0; i < pid_cntr; i++) {
		TST_PROCESS_STATE_WAIT(pid_list[i], 'T');
		kill(pid_list[i], SIGCONT);
	}
}
Пример #10
0
static void verify_execveat(unsigned int i)
{
	struct tcase *tc = &tcases[i];
	char *argv[2] = {TEST_APP, NULL};
	pid_t pid;

	pid = SAFE_FORK();
	if (pid == 0) {
		TEST(execveat(*tc->fd, tc->pathname, argv, environ, tc->flag));
		tst_res(TFAIL | TERRNO, "execveat() returns unexpected errno");
	}
}
Пример #11
0
Файл: test05.c Проект: 1587/ltp
static void do_test(void)
{
	pid_t pid = SAFE_FORK();

	switch (pid) {
	case 0:
		tst_res(TPASS, "Child (%i) reports", getpid());
	break;
	default:
		tst_res(TPASS, "Parent (%i) reports", getpid());
	break;
	}
}
Пример #12
0
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]);
		}
	}
}
Пример #13
0
static void verify_access(unsigned int n)
{
	struct tcase *tc = tcases + n;
	pid_t pid;

	access_test(tc, "root");

	pid = SAFE_FORK();
	if (pid) {
		SAFE_WAITPID(pid, NULL, 0);
	} else {
		SAFE_SETUID(uid);
		access_test(tc, "nobody");
	}
}
Пример #14
0
static void test_hugeshmctl(void)
{
	pid_t pid;
	int status;

	switch (pid = SAFE_FORK()) {
	case 0:
		/* set the user ID of the child to the non root user */
		SAFE_SETUID(ltp_uid);
		do_child();
		exit(0);
	default:
		SAFE_WAITPID(pid, &status, 0);
	}
}
Пример #15
0
Файл: shmat01.c Проект: kraj/ltp
static void verify_shmat(unsigned int n)
{
	int *addr;
	pid_t pid;
	int status;
	struct shmid_ds buf;

	struct test_case_t *tc = &tcases[n];

	addr = shmat(shm_id, *tc->shmaddr, tc->flag);
	if (addr == (void *)-1) {
		tst_res(TFAIL | TERRNO, "shmat() failed");
		return;
	}

	SAFE_SHMCTL(shm_id, IPC_STAT, &buf);

	if (buf.shm_nattch != 1) {
		tst_res(TFAIL, "number of attaches was incorrect");
		goto end;
	}

	if (buf.shm_segsz != INT_SIZE) {
		tst_res(TFAIL, "segment size was incorrect");
		goto end;
	}

	if (expected_addr(*tc->shmaddr, addr) != addr) {
		tst_res(TFAIL,
			"shared memory address %p is not correct, expected %p",
			addr, expected_addr(*tc->shmaddr, addr));
		goto end;
	}

	pid = SAFE_FORK();
	if (!pid)
		do_child(addr, tc->exp_status == SIGSEGV);
	else
		SAFE_WAITPID(pid, &status, 0);

	if (expected_status(status, tc->exp_status))
		tst_res(TFAIL, "shmat() failed to attach %s", tc->desp);
	else
		tst_res(TPASS, "shmat() succeeded to attach %s", tc->desp);

end:
	SAFE_SHMDT(addr);
}
Пример #16
0
static void test_swapping(void)
{
#if __WORDSIZE == 32
	tst_brk(TCONF, "test is not designed for 32-bit system.");
#endif

	init_meminfo();

	switch (pid = SAFE_FORK()) {
		case 0:
			do_alloc();
			exit(0);
		default:
			check_swapping();
	}
}
Пример #17
0
pid_t create_sig_proc(int sig, int count, unsigned int usec)
{
	pid_t pid, cpid;

	pid = getpid();
	cpid = SAFE_FORK();

	if (cpid == 0) {
		while (count-- > 0) {
			usleep(usec);
			if (kill(pid, sig) == -1)
				break;
		}
		exit(0);
	}

	return cpid;
}
Пример #18
0
static void do_fork(void)
{
	pid_t fork_pid;
	int i;

	TST_CHECKPOINT_WAIT(0);

	for (i = 0; i < 50; i++) {
		fork_pid = SAFE_FORK();
		if (fork_pid == 0)
			exit(3);

		if (TST_TRACE(reap_children(fork_pid, 0, &fork_pid, 1)))
			break;
	}

	exit(3);
}
Пример #19
0
Файл: shmat02.c Проект: kraj/ltp
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);
		}
	}
}
Пример #20
0
static void verify_execve(void)
{
	pid_t pid;
	char *argv[2] = {TEST_APP, NULL};

	pid = SAFE_FORK();
	if (pid == 0)
		do_child();

	TST_CHECKPOINT_WAIT(0);

	TEST(execve(TEST_APP, argv, environ));

	if (TST_ERR != ETXTBSY)
		tst_res(TFAIL | TTERRNO, "execve succeeded, expected failure");
	else
		tst_res(TPASS | TTERRNO, "execve failed as expected");

	TST_CHECKPOINT_WAKE(0);
}
Пример #21
0
static void verify_inotify(void)
{
	int inotify_fd, fd;
	pid_t pid;
	int i, tests;

	pid = SAFE_FORK();
	if (pid == 0) {
		while (1) {
			for (i = 0; i < FILES; i++) {
				fd = SAFE_OPEN(names[i], O_CREAT | O_RDWR, 0600);
				SAFE_CLOSE(fd);
			}
			for (i = 0; i < FILES; i++)
				SAFE_UNLINK(names[i]);
		}
	}

	for (tests = 0; tests < TEARDOWNS; tests++) {
		inotify_fd = myinotify_init1(O_NONBLOCK);
		if (inotify_fd < 0)
			tst_brk(TBROK | TERRNO, "inotify_init failed");

		for (i = 0; i < FILES; i++) {
			/*
			 * Both failure and success are fine since
			 * files are being deleted in parallel - this
			 * is what provokes the race we want to test
			 * for...
			 */
			myinotify_add_watch(inotify_fd, names[i], IN_MODIFY);
		}
		SAFE_CLOSE(inotify_fd);
	}
	/* We survived for given time - test succeeded */
	tst_res(TPASS, "kernel survived inotify beating");

	/* Kill the child creating / deleting files and wait for it */
	SAFE_KILL(pid, SIGKILL);
	SAFE_WAIT(NULL);
}
Пример #22
0
Файл: mkdir04.c Проект: kraj/ltp
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);
}
Пример #23
0
/*
 * 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");
}
Пример #24
0
Файл: mem.c Проект: sathnaga/ltp
/*
 * oom - allocates memory according to specified testcase and checks
 *       desired outcome (e.g. child killed, operation failed with ENOMEM)
 * @testcase: selects how child allocates memory
 *            valid choices are: NORMAL, MLOCK and KSM
 * @lite: if non-zero, child makes only single TESTMEM+MB allocation
 *        if zero, child keeps allocating memory until it gets killed
 *        or some operation fails
 * @retcode: expected return code of child process
 *           if matches child ret code, this function reports PASS,
 *           otherwise it reports FAIL
 * @allow_sigkill: if zero and child is killed, this function reports FAIL
 *                 if non-zero, then if child is killed by SIGKILL
 *                 it is considered as PASS
 */
void oom(int testcase, int lite, int retcode, int allow_sigkill)
{
	pid_t pid;
	int status, threads;

	switch (pid = SAFE_FORK()) {
	case 0:
		threads = MAX(1, tst_ncpus() - 1);
		child_alloc(testcase, lite, threads);
	default:
		break;
	}

	tst_res(TINFO, "expected victim is %d.", pid);
	SAFE_WAITPID(-1, &status, 0);

	if (WIFSIGNALED(status)) {
		if (allow_sigkill && WTERMSIG(status) == SIGKILL) {
			tst_res(TPASS, "victim signalled: (%d) %s",
				SIGKILL,
				tst_strsig(SIGKILL));
		} else {
			tst_res(TFAIL, "victim signalled: (%d) %s",
				WTERMSIG(status),
				tst_strsig(WTERMSIG(status)));
		}
	} else if (WIFEXITED(status)) {
		if (WEXITSTATUS(status) == retcode) {
			tst_res(TPASS, "victim retcode: (%d) %s",
				retcode, strerror(retcode));
		} else {
			tst_res(TFAIL, "victim unexpectedly ended with "
				"retcode: %d, expected: %d",
				WEXITSTATUS(status), retcode);
		}
	} else {
		tst_res(TFAIL, "victim unexpectedly ended");
	}
}
Пример #25
0
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");
}
Пример #26
0
Файл: wait401.c Проект: kraj/ltp
static void run(void)
{
	pid_t pid;
	int status = 1;
	struct rusage rusage;

	pid = SAFE_FORK();
	if (!pid) {
		TST_PROCESS_STATE_WAIT(getppid(), 'S');
		exit(0);
	}

	TEST(wait4(pid, &status, 0, &rusage));
	if (TST_RET == -1) {
		tst_res(TFAIL | TERRNO, "wait4() failed");
		return;
	}

	if (TST_RET != pid) {
		tst_res(TFAIL, "waitpid() returned wrong pid %li, expected %i",
			TST_RET, pid);
	} else {
		tst_res(TPASS, "waitpid() returned correct pid %i", pid);
	}

	if (!WIFEXITED(status)) {
		tst_res(TFAIL, "WIFEXITED() not set in status (%s)",
		        tst_strstatus(status));
		return;
	}

	tst_res(TPASS, "WIFEXITED() is set in status");

	if (WEXITSTATUS(status))
		tst_res(TFAIL, "WEXITSTATUS() != 0 but %i", WEXITSTATUS(status));
	else
		tst_res(TPASS, "WEXITSTATUS() == 0");

}
Пример #27
0
static int worker_run(struct worker *self)
{
	char buf[BUFFER_SIZE];
	struct sigaction term_sa = {
		.sa_handler = SIG_IGN,
		.sa_flags = 0,
	};
	struct queue *q = self->q;

	sigaction(SIGTTIN, &term_sa, NULL);

	while (1) {
		if (!queue_pop(q, buf))
			break;

		read_test(buf);
	}

	queue_destroy(q, 1);
	tst_flush();
	return 0;
}

static void spawn_workers(void)
{
	int i;
	struct worker *wa = workers;

	bzero(workers, worker_count * sizeof(*workers));

	for (i = 0; i < worker_count; i++) {
		wa[i].q = queue_init();
		wa[i].pid = SAFE_FORK();
		if (!wa[i].pid)
			exit(worker_run(wa + i));
	}
}
Пример #28
0
static void do_child_1(void)
{
	pid_t pid, group;
	int i;
	int status;

	group = SAFE_GETPGID(0);

	for (i = 0; i < MAXKIDS; i++) {
		if (i == (MAXKIDS / 2))
			SAFE_SETPGID(0, 0);

		pid = SAFE_FORK();
		if (pid == 0)
			do_exit(0);

		fork_kid_pid[i] = pid;
	}

	if (TST_TRACE(waitpid_ret_test(0, &status, WNOHANG, 0, 0)))
		return;

	if (TST_TRACE(waitpid_ret_test(-group, &status, WNOHANG, 0, 0)))
		return;

	TST_CHECKPOINT_WAKE2(0, MAXKIDS);

	if (TST_TRACE(reap_children(0, WNOHANG, fork_kid_pid + (MAXKIDS / 2),
				    MAXKIDS / 2)))
		return;

	if (TST_TRACE(reap_children(-group, WNOHANG, fork_kid_pid,
				    MAXKIDS / 2)))
		return;

	tst_res(TPASS, "Test PASSED");
}
Пример #29
0
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");
}
Пример #30
0
static void child(void)
{
	size_t i;
	char *ptr;
	unsigned int usage, old_limit, old_memsw_limit;
	int status, pid, retries = 0;

	SAFE_MKDIR(cgroup_path, 0777);
	SAFE_FILE_PRINTF(tasks_path, "%i", getpid());

	ptr = SAFE_MMAP(NULL, PAGES * page_size, PROT_READ | PROT_WRITE,
	                 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

	for (i = 0; i < PAGES * page_size; i++)
		ptr[i] = 'a';

	if (madvise(ptr, PAGES * page_size, MADV_FREE)) {
		if (errno == EINVAL)
			tst_brk(TCONF | TERRNO, "MADV_FREE is not supported");

		tst_brk(TBROK | TERRNO, "MADV_FREE failed");
	}

	if (ptr[page_size] != 'a')
		tst_res(TFAIL, "MADV_FREE pages were freed immediatelly");
	else
		tst_res(TPASS, "MADV_FREE pages were not freed immediatelly");

	ptr[TOUCHED_PAGE1 * page_size] = 'b';
	ptr[TOUCHED_PAGE2 * page_size] = 'b';

	usage = 8 * 1024 * 1024;
	tst_res(TINFO, "Setting memory limits to %u %u", usage, 2 * usage);

	SAFE_FILE_SCANF(limit_in_bytes_path, "%u", &old_limit);

	if (swap_accounting_enabled)
		SAFE_FILE_SCANF(memsw_limit_in_bytes_path, "%u", &old_memsw_limit);

	SAFE_FILE_PRINTF(limit_in_bytes_path, "%u", usage);

	if (swap_accounting_enabled)
		SAFE_FILE_PRINTF(memsw_limit_in_bytes_path, "%u", 2 * usage);

	do {
		sleep_between_faults++;

		pid = SAFE_FORK();
		if (!pid)
			memory_pressure_child();

		tst_res(TINFO, "Memory hungry child %i started, try %i", pid, retries);

		SAFE_WAIT(&status);
	} while (retries++ < 10 && count_freed(ptr) == 0);

	char map[PAGES+1];
	unsigned int freed = 0;
	unsigned int corrupted = 0;

	for (i = 0; i < PAGES; i++) {
		char exp_val;

		if (ptr[i * page_size]) {
			exp_val = 'a';
			map[i] = 'p';
		} else {
			exp_val = 0;
			map[i] = '_';
			freed++;
		}

		if (i != TOUCHED_PAGE1 && i != TOUCHED_PAGE2) {
			if (check_page(ptr + i * page_size, exp_val)) {
				map[i] = '?';
				corrupted++;
			}
		} else {
			if (check_page_baaa(ptr + i * page_size)) {
				map[i] = '?';
				corrupted++;
			}
		}
	}
	map[PAGES] = '\0';

	tst_res(TINFO, "Memory map: %s", map);

	if (freed)
		tst_res(TPASS, "Pages MADV_FREE were freed on low memory");
	else
		tst_res(TFAIL, "No MADV_FREE page was freed on low memory");

	if (corrupted)
		tst_res(TFAIL, "Found corrupted page");
	else
		tst_res(TPASS, "All pages have expected content");

	if (swap_accounting_enabled)
		SAFE_FILE_PRINTF(memsw_limit_in_bytes_path, "%u", old_memsw_limit);

	SAFE_FILE_PRINTF(limit_in_bytes_path, "%u", old_limit);

	SAFE_MUNMAP(ptr, PAGES);

	exit(0);
}