1/*-
| 1/*-
|
2 * Copyright (c) 2004-2008 Apple Inc.
| 2 * Copyright (c) 2004-2009 Apple Inc.
|
3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of Apple Inc. ("Apple") nor the names of 15 * its contributors may be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 *
| 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of Apple Inc. ("Apple") nor the names of 15 * its contributors may be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 *
|
29 * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/auditd.c#41 $
| 29 * $P4: //depot/projects/trustedbsd/openbsm/bin/auditd/auditd.c#43 $
|
30 */ 31 32#include <sys/types.h> 33 34#include <config/config.h> 35 36#include <sys/dirent.h> 37#ifdef HAVE_FULL_QUEUE_H 38#include <sys/queue.h> 39#else /* !HAVE_FULL_QUEUE_H */ 40#include <compat/queue.h> 41#endif /* !HAVE_FULL_QUEUE_H */ 42#include <sys/mman.h> 43#include <sys/param.h> 44#include <sys/stat.h> 45#include <sys/wait.h> 46 47#include <bsm/audit.h> 48#include <bsm/audit_uevents.h> 49#include <bsm/auditd_lib.h> 50#include <bsm/libbsm.h> 51 52#include <err.h> 53#include <errno.h> 54#include <fcntl.h> 55#include <grp.h> 56#include <stdio.h> 57#include <stdlib.h> 58#include <time.h> 59#include <unistd.h> 60#include <signal.h> 61#include <string.h> 62 63#include "auditd.h" 64 65#ifndef HAVE_STRLCPY 66#include <compat/strlcpy.h> 67#endif 68 69/*
| 30 */ 31 32#include <sys/types.h> 33 34#include <config/config.h> 35 36#include <sys/dirent.h> 37#ifdef HAVE_FULL_QUEUE_H 38#include <sys/queue.h> 39#else /* !HAVE_FULL_QUEUE_H */ 40#include <compat/queue.h> 41#endif /* !HAVE_FULL_QUEUE_H */ 42#include <sys/mman.h> 43#include <sys/param.h> 44#include <sys/stat.h> 45#include <sys/wait.h> 46 47#include <bsm/audit.h> 48#include <bsm/audit_uevents.h> 49#include <bsm/auditd_lib.h> 50#include <bsm/libbsm.h> 51 52#include <err.h> 53#include <errno.h> 54#include <fcntl.h> 55#include <grp.h> 56#include <stdio.h> 57#include <stdlib.h> 58#include <time.h> 59#include <unistd.h> 60#include <signal.h> 61#include <string.h> 62 63#include "auditd.h" 64 65#ifndef HAVE_STRLCPY 66#include <compat/strlcpy.h> 67#endif 68 69/*
|
70 * XXX the following is temporary until this can be added to the kernel
| 70 * XXX The following are temporary until these can be added to the kernel
|
71 * audit.h header. 72 */ 73#ifndef AUDIT_TRIGGER_INITIALIZE 74#define AUDIT_TRIGGER_INITIALIZE 7 75#endif
| 71 * audit.h header. 72 */ 73#ifndef AUDIT_TRIGGER_INITIALIZE 74#define AUDIT_TRIGGER_INITIALIZE 7 75#endif
|
| 76#ifndef AUDIT_TRIGGER_EXPIRE_TRAILS 77#define AUDIT_TRIGGER_EXPIRE_TRAILS 8 78#endif
|
76
| 79
|
| 80
|
77/* 78 * LaunchD flag (Mac OS X and, maybe, FreeBSD only.) See launchd(8) and 79 * http://wiki.freebsd.org/launchd for more information. 80 * 81 * In order for auditd to work "on demand" with launchd(8) it can't: 82 * call daemon(3) 83 * call fork and having the parent process exit 84 * change uids or gids. 85 * set up the current working directory or chroot. 86 * set the session id 87 * change stdio to /dev/null. 88 * call setrusage(2) 89 * call setpriority(2) 90 * Ignore SIGTERM. 91 * auditd (in 'launchd mode') is launched on demand so it must catch 92 * SIGTERM to exit cleanly. 93 */ 94static int launchd_flag = 0; 95 96/* 97 * The GID of the audit review group (if used). The audit trail files and 98 * system logs (Mac OS X only) can only be reviewed by members of this group 99 * or the audit administrator (aka. "root"). 100 */ 101static gid_t audit_review_gid = -1; 102 103/* 104 * The path and file name of the last audit trail file. 105 */ 106static char *lastfile = NULL; 107 108/* 109 * Error starting auditd. Run warn script and exit. 110 */ 111static void 112fail_exit(void) 113{ 114 115 audit_warn_nostart(); 116 exit(1); 117} 118 119/* 120 * Follow the 'current' symlink to get the active trail file name. 121 */ 122static char * 123get_curfile(void) 124{ 125 char *cf; 126 int len; 127 128 cf = malloc(MAXPATHLEN); 129 if (cf == NULL) { 130 auditd_log_err("malloc failed: %m"); 131 return (NULL); 132 } 133 134 len = readlink(AUDIT_CURRENT_LINK, cf, MAXPATHLEN - 1); 135 if (len < 0) { 136 free(cf); 137 return (NULL); 138 } 139 140 /* readlink() doesn't terminate string. */ 141 cf[len] = '\0'; 142 143 return (cf); 144} 145 146/* 147 * Close the previous audit trail file. 148 */ 149static int 150close_lastfile(char *TS) 151{ 152 char *ptr; 153 char *oldname; 154 size_t len; 155 156 /* If lastfile is NULL try to get it from the 'current' link. */ 157 if (lastfile == NULL) 158 lastfile = get_curfile(); 159 160 if (lastfile != NULL) { 161 len = strlen(lastfile) + 1; 162 oldname = (char *)malloc(len); 163 if (oldname == NULL) 164 return (-1); 165 strlcpy(oldname, lastfile, len); 166 167 /* Rename the last file -- append timestamp. */ 168 if ((ptr = strstr(lastfile, NOT_TERMINATED)) != NULL) {
| 81/* 82 * LaunchD flag (Mac OS X and, maybe, FreeBSD only.) See launchd(8) and 83 * http://wiki.freebsd.org/launchd for more information. 84 * 85 * In order for auditd to work "on demand" with launchd(8) it can't: 86 * call daemon(3) 87 * call fork and having the parent process exit 88 * change uids or gids. 89 * set up the current working directory or chroot. 90 * set the session id 91 * change stdio to /dev/null. 92 * call setrusage(2) 93 * call setpriority(2) 94 * Ignore SIGTERM. 95 * auditd (in 'launchd mode') is launched on demand so it must catch 96 * SIGTERM to exit cleanly. 97 */ 98static int launchd_flag = 0; 99 100/* 101 * The GID of the audit review group (if used). The audit trail files and 102 * system logs (Mac OS X only) can only be reviewed by members of this group 103 * or the audit administrator (aka. "root"). 104 */ 105static gid_t audit_review_gid = -1; 106 107/* 108 * The path and file name of the last audit trail file. 109 */ 110static char *lastfile = NULL; 111 112/* 113 * Error starting auditd. Run warn script and exit. 114 */ 115static void 116fail_exit(void) 117{ 118 119 audit_warn_nostart(); 120 exit(1); 121} 122 123/* 124 * Follow the 'current' symlink to get the active trail file name. 125 */ 126static char * 127get_curfile(void) 128{ 129 char *cf; 130 int len; 131 132 cf = malloc(MAXPATHLEN); 133 if (cf == NULL) { 134 auditd_log_err("malloc failed: %m"); 135 return (NULL); 136 } 137 138 len = readlink(AUDIT_CURRENT_LINK, cf, MAXPATHLEN - 1); 139 if (len < 0) { 140 free(cf); 141 return (NULL); 142 } 143 144 /* readlink() doesn't terminate string. */ 145 cf[len] = '\0'; 146 147 return (cf); 148} 149 150/* 151 * Close the previous audit trail file. 152 */ 153static int 154close_lastfile(char *TS) 155{ 156 char *ptr; 157 char *oldname; 158 size_t len; 159 160 /* If lastfile is NULL try to get it from the 'current' link. */ 161 if (lastfile == NULL) 162 lastfile = get_curfile(); 163 164 if (lastfile != NULL) { 165 len = strlen(lastfile) + 1; 166 oldname = (char *)malloc(len); 167 if (oldname == NULL) 168 return (-1); 169 strlcpy(oldname, lastfile, len); 170 171 /* Rename the last file -- append timestamp. */ 172 if ((ptr = strstr(lastfile, NOT_TERMINATED)) != NULL) {
|
169 strlcpy(ptr, TS, TIMESTAMP_LEN);
| 173 memcpy(ptr, TS, POSTFIX_LEN);
|
170 if (rename(oldname, lastfile) != 0) 171 auditd_log_err( 172 "Could not rename %s to %s: %m", oldname, 173 lastfile); 174 else { 175 /* 176 * Remove the 'current' symlink since the link 177 * is now invalid. 178 */ 179 (void) unlink(AUDIT_CURRENT_LINK); 180 auditd_log_notice( "renamed %s to %s", 181 oldname, lastfile); 182 audit_warn_closefile(lastfile); 183 } 184 } else 185 auditd_log_err( "Could not rename %s to %s", oldname, 186 lastfile); 187 free(lastfile); 188 free(oldname); 189 lastfile = NULL; 190 } 191 return (0); 192} 193 194/* 195 * Create the new file name, swap with existing audit file. 196 */ 197static int 198swap_audit_file(void) 199{ 200 int err; 201 char *newfile; 202 char TS[TIMESTAMP_LEN]; 203 time_t tt; 204 205 if (getTSstr(tt, TS, TIMESTAMP_LEN) != 0) 206 return (-1); 207 err = auditd_swap_trail(TS, &newfile, audit_review_gid, 208 audit_warn_getacdir); 209 if (err != ADE_NOERR) { 210 auditd_log_err( "%s: %m", auditd_strerror(err)); 211 if (err != ADE_ACTL) 212 return (-1); 213 } 214 215 /* 216 * Only close the last file if were in an auditing state before 217 * calling swap_audit_file(). We may need to recover from a crash. 218 */ 219 if (auditd_get_state() == AUD_STATE_ENABLED) 220 close_lastfile(TS); 221 222 223 /* 224 * auditd_swap_trail() potentially enables auditing (if not already 225 * enabled) so updated the cached state as well. 226 */ 227 auditd_set_state(AUD_STATE_ENABLED); 228 229 /* 230 * Create 'current' symlink. Recover from crash, if needed. 231 */ 232 if (auditd_new_curlink(newfile) != 0) 233 auditd_log_err("auditd_new_curlink(\"%s\") failed: %s: %m", 234 newfile, auditd_strerror(err)); 235 236 lastfile = newfile; 237 auditd_log_notice("New audit file is %s", newfile); 238 239 return (0); 240} 241 242/* 243 * Create a new audit log trail file and swap with the current one, if any. 244 */ 245static int 246do_trail_file(void) 247{ 248 int err; 249 250 /* 251 * First, refresh the list of audit log directories. 252 */ 253 err = auditd_read_dirs(audit_warn_soft, audit_warn_hard); 254 if (err) { 255 auditd_log_err("auditd_read_dirs(): %s", 256 auditd_strerror(err)); 257 if (err == ADE_HARDLIM) 258 audit_warn_allhard(); 259 if (err != ADE_SOFTLIM) 260 return (-1); 261 else 262 audit_warn_allsoft(); 263 /* continue on with soft limit error */ 264 } 265 266 /* 267 * Create a new file and swap with the one being used in kernel. 268 */ 269 if (swap_audit_file() == -1) { 270 /* 271 * XXX Faulty directory listing? - user should be given 272 * XXX an opportunity to change the audit_control file 273 * XXX switch to a reduced mode of auditing? 274 */ 275 return (-1); 276 } 277
| 174 if (rename(oldname, lastfile) != 0) 175 auditd_log_err( 176 "Could not rename %s to %s: %m", oldname, 177 lastfile); 178 else { 179 /* 180 * Remove the 'current' symlink since the link 181 * is now invalid. 182 */ 183 (void) unlink(AUDIT_CURRENT_LINK); 184 auditd_log_notice( "renamed %s to %s", 185 oldname, lastfile); 186 audit_warn_closefile(lastfile); 187 } 188 } else 189 auditd_log_err( "Could not rename %s to %s", oldname, 190 lastfile); 191 free(lastfile); 192 free(oldname); 193 lastfile = NULL; 194 } 195 return (0); 196} 197 198/* 199 * Create the new file name, swap with existing audit file. 200 */ 201static int 202swap_audit_file(void) 203{ 204 int err; 205 char *newfile; 206 char TS[TIMESTAMP_LEN]; 207 time_t tt; 208 209 if (getTSstr(tt, TS, TIMESTAMP_LEN) != 0) 210 return (-1); 211 err = auditd_swap_trail(TS, &newfile, audit_review_gid, 212 audit_warn_getacdir); 213 if (err != ADE_NOERR) { 214 auditd_log_err( "%s: %m", auditd_strerror(err)); 215 if (err != ADE_ACTL) 216 return (-1); 217 } 218 219 /* 220 * Only close the last file if were in an auditing state before 221 * calling swap_audit_file(). We may need to recover from a crash. 222 */ 223 if (auditd_get_state() == AUD_STATE_ENABLED) 224 close_lastfile(TS); 225 226 227 /* 228 * auditd_swap_trail() potentially enables auditing (if not already 229 * enabled) so updated the cached state as well. 230 */ 231 auditd_set_state(AUD_STATE_ENABLED); 232 233 /* 234 * Create 'current' symlink. Recover from crash, if needed. 235 */ 236 if (auditd_new_curlink(newfile) != 0) 237 auditd_log_err("auditd_new_curlink(\"%s\") failed: %s: %m", 238 newfile, auditd_strerror(err)); 239 240 lastfile = newfile; 241 auditd_log_notice("New audit file is %s", newfile); 242 243 return (0); 244} 245 246/* 247 * Create a new audit log trail file and swap with the current one, if any. 248 */ 249static int 250do_trail_file(void) 251{ 252 int err; 253 254 /* 255 * First, refresh the list of audit log directories. 256 */ 257 err = auditd_read_dirs(audit_warn_soft, audit_warn_hard); 258 if (err) { 259 auditd_log_err("auditd_read_dirs(): %s", 260 auditd_strerror(err)); 261 if (err == ADE_HARDLIM) 262 audit_warn_allhard(); 263 if (err != ADE_SOFTLIM) 264 return (-1); 265 else 266 audit_warn_allsoft(); 267 /* continue on with soft limit error */ 268 } 269 270 /* 271 * Create a new file and swap with the one being used in kernel. 272 */ 273 if (swap_audit_file() == -1) { 274 /* 275 * XXX Faulty directory listing? - user should be given 276 * XXX an opportunity to change the audit_control file 277 * XXX switch to a reduced mode of auditing? 278 */ 279 return (-1); 280 } 281
|
| 282 /* 283 * Finally, see if there are any trail files to expire. 284 */ 285 err = auditd_expire_trails(audit_warn_expired); 286 if (err) 287 auditd_log_err("auditd_expire_trails(): %s", 288 auditd_strerror(err)); 289
|
278 return (0); 279} 280 281/* 282 * Start up auditing. 283 */ 284static void 285audit_setup(void) 286{ 287 int err; 288 289 if (do_trail_file() == -1) { 290 auditd_log_err("Error creating audit trail file"); 291 fail_exit(); 292 } 293 294 /* Generate an audit record. */ 295 err = auditd_gen_record(AUE_audit_startup, NULL); 296 if (err) 297 auditd_log_err("auditd_gen_record(AUE_audit_startup) %s: %m", 298 auditd_strerror(err)); 299 300 if (auditd_config_controls() == 0) 301 auditd_log_info("Audit controls init successful"); 302 else 303 auditd_log_err("Audit controls init failed"); 304 305} 306 307 308/* 309 * Close auditd pid file and trigger mechanism. 310 */ 311static int 312close_misc(void) 313{ 314 315 auditd_close_dirs(); 316 if (unlink(AUDITD_PIDFILE) == -1 && errno != ENOENT) { 317 auditd_log_err("Couldn't remove %s: %m", AUDITD_PIDFILE); 318 return (1); 319 } 320 endac(); 321 322 if (auditd_close_trigger() != 0) { 323 auditd_log_err("Error closing trigger messaging mechanism"); 324 return (1); 325 } 326 return (0); 327} 328 329/* 330 * Close all log files, control files, and tell the audit system. 331 */ 332static int 333close_all(void) 334{ 335 int err_ret = 0; 336 char TS[TIMESTAMP_LEN]; 337 int err; 338 long cond; 339 time_t tt; 340 341 err = auditd_gen_record(AUE_audit_shutdown, NULL); 342 if (err) 343 auditd_log_err("auditd_gen_record(AUE_audit_shutdown) %s: %m", 344 auditd_strerror(err)); 345 346 /* Flush contents. */ 347 cond = AUC_DISABLED; 348 err_ret = auditon(A_SETCOND, &cond, sizeof(cond)); 349 if (err_ret != 0) { 350 auditd_log_err("Disabling audit failed! : %s", strerror(errno)); 351 err_ret = 1; 352 } 353 354 /* 355 * Updated the cached state that auditing has been disabled. 356 */ 357 auditd_set_state(AUD_STATE_DISABLED); 358 359 if (getTSstr(tt, TS, TIMESTAMP_LEN) == 0) 360 close_lastfile(TS); 361 if (lastfile != NULL) 362 free(lastfile); 363 364 err_ret += close_misc(); 365 366 if (err_ret) { 367 auditd_log_err("Could not unregister"); 368 audit_warn_postsigterm(); 369 } 370 371 auditd_log_info("Finished"); 372 return (err_ret); 373} 374 375/* 376 * Register the daemon with the signal handler and the auditd pid file. 377 */ 378static int 379register_daemon(void) 380{ 381 FILE * pidfile; 382 int fd; 383 pid_t pid; 384 385 /* Set up the signal hander. */ 386 if (signal(SIGTERM, auditd_relay_signal) == SIG_ERR) { 387 auditd_log_err( 388 "Could not set signal handler for SIGTERM"); 389 fail_exit(); 390 } 391 if (signal(SIGCHLD, auditd_relay_signal) == SIG_ERR) { 392 auditd_log_err( 393 "Could not set signal handler for SIGCHLD"); 394 fail_exit(); 395 } 396 if (signal(SIGHUP, auditd_relay_signal) == SIG_ERR) { 397 auditd_log_err( 398 "Could not set signal handler for SIGHUP"); 399 fail_exit(); 400 } 401 if (signal(SIGALRM, auditd_relay_signal) == SIG_ERR) { 402 auditd_log_err( 403 "Could not set signal handler for SIGALRM"); 404 fail_exit(); 405 } 406 407 if ((pidfile = fopen(AUDITD_PIDFILE, "a")) == NULL) { 408 auditd_log_err("Could not open PID file"); 409 audit_warn_tmpfile(); 410 return (-1); 411 } 412 413 /* Attempt to lock the pid file; if a lock is present, exit. */ 414 fd = fileno(pidfile); 415 if (flock(fd, LOCK_EX | LOCK_NB) < 0) { 416 auditd_log_err( 417 "PID file is locked (is another auditd running?)."); 418 audit_warn_ebusy(); 419 return (-1); 420 } 421 422 pid = getpid(); 423 ftruncate(fd, 0); 424 if (fprintf(pidfile, "%u\n", pid) < 0) { 425 /* Should not start the daemon. */ 426 fail_exit(); 427 } 428 429 fflush(pidfile); 430 return (0); 431} 432 433/* 434 * Handle the audit trigger event. 435 * 436 * We suppress (ignore) duplicated triggers in close succession in order to 437 * try to avoid thrashing-like behavior. However, not all triggers can be 438 * ignored, as triggers generally represent edge triggers, not level 439 * triggers, and won't be retransmitted if the condition persists. Of 440 * specific concern is the rotate trigger -- if one is dropped, then it will 441 * not be retransmitted, and the log file will grow in an unbounded fashion. 442 */ 443#define DUPLICATE_INTERVAL 30 444void 445auditd_handle_trigger(int trigger) 446{ 447 static int last_trigger, last_warning; 448 static time_t last_time; 449 struct timeval ts; 450 struct timezone tzp; 451 time_t tt; 452 int au_state; 453 int err = 0; 454 455 /* 456 * Suppress duplicate messages from the kernel within the specified 457 * interval. 458 */ 459 if (gettimeofday(&ts, &tzp) == 0) { 460 tt = (time_t)ts.tv_sec; 461 switch (trigger) { 462 case AUDIT_TRIGGER_LOW_SPACE: 463 case AUDIT_TRIGGER_NO_SPACE: 464 /* 465 * Triggers we can suppress. Of course, we also need 466 * to rate limit the warnings, so apply the same 467 * interval limit on syslog messages. 468 */ 469 if ((trigger == last_trigger) && 470 (tt < (last_time + DUPLICATE_INTERVAL))) { 471 if (tt >= (last_warning + DUPLICATE_INTERVAL)) 472 auditd_log_info( 473 "Suppressing duplicate trigger %d", 474 trigger); 475 return; 476 } 477 last_warning = tt; 478 break; 479 480 case AUDIT_TRIGGER_ROTATE_KERNEL: 481 case AUDIT_TRIGGER_ROTATE_USER: 482 case AUDIT_TRIGGER_READ_FILE: 483 case AUDIT_TRIGGER_CLOSE_AND_DIE: 484 case AUDIT_TRIGGER_INITIALIZE: 485 /* 486 * Triggers that we cannot suppress. 487 */ 488 break; 489 } 490 491 /* 492 * Only update last_trigger after aborting due to a duplicate 493 * trigger, not before, or we will never allow that trigger 494 * again. 495 */ 496 last_trigger = trigger; 497 last_time = tt; 498 } 499 500 au_state = auditd_get_state(); 501 502 /* 503 * Message processing is done here. 504 */ 505 switch(trigger) { 506 case AUDIT_TRIGGER_LOW_SPACE: 507 auditd_log_notice("Got low space trigger"); 508 if (do_trail_file() == -1) 509 auditd_log_err("Error swapping audit file"); 510 break; 511 512 case AUDIT_TRIGGER_NO_SPACE: 513 auditd_log_notice("Got no space trigger"); 514 if (do_trail_file() == -1) 515 auditd_log_err("Error swapping audit file"); 516 break; 517 518 case AUDIT_TRIGGER_ROTATE_KERNEL: 519 case AUDIT_TRIGGER_ROTATE_USER: 520 auditd_log_info("Got open new trigger from %s", trigger == 521 AUDIT_TRIGGER_ROTATE_KERNEL ? "kernel" : "user"); 522 if (au_state == AUD_STATE_ENABLED && do_trail_file() == -1) 523 auditd_log_err("Error swapping audit file"); 524 break; 525 526 case AUDIT_TRIGGER_READ_FILE: 527 auditd_log_info("Got read file trigger"); 528 if (au_state == AUD_STATE_ENABLED && 529 auditd_config_controls() == -1) 530 auditd_log_err("Error setting audit controls"); 531 break; 532 533 case AUDIT_TRIGGER_CLOSE_AND_DIE: 534 auditd_log_info("Got close and die trigger"); 535 if (au_state == AUD_STATE_ENABLED) 536 err = close_all(); 537 /* 538 * Running under launchd don't exit. Wait for launchd to 539 * send SIGTERM. 540 */ 541 if (!launchd_flag) { 542 auditd_log_info("auditd exiting."); 543 exit (err); 544 } 545 break; 546 547 case AUDIT_TRIGGER_INITIALIZE: 548 auditd_log_info("Got audit initialize trigger"); 549 if (au_state == AUD_STATE_DISABLED) 550 audit_setup(); 551 break; 552
| 290 return (0); 291} 292 293/* 294 * Start up auditing. 295 */ 296static void 297audit_setup(void) 298{ 299 int err; 300 301 if (do_trail_file() == -1) { 302 auditd_log_err("Error creating audit trail file"); 303 fail_exit(); 304 } 305 306 /* Generate an audit record. */ 307 err = auditd_gen_record(AUE_audit_startup, NULL); 308 if (err) 309 auditd_log_err("auditd_gen_record(AUE_audit_startup) %s: %m", 310 auditd_strerror(err)); 311 312 if (auditd_config_controls() == 0) 313 auditd_log_info("Audit controls init successful"); 314 else 315 auditd_log_err("Audit controls init failed"); 316 317} 318 319 320/* 321 * Close auditd pid file and trigger mechanism. 322 */ 323static int 324close_misc(void) 325{ 326 327 auditd_close_dirs(); 328 if (unlink(AUDITD_PIDFILE) == -1 && errno != ENOENT) { 329 auditd_log_err("Couldn't remove %s: %m", AUDITD_PIDFILE); 330 return (1); 331 } 332 endac(); 333 334 if (auditd_close_trigger() != 0) { 335 auditd_log_err("Error closing trigger messaging mechanism"); 336 return (1); 337 } 338 return (0); 339} 340 341/* 342 * Close all log files, control files, and tell the audit system. 343 */ 344static int 345close_all(void) 346{ 347 int err_ret = 0; 348 char TS[TIMESTAMP_LEN]; 349 int err; 350 long cond; 351 time_t tt; 352 353 err = auditd_gen_record(AUE_audit_shutdown, NULL); 354 if (err) 355 auditd_log_err("auditd_gen_record(AUE_audit_shutdown) %s: %m", 356 auditd_strerror(err)); 357 358 /* Flush contents. */ 359 cond = AUC_DISABLED; 360 err_ret = auditon(A_SETCOND, &cond, sizeof(cond)); 361 if (err_ret != 0) { 362 auditd_log_err("Disabling audit failed! : %s", strerror(errno)); 363 err_ret = 1; 364 } 365 366 /* 367 * Updated the cached state that auditing has been disabled. 368 */ 369 auditd_set_state(AUD_STATE_DISABLED); 370 371 if (getTSstr(tt, TS, TIMESTAMP_LEN) == 0) 372 close_lastfile(TS); 373 if (lastfile != NULL) 374 free(lastfile); 375 376 err_ret += close_misc(); 377 378 if (err_ret) { 379 auditd_log_err("Could not unregister"); 380 audit_warn_postsigterm(); 381 } 382 383 auditd_log_info("Finished"); 384 return (err_ret); 385} 386 387/* 388 * Register the daemon with the signal handler and the auditd pid file. 389 */ 390static int 391register_daemon(void) 392{ 393 FILE * pidfile; 394 int fd; 395 pid_t pid; 396 397 /* Set up the signal hander. */ 398 if (signal(SIGTERM, auditd_relay_signal) == SIG_ERR) { 399 auditd_log_err( 400 "Could not set signal handler for SIGTERM"); 401 fail_exit(); 402 } 403 if (signal(SIGCHLD, auditd_relay_signal) == SIG_ERR) { 404 auditd_log_err( 405 "Could not set signal handler for SIGCHLD"); 406 fail_exit(); 407 } 408 if (signal(SIGHUP, auditd_relay_signal) == SIG_ERR) { 409 auditd_log_err( 410 "Could not set signal handler for SIGHUP"); 411 fail_exit(); 412 } 413 if (signal(SIGALRM, auditd_relay_signal) == SIG_ERR) { 414 auditd_log_err( 415 "Could not set signal handler for SIGALRM"); 416 fail_exit(); 417 } 418 419 if ((pidfile = fopen(AUDITD_PIDFILE, "a")) == NULL) { 420 auditd_log_err("Could not open PID file"); 421 audit_warn_tmpfile(); 422 return (-1); 423 } 424 425 /* Attempt to lock the pid file; if a lock is present, exit. */ 426 fd = fileno(pidfile); 427 if (flock(fd, LOCK_EX | LOCK_NB) < 0) { 428 auditd_log_err( 429 "PID file is locked (is another auditd running?)."); 430 audit_warn_ebusy(); 431 return (-1); 432 } 433 434 pid = getpid(); 435 ftruncate(fd, 0); 436 if (fprintf(pidfile, "%u\n", pid) < 0) { 437 /* Should not start the daemon. */ 438 fail_exit(); 439 } 440 441 fflush(pidfile); 442 return (0); 443} 444 445/* 446 * Handle the audit trigger event. 447 * 448 * We suppress (ignore) duplicated triggers in close succession in order to 449 * try to avoid thrashing-like behavior. However, not all triggers can be 450 * ignored, as triggers generally represent edge triggers, not level 451 * triggers, and won't be retransmitted if the condition persists. Of 452 * specific concern is the rotate trigger -- if one is dropped, then it will 453 * not be retransmitted, and the log file will grow in an unbounded fashion. 454 */ 455#define DUPLICATE_INTERVAL 30 456void 457auditd_handle_trigger(int trigger) 458{ 459 static int last_trigger, last_warning; 460 static time_t last_time; 461 struct timeval ts; 462 struct timezone tzp; 463 time_t tt; 464 int au_state; 465 int err = 0; 466 467 /* 468 * Suppress duplicate messages from the kernel within the specified 469 * interval. 470 */ 471 if (gettimeofday(&ts, &tzp) == 0) { 472 tt = (time_t)ts.tv_sec; 473 switch (trigger) { 474 case AUDIT_TRIGGER_LOW_SPACE: 475 case AUDIT_TRIGGER_NO_SPACE: 476 /* 477 * Triggers we can suppress. Of course, we also need 478 * to rate limit the warnings, so apply the same 479 * interval limit on syslog messages. 480 */ 481 if ((trigger == last_trigger) && 482 (tt < (last_time + DUPLICATE_INTERVAL))) { 483 if (tt >= (last_warning + DUPLICATE_INTERVAL)) 484 auditd_log_info( 485 "Suppressing duplicate trigger %d", 486 trigger); 487 return; 488 } 489 last_warning = tt; 490 break; 491 492 case AUDIT_TRIGGER_ROTATE_KERNEL: 493 case AUDIT_TRIGGER_ROTATE_USER: 494 case AUDIT_TRIGGER_READ_FILE: 495 case AUDIT_TRIGGER_CLOSE_AND_DIE: 496 case AUDIT_TRIGGER_INITIALIZE: 497 /* 498 * Triggers that we cannot suppress. 499 */ 500 break; 501 } 502 503 /* 504 * Only update last_trigger after aborting due to a duplicate 505 * trigger, not before, or we will never allow that trigger 506 * again. 507 */ 508 last_trigger = trigger; 509 last_time = tt; 510 } 511 512 au_state = auditd_get_state(); 513 514 /* 515 * Message processing is done here. 516 */ 517 switch(trigger) { 518 case AUDIT_TRIGGER_LOW_SPACE: 519 auditd_log_notice("Got low space trigger"); 520 if (do_trail_file() == -1) 521 auditd_log_err("Error swapping audit file"); 522 break; 523 524 case AUDIT_TRIGGER_NO_SPACE: 525 auditd_log_notice("Got no space trigger"); 526 if (do_trail_file() == -1) 527 auditd_log_err("Error swapping audit file"); 528 break; 529 530 case AUDIT_TRIGGER_ROTATE_KERNEL: 531 case AUDIT_TRIGGER_ROTATE_USER: 532 auditd_log_info("Got open new trigger from %s", trigger == 533 AUDIT_TRIGGER_ROTATE_KERNEL ? "kernel" : "user"); 534 if (au_state == AUD_STATE_ENABLED && do_trail_file() == -1) 535 auditd_log_err("Error swapping audit file"); 536 break; 537 538 case AUDIT_TRIGGER_READ_FILE: 539 auditd_log_info("Got read file trigger"); 540 if (au_state == AUD_STATE_ENABLED && 541 auditd_config_controls() == -1) 542 auditd_log_err("Error setting audit controls"); 543 break; 544 545 case AUDIT_TRIGGER_CLOSE_AND_DIE: 546 auditd_log_info("Got close and die trigger"); 547 if (au_state == AUD_STATE_ENABLED) 548 err = close_all(); 549 /* 550 * Running under launchd don't exit. Wait for launchd to 551 * send SIGTERM. 552 */ 553 if (!launchd_flag) { 554 auditd_log_info("auditd exiting."); 555 exit (err); 556 } 557 break; 558 559 case AUDIT_TRIGGER_INITIALIZE: 560 auditd_log_info("Got audit initialize trigger"); 561 if (au_state == AUD_STATE_DISABLED) 562 audit_setup(); 563 break; 564
|
| 565 case AUDIT_TRIGGER_EXPIRE_TRAILS: 566 auditd_log_info("Got audit expire trails trigger"); 567 err = auditd_expire_trails(audit_warn_expired); 568 if (err) 569 auditd_log_err("auditd_expire_trails(): %s", 570 auditd_strerror(err)); 571 break; 572
|
553 default: 554 auditd_log_err("Got unknown trigger %d", trigger); 555 break; 556 } 557} 558 559/* 560 * Reap our children. 561 */ 562void 563auditd_reap_children(void) 564{ 565 pid_t child; 566 int wstatus; 567 568 while ((child = waitpid(-1, &wstatus, WNOHANG)) > 0) { 569 if (!wstatus) 570 continue; 571 auditd_log_info("warn process [pid=%d] %s %d.", child, 572 ((WIFEXITED(wstatus)) ? "exited with non-zero status" : 573 "exited as a result of signal"), 574 ((WIFEXITED(wstatus)) ? WEXITSTATUS(wstatus) : 575 WTERMSIG(wstatus))); 576 } 577} 578 579/* 580 * Reap any children and terminate. If under launchd don't shutdown auditing 581 * but just the other stuff. 582 */ 583void 584auditd_terminate(void) 585{ 586 int ret; 587 588 auditd_reap_children(); 589 590 if (launchd_flag) 591 ret = close_misc(); 592 else 593 ret = close_all(); 594 595 exit(ret); 596} 597 598/* 599 * Configure the audit controls in the kernel: the event to class mapping, 600 * kernel preselection mask, etc. 601 */ 602int 603auditd_config_controls(void) 604{ 605 int cnt, err; 606 int ret = 0; 607 608 /* 609 * Configure event to class mappings in kernel. 610 */ 611 cnt = auditd_set_evcmap(); 612 if (cnt < 0) { 613 auditd_log_err("auditd_set_evcmap() failed: %m"); 614 ret = -1; 615 } else if (cnt == 0) { 616 auditd_log_err("No events to class mappings registered."); 617 ret = -1; 618 } else 619 auditd_log_debug("Registered %d event to class mappings.", cnt); 620 621 /* 622 * Configure non-attributable event mask in kernel. 623 */ 624 err = auditd_set_namask(); 625 if (err) { 626 auditd_log_err("auditd_set_namask() %s: %m", 627 auditd_strerror(err)); 628 ret = -1; 629 } else 630 auditd_log_debug("Registered non-attributable event mask."); 631 632 /* 633 * Configure audit policy in kernel. 634 */ 635 err = auditd_set_policy(); 636 if (err) { 637 auditd_log_err("auditd_set_policy() %s: %m", 638 auditd_strerror(err)); 639 ret = -1; 640 } else 641 auditd_log_debug("Set audit policy in kernel."); 642 643 /* 644 * Configure audit trail log size in kernel. 645 */ 646 err = auditd_set_fsize(); 647 if (err) { 648 auditd_log_err("audit_set_fsize() %s: %m", 649 auditd_strerror(err)); 650 ret = -1; 651 } else 652 auditd_log_debug("Set audit trail size in kernel."); 653 654 /* 655 * Configure audit trail volume minimum free percentage of blocks in 656 * kernel. 657 */ 658 err = auditd_set_minfree(); 659 if (err) { 660 auditd_log_err("auditd_set_minfree() %s: %m", 661 auditd_strerror(err)); 662 ret = -1; 663 } else 664 auditd_log_debug( 665 "Set audit trail min free percent in kernel."); 666 667 /* 668 * Configure host address in the audit kernel information. 669 */ 670 err = auditd_set_host(); 671 if (err) {
| 573 default: 574 auditd_log_err("Got unknown trigger %d", trigger); 575 break; 576 } 577} 578 579/* 580 * Reap our children. 581 */ 582void 583auditd_reap_children(void) 584{ 585 pid_t child; 586 int wstatus; 587 588 while ((child = waitpid(-1, &wstatus, WNOHANG)) > 0) { 589 if (!wstatus) 590 continue; 591 auditd_log_info("warn process [pid=%d] %s %d.", child, 592 ((WIFEXITED(wstatus)) ? "exited with non-zero status" : 593 "exited as a result of signal"), 594 ((WIFEXITED(wstatus)) ? WEXITSTATUS(wstatus) : 595 WTERMSIG(wstatus))); 596 } 597} 598 599/* 600 * Reap any children and terminate. If under launchd don't shutdown auditing 601 * but just the other stuff. 602 */ 603void 604auditd_terminate(void) 605{ 606 int ret; 607 608 auditd_reap_children(); 609 610 if (launchd_flag) 611 ret = close_misc(); 612 else 613 ret = close_all(); 614 615 exit(ret); 616} 617 618/* 619 * Configure the audit controls in the kernel: the event to class mapping, 620 * kernel preselection mask, etc. 621 */ 622int 623auditd_config_controls(void) 624{ 625 int cnt, err; 626 int ret = 0; 627 628 /* 629 * Configure event to class mappings in kernel. 630 */ 631 cnt = auditd_set_evcmap(); 632 if (cnt < 0) { 633 auditd_log_err("auditd_set_evcmap() failed: %m"); 634 ret = -1; 635 } else if (cnt == 0) { 636 auditd_log_err("No events to class mappings registered."); 637 ret = -1; 638 } else 639 auditd_log_debug("Registered %d event to class mappings.", cnt); 640 641 /* 642 * Configure non-attributable event mask in kernel. 643 */ 644 err = auditd_set_namask(); 645 if (err) { 646 auditd_log_err("auditd_set_namask() %s: %m", 647 auditd_strerror(err)); 648 ret = -1; 649 } else 650 auditd_log_debug("Registered non-attributable event mask."); 651 652 /* 653 * Configure audit policy in kernel. 654 */ 655 err = auditd_set_policy(); 656 if (err) { 657 auditd_log_err("auditd_set_policy() %s: %m", 658 auditd_strerror(err)); 659 ret = -1; 660 } else 661 auditd_log_debug("Set audit policy in kernel."); 662 663 /* 664 * Configure audit trail log size in kernel. 665 */ 666 err = auditd_set_fsize(); 667 if (err) { 668 auditd_log_err("audit_set_fsize() %s: %m", 669 auditd_strerror(err)); 670 ret = -1; 671 } else 672 auditd_log_debug("Set audit trail size in kernel."); 673 674 /* 675 * Configure audit trail volume minimum free percentage of blocks in 676 * kernel. 677 */ 678 err = auditd_set_minfree(); 679 if (err) { 680 auditd_log_err("auditd_set_minfree() %s: %m", 681 auditd_strerror(err)); 682 ret = -1; 683 } else 684 auditd_log_debug( 685 "Set audit trail min free percent in kernel."); 686 687 /* 688 * Configure host address in the audit kernel information. 689 */ 690 err = auditd_set_host(); 691 if (err) {
|
672 auditd_log_err("auditd_set_host() %s: %m", 673 auditd_strerror(err)); 674 ret = -1;
| 692 if (err == ADE_PARSE) { 693 auditd_log_notice( 694 "audit_control(5) may be missing 'host:' field"); 695 } else { 696 auditd_log_err("auditd_set_host() %s: %m", 697 auditd_strerror(err)); 698 ret = -1; 699 }
|
675 } else 676 auditd_log_debug( 677 "Set audit host address information in kernel.");
| 700 } else 701 auditd_log_debug( 702 "Set audit host address information in kernel.");
|
678
| 703
|
679 return (ret); 680} 681 682/* 683 * Setup and initialize auditd. 684 */ 685static void 686setup(void) 687{ 688 int err; 689 690 if (auditd_open_trigger(launchd_flag) < 0) { 691 auditd_log_err("Error opening trigger messaging mechanism"); 692 fail_exit(); 693 } 694 695 /* 696 * To prevent event feedback cycles and avoid auditd becoming 697 * stalled if auditing is suspended, auditd and its children run 698 * without their events being audited. We allow the uid, tid, and 699 * mask fields to be implicitly set to zero, but do set the pid. We 700 * run this after opening the trigger device to avoid configuring 701 * audit state without audit present in the system. 702 */ 703 err = auditd_prevent_audit(); 704 if (err) { 705 auditd_log_err("auditd_prevent_audit() %s: %m", 706 auditd_strerror(err)); 707 fail_exit(); 708 } 709 710 /* 711 * Make sure auditd auditing state is correct. 712 */ 713 auditd_set_state(AUD_STATE_INIT); 714 715 /* 716 * If under launchd, don't start auditing. Wait for a trigger to 717 * do so. 718 */ 719 if (!launchd_flag) 720 audit_setup(); 721} 722 723int 724main(int argc, char **argv) 725{ 726 int ch; 727 int debug = 0; 728#ifdef AUDIT_REVIEW_GROUP 729 struct group *grp; 730#endif 731 732 while ((ch = getopt(argc, argv, "dl")) != -1) { 733 switch(ch) { 734 case 'd': 735 /* Debug option. */ 736 debug = 1; 737 break; 738 739 case 'l': 740 /* Be launchd friendly. */ 741 launchd_flag = 1; 742 break; 743 744 case '?': 745 default: 746 (void)fprintf(stderr, 747 "usage: auditd [-d] [-l]\n"); 748 exit(1); 749 } 750 } 751 752 audit_review_gid = getgid(); 753 754#ifdef AUDIT_REVIEW_GROUP 755 /* 756 * XXXRW: Currently, this code falls back to the daemon gid, which is 757 * likely the wheel group. Is there a better way to deal with this? 758 */ 759 grp = getgrnam(AUDIT_REVIEW_GROUP); 760 if (grp != NULL) 761 audit_review_gid = grp->gr_gid; 762#endif 763 764 auditd_openlog(debug, audit_review_gid); 765 766 if (launchd_flag) 767 auditd_log_info("started by launchd..."); 768 else 769 auditd_log_info("starting..."); 770 771#ifdef AUDIT_REVIEW_GROUP 772 if (grp == NULL) 773 auditd_log_info( 774 "Audit review group '%s' not available, using daemon gid (%d)", 775 AUDIT_REVIEW_GROUP, audit_review_gid); 776#endif 777 if (debug == 0 && launchd_flag == 0 && daemon(0, 0) == -1) { 778 auditd_log_err("Failed to daemonize"); 779 exit(1); 780 } 781 782 if (register_daemon() == -1) { 783 auditd_log_err("Could not register as daemon"); 784 exit(1); 785 } 786 787 setup(); 788 789 /* 790 * auditd_wait_for_events() shouldn't return unless something is wrong. 791 */ 792 auditd_wait_for_events(); 793 794 auditd_log_err("abnormal exit."); 795 close_all(); 796 exit(-1); 797}
| 704 return (ret); 705} 706 707/* 708 * Setup and initialize auditd. 709 */ 710static void 711setup(void) 712{ 713 int err; 714 715 if (auditd_open_trigger(launchd_flag) < 0) { 716 auditd_log_err("Error opening trigger messaging mechanism"); 717 fail_exit(); 718 } 719 720 /* 721 * To prevent event feedback cycles and avoid auditd becoming 722 * stalled if auditing is suspended, auditd and its children run 723 * without their events being audited. We allow the uid, tid, and 724 * mask fields to be implicitly set to zero, but do set the pid. We 725 * run this after opening the trigger device to avoid configuring 726 * audit state without audit present in the system. 727 */ 728 err = auditd_prevent_audit(); 729 if (err) { 730 auditd_log_err("auditd_prevent_audit() %s: %m", 731 auditd_strerror(err)); 732 fail_exit(); 733 } 734 735 /* 736 * Make sure auditd auditing state is correct. 737 */ 738 auditd_set_state(AUD_STATE_INIT); 739 740 /* 741 * If under launchd, don't start auditing. Wait for a trigger to 742 * do so. 743 */ 744 if (!launchd_flag) 745 audit_setup(); 746} 747 748int 749main(int argc, char **argv) 750{ 751 int ch; 752 int debug = 0; 753#ifdef AUDIT_REVIEW_GROUP 754 struct group *grp; 755#endif 756 757 while ((ch = getopt(argc, argv, "dl")) != -1) { 758 switch(ch) { 759 case 'd': 760 /* Debug option. */ 761 debug = 1; 762 break; 763 764 case 'l': 765 /* Be launchd friendly. */ 766 launchd_flag = 1; 767 break; 768 769 case '?': 770 default: 771 (void)fprintf(stderr, 772 "usage: auditd [-d] [-l]\n"); 773 exit(1); 774 } 775 } 776 777 audit_review_gid = getgid(); 778 779#ifdef AUDIT_REVIEW_GROUP 780 /* 781 * XXXRW: Currently, this code falls back to the daemon gid, which is 782 * likely the wheel group. Is there a better way to deal with this? 783 */ 784 grp = getgrnam(AUDIT_REVIEW_GROUP); 785 if (grp != NULL) 786 audit_review_gid = grp->gr_gid; 787#endif 788 789 auditd_openlog(debug, audit_review_gid); 790 791 if (launchd_flag) 792 auditd_log_info("started by launchd..."); 793 else 794 auditd_log_info("starting..."); 795 796#ifdef AUDIT_REVIEW_GROUP 797 if (grp == NULL) 798 auditd_log_info( 799 "Audit review group '%s' not available, using daemon gid (%d)", 800 AUDIT_REVIEW_GROUP, audit_review_gid); 801#endif 802 if (debug == 0 && launchd_flag == 0 && daemon(0, 0) == -1) { 803 auditd_log_err("Failed to daemonize"); 804 exit(1); 805 } 806 807 if (register_daemon() == -1) { 808 auditd_log_err("Could not register as daemon"); 809 exit(1); 810 } 811 812 setup(); 813 814 /* 815 * auditd_wait_for_events() shouldn't return unless something is wrong. 816 */ 817 auditd_wait_for_events(); 818 819 auditd_log_err("abnormal exit."); 820 close_all(); 821 exit(-1); 822}
|