auditd: Fix signal handling
Rewrite the main loop to use ppoll() instead of just blocking on read, blocking the signals we care about when we aren't polling. I didn't bother replacing alarm() with setitimer(); the alarm code is dead anyway since there is no way for max_idletime to acquire a non-zero value. While here, avoid leaking the pid file and trigger descriptors to the log child. PR: 295840 MFC after: 1 week Sponsored by: Klara, Inc. Reviewed by: kevans Differential Revision: https://reviews.freebsd.org/D57451
This commit is contained in:
@@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -57,6 +58,9 @@ auditwarnlog(char *args[])
|
|||||||
/*
|
/*
|
||||||
* Child.
|
* Child.
|
||||||
*/
|
*/
|
||||||
|
#ifndef USE_MACH_IPC
|
||||||
|
sigprocmask(SIG_SETMASK, &auditd_origmask, NULL);
|
||||||
|
#endif /* !USE_MACH_IPC */
|
||||||
execv(AUDITWARN_SCRIPT, loc_args);
|
execv(AUDITWARN_SCRIPT, loc_args);
|
||||||
syslog(LOG_ERR, "Could not exec %s (%m)\n",
|
syslog(LOG_ERR, "Could not exec %s (%m)\n",
|
||||||
AUDITWARN_SCRIPT);
|
AUDITWARN_SCRIPT);
|
||||||
|
|||||||
@@ -107,6 +107,19 @@ static gid_t audit_review_gid = -1;
|
|||||||
*/
|
*/
|
||||||
static char *lastfile = NULL;
|
static char *lastfile = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* File descriptor to our locked pid file.
|
||||||
|
*/
|
||||||
|
static int pidfd;
|
||||||
|
|
||||||
|
#ifndef USE_MACH_IPC
|
||||||
|
/*
|
||||||
|
* Original signal mask in effect at startup. Used by the main event loop
|
||||||
|
* and the log child.
|
||||||
|
*/
|
||||||
|
sigset_t auditd_origmask;
|
||||||
|
#endif /* !USE_MACH_IPC */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Error starting auditd. Run warn script and exit.
|
* Error starting auditd. Run warn script and exit.
|
||||||
*/
|
*/
|
||||||
@@ -354,12 +367,20 @@ close_misc(void)
|
|||||||
auditd_log_err("Couldn't remove %s: %m", AUDITD_PIDFILE);
|
auditd_log_err("Couldn't remove %s: %m", AUDITD_PIDFILE);
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
close(pidfd);
|
||||||
|
pidfd = -1;
|
||||||
endac();
|
endac();
|
||||||
|
|
||||||
if (auditd_close_trigger() != 0) {
|
if (auditd_close_trigger() != 0) {
|
||||||
auditd_log_err("Error closing trigger messaging mechanism");
|
auditd_log_err("Error closing trigger messaging mechanism");
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef USE_MACH_IPC
|
||||||
|
/* Restore the original signal mask. */
|
||||||
|
sigprocmask(SIG_SETMASK, &auditd_origmask, NULL);
|
||||||
|
#endif /* !USE_MACH_IPC */
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -416,9 +437,17 @@ static int
|
|||||||
register_daemon(void)
|
register_daemon(void)
|
||||||
{
|
{
|
||||||
struct sigaction action;
|
struct sigaction action;
|
||||||
FILE * pidfile;
|
sigset_t sigmask;
|
||||||
int fd;
|
|
||||||
pid_t pid;
|
#ifndef USE_MACH_IPC
|
||||||
|
/* Set up the signal mask. */
|
||||||
|
sigemptyset(&sigmask);
|
||||||
|
sigaddset(&sigmask, SIGTERM);
|
||||||
|
sigaddset(&sigmask, SIGALRM);
|
||||||
|
sigaddset(&sigmask, SIGCHLD);
|
||||||
|
sigaddset(&sigmask, SIGHUP);
|
||||||
|
sigprocmask(SIG_BLOCK, &sigmask, &auditd_origmask);
|
||||||
|
#endif /* !USE_MACH_IPC */
|
||||||
|
|
||||||
/* Set up the signal hander. */
|
/* Set up the signal hander. */
|
||||||
action.sa_handler = auditd_relay_signal;
|
action.sa_handler = auditd_relay_signal;
|
||||||
@@ -449,29 +478,30 @@ register_daemon(void)
|
|||||||
fail_exit();
|
fail_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((pidfile = fopen(AUDITD_PIDFILE, "a")) == NULL) {
|
/* Open the pid file. */
|
||||||
|
pidfd = open(AUDITD_PIDFILE, O_CREAT | O_WRONLY | O_APPEND | O_CLOEXEC,
|
||||||
|
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||||
|
if (pidfd < 0) {
|
||||||
auditd_log_err("Could not open PID file");
|
auditd_log_err("Could not open PID file");
|
||||||
audit_warn_tmpfile();
|
audit_warn_tmpfile();
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Attempt to lock the pid file; if a lock is present, exit. */
|
/* Attempt to lock the pid file; if a lock is present, exit. */
|
||||||
fd = fileno(pidfile);
|
if (flock(pidfd, LOCK_EX | LOCK_NB) < 0) {
|
||||||
if (flock(fd, LOCK_EX | LOCK_NB) < 0) {
|
|
||||||
auditd_log_err(
|
auditd_log_err(
|
||||||
"PID file is locked (is another auditd running?).");
|
"PID file is locked (is another auditd running?).");
|
||||||
audit_warn_ebusy();
|
audit_warn_ebusy();
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
pid = getpid();
|
/* Write our pid to the pid file and leave it open. */
|
||||||
ftruncate(fd, 0);
|
ftruncate(pidfd, 0);
|
||||||
if (fprintf(pidfile, "%u\n", pid) < 0) {
|
if (dprintf(pidfd, "%u\n", getpid()) < 0) {
|
||||||
/* Should not start the daemon. */
|
/* Should not start the daemon. */
|
||||||
fail_exit();
|
fail_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
fflush(pidfile);
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -96,5 +96,8 @@ void auditd_terminate(void);
|
|||||||
int auditd_config_controls(void);
|
int auditd_config_controls(void);
|
||||||
void auditd_reap_children(void);
|
void auditd_reap_children(void);
|
||||||
|
|
||||||
|
#ifndef USE_MACH_IPC
|
||||||
|
extern sigset_t auditd_origmask;
|
||||||
|
#endif /* !USE_MACH_IPC */
|
||||||
|
|
||||||
#endif /* !_AUDITD_H_ */
|
#endif /* !_AUDITD_H_ */
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <poll.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -57,10 +58,7 @@ static int auditing_state = AUD_STATE_INIT;
|
|||||||
*/
|
*/
|
||||||
static int max_idletime = 0;
|
static int max_idletime = 0;
|
||||||
|
|
||||||
static int sigchlds, sigchlds_handled;
|
static volatile sig_atomic_t signaled[NSIG];
|
||||||
static int sighups, sighups_handled;
|
|
||||||
static int sigterms, sigterms_handled;
|
|
||||||
static int sigalrms, sigalrms_handled;
|
|
||||||
|
|
||||||
static int triggerfd = 0;
|
static int triggerfd = 0;
|
||||||
|
|
||||||
@@ -173,7 +171,6 @@ auditd_set_state(int state)
|
|||||||
int
|
int
|
||||||
auditd_get_state(void)
|
auditd_get_state(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (auditing_state == AUD_STATE_INIT)
|
if (auditing_state == AUD_STATE_INIT)
|
||||||
init_audit_state();
|
init_audit_state();
|
||||||
|
|
||||||
@@ -186,8 +183,8 @@ auditd_get_state(void)
|
|||||||
int
|
int
|
||||||
auditd_open_trigger(int __unused launchd_flag)
|
auditd_open_trigger(int __unused launchd_flag)
|
||||||
{
|
{
|
||||||
|
triggerfd = open(AUDIT_TRIGGER_FILE, O_RDONLY | O_CLOEXEC);
|
||||||
return ((triggerfd = open(AUDIT_TRIGGER_FILE, O_RDONLY, 0)));
|
return (triggerfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -196,7 +193,6 @@ auditd_open_trigger(int __unused launchd_flag)
|
|||||||
int
|
int
|
||||||
auditd_close_trigger(void)
|
auditd_close_trigger(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
return (close(triggerfd));
|
return (close(triggerfd));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,45 +203,56 @@ auditd_close_trigger(void)
|
|||||||
void
|
void
|
||||||
auditd_wait_for_events(void)
|
auditd_wait_for_events(void)
|
||||||
{
|
{
|
||||||
int num;
|
struct pollfd pfd;
|
||||||
|
ssize_t ret;
|
||||||
unsigned int trigger;
|
unsigned int trigger;
|
||||||
|
|
||||||
|
pfd.fd = triggerfd;
|
||||||
|
pfd.events = POLLIN;
|
||||||
|
pfd.revents = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
num = read(triggerfd, &trigger, sizeof(trigger));
|
|
||||||
if ((num == -1) && (errno != EINTR)) {
|
|
||||||
auditd_log_err("%s: error %d", __FUNCTION__, errno);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reset the idle time alarm, if used. */
|
/* Reset the idle time alarm, if used. */
|
||||||
if (max_idletime)
|
if (max_idletime != 0)
|
||||||
alarm(max_idletime);
|
alarm(max_idletime);
|
||||||
|
|
||||||
if (sigterms != sigterms_handled) {
|
/* Check if any signals were caught. */
|
||||||
|
if (signaled[SIGTERM]) {
|
||||||
|
signaled[SIGTERM] = 0;
|
||||||
auditd_log_debug("%s: SIGTERM", __FUNCTION__);
|
auditd_log_debug("%s: SIGTERM", __FUNCTION__);
|
||||||
auditd_terminate();
|
auditd_terminate();
|
||||||
/* not reached */
|
/* not reached */
|
||||||
}
|
}
|
||||||
if (sigalrms != sigalrms_handled) {
|
if (signaled[SIGALRM]) {
|
||||||
|
signaled[SIGALRM] = 0;
|
||||||
auditd_log_debug("%s: SIGALRM", __FUNCTION__);
|
auditd_log_debug("%s: SIGALRM", __FUNCTION__);
|
||||||
auditd_terminate();
|
auditd_terminate();
|
||||||
/* not reached */
|
/* not reached */
|
||||||
}
|
}
|
||||||
if (sigchlds != sigchlds_handled) {
|
if (signaled[SIGCHLD]) {
|
||||||
sigchlds_handled = sigchlds;
|
signaled[SIGCHLD] = 0;
|
||||||
auditd_reap_children();
|
auditd_reap_children();
|
||||||
}
|
}
|
||||||
if (sighups != sighups_handled) {
|
if (signaled[SIGHUP]) {
|
||||||
|
signaled[SIGHUP] = 0;
|
||||||
auditd_log_debug("%s: SIGHUP", __FUNCTION__);
|
auditd_log_debug("%s: SIGHUP", __FUNCTION__);
|
||||||
sighups_handled = sighups;
|
|
||||||
auditd_config_controls();
|
auditd_config_controls();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num == -1)
|
/* Now wait for a trigger or signal. */
|
||||||
|
if ((ret = ppoll(&pfd, 1, NULL, &auditd_origmask)) < 0 &&
|
||||||
|
errno != EINTR) {
|
||||||
|
auditd_log_err("%s: error %d", __FUNCTION__, errno);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ret <= 0)
|
||||||
continue;
|
continue;
|
||||||
if (num == 0) {
|
if ((ret = read(triggerfd, &trigger, sizeof(trigger))) < 0) {
|
||||||
|
auditd_log_err("%s: error %d", __FUNCTION__, errno);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ret == 0) {
|
||||||
auditd_log_err("%s: read EOF", __FUNCTION__);
|
auditd_log_err("%s: read EOF", __FUNCTION__);
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
auditd_handle_trigger(trigger);
|
auditd_handle_trigger(trigger);
|
||||||
}
|
}
|
||||||
@@ -258,15 +265,7 @@ auditd_wait_for_events(void)
|
|||||||
* context.
|
* context.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
auditd_relay_signal(int signal)
|
auditd_relay_signal(int signo)
|
||||||
{
|
{
|
||||||
if (signal == SIGHUP)
|
signaled[signo] = 1;
|
||||||
sighups++;
|
|
||||||
if (signal == SIGTERM)
|
|
||||||
sigterms++;
|
|
||||||
if (signal == SIGCHLD)
|
|
||||||
sigchlds++;
|
|
||||||
if (signal == SIGALRM)
|
|
||||||
sigalrms++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user