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