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