diff options
Diffstat (limited to 'contrib/openbsm/bin/auditd/auditd.c')
-rw-r--r-- | contrib/openbsm/bin/auditd/auditd.c | 182 |
1 files changed, 107 insertions, 75 deletions
diff --git a/contrib/openbsm/bin/auditd/auditd.c b/contrib/openbsm/bin/auditd/auditd.c index 471f4f6..edfe6c0 100644 --- a/contrib/openbsm/bin/auditd/auditd.c +++ b/contrib/openbsm/bin/auditd/auditd.c @@ -30,7 +30,7 @@ * * @APPLE_BSD_LICENSE_HEADER_END@ * - * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/auditd.c#13 $ + * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/auditd.c#16 $ */ #include <sys/types.h> @@ -44,6 +44,7 @@ #include <bsm/audit_uevents.h> #include <bsm/libbsm.h> +#include <err.h> #include <errno.h> #include <fcntl.h> #include <grp.h> @@ -63,6 +64,7 @@ static int ret, minval; static char *lastfile = NULL; static int allhardcount = 0; static int triggerfd = 0; +static int sigchlds, sigchlds_handled; static int sighups, sighups_handled; static int sigterms, sigterms_handled; static long global_flags; @@ -127,7 +129,7 @@ affixdir(char *name, struct dir_ent *dirent) const char *sep = "/"; curdir = dirent->dirname; - syslog(LOG_INFO, "dir = %s\n", dirent->dirname); + syslog(LOG_DEBUG, "dir = %s", dirent->dirname); fn = malloc(strlen(curdir) + strlen(sep) + (2 * POSTFIX_LEN) + 1); if (fn == NULL) @@ -158,10 +160,10 @@ close_lastfile(char *TS) *ptr = '.'; strcpy(ptr+1, TS); if (rename(oldname, lastfile) != 0) - syslog(LOG_ERR, "Could not rename %s to %s \n", + syslog(LOG_ERR, "Could not rename %s to %s", oldname, lastfile); else - syslog(LOG_INFO, "renamed %s to %s \n", + syslog(LOG_INFO, "renamed %s to %s", oldname, lastfile); } free(lastfile); @@ -241,7 +243,7 @@ swap_audit_file(void) /* Try until we succeed. */ while ((dirent = TAILQ_FIRST(&dir_q))) { if ((fn = affixdir(timestr, dirent)) == NULL) { - syslog(LOG_INFO, "Failed to swap log at time %s\n", + syslog(LOG_INFO, "Failed to swap log at time %s", timestr); return (-1); } @@ -250,7 +252,7 @@ swap_audit_file(void) * Create and open the file; then close and pass to the * kernel if all went well. */ - syslog(LOG_INFO, "New audit file is %s\n", fn); + syslog(LOG_INFO, "New audit file is %s", fn); #ifdef AUDIT_REVIEW_GROUP fd = open_trail(fn, uid, gid); #else @@ -262,7 +264,7 @@ swap_audit_file(void) error = auditctl(fn); if (error) { syslog(LOG_ERR, - "auditctl failed setting log file! : %s\n", + "auditctl failed setting log file! : %s", strerror(errno)); close(fd); } else { @@ -284,7 +286,7 @@ swap_audit_file(void) free(dirent->dirname); free(dirent); } - syslog(LOG_INFO, "Log directories exhausted\n"); + syslog(LOG_ERR, "Log directories exhausted\n"); return (-1); } @@ -326,7 +328,7 @@ read_control_file(void) allhardcount = 0; if (swap_audit_file() == -1) { - syslog(LOG_ERR, "Could not swap audit file\n"); + syslog(LOG_ERR, "Could not swap audit file"); /* * XXX Faulty directory listing? - user should be given * XXX an opportunity to change the audit_control file @@ -341,16 +343,16 @@ read_control_file(void) * XXX is generated here? */ if (0 == (ret = getacmin(&minval))) { - syslog(LOG_INFO, "min free = %d\n", minval); + syslog(LOG_DEBUG, "min free = %d\n", minval); if (auditon(A_GETQCTRL, &qctrl, sizeof(qctrl)) != 0) { syslog(LOG_ERR, - "could not get audit queue settings\n"); + "could not get audit queue settings"); return (-1); } qctrl.aq_minfree = minval; if (auditon(A_SETQCTRL, &qctrl, sizeof(qctrl)) != 0) { syslog(LOG_ERR, - "could not set audit queue settings\n"); + "could not set audit queue settings"); return (-1); } } @@ -372,20 +374,20 @@ close_all(void) /* Generate an audit record. */ if ((aufd = au_open()) == -1) - syslog(LOG_ERR, "Could not create audit shutdown event.\n"); + syslog(LOG_ERR, "Could not create audit shutdown event."); else { if ((tok = au_to_text("auditd::Audit shutdown")) != NULL) au_write(aufd, tok); if (au_close(aufd, 1, AUE_audit_shutdown) == -1) syslog(LOG_ERR, - "Could not close audit shutdown event.\n"); + "Could not close audit shutdown event."); } /* Flush contents. */ cond = AUC_DISABLED; err_ret = auditon(A_SETCOND, &cond, sizeof(cond)); if (err_ret != 0) { - syslog(LOG_ERR, "Disabling audit failed! : %s\n", + syslog(LOG_ERR, "Disabling audit failed! : %s", strerror(errno)); err_ret = 1; } @@ -396,15 +398,15 @@ close_all(void) free_dir_q(); if ((remove(AUDITD_PIDFILE) == -1) || err_ret) { - syslog(LOG_ERR, "Could not unregister\n"); + syslog(LOG_ERR, "Could not unregister"); audit_warn_postsigterm(); return (1); } endac(); if (close(triggerfd) != 0) - syslog(LOG_ERR, "Error closing control file\n"); - syslog(LOG_INFO, "Finished.\n"); + syslog(LOG_ERR, "Error closing control file"); + syslog(LOG_INFO, "Finished"); return (0); } @@ -422,6 +424,8 @@ relay_signal(int signal) sighups++; if (signal == SIGTERM) sigterms++; + if (signal == SIGCHLD) + sigchlds++; } /* @@ -437,23 +441,22 @@ register_daemon(void) /* Set up the signal hander. */ if (signal(SIGTERM, relay_signal) == SIG_ERR) { syslog(LOG_ERR, - "Could not set signal handler for SIGTERM\n"); + "Could not set signal handler for SIGTERM"); fail_exit(); } if (signal(SIGCHLD, relay_signal) == SIG_ERR) { syslog(LOG_ERR, - "Could not set signal handler for SIGCHLD\n"); + "Could not set signal handler for SIGCHLD"); fail_exit(); } if (signal(SIGHUP, relay_signal) == SIG_ERR) { syslog(LOG_ERR, - "Could not set signal handler for SIGHUP\n"); + "Could not set signal handler for SIGHUP"); fail_exit(); } if ((pidfile = fopen(AUDITD_PIDFILE, "a")) == NULL) { - syslog(LOG_ERR, - "Could not open PID file\n"); + syslog(LOG_ERR, "Could not open PID file"); audit_warn_tmpfile(); return (-1); } @@ -462,7 +465,7 @@ register_daemon(void) fd = fileno(pidfile); if (flock(fd, LOCK_EX | LOCK_NB) < 0) { syslog(LOG_ERR, - "PID file is locked (is another auditd running?).\n"); + "PID file is locked (is another auditd running?)."); audit_warn_ebusy(); return (-1); } @@ -490,7 +493,6 @@ handle_audit_trigger(int trigger) static int last_trigger; static time_t last_time; struct dir_ent *dirent; - int rc; /* * Suppres duplicate messages from the kernel within the specified @@ -516,7 +518,7 @@ handle_audit_trigger(int trigger) switch(trigger) { case AUDIT_TRIGGER_LOW_SPACE: - syslog(LOG_INFO, "Got low space trigger\n"); + syslog(LOG_INFO, "Got low space trigger"); if (dirent && (dirent->softlim != 1)) { TAILQ_REMOVE(&dir_q, dirent, dirs); /* Add this node to the end of the list. */ @@ -526,7 +528,7 @@ handle_audit_trigger(int trigger) if (TAILQ_NEXT(TAILQ_FIRST(&dir_q), dirs) != NULL && swap_audit_file() == -1) - syslog(LOG_ERR, "Error swapping audit file\n"); + syslog(LOG_ERR, "Error swapping audit file"); /* * Check if the next dir has already reached its soft @@ -548,7 +550,7 @@ handle_audit_trigger(int trigger) break; case AUDIT_TRIGGER_NO_SPACE: - syslog(LOG_INFO, "Got no space trigger\n"); + syslog(LOG_INFO, "Got no space trigger"); /* Delete current dir, go on to next. */ TAILQ_REMOVE(&dir_q, dirent, dirs); @@ -557,7 +559,7 @@ handle_audit_trigger(int trigger) free(dirent); if (swap_audit_file() == -1) - syslog(LOG_ERR, "Error swapping audit file\n"); + syslog(LOG_ERR, "Error swapping audit file"); /* We are out of log directories. */ audit_warn_allhard(++allhardcount); @@ -568,21 +570,21 @@ handle_audit_trigger(int trigger) * Create a new file and swap with the one being used in * kernel */ - syslog(LOG_INFO, "Got open new trigger\n"); + syslog(LOG_INFO, "Got open new trigger"); if (swap_audit_file() == -1) - syslog(LOG_ERR, "Error swapping audit file\n"); + syslog(LOG_ERR, "Error swapping audit file"); break; case AUDIT_TRIGGER_READ_FILE: - syslog(LOG_INFO, "Got read file trigger\n"); + syslog(LOG_INFO, "Got read file trigger"); if (read_control_file() == -1) - syslog(LOG_ERR, "Error in audit control file\n"); + syslog(LOG_ERR, "Error in audit control file"); if (config_audit_controls() == -1) - syslog(LOG_ERR, "Error setting audit controls\n"); + syslog(LOG_ERR, "Error setting audit controls"); break; default: - syslog(LOG_ERR, "Got unknown trigger %d\n", trigger); + syslog(LOG_ERR, "Got unknown trigger %d", trigger); break; } } @@ -596,10 +598,38 @@ handle_sighup(void) } /* - * Read the control file for triggers and handle appropriately. + * Reap our children. + */ +static void +reap_children(void) +{ + pid_t child; + int wstatus; + + while ((child = waitpid(-1, &wstatus, WNOHANG)) > 0) { + if (!wstatus) + continue; + syslog(LOG_INFO, "warn process [pid=%d] %s %d.", child, + ((WIFEXITED(wstatus)) ? "exited with non-zero status" : + "exited as a result of signal"), + ((WIFEXITED(wstatus)) ? WEXITSTATUS(wstatus) : + WTERMSIG(wstatus))); + } +} + +static void +handle_sigchld(void) +{ + + sigchlds_handled = sigchlds; + reap_children(); +} + +/* + * Read the control file for triggers/signals and handle appropriately. */ static int -wait_for_triggers(void) +wait_for_events(void) { int num; unsigned int trigger; @@ -607,24 +637,28 @@ wait_for_triggers(void) for (;;) { num = read(triggerfd, &trigger, sizeof(trigger)); if ((num == -1) && (errno != EINTR)) { - syslog(LOG_ERR, "%s: error %d\n", __FUNCTION__, errno); + syslog(LOG_ERR, "%s: error %d", __FUNCTION__, errno); return (-1); } if (sigterms != sigterms_handled) { - syslog(LOG_INFO, "%s: SIGTERM", __FUNCTION__); + syslog(LOG_DEBUG, "%s: SIGTERM", __FUNCTION__); break; } + if (sigchlds != sigchlds_handled) { + syslog(LOG_DEBUG, "%s: SIGCHLD", __FUNCTION__); + handle_sigchld(); + } if (sighups != sighups_handled) { - syslog(LOG_INFO, "%s: SIGHUP", __FUNCTION__); + syslog(LOG_DEBUG, "%s: SIGHUP", __FUNCTION__); handle_sighup(); } if ((num == -1) && (errno == EINTR)) continue; if (num == 0) { - syslog(LOG_INFO, "%s: read EOF\n", __FUNCTION__); + syslog(LOG_ERR, "%s: read EOF", __FUNCTION__); return (-1); } - syslog(LOG_INFO, "%s: read %d\n", __FUNCTION__, trigger); + syslog(LOG_DEBUG, "%s: read %d", __FUNCTION__, trigger); if (trigger == AUDIT_TRIGGER_CLOSE_AND_DIE) break; else @@ -634,26 +668,6 @@ wait_for_triggers(void) } /* - * Reap our children. - */ -static void -reap_children(void) -{ - pid_t child; - int wstatus; - - while ((child = waitpid(-1, &wstatus, WNOHANG)) > 0) { - if (!wstatus) - continue; - syslog(LOG_INFO, "warn process [pid=%d] %s %d.\n", child, - ((WIFEXITED(wstatus)) ? "exited with non-zero status" : - "exited as a result of signal"), - ((WIFEXITED(wstatus)) ? WEXITSTATUS(wstatus) : - WTERMSIG(wstatus))); - } -} - -/* * Configure the audit controls in the kernel: the event to class mapping, * kernel preselection mask, etc. */ @@ -700,7 +714,7 @@ config_audit_controls(void) if (ctr == 0) syslog(LOG_ERR, "No events to class mappings registered."); else - syslog(LOG_INFO, "Registered %d event to class mappings.", + syslog(LOG_DEBUG, "Registered %d event to class mappings.", ctr); /* @@ -713,7 +727,7 @@ config_audit_controls(void) syslog(LOG_ERR, "Failed to register non-attributable event mask."); else - syslog(LOG_INFO, + syslog(LOG_DEBUG, "Registered non-attributable event mask."); } else syslog(LOG_ERR, @@ -731,35 +745,53 @@ config_audit_controls(void) static void setup(void) { + auditinfo_t auinfo; int aufd; token_t *tok; if ((triggerfd = open(AUDIT_TRIGGER_FILE, O_RDONLY, 0)) < 0) { - syslog(LOG_ERR, "Error opening trigger file\n"); + syslog(LOG_ERR, "Error opening trigger file"); + fail_exit(); + } + + /* + * To provide event feedback cycles and avoid auditd becoming + * stalled if auditing is suspended, auditd and its children run + * without their events being audited. We allow the uid, tid, and + * mask fields to be implicitly set to zero, but do set the pid. We + * run this after opening the trigger device to avoid configuring + * audit state without audit present in the system. + * + * XXXRW: Is there more to it than this? + */ + bzero(&auinfo, sizeof(auinfo)); + auinfo.ai_asid = getpid(); + if (setaudit(&auinfo) == -1) { + syslog(LOG_ERR, "Error setting audit stat"); fail_exit(); } TAILQ_INIT(&dir_q); if (read_control_file() == -1) { - syslog(LOG_ERR, "Error reading control file\n"); + syslog(LOG_ERR, "Error reading control file"); fail_exit(); } /* Generate an audit record. */ if ((aufd = au_open()) == -1) - syslog(LOG_ERR, "Could not create audit startup event.\n"); + syslog(LOG_ERR, "Could not create audit startup event."); else { if ((tok = au_to_text("auditd::Audit startup")) != NULL) au_write(aufd, tok); if (au_close(aufd, 1, AUE_audit_startup) == -1) syslog(LOG_ERR, - "Could not close audit startup event.\n"); + "Could not close audit startup event."); } if (config_audit_controls() == 0) - syslog(LOG_INFO, "Audit controls init successful\n"); + syslog(LOG_INFO, "Audit controls init successful"); else - syslog(LOG_INFO, "Audit controls init failed\n"); + syslog(LOG_ERR, "Audit controls init failed"); } int @@ -800,22 +832,22 @@ main(int argc, char **argv) #else openlog("auditd", LOG_CONS | LOG_PID, LOG_AUTH); #endif - syslog(LOG_INFO, "starting...\n"); + syslog(LOG_INFO, "starting..."); if (debug == 0 && daemon(0, 0) == -1) { - syslog(LOG_ERR, "Failed to daemonize\n"); + syslog(LOG_ERR, "Failed to daemonize"); exit(1); } if (register_daemon() == -1) { - syslog(LOG_ERR, "Could not register as daemon\n"); + syslog(LOG_ERR, "Could not register as daemon"); exit(1); } setup(); - rc = wait_for_triggers(); - syslog(LOG_INFO, "auditd exiting.\n"); + rc = wait_for_events(); + syslog(LOG_INFO, "auditd exiting."); exit(rc); } |