xref: /titanic_51/usr/src/uts/common/c2/audit_syscalls.c (revision dcda19f50b2b80bfc622fff718ac04fb0e1cb670)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * This file contains the auditing system call code.
28  *
29  */
30 
31 
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/user.h>
35 #include <sys/vnode.h>
36 #include <sys/vfs.h>
37 #include <sys/session.h>	/* for session structure (auditctl(2) */
38 #include <sys/kmem.h>		/* for KM_SLEEP */
39 #include <sys/cred_impl.h>
40 #include <sys/types.h>
41 #include <sys/proc.h>
42 #include <sys/uio.h>
43 #include <sys/file.h>
44 #include <sys/stat.h>
45 #include <sys/pathname.h>
46 #include <sys/acct.h>
47 #include <sys/stropts.h>
48 #include <sys/exec.h>
49 #include <sys/thread.h>
50 #include <sys/cmn_err.h>
51 #include <sys/debug.h>
52 #include <sys/disp.h>
53 #include <sys/kobj.h>
54 #include <sys/sysmacros.h>
55 #include <sys/policy.h>
56 #include <sys/taskq.h>
57 #include <sys/zone.h>
58 
59 #include <c2/audit.h>
60 #include <c2/audit_kernel.h>
61 #include <c2/audit_record.h>
62 
63 #define	CLEAR_VAL	-1
64 
65 #define	HEADER_SIZE64	1;
66 #define	HEADER_SIZE32	0;
67 #define	AU_MIN_FILE_SZ	0x80000	/* minumum audit file size */
68 #define	AUDIT_REC_SIZE	0x8000	/* maximum user audit record size */
69 
70 extern kmutex_t pidlock;
71 
72 extern pri_t		minclsyspri;		/* priority for taskq */
73 
74 extern int audit_load;		/* defined in audit_start.c */
75 
76 int		au_auditstate = AUC_UNSET;	/* global audit state */
77 int		audit_policy;	/* global audit policies in force */
78 static clock_t	au_resid = 15;	/* wait .15 sec before droping a rec */
79 
80 static int	getauid(caddr_t);
81 static int	setauid(caddr_t);
82 static int	getaudit(caddr_t);
83 static int	getaudit_addr(caddr_t, int);
84 static int	setaudit(caddr_t);
85 static int	setaudit_addr(caddr_t, int);
86 static int	auditdoor(int);
87 static int	auditctl(int, caddr_t, int);
88 static int	audit_modsysent(char *, int, int (*)());
89 static void	au_output_thread();
90 /*
91  * This is the loadable module wrapper.
92  */
93 #include <sys/modctl.h>
94 #include "sys/syscall.h"
95 
96 static struct sysent auditsysent = {
97 	6,
98 	0,
99 	_auditsys
100 };
101 
102 /*
103  * Module linkage information for the kernel.
104  */
105 extern struct mod_ops mod_syscallops;
106 
107 static struct modlsys modlsys = {
108 	&mod_syscallops, "C2 system call", &auditsysent
109 };
110 
111 static struct modlinkage modlinkage = {
112 	MODREV_1, (void *)&modlsys, 0
113 };
114 
115 int
116 _init()
117 {
118 	int retval;
119 
120 	if (audit_load == 0)
121 		return (-1);
122 
123 	/*
124 	 * We are going to do an ugly thing here.
125 	 *  Because auditsys is already defined as a regular
126 	 *  syscall we have to change the definition for syscall
127 	 *  auditsys. Basically or in the SE_LOADABLE flag for
128 	 *  auditsys. We no have a static loadable syscall. Also
129 	 *  create an rw_lock.
130 	 */
131 
132 	if ((audit_modsysent("c2audit", SE_LOADABLE|SE_NOUNLOAD,
133 	    _auditsys)) == -1)
134 		return (-1);
135 
136 	if ((retval = mod_install(&modlinkage)) != 0)
137 		return (retval);
138 
139 	return (0);
140 }
141 
142 int
143 _fini()
144 {
145 	return (EBUSY);
146 }
147 
148 int
149 _info(struct modinfo *modinfop)
150 {
151 	return (mod_info(&modlinkage, modinfop));
152 }
153 
154 /*
155  * when auditing is updated to allow enable/disable without
156  * reboot (and when the audit stubs are removed) *most* of these
157  * calls should return an error when auditing is off -- some
158  * for local zones only.
159  */
160 
161 int
162 _auditsys(struct auditcalls *uap, rval_t *rvp)
163 {
164 	int result = 0;
165 
166 	switch (uap->code) {
167 	case BSM_GETAUID:
168 		result = getauid((caddr_t)uap->a1);
169 		break;
170 	case BSM_SETAUID:
171 		result = setauid((caddr_t)uap->a1);
172 		break;
173 	case BSM_GETAUDIT:
174 		result = getaudit((caddr_t)uap->a1);
175 		break;
176 	case BSM_GETAUDIT_ADDR:
177 
178 		result = getaudit_addr((caddr_t)uap->a1, (int)uap->a2);
179 		break;
180 	case BSM_SETAUDIT:
181 		result = setaudit((caddr_t)uap->a1);
182 		break;
183 	case BSM_SETAUDIT_ADDR:
184 		result = setaudit_addr((caddr_t)uap->a1, (int)uap->a2);
185 		break;
186 	case BSM_AUDIT:
187 		result = audit((caddr_t)uap->a1, (int)uap->a2);
188 		break;
189 	case BSM_AUDITDOOR:
190 		result = auditdoor((int)uap->a1);
191 		break;
192 	case BSM_AUDITON:
193 	case BSM_AUDITCTL:
194 		result = auditctl((int)uap->a1, (caddr_t)uap->a2, (int)uap->a3);
195 		break;
196 	default:
197 		result = EINVAL;
198 	}
199 	rvp->r_vals = result;
200 	return (result);
201 }
202 
203 /*
204  * Return the audit user ID for the current process.  Currently only
205  * the privileged processes may see the audit id.  That may change.
206  * If copyout is unsucessful return EFAULT.
207  */
208 static int
209 getauid(caddr_t auid_p)
210 {
211 	const auditinfo_addr_t	*ainfo;
212 
213 	if (secpolicy_audit_getattr(CRED()) != 0)
214 		return (EPERM);
215 
216 	ainfo = crgetauinfo(CRED());
217 	if (ainfo == NULL)
218 		return (EINVAL);
219 
220 	if (copyout(&ainfo->ai_auid, auid_p, sizeof (au_id_t)))
221 		return (EFAULT);
222 
223 	return (0);
224 }
225 
226 /*
227  * Set the audit userid, for a process.  This can only be changed by
228  * privileged processes.  The audit userid is inherited across forks & execs.
229  * Passed in is a pointer to the au_id_t; if copyin unsuccessful return EFAULT.
230  */
231 static int
232 setauid(caddr_t auid_p)
233 {
234 	proc_t *p;
235 	au_id_t	auid;
236 	cred_t *newcred;
237 	auditinfo_addr_t *auinfo;
238 
239 	if (secpolicy_audit_config(CRED()) != 0)
240 		return (EPERM);
241 
242 	if (copyin(auid_p, &auid, sizeof (au_id_t))) {
243 		return (EFAULT);
244 	}
245 
246 	newcred = cralloc();
247 	if ((auinfo = crgetauinfo_modifiable(newcred)) == NULL) {
248 		crfree(newcred);
249 		return (EINVAL);
250 	}
251 
252 	/* grab p_crlock and switch to new cred */
253 	p = curproc;
254 	mutex_enter(&p->p_crlock);
255 	crcopy_to(p->p_cred, newcred);
256 	p->p_cred = newcred;
257 
258 	auinfo->ai_auid = auid;			/* update the auid */
259 
260 	/* unlock and broadcast the cred changes */
261 	mutex_exit(&p->p_crlock);
262 	crset(p, newcred);
263 
264 	return (0);
265 }
266 
267 /*
268  * Get the audit state information from the current process.
269  * Return EFAULT if copyout fails.
270  */
271 static int
272 getaudit(caddr_t info_p)
273 {
274 	STRUCT_DECL(auditinfo, info);
275 	const auditinfo_addr_t	*ainfo;
276 	model_t	model;
277 
278 	if (secpolicy_audit_getattr(CRED()) != 0)
279 		return (EPERM);
280 
281 	model = get_udatamodel();
282 	STRUCT_INIT(info, model);
283 
284 	ainfo = crgetauinfo(CRED());
285 	if (ainfo == NULL)
286 		return (EINVAL);
287 
288 	/* trying to read a process with an IPv6 address? */
289 	if (ainfo->ai_termid.at_type == AU_IPv6)
290 		return (EOVERFLOW);
291 
292 	STRUCT_FSET(info, ai_auid, ainfo->ai_auid);
293 	STRUCT_FSET(info, ai_mask, ainfo->ai_mask);
294 #ifdef _LP64
295 	if (model == DATAMODEL_ILP32) {
296 		dev32_t dev;
297 		/* convert internal 64 bit form to 32 bit version */
298 		if (cmpldev(&dev, ainfo->ai_termid.at_port) == 0) {
299 			return (EOVERFLOW);
300 		}
301 		STRUCT_FSET(info, ai_termid.port, dev);
302 	} else
303 		STRUCT_FSET(info, ai_termid.port, ainfo->ai_termid.at_port);
304 #else
305 	STRUCT_FSET(info, ai_termid.port, ainfo->ai_termid.at_port);
306 #endif
307 	STRUCT_FSET(info, ai_termid.machine, ainfo->ai_termid.at_addr[0]);
308 	STRUCT_FSET(info, ai_asid, ainfo->ai_asid);
309 
310 	if (copyout(STRUCT_BUF(info), info_p, STRUCT_SIZE(info)))
311 		return (EFAULT);
312 
313 	return (0);
314 }
315 
316 /*
317  * Get the audit state information from the current process.
318  * Return EFAULT if copyout fails.
319  */
320 static int
321 getaudit_addr(caddr_t info_p, int len)
322 {
323 	STRUCT_DECL(auditinfo_addr, info);
324 	const auditinfo_addr_t	*ainfo;
325 	model_t	model;
326 
327 	if (secpolicy_audit_getattr(CRED()) != 0)
328 		return (EPERM);
329 
330 	model = get_udatamodel();
331 	STRUCT_INIT(info, model);
332 
333 	if (len < STRUCT_SIZE(info))
334 		return (EOVERFLOW);
335 
336 	ainfo = crgetauinfo(CRED());
337 
338 	if (ainfo == NULL)
339 		return (EINVAL);
340 
341 	STRUCT_FSET(info, ai_auid, ainfo->ai_auid);
342 	STRUCT_FSET(info, ai_mask, ainfo->ai_mask);
343 #ifdef _LP64
344 	if (model == DATAMODEL_ILP32) {
345 		dev32_t dev;
346 		/* convert internal 64 bit form to 32 bit version */
347 		if (cmpldev(&dev, ainfo->ai_termid.at_port) == 0) {
348 			return (EOVERFLOW);
349 		}
350 		STRUCT_FSET(info, ai_termid.at_port, dev);
351 	} else
352 		STRUCT_FSET(info, ai_termid.at_port, ainfo->ai_termid.at_port);
353 #else
354 	STRUCT_FSET(info, ai_termid.at_port, ainfo->ai_termid.at_port);
355 #endif
356 	STRUCT_FSET(info, ai_termid.at_type, ainfo->ai_termid.at_type);
357 	STRUCT_FSET(info, ai_termid.at_addr[0], ainfo->ai_termid.at_addr[0]);
358 	STRUCT_FSET(info, ai_termid.at_addr[1], ainfo->ai_termid.at_addr[1]);
359 	STRUCT_FSET(info, ai_termid.at_addr[2], ainfo->ai_termid.at_addr[2]);
360 	STRUCT_FSET(info, ai_termid.at_addr[3], ainfo->ai_termid.at_addr[3]);
361 	STRUCT_FSET(info, ai_asid, ainfo->ai_asid);
362 
363 	if (copyout(STRUCT_BUF(info), info_p, STRUCT_SIZE(info)))
364 		return (EFAULT);
365 
366 	return (0);
367 }
368 
369 /*
370  * Set the audit state information for the current process.
371  * Return EFAULT if copyout fails.
372  */
373 static int
374 setaudit(caddr_t info_p)
375 {
376 	STRUCT_DECL(auditinfo, info);
377 	proc_t *p;
378 	cred_t	*newcred;
379 	model_t	model;
380 	auditinfo_addr_t *ainfo;
381 
382 	if (secpolicy_audit_config(CRED()) != 0)
383 		return (EPERM);
384 
385 	model = get_udatamodel();
386 	STRUCT_INIT(info, model);
387 
388 	if (copyin(info_p, STRUCT_BUF(info), STRUCT_SIZE(info)))
389 		return (EFAULT);
390 
391 	newcred = cralloc();
392 	if ((ainfo = crgetauinfo_modifiable(newcred)) == NULL) {
393 		crfree(newcred);
394 		return (EINVAL);
395 	}
396 
397 	/* grab p_crlock and switch to new cred */
398 	p = curproc;
399 	mutex_enter(&p->p_crlock);
400 	crcopy_to(p->p_cred, newcred);
401 	p->p_cred = newcred;
402 
403 	/* Set audit mask, id, termid and session id as specified */
404 	ainfo->ai_auid = STRUCT_FGET(info, ai_auid);
405 #ifdef _LP64
406 	/* only convert to 64 bit if coming from a 32 bit binary */
407 	if (model == DATAMODEL_ILP32)
408 		ainfo->ai_termid.at_port =
409 		    DEVEXPL(STRUCT_FGET(info, ai_termid.port));
410 	else
411 		ainfo->ai_termid.at_port = STRUCT_FGET(info, ai_termid.port);
412 #else
413 	ainfo->ai_termid.at_port = STRUCT_FGET(info, ai_termid.port);
414 #endif
415 	ainfo->ai_termid.at_type = AU_IPv4;
416 	ainfo->ai_termid.at_addr[0] = STRUCT_FGET(info, ai_termid.machine);
417 	ainfo->ai_asid = STRUCT_FGET(info, ai_asid);
418 	ainfo->ai_mask = STRUCT_FGET(info, ai_mask);
419 
420 	/* unlock and broadcast the cred changes */
421 	mutex_exit(&p->p_crlock);
422 	crset(p, newcred);
423 
424 	return (0);
425 }
426 
427 /*
428  * Set the audit state information for the current process.
429  * Return EFAULT if copyin fails.
430  */
431 static int
432 setaudit_addr(caddr_t info_p, int len)
433 {
434 	STRUCT_DECL(auditinfo_addr, info);
435 	proc_t *p;
436 	cred_t	*newcred;
437 	model_t	model;
438 	int i;
439 	int type;
440 	auditinfo_addr_t *ainfo;
441 
442 	if (secpolicy_audit_config(CRED()) != 0)
443 		return (EPERM);
444 
445 	model = get_udatamodel();
446 	STRUCT_INIT(info, model);
447 
448 	if (len < STRUCT_SIZE(info))
449 		return (EOVERFLOW);
450 
451 	if (copyin(info_p, STRUCT_BUF(info), STRUCT_SIZE(info)))
452 		return (EFAULT);
453 
454 	type = STRUCT_FGET(info, ai_termid.at_type);
455 	if ((type != AU_IPv4) && (type != AU_IPv6))
456 		return (EINVAL);
457 
458 	newcred = cralloc();
459 	if ((ainfo = crgetauinfo_modifiable(newcred)) == NULL) {
460 		crfree(newcred);
461 		return (EINVAL);
462 	}
463 
464 	/* grab p_crlock and switch to new cred */
465 	p = curproc;
466 	mutex_enter(&p->p_crlock);
467 	crcopy_to(p->p_cred, newcred);
468 	p->p_cred = newcred;
469 
470 	/* Set audit mask, id, termid and session id as specified */
471 	ainfo->ai_auid = STRUCT_FGET(info, ai_auid);
472 	ainfo->ai_mask = STRUCT_FGET(info, ai_mask);
473 #ifdef _LP64
474 	/* only convert to 64 bit if coming from a 32 bit binary */
475 	if (model == DATAMODEL_ILP32)
476 		ainfo->ai_termid.at_port =
477 		    DEVEXPL(STRUCT_FGET(info, ai_termid.at_port));
478 	else
479 		ainfo->ai_termid.at_port = STRUCT_FGET(info, ai_termid.at_port);
480 #else
481 	ainfo->ai_termid.at_port = STRUCT_FGET(info, ai_termid.at_port);
482 #endif
483 	ainfo->ai_termid.at_type = type;
484 	bzero(&ainfo->ai_termid.at_addr[0], sizeof (ainfo->ai_termid.at_addr));
485 	for (i = 0; i < (type/sizeof (int)); i++)
486 		ainfo->ai_termid.at_addr[i] =
487 		    STRUCT_FGET(info, ai_termid.at_addr[i]);
488 
489 	if (ainfo->ai_termid.at_type == AU_IPv6 &&
490 	    IN6_IS_ADDR_V4MAPPED(((in6_addr_t *)ainfo->ai_termid.at_addr))) {
491 		ainfo->ai_termid.at_type = AU_IPv4;
492 		ainfo->ai_termid.at_addr[0] = ainfo->ai_termid.at_addr[3];
493 		ainfo->ai_termid.at_addr[1] = 0;
494 		ainfo->ai_termid.at_addr[2] = 0;
495 		ainfo->ai_termid.at_addr[3] = 0;
496 	}
497 
498 	ainfo->ai_asid = STRUCT_FGET(info, ai_asid);
499 
500 	/* unlock and broadcast the cred changes */
501 	mutex_exit(&p->p_crlock);
502 	crset(p, newcred);
503 
504 	return (0);
505 }
506 
507 /*
508  * The audit system call. Trust what the user has sent down and save it
509  * away in the audit file. User passes a complete audit record and its
510  * length.  We will fill in the time stamp, check the header and the length
511  * Put a trailer and a sequence token if policy requires.
512  * In the future length might become size_t instead of an int.
513  *
514  * The call is valid whether or not AUDIT_PERZONE is set (think of
515  * login to a zone).  When the local audit state (auk_auditstate) is
516  * AUC_INIT_AUDIT, records are accepted even though auditd isn't
517  * running.
518  */
519 int
520 audit(caddr_t record, int length)
521 {
522 	char	c;
523 	int	count, l;
524 	token_t	*m, *n, *s, *ad;
525 	int	hdrlen, delta;
526 	adr_t	hadr;
527 	adr_t	sadr;
528 	int	size;	/* 0: 32 bit utility  1: 64 bit utility */
529 	int	host_len;
530 	size_t	zlen;
531 	au_kcontext_t	*kctx = GET_KCTX_PZ;
532 
533 	/* if auditing not enabled, then don't generate an audit record */
534 	if (kctx->auk_auditstate != AUC_AUDITING &&
535 	    kctx->auk_auditstate != AUC_INIT_AUDIT)
536 		return (0);
537 
538 	/* Only privileged processes can audit */
539 	if (secpolicy_audit_modify(CRED()) != 0)
540 		return (EPERM);
541 
542 	/* Max user record size is 32K */
543 	if (length > AUDIT_REC_SIZE)
544 		return (E2BIG);
545 
546 	/*
547 	 * The specified length must be at least as big as the smallest
548 	 * possible header token. Later after beginning to scan the
549 	 * header we'll determine the true minimum length according to
550 	 * the header type and attributes.
551 	 */
552 #define	AU_MIN_HEADER_LEN	(sizeof (char) + sizeof (int32_t) + \
553 	sizeof (char) + sizeof (short) + sizeof (short) + \
554 	(sizeof (int32_t) * 2))
555 
556 	if (length < AU_MIN_HEADER_LEN)
557 		return (EINVAL);
558 
559 	/* Read in user's audit record */
560 	count = length;
561 	m = n = s = ad = NULL;
562 	while (count) {
563 		m = au_getclr();
564 		if (!s)
565 			s = n = m;
566 		else {
567 			n->next_buf = m;
568 			n = m;
569 		}
570 		l = MIN(count, AU_BUFSIZE);
571 		if (copyin(record, memtod(m, caddr_t), (size_t)l)) {
572 			/* copyin failed release au_membuf */
573 			au_free_rec(s);
574 			return (EFAULT);
575 		}
576 		record += l;
577 		count -= l;
578 		m->len = (uchar_t)l;
579 	}
580 
581 	/* Now attach the entire thing to ad */
582 	au_write((caddr_t *)&(ad), s);
583 
584 	/* validate header token type. trust everything following it */
585 	adr_start(&hadr, memtod(s, char *));
586 	(void) adr_getchar(&hadr, &c);
587 	switch (c) {
588 	case AUT_HEADER32:
589 		/* size vers+event_ID+event_modifier fields */
590 		delta = 1 + 2 + 2;
591 		hdrlen = 1 + 4 + delta + (sizeof (int32_t) * 2);
592 		size = HEADER_SIZE32;
593 		break;
594 
595 #ifdef _LP64
596 	case AUT_HEADER64:
597 		/* size vers+event_ID+event_modifier fields */
598 		delta = 1 + 2 + 2;
599 		hdrlen = 1 + 4 + delta + (sizeof (int64_t) * 2);
600 		size = HEADER_SIZE64;
601 		break;
602 #endif
603 
604 	case AUT_HEADER32_EX:
605 		/*
606 		 * Skip over the length/version/type/mod fields and
607 		 * grab the host address type (length), then rewind.
608 		 * This is safe per the previous minimum length check.
609 		 */
610 		hadr.adr_now += 9;
611 		(void) adr_getint32(&hadr, &host_len);
612 		hadr.adr_now -= 9 + sizeof (int32_t);
613 
614 		/* size: vers+event_ID+event_modifier+IP_type+IP_addr_array */
615 		delta = 1 + 2 + 2 + 4 + host_len;
616 		hdrlen = 1 + 4 + delta + (sizeof (int32_t) * 2);
617 		size = HEADER_SIZE32;
618 		break;
619 
620 #ifdef _LP64
621 	case AUT_HEADER64_EX:
622 		/*
623 		 * Skip over the length/version/type/mod fields and grab
624 		 * the host address type (length), then rewind.
625 		 * This is safe per the previous minimum length check.
626 		 */
627 		hadr.adr_now += 9;
628 		(void) adr_getint32(&hadr, &host_len);
629 		hadr.adr_now -= 9 + sizeof (int32_t);
630 
631 		/* size: vers+event_ID+event_modifier+IP_type+IP_addr_array */
632 		delta = 1 + 2 + 2 + 4 + host_len;
633 		hdrlen = 1 + 4 + delta + (sizeof (int64_t) * 2);
634 		size = HEADER_SIZE64;
635 		break;
636 #endif
637 
638 	default:
639 		/* Header is wrong, reject message */
640 		au_free_rec(s);
641 		return (EINVAL);
642 	}
643 
644 	if (length < hdrlen) {
645 		au_free_rec(s);
646 		return (0);
647 	}
648 
649 	/* advance over header token length field */
650 	hadr.adr_now += 4;
651 
652 	/* validate version */
653 	(void) adr_getchar(&hadr, &c);
654 	if (c != TOKEN_VERSION) {
655 		/* version is wrong, reject message */
656 		au_free_rec(s);
657 		return (EINVAL);
658 	}
659 
660 	/* backup to header length field (including version field) */
661 	hadr.adr_now -= 5;
662 
663 	/*
664 	 * add on the zonename token if policy AUDIT_ZONENAME is set
665 	 */
666 	if (kctx->auk_policy & AUDIT_ZONENAME) {
667 		zlen = au_zonename_length(NULL);
668 		if (zlen > 0) {
669 			length += zlen;
670 			m = au_to_zonename(zlen, NULL);
671 			(void) au_append_rec(ad, m, AU_PACK);
672 		}
673 	}
674 	/* Add an (optional) sequence token. NULL offset if none */
675 	if (kctx->auk_policy & AUDIT_SEQ) {
676 		/* get the sequnce token */
677 		m = au_to_seq();
678 
679 		/* sequence token 5 bytes long */
680 		length += 5;
681 
682 		/* link to audit record (i.e. don't pack the data) */
683 		(void) au_append_rec(ad, m, AU_LINK);
684 
685 		/* advance to count field of token */
686 		adr_start(&sadr, memtod(m, char *));
687 		sadr.adr_now += 1;
688 	} else
689 		sadr.adr_now = (char *)NULL;
690 
691 	/* add the (optional) trailer token */
692 	if (kctx->auk_policy & AUDIT_TRAIL) {
693 		/* trailer token is 7 bytes long */
694 		length += 7;
695 
696 		/* append to audit record */
697 		(void) au_append_rec(ad, au_to_trailer(length), AU_PACK);
698 	}
699 
700 	/* audit record completely assembled. set the length */
701 	adr_int32(&hadr, (int32_t *)&length, 1);
702 
703 	/* advance to date/time field of header */
704 	hadr.adr_now += delta;
705 
706 	/* We are done  put it on the queue */
707 	AS_INC(as_generated, 1, kctx);
708 	AS_INC(as_audit, 1, kctx);
709 
710 	au_enqueue(kctx, s, &hadr, &sadr, size, 0);
711 
712 	AS_INC(as_totalsize, length, kctx);
713 
714 	return (0);
715 }
716 
717 static void
718 audit_dont_stop(void *kctx)
719 {
720 
721 	if ((((au_kcontext_t *)kctx)->auk_valid != AUK_VALID) ||
722 	    (((au_kcontext_t *)kctx)->auk_auditstate == AUC_NOAUDIT))
723 		return;
724 
725 	mutex_enter(&(((au_kcontext_t *)kctx)->auk_queue.lock));
726 	cv_broadcast(&(((au_kcontext_t *)kctx)->auk_queue.write_cv));
727 	mutex_exit(&(((au_kcontext_t *)kctx)->auk_queue.lock));
728 }
729 
730 /*
731  * auditdoor starts a kernel thread to generate output from the audit
732  * queue.  The thread terminates when it detects auditing being turned
733  * off, such as when auditd exits with a SIGTERM.  If a subsequent
734  * auditdoor arrives while the thread is running, the door descriptor
735  * of the last auditdoor in will be used for output.  auditd is responsible
736  * for insuring that multiple copies are not running.
737  */
738 
739 static int
740 auditdoor(int fd)
741 {
742 	struct file	*fp;
743 	struct vnode	*vp;
744 	int		do_create = 0;
745 	au_kcontext_t	*kctx;
746 
747 	if (secpolicy_audit_config(CRED()) != 0)
748 		return (EPERM);
749 
750 	if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc))
751 		return (EINVAL);
752 
753 	kctx = GET_KCTX_NGZ;
754 
755 	/*
756 	 * convert file pointer to file descriptor
757 	 *   Note: fd ref count incremented here.
758 	 */
759 	if ((fp = (struct file *)getf(fd)) == NULL) {
760 		return (EBADF);
761 	}
762 	vp = fp->f_vnode;
763 	if (vp->v_type != VDOOR) {
764 		cmn_err(CE_WARN,
765 		    "auditdoor() did not get the expected door descriptor\n");
766 		releasef(fd);
767 		return (EINVAL);
768 	}
769 	/*
770 	 * If the output thread is already running, then replace the
771 	 * door descriptor with the new one and continue; otherwise
772 	 * create the thread too.  Since au_output_thread makes a call
773 	 * to au_doorio() which also does
774 	 * mutex_lock(&(kctx->auk_svc_lock)), the create/dispatch is
775 	 * done after the unlock...
776 	 */
777 	mutex_enter(&(kctx->auk_svc_lock));
778 
779 	if (kctx->auk_current_vp != NULL)
780 		VN_RELE(kctx->auk_current_vp);
781 
782 	kctx->auk_current_vp = vp;
783 	VN_HOLD(kctx->auk_current_vp);
784 	releasef(fd);
785 
786 	if (!kctx->auk_output_active) {
787 		kctx->auk_output_active = 1;
788 		do_create = 1;
789 	}
790 	mutex_exit(&(kctx->auk_svc_lock));
791 	if (do_create) {
792 		kctx->auk_taskq =
793 		    taskq_create("output_master", 1, minclsyspri, 1, 1, 0);
794 		(void) taskq_dispatch(kctx->auk_taskq,
795 		    (task_func_t *)au_output_thread,
796 		    kctx, TQ_SLEEP);
797 	}
798 	return (0);
799 }
800 
801 /*
802  * au_queue_kick -- wake up the output queue after delay ticks
803  */
804 static void
805 au_queue_kick(void *kctx)
806 {
807 	/*
808 	 * wakeup reader if its not running and there is something
809 	 * to do.  It also helps that kctx still be valid...
810 	 */
811 
812 	if ((((au_kcontext_t *)kctx)->auk_valid != AUK_VALID) ||
813 	    (((au_kcontext_t *)kctx)->auk_auditstate == AUC_NOAUDIT))
814 		return;
815 
816 	if (((au_kcontext_t *)kctx)->auk_queue.cnt &&
817 	    ((au_kcontext_t *)kctx)->auk_queue.rd_block)
818 		cv_broadcast(&((au_kcontext_t *)kctx)->auk_queue.read_cv);
819 
820 	/* fire off timeout event to kick audit queue awake */
821 	(void) timeout(au_queue_kick, kctx,
822 	    ((au_kcontext_t *)kctx)->auk_queue.delay);
823 }
824 
825 /*
826  * output thread
827  *
828  * this runs "forever" where "forever" means until either auk_auditstate
829  * changes from AUC_AUDITING or if the door descriptor becomes invalid.
830  *
831  * there is one thread per active zone if AUC_PERZONE is set.  Since
832  * there is the possibility that a zone may go down without auditd
833  * terminating properly, a zone shutdown kills its au_output_thread()
834  * via taskq_destroy().
835  */
836 
837 static void
838 au_output_thread(au_kcontext_t *kctx)
839 {
840 	int		error = 0;
841 
842 	(void) timeout(au_queue_kick, kctx, kctx->auk_queue.delay);
843 
844 	/*
845 	 * Wait for work, until a signal arrives,
846 	 * or until auditing is disabled.
847 	 */
848 
849 	while (!error) {
850 		if (kctx->auk_auditstate == AUC_AUDITING) {
851 			mutex_enter(&(kctx->auk_queue.lock));
852 			while (kctx->auk_queue.head == NULL) {
853 				/* safety check. kick writer awake */
854 				if (kctx->auk_queue.wt_block) {
855 					cv_broadcast(&(kctx->
856 					    auk_queue.write_cv));
857 				}
858 
859 				kctx->auk_queue.rd_block = 1;
860 				AS_INC(as_rblocked, 1, kctx);
861 
862 				cv_wait(&(kctx->auk_queue.read_cv),
863 				    &(kctx->auk_queue.lock));
864 				kctx->auk_queue.rd_block = 0;
865 
866 				if (kctx->auk_auditstate != AUC_AUDITING) {
867 					mutex_exit(&(kctx->auk_queue.lock));
868 					(void) timeout(audit_dont_stop, kctx,
869 					    au_resid);
870 					goto output_exit;
871 				}
872 				kctx->auk_queue.rd_block = 0;
873 			}
874 			mutex_exit(&(kctx->auk_queue.lock));
875 			/*
876 			 * au_doorio() calls au_door_upcall which holds
877 			 * auk_svc_lock; au_doorio empties the queue before
878 			 * returning.
879 			 */
880 
881 			error = au_doorio(kctx);
882 		} else {
883 			/* auditing turned off while we slept */
884 			break;
885 		}
886 	}
887 output_exit:
888 	mutex_enter(&(kctx->auk_svc_lock));
889 
890 	VN_RELE(kctx->auk_current_vp);
891 	kctx->auk_current_vp = NULL;
892 
893 	kctx->auk_output_active = 0;
894 
895 	mutex_exit(&(kctx->auk_svc_lock));
896 }
897 
898 
899 /*
900  * Get the global policy flag
901  */
902 
903 static int
904 getpolicy(caddr_t data)
905 {
906 	int	policy;
907 	au_kcontext_t	*kctx = GET_KCTX_PZ;
908 
909 	policy = audit_policy | kctx->auk_policy;
910 
911 	if (copyout(&policy, data, sizeof (int)))
912 		return (EFAULT);
913 	return (0);
914 }
915 
916 /*
917  * Set the global and local policy flags
918  *
919  * The global flags only make sense from the global zone;
920  * the local flags depend on the AUDIT_PERZONE policy:
921  * if the perzone policy is set, then policy is set separately
922  * per zone, else held only in the global zone.
923  *
924  * The initial value of a local zone's policy flag is determined
925  * by the value of the global zone's flags at the time the
926  * local zone is created.
927  *
928  * While auditconfig(1M) allows setting and unsetting policies one bit
929  * at a time, the mask passed in from auditconfig() is created by a
930  * syscall to getpolicy and then modified based on the auditconfig()
931  * cmd line, so the input policy value is used to replace the existing
932  * policy.
933  */
934 
935 
936 static int
937 setpolicy(caddr_t data)
938 {
939 	int	policy;
940 	au_kcontext_t	*kctx;
941 
942 	if (copyin(data, &policy, sizeof (int)))
943 		return (EFAULT);
944 
945 	kctx = GET_KCTX_NGZ;
946 
947 	if (INGLOBALZONE(curproc)) {
948 		if (policy & ~(AUDIT_GLOBAL | AUDIT_LOCAL))
949 			return (EINVAL);
950 
951 		audit_policy = policy & AUDIT_GLOBAL;
952 	} else {
953 		if (!(audit_policy & AUDIT_PERZONE))
954 			return (EINVAL);
955 
956 		if (policy & ~AUDIT_LOCAL)	/* global bits are a no-no */
957 			return (EINVAL);
958 	}
959 	kctx->auk_policy = policy & AUDIT_LOCAL;
960 
961 	/*
962 	 * auk_current_vp is NULL before auditd starts (or during early
963 	 * auditd starup) or if auditd is halted; in either case,
964 	 * notification of a policy change is not needed, since auditd
965 	 * reads policy as it comes up.  The error return from au_doormsg()
966 	 * is ignored to avoid a race condition -- for example if auditd
967 	 * segv's, the audit state may be "auditing" but the door may
968 	 * be closed.  Returning an error if the door is open makes it
969 	 * impossible for Greenline to restart auditd.
970 	 */
971 	if (kctx->auk_current_vp != NULL)
972 		(void) au_doormsg(kctx, AU_DBUF_POLICY, &policy);
973 
974 	/*
975 	 * Wake up anyone who might have blocked on full audit
976 	 * partitions. audit daemons need to set AUDIT_FULL when no
977 	 * space so we can tell if we should start dropping records.
978 	 */
979 	mutex_enter(&(kctx->auk_queue.lock));
980 
981 	if ((policy & (AUDIT_CNT | AUDIT_SCNT) &&
982 	    (kctx->auk_queue.cnt >= kctx->auk_queue.hiwater)))
983 		cv_broadcast(&(kctx->auk_queue.write_cv));
984 
985 	mutex_exit(&(kctx->auk_queue.lock));
986 
987 	return (0);
988 }
989 
990 static int
991 getkmask(caddr_t data)
992 {
993 	au_kcontext_t	*kctx;
994 
995 	kctx = GET_KCTX_PZ;
996 
997 	if (copyout(&kctx->auk_info.ai_mask, data, sizeof (au_mask_t)))
998 		return (EFAULT);
999 	return (0);
1000 }
1001 
1002 static int
1003 setkmask(caddr_t data)
1004 {
1005 	au_mask_t	mask;
1006 	au_kcontext_t	*kctx;
1007 
1008 	if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc))
1009 		return (EINVAL);
1010 
1011 	kctx = GET_KCTX_NGZ;
1012 
1013 	if (copyin(data, &mask, sizeof (au_mask_t)))
1014 		return (EFAULT);
1015 
1016 	kctx->auk_info.ai_mask = mask;
1017 	return (0);
1018 }
1019 
1020 static int
1021 getkaudit(caddr_t info_p, int len)
1022 {
1023 	STRUCT_DECL(auditinfo_addr, info);
1024 	model_t model;
1025 	au_kcontext_t	*kctx = GET_KCTX_PZ;
1026 
1027 	model = get_udatamodel();
1028 	STRUCT_INIT(info, model);
1029 
1030 	if (len < STRUCT_SIZE(info))
1031 		return (EOVERFLOW);
1032 
1033 	STRUCT_FSET(info, ai_auid, kctx->auk_info.ai_auid);
1034 	STRUCT_FSET(info, ai_mask, kctx->auk_info.ai_mask);
1035 #ifdef _LP64
1036 	if (model == DATAMODEL_ILP32) {
1037 		dev32_t dev;
1038 		/* convert internal 64 bit form to 32 bit version */
1039 		if (cmpldev(&dev, kctx->auk_info.ai_termid.at_port) == 0) {
1040 			return (EOVERFLOW);
1041 		}
1042 		STRUCT_FSET(info, ai_termid.at_port, dev);
1043 	} else {
1044 		STRUCT_FSET(info, ai_termid.at_port,
1045 		    kctx->auk_info.ai_termid.at_port);
1046 	}
1047 #else
1048 	STRUCT_FSET(info, ai_termid.at_port,
1049 	    kctx->auk_info.ai_termid.at_port);
1050 #endif
1051 	STRUCT_FSET(info, ai_termid.at_type,
1052 	    kctx->auk_info.ai_termid.at_type);
1053 	STRUCT_FSET(info, ai_termid.at_addr[0],
1054 	    kctx->auk_info.ai_termid.at_addr[0]);
1055 	STRUCT_FSET(info, ai_termid.at_addr[1],
1056 	    kctx->auk_info.ai_termid.at_addr[1]);
1057 	STRUCT_FSET(info, ai_termid.at_addr[2],
1058 	    kctx->auk_info.ai_termid.at_addr[2]);
1059 	STRUCT_FSET(info, ai_termid.at_addr[3],
1060 	    kctx->auk_info.ai_termid.at_addr[3]);
1061 	STRUCT_FSET(info, ai_asid, kctx->auk_info.ai_asid);
1062 
1063 	if (copyout(STRUCT_BUF(info), info_p, STRUCT_SIZE(info)))
1064 		return (EFAULT);
1065 
1066 	return (0);
1067 }
1068 
1069 /*
1070  * the host address for AUDIT_PERZONE == 0 is that of the global
1071  * zone and for local zones it is of the current zone.
1072  */
1073 
1074 static int
1075 setkaudit(caddr_t info_p, int len)
1076 {
1077 	STRUCT_DECL(auditinfo_addr, info);
1078 	model_t model;
1079 	au_kcontext_t	*kctx;
1080 
1081 	if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc))
1082 		return (EINVAL);
1083 
1084 	kctx = GET_KCTX_NGZ;
1085 
1086 	model = get_udatamodel();
1087 	STRUCT_INIT(info, model);
1088 
1089 	if (len < STRUCT_SIZE(info))
1090 		return (EOVERFLOW);
1091 
1092 	if (copyin(info_p, STRUCT_BUF(info), STRUCT_SIZE(info)))
1093 		return (EFAULT);
1094 
1095 	if ((STRUCT_FGET(info, ai_termid.at_type) != AU_IPv4) &&
1096 	    (STRUCT_FGET(info, ai_termid.at_type) != AU_IPv6))
1097 		return (EINVAL);
1098 
1099 	/* Set audit mask, termid and session id as specified */
1100 	kctx->auk_info.ai_auid = STRUCT_FGET(info, ai_auid);
1101 	kctx->auk_info.ai_mask = STRUCT_FGET(info, ai_mask);
1102 #ifdef _LP64
1103 	/* only convert to 64 bit if coming from a 32 bit binary */
1104 	if (model == DATAMODEL_ILP32)
1105 		kctx->auk_info.ai_termid.at_port =
1106 		    DEVEXPL(STRUCT_FGET(info, ai_termid.at_port));
1107 	else
1108 		kctx->auk_info.ai_termid.at_port =
1109 		    STRUCT_FGET(info, ai_termid.at_port);
1110 #else
1111 	kctx->auk_info.ai_termid.at_port = STRUCT_FGET(info, ai_termid.at_port);
1112 #endif
1113 	kctx->auk_info.ai_termid.at_type = STRUCT_FGET(info, ai_termid.at_type);
1114 	bzero(&kctx->auk_info.ai_termid.at_addr[0],
1115 	    sizeof (kctx->auk_info.ai_termid.at_addr));
1116 	kctx->auk_info.ai_termid.at_addr[0] =
1117 	    STRUCT_FGET(info, ai_termid.at_addr[0]);
1118 	kctx->auk_info.ai_termid.at_addr[1] =
1119 	    STRUCT_FGET(info, ai_termid.at_addr[1]);
1120 	kctx->auk_info.ai_termid.at_addr[2] =
1121 	    STRUCT_FGET(info, ai_termid.at_addr[2]);
1122 	kctx->auk_info.ai_termid.at_addr[3] =
1123 	    STRUCT_FGET(info, ai_termid.at_addr[3]);
1124 	kctx->auk_info.ai_asid = STRUCT_FGET(info, ai_asid);
1125 
1126 	if (kctx->auk_info.ai_termid.at_type == AU_IPv6 &&
1127 	    IN6_IS_ADDR_V4MAPPED(
1128 	    ((in6_addr_t *)kctx->auk_info.ai_termid.at_addr))) {
1129 		kctx->auk_info.ai_termid.at_type = AU_IPv4;
1130 		kctx->auk_info.ai_termid.at_addr[0] =
1131 		    kctx->auk_info.ai_termid.at_addr[3];
1132 		kctx->auk_info.ai_termid.at_addr[1] = 0;
1133 		kctx->auk_info.ai_termid.at_addr[2] = 0;
1134 		kctx->auk_info.ai_termid.at_addr[3] = 0;
1135 	}
1136 	if (kctx->auk_info.ai_termid.at_type == AU_IPv6)
1137 		kctx->auk_hostaddr_valid = IN6_IS_ADDR_UNSPECIFIED(
1138 		    (in6_addr_t *)kctx->auk_info.ai_termid.at_addr) ? 0 : 1;
1139 	else
1140 		kctx->auk_hostaddr_valid =
1141 		    (kctx->auk_info.ai_termid.at_addr[0] ==
1142 		    htonl(INADDR_ANY)) ? 0 : 1;
1143 
1144 	return (0);
1145 }
1146 
1147 static int
1148 getqctrl(caddr_t data)
1149 {
1150 	au_kcontext_t	*kctx = GET_KCTX_PZ;
1151 	STRUCT_DECL(au_qctrl, qctrl);
1152 	STRUCT_INIT(qctrl, get_udatamodel());
1153 
1154 	mutex_enter(&(kctx->auk_queue.lock));
1155 	STRUCT_FSET(qctrl, aq_hiwater, kctx->auk_queue.hiwater);
1156 	STRUCT_FSET(qctrl, aq_lowater, kctx->auk_queue.lowater);
1157 	STRUCT_FSET(qctrl, aq_bufsz, kctx->auk_queue.bufsz);
1158 	STRUCT_FSET(qctrl, aq_delay, kctx->auk_queue.delay);
1159 	mutex_exit(&(kctx->auk_queue.lock));
1160 
1161 	if (copyout(STRUCT_BUF(qctrl), data, STRUCT_SIZE(qctrl)))
1162 		return (EFAULT);
1163 
1164 	return (0);
1165 }
1166 
1167 static int
1168 setqctrl(caddr_t data)
1169 {
1170 	au_kcontext_t	*kctx;
1171 	struct au_qctrl qctrl_tmp;
1172 	STRUCT_DECL(au_qctrl, qctrl);
1173 	STRUCT_INIT(qctrl, get_udatamodel());
1174 
1175 	if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc))
1176 		return (EINVAL);
1177 	kctx = GET_KCTX_NGZ;
1178 
1179 	if (copyin(data, STRUCT_BUF(qctrl), STRUCT_SIZE(qctrl)))
1180 		return (EFAULT);
1181 
1182 	qctrl_tmp.aq_hiwater = (size_t)STRUCT_FGET(qctrl, aq_hiwater);
1183 	qctrl_tmp.aq_lowater = (size_t)STRUCT_FGET(qctrl, aq_lowater);
1184 	qctrl_tmp.aq_bufsz = (size_t)STRUCT_FGET(qctrl, aq_bufsz);
1185 	qctrl_tmp.aq_delay = (clock_t)STRUCT_FGET(qctrl, aq_delay);
1186 
1187 	/* enforce sane values */
1188 
1189 	if (qctrl_tmp.aq_hiwater <= qctrl_tmp.aq_lowater)
1190 		return (EINVAL);
1191 
1192 	if (qctrl_tmp.aq_hiwater < AQ_LOWATER)
1193 		return (EINVAL);
1194 
1195 	if (qctrl_tmp.aq_hiwater > AQ_MAXHIGH)
1196 		return (EINVAL);
1197 
1198 	if (qctrl_tmp.aq_bufsz < AQ_BUFSZ)
1199 		return (EINVAL);
1200 
1201 	if (qctrl_tmp.aq_bufsz > AQ_MAXBUFSZ)
1202 		return (EINVAL);
1203 
1204 	if (qctrl_tmp.aq_delay == 0)
1205 		return (EINVAL);
1206 
1207 	if (qctrl_tmp.aq_delay > AQ_MAXDELAY)
1208 		return (EINVAL);
1209 
1210 	/* update everything at once so things are consistant */
1211 	mutex_enter(&(kctx->auk_queue.lock));
1212 	kctx->auk_queue.hiwater = qctrl_tmp.aq_hiwater;
1213 	kctx->auk_queue.lowater = qctrl_tmp.aq_lowater;
1214 	kctx->auk_queue.bufsz = qctrl_tmp.aq_bufsz;
1215 	kctx->auk_queue.delay = qctrl_tmp.aq_delay;
1216 
1217 	if (kctx->auk_queue.rd_block &&
1218 	    kctx->auk_queue.cnt > kctx->auk_queue.lowater)
1219 		cv_broadcast(&(kctx->auk_queue.read_cv));
1220 
1221 	if (kctx->auk_queue.wt_block &&
1222 	    kctx->auk_queue.cnt < kctx->auk_queue.hiwater)
1223 		cv_broadcast(&(kctx->auk_queue.write_cv));
1224 
1225 	mutex_exit(&(kctx->auk_queue.lock));
1226 
1227 	return (0);
1228 }
1229 
1230 static int
1231 getcwd(caddr_t data, int length)
1232 {
1233 	struct p_audit_data	*pad;
1234 	struct audit_path	*app;
1235 	int	pathlen;
1236 
1237 	pad = P2A(curproc);
1238 	ASSERT(pad != NULL);
1239 
1240 	mutex_enter(&(pad->pad_lock));
1241 	app = pad->pad_cwd;
1242 	au_pathhold(app);
1243 	mutex_exit(&(pad->pad_lock));
1244 
1245 	pathlen = app->audp_sect[1] - app->audp_sect[0];
1246 	if (pathlen > length) {
1247 		au_pathrele(app);
1248 		return (E2BIG);
1249 	}
1250 
1251 	if (copyout(app->audp_sect[0], data, pathlen)) {
1252 		au_pathrele(app);
1253 		return (EFAULT);
1254 	}
1255 
1256 	au_pathrele(app);
1257 	return (0);
1258 }
1259 
1260 static int
1261 getcar(caddr_t data, int length)
1262 {
1263 	struct p_audit_data	*pad;
1264 	struct audit_path	*app;
1265 	int	pathlen;
1266 
1267 	pad = P2A(curproc);
1268 	ASSERT(pad != NULL);
1269 
1270 	mutex_enter(&(pad->pad_lock));
1271 	app = pad->pad_root;
1272 	au_pathhold(app);
1273 	mutex_exit(&(pad->pad_lock));
1274 
1275 	pathlen = app->audp_sect[1] - app->audp_sect[0];
1276 	if (pathlen > length) {
1277 		au_pathrele(app);
1278 		return (E2BIG);
1279 	}
1280 
1281 	if (copyout(app->audp_sect[0], data, pathlen)) {
1282 		au_pathrele(app);
1283 		return (EFAULT);
1284 	}
1285 
1286 	au_pathrele(app);
1287 	return (0);
1288 }
1289 
1290 static int
1291 getstat(caddr_t data)
1292 {
1293 	au_kcontext_t	*kctx = GET_KCTX_PZ;
1294 
1295 	membar_consumer();
1296 
1297 	if (copyout((caddr_t)&(kctx->auk_statistics), data, sizeof (au_stat_t)))
1298 		return (EFAULT);
1299 	return (0);
1300 }
1301 
1302 
1303 static int
1304 setstat(caddr_t data)
1305 {
1306 	au_kcontext_t	*kctx = GET_KCTX_PZ;
1307 	au_stat_t au_stat;
1308 
1309 	if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc))
1310 		return (EINVAL);
1311 
1312 	if (copyin(data, &au_stat, sizeof (au_stat_t)))
1313 		return (EFAULT);
1314 
1315 	if (au_stat.as_generated == CLEAR_VAL)
1316 		kctx->auk_statistics.as_generated = 0;
1317 	if (au_stat.as_nonattrib == CLEAR_VAL)
1318 		kctx->auk_statistics.as_nonattrib = 0;
1319 	if (au_stat.as_kernel == CLEAR_VAL)
1320 		kctx->auk_statistics.as_kernel = 0;
1321 	if (au_stat.as_audit == CLEAR_VAL)
1322 		kctx->auk_statistics.as_audit = 0;
1323 	if (au_stat.as_auditctl == CLEAR_VAL)
1324 		kctx->auk_statistics.as_auditctl = 0;
1325 	if (au_stat.as_enqueue == CLEAR_VAL)
1326 		kctx->auk_statistics.as_enqueue = 0;
1327 	if (au_stat.as_written == CLEAR_VAL)
1328 		kctx->auk_statistics.as_written = 0;
1329 	if (au_stat.as_wblocked == CLEAR_VAL)
1330 		kctx->auk_statistics.as_wblocked = 0;
1331 	if (au_stat.as_rblocked == CLEAR_VAL)
1332 		kctx->auk_statistics.as_rblocked = 0;
1333 	if (au_stat.as_dropped == CLEAR_VAL)
1334 		kctx->auk_statistics.as_dropped = 0;
1335 	if (au_stat.as_totalsize == CLEAR_VAL)
1336 		kctx->auk_statistics.as_totalsize = 0;
1337 
1338 	membar_producer();
1339 
1340 	return (0);
1341 
1342 }
1343 
1344 static int
1345 setumask(caddr_t data)
1346 {
1347 	STRUCT_DECL(auditinfo, user_info);
1348 	struct proc *p;
1349 	const auditinfo_addr_t	*ainfo;
1350 	model_t	model;
1351 
1352 	/* setumask not applicable in non-global zones without perzone policy */
1353 	if (!(audit_policy & AUDIT_PERZONE) && (!INGLOBALZONE(curproc)))
1354 		return (EINVAL);
1355 
1356 	model = get_udatamodel();
1357 	STRUCT_INIT(user_info, model);
1358 
1359 	if (copyin(data, STRUCT_BUF(user_info), STRUCT_SIZE(user_info)))
1360 		return (EFAULT);
1361 
1362 	mutex_enter(&pidlock);	/* lock the process queue against updates */
1363 	for (p = practive; p != NULL; p = p->p_next) {
1364 		cred_t	*cr;
1365 
1366 		/* if in non-global zone only modify processes in same zone */
1367 		if (!HASZONEACCESS(curproc, p->p_zone->zone_id))
1368 			continue;
1369 
1370 		mutex_enter(&p->p_lock);	/* so process doesn't go away */
1371 
1372 		/* skip system processes and ones being created or going away */
1373 		if (p->p_stat == SIDL || p->p_stat == SZOMB ||
1374 		    (p->p_flag & (SSYS | SEXITING | SEXITLWPS))) {
1375 			mutex_exit(&p->p_lock);
1376 			continue;
1377 		}
1378 
1379 		mutex_enter(&p->p_crlock);
1380 		crhold(cr = p->p_cred);
1381 		mutex_exit(&p->p_crlock);
1382 		ainfo = crgetauinfo(cr);
1383 		if (ainfo == NULL) {
1384 			mutex_exit(&p->p_lock);
1385 			crfree(cr);
1386 			continue;
1387 		}
1388 
1389 		if (ainfo->ai_auid == STRUCT_FGET(user_info, ai_auid)) {
1390 			au_mask_t	mask;
1391 			int		err;
1392 
1393 			/*
1394 			 * Here's a process which matches the specified auid.
1395 			 * If its mask doesn't already match the new mask,
1396 			 * save the new mask in the pad, to be picked up
1397 			 * next syscall.
1398 			 */
1399 			mask = STRUCT_FGET(user_info, ai_mask);
1400 			err = bcmp(&mask, &ainfo->ai_mask, sizeof (au_mask_t));
1401 			crfree(cr);
1402 			if (err != 0) {
1403 				struct p_audit_data *pad = P2A(p);
1404 				ASSERT(pad != NULL);
1405 
1406 				mutex_enter(&(pad->pad_lock));
1407 				pad->pad_flags |= PAD_SETMASK;
1408 				pad->pad_newmask = mask;
1409 				mutex_exit(&(pad->pad_lock));
1410 
1411 				/*
1412 				 * No need to call set_proc_pre_sys(), since
1413 				 * t_pre_sys is ALWAYS on when audit is
1414 				 * enabled...due to syscall auditing.
1415 				 */
1416 			}
1417 		} else {
1418 			crfree(cr);
1419 		}
1420 		mutex_exit(&p->p_lock);
1421 	}
1422 	mutex_exit(&pidlock);
1423 
1424 	return (0);
1425 }
1426 
1427 static int
1428 setsmask(caddr_t data)
1429 {
1430 	STRUCT_DECL(auditinfo, user_info);
1431 	struct proc *p;
1432 	const auditinfo_addr_t	*ainfo;
1433 	model_t	model;
1434 
1435 	/* setsmask not applicable in non-global zones without perzone policy */
1436 	if (!(audit_policy & AUDIT_PERZONE) && (!INGLOBALZONE(curproc)))
1437 		return (EINVAL);
1438 
1439 	model = get_udatamodel();
1440 	STRUCT_INIT(user_info, model);
1441 
1442 	if (copyin(data, STRUCT_BUF(user_info), STRUCT_SIZE(user_info)))
1443 		return (EFAULT);
1444 
1445 	mutex_enter(&pidlock);	/* lock the process queue against updates */
1446 	for (p = practive; p != NULL; p = p->p_next) {
1447 		cred_t	*cr;
1448 
1449 		/* if in non-global zone only modify processes in same zone */
1450 		if (!HASZONEACCESS(curproc, p->p_zone->zone_id))
1451 			continue;
1452 
1453 		mutex_enter(&p->p_lock);	/* so process doesn't go away */
1454 
1455 		/* skip system processes and ones being created or going away */
1456 		if (p->p_stat == SIDL || p->p_stat == SZOMB ||
1457 		    (p->p_flag & (SSYS | SEXITING | SEXITLWPS))) {
1458 			mutex_exit(&p->p_lock);
1459 			continue;
1460 		}
1461 
1462 		mutex_enter(&p->p_crlock);
1463 		crhold(cr = p->p_cred);
1464 		mutex_exit(&p->p_crlock);
1465 		ainfo = crgetauinfo(cr);
1466 		if (ainfo == NULL) {
1467 			mutex_exit(&p->p_lock);
1468 			crfree(cr);
1469 			continue;
1470 		}
1471 
1472 		if (ainfo->ai_asid == STRUCT_FGET(user_info, ai_asid)) {
1473 			au_mask_t	mask;
1474 			int		err;
1475 
1476 			/*
1477 			 * Here's a process which matches the specified asid.
1478 			 * If its mask doesn't already match the new mask,
1479 			 * save the new mask in the pad, to be picked up
1480 			 * next syscall.
1481 			 */
1482 			mask = STRUCT_FGET(user_info, ai_mask);
1483 			err = bcmp(&mask, &ainfo->ai_mask, sizeof (au_mask_t));
1484 			crfree(cr);
1485 			if (err != 0) {
1486 				struct p_audit_data *pad = P2A(p);
1487 				ASSERT(pad != NULL);
1488 
1489 				mutex_enter(&(pad->pad_lock));
1490 				pad->pad_flags |= PAD_SETMASK;
1491 				pad->pad_newmask = mask;
1492 				mutex_exit(&(pad->pad_lock));
1493 
1494 				/*
1495 				 * No need to call set_proc_pre_sys(), since
1496 				 * t_pre_sys is ALWAYS on when audit is
1497 				 * enabled...due to syscall auditing.
1498 				 */
1499 			}
1500 		} else {
1501 			crfree(cr);
1502 		}
1503 		mutex_exit(&p->p_lock);
1504 	}
1505 	mutex_exit(&pidlock);
1506 
1507 	return (0);
1508 }
1509 
1510 /*
1511  * Get the current audit state of the system
1512  */
1513 static int
1514 getcond(caddr_t data)
1515 {
1516 	au_kcontext_t	*kctx;
1517 
1518 	if (au_auditstate == AUC_DISABLED)
1519 		if (copyout(&au_auditstate, data, sizeof (int)))
1520 			return (EFAULT);
1521 
1522 	kctx = GET_KCTX_PZ;
1523 
1524 	if (copyout(&(kctx->auk_auditstate), data, sizeof (int)))
1525 		return (EFAULT);
1526 
1527 	return (0);
1528 }
1529 
1530 /*
1531  * Set the current audit state of the system to on (AUC_AUDITING) or
1532  * off (AUC_NOAUDIT).
1533  */
1534 /* ARGSUSED */
1535 static int
1536 setcond(caddr_t data)
1537 {
1538 	int	auditstate;
1539 	au_kcontext_t	*kctx;
1540 
1541 	if (!(audit_policy & AUDIT_PERZONE) && (!INGLOBALZONE(curproc)))
1542 		return (EINVAL);
1543 
1544 	kctx = GET_KCTX_NGZ;
1545 
1546 	if (copyin(data, &auditstate, sizeof (int)))
1547 		return (EFAULT);
1548 
1549 	switch (auditstate) {
1550 	case AUC_AUDITING:		/* Turn auditing on */
1551 		kctx->auk_auditstate = AUC_AUDITING;
1552 		au_auditstate = AUC_ENABLED;
1553 		break;
1554 
1555 	case AUC_NOAUDIT:		/* Turn auditing off */
1556 		if (kctx->auk_auditstate == AUC_NOAUDIT)
1557 			break;
1558 		kctx->auk_auditstate = AUC_NOAUDIT;
1559 
1560 		/* clear out the audit queue */
1561 
1562 		mutex_enter(&(kctx->auk_queue.lock));
1563 		if (kctx->auk_queue.wt_block)
1564 			cv_broadcast(&(kctx->auk_queue.write_cv));
1565 
1566 		/* unblock au_output_thread */
1567 		cv_broadcast(&(kctx->auk_queue.read_cv));
1568 
1569 		mutex_exit(&(kctx->auk_queue.lock));
1570 		break;
1571 
1572 	default:
1573 		return (EINVAL);
1574 	}
1575 
1576 	return (0);
1577 }
1578 
1579 static int
1580 getclass(caddr_t data)
1581 {
1582 	au_evclass_map_t event;
1583 	au_kcontext_t	*kctx = GET_KCTX_PZ;
1584 
1585 	if (copyin(data, &event, sizeof (au_evclass_map_t)))
1586 		return (EFAULT);
1587 
1588 	if (event.ec_number > MAX_KEVENTS)
1589 		return (EINVAL);
1590 
1591 	event.ec_class = kctx->auk_ets[event.ec_number];
1592 
1593 	if (copyout(&event, data, sizeof (au_evclass_map_t)))
1594 		return (EFAULT);
1595 
1596 	return (0);
1597 }
1598 
1599 static int
1600 setclass(caddr_t data)
1601 {
1602 	au_evclass_map_t event;
1603 	au_kcontext_t	*kctx;
1604 
1605 	if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc))
1606 		return (EINVAL);
1607 
1608 	kctx = GET_KCTX_NGZ;
1609 
1610 	if (copyin(data, &event, sizeof (au_evclass_map_t)))
1611 		return (EFAULT);
1612 
1613 	if (event.ec_number > MAX_KEVENTS)
1614 		return (EINVAL);
1615 
1616 	kctx->auk_ets[event.ec_number] = event.ec_class;
1617 
1618 	return (0);
1619 }
1620 
1621 static int
1622 getpinfo(caddr_t data)
1623 {
1624 	STRUCT_DECL(auditpinfo, apinfo);
1625 	proc_t *proc;
1626 	const auditinfo_addr_t	*ainfo;
1627 	model_t	model;
1628 	cred_t	*cr, *newcred;
1629 
1630 	model = get_udatamodel();
1631 	STRUCT_INIT(apinfo, model);
1632 
1633 	if (copyin(data, STRUCT_BUF(apinfo), STRUCT_SIZE(apinfo)))
1634 		return (EFAULT);
1635 
1636 	newcred = cralloc();
1637 
1638 	mutex_enter(&pidlock);
1639 	if ((proc = prfind(STRUCT_FGET(apinfo, ap_pid))) == NULL) {
1640 		mutex_exit(&pidlock);
1641 		crfree(newcred);
1642 		return (ESRCH);		/* no such process */
1643 	}
1644 	mutex_enter(&proc->p_lock);	/* so process doesn't go away */
1645 	mutex_exit(&pidlock);
1646 
1647 	audit_update_context(proc, newcred);	/* make sure it's up-to-date */
1648 
1649 	mutex_enter(&proc->p_crlock);
1650 	crhold(cr = proc->p_cred);
1651 	mutex_exit(&proc->p_crlock);
1652 	mutex_exit(&proc->p_lock);
1653 
1654 	ainfo = crgetauinfo(cr);
1655 	if (ainfo == NULL) {
1656 		crfree(cr);
1657 		return (EINVAL);
1658 	}
1659 
1660 	/* designated process has an ipv6 address? */
1661 	if (ainfo->ai_termid.at_type == AU_IPv6) {
1662 		crfree(cr);
1663 		return (EOVERFLOW);
1664 	}
1665 
1666 	STRUCT_FSET(apinfo, ap_auid, ainfo->ai_auid);
1667 	STRUCT_FSET(apinfo, ap_asid, ainfo->ai_asid);
1668 #ifdef _LP64
1669 	if (model == DATAMODEL_ILP32) {
1670 		dev32_t dev;
1671 		/* convert internal 64 bit form to 32 bit version */
1672 		if (cmpldev(&dev, ainfo->ai_termid.at_port) == 0) {
1673 			crfree(cr);
1674 			return (EOVERFLOW);
1675 		}
1676 		STRUCT_FSET(apinfo, ap_termid.port, dev);
1677 	} else
1678 		STRUCT_FSET(apinfo, ap_termid.port, ainfo->ai_termid.at_port);
1679 #else
1680 	STRUCT_FSET(apinfo, ap_termid.port, ainfo->ai_termid.at_port);
1681 #endif
1682 	STRUCT_FSET(apinfo, ap_termid.machine, ainfo->ai_termid.at_addr[0]);
1683 	STRUCT_FSET(apinfo, ap_mask, ainfo->ai_mask);
1684 
1685 	crfree(cr);
1686 
1687 	if (copyout(STRUCT_BUF(apinfo), data, STRUCT_SIZE(apinfo)))
1688 		return (EFAULT);
1689 
1690 	return (0);
1691 }
1692 
1693 static int
1694 getpinfo_addr(caddr_t data, int len)
1695 {
1696 	STRUCT_DECL(auditpinfo_addr, apinfo);
1697 	proc_t *proc;
1698 	const auditinfo_addr_t	*ainfo;
1699 	model_t	model;
1700 	cred_t	*cr, *newcred;
1701 
1702 	model = get_udatamodel();
1703 	STRUCT_INIT(apinfo, model);
1704 
1705 	if (len < STRUCT_SIZE(apinfo))
1706 		return (EOVERFLOW);
1707 
1708 	if (copyin(data, STRUCT_BUF(apinfo), STRUCT_SIZE(apinfo)))
1709 		return (EFAULT);
1710 
1711 	newcred = cralloc();
1712 
1713 	mutex_enter(&pidlock);
1714 	if ((proc = prfind(STRUCT_FGET(apinfo, ap_pid))) == NULL) {
1715 		mutex_exit(&pidlock);
1716 		crfree(newcred);
1717 		return (ESRCH);
1718 	}
1719 	mutex_enter(&proc->p_lock);	/* so process doesn't go away */
1720 	mutex_exit(&pidlock);
1721 
1722 	audit_update_context(proc, newcred);	/* make sure it's up-to-date */
1723 
1724 	mutex_enter(&proc->p_crlock);
1725 	crhold(cr = proc->p_cred);
1726 	mutex_exit(&proc->p_crlock);
1727 	mutex_exit(&proc->p_lock);
1728 
1729 	ainfo = crgetauinfo(cr);
1730 	if (ainfo == NULL) {
1731 		crfree(cr);
1732 		return (EINVAL);
1733 	}
1734 
1735 	STRUCT_FSET(apinfo, ap_auid, ainfo->ai_auid);
1736 	STRUCT_FSET(apinfo, ap_asid, ainfo->ai_asid);
1737 #ifdef _LP64
1738 	if (model == DATAMODEL_ILP32) {
1739 		dev32_t dev;
1740 		/* convert internal 64 bit form to 32 bit version */
1741 		if (cmpldev(&dev, ainfo->ai_termid.at_port) == 0) {
1742 			crfree(cr);
1743 			return (EOVERFLOW);
1744 		}
1745 		STRUCT_FSET(apinfo, ap_termid.at_port, dev);
1746 	} else
1747 		STRUCT_FSET(apinfo, ap_termid.at_port,
1748 		    ainfo->ai_termid.at_port);
1749 #else
1750 	STRUCT_FSET(apinfo, ap_termid.at_port, ainfo->ai_termid.at_port);
1751 #endif
1752 	STRUCT_FSET(apinfo, ap_termid.at_type, ainfo->ai_termid.at_type);
1753 	STRUCT_FSET(apinfo, ap_termid.at_addr[0], ainfo->ai_termid.at_addr[0]);
1754 	STRUCT_FSET(apinfo, ap_termid.at_addr[1], ainfo->ai_termid.at_addr[1]);
1755 	STRUCT_FSET(apinfo, ap_termid.at_addr[2], ainfo->ai_termid.at_addr[2]);
1756 	STRUCT_FSET(apinfo, ap_termid.at_addr[3], ainfo->ai_termid.at_addr[3]);
1757 	STRUCT_FSET(apinfo, ap_mask, ainfo->ai_mask);
1758 
1759 	crfree(cr);
1760 
1761 	if (copyout(STRUCT_BUF(apinfo), data, STRUCT_SIZE(apinfo)))
1762 		return (EFAULT);
1763 
1764 	return (0);
1765 }
1766 
1767 static int
1768 setpmask(caddr_t data)
1769 {
1770 	STRUCT_DECL(auditpinfo, apinfo);
1771 	proc_t *proc;
1772 	cred_t	*newcred;
1773 	auditinfo_addr_t	*ainfo;
1774 	struct p_audit_data	*pad;
1775 
1776 	model_t	model;
1777 
1778 	model = get_udatamodel();
1779 	STRUCT_INIT(apinfo, model);
1780 
1781 	if (copyin(data, STRUCT_BUF(apinfo), STRUCT_SIZE(apinfo)))
1782 		return (EFAULT);
1783 
1784 	mutex_enter(&pidlock);
1785 	if ((proc = prfind(STRUCT_FGET(apinfo, ap_pid))) == NULL) {
1786 		mutex_exit(&pidlock);
1787 		return (ESRCH);
1788 	}
1789 	mutex_enter(&proc->p_lock);	/* so process doesn't go away */
1790 	mutex_exit(&pidlock);
1791 
1792 	newcred = cralloc();
1793 	if ((ainfo = crgetauinfo_modifiable(newcred)) == NULL) {
1794 		mutex_exit(&proc->p_lock);
1795 		crfree(newcred);
1796 		return (EINVAL);
1797 	}
1798 
1799 	mutex_enter(&proc->p_crlock);
1800 	crcopy_to(proc->p_cred, newcred);
1801 	proc->p_cred = newcred;
1802 
1803 	ainfo->ai_mask = STRUCT_FGET(apinfo, ap_mask);
1804 
1805 	/*
1806 	 * Unlock. No need to broadcast changes via set_proc_pre_sys(),
1807 	 * since t_pre_sys is ALWAYS on when audit is enabled... due to
1808 	 * syscall auditing.
1809 	 */
1810 	crfree(newcred);
1811 	mutex_exit(&proc->p_crlock);
1812 
1813 	/* Reset flag for any previous pending mask change; this supercedes */
1814 	pad = P2A(proc);
1815 	ASSERT(pad != NULL);
1816 	mutex_enter(&(pad->pad_lock));
1817 	pad->pad_flags &= ~PAD_SETMASK;
1818 	mutex_exit(&(pad->pad_lock));
1819 
1820 	mutex_exit(&proc->p_lock);
1821 
1822 	return (0);
1823 }
1824 
1825 static int
1826 getfsize(caddr_t data)
1827 {
1828 	au_fstat_t fstat;
1829 	au_kcontext_t	*kctx = GET_KCTX_PZ;
1830 
1831 	mutex_enter(&(kctx->auk_fstat_lock));
1832 	fstat.af_filesz = kctx->auk_file_stat.af_filesz;
1833 	fstat.af_currsz = kctx->auk_file_stat.af_currsz;
1834 	mutex_exit(&(kctx->auk_fstat_lock));
1835 
1836 	if (copyout(&fstat, data, sizeof (au_fstat_t)))
1837 		return (EFAULT);
1838 
1839 	return (0);
1840 }
1841 
1842 static int
1843 setfsize(caddr_t data)
1844 {
1845 	au_fstat_t fstat;
1846 	au_kcontext_t	*kctx;
1847 
1848 	if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc))
1849 		return (EINVAL);
1850 
1851 	kctx = GET_KCTX_NGZ;
1852 
1853 	if (copyin(data, &fstat, sizeof (au_fstat_t)))
1854 		return (EFAULT);
1855 
1856 	if ((fstat.af_filesz != 0) && (fstat.af_filesz < AU_MIN_FILE_SZ))
1857 		return (EINVAL);
1858 
1859 	mutex_enter(&(kctx->auk_fstat_lock));
1860 	kctx->auk_file_stat.af_filesz = fstat.af_filesz;
1861 	mutex_exit(&(kctx->auk_fstat_lock));
1862 
1863 	return (0);
1864 }
1865 /*
1866  * The out of control system call
1867  * This is audit kitchen sink aka auditadm, aka auditon
1868  */
1869 static int
1870 auditctl(
1871 	int	cmd,
1872 	caddr_t data,
1873 	int	length)
1874 {
1875 	int result;
1876 
1877 	if (!audit_active)
1878 		return (EINVAL);
1879 
1880 	switch (cmd) {
1881 	case A_GETCOND:
1882 	case A_GETCAR:
1883 	case A_GETCLASS:
1884 	case A_GETCWD:
1885 	case A_GETFSIZE:
1886 	case A_GETKAUDIT:
1887 	case A_GETKMASK:
1888 	case A_GETPINFO:
1889 	case A_GETPINFO_ADDR:
1890 	case A_GETPOLICY:
1891 	case A_GETQCTRL:
1892 	case A_GETSTAT:
1893 		if (secpolicy_audit_getattr(CRED()) != 0)
1894 			return (EPERM);
1895 		break;
1896 	default:
1897 		if (secpolicy_audit_config(CRED()) != 0)
1898 			return (EPERM);
1899 		break;
1900 	}
1901 
1902 	switch (cmd) {
1903 	case A_GETPOLICY:
1904 		result = getpolicy(data);
1905 		break;
1906 	case A_SETPOLICY:
1907 		result = setpolicy(data);
1908 		break;
1909 	case A_GETKMASK:
1910 		result = getkmask(data);
1911 		break;
1912 	case A_SETKMASK:
1913 		result = setkmask(data);
1914 		break;
1915 	case A_GETKAUDIT:
1916 		result = getkaudit(data, length);
1917 		break;
1918 	case A_SETKAUDIT:
1919 		result = setkaudit(data, length);
1920 		break;
1921 	case A_GETQCTRL:
1922 		result = getqctrl(data);
1923 		break;
1924 	case A_SETQCTRL:
1925 		result = setqctrl(data);
1926 		break;
1927 	case A_GETCWD:
1928 		result = getcwd(data, length);
1929 		break;
1930 	case A_GETCAR:
1931 		result = getcar(data, length);
1932 		break;
1933 	case A_GETSTAT:
1934 		result = getstat(data);
1935 		break;
1936 	case A_SETSTAT:
1937 		result = setstat(data);
1938 		break;
1939 	case A_SETUMASK:
1940 		result = setumask(data);
1941 		break;
1942 	case A_SETSMASK:
1943 		result = setsmask(data);
1944 		break;
1945 	case A_GETCOND:
1946 		result = getcond(data);
1947 		break;
1948 	case A_SETCOND:
1949 		result = setcond(data);
1950 		break;
1951 	case A_GETCLASS:
1952 		result = getclass(data);
1953 		break;
1954 	case A_SETCLASS:
1955 		result = setclass(data);
1956 		break;
1957 	case A_GETPINFO:
1958 		result = getpinfo(data);
1959 		break;
1960 	case A_GETPINFO_ADDR:
1961 		result = getpinfo_addr(data, length);
1962 		break;
1963 	case A_SETPMASK:
1964 		result = setpmask(data);
1965 		break;
1966 	case A_SETFSIZE:
1967 		result = setfsize(data);
1968 		break;
1969 	case A_GETFSIZE:
1970 		result = getfsize(data);
1971 		break;
1972 	default:
1973 		result = EINVAL;
1974 		break;
1975 	}
1976 	return (result);
1977 }
1978 
1979 static int
1980 audit_modsysent(char *modname, int flags, int (*func)())
1981 {
1982 	struct sysent *sysp;
1983 	int sysnum;
1984 	krwlock_t *kl;
1985 
1986 	if ((sysnum = mod_getsysnum(modname)) == -1) {
1987 		cmn_err(CE_WARN, "system call missing from bind file");
1988 		return (-1);
1989 	}
1990 
1991 	kl = (krwlock_t *)kobj_zalloc(sizeof (krwlock_t), KM_SLEEP);
1992 
1993 	sysp = &sysent[sysnum];
1994 	sysp->sy_narg = auditsysent.sy_narg;
1995 #ifdef _LP64
1996 	sysp->sy_flags = (unsigned short)flags;
1997 #else
1998 	sysp->sy_flags = (unsigned char)flags;
1999 #endif
2000 	sysp->sy_call = func;
2001 	sysp->sy_lock = kl;
2002 
2003 #ifdef _SYSCALL32_IMPL
2004 	sysp = &sysent32[sysnum];
2005 	sysp->sy_narg = auditsysent.sy_narg;
2006 	sysp->sy_flags = (unsigned short)flags;
2007 	sysp->sy_call = func;
2008 	sysp->sy_lock = kl;
2009 #endif
2010 
2011 	rw_init(sysp->sy_lock, NULL, RW_DEFAULT, NULL);
2012 
2013 	return (0);
2014 }
2015