Exemplo n.º 1
0
int main(int ac, char **av)
{
	int lc;
	const char *msg;

	if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL)
		tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);

	setup();

	for (lc = 0; TEST_LOOPING(lc); lc++) {
		/* Check ONLYDIR on a directory */
		CHECK_MARK(".", FAN_MARK_ONLYDIR, 0, NULL);

		/* Check ONLYDIR without a directory */
		CHECK_MARK(fname, FAN_MARK_ONLYDIR, -1, NULL);

		/* Check DONT_FOLLOW for a symlink */
		CHECK_MARK(sname, FAN_MARK_DONT_FOLLOW, 0, test_open_symlink);

		/* Check without DONT_FOLLOW for a symlink */
		CHECK_MARK(sname, 0, 0, test_open_file);

		/* Verify FAN_MARK_FLUSH destroys all inode marks */
		if (myfanotify_mark(fd_notify, FAN_MARK_ADD,
				    FAN_OPEN, AT_FDCWD, fname) < 0) {
			tst_brkm(TBROK | TERRNO, cleanup,
			    "fanotify_mark (%d, FAN_MARK_ADD, FAN_OPEN, "
			    "AT_FDCWD, '%s') failed", fd_notify, fname);
		}
		if (myfanotify_mark(fd_notify, FAN_MARK_ADD,
				    FAN_OPEN | FAN_ONDIR, AT_FDCWD, dir) < 0) {
			tst_brkm(TBROK | TERRNO, cleanup,
			    "fanotify_mark (%d, FAN_MARK_ADD, FAN_OPEN | "
			    "FAN_ONDIR, AT_FDCWD, '%s') failed", fd_notify,
			    dir);
		}
		open_file(fname);
		verify_event(S_IFREG);
		open_dir(dir);
		verify_event(S_IFDIR);
		if (myfanotify_mark(fd_notify, FAN_MARK_FLUSH,
				    0, AT_FDCWD, ".") < 0) {
			tst_brkm(TBROK | TERRNO, cleanup,
			    "fanotify_mark (%d, FAN_MARK_FLUSH, 0, "
			    "AT_FDCWD, '.') failed", fd_notify);
		}

		open_dir(dir);
		verify_no_event();
	}

	cleanup();
	tst_exit();
}
Exemplo n.º 2
0
void test01(void)
{
	/* Check ONLYDIR on a directory */
	CHECK_MARK(".", FAN_MARK_ONLYDIR, 0, NULL);

	/* Check ONLYDIR without a directory */
	CHECK_MARK(fname, FAN_MARK_ONLYDIR, -1, NULL);

	/* Check DONT_FOLLOW for a symlink */
	CHECK_MARK(sname, FAN_MARK_DONT_FOLLOW, 0, test_open_symlink);

	/* Check without DONT_FOLLOW for a symlink */
	CHECK_MARK(sname, 0, 0, test_open_file);

	/* Verify FAN_MARK_FLUSH destroys all inode marks */
	if (fanotify_mark(fd_notify, FAN_MARK_ADD,
			    FAN_OPEN, AT_FDCWD, fname) < 0) {
		tst_brk(TBROK | TERRNO,
		    "fanotify_mark (%d, FAN_MARK_ADD, FAN_OPEN, "
		    "AT_FDCWD, '%s') failed", fd_notify, fname);
	}
	if (fanotify_mark(fd_notify, FAN_MARK_ADD,
			    FAN_OPEN | FAN_ONDIR, AT_FDCWD, dir) < 0) {
		tst_brk(TBROK | TERRNO,
		    "fanotify_mark (%d, FAN_MARK_ADD, FAN_OPEN | "
		    "FAN_ONDIR, AT_FDCWD, '%s') failed", fd_notify,
		    dir);
	}
	open_file(fname);
	verify_event(S_IFREG);
	open_dir(dir);
	verify_event(S_IFDIR);
	if (fanotify_mark(fd_notify, FAN_MARK_FLUSH,
			    0, AT_FDCWD, ".") < 0) {
		tst_brk(TBROK | TERRNO,
		    "fanotify_mark (%d, FAN_MARK_FLUSH, 0, "
		    "AT_FDCWD, '.') failed", fd_notify);
	}

	open_dir(dir);
	verify_no_event();
}
Exemplo n.º 3
0
static void
do_spawn (void)
{
	int          n;
	int          size;
	uid_t        uid;
	gid_t        gid;
	int          env_inherit;
	pid_t        child;
	int          envs         = 0;
	int          log_stderr   = 0;
	char        *interpreter  = NULL;
	char        *log_file     = NULL;
	char        *uid_str      = NULL;
	char        *chroot_dir   = NULL;
	char       **envp         = NULL;
	char        *p            = spawn_shared;
	const char  *argv[]       = {"sh", "-c", NULL, NULL};

#define CHECK_MARK(val)           \
	if ((*(int *)p) != val) { \
		goto cleanup;     \
	} else {                  \
		p += sizeof(int); \
	}

#define ALIGN4(buf) while ((long)p & 0x3) p++;

	/* Read the shared memory
	 */

	/* 1.- Interpreter */
	CHECK_MARK (0xF0);

	size = *((int *)p);
	p += sizeof(int);
	if (size <= 0) {
		goto cleanup;
	}

	interpreter = malloc (sizeof("exec ") + size);
	if (interpreter == NULL) {
		goto cleanup;
	}
	strncpy (interpreter, "exec ", 5);
	strncpy (interpreter + 5, p, size + 1);
	p += size + 1;
	ALIGN4 (p);

	/* 2.- UID & GID */
	CHECK_MARK (0xF1);

	size = *((int *)p);
	if (size > 0) {
		uid_str = strdup (p + sizeof(int));
	}
	p += sizeof(int) + size + 1;
	ALIGN4 (p);

	memcpy (&uid, p, sizeof(uid_t));
	p += sizeof(uid_t);

	memcpy (&gid, p, sizeof(gid_t));
	p += sizeof(gid_t);

	/* 3.- Chroot directory */
	CHECK_MARK (0xF2);
	size = *((int *) p);
	p += sizeof(int);
	if (size > 0) {
		chroot_dir = malloc(size + 1);
		memcpy(chroot_dir, p, size + 1);
	}
	p += size + 1;
	ALIGN4 (p);

	/* 4.- Environment */
	CHECK_MARK (0xF3);

	env_inherit = *((int *)p);
	p += sizeof(int);

	envs = *((int *)p);
	p += sizeof(int);

	envp = malloc (sizeof(char *) * (envs + 1));
	if (envp == NULL) {
		goto cleanup;
	}
	envp[envs] = NULL;

	for (n=0; n<envs; n++) {
		char *e;

		size = *((int *)p);
		p += sizeof(int);

		e = malloc (size + 1);
		if (e == NULL) {
			goto cleanup;
		}

		memcpy (e, p, size);
		e[size] = '\0';

		envp[n] = e;
		p += size + 1;
		ALIGN4 (p);
	}

	/* 5.- Error log */
	CHECK_MARK (0xF4);

	size = *((int *)p);
	p += sizeof(int);

	if (size > 0) {
		if (! strncmp (p, "stderr", 6)) {
			log_stderr = 1;
		} else if (! strncmp (p, "file,", 5)) {
			log_file = p+5;
		}

		p += (size + 1);
		ALIGN4 (p);
	}

	/* 6.- PID: it's -1 now */
	CHECK_MARK (0xF5);

	n = *((int *)p);
	if (n > 0) {
		kill (n, SIGTERM);
		*p = -1;
	}

	/* Spawn
	 */
	child = fork();
	switch (child) {
	case 0: {
		int              i;
		struct sigaction sig_action;

		/* Reset signal handlers */
		sig_action.sa_handler = SIG_DFL;
		sig_action.sa_flags   = 0;
		sigemptyset (&sig_action.sa_mask);

		for (i=0 ; i < NSIG ; i++) {
			sigaction (i, &sig_action, NULL);
		}

		/* Logging */
		if (log_file) {
			int fd;
			fd = open (log_file, O_WRONLY | O_APPEND | O_CREAT, 0600);
			if (fd < 0) {
				PRINT_ERROR ("(warning) Couldn't open '%s' for writing..\n", log_file);
			}
			close (STDOUT_FILENO);
			close (STDERR_FILENO);
			dup2 (fd, STDOUT_FILENO);
			dup2 (fd, STDERR_FILENO);
		} else if (log_stderr) {
			/* do nothing */
		} else {
			int tmp_fd;
			tmp_fd = open ("/dev/null", O_WRONLY);

			close (STDOUT_FILENO);
			close (STDERR_FILENO);
			dup2 (tmp_fd, STDOUT_FILENO);
			dup2 (tmp_fd, STDERR_FILENO);
		}

		/* Change root */
		if (chroot_dir) {
			int re = chroot(chroot_dir);
			if (re < 0) {
				PRINT_ERROR ("(critial) Couldn't chroot to %s\n", chroot_dir);
				exit (1);
			}
		}

		/* Change user & group */
		if (uid_str != NULL) {
			n = initgroups (uid_str, gid);
			if (n == -1) {
				PRINT_ERROR ("(warning) initgroups failed User=%s, GID=%d\n", uid_str, gid);
			}
		}

		if ((int)gid != -1) {
			n = setgid (gid);
			if (n != 0) {
				PRINT_ERROR ("(warning) Couldn't set GID=%d\n", gid);
			}
		}

		if ((int)uid != -1) {
			n = setuid (uid);
			if (n != 0) {
				PRINT_ERROR ("(warning) Couldn't set UID=%d\n", uid);
			}
		}

		/* Clean the shared memory */
		size = (p - spawn_shared) - sizeof(int);
		memset (spawn_shared, 0, size);

		/* Execute the interpreter */
		argv[2] = interpreter;

		if (env_inherit) {
			do {
				execv ("/bin/sh", (char **)argv);
			} while (errno == EINTR);
		} else {
			do {
				execve ("/bin/sh", (char **)argv, envp);
			} while (errno == EINTR);
		}

		PRINT_MSG ("(critical) Couldn't spawn: sh -c %s\n", interpreter);
		exit (1);
	}

	case -1:
		/* Error */
		PRINT_MSG ("(critical) Couldn't fork(): %s\n", strerror(errno));
		goto cleanup;

	default:
		break;
	}

	/* Return the PID
	 */
	memcpy (p, (char *)&child, sizeof(int));
	printf ("PID %d: launched '/bin/sh -c %s' with uid=%d, gid=%d, chroot=%s, env=%s\n", child, interpreter, uid, gid, chroot_dir, env_inherit ? "inherited":"custom");

cleanup:
	/* Unlock worker
	 */
	do_sem_op (SEM_LAUNCH_READY, 1);

	/* Clean up
	 */
	free (uid_str);
	free (interpreter);
	free (chroot_dir);

	if (envp != NULL) {
		for (n=0; n<envs; n++) {
			free (envp[n]);
		}
		free (envp);
	}
}