Пример #1
0
void
priv_init(const char *chrootdir, int ctl, uid_t uid, gid_t gid)
{

	int pair[2];

	/* Create socket pair */
	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) < 0) {
		fatal("privsep",
		    "unable to create socket pair for privilege separation");
	}

	priv_unprivileged_fd(pair[0]);
	priv_privileged_fd(pair[1]);

#ifdef ENABLE_PRIVSEP
	gid_t gidset[1];
        int status;
	/* Spawn off monitor */
	if ((monitored = fork()) < 0)
		fatal("privsep", "unable to fork monitor");
	switch (monitored) {
	case 0:
		/* We are in the children, drop privileges */
		if (RUNNING_ON_VALGRIND)
			log_warnx("privsep", "running on valgrind, keep privileges");
		else {
			priv_setup_chroot(chrootdir);
			if (chroot(chrootdir) == -1)
				fatal("privsep", "unable to chroot");
			if (chdir("/") != 0)
				fatal("privsep", "unable to chdir");
			gidset[0] = gid;
#ifdef HAVE_SETRESGID
			if (setresgid(gid, gid, gid) == -1)
				fatal("privsep", "setresgid() failed");
#else
			if (setregid(gid, gid) == -1)
				fatal("privsep", "setregid() failed");
#endif
			if (setgroups(1, gidset) == -1)
				fatal("privsep", "setgroups() failed");
#ifdef HAVE_SETRESUID
			if (setresuid(uid, uid, uid) == -1)
				fatal("privsep", "setresuid() failed");
#else
			if (setreuid(uid, uid) == -1)
				fatal("privsep", "setreuid() failed");
#endif
		}
		close(pair[1]);
		priv_ping();
		break;
	default:
		/* We are in the monitor */
		if (ctl != -1) close(ctl);
		close(pair[0]);
		if (atexit(priv_exit) != 0)
			fatal("privsep", "unable to set exit function");

		/* Install signal handlers */
		const struct sigaction pass_to_child = {
			.sa_handler = sig_pass_to_chld,
			.sa_flags = SA_RESTART
		};
		sigaction(SIGALRM, &pass_to_child, NULL);
		sigaction(SIGTERM, &pass_to_child, NULL);
		sigaction(SIGHUP,  &pass_to_child, NULL);
		sigaction(SIGINT,  &pass_to_child, NULL);
		sigaction(SIGQUIT, &pass_to_child, NULL);
		const struct sigaction child = {
			.sa_handler = sig_chld,
			.sa_flags = SA_RESTART
		};
		sigaction(SIGCHLD, &child, NULL);

                if (waitpid(monitored, &status, WNOHANG) != 0)
                        /* Child is already dead */
                        _exit(1);
		priv_loop(pair[1], 0);
		exit(0);
	}
#else
	log_warnx("priv", "no privilege separation available");
	priv_ping();
#endif
}
Пример #2
0
/* Initialization */
void
priv_init(const char *chrootdir, int ctl, uid_t uid, gid_t gid)
{

	int pair[2];
	gid_t gidset[1];
        int status;

	/* Create socket pair */
	if (socketpair(AF_LOCAL, SOCK_DGRAM, PF_UNSPEC, pair) < 0)
		fatal("privsep", "unable to create socket pair for privilege separation");

	/* Spawn off monitor */
	if ((monitored = fork()) < 0)
		fatal("privsep", "unable to fork monitor");
	switch (monitored) {
	case 0:
		/* We are in the children, drop privileges */
		if (RUNNING_ON_VALGRIND)
			log_warnx("privsep", "running on valgrind, keep privileges");
		else {
			struct stat schroot;
			if (stat(chrootdir, &schroot) == -1) {
				if (errno != ENOENT)
					fatal("privsep", "chroot directory does not exist");
				if (mkdir(chrootdir, 0755) == -1)
					fatal("privsep", "unable to create chroot directory");
				log_info("privsep", "created chroot directory %s",
				    chrootdir);
			}
			if (chroot(chrootdir) == -1)
				fatal("privsep", "unable to chroot");
			if (chdir("/") != 0)
				fatal("privsep", "unable to chdir");
			gidset[0] = gid;
#ifdef HAVE_SETRESGID
			if (setresgid(gid, gid, gid) == -1)
				fatal("privsep", "setresgid() failed");
#else
			if (setregid(gid, gid) == -1)
				fatal("privsep", "setregid() failed");
#endif
			if (setgroups(1, gidset) == -1)
				fatal("privsep", "setgroups() failed");
#ifdef HAVE_SETRESUID
			if (setresuid(uid, uid, uid) == -1)
				fatal("privsep", "setresuid() failed");
#else
			if (setreuid(uid, uid) == -1)
				fatal("privsep", "setreuid() failed");
#endif
		}
		priv_remote(pair[0]);
		close(pair[1]);
		priv_ping();
		break;
	default:
		/* We are in the monitor */
		if (ctl != -1) close(ctl);
		priv_remote(pair[1]);
		close(pair[0]);
		if (atexit(priv_exit) != 0)
			fatal("privsep", "unable to set exit function");

		/* Install signal handlers */
		const struct sigaction pass_to_child = {
			.sa_handler = sig_pass_to_chld,
			.sa_flags = SA_RESTART
		};
		sigaction(SIGALRM, &pass_to_child, NULL);
		sigaction(SIGTERM, &pass_to_child, NULL);
		sigaction(SIGHUP,  &pass_to_child, NULL);
		sigaction(SIGINT,  &pass_to_child, NULL);
		sigaction(SIGQUIT, &pass_to_child, NULL);
		const struct sigaction child = {
			.sa_handler = sig_chld,
			.sa_flags = SA_RESTART
		};
		sigaction(SIGCHLD, &child, NULL);

                if (waitpid(monitored, &status, WNOHANG) != 0)
                        /* Child is already dead */
                        _exit(1);
		priv_loop();
		exit(0);
	}
}