audit_bsm.c revision 159259
1/*
2 * Copyright (c) 1999-2005 Apple Computer, 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 * 1.  Redistributions of source code must retain the above copyright
9 *     notice, this list of conditions and the following disclaimer.
10 * 2.  Redistributions in binary form must reproduce the above copyright
11 *     notice, this list of conditions and the following disclaimer in the
12 *     documentation and/or other materials provided with the distribution.
13 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 *     its contributors may be used to endorse or promote products derived
15 *     from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
26 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
29 * $FreeBSD: head/sys/security/audit/audit_bsm.c 159259 2006-06-05 13:13:02Z rwatson $
30 */
31
32#include <sys/param.h>
33#include <sys/vnode.h>
34#include <sys/ipc.h>
35#include <sys/lock.h>
36#include <sys/malloc.h>
37#include <sys/mutex.h>
38#include <sys/socket.h>
39#include <sys/fcntl.h>
40#include <sys/user.h>
41#include <sys/systm.h>
42
43#include <bsm/audit.h>
44#include <bsm/audit_internal.h>
45#include <bsm/audit_record.h>
46#include <bsm/audit_kevents.h>
47
48#include <security/audit/audit.h>
49#include <security/audit/audit_private.h>
50
51#include <netinet/in_systm.h>
52#include <netinet/in.h>
53#include <netinet/ip.h>
54
55MALLOC_DEFINE(M_AUDITBSM, "audit_bsm", "Audit BSM data");
56
57/*
58 * Forward declares.
59 */
60static void	audit_sys_auditon(struct audit_record *ar,
61		    struct au_record *rec);
62
63/*
64 * Initialize the BSM auditing subsystem.
65 */
66void
67kau_init(void)
68{
69
70	printf("BSM auditing present\n");
71	au_evclassmap_init();
72}
73
74/*
75 * This call reserves memory for the audit record.  Memory must be guaranteed
76 * before any auditable event can be generated.  The au_record structure
77 * maintains a reference to the memory allocated above and also the list of
78 * tokens associated with this record
79 */
80static struct au_record *
81kau_open(void)
82{
83	struct au_record *rec;
84
85	rec = malloc(sizeof(*rec), M_AUDITBSM, M_WAITOK);
86	rec->data = malloc(MAX_AUDIT_RECORD_SIZE * sizeof(u_char),
87	    M_AUDITBSM, M_WAITOK | M_ZERO);
88	TAILQ_INIT(&rec->token_q);
89	rec->len = 0;
90	rec->used = 1;
91
92	return (rec);
93}
94
95/*
96 * Store the token with the record descriptor.
97 */
98static void
99kau_write(struct au_record *rec, struct au_token *tok)
100{
101
102	KASSERT(tok != NULL, ("kau_write: tok == NULL"));
103
104	TAILQ_INSERT_TAIL(&rec->token_q, tok, tokens);
105	rec->len += tok->len;
106}
107
108/*
109 * Close out the audit record by adding the header token, identifying any
110 * missing tokens.  Write out the tokens to the record memory.
111 */
112static void
113kau_close(struct au_record *rec, struct timespec *ctime, short event)
114{
115	u_char *dptr;
116	size_t tot_rec_size;
117	token_t *cur, *hdr, *trail;
118	struct timeval tm;
119
120	tot_rec_size = rec->len + BSM_HEADER_SIZE + BSM_TRAILER_SIZE;
121	if (tot_rec_size <= MAX_AUDIT_RECORD_SIZE) {
122		/* Create the header token */
123		tm.tv_usec = ctime->tv_nsec / 1000;
124		tm.tv_sec = ctime->tv_sec;
125		hdr = au_to_header32_tm(tot_rec_size, event, 0, tm);
126		TAILQ_INSERT_HEAD(&rec->token_q, hdr, tokens);
127
128		trail = au_to_trailer(tot_rec_size);
129		TAILQ_INSERT_TAIL(&rec->token_q, trail, tokens);
130
131		/* Serialize token data to the record. */
132		rec->len = tot_rec_size;
133		dptr = rec->data;
134		TAILQ_FOREACH(cur, &rec->token_q, tokens) {
135			memcpy(dptr, cur->t_data, cur->len);
136			dptr += cur->len;
137		}
138	}
139}
140
141/*
142 * Free a BSM audit record by releasing all the tokens and clearing the audit
143 * record information.
144 */
145void
146kau_free(struct au_record *rec)
147{
148	struct au_token *tok;
149
150	/* Free the token list. */
151	while ((tok = TAILQ_FIRST(&rec->token_q))) {
152		TAILQ_REMOVE(&rec->token_q, tok, tokens);
153		free(tok->t_data, M_AUDITBSM);
154		free(tok, M_AUDITBSM);
155	}
156
157	rec->used = 0;
158	rec->len = 0;
159	free(rec->data, M_AUDITBSM);
160	free(rec, M_AUDITBSM);
161}
162
163/*
164 * XXX May want turn some (or all) of these macros into functions in order
165 * to reduce the generated code sized.
166 *
167 * XXXAUDIT: These macros assume that 'kar', 'ar', 'rec', and 'tok' in the
168 * caller are OK with this.
169 */
170#define UPATH1_TOKENS do {						\
171	if (ARG_IS_VALID(kar, ARG_UPATH1)) {				\
172		tok = au_to_path(ar->ar_arg_upath1);			\
173		kau_write(rec, tok);					\
174	}								\
175} while (0)
176
177#define UPATH2_TOKENS do {						\
178	if (ARG_IS_VALID(kar, ARG_UPATH2)) {				\
179		tok = au_to_path(ar->ar_arg_upath2);			\
180		kau_write(rec, tok);					\
181	}								\
182} while (0)
183
184#define VNODE1_TOKENS do {						\
185	if (ARG_IS_VALID(kar, ARG_VNODE1)) {  				\
186		tok = au_to_attr32(&ar->ar_arg_vnode1);			\
187		kau_write(rec, tok);					\
188	}								\
189} while (0)
190
191#define UPATH1_VNODE1_TOKENS do {					\
192	if (ARG_IS_VALID(kar, ARG_UPATH1)) {  				\
193		UPATH1_TOKENS;						\
194	}								\
195	if (ARG_IS_VALID(kar, ARG_VNODE1)) {  				\
196		tok = au_to_attr32(&ar->ar_arg_vnode1);			\
197		kau_write(rec, tok);					\
198	}								\
199} while (0)
200
201#define VNODE2_TOKENS do {						\
202	if (ARG_IS_VALID(kar, ARG_VNODE2)) {  				\
203		tok = au_to_attr32(&ar->ar_arg_vnode2);			\
204		kau_write(rec, tok);					\
205	}								\
206} while (0)
207
208#define FD_VNODE1_TOKENS	do {					\
209	if (ARG_IS_VALID(kar, ARG_VNODE1)) {				\
210		if (ARG_IS_VALID(kar, ARG_FD)) {			\
211			tok = au_to_arg32(1, "fd", ar->ar_arg_fd);	\
212			kau_write(rec, tok);				\
213		}							\
214		tok = au_to_attr32(&ar->ar_arg_vnode1);			\
215		kau_write(rec, tok);					\
216	} else {							\
217		if (ARG_IS_VALID(kar, ARG_FD)) {			\
218			tok = au_to_arg32(1, "non-file: fd",		\
219			    ar->ar_arg_fd);				\
220			kau_write(rec, tok);				\
221		}							\
222	}								\
223} while (0)
224
225#define PROCESS_PID_TOKENS(argn) do {					\
226	if (ARG_IS_VALID(kar, ARG_PID)) {				\
227		if ((ar->ar_arg_pid > 0) /* Kill a single process */	\
228		    && (ARG_IS_VALID(kar, ARG_PROCESS))) {		\
229			tok = au_to_process(ar->ar_arg_auid,		\
230			    ar->ar_arg_euid, ar->ar_arg_egid,		\
231			    ar->ar_arg_ruid, ar->ar_arg_rgid,		\
232			    ar->ar_arg_pid, ar->ar_arg_asid,		\
233			    &ar->ar_arg_termid);			\
234			kau_write(rec, tok);				\
235		} else {						\
236			tok = au_to_arg32(argn, "process",		\
237			    ar->ar_arg_pid);				\
238			kau_write(rec, tok);				\
239		}							\
240	}								\
241} while (0)								\
242
243/*
244 * Implement auditing for the auditon() system call. The audit tokens that
245 * are generated depend on the command that was sent into the auditon()
246 * system call.
247 */
248static void
249audit_sys_auditon(struct audit_record *ar, struct au_record *rec)
250{
251	struct au_token *tok;
252
253	switch (ar->ar_arg_cmd) {
254	case A_SETPOLICY:
255		if (sizeof(ar->ar_arg_auditon.au_flags) > 4)
256			tok = au_to_arg64(1, "policy",
257			    ar->ar_arg_auditon.au_flags);
258		else
259			tok = au_to_arg32(1, "policy",
260			    ar->ar_arg_auditon.au_flags);
261		kau_write(rec, tok);
262		break;
263
264	case A_SETKMASK:
265		tok = au_to_arg32(2, "setkmask:as_success",
266		    ar->ar_arg_auditon.au_mask.am_success);
267		kau_write(rec, tok);
268		tok = au_to_arg32(2, "setkmask:as_failure",
269		    ar->ar_arg_auditon.au_mask.am_failure);
270		kau_write(rec, tok);
271		break;
272
273	case A_SETQCTRL:
274		tok = au_to_arg32(3, "setqctrl:aq_hiwater",
275		    ar->ar_arg_auditon.au_qctrl.aq_hiwater);
276		kau_write(rec, tok);
277		tok = au_to_arg32(3, "setqctrl:aq_lowater",
278		    ar->ar_arg_auditon.au_qctrl.aq_lowater);
279		kau_write(rec, tok);
280		tok = au_to_arg32(3, "setqctrl:aq_bufsz",
281		    ar->ar_arg_auditon.au_qctrl.aq_bufsz);
282		kau_write(rec, tok);
283		tok = au_to_arg32(3, "setqctrl:aq_delay",
284		    ar->ar_arg_auditon.au_qctrl.aq_delay);
285		kau_write(rec, tok);
286		tok = au_to_arg32(3, "setqctrl:aq_minfree",
287		    ar->ar_arg_auditon.au_qctrl.aq_minfree);
288		kau_write(rec, tok);
289		break;
290
291	case A_SETUMASK:
292		tok = au_to_arg32(3, "setumask:as_success",
293		    ar->ar_arg_auditon.au_auinfo.ai_mask.am_success);
294		kau_write(rec, tok);
295		tok = au_to_arg32(3, "setumask:as_failure",
296		    ar->ar_arg_auditon.au_auinfo.ai_mask.am_failure);
297		kau_write(rec, tok);
298		break;
299
300	case A_SETSMASK:
301		tok = au_to_arg32(3, "setsmask:as_success",
302		    ar->ar_arg_auditon.au_auinfo.ai_mask.am_success);
303		kau_write(rec, tok);
304		tok = au_to_arg32(3, "setsmask:as_failure",
305		    ar->ar_arg_auditon.au_auinfo.ai_mask.am_failure);
306		kau_write(rec, tok);
307		break;
308
309	case A_SETCOND:
310		if (sizeof(ar->ar_arg_auditon.au_cond) > 4)
311			tok = au_to_arg64(3, "setcond",
312			    ar->ar_arg_auditon.au_cond);
313		else
314			tok = au_to_arg32(3, "setcond",
315			    ar->ar_arg_auditon.au_cond);
316		kau_write(rec, tok);
317		break;
318
319	case A_SETCLASS:
320		tok = au_to_arg32(2, "setclass:ec_event",
321		    ar->ar_arg_auditon.au_evclass.ec_number);
322		kau_write(rec, tok);
323		tok = au_to_arg32(3, "setclass:ec_class",
324		    ar->ar_arg_auditon.au_evclass.ec_class);
325		kau_write(rec, tok);
326		break;
327
328	case A_SETPMASK:
329		tok = au_to_arg32(2, "setpmask:as_success",
330		    ar->ar_arg_auditon.au_aupinfo.ap_mask.am_success);
331		kau_write(rec, tok);
332		tok = au_to_arg32(2, "setpmask:as_failure",
333		    ar->ar_arg_auditon.au_aupinfo.ap_mask.am_failure);
334		kau_write(rec, tok);
335		break;
336
337	case A_SETFSIZE:
338		tok = au_to_arg32(2, "setfsize:filesize",
339		    ar->ar_arg_auditon.au_fstat.af_filesz);
340		kau_write(rec, tok);
341		break;
342
343	default:
344		break;
345	}
346}
347
348/*
349 * Convert an internal kernel audit record to a BSM record and return a
350 * success/failure indicator. The BSM record is passed as an out parameter to
351 * this function.
352 *
353 * Return conditions:
354 *   BSM_SUCCESS: The BSM record is valid
355 *   BSM_FAILURE: Failure; the BSM record is NULL.
356 *   BSM_NOAUDIT: The event is not auditable for BSM; the BSM record is NULL.
357 */
358int
359kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
360{
361	struct au_token *tok, *subj_tok;
362	struct au_record *rec;
363	au_tid_t tid;
364	struct audit_record *ar;
365	int ctr;
366
367	KASSERT(kar != NULL, ("kaudit_to_bsm: kar == NULL"));
368
369	*pau = NULL;
370	ar = &kar->k_ar;
371	rec = kau_open();
372
373	/* Create the subject token */
374	tid.port = ar->ar_subj_term.port;
375	tid.machine = ar->ar_subj_term.machine;
376	subj_tok = au_to_subject32(ar->ar_subj_auid,  /* audit ID */
377		ar->ar_subj_cred.cr_uid, /* eff uid */
378		ar->ar_subj_egid,	/* eff group id */
379		ar->ar_subj_ruid, 	/* real uid */
380		ar->ar_subj_rgid, 	/* real group id */
381		ar->ar_subj_pid,	/* process id */
382		ar->ar_subj_asid,	/* session ID */
383		&tid);
384
385	/*
386	 * The logic inside each case fills in the tokens required for the
387	 * event, except for the header, trailer, and return tokens.  The
388	 * header and trailer tokens are added by the kau_close() function.
389	 * The return token is added outside of the switch statement.
390	 */
391	switch(ar->ar_event) {
392	case AUE_ACCEPT:
393	case AUE_BIND:
394	case AUE_CONNECT:
395	case AUE_RECVFROM:
396	case AUE_RECVMSG:
397	case AUE_SENDMSG:
398	case AUE_SENDTO:
399		/*
400		 * Socket-related events.
401		 */
402		if (ARG_IS_VALID(kar, ARG_FD)) {
403			tok = au_to_arg32(1, "fd", ar->ar_arg_fd);
404			kau_write(rec, tok);
405		}
406		if (ARG_IS_VALID(kar, ARG_SADDRINET)) {
407			tok = au_to_sock_inet((struct sockaddr_in *)
408			    &ar->ar_arg_sockaddr);
409			kau_write(rec, tok);
410		}
411		if (ARG_IS_VALID(kar, ARG_SADDRUNIX)) {
412			tok = au_to_sock_unix((struct sockaddr_un *)
413			    &ar->ar_arg_sockaddr);
414			kau_write(rec, tok);
415			UPATH1_TOKENS;
416		}
417		/* XXX Need to handle ARG_SADDRINET6 */
418		break;
419
420	case AUE_SOCKET:
421	case AUE_SOCKETPAIR:
422		if (ARG_IS_VALID(kar, ARG_SOCKINFO)) {
423			tok = au_to_arg32(1,"domain",
424			    ar->ar_arg_sockinfo.so_domain);
425			kau_write(rec, tok);
426			tok = au_to_arg32(2,"type",
427			    ar->ar_arg_sockinfo.so_type);
428			kau_write(rec, tok);
429			tok = au_to_arg32(3,"protocol",
430			    ar->ar_arg_sockinfo.so_protocol);
431			kau_write(rec, tok);
432		}
433		break;
434
435	case AUE_SETSOCKOPT:
436	case AUE_SHUTDOWN:
437		if (ARG_IS_VALID(kar, ARG_FD)) {
438			tok = au_to_arg32(1, "fd", ar->ar_arg_fd);
439			kau_write(rec, tok);
440		}
441		break;
442
443	case AUE_ACCT:
444		if (ARG_IS_VALID(kar, ARG_UPATH1)) {
445			UPATH1_VNODE1_TOKENS;
446		} else {
447			tok = au_to_arg32(1, "accounting off", 0);
448			kau_write(rec, tok);
449		}
450		break;
451
452	case AUE_SETAUID:
453		if (ARG_IS_VALID(kar, ARG_AUID)) {
454			tok = au_to_arg32(2, "setauid", ar->ar_arg_auid);
455			kau_write(rec, tok);
456		}
457		break;
458
459	case AUE_SETAUDIT:
460		if (ARG_IS_VALID(kar, ARG_AUID)) {
461			tok = au_to_arg32(1, "setaudit:auid",
462			    ar->ar_arg_auid);
463			kau_write(rec, tok);
464			tok = au_to_arg32(1, "setaudit:port",
465			    ar->ar_arg_termid.port);
466			kau_write(rec, tok);
467			tok = au_to_arg32(1, "setaudit:machine",
468			    ar->ar_arg_termid.machine);
469			kau_write(rec, tok);
470			tok = au_to_arg32(1, "setaudit:as_success",
471			    ar->ar_arg_amask.am_success);
472			kau_write(rec, tok);
473			tok = au_to_arg32(1, "setaudit:as_failure",
474			    ar->ar_arg_amask.am_failure);
475			kau_write(rec, tok);
476			tok = au_to_arg32(1, "setaudit:asid",
477			    ar->ar_arg_asid);
478			kau_write(rec, tok);
479		}
480		break;
481
482	case AUE_SETAUDIT_ADDR:
483		break;		/* XXX need to add arguments */
484
485	case AUE_AUDITON:
486		/*
487		 * For AUDITON commands without own event, audit the cmd.
488		 */
489		if (ARG_IS_VALID(kar, ARG_CMD)) {
490			tok = au_to_arg32(1, "cmd", ar->ar_arg_cmd);
491			kau_write(rec, tok);
492		}
493		/* fall thru */
494
495	case AUE_AUDITON_GETCAR:
496	case AUE_AUDITON_GETCLASS:
497	case AUE_AUDITON_GETCOND:
498	case AUE_AUDITON_GETCWD:
499	case AUE_AUDITON_GETKMASK:
500	case AUE_AUDITON_GETSTAT:
501	case AUE_AUDITON_GPOLICY:
502	case AUE_AUDITON_GQCTRL:
503	case AUE_AUDITON_SETCLASS:
504	case AUE_AUDITON_SETCOND:
505	case AUE_AUDITON_SETKMASK:
506	case AUE_AUDITON_SETSMASK:
507	case AUE_AUDITON_SETSTAT:
508	case AUE_AUDITON_SETUMASK:
509	case AUE_AUDITON_SPOLICY:
510	case AUE_AUDITON_SQCTRL:
511		if (ARG_IS_VALID(kar, ARG_AUDITON))
512			audit_sys_auditon(ar, rec);
513		break;
514
515	case AUE_AUDITCTL:
516		UPATH1_VNODE1_TOKENS;
517		break;
518
519	case AUE_EXIT:
520		if (ARG_IS_VALID(kar, ARG_EXIT)) {
521			tok = au_to_exit(ar->ar_arg_exitretval,
522			    ar->ar_arg_exitstatus);
523			kau_write(rec, tok);
524		}
525		break;
526
527	case AUE_ADJTIME:
528	case AUE_AUDIT:
529	case AUE_GETAUDIT:
530	case AUE_GETAUDIT_ADDR:
531	case AUE_GETAUID:
532	case AUE_GETFSSTAT:
533	case AUE_PIPE:
534	case AUE_SETPGRP:
535	case AUE_SETRLIMIT:
536	case AUE_SETSID:
537	case AUE_SETTIMEOFDAY:
538	case AUE_NEWSYSTEMSHREG:
539		/*
540		 * Header, subject, and return tokens added at end.
541		 */
542		break;
543
544	case AUE_ACCESS:
545	case AUE_CHDIR:
546	case AUE_CHROOT:
547	case AUE_EACCESS:
548	case AUE_EXECVE:
549	case AUE_GETATTRLIST:
550	case AUE_NFS_GETFH:
551	case AUE_LSTAT:
552	case AUE_MKFIFO:
553	case AUE_PATHCONF:
554	case AUE_READLINK:
555	case AUE_REVOKE:
556	case AUE_RMDIR:
557	case AUE_SEARCHFS:
558	case AUE_SETATTRLIST:
559	case AUE_STAT:
560	case AUE_STATFS:
561	case AUE_TRUNCATE:
562	case AUE_UNDELETE:
563	case AUE_UNLINK:
564	case AUE_UTIMES:
565		UPATH1_VNODE1_TOKENS;
566		break;
567
568	case AUE_CHFLAGS:
569	case AUE_LCHFLAGS:
570		if (ARG_IS_VALID(kar, ARG_FFLAGS)) {
571			tok = au_to_arg32(2, "flags", ar->ar_arg_fflags);
572			kau_write(rec, tok);
573		}
574		UPATH1_VNODE1_TOKENS;
575		break;
576
577	case AUE_CHMOD:
578	case AUE_LCHMOD:
579		if (ARG_IS_VALID(kar, ARG_MODE)) {
580			tok = au_to_arg32(2, "new file mode",
581			    ar->ar_arg_mode);
582			kau_write(rec, tok);
583		}
584		UPATH1_VNODE1_TOKENS;
585		break;
586
587	case AUE_CHOWN:
588	case AUE_LCHOWN:
589		if (ARG_IS_VALID(kar, ARG_UID)) {
590			tok = au_to_arg32(2, "new file uid", ar->ar_arg_uid);
591			kau_write(rec, tok);
592		}
593		if (ARG_IS_VALID(kar, ARG_GID)) {
594			tok = au_to_arg32(3, "new file gid", ar->ar_arg_gid);
595			kau_write(rec, tok);
596		}
597		UPATH1_VNODE1_TOKENS;
598		break;
599
600	case AUE_EXCHANGEDATA:
601		UPATH1_VNODE1_TOKENS;
602		UPATH2_TOKENS;
603		break;
604
605	case AUE_CLOSE:
606		if (ARG_IS_VALID(kar, ARG_FD)) {
607			tok = au_to_arg32(2, "fd", ar->ar_arg_fd);
608			kau_write(rec, tok);
609		}
610		UPATH1_VNODE1_TOKENS;
611		break;
612
613	case AUE_FCHMOD:
614		if (ARG_IS_VALID(kar, ARG_MODE)) {
615			tok = au_to_arg32(2, "new file mode",
616			    ar->ar_arg_mode);
617			kau_write(rec, tok);
618		}
619		FD_VNODE1_TOKENS;
620		break;
621
622	case AUE_FCHDIR:
623	case AUE_FPATHCONF:
624	case AUE_FSTAT:		/* XXX Need to handle sockets and shm */
625	case AUE_FSTATFS:
626	case AUE_FSYNC:
627	case AUE_FTRUNCATE:
628	case AUE_FUTIMES:
629	case AUE_GETDIRENTRIES:
630	case AUE_GETDIRENTRIESATTR:
631		FD_VNODE1_TOKENS;
632		break;
633
634	case AUE_FCHOWN:
635		if (ARG_IS_VALID(kar, ARG_UID)) {
636			tok = au_to_arg32(2, "new file uid", ar->ar_arg_uid);
637			kau_write(rec, tok);
638		}
639		if (ARG_IS_VALID(kar, ARG_GID)) {
640			tok = au_to_arg32(3, "new file gid", ar->ar_arg_gid);
641			kau_write(rec, tok);
642		}
643		FD_VNODE1_TOKENS;
644		break;
645
646	case AUE_FCNTL:
647		if (ar->ar_arg_cmd == F_GETLK || ar->ar_arg_cmd == F_SETLK ||
648			ar->ar_arg_cmd == F_SETLKW) {
649			if (ARG_IS_VALID(kar, ARG_CMD)) {
650				tok = au_to_arg32(2, "cmd", ar->ar_arg_cmd);
651				kau_write(rec, tok);
652			}
653			FD_VNODE1_TOKENS;
654		}
655		break;
656
657	case AUE_FCHFLAGS:
658		if (ARG_IS_VALID(kar, ARG_FFLAGS)) {
659			tok = au_to_arg32(2, "flags", ar->ar_arg_fflags);
660			kau_write(rec, tok);
661		}
662		FD_VNODE1_TOKENS;
663		break;
664
665	case AUE_FLOCK:
666		if (ARG_IS_VALID(kar, ARG_CMD)) {
667			tok = au_to_arg32(2, "operation", ar->ar_arg_cmd);
668			kau_write(rec, tok);
669		}
670		FD_VNODE1_TOKENS;
671		break;
672
673	case AUE_RFORK:
674		if (ARG_IS_VALID(kar, ARG_FFLAGS)) {
675			tok = au_to_arg32(1, "flags", ar->ar_arg_fflags);
676			kau_write(rec, tok);
677		}
678		/* fall through */
679	case AUE_FORK:
680	case AUE_VFORK:
681		if (ARG_IS_VALID(kar, ARG_PID)) {
682			tok = au_to_arg32(0, "child PID", ar->ar_arg_pid);
683			kau_write(rec, tok);
684		}
685		break;
686
687	case AUE_IOCTL:
688		if (ARG_IS_VALID(kar, ARG_CMD)) {
689			tok = au_to_arg32(2, "cmd", ar->ar_arg_cmd);
690			kau_write(rec, tok);
691		}
692		if (ARG_IS_VALID(kar, ARG_ADDR)) {
693			tok = au_to_arg32(1, "arg",
694			    (u_int32_t)(uintptr_t)ar->ar_arg_addr);
695			kau_write(rec, tok);
696		}
697		if (ARG_IS_VALID(kar, ARG_VNODE1))
698			FD_VNODE1_TOKENS;
699		else {
700			if (ARG_IS_VALID(kar, ARG_SOCKINFO)) {
701				tok = kau_to_socket(&ar->ar_arg_sockinfo);
702				kau_write(rec, tok);
703			} else {
704				if (ARG_IS_VALID(kar, ARG_FD)) {
705					tok = au_to_arg32(1, "fd",
706					    ar->ar_arg_fd);
707			    		kau_write(rec, tok);
708				}
709			}
710		}
711		break;
712
713	case AUE_KILL:
714		if (ARG_IS_VALID(kar, ARG_SIGNUM)) {
715			tok = au_to_arg32(2, "signal", ar->ar_arg_signum);
716			kau_write(rec, tok);
717		}
718		PROCESS_PID_TOKENS(1);
719		break;
720
721	case AUE_KTRACE:
722		if (ARG_IS_VALID(kar, ARG_CMD)) {
723			tok = au_to_arg32(2, "ops", ar->ar_arg_cmd);
724			kau_write(rec, tok);
725		}
726		if (ARG_IS_VALID(kar, ARG_VALUE)) {
727			tok = au_to_arg32(3, "trpoints", ar->ar_arg_value);
728			kau_write(rec, tok);
729		}
730		PROCESS_PID_TOKENS(4);
731		UPATH1_VNODE1_TOKENS;
732		break;
733
734	case AUE_LINK:
735	case AUE_RENAME:
736		UPATH1_VNODE1_TOKENS;
737		UPATH2_TOKENS;
738		break;
739
740	case AUE_LOADSHFILE:
741		if (ARG_IS_VALID(kar, ARG_ADDR)) {
742			tok = au_to_arg32(4, "base addr",
743			    (u_int32_t)(uintptr_t)ar->ar_arg_addr);
744			kau_write(rec, tok);
745		}
746		UPATH1_VNODE1_TOKENS;
747		break;
748
749	case AUE_MKDIR:
750		if (ARG_IS_VALID(kar, ARG_MODE)) {
751			tok = au_to_arg32(2, "mode", ar->ar_arg_mode);
752			kau_write(rec, tok);
753		}
754		UPATH1_VNODE1_TOKENS;
755		break;
756
757	case AUE_MKNOD:
758		if (ARG_IS_VALID(kar, ARG_MODE)) {
759			tok = au_to_arg32(2, "mode", ar->ar_arg_mode);
760			kau_write(rec, tok);
761		}
762		if (ARG_IS_VALID(kar, ARG_DEV)) {
763			tok = au_to_arg32(3, "dev", ar->ar_arg_dev);
764			kau_write(rec, tok);
765		}
766		UPATH1_VNODE1_TOKENS;
767		break;
768
769	case AUE_MMAP:
770	case AUE_MUNMAP:
771	case AUE_MPROTECT:
772	case AUE_MLOCK:
773	case AUE_MUNLOCK:
774	case AUE_MINHERIT:
775		if (ARG_IS_VALID(kar, ARG_ADDR)) {
776			tok = au_to_arg32(1, "addr",
777			    (u_int32_t)(uintptr_t)ar->ar_arg_addr);
778			kau_write(rec, tok);
779		}
780		if (ARG_IS_VALID(kar, ARG_LEN)) {
781			tok = au_to_arg32(2, "len", ar->ar_arg_len);
782			kau_write(rec, tok);
783		}
784		if (ar->ar_event == AUE_MMAP)
785			FD_VNODE1_TOKENS;
786		if (ar->ar_event == AUE_MPROTECT) {
787			if (ARG_IS_VALID(kar, ARG_VALUE)) {
788				tok = au_to_arg32(3, "protection",
789				    ar->ar_arg_value);
790				kau_write(rec, tok);
791			}
792		}
793		if (ar->ar_event == AUE_MINHERIT) {
794			if (ARG_IS_VALID(kar, ARG_VALUE)) {
795				tok = au_to_arg32(3, "inherit",
796				    ar->ar_arg_value);
797				kau_write(rec, tok);
798			}
799		}
800		break;
801
802	case AUE_MOUNT:
803		/* XXX Need to handle NFS mounts */
804		if (ARG_IS_VALID(kar, ARG_FFLAGS)) {
805			tok = au_to_arg32(3, "flags", ar->ar_arg_fflags);
806			kau_write(rec, tok);
807		}
808		if (ARG_IS_VALID(kar, ARG_TEXT)) {
809			tok = au_to_text(ar->ar_arg_text);
810			kau_write(rec, tok);
811		}
812		/* fall through */
813
814	case AUE_UMOUNT:
815		UPATH1_VNODE1_TOKENS;
816		break;
817
818	case AUE_MSGCTL:
819		ar->ar_event = msgctl_to_event(ar->ar_arg_svipc_cmd);
820		/* Fall through */
821
822	case AUE_MSGRCV:
823	case AUE_MSGSND:
824		tok = au_to_arg32(1, "msg ID", ar->ar_arg_svipc_id);
825		kau_write(rec, tok);
826		if (ar->ar_errno != EINVAL) {
827			tok = au_to_ipc(AT_IPC_MSG, ar->ar_arg_svipc_id);
828			kau_write(rec, tok);
829		}
830		break;
831
832	case AUE_MSGGET:
833		if (ar->ar_errno == 0) {
834			if (ARG_IS_VALID(kar, ARG_SVIPC_ID)) {
835				tok = au_to_ipc(AT_IPC_MSG,
836				    ar->ar_arg_svipc_id);
837				kau_write(rec, tok);
838			}
839		}
840		break;
841
842	case AUE_RESETSHFILE:
843		if (ARG_IS_VALID(kar, ARG_ADDR)) {
844			tok = au_to_arg32(1, "base addr",
845			    (u_int32_t)(uintptr_t)ar->ar_arg_addr);
846			kau_write(rec, tok);
847		}
848		break;
849
850	case AUE_OPEN_RC:
851	case AUE_OPEN_RTC:
852	case AUE_OPEN_RWC:
853	case AUE_OPEN_RWTC:
854	case AUE_OPEN_WC:
855	case AUE_OPEN_WTC:
856	/* case AUE_O_CREAT: */		/* AUE_O_CREAT == AUE_OPEN_RWTC */
857		if (ARG_IS_VALID(kar, ARG_MODE)) {
858			tok = au_to_arg32(3, "mode", ar->ar_arg_mode);
859			kau_write(rec, tok);
860		}
861		/* fall through */
862
863	case AUE_OPEN_R:
864	case AUE_OPEN_RT:
865	case AUE_OPEN_RW:
866	case AUE_OPEN_RWT:
867	case AUE_OPEN_W:
868	case AUE_OPEN_WT:
869		if (ARG_IS_VALID(kar, ARG_FFLAGS)) {
870			tok = au_to_arg32(2, "flags", ar->ar_arg_fflags);
871			kau_write(rec, tok);
872		}
873		UPATH1_VNODE1_TOKENS;
874		break;
875
876	case AUE_PTRACE:
877		if (ARG_IS_VALID(kar, ARG_CMD)) {
878			tok = au_to_arg32(1, "request", ar->ar_arg_cmd);
879			kau_write(rec, tok);
880		}
881		if (ARG_IS_VALID(kar, ARG_ADDR)) {
882			tok = au_to_arg32(3, "addr",
883			    (u_int32_t)(uintptr_t)ar->ar_arg_addr);
884			kau_write(rec, tok);
885		}
886		if (ARG_IS_VALID(kar, ARG_VALUE)) {
887			tok = au_to_arg32(4, "data", ar->ar_arg_value);
888			kau_write(rec, tok);
889		}
890		PROCESS_PID_TOKENS(2);
891		break;
892
893	case AUE_QUOTACTL:
894		if (ARG_IS_VALID(kar, ARG_CMD)) {
895			tok = au_to_arg32(2, "command", ar->ar_arg_cmd);
896			kau_write(rec, tok);
897		}
898		if (ARG_IS_VALID(kar, ARG_UID)) {
899			tok = au_to_arg32(3, "uid", ar->ar_arg_uid);
900			kau_write(rec, tok);
901		}
902		UPATH1_VNODE1_TOKENS;
903		break;
904
905	case AUE_REBOOT:
906		if (ARG_IS_VALID(kar, ARG_CMD)) {
907			tok = au_to_arg32(1, "howto", ar->ar_arg_cmd);
908			kau_write(rec, tok);
909		}
910		break;
911
912	case AUE_SEMCTL:
913		ar->ar_event = semctl_to_event(ar->ar_arg_svipc_cmd);
914		/* Fall through */
915
916	case AUE_SEMOP:
917		if (ARG_IS_VALID(kar, ARG_SVIPC_ID)) {
918			tok = au_to_arg32(1, "sem ID", ar->ar_arg_svipc_id);
919			kau_write(rec, tok);
920			if (ar->ar_errno != EINVAL) {
921				tok = au_to_ipc(AT_IPC_SEM,
922				    ar->ar_arg_svipc_id);
923				kau_write(rec, tok);
924			}
925		}
926		break;
927
928	case AUE_SEMGET:
929		if (ar->ar_errno == 0) {
930			if (ARG_IS_VALID(kar, ARG_SVIPC_ID)) {
931				tok = au_to_ipc(AT_IPC_SEM,
932				    ar->ar_arg_svipc_id);
933				kau_write(rec, tok);
934			}
935		}
936		break;
937
938	case AUE_SETEGID:
939		if (ARG_IS_VALID(kar, ARG_EGID)) {
940			tok = au_to_arg32(1, "gid", ar->ar_arg_egid);
941			kau_write(rec, tok);
942		}
943		break;
944
945	case AUE_SETEUID:
946		if (ARG_IS_VALID(kar, ARG_EUID)) {
947			tok = au_to_arg32(1, "uid", ar->ar_arg_euid);
948			kau_write(rec, tok);
949		}
950		break;
951
952	case AUE_SETREGID:
953		if (ARG_IS_VALID(kar, ARG_RGID)) {
954			tok = au_to_arg32(1, "rgid", ar->ar_arg_rgid);
955			kau_write(rec, tok);
956		}
957		if (ARG_IS_VALID(kar, ARG_EGID)) {
958			tok = au_to_arg32(2, "egid", ar->ar_arg_egid);
959			kau_write(rec, tok);
960		}
961		break;
962
963	case AUE_SETREUID:
964		if (ARG_IS_VALID(kar, ARG_RUID)) {
965			tok = au_to_arg32(1, "ruid", ar->ar_arg_ruid);
966			kau_write(rec, tok);
967		}
968		if (ARG_IS_VALID(kar, ARG_EUID)) {
969			tok = au_to_arg32(2, "euid", ar->ar_arg_euid);
970			kau_write(rec, tok);
971		}
972		break;
973
974	case AUE_SETRESGID:
975		if (ARG_IS_VALID(kar, ARG_RGID)) {
976			tok = au_to_arg32(1, "rgid", ar->ar_arg_rgid);
977			kau_write(rec, tok);
978		}
979		if (ARG_IS_VALID(kar, ARG_EGID)) {
980			tok = au_to_arg32(2, "egid", ar->ar_arg_egid);
981			kau_write(rec, tok);
982		}
983		if (ARG_IS_VALID(kar, ARG_SGID)) {
984			tok = au_to_arg32(3, "sgid", ar->ar_arg_sgid);
985			kau_write(rec, tok);
986		}
987		break;
988
989	case AUE_SETRESUID:
990		if (ARG_IS_VALID(kar, ARG_RUID)) {
991			tok = au_to_arg32(1, "ruid", ar->ar_arg_ruid);
992			kau_write(rec, tok);
993		}
994		if (ARG_IS_VALID(kar, ARG_EUID)) {
995			tok = au_to_arg32(2, "euid", ar->ar_arg_euid);
996			kau_write(rec, tok);
997		}
998		if (ARG_IS_VALID(kar, ARG_SUID)) {
999			tok = au_to_arg32(3, "suid", ar->ar_arg_suid);
1000			kau_write(rec, tok);
1001		}
1002		break;
1003
1004	case AUE_SETGID:
1005		if (ARG_IS_VALID(kar, ARG_GID)) {
1006			tok = au_to_arg32(1, "gid", ar->ar_arg_gid);
1007			kau_write(rec, tok);
1008		}
1009		break;
1010
1011	case AUE_SETUID:
1012		if (ARG_IS_VALID(kar, ARG_UID)) {
1013			tok = au_to_arg32(1, "uid", ar->ar_arg_uid);
1014			kau_write(rec, tok);
1015		}
1016		break;
1017
1018	case AUE_SETGROUPS:
1019		if (ARG_IS_VALID(kar, ARG_GROUPSET)) {
1020			for(ctr = 0; ctr < ar->ar_arg_groups.gidset_size; ctr++)
1021			{
1022				tok = au_to_arg32(1, "setgroups", 							ar->ar_arg_groups.gidset[ctr]);
1023				kau_write(rec, tok);
1024			}
1025		}
1026		break;
1027
1028	case AUE_SETLOGIN:
1029		if (ARG_IS_VALID(kar, ARG_TEXT)) {
1030			tok = au_to_text(ar->ar_arg_text);
1031			kau_write(rec, tok);
1032		}
1033		break;
1034
1035	case AUE_SETPRIORITY:
1036		if (ARG_IS_VALID(kar, ARG_CMD)) {
1037			tok = au_to_arg32(1, "which", ar->ar_arg_cmd);
1038			kau_write(rec, tok);
1039		}
1040		if (ARG_IS_VALID(kar, ARG_UID)) {
1041			tok = au_to_arg32(2, "who", ar->ar_arg_uid);
1042			kau_write(rec, tok);
1043		}
1044		if (ARG_IS_VALID(kar, ARG_VALUE)) {
1045			tok = au_to_arg32(2, "priority", ar->ar_arg_value);
1046			kau_write(rec, tok);
1047		}
1048		break;
1049
1050	case AUE_SETPRIVEXEC:
1051		if (ARG_IS_VALID(kar, ARG_VALUE)) {
1052			tok = au_to_arg32(1, "flag", ar->ar_arg_value);
1053			kau_write(rec, tok);
1054		}
1055		break;
1056
1057	/* AUE_SHMAT, AUE_SHMCTL, AUE_SHMDT and AUE_SHMGET are SysV IPC */
1058	case AUE_SHMAT:
1059		if (ARG_IS_VALID(kar, ARG_SVIPC_ID)) {
1060			tok = au_to_arg32(1, "shmid", ar->ar_arg_svipc_id);
1061			kau_write(rec, tok);
1062			/* XXXAUDIT: Does having the ipc token make sense? */
1063			tok = au_to_ipc(AT_IPC_SHM, ar->ar_arg_svipc_id);
1064			kau_write(rec, tok);
1065		}
1066		if (ARG_IS_VALID(kar, ARG_SVIPC_ADDR)) {
1067			tok = au_to_arg32(2, "shmaddr",
1068			    (int)(uintptr_t)ar->ar_arg_svipc_addr);
1069			kau_write(rec, tok);
1070		}
1071		if (ARG_IS_VALID(kar, ARG_SVIPC_PERM)) {
1072			tok = au_to_ipc_perm(&ar->ar_arg_svipc_perm);
1073			kau_write(rec, tok);
1074		}
1075		break;
1076
1077	case AUE_SHMCTL:
1078		if (ARG_IS_VALID(kar, ARG_SVIPC_ID)) {
1079			tok = au_to_arg32(1, "shmid", ar->ar_arg_svipc_id);
1080			kau_write(rec, tok);
1081			/* XXXAUDIT: Does having the ipc token make sense? */
1082			tok = au_to_ipc(AT_IPC_SHM, ar->ar_arg_svipc_id);
1083			kau_write(rec, tok);
1084		}
1085		switch (ar->ar_arg_svipc_cmd) {
1086		case IPC_STAT:
1087			ar->ar_event = AUE_SHMCTL_STAT;
1088			break;
1089		case IPC_RMID:
1090			ar->ar_event = AUE_SHMCTL_RMID;
1091			break;
1092		case IPC_SET:
1093			ar->ar_event = AUE_SHMCTL_SET;
1094			if (ARG_IS_VALID(kar, ARG_SVIPC_PERM)) {
1095				tok = au_to_ipc_perm(&ar->ar_arg_svipc_perm);
1096				kau_write(rec, tok);
1097			}
1098			break;
1099		default:
1100			break;	/* We will audit a bad command */
1101		}
1102		break;
1103
1104	case AUE_SHMDT:
1105		if (ARG_IS_VALID(kar, ARG_SVIPC_ADDR)) {
1106			tok = au_to_arg32(1, "shmaddr",
1107			    (int)(uintptr_t)ar->ar_arg_svipc_addr);
1108			kau_write(rec, tok);
1109		}
1110		break;
1111
1112	case AUE_SHMGET:
1113		/* This is unusual; the return value is in an argument token */
1114		if (ARG_IS_VALID(kar, ARG_SVIPC_ID)) {
1115			tok = au_to_arg32(0, "shmid", ar->ar_arg_svipc_id);
1116			kau_write(rec, tok);
1117			tok = au_to_ipc(AT_IPC_SHM, ar->ar_arg_svipc_id);
1118			kau_write(rec, tok);
1119		}
1120		if (ARG_IS_VALID(kar, ARG_SVIPC_PERM)) {
1121			tok = au_to_ipc_perm(&ar->ar_arg_svipc_perm);
1122			kau_write(rec, tok);
1123		}
1124		break;
1125
1126	/* AUE_SHMOPEN, AUE_SHMUNLINK, AUE_SEMOPEN, AUE_SEMCLOSE
1127	 * and AUE_SEMUNLINK are Posix IPC */
1128	case AUE_SHMOPEN:
1129		if (ARG_IS_VALID(kar, ARG_SVIPC_ADDR)) {
1130			tok = au_to_arg32(2, "flags", ar->ar_arg_fflags);
1131			kau_write(rec, tok);
1132		}
1133		if (ARG_IS_VALID(kar, ARG_MODE)) {
1134			tok = au_to_arg32(3, "mode", ar->ar_arg_mode);
1135			kau_write(rec, tok);
1136		}
1137	case AUE_SHMUNLINK:
1138		if (ARG_IS_VALID(kar, ARG_TEXT)) {
1139			tok = au_to_text(ar->ar_arg_text);
1140			kau_write(rec, tok);
1141		}
1142		if (ARG_IS_VALID(kar, ARG_POSIX_IPC_PERM)) {
1143		/* Create an ipc_perm token */
1144			struct ipc_perm perm;
1145			perm.uid = ar->ar_arg_pipc_perm.pipc_uid;
1146			perm.gid = ar->ar_arg_pipc_perm.pipc_gid;
1147			perm.cuid = ar->ar_arg_pipc_perm.pipc_uid;
1148			perm.cgid = ar->ar_arg_pipc_perm.pipc_gid;
1149			perm.mode = ar->ar_arg_pipc_perm.pipc_mode;
1150			perm.seq = 0;
1151			perm.key = 0;
1152			tok = au_to_ipc_perm(&perm);
1153			kau_write(rec, tok);
1154		}
1155		break;
1156
1157	case AUE_SEMOPEN:
1158		if (ARG_IS_VALID(kar, ARG_FFLAGS)) {
1159			tok = au_to_arg32(2, "flags", ar->ar_arg_fflags);
1160			kau_write(rec, tok);
1161		}
1162		if (ARG_IS_VALID(kar, ARG_MODE)) {
1163			tok = au_to_arg32(3, "mode", ar->ar_arg_mode);
1164			kau_write(rec, tok);
1165		}
1166		if (ARG_IS_VALID(kar, ARG_VALUE)) {
1167			tok = au_to_arg32(4, "value", ar->ar_arg_value);
1168			kau_write(rec, tok);
1169		}
1170		/* fall through */
1171
1172	case AUE_SEMUNLINK:
1173		if (ARG_IS_VALID(kar, ARG_TEXT)) {
1174			tok = au_to_text(ar->ar_arg_text);
1175			kau_write(rec, tok);
1176		}
1177		if (ARG_IS_VALID(kar, ARG_POSIX_IPC_PERM)) {
1178		/* Create an ipc_perm token */
1179			struct ipc_perm perm;
1180			perm.uid = ar->ar_arg_pipc_perm.pipc_uid;
1181			perm.gid = ar->ar_arg_pipc_perm.pipc_gid;
1182			perm.cuid = ar->ar_arg_pipc_perm.pipc_uid;
1183			perm.cgid = ar->ar_arg_pipc_perm.pipc_gid;
1184			perm.mode = ar->ar_arg_pipc_perm.pipc_mode;
1185			perm.seq = 0;
1186			perm.key = 0;
1187			tok = au_to_ipc_perm(&perm);
1188			kau_write(rec, tok);
1189		}
1190		break;
1191
1192	case AUE_SEMCLOSE:
1193		if (ARG_IS_VALID(kar, ARG_FD)) {
1194			tok = au_to_arg32(1, "sem", ar->ar_arg_fd);
1195			kau_write(rec, tok);
1196		}
1197		break;
1198
1199	case AUE_SYMLINK:
1200		if (ARG_IS_VALID(kar, ARG_TEXT)) {
1201			tok = au_to_text(ar->ar_arg_text);
1202			kau_write(rec, tok);
1203		}
1204		UPATH1_VNODE1_TOKENS;
1205		break;
1206
1207	case AUE_SYSCTL:
1208		if (ARG_IS_VALID(kar, ARG_CTLNAME | ARG_LEN)) {
1209			for (ctr = 0; ctr < ar->ar_arg_len; ctr++) {
1210				tok = au_to_arg32(1, "name",
1211				    ar->ar_arg_ctlname[ctr]);
1212				kau_write(rec, tok);
1213			}
1214		}
1215		if (ARG_IS_VALID(kar, ARG_VALUE)) {
1216			tok = au_to_arg32(5, "newval", ar->ar_arg_value);
1217			kau_write(rec, tok);
1218		}
1219		if (ARG_IS_VALID(kar, ARG_TEXT)) {
1220			tok = au_to_text(ar->ar_arg_text);
1221			kau_write(rec, tok);
1222		}
1223		break;
1224
1225	case AUE_UMASK:
1226		if (ARG_IS_VALID(kar, ARG_MASK)) {
1227			tok = au_to_arg32(1, "new mask", ar->ar_arg_mask);
1228			kau_write(rec, tok);
1229		}
1230		tok = au_to_arg32(0, "prev mask", ar->ar_retval);
1231		kau_write(rec, tok);
1232		break;
1233
1234	case AUE_WAIT4:
1235		if (ARG_IS_VALID(kar, ARG_PID)) {
1236			tok = au_to_arg32(0, "pid", ar->ar_arg_pid);
1237			kau_write(rec, tok);
1238		}
1239		break;
1240
1241	default:
1242		printf("BSM conversion requested for unknown event %d\n",
1243		    ar->ar_event);
1244		/* Write the subject token so it is properly freed here. */
1245		kau_write(rec, subj_tok);
1246		kau_free(rec);
1247		return (BSM_NOAUDIT);
1248	}
1249
1250	kau_write(rec, subj_tok);
1251	tok = au_to_return32((char)ar->ar_errno, ar->ar_retval);
1252	kau_write(rec, tok);  /* Every record gets a return token */
1253
1254	kau_close(rec, &ar->ar_endtime, ar->ar_event);
1255
1256	*pau = rec;
1257	return (BSM_SUCCESS);
1258}
1259
1260/*
1261 * Verify that a record is a valid BSM record. This verification is simple
1262 * now, but may be expanded on sometime in the future.  Return 1 if the
1263 * record is good, 0 otherwise.
1264 */
1265int
1266bsm_rec_verify(void *rec)
1267{
1268	char c = *(char *)rec;
1269
1270	/*
1271	 * Check the token ID of the first token; it has to be a header
1272	 * token.
1273	 *
1274	 * XXXAUDIT There needs to be a token structure to map a token.
1275	 * XXXAUDIT 'Shouldn't be simply looking at the first char.
1276	 */
1277	if ((c != AUT_HEADER32) && (c != AUT_HEADER32_EX) &&
1278	    (c != AUT_HEADER64) && (c != AUT_HEADER64_EX))
1279		return (0);
1280	return (1);
1281}
1282