/* Main loop, run as root */ static void priv_loop(int privileged, int once) { enum priv_cmd cmd; struct dispatch_actions *a; #ifdef ENABLE_PRIVSEP setproctitle("monitor"); #ifdef USE_SECCOMP if (priv_seccomp_init(privileged, monitored) != 0) fatal("privsep", "cannot continue without seccomp setup"); #endif #endif while (!may_read(PRIV_PRIVILEGED, &cmd, sizeof(enum priv_cmd))) { log_debug("privsep", "received command %d", cmd); for (a = actions; a->function != NULL; a++) { if (cmd == a->msg) { a->function(); break; } } if (a->function == NULL) fatalx("privsep", "bogus message received"); if (once) break; } }
int isc_priv_init(int lstderr) { int i, socks[2], cmd; logmsg(LOG_NOTICE, "Starting privilege separation"); log_stderr = lstderr; /* Create sockets */ if (socketpair(AF_LOCAL, SOCK_STREAM, PF_UNSPEC, socks) == -1) fatal("socketpair() failed"); switch (child_pid = fork()) { case -1: fatal("failed to fork() for privsep"); case 0: close(socks[0]); priv_fd = socks[1]; return (0); default: break; } for (i = 1; i < _NSIG; i++) signal(i, SIG_DFL); signal(SIGALRM, sig_pass_to_chld); signal(SIGTERM, sig_pass_to_chld); signal(SIGHUP, sig_pass_to_chld); signal(SIGINT, sig_pass_to_chld); signal(SIGCHLD, sig_got_chld); /* Father - close unneeded sockets */ for (i = STDERR_FILENO + 1; i < socks[0]; i++) close(i); closefrom(socks[0] + 1); setproctitle("[priv]"); while (cur_state != STATE_QUIT) { if (may_read(socks[0], &cmd, sizeof(int))) break; switch (cmd) { case PRIV_BIND: parent_bind(socks[0]); break; default: logmsg(LOG_ERR, "[priv]: unknown command %d", cmd); _exit(1); /* NOTREACHED */ } } _exit(0); }
/* Main loop, run as root */ static void priv_loop() { enum priv_cmd cmd; struct dispatch_actions *a; setproctitle("monitor"); while (!may_read(&cmd, sizeof(enum priv_cmd))) { for (a = actions; a->function != NULL; a++) { if (cmd == a->msg) { a->function(); break; } } if (a->function == NULL) fatal("privsep", "bogus message received"); } /* Should never be there */ }
/* based on syslogd privsep */ int priv_init(void) { int i, fd, socks[2], cmd; int snaplen, ret, olderrno; struct passwd *pw; #ifdef __FreeBSD__ for (i = 1; i < NSIG; i++) #else for (i = 1; i < _NSIG; i++) #endif signal(i, SIG_DFL); /* Create sockets */ if (socketpair(AF_LOCAL, SOCK_STREAM, PF_UNSPEC, socks) == -1) err(1, "socketpair() failed"); pw = getpwnam("_pflogd"); if (pw == NULL) errx(1, "unknown user _pflogd"); endpwent(); child_pid = fork(); if (child_pid < 0) err(1, "fork() failed"); if (!child_pid) { gid_t gidset[1]; /* Child - drop privileges and return */ if (chroot(pw->pw_dir) != 0) err(1, "unable to chroot"); if (chdir("/") != 0) err(1, "unable to chdir"); gidset[0] = pw->pw_gid; if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1) err(1, "setresgid() failed"); if (setgroups(1, gidset) == -1) err(1, "setgroups() failed"); if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1) err(1, "setresuid() failed"); close(socks[0]); priv_fd = socks[1]; return 0; } /* Father */ /* Pass ALRM/TERM/HUP/INT/QUIT through to child, and accept CHLD */ signal(SIGALRM, sig_pass_to_chld); signal(SIGTERM, sig_pass_to_chld); signal(SIGHUP, sig_pass_to_chld); signal(SIGINT, sig_pass_to_chld); signal(SIGQUIT, sig_pass_to_chld); signal(SIGCHLD, sig_chld); setproctitle("[priv]"); close(socks[1]); while (!gotsig_chld) { if (may_read(socks[0], &cmd, sizeof(int))) break; switch (cmd) { case PRIV_SET_SNAPLEN: logmsg(LOG_DEBUG, "[priv]: msg PRIV_SET_SNAPLENGTH received"); must_read(socks[0], &snaplen, sizeof(int)); ret = set_snaplen(snaplen); if (ret) { logmsg(LOG_NOTICE, "[priv]: set_snaplen failed for snaplen %d", snaplen); } must_write(socks[0], &ret, sizeof(int)); break; case PRIV_OPEN_LOG: logmsg(LOG_DEBUG, "[priv]: msg PRIV_OPEN_LOG received"); /* create or append logs but do not follow symlinks */ fd = open(filename, O_RDWR|O_CREAT|O_APPEND|O_NONBLOCK|O_NOFOLLOW, 0600); olderrno = errno; send_fd(socks[0], fd); if (fd < 0) logmsg(LOG_NOTICE, "[priv]: failed to open %s: %s", filename, strerror(olderrno)); else close(fd); break; case PRIV_MOVE_LOG: logmsg(LOG_DEBUG, "[priv]: msg PRIV_MOVE_LOG received"); ret = move_log(filename); must_write(socks[0], &ret, sizeof(int)); break; default: logmsg(LOG_ERR, "[priv]: unknown command %d", cmd); _exit(1); /* NOTREACHED */ } } _exit(1); }