Mercurial > illumos > illumos-gate
changeset 5007:51890a00057d
6411336 audit_binfile(5) creates an empty audit trail file on startup
6430878 audit_binfile(5) doesn't rotate the audit.log at all
6483684 auditd drops audit records when the allhard condition is reached and continue policy is not set
6492045 auditd does not honor its 20second interval if log file system is full
6555845 auditd creates audit files in / if no directory specified in audit_control
author | paulson |
---|---|
date | Fri, 07 Sep 2007 02:20:59 -0700 |
parents | 304eb1332eef |
children | 4ceab57ff7f2 |
files | usr/src/cmd/audit/audit.c usr/src/cmd/audit_warn/audit_warn.sh usr/src/cmd/auditd/doorway.c usr/src/lib/auditd_plugins/binfile/binfile.c usr/src/lib/libbsm/common/getacval.c |
diffstat | 5 files changed, 128 insertions(+), 78 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/cmd/audit/audit.c Thu Sep 06 19:30:39 2007 -0700 +++ b/usr/src/cmd/audit/audit.c Fri Sep 07 02:20:59 2007 -0700 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" @@ -217,7 +217,8 @@ int rc; int min; kva_t *kvlist; - char *value; + char *plugin_name; + char *plugin_dir; au_acinfo_t *ach; ach = _openac(filename); /* open audit_control */ @@ -242,18 +243,29 @@ * _getacplug -- all that is of interest is the return code. */ _rewindac(ach); /* rewind audit_control */ - if ((rc = _getacplug(ach, &kvlist)) == 0) { - value = kva_match(kvlist, "name"); - if (value == NULL) { + while ((rc = _getacplug(ach, &kvlist)) == 0) { + plugin_name = kva_match(kvlist, "name"); + if (plugin_name == NULL) { (void) fprintf(stderr, gettext("%s: audit_control " "\"plugin:\" missing name\n"), progname); state = 0; /* is_not_ok */ + } else { + if (strcmp(plugin_name, "audit_binfile.so") == 0) { + plugin_dir = kva_match(kvlist, "p_dir"); + if ((plugin_dir == NULL) && (outputs == 0)) { + (void) fprintf(stderr, + gettext("%s: audit_control " + "\"plugin:\" missing p_dir\n"), + progname); + state = 0; /* is_not_ok */ + } else { + outputs++; + } + } } - else - outputs++; - _kva_free(kvlist); - } else if (rc < -1) { + } + if (rc < -1) { (void) fprintf(stderr, gettext("%s: audit_control \"plugin:\" spec invalid\n"), progname); @@ -262,7 +274,8 @@ if (outputs == 0) { (void) fprintf(stderr, gettext("%s: audit_control must have either a " - "\"dir:\" or a \"plugin:\" specified.\n"), + "valid \"dir:\" entry or a valid \"plugin:\" " + "entry with \"p_dir:\" specified.\n"), progname); state = 0; /* is_not_ok */ }
--- a/usr/src/cmd/audit_warn/audit_warn.sh Thu Sep 06 19:30:39 2007 -0700 +++ b/usr/src/cmd/audit_warn/audit_warn.sh Fri Sep 07 02:20:59 2007 -0700 @@ -3,9 +3,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -23,7 +22,7 @@ # # ident "%Z%%M% %I% %E% SMI" # -# Copyright 2003 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -246,12 +245,17 @@ exit 1 else COUNT=$2 + if [ $COUNT -eq 1 ]; then + S="" + else + S="s" + fi fi # Set message MESSAGE="There is a problem getting the directory\ - list from audit_control. The audit daemon will hang until this file is\ - fixed. This message has been displayed $COUNT times." + list or plugin list from audit_control(4). The audit daemon will hang + until this file is fixed. This message has been displayed $COUNT time$S." send_msg break ;; @@ -292,6 +296,11 @@ exit 1 else COUNT=$5 + if [ $COUNT -eq 1 ]; then + S="" + else + S="s" + fi fi # Set message @@ -299,7 +308,7 @@ following problem with loading or executing plugins:\n\n\ $PLUGNAME: $ERROR\n\ $TEXT\n\ -This message has been displayed $COUNT times." +This message has been displayed $COUNT time$S." send_msg break ;;
--- a/usr/src/cmd/auditd/doorway.c Thu Sep 06 19:30:39 2007 -0700 +++ b/usr/src/cmd/auditd/doorway.c Fri Sep 07 02:20:59 2007 -0700 @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * */ @@ -588,7 +587,7 @@ audit_queue_init(&(p->plg_pool)); DPRINT((dbfp, "qpool_init(%d) max, min, threshhold = %d, %d, %d\n", - p->plg_tid, p->plg_qmax, p->plg_qmin, threshold)); + p->plg_tid, p->plg_qmax, p->plg_qmin, threshold)); if (p->plg_qmax > largest_queue) largest_queue = p->plg_qmax; @@ -707,8 +706,8 @@ rc = audit_dequeue(&b_pool, (void *)&node); DPRINT((dbfp, "bpool_withdraw buf length=%d," - " requested size=%d, dequeue rc=%d\n", - new_length, request_size, rc)); + " requested size=%d, dequeue rc=%d\n", + new_length, request_size, rc)); if (rc == 0) { DPRINT((dbfp, "bpool_withdraw node=%X (pool=%d)\n", node, @@ -911,8 +910,7 @@ audit_q_t *q_copy; boolean_t referenced = 0; static char *invalid_msg = "invalid audit record discarded"; - static char *invalid_control = - "invalid audit control discarded"; + static char *invalid_control = "invalid audit control discarded"; static audit_rec_t *alt_b_copy = NULL; static size_t alt_length; @@ -1196,6 +1194,7 @@ int sendsignal; int queue_len; struct sched_param param; + static boolean_t once = B_FALSE; DPRINT((dbfp, "%s is thread %d\n", p->plg_path, p->plg_tid)); p->plg_priority = param.sched_priority = BASE_PRIORITY; @@ -1204,8 +1203,6 @@ delay.tv_nsec = 0; for (;;) { - retry_mode: - while (audit_dequeue(&(p->plg_queue), (void *)&q_node) != 0) { DUMP("process", p, p->plg_last_seq_out, "blocked"); (void) pthread_cond_signal(&(in_thr.thd_cv)); @@ -1218,12 +1215,10 @@ (void) pthread_mutex_unlock(&(p->plg_mutex)); if (p->plg_removed) - break; + goto plugin_removed; DUMP("process", p, p->plg_last_seq_out, "unblocked"); } - if (p->plg_removed) - break; #if DEBUG if (q_node->aqq_sequence != p->plg_last_seq_out + 1) (void) fprintf(dbfp, @@ -1234,15 +1229,21 @@ error_string = NULL; b_node = q_node->aqq_data; +retry_mode: plugrc = p->plg_fplugin(b_node->abq_buffer, - b_node->abq_data_len, - q_node->aqq_sequence, &error_string); + b_node->abq_data_len, q_node->aqq_sequence, &error_string); + + if (p->plg_removed) + goto plugin_removed; #if DEBUG p->plg_last_seq_out = q_node->aqq_sequence; #endif switch (plugrc) { case AUDITD_RETRY: - report_error(plugrc, error_string, p->plg_path); + if (!once) { + report_error(plugrc, error_string, p->plg_path); + once = B_TRUE; + } free(error_string); error_string = NULL; @@ -1257,7 +1258,7 @@ (void) pthread_mutex_lock(&(p->plg_mutex)); p->plg_waiting++; (void) pthread_cond_reltimedwait_np(&(p->plg_cv), - &(p->plg_mutex), &delay); + &(p->plg_mutex), &delay); p->plg_waiting--; (void) pthread_mutex_unlock(&(p->plg_mutex)); @@ -1266,6 +1267,7 @@ case AUDITD_SUCCESS: p->plg_output++; + once = B_FALSE; break; default: report_error(plugrc, error_string, p->plg_path); @@ -1303,6 +1305,7 @@ ¶m); } } /* end for (;;) */ +plugin_removed: DUMP("process", p, p->plg_last_seq_out, "exit"); error_string = NULL; if ((rc = p->plg_fplugin_close(&error_string)) !=
--- a/usr/src/lib/auditd_plugins/binfile/binfile.c Thu Sep 06 19:30:39 2007 -0700 +++ b/usr/src/lib/auditd_plugins/binfile/binfile.c Fri Sep 07 02:20:59 2007 -0700 @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * write binary audit records directly to a file. @@ -73,12 +72,13 @@ #define SOFT_SPACE 0 /* minfree or less space available */ #define PLENTY_SPACE 1 /* more than minfree available */ #define SPACE_FULL 2 /* out of space */ -#define STAY_FULL 3 /* unusable file system */ #define AVAIL_MIN 50 /* If there are less that this number */ /* of blocks avail, the filesystem is */ /* presumed full. */ +#define ALLHARD_DELAY 20 /* Call audit_warn(allhard) every 20 seconds */ + /* * The directory list is a circular linked list. It is pointed into by @@ -114,9 +114,10 @@ static int minfreeblocks; /* minfree in blocks */ static dirlist_t *activeDir = NULL; /* current directory */ +static dirlist_t *startdir; /* first dir in the ring */ static int activeCount = 0; /* number of dirs in the ring */ -static int openNewFile = 1; /* need to open a new file */ +static int openNewFile = 0; /* need to open a new file */ static int hung_count = 0; /* count of audit_warn hard */ /* flag from audit_plugin_open to audit_plugin_close */ @@ -253,7 +254,7 @@ /* at least one directory is needed */ while ((acresult = _getacdir(ach, buf, sizeof (buf))) == 0 || - acresult == 2 || acresult == -3) { + acresult == 2 || acresult == -3) { /* * loop if the result is 0 (success), 2 (a warning * that the audit_data file has been rewound), @@ -370,11 +371,14 @@ if (rc == -2) { (void) pthread_mutex_lock(&log_mutex); DPRINT((dbfp, "loadauditlist: close / open log\n")); - if (open_log(listhead) == 0) + if (open_log(listhead) == 0) { openNewFile = 1; /* try again later */ + } else { + openNewFile = 0; + } freedirlist(activeList); /* old list */ activeList = listhead; /* new list */ - activeDir = thisdir; + activeDir = startdir = thisdir; activeCount = node_count; (void) pthread_mutex_unlock(&log_mutex); } else @@ -426,8 +430,8 @@ * tzfile.h . */ (void) sprintf(date, "%.4d%.2d%.2d%.2d%.2d%.2d", - tm.tm_year + TM_YEAR_BASE, tm.tm_mon + 1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec); + tm.tm_year + TM_YEAR_BASE, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); } @@ -598,7 +602,7 @@ name = (char *)strrchr(oldname, '/') + 1; (void) memcpy(name + AUDIT_DATE_SZ + 1, auditdate, - AUDIT_DATE_SZ); + AUDIT_DATE_SZ); close_log(lastOpenDir, oldname, newname); } @@ -661,10 +665,7 @@ assert(thisdir != NULL); - if (thisdir->dl_space == STAY_FULL) { - thisdir->dl_space = SPACE_FULL; - minfreeblocks = AVAIL_MIN; - } else if (statvfs(thisdir->dl_dirname, &sb) < 0) { + if (statvfs(thisdir->dl_dirname, &sb) < 0) { thisdir->dl_space = SPACE_FULL; minfreeblocks = AVAIL_MIN; return (-1); @@ -673,9 +674,10 @@ if (sb.f_bavail < AVAIL_MIN) thisdir->dl_space = SPACE_FULL; - else if (sb.f_bavail > minfreeblocks) - thisdir->dl_space = PLENTY_SPACE; - else + else if (sb.f_bavail > minfreeblocks) { + thisdir->dl_space = fullness_state = PLENTY_SPACE; + ignore_size = 0; + } else thisdir->dl_space = SOFT_SPACE; } if (thisdir->dl_space == PLENTY_SPACE) @@ -685,10 +687,12 @@ } /* - * auditd_plugin() writes a buffer to the currently open file The - * global "openNewFile" is used to force a new log file for the - * initial open; for "audit -s" with changed audit_control data or - * "audit -n" the new log file is opened immediately. + * auditd_plugin() writes a buffer to the currently open file. The + * global "openNewFile" is used to force a new log file for cases + * such as the initial open, when minfree is reached or the current + * file system fills up, and "audit -s" with changed audit_control + * data. For "audit -n" a new log file is opened immediately in + * auditd_plugin_open(). * * This function manages one or more audit directories as follows: * @@ -713,14 +717,15 @@ auditd_plugin(const char *input, size_t in_len, uint32_t sequence, char **error) { auditd_rc_t rc = AUDITD_FAIL; - dirlist_t *startdir; int open_status; size_t out_len; /* LINTED */ int statrc; /* avoid excess audit_warnage */ - static int somesoftfull_warning = 0; static int allsoftfull_warning = 0; + static int allhard_pause = 0; + static struct timeval next_allhard; + struct timeval now; #if DEBUG static char *last_file_written_to = NULL; static uint32_t last_sequence = 0; @@ -728,18 +733,17 @@ if ((last_sequence > 0) && (sequence != last_sequence + 1)) fprintf(dbfp, "binfile: buffer sequence=%d but prev=%d=n", - sequence, last_sequence); + sequence, last_sequence); last_sequence = sequence; fprintf(dbfp, "binfile: input seq=%d, len=%d\n", - sequence, in_len); + sequence, in_len); #endif *error = NULL; /* * lock is for activeDir, referenced by open_log() and close_log() */ (void) pthread_mutex_lock(&log_mutex); - startdir = activeDir; while (rc == AUDITD_FAIL) { open_status = 1; if (openNewFile) { @@ -781,12 +785,11 @@ " l=%u\n", ++write_count, sequence, out_len)); allsoftfull_warning = 0; - if (fullness_state == PLENTY_SPACE) - somesoftfull_warning = 0; + activeDir->dl_flags = 0; rc = AUDITD_SUCCESS; break; - } else if (!activeDir->dl_flags & HARD_WARNED) { + } else if (!(activeDir->dl_flags & HARD_WARNED)) { DPRINT((dbfp, "binfile: write failed, sequence=%u, " "l=%u\n", sequence, out_len)); @@ -799,18 +802,18 @@ } else { DPRINT((dbfp, "binfile: statrc=%d, fullness_state=%d\n", statrc, fullness_state)); - somesoftfull_warning++; - if ((somesoftfull_warning <= activeCount) && - !(activeDir->dl_flags & SOFT_WARNED)) { + if (!(activeDir->dl_flags & SOFT_WARNED) && + (activeDir->dl_space == SOFT_SPACE)) { DPRINT((dbfp, "soft warning sent\n")); __audit_dowarn("soft", activeDir->dl_dirname, 0); activeDir->dl_flags |= SOFT_WARNED; } - if (!activeDir->dl_flags & HARD_WARNED) { + if (!(activeDir->dl_flags & HARD_WARNED) && + (activeDir->dl_space == SPACE_FULL)) { DPRINT((dbfp, "hard warning sent.\n")); __audit_dowarn("hard", - activeDir->dl_dirname, 0); + activeDir->dl_dirname, 0); activeDir->dl_flags |= HARD_WARNED; } } @@ -818,6 +821,7 @@ activeDir->dl_dirname, activeDir->dl_next->dl_dirname)); activeDir = activeDir->dl_next; + openNewFile = 1; if (activeDir == startdir) { /* full circle */ if (fullness_state == PLENTY_SPACE) { /* once */ @@ -827,7 +831,24 @@ __audit_dowarn("allsoft", "", 0); } } else { /* full circle twice */ - __audit_dowarn("allhard", "", ++hung_count); + if ((hung_count > 0) && !allhard_pause) { + allhard_pause = 1; + (void) gettimeofday(&next_allhard, + NULL); + next_allhard.tv_sec += ALLHARD_DELAY; + } + + if (allhard_pause) { + (void) gettimeofday(&now, NULL); + if (now.tv_sec >= next_allhard.tv_sec) { + allhard_pause = 0; + __audit_dowarn("allhard", "", + ++hung_count); + } + } else { + __audit_dowarn("allhard", "", + ++hung_count); + } minfreeblocks = AVAIL_MIN; rc = AUDITD_RETRY; *error = strdup(gettext( @@ -913,7 +934,7 @@ } else { /* status is 0 or -2 (no change or changed) */ hung_count = 0; DPRINT((dbfp, "binfile: loadauditlist returned %d\n", - status)); + status)); } break; case 1: /* audit -n */
--- a/usr/src/lib/libbsm/common/getacval.c Thu Sep 06 19:30:39 2007 -0700 +++ b/usr/src/lib/libbsm/common/getacval.c Fri Sep 07 02:20:59 2007 -0700 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" @@ -217,10 +217,14 @@ if (retstat >= SUCCESS) do { if (getlongline(entry, REALLY_LONG_LINE, context->fp) != NULL) { if (*entry == 'd') { - retstat = getvalue(dir, entry, DIRLABEL, - len); - if (retstat == SUCCESS) - gotone = 1; + retstat = getvalue(dir, entry, DIRLABEL, len); + if (retstat == SUCCESS) { + if (strlen(dir) == 0) { + retstat = FORMAT_ERR; + } else { + gotone = 1; + } + } } } else if ((feof(context->fp)) == 0) { retstat = ERROR;