10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
54165Stz204579 * Common Development and Distribution License (the "License").
64165Stz204579 * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
2212617SMarek.Pospisil@Sun.COM * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate */
240Sstevel@tonic-gate
2512617SMarek.Pospisil@Sun.COM /*
2612617SMarek.Pospisil@Sun.COM * Routines for writing audit records.
2712617SMarek.Pospisil@Sun.COM */
280Sstevel@tonic-gate
290Sstevel@tonic-gate #include <sys/door.h>
300Sstevel@tonic-gate #include <sys/param.h>
310Sstevel@tonic-gate #include <sys/time.h>
320Sstevel@tonic-gate #include <sys/types.h>
330Sstevel@tonic-gate #include <sys/statvfs.h> /* for statfs */
340Sstevel@tonic-gate #include <sys/vnode.h>
350Sstevel@tonic-gate #include <sys/file.h>
360Sstevel@tonic-gate #include <sys/vfs.h>
370Sstevel@tonic-gate #include <sys/user.h>
380Sstevel@tonic-gate #include <sys/uio.h>
390Sstevel@tonic-gate #include <sys/reboot.h>
400Sstevel@tonic-gate #include <sys/kmem.h> /* for KM_SLEEP */
410Sstevel@tonic-gate #include <sys/resource.h> /* for RLIM_INFINITY */
420Sstevel@tonic-gate #include <sys/cmn_err.h> /* panic */
430Sstevel@tonic-gate #include <sys/systm.h>
440Sstevel@tonic-gate #include <sys/debug.h>
450Sstevel@tonic-gate #include <sys/sysmacros.h>
460Sstevel@tonic-gate #include <sys/syscall.h>
470Sstevel@tonic-gate #include <sys/zone.h>
480Sstevel@tonic-gate
490Sstevel@tonic-gate #include <c2/audit.h>
500Sstevel@tonic-gate #include <c2/audit_kernel.h>
510Sstevel@tonic-gate #include <c2/audit_record.h>
520Sstevel@tonic-gate #include <c2/audit_kevents.h>
530Sstevel@tonic-gate #include <c2/audit_door_infc.h>
540Sstevel@tonic-gate
550Sstevel@tonic-gate static void au_dequeue(au_kcontext_t *, au_buff_t *);
560Sstevel@tonic-gate static void audit_async_finish_backend(void *);
570Sstevel@tonic-gate static int audit_sync_block(au_kcontext_t *);
580Sstevel@tonic-gate /*
590Sstevel@tonic-gate * each of these two tables are indexed by the values AU_DBUF_COMPLETE
600Sstevel@tonic-gate * through AU_DBUF_LAST; the content is the next state value. The
610Sstevel@tonic-gate * first table determines the next state for a buffer which is not the
620Sstevel@tonic-gate * end of a record and the second table determines the state for a
630Sstevel@tonic-gate * buffer which is the end of a record. The initial state is
640Sstevel@tonic-gate * AU_DBUF_COMPLETE.
650Sstevel@tonic-gate */
660Sstevel@tonic-gate static int state_if_part[] = {
670Sstevel@tonic-gate AU_DBUF_FIRST, AU_DBUF_MIDDLE, AU_DBUF_MIDDLE, AU_DBUF_FIRST};
680Sstevel@tonic-gate static int state_if_not_part[] = {
690Sstevel@tonic-gate AU_DBUF_COMPLETE, AU_DBUF_LAST, AU_DBUF_LAST, AU_DBUF_COMPLETE};
700Sstevel@tonic-gate /*
710Sstevel@tonic-gate * Write to an audit descriptor.
720Sstevel@tonic-gate * Add the au_membuf to the descriptor chain and free the chain passed in.
730Sstevel@tonic-gate */
740Sstevel@tonic-gate void
au_uwrite(m)750Sstevel@tonic-gate au_uwrite(m)
760Sstevel@tonic-gate token_t *m;
770Sstevel@tonic-gate {
780Sstevel@tonic-gate au_write(&(u_ad), m);
790Sstevel@tonic-gate }
800Sstevel@tonic-gate
810Sstevel@tonic-gate void
au_write(caddr_t * d,token_t * m)820Sstevel@tonic-gate au_write(caddr_t *d, token_t *m)
830Sstevel@tonic-gate {
840Sstevel@tonic-gate if (d == NULL) {
850Sstevel@tonic-gate au_toss_token(m);
860Sstevel@tonic-gate return;
870Sstevel@tonic-gate }
880Sstevel@tonic-gate if (m == (token_t *)0) {
890Sstevel@tonic-gate printf("au_write: null token\n");
900Sstevel@tonic-gate return;
910Sstevel@tonic-gate }
920Sstevel@tonic-gate
930Sstevel@tonic-gate if (*d == NULL)
940Sstevel@tonic-gate *d = (caddr_t)m;
950Sstevel@tonic-gate else
960Sstevel@tonic-gate (void) au_append_rec((au_buff_t *)*d, m, AU_PACK);
970Sstevel@tonic-gate }
980Sstevel@tonic-gate
990Sstevel@tonic-gate /*
1000Sstevel@tonic-gate * Close an audit descriptor.
1010Sstevel@tonic-gate * Use the second parameter to indicate if it should be written or not.
1020Sstevel@tonic-gate */
1030Sstevel@tonic-gate void
au_close(au_kcontext_t * kctx,caddr_t * d,int flag,au_event_t e_type,au_emod_t e_mod,timestruc_t * e_time)1047753STon.Nguyen@Sun.COM au_close(au_kcontext_t *kctx, caddr_t *d, int flag, au_event_t e_type,
10511861SMarek.Pospisil@Sun.COM au_emod_t e_mod, timestruc_t *e_time)
1060Sstevel@tonic-gate {
1070Sstevel@tonic-gate token_t *dchain; /* au_membuf chain which is the tokens */
1080Sstevel@tonic-gate t_audit_data_t *tad = U2A(u);
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate ASSERT(tad != NULL);
1110Sstevel@tonic-gate ASSERT(d != NULL);
1120Sstevel@tonic-gate ASSERT(kctx != NULL);
1130Sstevel@tonic-gate
1140Sstevel@tonic-gate if ((dchain = (token_t *)*d) == (token_t *)NULL)
1150Sstevel@tonic-gate return;
1160Sstevel@tonic-gate
1170Sstevel@tonic-gate *d = NULL;
1180Sstevel@tonic-gate
1190Sstevel@tonic-gate /*
1200Sstevel@tonic-gate * If async then defer; or if requested, defer the closing/queueing to
1210Sstevel@tonic-gate * syscall end, unless no syscall is active or the syscall is _exit.
1220Sstevel@tonic-gate */
1230Sstevel@tonic-gate if ((flag & AU_DONTBLOCK) || ((flag & AU_DEFER) &&
1240Sstevel@tonic-gate (tad->tad_scid != 0) && (tad->tad_scid != SYS_exit))) {
12511861SMarek.Pospisil@Sun.COM au_close_defer(dchain, flag, e_type, e_mod, e_time);
1260Sstevel@tonic-gate return;
1270Sstevel@tonic-gate }
12811861SMarek.Pospisil@Sun.COM au_close_time(kctx, dchain, flag, e_type, e_mod, e_time);
1290Sstevel@tonic-gate }
1300Sstevel@tonic-gate
1310Sstevel@tonic-gate /*
1320Sstevel@tonic-gate * Defer closing/queueing of an audit descriptor. For async events, queue
1330Sstevel@tonic-gate * via softcall. Otherwise, defer by queueing the record onto the tad; at
1340Sstevel@tonic-gate * syscall end time it will be pulled off.
1350Sstevel@tonic-gate */
1360Sstevel@tonic-gate void
au_close_defer(token_t * dchain,int flag,au_event_t e_type,au_emod_t e_mod,timestruc_t * e_time)13711861SMarek.Pospisil@Sun.COM au_close_defer(token_t *dchain, int flag, au_event_t e_type, au_emod_t e_mod,
13811861SMarek.Pospisil@Sun.COM timestruc_t *e_time)
1390Sstevel@tonic-gate {
1400Sstevel@tonic-gate au_defer_info_t *attr;
1410Sstevel@tonic-gate t_audit_data_t *tad = U2A(u);
1420Sstevel@tonic-gate
1430Sstevel@tonic-gate ASSERT(tad != NULL);
1440Sstevel@tonic-gate
1450Sstevel@tonic-gate /* If not to be written, toss the record. */
1460Sstevel@tonic-gate if ((flag & AU_OK) == 0) {
1470Sstevel@tonic-gate au_toss_token(dchain);
1480Sstevel@tonic-gate return;
1490Sstevel@tonic-gate }
1500Sstevel@tonic-gate
1510Sstevel@tonic-gate attr = kmem_alloc(sizeof (au_defer_info_t), KM_NOSLEEP);
1520Sstevel@tonic-gate /* If no mem available, failing silently is the best recourse */
1530Sstevel@tonic-gate if (attr == NULL) {
1540Sstevel@tonic-gate au_toss_token(dchain);
1550Sstevel@tonic-gate return;
1560Sstevel@tonic-gate }
1570Sstevel@tonic-gate
1580Sstevel@tonic-gate attr->audi_next = NULL;
1590Sstevel@tonic-gate attr->audi_ad = dchain;
1600Sstevel@tonic-gate attr->audi_e_type = e_type;
1610Sstevel@tonic-gate attr->audi_e_mod = e_mod;
1620Sstevel@tonic-gate attr->audi_flag = flag;
16311861SMarek.Pospisil@Sun.COM if (e_time != NULL)
16411861SMarek.Pospisil@Sun.COM attr->audi_atime = *e_time;
16511861SMarek.Pospisil@Sun.COM else
16611861SMarek.Pospisil@Sun.COM gethrestime(&attr->audi_atime);
1670Sstevel@tonic-gate
1680Sstevel@tonic-gate /*
1690Sstevel@tonic-gate * All async events must be queued via softcall to avoid possible
1700Sstevel@tonic-gate * sleeping in high interrupt context. softcall will ensure it's
1710Sstevel@tonic-gate * done on a dedicated software-level interrupt thread.
1720Sstevel@tonic-gate */
1730Sstevel@tonic-gate if (flag & AU_DONTBLOCK) {
1740Sstevel@tonic-gate softcall(audit_async_finish_backend, attr);
1750Sstevel@tonic-gate audit_async_done(NULL, 0);
1760Sstevel@tonic-gate return;
1770Sstevel@tonic-gate }
1780Sstevel@tonic-gate
1790Sstevel@tonic-gate /*
1800Sstevel@tonic-gate * If not an async event, defer by queuing onto the tad until
1810Sstevel@tonic-gate * syscall end. No locking is needed because the tad is per-thread.
1820Sstevel@tonic-gate */
1830Sstevel@tonic-gate if (tad->tad_defer_head)
1840Sstevel@tonic-gate tad->tad_defer_tail->audi_next = attr;
1850Sstevel@tonic-gate else
1860Sstevel@tonic-gate tad->tad_defer_head = attr;
1870Sstevel@tonic-gate tad->tad_defer_tail = attr;
1880Sstevel@tonic-gate }
1890Sstevel@tonic-gate
1900Sstevel@tonic-gate
1910Sstevel@tonic-gate /*
1920Sstevel@tonic-gate * Save the time in the event header. If time is not specified (i.e., pointer
1930Sstevel@tonic-gate * is NULL), use the current time. This code is fairly ugly since it needs
1940Sstevel@tonic-gate * to support both 32- and 64-bit environments and can be called indirectly
1950Sstevel@tonic-gate * from both au_close() (for kernel audit) and from audit() (userland audit).
1960Sstevel@tonic-gate */
1970Sstevel@tonic-gate /*ARGSUSED*/
1980Sstevel@tonic-gate static void
au_save_time(adr_t * hadrp,timestruc_t * time,int size)1990Sstevel@tonic-gate au_save_time(adr_t *hadrp, timestruc_t *time, int size)
2000Sstevel@tonic-gate {
2010Sstevel@tonic-gate struct {
2020Sstevel@tonic-gate uint32_t sec;
2030Sstevel@tonic-gate uint32_t usec;
2040Sstevel@tonic-gate } tv;
2050Sstevel@tonic-gate timestruc_t now;
2060Sstevel@tonic-gate
2070Sstevel@tonic-gate if (time == NULL) {
2080Sstevel@tonic-gate gethrestime(&now);
2090Sstevel@tonic-gate time = &now;
2100Sstevel@tonic-gate }
2110Sstevel@tonic-gate
2120Sstevel@tonic-gate #ifdef _LP64
2130Sstevel@tonic-gate if (size)
2140Sstevel@tonic-gate adr_int64(hadrp, (int64_t *)time, 2);
2150Sstevel@tonic-gate else
2160Sstevel@tonic-gate #endif
2170Sstevel@tonic-gate {
2180Sstevel@tonic-gate tv.sec = (uint32_t)time->tv_sec;
2190Sstevel@tonic-gate tv.usec = (uint32_t)time->tv_nsec;
2200Sstevel@tonic-gate adr_int32(hadrp, (int32_t *)&tv, 2);
2210Sstevel@tonic-gate }
2220Sstevel@tonic-gate }
2230Sstevel@tonic-gate
2240Sstevel@tonic-gate
2250Sstevel@tonic-gate /*
2260Sstevel@tonic-gate * Close an audit descriptor.
2270Sstevel@tonic-gate * If time of event is specified, use it in the record, otherwise use the
2280Sstevel@tonic-gate * current time.
2290Sstevel@tonic-gate */
2300Sstevel@tonic-gate void
au_close_time(au_kcontext_t * kctx,token_t * dchain,int flag,au_event_t e_type,au_emod_t e_mod,timestruc_t * etime)2317753STon.Nguyen@Sun.COM au_close_time(au_kcontext_t *kctx, token_t *dchain, int flag, au_event_t e_type,
2327753STon.Nguyen@Sun.COM au_emod_t e_mod, timestruc_t *etime)
2330Sstevel@tonic-gate {
2340Sstevel@tonic-gate token_t *record; /* au_membuf chain == the record */
2350Sstevel@tonic-gate int byte_count;
2360Sstevel@tonic-gate token_t *m; /* for potential sequence token */
2370Sstevel@tonic-gate adr_t hadr; /* handle for header token */
2380Sstevel@tonic-gate adr_t sadr; /* handle for sequence token */
2390Sstevel@tonic-gate size_t zone_length; /* length of zonename token */
24011861SMarek.Pospisil@Sun.COM uint32_t auditing;
2410Sstevel@tonic-gate
2420Sstevel@tonic-gate ASSERT(dchain != NULL);
2430Sstevel@tonic-gate
2440Sstevel@tonic-gate /* If not to be written, toss the record */
2450Sstevel@tonic-gate if ((flag & AU_OK) == 0) {
2460Sstevel@tonic-gate au_toss_token(dchain);
2470Sstevel@tonic-gate return;
2480Sstevel@tonic-gate }
2490Sstevel@tonic-gate /* if auditing not enabled, then don't generate an audit record */
25011861SMarek.Pospisil@Sun.COM ASSERT(U2A(u) != NULL);
2510Sstevel@tonic-gate ASSERT(kctx != NULL);
2520Sstevel@tonic-gate
25311861SMarek.Pospisil@Sun.COM auditing = (U2A(u)->tad_audit == AUC_UNSET)
25411861SMarek.Pospisil@Sun.COM ? kctx->auk_auditstate
25511861SMarek.Pospisil@Sun.COM : U2A(u)->tad_audit;
25611861SMarek.Pospisil@Sun.COM
25711861SMarek.Pospisil@Sun.COM if (auditing & ~(AUC_AUDITING | AUC_INIT_AUDIT)) {
2580Sstevel@tonic-gate /*
2590Sstevel@tonic-gate * at system boot, neither is set yet we want to generate
2600Sstevel@tonic-gate * an audit record.
2610Sstevel@tonic-gate */
2620Sstevel@tonic-gate if (e_type != AUE_SYSTEMBOOT) {
2630Sstevel@tonic-gate au_toss_token(dchain);
2640Sstevel@tonic-gate return;
2650Sstevel@tonic-gate }
2660Sstevel@tonic-gate }
2670Sstevel@tonic-gate
2680Sstevel@tonic-gate /* Count up the bytes used in the record. */
2690Sstevel@tonic-gate byte_count = au_token_size(dchain);
2700Sstevel@tonic-gate
2710Sstevel@tonic-gate /*
2720Sstevel@tonic-gate * add in size of header token (always present).
2730Sstevel@tonic-gate */
2740Sstevel@tonic-gate byte_count += sizeof (char) + sizeof (int32_t) +
2750Sstevel@tonic-gate sizeof (char) + 2 * sizeof (short) + sizeof (timestruc_t);
2760Sstevel@tonic-gate
2770Sstevel@tonic-gate if (kctx->auk_hostaddr_valid)
2785992Sgww byte_count += sizeof (int32_t) +
2795992Sgww kctx->auk_info.ai_termid.at_type;
2800Sstevel@tonic-gate
2810Sstevel@tonic-gate /*
2820Sstevel@tonic-gate * add in size of zonename token (zero if !AUDIT_ZONENAME)
2830Sstevel@tonic-gate */
2840Sstevel@tonic-gate if (kctx->auk_policy & AUDIT_ZONENAME) {
2854165Stz204579 zone_length = au_zonename_length(NULL);
2860Sstevel@tonic-gate byte_count += zone_length;
2870Sstevel@tonic-gate } else {
2880Sstevel@tonic-gate zone_length = 0;
2890Sstevel@tonic-gate }
2900Sstevel@tonic-gate /* add in size of (optional) trailer token */
2910Sstevel@tonic-gate if (kctx->auk_policy & AUDIT_TRAIL)
2920Sstevel@tonic-gate byte_count += 7;
2930Sstevel@tonic-gate
2940Sstevel@tonic-gate /* add in size of (optional) sequence token */
2950Sstevel@tonic-gate if (kctx->auk_policy & AUDIT_SEQ)
2960Sstevel@tonic-gate byte_count += 5;
2970Sstevel@tonic-gate
2980Sstevel@tonic-gate /* build the header */
2990Sstevel@tonic-gate if (kctx->auk_hostaddr_valid)
3000Sstevel@tonic-gate record = au_to_header_ex(byte_count, e_type, e_mod);
3010Sstevel@tonic-gate else
3020Sstevel@tonic-gate record = au_to_header(byte_count, e_type, e_mod);
3030Sstevel@tonic-gate
3040Sstevel@tonic-gate /*
3050Sstevel@tonic-gate * If timestamp was specified, save it in header now. Otherwise,
3060Sstevel@tonic-gate * save reference to header so we can update time/data later
3070Sstevel@tonic-gate * and artificially adjust pointer to the time/date field of header.
3080Sstevel@tonic-gate */
3090Sstevel@tonic-gate adr_start(&hadr, memtod(record, char *));
3100Sstevel@tonic-gate hadr.adr_now += sizeof (char) + sizeof (int32_t) +
3110Sstevel@tonic-gate sizeof (char) + 2 * sizeof (short);
3120Sstevel@tonic-gate if (kctx->auk_hostaddr_valid)
3130Sstevel@tonic-gate hadr.adr_now += sizeof (int32_t) +
3140Sstevel@tonic-gate kctx->auk_info.ai_termid.at_type;
3150Sstevel@tonic-gate if (etime != NULL) {
3160Sstevel@tonic-gate au_save_time(&hadr, etime, 1);
3170Sstevel@tonic-gate hadr.adr_now = (char *)NULL;
3180Sstevel@tonic-gate }
3190Sstevel@tonic-gate
3200Sstevel@tonic-gate /* append body of audit record */
3210Sstevel@tonic-gate (void) au_append_rec(record, dchain, AU_PACK);
3220Sstevel@tonic-gate
3230Sstevel@tonic-gate /* add (optional) zonename token */
3240Sstevel@tonic-gate if (zone_length > 0) {
3254165Stz204579 m = au_to_zonename(zone_length, NULL);
3260Sstevel@tonic-gate (void) au_append_rec(record, m, AU_PACK);
3270Sstevel@tonic-gate }
3280Sstevel@tonic-gate
3290Sstevel@tonic-gate /* Add an (optional) sequence token. NULL offset if none */
3300Sstevel@tonic-gate if (kctx->auk_policy & AUDIT_SEQ) {
3310Sstevel@tonic-gate /* get the sequence token */
3320Sstevel@tonic-gate m = au_to_seq();
3330Sstevel@tonic-gate
3340Sstevel@tonic-gate /* link to audit record (i.e. don't pack the data) */
3350Sstevel@tonic-gate (void) au_append_rec(record, m, AU_LINK);
3360Sstevel@tonic-gate
3370Sstevel@tonic-gate /*
3380Sstevel@tonic-gate * advance to count field of sequence token by skipping
3390Sstevel@tonic-gate * the token type byte.
3400Sstevel@tonic-gate */
3410Sstevel@tonic-gate adr_start(&sadr, memtod(m, char *));
3420Sstevel@tonic-gate sadr.adr_now += 1;
3430Sstevel@tonic-gate } else {
3440Sstevel@tonic-gate sadr.adr_now = NULL;
3450Sstevel@tonic-gate }
3460Sstevel@tonic-gate /* add (optional) trailer token */
3470Sstevel@tonic-gate if (kctx->auk_policy & AUDIT_TRAIL) {
3480Sstevel@tonic-gate (void) au_append_rec(record, au_to_trailer(byte_count),
3490Sstevel@tonic-gate AU_PACK);
3500Sstevel@tonic-gate }
3510Sstevel@tonic-gate
3520Sstevel@tonic-gate /*
3530Sstevel@tonic-gate * 1 - use 64 bit version of audit tokens for 64 bit kernels.
3540Sstevel@tonic-gate * 0 - use 32 bit version of audit tokens for 32 bit kernels.
3550Sstevel@tonic-gate */
3560Sstevel@tonic-gate #ifdef _LP64
3570Sstevel@tonic-gate au_enqueue(kctx, record, &hadr, &sadr, 1, flag & AU_DONTBLOCK);
3580Sstevel@tonic-gate #else
3590Sstevel@tonic-gate au_enqueue(kctx, record, &hadr, &sadr, 0, flag & AU_DONTBLOCK);
3600Sstevel@tonic-gate #endif
3610Sstevel@tonic-gate AS_INC(as_totalsize, byte_count, kctx);
3620Sstevel@tonic-gate }
3630Sstevel@tonic-gate
3640Sstevel@tonic-gate /*ARGSUSED*/
3650Sstevel@tonic-gate void
au_enqueue(au_kcontext_t * kctx,au_buff_t * m,adr_t * hadrp,adr_t * sadrp,int size,int dontblock)3660Sstevel@tonic-gate au_enqueue(au_kcontext_t *kctx, au_buff_t *m, adr_t *hadrp, adr_t *sadrp,
3670Sstevel@tonic-gate int size, int dontblock)
3680Sstevel@tonic-gate {
3690Sstevel@tonic-gate if (kctx == NULL)
3700Sstevel@tonic-gate return;
3710Sstevel@tonic-gate
3720Sstevel@tonic-gate mutex_enter(&(kctx->auk_queue.lock));
3730Sstevel@tonic-gate
3740Sstevel@tonic-gate if (!dontblock && (kctx->auk_queue.cnt >= kctx->auk_queue.hiwater) &&
3750Sstevel@tonic-gate audit_sync_block(kctx)) {
3760Sstevel@tonic-gate mutex_exit(&(kctx->auk_queue.lock));
3770Sstevel@tonic-gate au_free_rec(m);
3780Sstevel@tonic-gate return;
3790Sstevel@tonic-gate }
3800Sstevel@tonic-gate
3810Sstevel@tonic-gate /* Fill in date and time if needed */
3820Sstevel@tonic-gate if (hadrp->adr_now) {
3830Sstevel@tonic-gate au_save_time(hadrp, NULL, size);
3840Sstevel@tonic-gate }
3850Sstevel@tonic-gate
3860Sstevel@tonic-gate /* address will be non-zero only if AUDIT_SEQ set */
3870Sstevel@tonic-gate if (sadrp->adr_now) {
3880Sstevel@tonic-gate kctx->auk_sequence++;
3890Sstevel@tonic-gate adr_int32(sadrp, (int32_t *)&(kctx->auk_sequence), 1);
3900Sstevel@tonic-gate }
3910Sstevel@tonic-gate
3920Sstevel@tonic-gate if (kctx->auk_queue.head)
3930Sstevel@tonic-gate kctx->auk_queue.tail->next_rec = m;
3940Sstevel@tonic-gate else
3950Sstevel@tonic-gate kctx->auk_queue.head = m;
3960Sstevel@tonic-gate
3970Sstevel@tonic-gate kctx->auk_queue.tail = m;
3980Sstevel@tonic-gate
3990Sstevel@tonic-gate if (++(kctx->auk_queue.cnt) >
4000Sstevel@tonic-gate kctx->auk_queue.lowater && kctx->auk_queue.rd_block)
4010Sstevel@tonic-gate cv_broadcast(&(kctx->auk_queue.read_cv));
4020Sstevel@tonic-gate
4030Sstevel@tonic-gate mutex_exit(&(kctx->auk_queue.lock));
4040Sstevel@tonic-gate
4050Sstevel@tonic-gate /* count # audit records put onto kernel audit queue */
4060Sstevel@tonic-gate AS_INC(as_enqueue, 1, kctx);
4070Sstevel@tonic-gate }
4080Sstevel@tonic-gate
4090Sstevel@tonic-gate /*
4100Sstevel@tonic-gate * Dequeue and free buffers upto and including "freeto"
4110Sstevel@tonic-gate * Keeps the queue lock long but acquires it only once when doing
4120Sstevel@tonic-gate * bulk dequeueing.
4130Sstevel@tonic-gate */
4140Sstevel@tonic-gate static void
au_dequeue(au_kcontext_t * kctx,au_buff_t * freeto)4150Sstevel@tonic-gate au_dequeue(au_kcontext_t *kctx, au_buff_t *freeto)
4160Sstevel@tonic-gate {
4170Sstevel@tonic-gate au_buff_t *m, *l, *lastl;
4180Sstevel@tonic-gate int n = 0;
4190Sstevel@tonic-gate
4200Sstevel@tonic-gate ASSERT(kctx != NULL);
4210Sstevel@tonic-gate
4220Sstevel@tonic-gate mutex_enter(&(kctx->auk_queue.lock));
4230Sstevel@tonic-gate
4240Sstevel@tonic-gate ASSERT(kctx->auk_queue.head != NULL);
4250Sstevel@tonic-gate ASSERT(freeto != NULL);
4260Sstevel@tonic-gate
4270Sstevel@tonic-gate l = m = kctx->auk_queue.head;
4280Sstevel@tonic-gate
4290Sstevel@tonic-gate do {
4300Sstevel@tonic-gate n++;
4310Sstevel@tonic-gate lastl = l;
4320Sstevel@tonic-gate l = l->next_rec;
4330Sstevel@tonic-gate } while (l != NULL && freeto != lastl);
4340Sstevel@tonic-gate
4350Sstevel@tonic-gate kctx->auk_queue.cnt -= n;
4360Sstevel@tonic-gate lastl->next_rec = NULL;
4370Sstevel@tonic-gate kctx->auk_queue.head = l;
4380Sstevel@tonic-gate
4390Sstevel@tonic-gate /* Freeto must exist in the list */
4400Sstevel@tonic-gate ASSERT(freeto == lastl);
4410Sstevel@tonic-gate
4420Sstevel@tonic-gate if (kctx->auk_queue.cnt <= kctx->auk_queue.lowater &&
4430Sstevel@tonic-gate kctx->auk_queue.wt_block)
4440Sstevel@tonic-gate cv_broadcast(&(kctx->auk_queue.write_cv));
4450Sstevel@tonic-gate
4460Sstevel@tonic-gate mutex_exit(&(kctx->auk_queue.lock));
4470Sstevel@tonic-gate
4480Sstevel@tonic-gate while (m) {
4490Sstevel@tonic-gate l = m->next_rec;
4500Sstevel@tonic-gate au_free_rec(m);
4510Sstevel@tonic-gate m = l;
4520Sstevel@tonic-gate }
4530Sstevel@tonic-gate AS_INC(as_written, n, kctx);
4540Sstevel@tonic-gate }
4550Sstevel@tonic-gate
4560Sstevel@tonic-gate /*
4570Sstevel@tonic-gate * audit_sync_block()
4580Sstevel@tonic-gate * If we've reached the high water mark, we look at the policy to see
4590Sstevel@tonic-gate * if we sleep or we should drop the audit record.
4600Sstevel@tonic-gate * This function is called with the auk_queue.lock held and the check
4610Sstevel@tonic-gate * performed one time already as an optimization. Caller should unlock.
4620Sstevel@tonic-gate * Returns 1 if the caller needs to free the record.
4630Sstevel@tonic-gate */
4640Sstevel@tonic-gate static int
audit_sync_block(au_kcontext_t * kctx)4650Sstevel@tonic-gate audit_sync_block(au_kcontext_t *kctx)
4660Sstevel@tonic-gate {
4670Sstevel@tonic-gate ASSERT(MUTEX_HELD(&(kctx->auk_queue.lock)));
4680Sstevel@tonic-gate /*
4690Sstevel@tonic-gate * Loop while we are at the high watermark.
4700Sstevel@tonic-gate */
4710Sstevel@tonic-gate do {
47211861SMarek.Pospisil@Sun.COM if (((U2A(u)->tad_audit != AUC_UNSET)
47311861SMarek.Pospisil@Sun.COM ? (U2A(u)->tad_audit != AUC_AUDITING)
47411861SMarek.Pospisil@Sun.COM : (kctx->auk_auditstate != AUC_AUDITING)) ||
4750Sstevel@tonic-gate (kctx->auk_policy & AUDIT_CNT)) {
4760Sstevel@tonic-gate
4770Sstevel@tonic-gate /* just count # of dropped audit records */
4780Sstevel@tonic-gate AS_INC(as_dropped, 1, kctx);
4790Sstevel@tonic-gate
4800Sstevel@tonic-gate return (1);
4810Sstevel@tonic-gate }
4820Sstevel@tonic-gate
4830Sstevel@tonic-gate /* kick reader awake if its asleep */
4840Sstevel@tonic-gate if (kctx->auk_queue.rd_block &&
4850Sstevel@tonic-gate kctx->auk_queue.cnt > kctx->auk_queue.lowater)
4860Sstevel@tonic-gate cv_broadcast(&(kctx->auk_queue.read_cv));
4870Sstevel@tonic-gate
4880Sstevel@tonic-gate /* keep count of # times blocked */
4890Sstevel@tonic-gate AS_INC(as_wblocked, 1, kctx);
4900Sstevel@tonic-gate
4910Sstevel@tonic-gate /* sleep now, until woken by reader */
4920Sstevel@tonic-gate kctx->auk_queue.wt_block++;
4930Sstevel@tonic-gate cv_wait(&(kctx->auk_queue.write_cv), &(kctx->auk_queue.lock));
4940Sstevel@tonic-gate kctx->auk_queue.wt_block--;
4950Sstevel@tonic-gate } while (kctx->auk_queue.cnt >= kctx->auk_queue.hiwater);
4960Sstevel@tonic-gate
4970Sstevel@tonic-gate return (0);
4980Sstevel@tonic-gate }
4990Sstevel@tonic-gate
5000Sstevel@tonic-gate /*
5010Sstevel@tonic-gate * audit_async_block()
5020Sstevel@tonic-gate * if we've reached the high water mark, we look at the ahlt policy to see
5030Sstevel@tonic-gate * if we reboot we should drop the audit record.
5040Sstevel@tonic-gate * Returns 1 if blocked.
5050Sstevel@tonic-gate */
5060Sstevel@tonic-gate static int
audit_async_block(au_kcontext_t * kctx,caddr_t * rpp)5070Sstevel@tonic-gate audit_async_block(au_kcontext_t *kctx, caddr_t *rpp)
5080Sstevel@tonic-gate {
5090Sstevel@tonic-gate ASSERT(kctx != NULL);
5100Sstevel@tonic-gate
5110Sstevel@tonic-gate mutex_enter(&(kctx->auk_queue.lock));
5120Sstevel@tonic-gate /* see if we've reached high water mark */
5130Sstevel@tonic-gate if (kctx->auk_queue.cnt >= kctx->auk_queue.hiwater) {
5140Sstevel@tonic-gate mutex_exit(&(kctx->auk_queue.lock));
5150Sstevel@tonic-gate
5160Sstevel@tonic-gate audit_async_drop(rpp, AU_BACKEND);
5170Sstevel@tonic-gate return (1);
5180Sstevel@tonic-gate }
5190Sstevel@tonic-gate mutex_exit(&(kctx->auk_queue.lock));
5200Sstevel@tonic-gate return (0);
5210Sstevel@tonic-gate }
5220Sstevel@tonic-gate
5230Sstevel@tonic-gate /*
5240Sstevel@tonic-gate * au_door_upcall. auditdoor() may change vp without notice, so
5250Sstevel@tonic-gate * some locking seems in order.
5260Sstevel@tonic-gate *
5270Sstevel@tonic-gate */
5280Sstevel@tonic-gate #define AGAIN_TICKS 10
5290Sstevel@tonic-gate
5300Sstevel@tonic-gate static int
au_door_upcall(au_kcontext_t * kctx,au_dbuf_t * aubuf)5310Sstevel@tonic-gate au_door_upcall(au_kcontext_t *kctx, au_dbuf_t *aubuf)
5320Sstevel@tonic-gate {
5330Sstevel@tonic-gate int rc;
5340Sstevel@tonic-gate door_arg_t darg;
5350Sstevel@tonic-gate int retry = 1;
5360Sstevel@tonic-gate int ticks_to_wait;
5370Sstevel@tonic-gate
5380Sstevel@tonic-gate darg.data_ptr = (char *)aubuf;
5390Sstevel@tonic-gate darg.data_size = AU_DBUF_HEADER + aubuf->aub_size;
5400Sstevel@tonic-gate
5410Sstevel@tonic-gate darg.desc_ptr = NULL;
5420Sstevel@tonic-gate darg.desc_num = 0;
5430Sstevel@tonic-gate
5440Sstevel@tonic-gate while (retry == 1) {
5450Sstevel@tonic-gate /* non-zero means return results expected */
5460Sstevel@tonic-gate darg.rbuf = (char *)aubuf;
5470Sstevel@tonic-gate darg.rsize = darg.data_size;
5480Sstevel@tonic-gate
5490Sstevel@tonic-gate retry = 0;
5500Sstevel@tonic-gate mutex_enter(&(kctx->auk_svc_lock));
5516997Sjwadams rc = door_upcall(kctx->auk_current_vp, &darg, NULL,
5526997Sjwadams SIZE_MAX, 0);
5536263Sseb if (rc != 0) {
5540Sstevel@tonic-gate mutex_exit(&(kctx->auk_svc_lock));
5550Sstevel@tonic-gate if (rc == EAGAIN)
5560Sstevel@tonic-gate ticks_to_wait = AGAIN_TICKS;
5570Sstevel@tonic-gate else
5580Sstevel@tonic-gate return (rc);
5590Sstevel@tonic-gate
5600Sstevel@tonic-gate mutex_enter(&(kctx->auk_eagain_mutex));
56111066Srafael.vanoni@sun.com (void) cv_reltimedwait(&(kctx->auk_eagain_cv),
56211066Srafael.vanoni@sun.com &(kctx->auk_eagain_mutex), ticks_to_wait,
56311066Srafael.vanoni@sun.com TR_CLOCK_TICK);
5640Sstevel@tonic-gate mutex_exit(&(kctx->auk_eagain_mutex));
5650Sstevel@tonic-gate
5660Sstevel@tonic-gate retry = 1;
5670Sstevel@tonic-gate } else
5680Sstevel@tonic-gate mutex_exit(&(kctx->auk_svc_lock)); /* no retry */
5690Sstevel@tonic-gate } /* end while (retry == 1) */
5700Sstevel@tonic-gate if (darg.rbuf == NULL)
5710Sstevel@tonic-gate return (-1);
5720Sstevel@tonic-gate
5730Sstevel@tonic-gate /* return code from door server */
5740Sstevel@tonic-gate return (*(int *)darg.rbuf);
5750Sstevel@tonic-gate }
5760Sstevel@tonic-gate
5770Sstevel@tonic-gate /*
5780Sstevel@tonic-gate * Write an audit control message to the door handle. The message
5790Sstevel@tonic-gate * structure depends on message_code and at present the only control
5800Sstevel@tonic-gate * message defined is for a policy change. These are infrequent,
5810Sstevel@tonic-gate * so no memory is held for control messages.
5820Sstevel@tonic-gate */
5830Sstevel@tonic-gate int
au_doormsg(au_kcontext_t * kctx,uint32_t message_code,void * message)5840Sstevel@tonic-gate au_doormsg(au_kcontext_t *kctx, uint32_t message_code, void *message)
5850Sstevel@tonic-gate {
5860Sstevel@tonic-gate int rc;
5870Sstevel@tonic-gate au_dbuf_t *buf;
5880Sstevel@tonic-gate size_t alloc_size;
5890Sstevel@tonic-gate
5900Sstevel@tonic-gate switch (message_code) {
5910Sstevel@tonic-gate case AU_DBUF_POLICY:
5920Sstevel@tonic-gate alloc_size = AU_DBUF_HEADER + sizeof (uint32_t);
5930Sstevel@tonic-gate buf = kmem_alloc(alloc_size, KM_SLEEP);
5940Sstevel@tonic-gate buf->aub_size = sizeof (uint32_t);
5950Sstevel@tonic-gate *(uint32_t *)buf->aub_buf = *(uint32_t *)message;
5960Sstevel@tonic-gate break;
5970Sstevel@tonic-gate case AU_DBUF_SHUTDOWN:
5980Sstevel@tonic-gate alloc_size = AU_DBUF_HEADER;
5990Sstevel@tonic-gate buf = kmem_alloc(alloc_size, KM_SLEEP);
6000Sstevel@tonic-gate buf->aub_size = 0;
6010Sstevel@tonic-gate break;
6020Sstevel@tonic-gate default:
6030Sstevel@tonic-gate return (1);
6040Sstevel@tonic-gate }
6050Sstevel@tonic-gate
6060Sstevel@tonic-gate buf->aub_type = AU_DBUF_NOTIFY | message_code;
6070Sstevel@tonic-gate rc = au_door_upcall(kctx, buf);
6080Sstevel@tonic-gate kmem_free(buf, alloc_size);
6090Sstevel@tonic-gate
6100Sstevel@tonic-gate return (rc);
6110Sstevel@tonic-gate }
6120Sstevel@tonic-gate
6130Sstevel@tonic-gate /*
6140Sstevel@tonic-gate * Write audit information to the door handle. au_doorio is called with
6150Sstevel@tonic-gate * one or more complete audit records on the queue and outputs those
6160Sstevel@tonic-gate * records in buffers of up to auk_queue.buflen in size.
6170Sstevel@tonic-gate */
6180Sstevel@tonic-gate int
au_doorio(au_kcontext_t * kctx)6190Sstevel@tonic-gate au_doorio(au_kcontext_t *kctx) {
6200Sstevel@tonic-gate off_t off; /* space used in buffer */
6210Sstevel@tonic-gate ssize_t used; /* space used in au_membuf */
6220Sstevel@tonic-gate token_t *cAR; /* current AR being processed */
6230Sstevel@tonic-gate token_t *cMB; /* current au_membuf being processed */
6240Sstevel@tonic-gate token_t *sp; /* last AR processed */
6250Sstevel@tonic-gate char *bp; /* start of free space in staging buffer */
6260Sstevel@tonic-gate unsigned char *cp; /* ptr to data to be moved */
627*13128SMarek.Pospisil@Sun.COM int error = 0; /* return from door upcall */
6280Sstevel@tonic-gate
6290Sstevel@tonic-gate /*
6300Sstevel@tonic-gate * size (data left in au_membuf - space in buffer)
6310Sstevel@tonic-gate */
6320Sstevel@tonic-gate ssize_t sz;
6330Sstevel@tonic-gate ssize_t len; /* len of data to move, size of AR */
6340Sstevel@tonic-gate ssize_t curr_sz = 0; /* amount of data written during now */
6350Sstevel@tonic-gate /*
6360Sstevel@tonic-gate * partial_state is AU_DBUF_COMPLETE...LAST; see audit_door_infc.h
6370Sstevel@tonic-gate */
6380Sstevel@tonic-gate int part = 0; /* partial audit record written */
6390Sstevel@tonic-gate int partial_state = AU_DBUF_COMPLETE;
6400Sstevel@tonic-gate /*
6410Sstevel@tonic-gate * Has the write buffer changed length due to a auditctl(2)?
6420Sstevel@tonic-gate * Initial allocation is from audit_start.c/audit_init()
6430Sstevel@tonic-gate */
6440Sstevel@tonic-gate if (kctx->auk_queue.bufsz != kctx->auk_queue.buflen) {
64511965SMarek.Pospisil@Sun.COM size_t new_sz = kctx->auk_queue.bufsz;
64611965SMarek.Pospisil@Sun.COM
6470Sstevel@tonic-gate kmem_free(kctx->auk_dbuffer, AU_DBUF_HEADER +
6480Sstevel@tonic-gate kctx->auk_queue.buflen);
6490Sstevel@tonic-gate
65011965SMarek.Pospisil@Sun.COM kctx->auk_dbuffer = kmem_alloc(AU_DBUF_HEADER + new_sz,
65111965SMarek.Pospisil@Sun.COM KM_SLEEP);
6520Sstevel@tonic-gate
6530Sstevel@tonic-gate /* omit the 64 bit header */
65411965SMarek.Pospisil@Sun.COM kctx->auk_queue.buflen = new_sz;
6550Sstevel@tonic-gate }
6560Sstevel@tonic-gate if (!kctx->auk_queue.head)
6570Sstevel@tonic-gate goto nodata;
6580Sstevel@tonic-gate
6590Sstevel@tonic-gate sp = NULL; /* no record copied */
6600Sstevel@tonic-gate off = 0; /* no space used in buffer */
6610Sstevel@tonic-gate used = 0; /* no data processed in au_membuf */
6620Sstevel@tonic-gate cAR = kctx->auk_queue.head; /* start at head of queue */
6630Sstevel@tonic-gate cMB = cAR; /* start with first au_membuf of record */
6640Sstevel@tonic-gate
6650Sstevel@tonic-gate /* start at beginning of buffer */
6660Sstevel@tonic-gate bp = &(kctx->auk_dbuffer->aub_buf[0]);
6670Sstevel@tonic-gate
6680Sstevel@tonic-gate while (cMB) {
6690Sstevel@tonic-gate part = 1; /* indicate audit record being processed */
6700Sstevel@tonic-gate
6710Sstevel@tonic-gate cp = memtod(cMB, unsigned char *); /* buffer ptr */
6720Sstevel@tonic-gate
6730Sstevel@tonic-gate sz = (ssize_t)cMB->len - used; /* data left in au_membuf */
6740Sstevel@tonic-gate /* len to move */
6750Sstevel@tonic-gate len = (ssize_t)MIN(sz, kctx->auk_queue.buflen - off);
6760Sstevel@tonic-gate
6770Sstevel@tonic-gate /* move the data */
6780Sstevel@tonic-gate bcopy(cp + used, bp + off, len);
6790Sstevel@tonic-gate used += len; /* update used au_membuf */
6800Sstevel@tonic-gate off += len; /* update offset into buffer */
6810Sstevel@tonic-gate
6820Sstevel@tonic-gate if (used >= (ssize_t)cMB->len) {
6830Sstevel@tonic-gate /* advance to next au_membuf */
6840Sstevel@tonic-gate used = 0;
6850Sstevel@tonic-gate cMB = cMB->next_buf;
6860Sstevel@tonic-gate }
6870Sstevel@tonic-gate if (cMB == NULL) {
6880Sstevel@tonic-gate /* advance to next audit record */
6890Sstevel@tonic-gate sp = cAR;
6900Sstevel@tonic-gate cAR = cAR->next_rec;
6910Sstevel@tonic-gate cMB = cAR;
6920Sstevel@tonic-gate part = 0; /* have a complete record */
6930Sstevel@tonic-gate }
6940Sstevel@tonic-gate error = 0;
6950Sstevel@tonic-gate if ((kctx->auk_queue.buflen == off) || (part == 0)) {
6960Sstevel@tonic-gate if (part)
6970Sstevel@tonic-gate partial_state = state_if_part[partial_state];
6980Sstevel@tonic-gate else
6990Sstevel@tonic-gate partial_state =
7000Sstevel@tonic-gate state_if_not_part[partial_state];
7010Sstevel@tonic-gate
7020Sstevel@tonic-gate kctx->auk_dbuffer->aub_type = partial_state;
7030Sstevel@tonic-gate kctx->auk_dbuffer->aub_size = off;
7040Sstevel@tonic-gate error = au_door_upcall(kctx, kctx->auk_dbuffer);
7050Sstevel@tonic-gate if (error != 0)
7060Sstevel@tonic-gate goto nodata;
7070Sstevel@tonic-gate /*
7080Sstevel@tonic-gate * if we've successfully written an audit record,
7090Sstevel@tonic-gate * free records up to last full record copied
7100Sstevel@tonic-gate */
7110Sstevel@tonic-gate if (sp)
7120Sstevel@tonic-gate au_dequeue(kctx, sp);
7130Sstevel@tonic-gate
7140Sstevel@tonic-gate /* Update size */
7150Sstevel@tonic-gate curr_sz += off;
7160Sstevel@tonic-gate
7170Sstevel@tonic-gate /* reset auk_dbuffer pointers */
7180Sstevel@tonic-gate sp = NULL;
7190Sstevel@tonic-gate off = 0;
7200Sstevel@tonic-gate }
7210Sstevel@tonic-gate } /* while(cMB) */
7220Sstevel@tonic-gate nodata:
7230Sstevel@tonic-gate return (error);
7240Sstevel@tonic-gate }
7250Sstevel@tonic-gate
7260Sstevel@tonic-gate /*
7270Sstevel@tonic-gate * Clean up thread audit state to clear out asynchronous audit record
7280Sstevel@tonic-gate * generation error recovery processing. Note that this is done on a
7290Sstevel@tonic-gate * per-thread basis and thus does not need any locking.
7300Sstevel@tonic-gate */
7310Sstevel@tonic-gate void
audit_async_done(caddr_t * rpp,int flags)7320Sstevel@tonic-gate audit_async_done(caddr_t *rpp, int flags)
7330Sstevel@tonic-gate {
7340Sstevel@tonic-gate t_audit_data_t *tad = U2A(u);
7350Sstevel@tonic-gate
7360Sstevel@tonic-gate /* clean up the tad unless called from softcall backend */
7370Sstevel@tonic-gate if (!(flags & AU_BACKEND)) {
7380Sstevel@tonic-gate ASSERT(tad != NULL);
73912617SMarek.Pospisil@Sun.COM ASSERT(tad->tad_ctrl & TAD_ERRJMP);
7400Sstevel@tonic-gate
74112617SMarek.Pospisil@Sun.COM tad->tad_ctrl &= ~TAD_ERRJMP;
7420Sstevel@tonic-gate tad->tad_errjmp = NULL;
7430Sstevel@tonic-gate }
7440Sstevel@tonic-gate
7450Sstevel@tonic-gate /* clean out partial audit record */
7460Sstevel@tonic-gate if ((rpp != NULL) && (*rpp != NULL)) {
7470Sstevel@tonic-gate au_toss_token((au_buff_t *)*rpp);
7480Sstevel@tonic-gate *rpp = NULL;
7490Sstevel@tonic-gate }
7500Sstevel@tonic-gate }
7510Sstevel@tonic-gate
7520Sstevel@tonic-gate /*
7530Sstevel@tonic-gate * implement the audit policy for asynchronous events generated within
7540Sstevel@tonic-gate * the kernel.
7550Sstevel@tonic-gate * XXX might need locks around audit_policy check.
7560Sstevel@tonic-gate */
7570Sstevel@tonic-gate void
audit_async_drop(caddr_t * rpp,int flags)7580Sstevel@tonic-gate audit_async_drop(caddr_t *rpp, int flags)
7590Sstevel@tonic-gate {
7600Sstevel@tonic-gate au_kcontext_t *kctx;
7610Sstevel@tonic-gate
7620Sstevel@tonic-gate /* could not generate audit record, clean up */
7630Sstevel@tonic-gate audit_async_done((caddr_t *)rpp, flags);
7640Sstevel@tonic-gate
7654197Spaulson kctx = GET_KCTX_GZ;
7664197Spaulson
7670Sstevel@tonic-gate /* just drop the record and return */
7680Sstevel@tonic-gate if (((audit_policy & AUDIT_AHLT) == 0) ||
7690Sstevel@tonic-gate (kctx->auk_auditstate == AUC_INIT_AUDIT)) {
7700Sstevel@tonic-gate /* just count # of dropped audit records */
7710Sstevel@tonic-gate AS_INC(as_dropped, 1, kctx);
7720Sstevel@tonic-gate return;
7730Sstevel@tonic-gate }
7740Sstevel@tonic-gate
7750Sstevel@tonic-gate /*
7760Sstevel@tonic-gate * There can be a lot of data in the audit queue. We
7770Sstevel@tonic-gate * will first sync the file systems then attempt to
7780Sstevel@tonic-gate * shutdown the kernel so that a memory dump is
7790Sstevel@tonic-gate * performed.
7800Sstevel@tonic-gate */
7810Sstevel@tonic-gate sync();
7820Sstevel@tonic-gate sync();
7830Sstevel@tonic-gate
7840Sstevel@tonic-gate /*
7850Sstevel@tonic-gate * now shut down. What a cruel world it has been
7860Sstevel@tonic-gate */
7870Sstevel@tonic-gate panic("non-attributable halt. should dump core");
7880Sstevel@tonic-gate /* No return */
7890Sstevel@tonic-gate }
7900Sstevel@tonic-gate
7910Sstevel@tonic-gate int
audit_async_start(label_t * jb,au_event_t event,int sorf)7927753STon.Nguyen@Sun.COM audit_async_start(label_t *jb, au_event_t event, int sorf)
7930Sstevel@tonic-gate {
7940Sstevel@tonic-gate t_audit_data_t *tad = U2A(u);
7950Sstevel@tonic-gate au_state_t estate;
7960Sstevel@tonic-gate int success = 0, failure = 0;
7974197Spaulson au_kcontext_t *kctx = GET_KCTX_GZ;
7980Sstevel@tonic-gate
7990Sstevel@tonic-gate /* if audit state off, then no audit record generation */
8000Sstevel@tonic-gate if ((kctx->auk_auditstate != AUC_AUDITING) &&
8010Sstevel@tonic-gate (kctx->auk_auditstate != AUC_INIT_AUDIT))
8020Sstevel@tonic-gate return (1);
8030Sstevel@tonic-gate
8040Sstevel@tonic-gate /*
8050Sstevel@tonic-gate * preselect asynchronous event
8060Sstevel@tonic-gate * XXX should we check for out-of-range???
8070Sstevel@tonic-gate */
8080Sstevel@tonic-gate estate = kctx->auk_ets[event];
8090Sstevel@tonic-gate
8100Sstevel@tonic-gate if (sorf & AUM_SUCC)
81112918SJan.Friedel@Sun.COM success = kctx->auk_info.ai_namask.as_success & estate;
8120Sstevel@tonic-gate if (sorf & AUM_FAIL)
81312918SJan.Friedel@Sun.COM failure = kctx->auk_info.ai_namask.as_failure & estate;
8140Sstevel@tonic-gate
8150Sstevel@tonic-gate if ((success | failure) == NULL)
8160Sstevel@tonic-gate return (1);
8170Sstevel@tonic-gate
8180Sstevel@tonic-gate ASSERT(tad->tad_errjmp == NULL);
8190Sstevel@tonic-gate tad->tad_errjmp = (void *)jb;
82012617SMarek.Pospisil@Sun.COM tad->tad_ctrl |= TAD_ERRJMP;
8210Sstevel@tonic-gate
8220Sstevel@tonic-gate return (0);
8230Sstevel@tonic-gate }
8240Sstevel@tonic-gate
8250Sstevel@tonic-gate /*
8260Sstevel@tonic-gate * Complete auditing of an async event. The AU_DONTBLOCK flag to au_close will
8270Sstevel@tonic-gate * result in the backend routine being invoked from softcall, so all the real
8280Sstevel@tonic-gate * work can be done in a safe context.
8290Sstevel@tonic-gate */
8300Sstevel@tonic-gate void
audit_async_finish(caddr_t * ad,au_event_t aid,au_emod_t amod,timestruc_t * e_time)83111861SMarek.Pospisil@Sun.COM audit_async_finish(caddr_t *ad, au_event_t aid, au_emod_t amod,
83211861SMarek.Pospisil@Sun.COM timestruc_t *e_time)
8330Sstevel@tonic-gate {
8340Sstevel@tonic-gate au_kcontext_t *kctx;
8350Sstevel@tonic-gate
8364197Spaulson kctx = GET_KCTX_GZ;
8370Sstevel@tonic-gate
83811861SMarek.Pospisil@Sun.COM au_close(kctx, ad, AU_DONTBLOCK | AU_OK, aid, PAD_NONATTR|amod, e_time);
8390Sstevel@tonic-gate }
8400Sstevel@tonic-gate
8410Sstevel@tonic-gate /*
8420Sstevel@tonic-gate * Backend routine to complete an async audit. Invoked from softcall.
8430Sstevel@tonic-gate * (Note: the blocking and the queuing below both involve locking which can't
8440Sstevel@tonic-gate * be done safely in high interrupt context due to the chance of sleeping on
8450Sstevel@tonic-gate * the corresponding adaptive mutex. Hence the softcall.)
8460Sstevel@tonic-gate */
8470Sstevel@tonic-gate static void
audit_async_finish_backend(void * addr)8480Sstevel@tonic-gate audit_async_finish_backend(void *addr)
8490Sstevel@tonic-gate {
8500Sstevel@tonic-gate au_kcontext_t *kctx;
8510Sstevel@tonic-gate au_defer_info_t *attr = (au_defer_info_t *)addr;
8520Sstevel@tonic-gate
8530Sstevel@tonic-gate if (attr == NULL)
8540Sstevel@tonic-gate return; /* won't happen unless softcall is broken */
8550Sstevel@tonic-gate
8564197Spaulson kctx = GET_KCTX_GZ;
8570Sstevel@tonic-gate
8580Sstevel@tonic-gate if (audit_async_block(kctx, (caddr_t *)&attr->audi_ad)) {
8590Sstevel@tonic-gate kmem_free(attr, sizeof (au_defer_info_t));
8600Sstevel@tonic-gate return;
8610Sstevel@tonic-gate }
8620Sstevel@tonic-gate
8630Sstevel@tonic-gate /*
8640Sstevel@tonic-gate * Call au_close_time to complete the audit with the saved values.
8650Sstevel@tonic-gate *
8660Sstevel@tonic-gate * For the exit-prom event, use the current time instead of the
8670Sstevel@tonic-gate * saved time as a better approximation. (Because the time saved via
8680Sstevel@tonic-gate * gethrestime during prom-exit handling would not yet be caught up
8690Sstevel@tonic-gate * after the system was idled in the debugger for a period of time.)
8700Sstevel@tonic-gate */
8710Sstevel@tonic-gate if (attr->audi_e_type == AUE_EXITPROM) {
8720Sstevel@tonic-gate au_close_time(kctx, (token_t *)attr->audi_ad, attr->audi_flag,
8730Sstevel@tonic-gate attr->audi_e_type, attr->audi_e_mod, NULL);
8740Sstevel@tonic-gate } else {
8750Sstevel@tonic-gate au_close_time(kctx, (token_t *)attr->audi_ad, attr->audi_flag,
8760Sstevel@tonic-gate attr->audi_e_type, attr->audi_e_mod, &attr->audi_atime);
8770Sstevel@tonic-gate }
8780Sstevel@tonic-gate
8790Sstevel@tonic-gate AS_INC(as_generated, 1, kctx);
8800Sstevel@tonic-gate AS_INC(as_nonattrib, 1, kctx);
8810Sstevel@tonic-gate
8820Sstevel@tonic-gate kmem_free(attr, sizeof (au_defer_info_t));
8830Sstevel@tonic-gate }
884