xref: /illumos-gate/usr/src/uts/common/syscall/auditsys.c (revision b6805bf78d2bbbeeaea8909a05623587b42d58b3)
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 (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 
25 #include <sys/systm.h>
26 #include <sys/errno.h>
27 #include <sys/policy.h>
28 
29 #include <c2/audit.h>
30 #include <c2/audit_kernel.h>
31 #include <c2/audit_record.h>
32 
33 #define	CLEAR_VAL -1
34 
35 extern kmutex_t pidlock;
36 
37 uint32_t audit_policy; /* global audit policies in force */
38 
39 
40 /*ARGSUSED1*/
41 int
42 auditsys(struct auditcalls *uap, rval_t *rvp)
43 {
44 	int err;
45 	int result = 0;
46 
47 	if (audit_active == C2AUDIT_DISABLED)
48 		return (ENOTSUP);
49 
50 	switch (uap->code) {
51 	case BSM_GETAUID:
52 		result = getauid((caddr_t)uap->a1);
53 		break;
54 	case BSM_SETAUID:
55 		result = setauid((caddr_t)uap->a1);
56 		break;
57 	case BSM_GETAUDIT:
58 		result = getaudit((caddr_t)uap->a1);
59 		break;
60 	case BSM_GETAUDIT_ADDR:
61 		result = getaudit_addr((caddr_t)uap->a1, (int)uap->a2);
62 		break;
63 	case BSM_SETAUDIT:
64 		result = setaudit((caddr_t)uap->a1);
65 		break;
66 	case BSM_SETAUDIT_ADDR:
67 		result = setaudit_addr((caddr_t)uap->a1, (int)uap->a2);
68 		break;
69 	case BSM_AUDITCTL:
70 		result = auditctl((int)uap->a1, (caddr_t)uap->a2, (int)uap->a3);
71 		break;
72 	case BSM_AUDIT:
73 		if (audit_active == C2AUDIT_UNLOADED)
74 			return (0);
75 		result = audit((caddr_t)uap->a1, (int)uap->a2);
76 		break;
77 	case BSM_AUDITDOOR:
78 		if (audit_active == C2AUDIT_LOADED) {
79 			result = auditdoor((int)uap->a1);
80 			break;
81 		}
82 	default:
83 		if (audit_active == C2AUDIT_LOADED) {
84 			result = EINVAL;
85 			break;
86 		}
87 		/* Return a different error when not privileged */
88 		err = secpolicy_audit_config(CRED());
89 		if (err == 0)
90 			return (EINVAL);
91 		else
92 			return (err);
93 	}
94 	rvp->r_vals = result;
95 	return (result);
96 }
97 
98 /*
99  * Return the audit user ID for the current process.  Currently only
100  * the privileged processes may see the audit id.  That may change.
101  * If copyout is unsucessful return EFAULT.
102  */
103 int
104 getauid(caddr_t auid_p)
105 {
106 	const auditinfo_addr_t	*ainfo;
107 
108 	if (secpolicy_audit_getattr(CRED(), B_FALSE) != 0)
109 		return (EPERM);
110 
111 	ainfo = crgetauinfo(CRED());
112 	if (ainfo == NULL)
113 		return (EINVAL);
114 
115 	if (copyout(&ainfo->ai_auid, auid_p, sizeof (au_id_t)))
116 		return (EFAULT);
117 
118 	return (0);
119 }
120 
121 /*
122  * Set the audit userid, for a process.  This can only be changed by
123  * privileged processes.  The audit userid is inherited across forks & execs.
124  * Passed in is a pointer to the au_id_t; if copyin unsuccessful return EFAULT.
125  */
126 int
127 setauid(caddr_t auid_p)
128 {
129 	proc_t *p;
130 	au_id_t	auid;
131 	cred_t *newcred;
132 	auditinfo_addr_t *auinfo;
133 
134 	if (secpolicy_audit_config(CRED()) != 0)
135 		return (EPERM);
136 
137 	if (copyin(auid_p, &auid, sizeof (au_id_t))) {
138 		return (EFAULT);
139 	}
140 
141 	newcred = cralloc();
142 	if ((auinfo = crgetauinfo_modifiable(newcred)) == NULL) {
143 		crfree(newcred);
144 		return (EINVAL);
145 	}
146 
147 	/* grab p_crlock and switch to new cred */
148 	p = curproc;
149 	mutex_enter(&p->p_crlock);
150 	crcopy_to(p->p_cred, newcred);
151 	p->p_cred = newcred;
152 
153 	auinfo->ai_auid = auid;			/* update the auid */
154 
155 	/* unlock and broadcast the cred changes */
156 	mutex_exit(&p->p_crlock);
157 	crset(p, newcred);
158 
159 	return (0);
160 }
161 
162 /*
163  * Get the audit state information from the current process.
164  * Return EFAULT if copyout fails.
165  */
166 int
167 getaudit(caddr_t info_p)
168 {
169 	STRUCT_DECL(auditinfo, info);
170 	const auditinfo_addr_t	*ainfo;
171 	model_t	model;
172 
173 	if (secpolicy_audit_getattr(CRED(), B_FALSE) != 0)
174 		return (EPERM);
175 
176 	model = get_udatamodel();
177 	STRUCT_INIT(info, model);
178 
179 	ainfo = crgetauinfo(CRED());
180 	if (ainfo == NULL)
181 		return (EINVAL);
182 
183 	/* trying to read a process with an IPv6 address? */
184 	if (ainfo->ai_termid.at_type == AU_IPv6)
185 		return (EOVERFLOW);
186 
187 	STRUCT_FSET(info, ai_auid, ainfo->ai_auid);
188 	STRUCT_FSET(info, ai_mask, ainfo->ai_mask);
189 #ifdef _LP64
190 	if (model == DATAMODEL_ILP32) {
191 		dev32_t dev;
192 		/* convert internal 64 bit form to 32 bit version */
193 		if (cmpldev(&dev, ainfo->ai_termid.at_port) == 0) {
194 			return (EOVERFLOW);
195 		}
196 		STRUCT_FSET(info, ai_termid.port, dev);
197 	} else
198 		STRUCT_FSET(info, ai_termid.port, ainfo->ai_termid.at_port);
199 #else
200 	STRUCT_FSET(info, ai_termid.port, ainfo->ai_termid.at_port);
201 #endif
202 	STRUCT_FSET(info, ai_termid.machine, ainfo->ai_termid.at_addr[0]);
203 	STRUCT_FSET(info, ai_asid, ainfo->ai_asid);
204 
205 	if (copyout(STRUCT_BUF(info), info_p, STRUCT_SIZE(info)))
206 		return (EFAULT);
207 
208 	return (0);
209 }
210 
211 /*
212  * Get the audit state information from the current process.
213  * Return EFAULT if copyout fails.
214  */
215 int
216 getaudit_addr(caddr_t info_p, int len)
217 {
218 	STRUCT_DECL(auditinfo_addr, info);
219 	const auditinfo_addr_t	*ainfo;
220 	model_t	model;
221 
222 	if (secpolicy_audit_getattr(CRED(), B_FALSE) != 0)
223 		return (EPERM);
224 
225 	model = get_udatamodel();
226 	STRUCT_INIT(info, model);
227 
228 	if (len < STRUCT_SIZE(info))
229 		return (EOVERFLOW);
230 
231 	ainfo = crgetauinfo(CRED());
232 
233 	if (ainfo == NULL)
234 		return (EINVAL);
235 
236 	STRUCT_FSET(info, ai_auid, ainfo->ai_auid);
237 	STRUCT_FSET(info, ai_mask, ainfo->ai_mask);
238 #ifdef _LP64
239 	if (model == DATAMODEL_ILP32) {
240 		dev32_t dev;
241 		/* convert internal 64 bit form to 32 bit version */
242 		if (cmpldev(&dev, ainfo->ai_termid.at_port) == 0) {
243 			return (EOVERFLOW);
244 		}
245 		STRUCT_FSET(info, ai_termid.at_port, dev);
246 	} else
247 		STRUCT_FSET(info, ai_termid.at_port, ainfo->ai_termid.at_port);
248 #else
249 	STRUCT_FSET(info, ai_termid.at_port, ainfo->ai_termid.at_port);
250 #endif
251 	STRUCT_FSET(info, ai_termid.at_type, ainfo->ai_termid.at_type);
252 	STRUCT_FSET(info, ai_termid.at_addr[0], ainfo->ai_termid.at_addr[0]);
253 	STRUCT_FSET(info, ai_termid.at_addr[1], ainfo->ai_termid.at_addr[1]);
254 	STRUCT_FSET(info, ai_termid.at_addr[2], ainfo->ai_termid.at_addr[2]);
255 	STRUCT_FSET(info, ai_termid.at_addr[3], ainfo->ai_termid.at_addr[3]);
256 	STRUCT_FSET(info, ai_asid, ainfo->ai_asid);
257 
258 	if (copyout(STRUCT_BUF(info), info_p, STRUCT_SIZE(info)))
259 		return (EFAULT);
260 
261 	return (0);
262 }
263 
264 /*
265  * Set the audit state information for the current process.
266  * Return EFAULT if copyout fails.
267  */
268 int
269 setaudit(caddr_t info_p)
270 {
271 	STRUCT_DECL(auditinfo, info);
272 	proc_t *p;
273 	cred_t	*newcred;
274 	model_t	model;
275 	auditinfo_addr_t *ainfo;
276 
277 	if (secpolicy_audit_config(CRED()) != 0)
278 		return (EPERM);
279 
280 	model = get_udatamodel();
281 	STRUCT_INIT(info, model);
282 
283 	if (copyin(info_p, STRUCT_BUF(info), STRUCT_SIZE(info)))
284 		return (EFAULT);
285 
286 	newcred = cralloc();
287 	if ((ainfo = crgetauinfo_modifiable(newcred)) == NULL) {
288 		crfree(newcred);
289 		return (EINVAL);
290 	}
291 
292 	/* grab p_crlock and switch to new cred */
293 	p = curproc;
294 	mutex_enter(&p->p_crlock);
295 	crcopy_to(p->p_cred, newcred);
296 	p->p_cred = newcred;
297 
298 	/* Set audit mask, id, termid and session id as specified */
299 	ainfo->ai_auid = STRUCT_FGET(info, ai_auid);
300 #ifdef _LP64
301 	/* only convert to 64 bit if coming from a 32 bit binary */
302 	if (model == DATAMODEL_ILP32)
303 		ainfo->ai_termid.at_port =
304 		    DEVEXPL(STRUCT_FGET(info, ai_termid.port));
305 	else
306 		ainfo->ai_termid.at_port = STRUCT_FGET(info, ai_termid.port);
307 #else
308 	ainfo->ai_termid.at_port = STRUCT_FGET(info, ai_termid.port);
309 #endif
310 	ainfo->ai_termid.at_type = AU_IPv4;
311 	ainfo->ai_termid.at_addr[0] = STRUCT_FGET(info, ai_termid.machine);
312 	ainfo->ai_asid = STRUCT_FGET(info, ai_asid);
313 	ainfo->ai_mask = STRUCT_FGET(info, ai_mask);
314 
315 	/* unlock and broadcast the cred changes */
316 	mutex_exit(&p->p_crlock);
317 	crset(p, newcred);
318 
319 	return (0);
320 }
321 
322 /*
323  * Set the audit state information for the current process.
324  * Return EFAULT if copyin fails.
325  */
326 int
327 setaudit_addr(caddr_t info_p, int len)
328 {
329 	STRUCT_DECL(auditinfo_addr, info);
330 	proc_t *p;
331 	cred_t	*newcred;
332 	model_t	model;
333 	int i;
334 	int type;
335 	auditinfo_addr_t *ainfo;
336 
337 	if (secpolicy_audit_config(CRED()) != 0)
338 		return (EPERM);
339 
340 	model = get_udatamodel();
341 	STRUCT_INIT(info, model);
342 
343 	if (len < STRUCT_SIZE(info))
344 		return (EOVERFLOW);
345 
346 	if (copyin(info_p, STRUCT_BUF(info), STRUCT_SIZE(info)))
347 		return (EFAULT);
348 
349 	type = STRUCT_FGET(info, ai_termid.at_type);
350 	if ((type != AU_IPv4) && (type != AU_IPv6))
351 		return (EINVAL);
352 
353 	newcred = cralloc();
354 	if ((ainfo = crgetauinfo_modifiable(newcred)) == NULL) {
355 		crfree(newcred);
356 		return (EINVAL);
357 	}
358 
359 	/* grab p_crlock and switch to new cred */
360 	p = curproc;
361 	mutex_enter(&p->p_crlock);
362 	crcopy_to(p->p_cred, newcred);
363 	p->p_cred = newcred;
364 
365 	/* Set audit mask, id, termid and session id as specified */
366 	ainfo->ai_auid = STRUCT_FGET(info, ai_auid);
367 	ainfo->ai_mask = STRUCT_FGET(info, ai_mask);
368 #ifdef _LP64
369 	/* only convert to 64 bit if coming from a 32 bit binary */
370 	if (model == DATAMODEL_ILP32)
371 		ainfo->ai_termid.at_port =
372 		    DEVEXPL(STRUCT_FGET(info, ai_termid.at_port));
373 	else
374 		ainfo->ai_termid.at_port = STRUCT_FGET(info, ai_termid.at_port);
375 #else
376 	ainfo->ai_termid.at_port = STRUCT_FGET(info, ai_termid.at_port);
377 #endif
378 	ainfo->ai_termid.at_type = type;
379 	bzero(&ainfo->ai_termid.at_addr[0], sizeof (ainfo->ai_termid.at_addr));
380 	for (i = 0; i < (type/sizeof (int)); i++)
381 		ainfo->ai_termid.at_addr[i] =
382 		    STRUCT_FGET(info, ai_termid.at_addr[i]);
383 
384 	if (ainfo->ai_termid.at_type == AU_IPv6 &&
385 	    IN6_IS_ADDR_V4MAPPED(((in6_addr_t *)ainfo->ai_termid.at_addr))) {
386 		ainfo->ai_termid.at_type = AU_IPv4;
387 		ainfo->ai_termid.at_addr[0] = ainfo->ai_termid.at_addr[3];
388 		ainfo->ai_termid.at_addr[1] = 0;
389 		ainfo->ai_termid.at_addr[2] = 0;
390 		ainfo->ai_termid.at_addr[3] = 0;
391 	}
392 
393 	ainfo->ai_asid = STRUCT_FGET(info, ai_asid);
394 
395 	/* unlock and broadcast the cred changes */
396 	mutex_exit(&p->p_crlock);
397 	crset(p, newcred);
398 
399 	return (0);
400 }
401 
402 /*
403  * Get the global policy flag
404  */
405 static int
406 getpolicy(caddr_t data)
407 {
408 	uint32_t	policy;
409 	au_kcontext_t	*kctx = GET_KCTX_PZ;
410 
411 	policy = audit_policy | kctx->auk_policy;
412 
413 	if (copyout(&policy, data, sizeof (policy)))
414 		return (EFAULT);
415 	return (0);
416 }
417 
418 /*
419  * Set the global and local policy flags
420  *
421  * The global flags only make sense from the global zone;
422  * the local flags depend on the AUDIT_PERZONE policy:
423  * if the perzone policy is set, then policy is set separately
424  * per zone, else held only in the global zone.
425  *
426  * The initial value of a local zone's policy flag is determined
427  * by the value of the global zone's flags at the time the
428  * local zone is created.
429  *
430  * While auditconfig(1M) allows setting and unsetting policies one bit
431  * at a time, the mask passed in from auditconfig() is created by a
432  * syscall to getpolicy and then modified based on the auditconfig()
433  * cmd line, so the input policy value is used to replace the existing
434  * policy.
435  */
436 static int
437 setpolicy(caddr_t data)
438 {
439 	uint32_t	policy;
440 	au_kcontext_t	*kctx;
441 
442 	if (copyin(data, &policy, sizeof (policy)))
443 		return (EFAULT);
444 
445 	kctx = GET_KCTX_NGZ;
446 
447 	if (INGLOBALZONE(curproc)) {
448 		if (policy & ~(AUDIT_GLOBAL | AUDIT_LOCAL))
449 			return (EINVAL);
450 
451 		audit_policy = policy & AUDIT_GLOBAL;
452 	} else {
453 		if (!(audit_policy & AUDIT_PERZONE))
454 			return (EINVAL);
455 
456 		if (policy & ~AUDIT_LOCAL)	/* global bits are a no-no */
457 			return (EINVAL);
458 	}
459 	kctx->auk_policy = policy & AUDIT_LOCAL;
460 
461 	/*
462 	 * auk_current_vp is NULL before auditd starts (or during early
463 	 * auditd starup) or if auditd is halted; in either case,
464 	 * notification of a policy change is not needed, since auditd
465 	 * reads policy as it comes up.  The error return from au_doormsg()
466 	 * is ignored to avoid a race condition -- for example if auditd
467 	 * segv's, the audit state may be "auditing" but the door may
468 	 * be closed.  Returning an error if the door is open makes it
469 	 * impossible for Greenline to restart auditd.
470 	 */
471 	if (kctx->auk_current_vp != NULL)
472 		(void) au_doormsg(kctx, AU_DBUF_POLICY, &policy);
473 
474 	/*
475 	 * Wake up anyone who might have blocked on full audit
476 	 * partitions. audit daemons need to set AUDIT_FULL when no
477 	 * space so we can tell if we should start dropping records.
478 	 */
479 	mutex_enter(&(kctx->auk_queue.lock));
480 
481 	if ((policy & (AUDIT_CNT | AUDIT_SCNT) &&
482 	    (kctx->auk_queue.cnt >= kctx->auk_queue.hiwater)))
483 		cv_broadcast(&(kctx->auk_queue.write_cv));
484 
485 	mutex_exit(&(kctx->auk_queue.lock));
486 
487 	return (0);
488 }
489 
490 static int
491 getamask(caddr_t data)
492 {
493 	au_kcontext_t	*kctx;
494 
495 	kctx = GET_KCTX_PZ;
496 
497 	if (copyout(&kctx->auk_info.ai_amask, data, sizeof (au_mask_t)))
498 		return (EFAULT);
499 
500 	return (0);
501 }
502 
503 static int
504 setamask(caddr_t data)
505 {
506 	au_mask_t	mask;
507 	au_kcontext_t	*kctx;
508 
509 	if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc))
510 		return (EINVAL);
511 
512 	kctx = GET_KCTX_NGZ;
513 
514 	if (copyin(data, &mask, sizeof (au_mask_t)))
515 		return (EFAULT);
516 
517 	kctx->auk_info.ai_amask = mask;
518 	return (0);
519 }
520 
521 static int
522 getkmask(caddr_t data)
523 {
524 	au_kcontext_t	*kctx;
525 
526 	kctx = GET_KCTX_PZ;
527 
528 	if (copyout(&kctx->auk_info.ai_namask, data, sizeof (au_mask_t)))
529 		return (EFAULT);
530 	return (0);
531 }
532 
533 static int
534 setkmask(caddr_t data)
535 {
536 	au_mask_t	mask;
537 	au_kcontext_t	*kctx;
538 
539 	if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc))
540 		return (EINVAL);
541 
542 	kctx = GET_KCTX_NGZ;
543 
544 	if (copyin(data, &mask, sizeof (au_mask_t)))
545 		return (EFAULT);
546 
547 	kctx->auk_info.ai_namask = mask;
548 	return (0);
549 }
550 
551 static int
552 getkaudit(caddr_t info_p, int len)
553 {
554 	STRUCT_DECL(auditinfo_addr, info);
555 	model_t model;
556 	au_kcontext_t	*kctx = GET_KCTX_PZ;
557 
558 	model = get_udatamodel();
559 	STRUCT_INIT(info, model);
560 
561 	if (len < STRUCT_SIZE(info))
562 		return (EOVERFLOW);
563 
564 	STRUCT_FSET(info, ai_auid, kctx->auk_info.ai_auid);
565 	STRUCT_FSET(info, ai_mask, kctx->auk_info.ai_namask);
566 #ifdef _LP64
567 	if (model == DATAMODEL_ILP32) {
568 		dev32_t dev;
569 		/* convert internal 64 bit form to 32 bit version */
570 		if (cmpldev(&dev, kctx->auk_info.ai_termid.at_port) == 0) {
571 			return (EOVERFLOW);
572 		}
573 		STRUCT_FSET(info, ai_termid.at_port, dev);
574 	} else {
575 		STRUCT_FSET(info, ai_termid.at_port,
576 		    kctx->auk_info.ai_termid.at_port);
577 	}
578 #else
579 	STRUCT_FSET(info, ai_termid.at_port,
580 	    kctx->auk_info.ai_termid.at_port);
581 #endif
582 	STRUCT_FSET(info, ai_termid.at_type,
583 	    kctx->auk_info.ai_termid.at_type);
584 	STRUCT_FSET(info, ai_termid.at_addr[0],
585 	    kctx->auk_info.ai_termid.at_addr[0]);
586 	STRUCT_FSET(info, ai_termid.at_addr[1],
587 	    kctx->auk_info.ai_termid.at_addr[1]);
588 	STRUCT_FSET(info, ai_termid.at_addr[2],
589 	    kctx->auk_info.ai_termid.at_addr[2]);
590 	STRUCT_FSET(info, ai_termid.at_addr[3],
591 	    kctx->auk_info.ai_termid.at_addr[3]);
592 	STRUCT_FSET(info, ai_asid, kctx->auk_info.ai_asid);
593 
594 	if (copyout(STRUCT_BUF(info), info_p, STRUCT_SIZE(info)))
595 		return (EFAULT);
596 
597 	return (0);
598 }
599 
600 /*
601  * the host address for AUDIT_PERZONE == 0 is that of the global
602  * zone and for local zones it is of the current zone.
603  */
604 static int
605 setkaudit(caddr_t info_p, int len)
606 {
607 	STRUCT_DECL(auditinfo_addr, info);
608 	model_t model;
609 	au_kcontext_t	*kctx;
610 
611 	if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc))
612 		return (EINVAL);
613 
614 	kctx = GET_KCTX_NGZ;
615 
616 	model = get_udatamodel();
617 	STRUCT_INIT(info, model);
618 
619 	if (len < STRUCT_SIZE(info))
620 		return (EOVERFLOW);
621 
622 	if (copyin(info_p, STRUCT_BUF(info), STRUCT_SIZE(info)))
623 		return (EFAULT);
624 
625 	if ((STRUCT_FGET(info, ai_termid.at_type) != AU_IPv4) &&
626 	    (STRUCT_FGET(info, ai_termid.at_type) != AU_IPv6))
627 		return (EINVAL);
628 
629 	/* Set audit mask, termid and session id as specified */
630 	kctx->auk_info.ai_auid = STRUCT_FGET(info, ai_auid);
631 	kctx->auk_info.ai_namask = STRUCT_FGET(info, ai_mask);
632 #ifdef _LP64
633 	/* only convert to 64 bit if coming from a 32 bit binary */
634 	if (model == DATAMODEL_ILP32)
635 		kctx->auk_info.ai_termid.at_port =
636 		    DEVEXPL(STRUCT_FGET(info, ai_termid.at_port));
637 	else
638 		kctx->auk_info.ai_termid.at_port =
639 		    STRUCT_FGET(info, ai_termid.at_port);
640 #else
641 	kctx->auk_info.ai_termid.at_port = STRUCT_FGET(info, ai_termid.at_port);
642 #endif
643 	kctx->auk_info.ai_termid.at_type = STRUCT_FGET(info, ai_termid.at_type);
644 	bzero(&kctx->auk_info.ai_termid.at_addr[0],
645 	    sizeof (kctx->auk_info.ai_termid.at_addr));
646 	kctx->auk_info.ai_termid.at_addr[0] =
647 	    STRUCT_FGET(info, ai_termid.at_addr[0]);
648 	kctx->auk_info.ai_termid.at_addr[1] =
649 	    STRUCT_FGET(info, ai_termid.at_addr[1]);
650 	kctx->auk_info.ai_termid.at_addr[2] =
651 	    STRUCT_FGET(info, ai_termid.at_addr[2]);
652 	kctx->auk_info.ai_termid.at_addr[3] =
653 	    STRUCT_FGET(info, ai_termid.at_addr[3]);
654 	kctx->auk_info.ai_asid = STRUCT_FGET(info, ai_asid);
655 
656 	if (kctx->auk_info.ai_termid.at_type == AU_IPv6 &&
657 	    IN6_IS_ADDR_V4MAPPED(
658 	    ((in6_addr_t *)kctx->auk_info.ai_termid.at_addr))) {
659 		kctx->auk_info.ai_termid.at_type = AU_IPv4;
660 		kctx->auk_info.ai_termid.at_addr[0] =
661 		    kctx->auk_info.ai_termid.at_addr[3];
662 		kctx->auk_info.ai_termid.at_addr[1] = 0;
663 		kctx->auk_info.ai_termid.at_addr[2] = 0;
664 		kctx->auk_info.ai_termid.at_addr[3] = 0;
665 	}
666 	if (kctx->auk_info.ai_termid.at_type == AU_IPv6)
667 		kctx->auk_hostaddr_valid = IN6_IS_ADDR_UNSPECIFIED(
668 		    (in6_addr_t *)kctx->auk_info.ai_termid.at_addr) ? 0 : 1;
669 	else
670 		kctx->auk_hostaddr_valid =
671 		    (kctx->auk_info.ai_termid.at_addr[0] ==
672 		    htonl(INADDR_ANY)) ? 0 : 1;
673 
674 	return (0);
675 }
676 
677 static int
678 getqctrl(caddr_t data)
679 {
680 	au_kcontext_t	*kctx = GET_KCTX_PZ;
681 	STRUCT_DECL(au_qctrl, qctrl);
682 	STRUCT_INIT(qctrl, get_udatamodel());
683 
684 	mutex_enter(&(kctx->auk_queue.lock));
685 	STRUCT_FSET(qctrl, aq_hiwater, kctx->auk_queue.hiwater);
686 	STRUCT_FSET(qctrl, aq_lowater, kctx->auk_queue.lowater);
687 	STRUCT_FSET(qctrl, aq_bufsz, kctx->auk_queue.bufsz);
688 	STRUCT_FSET(qctrl, aq_delay, kctx->auk_queue.delay);
689 	mutex_exit(&(kctx->auk_queue.lock));
690 
691 	if (copyout(STRUCT_BUF(qctrl), data, STRUCT_SIZE(qctrl)))
692 		return (EFAULT);
693 
694 	return (0);
695 }
696 
697 static int
698 setqctrl(caddr_t data)
699 {
700 	au_kcontext_t	*kctx;
701 	struct au_qctrl qctrl_tmp;
702 	STRUCT_DECL(au_qctrl, qctrl);
703 	STRUCT_INIT(qctrl, get_udatamodel());
704 
705 	if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc))
706 		return (EINVAL);
707 	kctx = GET_KCTX_NGZ;
708 
709 	if (copyin(data, STRUCT_BUF(qctrl), STRUCT_SIZE(qctrl)))
710 		return (EFAULT);
711 
712 	qctrl_tmp.aq_hiwater = (size_t)STRUCT_FGET(qctrl, aq_hiwater);
713 	qctrl_tmp.aq_lowater = (size_t)STRUCT_FGET(qctrl, aq_lowater);
714 	qctrl_tmp.aq_bufsz = (size_t)STRUCT_FGET(qctrl, aq_bufsz);
715 	qctrl_tmp.aq_delay = (clock_t)STRUCT_FGET(qctrl, aq_delay);
716 
717 	/* enforce sane values */
718 
719 	if (qctrl_tmp.aq_hiwater <= qctrl_tmp.aq_lowater)
720 		return (EINVAL);
721 
722 	if (qctrl_tmp.aq_hiwater < AQ_LOWATER)
723 		return (EINVAL);
724 
725 	if (qctrl_tmp.aq_hiwater > AQ_MAXHIGH)
726 		return (EINVAL);
727 
728 	if (qctrl_tmp.aq_bufsz < AQ_BUFSZ)
729 		return (EINVAL);
730 
731 	if (qctrl_tmp.aq_bufsz > AQ_MAXBUFSZ)
732 		return (EINVAL);
733 
734 	if (qctrl_tmp.aq_delay == 0)
735 		return (EINVAL);
736 
737 	if (qctrl_tmp.aq_delay > AQ_MAXDELAY)
738 		return (EINVAL);
739 
740 	/* update everything at once so things are consistant */
741 	mutex_enter(&(kctx->auk_queue.lock));
742 	kctx->auk_queue.hiwater = qctrl_tmp.aq_hiwater;
743 	kctx->auk_queue.lowater = qctrl_tmp.aq_lowater;
744 	kctx->auk_queue.bufsz = qctrl_tmp.aq_bufsz;
745 	kctx->auk_queue.delay = qctrl_tmp.aq_delay;
746 
747 	if (kctx->auk_queue.rd_block &&
748 	    kctx->auk_queue.cnt > kctx->auk_queue.lowater)
749 		cv_broadcast(&(kctx->auk_queue.read_cv));
750 
751 	if (kctx->auk_queue.wt_block &&
752 	    kctx->auk_queue.cnt < kctx->auk_queue.hiwater)
753 		cv_broadcast(&(kctx->auk_queue.write_cv));
754 
755 	mutex_exit(&(kctx->auk_queue.lock));
756 
757 	return (0);
758 }
759 
760 static int
761 getcwd(caddr_t data, int length)
762 {
763 	struct p_audit_data	*pad;
764 	struct audit_path	*app;
765 	int	pathlen;
766 
767 	pad = P2A(curproc);
768 	ASSERT(pad != NULL);
769 
770 	mutex_enter(&(pad->pad_lock));
771 	app = pad->pad_cwd;
772 	au_pathhold(app);
773 	mutex_exit(&(pad->pad_lock));
774 
775 	pathlen = app->audp_sect[1] - app->audp_sect[0];
776 	if (pathlen > length) {
777 		au_pathrele(app);
778 		return (E2BIG);
779 	}
780 
781 	if (copyout(app->audp_sect[0], data, pathlen)) {
782 		au_pathrele(app);
783 		return (EFAULT);
784 	}
785 
786 	au_pathrele(app);
787 	return (0);
788 }
789 
790 static int
791 getcar(caddr_t data, int length)
792 {
793 	struct p_audit_data	*pad;
794 	struct audit_path	*app;
795 	int	pathlen;
796 
797 	pad = P2A(curproc);
798 	ASSERT(pad != NULL);
799 
800 	mutex_enter(&(pad->pad_lock));
801 	app = pad->pad_root;
802 	au_pathhold(app);
803 	mutex_exit(&(pad->pad_lock));
804 
805 	pathlen = app->audp_sect[1] - app->audp_sect[0];
806 	if (pathlen > length) {
807 		au_pathrele(app);
808 		return (E2BIG);
809 	}
810 
811 	if (copyout(app->audp_sect[0], data, pathlen)) {
812 		au_pathrele(app);
813 		return (EFAULT);
814 	}
815 
816 	au_pathrele(app);
817 	return (0);
818 }
819 
820 static int
821 getstat(caddr_t data)
822 {
823 	au_kcontext_t	*kctx = GET_KCTX_PZ;
824 
825 	membar_consumer();
826 
827 	if (copyout((caddr_t)&(kctx->auk_statistics), data, sizeof (au_stat_t)))
828 		return (EFAULT);
829 	return (0);
830 }
831 
832 static int
833 setstat(caddr_t data)
834 {
835 	au_kcontext_t *kctx = GET_KCTX_PZ;
836 	au_stat_t au_stat;
837 
838 	if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc))
839 		return (EINVAL);
840 
841 	if (copyin(data, &au_stat, sizeof (au_stat_t)))
842 		return (EFAULT);
843 
844 	if (au_stat.as_generated == CLEAR_VAL)
845 		kctx->auk_statistics.as_generated = 0;
846 	if (au_stat.as_nonattrib == CLEAR_VAL)
847 		kctx->auk_statistics.as_nonattrib = 0;
848 	if (au_stat.as_kernel == CLEAR_VAL)
849 		kctx->auk_statistics.as_kernel = 0;
850 	if (au_stat.as_audit == CLEAR_VAL)
851 		kctx->auk_statistics.as_audit = 0;
852 	if (au_stat.as_auditctl == CLEAR_VAL)
853 		kctx->auk_statistics.as_auditctl = 0;
854 	if (au_stat.as_enqueue == CLEAR_VAL)
855 		kctx->auk_statistics.as_enqueue = 0;
856 	if (au_stat.as_written == CLEAR_VAL)
857 		kctx->auk_statistics.as_written = 0;
858 	if (au_stat.as_wblocked == CLEAR_VAL)
859 		kctx->auk_statistics.as_wblocked = 0;
860 	if (au_stat.as_rblocked == CLEAR_VAL)
861 		kctx->auk_statistics.as_rblocked = 0;
862 	if (au_stat.as_dropped == CLEAR_VAL)
863 		kctx->auk_statistics.as_dropped = 0;
864 	if (au_stat.as_totalsize == CLEAR_VAL)
865 		kctx->auk_statistics.as_totalsize = 0;
866 
867 	membar_producer();
868 
869 	return (0);
870 
871 }
872 
873 static int
874 setumask(caddr_t data)
875 {
876 	STRUCT_DECL(auditinfo, user_info);
877 	struct proc *p;
878 	const auditinfo_addr_t	*ainfo;
879 	model_t	model;
880 
881 	/* setumask not applicable in non-global zones without perzone policy */
882 	if (!(audit_policy & AUDIT_PERZONE) && (!INGLOBALZONE(curproc)))
883 		return (EINVAL);
884 
885 	model = get_udatamodel();
886 	STRUCT_INIT(user_info, model);
887 
888 	if (copyin(data, STRUCT_BUF(user_info), STRUCT_SIZE(user_info)))
889 		return (EFAULT);
890 
891 	mutex_enter(&pidlock);	/* lock the process queue against updates */
892 	for (p = practive; p != NULL; p = p->p_next) {
893 		cred_t	*cr;
894 
895 		/* if in non-global zone only modify processes in same zone */
896 		if (!HASZONEACCESS(curproc, p->p_zone->zone_id))
897 			continue;
898 
899 		mutex_enter(&p->p_lock);	/* so process doesn't go away */
900 
901 		/* skip system processes and ones being created or going away */
902 		if (p->p_stat == SIDL || p->p_stat == SZOMB ||
903 		    (p->p_flag & (SSYS | SEXITING | SEXITLWPS))) {
904 			mutex_exit(&p->p_lock);
905 			continue;
906 		}
907 
908 		mutex_enter(&p->p_crlock);
909 		crhold(cr = p->p_cred);
910 		mutex_exit(&p->p_crlock);
911 		ainfo = crgetauinfo(cr);
912 		if (ainfo == NULL) {
913 			mutex_exit(&p->p_lock);
914 			crfree(cr);
915 			continue;
916 		}
917 
918 		if (ainfo->ai_auid == STRUCT_FGET(user_info, ai_auid)) {
919 			au_mask_t	mask;
920 			int		err;
921 
922 			/*
923 			 * Here's a process which matches the specified auid.
924 			 * If its mask doesn't already match the new mask,
925 			 * save the new mask in the pad, to be picked up
926 			 * next syscall.
927 			 */
928 			mask = STRUCT_FGET(user_info, ai_mask);
929 			err = bcmp(&mask, &ainfo->ai_mask, sizeof (au_mask_t));
930 			crfree(cr);
931 			if (err != 0) {
932 				struct p_audit_data *pad = P2A(p);
933 				ASSERT(pad != NULL);
934 
935 				mutex_enter(&(pad->pad_lock));
936 				pad->pad_flags |= PAD_SETMASK;
937 				pad->pad_newmask = mask;
938 				mutex_exit(&(pad->pad_lock));
939 
940 				/*
941 				 * No need to call set_proc_pre_sys(), since
942 				 * t_pre_sys is ALWAYS on when audit is
943 				 * enabled...due to syscall auditing.
944 				 */
945 			}
946 		} else {
947 			crfree(cr);
948 		}
949 		mutex_exit(&p->p_lock);
950 	}
951 	mutex_exit(&pidlock);
952 
953 	return (0);
954 }
955 
956 static int
957 setsmask(caddr_t data)
958 {
959 	STRUCT_DECL(auditinfo, user_info);
960 	struct proc *p;
961 	const auditinfo_addr_t	*ainfo;
962 	model_t	model;
963 
964 	/* setsmask not applicable in non-global zones without perzone policy */
965 	if (!(audit_policy & AUDIT_PERZONE) && (!INGLOBALZONE(curproc)))
966 		return (EINVAL);
967 
968 	model = get_udatamodel();
969 	STRUCT_INIT(user_info, model);
970 
971 	if (copyin(data, STRUCT_BUF(user_info), STRUCT_SIZE(user_info)))
972 		return (EFAULT);
973 
974 	mutex_enter(&pidlock);	/* lock the process queue against updates */
975 	for (p = practive; p != NULL; p = p->p_next) {
976 		cred_t	*cr;
977 
978 		/* if in non-global zone only modify processes in same zone */
979 		if (!HASZONEACCESS(curproc, p->p_zone->zone_id))
980 			continue;
981 
982 		mutex_enter(&p->p_lock);	/* so process doesn't go away */
983 
984 		/* skip system processes and ones being created or going away */
985 		if (p->p_stat == SIDL || p->p_stat == SZOMB ||
986 		    (p->p_flag & (SSYS | SEXITING | SEXITLWPS))) {
987 			mutex_exit(&p->p_lock);
988 			continue;
989 		}
990 
991 		mutex_enter(&p->p_crlock);
992 		crhold(cr = p->p_cred);
993 		mutex_exit(&p->p_crlock);
994 		ainfo = crgetauinfo(cr);
995 		if (ainfo == NULL) {
996 			mutex_exit(&p->p_lock);
997 			crfree(cr);
998 			continue;
999 		}
1000 
1001 		if (ainfo->ai_asid == STRUCT_FGET(user_info, ai_asid)) {
1002 			au_mask_t	mask;
1003 			int		err;
1004 
1005 			/*
1006 			 * Here's a process which matches the specified asid.
1007 			 * If its mask doesn't already match the new mask,
1008 			 * save the new mask in the pad, to be picked up
1009 			 * next syscall.
1010 			 */
1011 			mask = STRUCT_FGET(user_info, ai_mask);
1012 			err = bcmp(&mask, &ainfo->ai_mask, sizeof (au_mask_t));
1013 			crfree(cr);
1014 			if (err != 0) {
1015 				struct p_audit_data *pad = P2A(p);
1016 				ASSERT(pad != NULL);
1017 
1018 				mutex_enter(&(pad->pad_lock));
1019 				pad->pad_flags |= PAD_SETMASK;
1020 				pad->pad_newmask = mask;
1021 				mutex_exit(&(pad->pad_lock));
1022 
1023 				/*
1024 				 * No need to call set_proc_pre_sys(), since
1025 				 * t_pre_sys is ALWAYS on when audit is
1026 				 * enabled...due to syscall auditing.
1027 				 */
1028 			}
1029 		} else {
1030 			crfree(cr);
1031 		}
1032 		mutex_exit(&p->p_lock);
1033 	}
1034 	mutex_exit(&pidlock);
1035 
1036 	return (0);
1037 }
1038 
1039 /*
1040  * Get the current audit state of the system
1041  */
1042 static int
1043 getcond(caddr_t data)
1044 {
1045 	au_kcontext_t *kctx = GET_KCTX_PZ;
1046 
1047 	if (copyout(&(kctx->auk_auditstate), data, sizeof (int)))
1048 		return (EFAULT);
1049 
1050 	return (0);
1051 }
1052 
1053 /*
1054  * Set the current audit state of the system to on (AUC_AUDITING) or
1055  * off (AUC_NOAUDIT).
1056  */
1057 /* ARGSUSED */
1058 static int
1059 setcond(caddr_t data)
1060 {
1061 	int auditstate;
1062 	au_kcontext_t *kctx;
1063 
1064 	if (!(audit_policy & AUDIT_PERZONE) && (!INGLOBALZONE(curproc)))
1065 		return (EINVAL);
1066 
1067 	kctx = GET_KCTX_NGZ;
1068 
1069 	if (copyin(data, &auditstate, sizeof (int)))
1070 		return (EFAULT);
1071 
1072 	switch (auditstate) {
1073 	case AUC_AUDITING:		/* Turn auditing on */
1074 		if (audit_active == C2AUDIT_UNLOADED)
1075 			audit_init_module();
1076 		kctx->auk_auditstate = AUC_AUDITING;
1077 		if (!(audit_policy & AUDIT_PERZONE) && INGLOBALZONE(curproc))
1078 			set_all_zone_usr_proc_sys(ALL_ZONES);
1079 		else
1080 			set_all_zone_usr_proc_sys(curproc->p_zone->zone_id);
1081 		break;
1082 
1083 	case AUC_NOAUDIT:		/* Turn auditing off */
1084 		if (kctx->auk_auditstate == AUC_NOAUDIT)
1085 			break;
1086 		kctx->auk_auditstate = AUC_NOAUDIT;
1087 
1088 		/* clear out the audit queue */
1089 
1090 		mutex_enter(&(kctx->auk_queue.lock));
1091 		if (kctx->auk_queue.wt_block)
1092 			cv_broadcast(&(kctx->auk_queue.write_cv));
1093 
1094 		/* unblock au_output_thread */
1095 		cv_broadcast(&(kctx->auk_queue.read_cv));
1096 
1097 		mutex_exit(&(kctx->auk_queue.lock));
1098 		break;
1099 
1100 	default:
1101 		return (EINVAL);
1102 	}
1103 
1104 	return (0);
1105 }
1106 
1107 static int
1108 getclass(caddr_t data)
1109 {
1110 	au_evclass_map_t event;
1111 	au_kcontext_t	*kctx = GET_KCTX_PZ;
1112 
1113 	if (copyin(data, &event, sizeof (au_evclass_map_t)))
1114 		return (EFAULT);
1115 
1116 	if (event.ec_number > MAX_KEVENTS)
1117 		return (EINVAL);
1118 
1119 	event.ec_class = kctx->auk_ets[event.ec_number];
1120 
1121 	if (copyout(&event, data, sizeof (au_evclass_map_t)))
1122 		return (EFAULT);
1123 
1124 	return (0);
1125 }
1126 
1127 static int
1128 setclass(caddr_t data)
1129 {
1130 	au_evclass_map_t event;
1131 	au_kcontext_t	*kctx;
1132 
1133 	if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc))
1134 		return (EINVAL);
1135 
1136 	kctx = GET_KCTX_NGZ;
1137 
1138 	if (copyin(data, &event, sizeof (au_evclass_map_t)))
1139 		return (EFAULT);
1140 
1141 	if (event.ec_number > MAX_KEVENTS)
1142 		return (EINVAL);
1143 
1144 	kctx->auk_ets[event.ec_number] = event.ec_class;
1145 
1146 	return (0);
1147 }
1148 
1149 static int
1150 getpinfo(caddr_t data)
1151 {
1152 	STRUCT_DECL(auditpinfo, apinfo);
1153 	proc_t *proc;
1154 	const auditinfo_addr_t	*ainfo;
1155 	model_t	model;
1156 	cred_t	*cr, *newcred;
1157 
1158 	model = get_udatamodel();
1159 	STRUCT_INIT(apinfo, model);
1160 
1161 	if (copyin(data, STRUCT_BUF(apinfo), STRUCT_SIZE(apinfo)))
1162 		return (EFAULT);
1163 
1164 	newcred = cralloc();
1165 
1166 	mutex_enter(&pidlock);
1167 	if ((proc = prfind(STRUCT_FGET(apinfo, ap_pid))) == NULL) {
1168 		mutex_exit(&pidlock);
1169 		crfree(newcred);
1170 		return (ESRCH);		/* no such process */
1171 	}
1172 	mutex_enter(&proc->p_lock);	/* so process doesn't go away */
1173 	mutex_exit(&pidlock);
1174 
1175 	audit_update_context(proc, newcred);	/* make sure it's up-to-date */
1176 
1177 	mutex_enter(&proc->p_crlock);
1178 	crhold(cr = proc->p_cred);
1179 	mutex_exit(&proc->p_crlock);
1180 	mutex_exit(&proc->p_lock);
1181 
1182 	ainfo = crgetauinfo(cr);
1183 	if (ainfo == NULL) {
1184 		crfree(cr);
1185 		return (EINVAL);
1186 	}
1187 
1188 	/* designated process has an ipv6 address? */
1189 	if (ainfo->ai_termid.at_type == AU_IPv6) {
1190 		crfree(cr);
1191 		return (EOVERFLOW);
1192 	}
1193 
1194 	STRUCT_FSET(apinfo, ap_auid, ainfo->ai_auid);
1195 	STRUCT_FSET(apinfo, ap_asid, ainfo->ai_asid);
1196 #ifdef _LP64
1197 	if (model == DATAMODEL_ILP32) {
1198 		dev32_t dev;
1199 		/* convert internal 64 bit form to 32 bit version */
1200 		if (cmpldev(&dev, ainfo->ai_termid.at_port) == 0) {
1201 			crfree(cr);
1202 			return (EOVERFLOW);
1203 		}
1204 		STRUCT_FSET(apinfo, ap_termid.port, dev);
1205 	} else
1206 		STRUCT_FSET(apinfo, ap_termid.port, ainfo->ai_termid.at_port);
1207 #else
1208 	STRUCT_FSET(apinfo, ap_termid.port, ainfo->ai_termid.at_port);
1209 #endif
1210 	STRUCT_FSET(apinfo, ap_termid.machine, ainfo->ai_termid.at_addr[0]);
1211 	STRUCT_FSET(apinfo, ap_mask, ainfo->ai_mask);
1212 
1213 	crfree(cr);
1214 
1215 	if (copyout(STRUCT_BUF(apinfo), data, STRUCT_SIZE(apinfo)))
1216 		return (EFAULT);
1217 
1218 	return (0);
1219 }
1220 
1221 static int
1222 getpinfo_addr(caddr_t data, int len)
1223 {
1224 	STRUCT_DECL(auditpinfo_addr, apinfo);
1225 	proc_t *proc;
1226 	const auditinfo_addr_t	*ainfo;
1227 	model_t	model;
1228 	cred_t	*cr, *newcred;
1229 
1230 	model = get_udatamodel();
1231 	STRUCT_INIT(apinfo, model);
1232 
1233 	if (len < STRUCT_SIZE(apinfo))
1234 		return (EOVERFLOW);
1235 
1236 	if (copyin(data, STRUCT_BUF(apinfo), STRUCT_SIZE(apinfo)))
1237 		return (EFAULT);
1238 
1239 	newcred = cralloc();
1240 
1241 	mutex_enter(&pidlock);
1242 	if ((proc = prfind(STRUCT_FGET(apinfo, ap_pid))) == NULL) {
1243 		mutex_exit(&pidlock);
1244 		crfree(newcred);
1245 		return (ESRCH);
1246 	}
1247 	mutex_enter(&proc->p_lock);	/* so process doesn't go away */
1248 	mutex_exit(&pidlock);
1249 
1250 	audit_update_context(proc, newcred);	/* make sure it's up-to-date */
1251 
1252 	mutex_enter(&proc->p_crlock);
1253 	crhold(cr = proc->p_cred);
1254 	mutex_exit(&proc->p_crlock);
1255 	mutex_exit(&proc->p_lock);
1256 
1257 	ainfo = crgetauinfo(cr);
1258 	if (ainfo == NULL) {
1259 		crfree(cr);
1260 		return (EINVAL);
1261 	}
1262 
1263 	STRUCT_FSET(apinfo, ap_auid, ainfo->ai_auid);
1264 	STRUCT_FSET(apinfo, ap_asid, ainfo->ai_asid);
1265 #ifdef _LP64
1266 	if (model == DATAMODEL_ILP32) {
1267 		dev32_t dev;
1268 		/* convert internal 64 bit form to 32 bit version */
1269 		if (cmpldev(&dev, ainfo->ai_termid.at_port) == 0) {
1270 			crfree(cr);
1271 			return (EOVERFLOW);
1272 		}
1273 		STRUCT_FSET(apinfo, ap_termid.at_port, dev);
1274 	} else
1275 		STRUCT_FSET(apinfo, ap_termid.at_port,
1276 		    ainfo->ai_termid.at_port);
1277 #else
1278 	STRUCT_FSET(apinfo, ap_termid.at_port, ainfo->ai_termid.at_port);
1279 #endif
1280 	STRUCT_FSET(apinfo, ap_termid.at_type, ainfo->ai_termid.at_type);
1281 	STRUCT_FSET(apinfo, ap_termid.at_addr[0], ainfo->ai_termid.at_addr[0]);
1282 	STRUCT_FSET(apinfo, ap_termid.at_addr[1], ainfo->ai_termid.at_addr[1]);
1283 	STRUCT_FSET(apinfo, ap_termid.at_addr[2], ainfo->ai_termid.at_addr[2]);
1284 	STRUCT_FSET(apinfo, ap_termid.at_addr[3], ainfo->ai_termid.at_addr[3]);
1285 	STRUCT_FSET(apinfo, ap_mask, ainfo->ai_mask);
1286 
1287 	crfree(cr);
1288 
1289 	if (copyout(STRUCT_BUF(apinfo), data, STRUCT_SIZE(apinfo)))
1290 		return (EFAULT);
1291 
1292 	return (0);
1293 }
1294 
1295 static int
1296 setpmask(caddr_t data)
1297 {
1298 	STRUCT_DECL(auditpinfo, apinfo);
1299 	proc_t *proc;
1300 	cred_t	*newcred;
1301 	auditinfo_addr_t	*ainfo;
1302 	struct p_audit_data	*pad;
1303 
1304 	model_t	model;
1305 
1306 	model = get_udatamodel();
1307 	STRUCT_INIT(apinfo, model);
1308 
1309 	if (copyin(data, STRUCT_BUF(apinfo), STRUCT_SIZE(apinfo)))
1310 		return (EFAULT);
1311 
1312 	mutex_enter(&pidlock);
1313 	if ((proc = prfind(STRUCT_FGET(apinfo, ap_pid))) == NULL) {
1314 		mutex_exit(&pidlock);
1315 		return (ESRCH);
1316 	}
1317 	mutex_enter(&proc->p_lock);	/* so process doesn't go away */
1318 	mutex_exit(&pidlock);
1319 
1320 	newcred = cralloc();
1321 	if ((ainfo = crgetauinfo_modifiable(newcred)) == NULL) {
1322 		mutex_exit(&proc->p_lock);
1323 		crfree(newcred);
1324 		return (EINVAL);
1325 	}
1326 
1327 	mutex_enter(&proc->p_crlock);
1328 	crcopy_to(proc->p_cred, newcred);
1329 	proc->p_cred = newcred;
1330 
1331 	ainfo->ai_mask = STRUCT_FGET(apinfo, ap_mask);
1332 
1333 	/*
1334 	 * Unlock. No need to broadcast changes via set_proc_pre_sys(),
1335 	 * since t_pre_sys is ALWAYS on when audit is enabled... due to
1336 	 * syscall auditing.
1337 	 */
1338 	crfree(newcred);
1339 	mutex_exit(&proc->p_crlock);
1340 
1341 	/* Reset flag for any previous pending mask change; this supercedes */
1342 	pad = P2A(proc);
1343 	ASSERT(pad != NULL);
1344 	mutex_enter(&(pad->pad_lock));
1345 	pad->pad_flags &= ~PAD_SETMASK;
1346 	mutex_exit(&(pad->pad_lock));
1347 
1348 	mutex_exit(&proc->p_lock);
1349 
1350 	return (0);
1351 }
1352 
1353 /*
1354  * The out of control system call
1355  * This is audit kitchen sink aka auditadm, aka auditon
1356  */
1357 int
1358 auditctl(
1359 	int	cmd,
1360 	caddr_t data,
1361 	int	length)
1362 {
1363 	int result;
1364 
1365 	switch (cmd) {
1366 	case A_GETAMASK:
1367 	case A_GETCOND:
1368 	case A_GETCAR:
1369 	case A_GETCLASS:
1370 	case A_GETCWD:
1371 	case A_GETKAUDIT:
1372 	case A_GETKMASK:
1373 	case A_GETPINFO:
1374 	case A_GETPINFO_ADDR:
1375 	case A_GETPOLICY:
1376 	case A_GETQCTRL:
1377 	case A_GETSTAT:
1378 		if (secpolicy_audit_getattr(CRED(), B_FALSE) != 0)
1379 			return (EPERM);
1380 		break;
1381 	default:
1382 		if (secpolicy_audit_config(CRED()) != 0)
1383 			return (EPERM);
1384 		break;
1385 	}
1386 
1387 	switch (cmd) {
1388 	case A_GETPOLICY:
1389 		result = getpolicy(data);
1390 		break;
1391 	case A_SETPOLICY:
1392 		result = setpolicy(data);
1393 		break;
1394 	case A_GETAMASK:
1395 		result = getamask(data);
1396 		break;
1397 	case A_SETAMASK:
1398 		result = setamask(data);
1399 		break;
1400 	case A_GETKMASK:
1401 		result = getkmask(data);
1402 		break;
1403 	case A_SETKMASK:
1404 		result = setkmask(data);
1405 		break;
1406 	case A_GETKAUDIT:
1407 		result = getkaudit(data, length);
1408 		break;
1409 	case A_SETKAUDIT:
1410 		result = setkaudit(data, length);
1411 		break;
1412 	case A_GETQCTRL:
1413 		result = getqctrl(data);
1414 		break;
1415 	case A_SETQCTRL:
1416 		result = setqctrl(data);
1417 		break;
1418 	case A_GETCWD:
1419 		result = getcwd(data, length);
1420 		break;
1421 	case A_GETCAR:
1422 		result = getcar(data, length);
1423 		break;
1424 	case A_GETSTAT:
1425 		result = getstat(data);
1426 		break;
1427 	case A_SETSTAT:
1428 		result = setstat(data);
1429 		break;
1430 	case A_SETUMASK:
1431 		result = setumask(data);
1432 		break;
1433 	case A_SETSMASK:
1434 		result = setsmask(data);
1435 		break;
1436 	case A_GETCOND:
1437 		result = getcond(data);
1438 		break;
1439 	case A_SETCOND:
1440 		result = setcond(data);
1441 		break;
1442 	case A_GETCLASS:
1443 		result = getclass(data);
1444 		break;
1445 	case A_SETCLASS:
1446 		result = setclass(data);
1447 		break;
1448 	case A_GETPINFO:
1449 		result = getpinfo(data);
1450 		break;
1451 	case A_GETPINFO_ADDR:
1452 		result = getpinfo_addr(data, length);
1453 		break;
1454 	case A_SETPMASK:
1455 		result = setpmask(data);
1456 		break;
1457 	default:
1458 		result = EINVAL;
1459 		break;
1460 	}
1461 	return (result);
1462 }
1463