xref: /titanic_53/usr/src/uts/common/syscall/auditsys.c (revision 96093503d6c90cc5a0cd2ce8c88e1975be2d00b3)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5405e5d68Stz204579  * Common Development and Distribution License (the "License").
6405e5d68Stz204579  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22005d3febSMarek Pospisil  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <sys/systm.h>
277c478bd9Sstevel@tonic-gate #include <sys/errno.h>
287c478bd9Sstevel@tonic-gate #include <sys/policy.h>
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #include <c2/audit.h>
31005d3febSMarek Pospisil #include <c2/audit_kernel.h>
32005d3febSMarek Pospisil #include <c2/audit_record.h>
33005d3febSMarek Pospisil 
34005d3febSMarek Pospisil #define	CLEAR_VAL -1
35005d3febSMarek Pospisil 
36005d3febSMarek Pospisil extern kmutex_t pidlock;
37005d3febSMarek Pospisil 
38*96093503SMarek Pospisil uint32_t audit_policy; /* global audit policies in force */
39005d3febSMarek Pospisil 
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate /*ARGSUSED1*/
427c478bd9Sstevel@tonic-gate int
437c478bd9Sstevel@tonic-gate auditsys(struct auditcalls *uap, rval_t *rvp)
447c478bd9Sstevel@tonic-gate {
457c478bd9Sstevel@tonic-gate 	int err;
46005d3febSMarek Pospisil 	int result = 0;
477c478bd9Sstevel@tonic-gate 
48005d3febSMarek Pospisil 	if (audit_active == C2AUDIT_DISABLED)
49405e5d68Stz204579 		return (ENOTSUP);
50405e5d68Stz204579 
517c478bd9Sstevel@tonic-gate 	switch (uap->code) {
527c478bd9Sstevel@tonic-gate 	case BSM_GETAUID:
53005d3febSMarek Pospisil 		result = getauid((caddr_t)uap->a1);
54005d3febSMarek Pospisil 		break;
557c478bd9Sstevel@tonic-gate 	case BSM_SETAUID:
56005d3febSMarek Pospisil 		result = setauid((caddr_t)uap->a1);
57005d3febSMarek Pospisil 		break;
587c478bd9Sstevel@tonic-gate 	case BSM_GETAUDIT:
59005d3febSMarek Pospisil 		result = getaudit((caddr_t)uap->a1);
60005d3febSMarek Pospisil 		break;
61005d3febSMarek Pospisil 	case BSM_GETAUDIT_ADDR:
62005d3febSMarek Pospisil 		result = getaudit_addr((caddr_t)uap->a1, (int)uap->a2);
63005d3febSMarek Pospisil 		break;
647c478bd9Sstevel@tonic-gate 	case BSM_SETAUDIT:
65005d3febSMarek Pospisil 		result = setaudit((caddr_t)uap->a1);
66005d3febSMarek Pospisil 		break;
67005d3febSMarek Pospisil 	case BSM_SETAUDIT_ADDR:
68005d3febSMarek Pospisil 		result = setaudit_addr((caddr_t)uap->a1, (int)uap->a2);
69005d3febSMarek Pospisil 		break;
707c478bd9Sstevel@tonic-gate 	case BSM_AUDITCTL:
71005d3febSMarek Pospisil 		result = auditctl((int)uap->a1, (caddr_t)uap->a2, (int)uap->a3);
72005d3febSMarek Pospisil 		break;
73005d3febSMarek Pospisil 	case BSM_AUDIT:
74005d3febSMarek Pospisil 		if (audit_active == C2AUDIT_UNLOADED)
75005d3febSMarek Pospisil 			return (0);
76005d3febSMarek Pospisil 		result = audit((caddr_t)uap->a1, (int)uap->a2);
77005d3febSMarek Pospisil 		break;
78005d3febSMarek Pospisil 	case BSM_AUDITDOOR:
79005d3febSMarek Pospisil 		if (audit_active == C2AUDIT_LOADED) {
80005d3febSMarek Pospisil 			result = auditdoor((int)uap->a1);
81005d3febSMarek Pospisil 			break;
82005d3febSMarek Pospisil 		}
837c478bd9Sstevel@tonic-gate 	default:
84005d3febSMarek Pospisil 		if (audit_active == C2AUDIT_LOADED) {
85005d3febSMarek Pospisil 			result = EINVAL;
86005d3febSMarek Pospisil 			break;
87005d3febSMarek Pospisil 		}
887c478bd9Sstevel@tonic-gate 		/* Return a different error when not privileged */
897c478bd9Sstevel@tonic-gate 		err = secpolicy_audit_config(CRED());
907c478bd9Sstevel@tonic-gate 		if (err == 0)
917c478bd9Sstevel@tonic-gate 			return (EINVAL);
927c478bd9Sstevel@tonic-gate 		else
937c478bd9Sstevel@tonic-gate 			return (err);
947c478bd9Sstevel@tonic-gate 	}
95005d3febSMarek Pospisil 	rvp->r_vals = result;
96005d3febSMarek Pospisil 	return (result);
97005d3febSMarek Pospisil }
98005d3febSMarek Pospisil 
99005d3febSMarek Pospisil /*
100005d3febSMarek Pospisil  * Return the audit user ID for the current process.  Currently only
101005d3febSMarek Pospisil  * the privileged processes may see the audit id.  That may change.
102005d3febSMarek Pospisil  * If copyout is unsucessful return EFAULT.
103005d3febSMarek Pospisil  */
104005d3febSMarek Pospisil int
105005d3febSMarek Pospisil getauid(caddr_t auid_p)
106005d3febSMarek Pospisil {
107005d3febSMarek Pospisil 	const auditinfo_addr_t	*ainfo;
108005d3febSMarek Pospisil 
109005d3febSMarek Pospisil 	if (secpolicy_audit_getattr(CRED()) != 0)
110005d3febSMarek Pospisil 		return (EPERM);
111005d3febSMarek Pospisil 
112005d3febSMarek Pospisil 	ainfo = crgetauinfo(CRED());
113005d3febSMarek Pospisil 	if (ainfo == NULL)
114005d3febSMarek Pospisil 		return (EINVAL);
115005d3febSMarek Pospisil 
116005d3febSMarek Pospisil 	if (copyout(&ainfo->ai_auid, auid_p, sizeof (au_id_t)))
117005d3febSMarek Pospisil 		return (EFAULT);
118005d3febSMarek Pospisil 
119005d3febSMarek Pospisil 	return (0);
120005d3febSMarek Pospisil }
121005d3febSMarek Pospisil 
122005d3febSMarek Pospisil /*
123005d3febSMarek Pospisil  * Set the audit userid, for a process.  This can only be changed by
124005d3febSMarek Pospisil  * privileged processes.  The audit userid is inherited across forks & execs.
125005d3febSMarek Pospisil  * Passed in is a pointer to the au_id_t; if copyin unsuccessful return EFAULT.
126005d3febSMarek Pospisil  */
127005d3febSMarek Pospisil int
128005d3febSMarek Pospisil setauid(caddr_t auid_p)
129005d3febSMarek Pospisil {
130005d3febSMarek Pospisil 	proc_t *p;
131005d3febSMarek Pospisil 	au_id_t	auid;
132005d3febSMarek Pospisil 	cred_t *newcred;
133005d3febSMarek Pospisil 	auditinfo_addr_t *auinfo;
134005d3febSMarek Pospisil 
135005d3febSMarek Pospisil 	if (secpolicy_audit_config(CRED()) != 0)
136005d3febSMarek Pospisil 		return (EPERM);
137005d3febSMarek Pospisil 
138005d3febSMarek Pospisil 	if (copyin(auid_p, &auid, sizeof (au_id_t))) {
139005d3febSMarek Pospisil 		return (EFAULT);
140005d3febSMarek Pospisil 	}
141005d3febSMarek Pospisil 
142005d3febSMarek Pospisil 	newcred = cralloc();
143005d3febSMarek Pospisil 	if ((auinfo = crgetauinfo_modifiable(newcred)) == NULL) {
144005d3febSMarek Pospisil 		crfree(newcred);
145005d3febSMarek Pospisil 		return (EINVAL);
146005d3febSMarek Pospisil 	}
147005d3febSMarek Pospisil 
148005d3febSMarek Pospisil 	/* grab p_crlock and switch to new cred */
149005d3febSMarek Pospisil 	p = curproc;
150005d3febSMarek Pospisil 	mutex_enter(&p->p_crlock);
151005d3febSMarek Pospisil 	crcopy_to(p->p_cred, newcred);
152005d3febSMarek Pospisil 	p->p_cred = newcred;
153005d3febSMarek Pospisil 
154005d3febSMarek Pospisil 	auinfo->ai_auid = auid;			/* update the auid */
155005d3febSMarek Pospisil 
156005d3febSMarek Pospisil 	/* unlock and broadcast the cred changes */
157005d3febSMarek Pospisil 	mutex_exit(&p->p_crlock);
158005d3febSMarek Pospisil 	crset(p, newcred);
159005d3febSMarek Pospisil 
160005d3febSMarek Pospisil 	return (0);
161005d3febSMarek Pospisil }
162005d3febSMarek Pospisil 
163005d3febSMarek Pospisil /*
164005d3febSMarek Pospisil  * Get the audit state information from the current process.
165005d3febSMarek Pospisil  * Return EFAULT if copyout fails.
166005d3febSMarek Pospisil  */
167005d3febSMarek Pospisil int
168005d3febSMarek Pospisil getaudit(caddr_t info_p)
169005d3febSMarek Pospisil {
170005d3febSMarek Pospisil 	STRUCT_DECL(auditinfo, info);
171005d3febSMarek Pospisil 	const auditinfo_addr_t	*ainfo;
172005d3febSMarek Pospisil 	model_t	model;
173005d3febSMarek Pospisil 
174005d3febSMarek Pospisil 	if (secpolicy_audit_getattr(CRED()) != 0)
175005d3febSMarek Pospisil 		return (EPERM);
176005d3febSMarek Pospisil 
177005d3febSMarek Pospisil 	model = get_udatamodel();
178005d3febSMarek Pospisil 	STRUCT_INIT(info, model);
179005d3febSMarek Pospisil 
180005d3febSMarek Pospisil 	ainfo = crgetauinfo(CRED());
181005d3febSMarek Pospisil 	if (ainfo == NULL)
182005d3febSMarek Pospisil 		return (EINVAL);
183005d3febSMarek Pospisil 
184005d3febSMarek Pospisil 	/* trying to read a process with an IPv6 address? */
185005d3febSMarek Pospisil 	if (ainfo->ai_termid.at_type == AU_IPv6)
186005d3febSMarek Pospisil 		return (EOVERFLOW);
187005d3febSMarek Pospisil 
188005d3febSMarek Pospisil 	STRUCT_FSET(info, ai_auid, ainfo->ai_auid);
189005d3febSMarek Pospisil 	STRUCT_FSET(info, ai_mask, ainfo->ai_mask);
190005d3febSMarek Pospisil #ifdef _LP64
191005d3febSMarek Pospisil 	if (model == DATAMODEL_ILP32) {
192005d3febSMarek Pospisil 		dev32_t dev;
193005d3febSMarek Pospisil 		/* convert internal 64 bit form to 32 bit version */
194005d3febSMarek Pospisil 		if (cmpldev(&dev, ainfo->ai_termid.at_port) == 0) {
195005d3febSMarek Pospisil 			return (EOVERFLOW);
196005d3febSMarek Pospisil 		}
197005d3febSMarek Pospisil 		STRUCT_FSET(info, ai_termid.port, dev);
198005d3febSMarek Pospisil 	} else
199005d3febSMarek Pospisil 		STRUCT_FSET(info, ai_termid.port, ainfo->ai_termid.at_port);
200005d3febSMarek Pospisil #else
201005d3febSMarek Pospisil 	STRUCT_FSET(info, ai_termid.port, ainfo->ai_termid.at_port);
202005d3febSMarek Pospisil #endif
203005d3febSMarek Pospisil 	STRUCT_FSET(info, ai_termid.machine, ainfo->ai_termid.at_addr[0]);
204005d3febSMarek Pospisil 	STRUCT_FSET(info, ai_asid, ainfo->ai_asid);
205005d3febSMarek Pospisil 
206005d3febSMarek Pospisil 	if (copyout(STRUCT_BUF(info), info_p, STRUCT_SIZE(info)))
207005d3febSMarek Pospisil 		return (EFAULT);
208005d3febSMarek Pospisil 
209005d3febSMarek Pospisil 	return (0);
210005d3febSMarek Pospisil }
211005d3febSMarek Pospisil 
212005d3febSMarek Pospisil /*
213005d3febSMarek Pospisil  * Get the audit state information from the current process.
214005d3febSMarek Pospisil  * Return EFAULT if copyout fails.
215005d3febSMarek Pospisil  */
216005d3febSMarek Pospisil int
217005d3febSMarek Pospisil getaudit_addr(caddr_t info_p, int len)
218005d3febSMarek Pospisil {
219005d3febSMarek Pospisil 	STRUCT_DECL(auditinfo_addr, info);
220005d3febSMarek Pospisil 	const auditinfo_addr_t	*ainfo;
221005d3febSMarek Pospisil 	model_t	model;
222005d3febSMarek Pospisil 
223005d3febSMarek Pospisil 	if (secpolicy_audit_getattr(CRED()) != 0)
224005d3febSMarek Pospisil 		return (EPERM);
225005d3febSMarek Pospisil 
226005d3febSMarek Pospisil 	model = get_udatamodel();
227005d3febSMarek Pospisil 	STRUCT_INIT(info, model);
228005d3febSMarek Pospisil 
229005d3febSMarek Pospisil 	if (len < STRUCT_SIZE(info))
230005d3febSMarek Pospisil 		return (EOVERFLOW);
231005d3febSMarek Pospisil 
232005d3febSMarek Pospisil 	ainfo = crgetauinfo(CRED());
233005d3febSMarek Pospisil 
234005d3febSMarek Pospisil 	if (ainfo == NULL)
235005d3febSMarek Pospisil 		return (EINVAL);
236005d3febSMarek Pospisil 
237005d3febSMarek Pospisil 	STRUCT_FSET(info, ai_auid, ainfo->ai_auid);
238005d3febSMarek Pospisil 	STRUCT_FSET(info, ai_mask, ainfo->ai_mask);
239005d3febSMarek Pospisil #ifdef _LP64
240005d3febSMarek Pospisil 	if (model == DATAMODEL_ILP32) {
241005d3febSMarek Pospisil 		dev32_t dev;
242005d3febSMarek Pospisil 		/* convert internal 64 bit form to 32 bit version */
243005d3febSMarek Pospisil 		if (cmpldev(&dev, ainfo->ai_termid.at_port) == 0) {
244005d3febSMarek Pospisil 			return (EOVERFLOW);
245005d3febSMarek Pospisil 		}
246005d3febSMarek Pospisil 		STRUCT_FSET(info, ai_termid.at_port, dev);
247005d3febSMarek Pospisil 	} else
248005d3febSMarek Pospisil 		STRUCT_FSET(info, ai_termid.at_port, ainfo->ai_termid.at_port);
249005d3febSMarek Pospisil #else
250005d3febSMarek Pospisil 	STRUCT_FSET(info, ai_termid.at_port, ainfo->ai_termid.at_port);
251005d3febSMarek Pospisil #endif
252005d3febSMarek Pospisil 	STRUCT_FSET(info, ai_termid.at_type, ainfo->ai_termid.at_type);
253005d3febSMarek Pospisil 	STRUCT_FSET(info, ai_termid.at_addr[0], ainfo->ai_termid.at_addr[0]);
254005d3febSMarek Pospisil 	STRUCT_FSET(info, ai_termid.at_addr[1], ainfo->ai_termid.at_addr[1]);
255005d3febSMarek Pospisil 	STRUCT_FSET(info, ai_termid.at_addr[2], ainfo->ai_termid.at_addr[2]);
256005d3febSMarek Pospisil 	STRUCT_FSET(info, ai_termid.at_addr[3], ainfo->ai_termid.at_addr[3]);
257005d3febSMarek Pospisil 	STRUCT_FSET(info, ai_asid, ainfo->ai_asid);
258005d3febSMarek Pospisil 
259005d3febSMarek Pospisil 	if (copyout(STRUCT_BUF(info), info_p, STRUCT_SIZE(info)))
260005d3febSMarek Pospisil 		return (EFAULT);
261005d3febSMarek Pospisil 
262005d3febSMarek Pospisil 	return (0);
263005d3febSMarek Pospisil }
264005d3febSMarek Pospisil 
265005d3febSMarek Pospisil /*
266005d3febSMarek Pospisil  * Set the audit state information for the current process.
267005d3febSMarek Pospisil  * Return EFAULT if copyout fails.
268005d3febSMarek Pospisil  */
269005d3febSMarek Pospisil int
270005d3febSMarek Pospisil setaudit(caddr_t info_p)
271005d3febSMarek Pospisil {
272005d3febSMarek Pospisil 	STRUCT_DECL(auditinfo, info);
273005d3febSMarek Pospisil 	proc_t *p;
274005d3febSMarek Pospisil 	cred_t	*newcred;
275005d3febSMarek Pospisil 	model_t	model;
276005d3febSMarek Pospisil 	auditinfo_addr_t *ainfo;
277005d3febSMarek Pospisil 
278005d3febSMarek Pospisil 	if (secpolicy_audit_config(CRED()) != 0)
279005d3febSMarek Pospisil 		return (EPERM);
280005d3febSMarek Pospisil 
281005d3febSMarek Pospisil 	model = get_udatamodel();
282005d3febSMarek Pospisil 	STRUCT_INIT(info, model);
283005d3febSMarek Pospisil 
284005d3febSMarek Pospisil 	if (copyin(info_p, STRUCT_BUF(info), STRUCT_SIZE(info)))
285005d3febSMarek Pospisil 		return (EFAULT);
286005d3febSMarek Pospisil 
287005d3febSMarek Pospisil 	newcred = cralloc();
288005d3febSMarek Pospisil 	if ((ainfo = crgetauinfo_modifiable(newcred)) == NULL) {
289005d3febSMarek Pospisil 		crfree(newcred);
290005d3febSMarek Pospisil 		return (EINVAL);
291005d3febSMarek Pospisil 	}
292005d3febSMarek Pospisil 
293005d3febSMarek Pospisil 	/* grab p_crlock and switch to new cred */
294005d3febSMarek Pospisil 	p = curproc;
295005d3febSMarek Pospisil 	mutex_enter(&p->p_crlock);
296005d3febSMarek Pospisil 	crcopy_to(p->p_cred, newcred);
297005d3febSMarek Pospisil 	p->p_cred = newcred;
298005d3febSMarek Pospisil 
299005d3febSMarek Pospisil 	/* Set audit mask, id, termid and session id as specified */
300005d3febSMarek Pospisil 	ainfo->ai_auid = STRUCT_FGET(info, ai_auid);
301005d3febSMarek Pospisil #ifdef _LP64
302005d3febSMarek Pospisil 	/* only convert to 64 bit if coming from a 32 bit binary */
303005d3febSMarek Pospisil 	if (model == DATAMODEL_ILP32)
304005d3febSMarek Pospisil 		ainfo->ai_termid.at_port =
305005d3febSMarek Pospisil 		    DEVEXPL(STRUCT_FGET(info, ai_termid.port));
306005d3febSMarek Pospisil 	else
307005d3febSMarek Pospisil 		ainfo->ai_termid.at_port = STRUCT_FGET(info, ai_termid.port);
308005d3febSMarek Pospisil #else
309005d3febSMarek Pospisil 	ainfo->ai_termid.at_port = STRUCT_FGET(info, ai_termid.port);
310005d3febSMarek Pospisil #endif
311005d3febSMarek Pospisil 	ainfo->ai_termid.at_type = AU_IPv4;
312005d3febSMarek Pospisil 	ainfo->ai_termid.at_addr[0] = STRUCT_FGET(info, ai_termid.machine);
313005d3febSMarek Pospisil 	ainfo->ai_asid = STRUCT_FGET(info, ai_asid);
314005d3febSMarek Pospisil 	ainfo->ai_mask = STRUCT_FGET(info, ai_mask);
315005d3febSMarek Pospisil 
316005d3febSMarek Pospisil 	/* unlock and broadcast the cred changes */
317005d3febSMarek Pospisil 	mutex_exit(&p->p_crlock);
318005d3febSMarek Pospisil 	crset(p, newcred);
319005d3febSMarek Pospisil 
320005d3febSMarek Pospisil 	return (0);
321005d3febSMarek Pospisil }
322005d3febSMarek Pospisil 
323005d3febSMarek Pospisil /*
324005d3febSMarek Pospisil  * Set the audit state information for the current process.
325005d3febSMarek Pospisil  * Return EFAULT if copyin fails.
326005d3febSMarek Pospisil  */
327005d3febSMarek Pospisil int
328005d3febSMarek Pospisil setaudit_addr(caddr_t info_p, int len)
329005d3febSMarek Pospisil {
330005d3febSMarek Pospisil 	STRUCT_DECL(auditinfo_addr, info);
331005d3febSMarek Pospisil 	proc_t *p;
332005d3febSMarek Pospisil 	cred_t	*newcred;
333005d3febSMarek Pospisil 	model_t	model;
334005d3febSMarek Pospisil 	int i;
335005d3febSMarek Pospisil 	int type;
336005d3febSMarek Pospisil 	auditinfo_addr_t *ainfo;
337005d3febSMarek Pospisil 
338005d3febSMarek Pospisil 	if (secpolicy_audit_config(CRED()) != 0)
339005d3febSMarek Pospisil 		return (EPERM);
340005d3febSMarek Pospisil 
341005d3febSMarek Pospisil 	model = get_udatamodel();
342005d3febSMarek Pospisil 	STRUCT_INIT(info, model);
343005d3febSMarek Pospisil 
344005d3febSMarek Pospisil 	if (len < STRUCT_SIZE(info))
345005d3febSMarek Pospisil 		return (EOVERFLOW);
346005d3febSMarek Pospisil 
347005d3febSMarek Pospisil 	if (copyin(info_p, STRUCT_BUF(info), STRUCT_SIZE(info)))
348005d3febSMarek Pospisil 		return (EFAULT);
349005d3febSMarek Pospisil 
350005d3febSMarek Pospisil 	type = STRUCT_FGET(info, ai_termid.at_type);
351005d3febSMarek Pospisil 	if ((type != AU_IPv4) && (type != AU_IPv6))
352005d3febSMarek Pospisil 		return (EINVAL);
353005d3febSMarek Pospisil 
354005d3febSMarek Pospisil 	newcred = cralloc();
355005d3febSMarek Pospisil 	if ((ainfo = crgetauinfo_modifiable(newcred)) == NULL) {
356005d3febSMarek Pospisil 		crfree(newcred);
357005d3febSMarek Pospisil 		return (EINVAL);
358005d3febSMarek Pospisil 	}
359005d3febSMarek Pospisil 
360005d3febSMarek Pospisil 	/* grab p_crlock and switch to new cred */
361005d3febSMarek Pospisil 	p = curproc;
362005d3febSMarek Pospisil 	mutex_enter(&p->p_crlock);
363005d3febSMarek Pospisil 	crcopy_to(p->p_cred, newcred);
364005d3febSMarek Pospisil 	p->p_cred = newcred;
365005d3febSMarek Pospisil 
366005d3febSMarek Pospisil 	/* Set audit mask, id, termid and session id as specified */
367005d3febSMarek Pospisil 	ainfo->ai_auid = STRUCT_FGET(info, ai_auid);
368005d3febSMarek Pospisil 	ainfo->ai_mask = STRUCT_FGET(info, ai_mask);
369005d3febSMarek Pospisil #ifdef _LP64
370005d3febSMarek Pospisil 	/* only convert to 64 bit if coming from a 32 bit binary */
371005d3febSMarek Pospisil 	if (model == DATAMODEL_ILP32)
372005d3febSMarek Pospisil 		ainfo->ai_termid.at_port =
373005d3febSMarek Pospisil 		    DEVEXPL(STRUCT_FGET(info, ai_termid.at_port));
374005d3febSMarek Pospisil 	else
375005d3febSMarek Pospisil 		ainfo->ai_termid.at_port = STRUCT_FGET(info, ai_termid.at_port);
376005d3febSMarek Pospisil #else
377005d3febSMarek Pospisil 	ainfo->ai_termid.at_port = STRUCT_FGET(info, ai_termid.at_port);
378005d3febSMarek Pospisil #endif
379005d3febSMarek Pospisil 	ainfo->ai_termid.at_type = type;
380005d3febSMarek Pospisil 	bzero(&ainfo->ai_termid.at_addr[0], sizeof (ainfo->ai_termid.at_addr));
381005d3febSMarek Pospisil 	for (i = 0; i < (type/sizeof (int)); i++)
382005d3febSMarek Pospisil 		ainfo->ai_termid.at_addr[i] =
383005d3febSMarek Pospisil 		    STRUCT_FGET(info, ai_termid.at_addr[i]);
384005d3febSMarek Pospisil 
385005d3febSMarek Pospisil 	if (ainfo->ai_termid.at_type == AU_IPv6 &&
386005d3febSMarek Pospisil 	    IN6_IS_ADDR_V4MAPPED(((in6_addr_t *)ainfo->ai_termid.at_addr))) {
387005d3febSMarek Pospisil 		ainfo->ai_termid.at_type = AU_IPv4;
388005d3febSMarek Pospisil 		ainfo->ai_termid.at_addr[0] = ainfo->ai_termid.at_addr[3];
389005d3febSMarek Pospisil 		ainfo->ai_termid.at_addr[1] = 0;
390005d3febSMarek Pospisil 		ainfo->ai_termid.at_addr[2] = 0;
391005d3febSMarek Pospisil 		ainfo->ai_termid.at_addr[3] = 0;
392005d3febSMarek Pospisil 	}
393005d3febSMarek Pospisil 
394005d3febSMarek Pospisil 	ainfo->ai_asid = STRUCT_FGET(info, ai_asid);
395005d3febSMarek Pospisil 
396005d3febSMarek Pospisil 	/* unlock and broadcast the cred changes */
397005d3febSMarek Pospisil 	mutex_exit(&p->p_crlock);
398005d3febSMarek Pospisil 	crset(p, newcred);
399005d3febSMarek Pospisil 
400005d3febSMarek Pospisil 	return (0);
401005d3febSMarek Pospisil }
402005d3febSMarek Pospisil 
403005d3febSMarek Pospisil /*
404005d3febSMarek Pospisil  * Get the global policy flag
405005d3febSMarek Pospisil  */
406005d3febSMarek Pospisil static int
407005d3febSMarek Pospisil getpolicy(caddr_t data)
408005d3febSMarek Pospisil {
409*96093503SMarek Pospisil 	uint32_t	policy;
410005d3febSMarek Pospisil 	au_kcontext_t	*kctx = GET_KCTX_PZ;
411005d3febSMarek Pospisil 
412005d3febSMarek Pospisil 	policy = audit_policy | kctx->auk_policy;
413005d3febSMarek Pospisil 
414*96093503SMarek Pospisil 	if (copyout(&policy, data, sizeof (policy)))
415005d3febSMarek Pospisil 		return (EFAULT);
416005d3febSMarek Pospisil 	return (0);
417005d3febSMarek Pospisil }
418005d3febSMarek Pospisil 
419005d3febSMarek Pospisil /*
420005d3febSMarek Pospisil  * Set the global and local policy flags
421005d3febSMarek Pospisil  *
422005d3febSMarek Pospisil  * The global flags only make sense from the global zone;
423005d3febSMarek Pospisil  * the local flags depend on the AUDIT_PERZONE policy:
424005d3febSMarek Pospisil  * if the perzone policy is set, then policy is set separately
425005d3febSMarek Pospisil  * per zone, else held only in the global zone.
426005d3febSMarek Pospisil  *
427005d3febSMarek Pospisil  * The initial value of a local zone's policy flag is determined
428005d3febSMarek Pospisil  * by the value of the global zone's flags at the time the
429005d3febSMarek Pospisil  * local zone is created.
430005d3febSMarek Pospisil  *
431005d3febSMarek Pospisil  * While auditconfig(1M) allows setting and unsetting policies one bit
432005d3febSMarek Pospisil  * at a time, the mask passed in from auditconfig() is created by a
433005d3febSMarek Pospisil  * syscall to getpolicy and then modified based on the auditconfig()
434005d3febSMarek Pospisil  * cmd line, so the input policy value is used to replace the existing
435005d3febSMarek Pospisil  * policy.
436005d3febSMarek Pospisil  */
437005d3febSMarek Pospisil static int
438005d3febSMarek Pospisil setpolicy(caddr_t data)
439005d3febSMarek Pospisil {
440*96093503SMarek Pospisil 	uint32_t	policy;
441005d3febSMarek Pospisil 	au_kcontext_t	*kctx;
442005d3febSMarek Pospisil 
443*96093503SMarek Pospisil 	if (copyin(data, &policy, sizeof (policy)))
444005d3febSMarek Pospisil 		return (EFAULT);
445005d3febSMarek Pospisil 
446005d3febSMarek Pospisil 	kctx = GET_KCTX_NGZ;
447005d3febSMarek Pospisil 
448005d3febSMarek Pospisil 	if (INGLOBALZONE(curproc)) {
449005d3febSMarek Pospisil 		if (policy & ~(AUDIT_GLOBAL | AUDIT_LOCAL))
450005d3febSMarek Pospisil 			return (EINVAL);
451005d3febSMarek Pospisil 
452005d3febSMarek Pospisil 		audit_policy = policy & AUDIT_GLOBAL;
453005d3febSMarek Pospisil 	} else {
454005d3febSMarek Pospisil 		if (!(audit_policy & AUDIT_PERZONE))
455005d3febSMarek Pospisil 			return (EINVAL);
456005d3febSMarek Pospisil 
457005d3febSMarek Pospisil 		if (policy & ~AUDIT_LOCAL)	/* global bits are a no-no */
458005d3febSMarek Pospisil 			return (EINVAL);
459005d3febSMarek Pospisil 	}
460005d3febSMarek Pospisil 	kctx->auk_policy = policy & AUDIT_LOCAL;
461005d3febSMarek Pospisil 
462005d3febSMarek Pospisil 	/*
463005d3febSMarek Pospisil 	 * auk_current_vp is NULL before auditd starts (or during early
464005d3febSMarek Pospisil 	 * auditd starup) or if auditd is halted; in either case,
465005d3febSMarek Pospisil 	 * notification of a policy change is not needed, since auditd
466005d3febSMarek Pospisil 	 * reads policy as it comes up.  The error return from au_doormsg()
467005d3febSMarek Pospisil 	 * is ignored to avoid a race condition -- for example if auditd
468005d3febSMarek Pospisil 	 * segv's, the audit state may be "auditing" but the door may
469005d3febSMarek Pospisil 	 * be closed.  Returning an error if the door is open makes it
470005d3febSMarek Pospisil 	 * impossible for Greenline to restart auditd.
471005d3febSMarek Pospisil 	 */
472005d3febSMarek Pospisil 	if (kctx->auk_current_vp != NULL)
473005d3febSMarek Pospisil 		(void) au_doormsg(kctx, AU_DBUF_POLICY, &policy);
474005d3febSMarek Pospisil 
475005d3febSMarek Pospisil 	/*
476005d3febSMarek Pospisil 	 * Wake up anyone who might have blocked on full audit
477005d3febSMarek Pospisil 	 * partitions. audit daemons need to set AUDIT_FULL when no
478005d3febSMarek Pospisil 	 * space so we can tell if we should start dropping records.
479005d3febSMarek Pospisil 	 */
480005d3febSMarek Pospisil 	mutex_enter(&(kctx->auk_queue.lock));
481005d3febSMarek Pospisil 
482005d3febSMarek Pospisil 	if ((policy & (AUDIT_CNT | AUDIT_SCNT) &&
483005d3febSMarek Pospisil 	    (kctx->auk_queue.cnt >= kctx->auk_queue.hiwater)))
484005d3febSMarek Pospisil 		cv_broadcast(&(kctx->auk_queue.write_cv));
485005d3febSMarek Pospisil 
486005d3febSMarek Pospisil 	mutex_exit(&(kctx->auk_queue.lock));
487005d3febSMarek Pospisil 
488005d3febSMarek Pospisil 	return (0);
489005d3febSMarek Pospisil }
490005d3febSMarek Pospisil 
491005d3febSMarek Pospisil static int
492005d3febSMarek Pospisil getkmask(caddr_t data)
493005d3febSMarek Pospisil {
494005d3febSMarek Pospisil 	au_kcontext_t	*kctx;
495005d3febSMarek Pospisil 
496005d3febSMarek Pospisil 	kctx = GET_KCTX_PZ;
497005d3febSMarek Pospisil 
498005d3febSMarek Pospisil 	if (copyout(&kctx->auk_info.ai_mask, data, sizeof (au_mask_t)))
499005d3febSMarek Pospisil 		return (EFAULT);
500005d3febSMarek Pospisil 	return (0);
501005d3febSMarek Pospisil }
502005d3febSMarek Pospisil 
503005d3febSMarek Pospisil static int
504005d3febSMarek Pospisil setkmask(caddr_t data)
505005d3febSMarek Pospisil {
506005d3febSMarek Pospisil 	au_mask_t	mask;
507005d3febSMarek Pospisil 	au_kcontext_t	*kctx;
508005d3febSMarek Pospisil 
509005d3febSMarek Pospisil 	if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc))
510005d3febSMarek Pospisil 		return (EINVAL);
511005d3febSMarek Pospisil 
512005d3febSMarek Pospisil 	kctx = GET_KCTX_NGZ;
513005d3febSMarek Pospisil 
514005d3febSMarek Pospisil 	if (copyin(data, &mask, sizeof (au_mask_t)))
515005d3febSMarek Pospisil 		return (EFAULT);
516005d3febSMarek Pospisil 
517005d3febSMarek Pospisil 	kctx->auk_info.ai_mask = mask;
518005d3febSMarek Pospisil 	return (0);
519005d3febSMarek Pospisil }
520005d3febSMarek Pospisil 
521005d3febSMarek Pospisil static int
522005d3febSMarek Pospisil getkaudit(caddr_t info_p, int len)
523005d3febSMarek Pospisil {
524005d3febSMarek Pospisil 	STRUCT_DECL(auditinfo_addr, info);
525005d3febSMarek Pospisil 	model_t model;
526005d3febSMarek Pospisil 	au_kcontext_t	*kctx = GET_KCTX_PZ;
527005d3febSMarek Pospisil 
528005d3febSMarek Pospisil 	model = get_udatamodel();
529005d3febSMarek Pospisil 	STRUCT_INIT(info, model);
530005d3febSMarek Pospisil 
531005d3febSMarek Pospisil 	if (len < STRUCT_SIZE(info))
532005d3febSMarek Pospisil 		return (EOVERFLOW);
533005d3febSMarek Pospisil 
534005d3febSMarek Pospisil 	STRUCT_FSET(info, ai_auid, kctx->auk_info.ai_auid);
535005d3febSMarek Pospisil 	STRUCT_FSET(info, ai_mask, kctx->auk_info.ai_mask);
536005d3febSMarek Pospisil #ifdef _LP64
537005d3febSMarek Pospisil 	if (model == DATAMODEL_ILP32) {
538005d3febSMarek Pospisil 		dev32_t dev;
539005d3febSMarek Pospisil 		/* convert internal 64 bit form to 32 bit version */
540005d3febSMarek Pospisil 		if (cmpldev(&dev, kctx->auk_info.ai_termid.at_port) == 0) {
541005d3febSMarek Pospisil 			return (EOVERFLOW);
542005d3febSMarek Pospisil 		}
543005d3febSMarek Pospisil 		STRUCT_FSET(info, ai_termid.at_port, dev);
544005d3febSMarek Pospisil 	} else {
545005d3febSMarek Pospisil 		STRUCT_FSET(info, ai_termid.at_port,
546005d3febSMarek Pospisil 		    kctx->auk_info.ai_termid.at_port);
547005d3febSMarek Pospisil 	}
548005d3febSMarek Pospisil #else
549005d3febSMarek Pospisil 	STRUCT_FSET(info, ai_termid.at_port,
550005d3febSMarek Pospisil 	    kctx->auk_info.ai_termid.at_port);
551005d3febSMarek Pospisil #endif
552005d3febSMarek Pospisil 	STRUCT_FSET(info, ai_termid.at_type,
553005d3febSMarek Pospisil 	    kctx->auk_info.ai_termid.at_type);
554005d3febSMarek Pospisil 	STRUCT_FSET(info, ai_termid.at_addr[0],
555005d3febSMarek Pospisil 	    kctx->auk_info.ai_termid.at_addr[0]);
556005d3febSMarek Pospisil 	STRUCT_FSET(info, ai_termid.at_addr[1],
557005d3febSMarek Pospisil 	    kctx->auk_info.ai_termid.at_addr[1]);
558005d3febSMarek Pospisil 	STRUCT_FSET(info, ai_termid.at_addr[2],
559005d3febSMarek Pospisil 	    kctx->auk_info.ai_termid.at_addr[2]);
560005d3febSMarek Pospisil 	STRUCT_FSET(info, ai_termid.at_addr[3],
561005d3febSMarek Pospisil 	    kctx->auk_info.ai_termid.at_addr[3]);
562005d3febSMarek Pospisil 	STRUCT_FSET(info, ai_asid, kctx->auk_info.ai_asid);
563005d3febSMarek Pospisil 
564005d3febSMarek Pospisil 	if (copyout(STRUCT_BUF(info), info_p, STRUCT_SIZE(info)))
565005d3febSMarek Pospisil 		return (EFAULT);
566005d3febSMarek Pospisil 
567005d3febSMarek Pospisil 	return (0);
568005d3febSMarek Pospisil }
569005d3febSMarek Pospisil 
570005d3febSMarek Pospisil /*
571005d3febSMarek Pospisil  * the host address for AUDIT_PERZONE == 0 is that of the global
572005d3febSMarek Pospisil  * zone and for local zones it is of the current zone.
573005d3febSMarek Pospisil  */
574005d3febSMarek Pospisil static int
575005d3febSMarek Pospisil setkaudit(caddr_t info_p, int len)
576005d3febSMarek Pospisil {
577005d3febSMarek Pospisil 	STRUCT_DECL(auditinfo_addr, info);
578005d3febSMarek Pospisil 	model_t model;
579005d3febSMarek Pospisil 	au_kcontext_t	*kctx;
580005d3febSMarek Pospisil 
581005d3febSMarek Pospisil 	if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc))
582005d3febSMarek Pospisil 		return (EINVAL);
583005d3febSMarek Pospisil 
584005d3febSMarek Pospisil 	kctx = GET_KCTX_NGZ;
585005d3febSMarek Pospisil 
586005d3febSMarek Pospisil 	model = get_udatamodel();
587005d3febSMarek Pospisil 	STRUCT_INIT(info, model);
588005d3febSMarek Pospisil 
589005d3febSMarek Pospisil 	if (len < STRUCT_SIZE(info))
590005d3febSMarek Pospisil 		return (EOVERFLOW);
591005d3febSMarek Pospisil 
592005d3febSMarek Pospisil 	if (copyin(info_p, STRUCT_BUF(info), STRUCT_SIZE(info)))
593005d3febSMarek Pospisil 		return (EFAULT);
594005d3febSMarek Pospisil 
595005d3febSMarek Pospisil 	if ((STRUCT_FGET(info, ai_termid.at_type) != AU_IPv4) &&
596005d3febSMarek Pospisil 	    (STRUCT_FGET(info, ai_termid.at_type) != AU_IPv6))
597005d3febSMarek Pospisil 		return (EINVAL);
598005d3febSMarek Pospisil 
599005d3febSMarek Pospisil 	/* Set audit mask, termid and session id as specified */
600005d3febSMarek Pospisil 	kctx->auk_info.ai_auid = STRUCT_FGET(info, ai_auid);
601005d3febSMarek Pospisil 	kctx->auk_info.ai_mask = STRUCT_FGET(info, ai_mask);
602005d3febSMarek Pospisil #ifdef _LP64
603005d3febSMarek Pospisil 	/* only convert to 64 bit if coming from a 32 bit binary */
604005d3febSMarek Pospisil 	if (model == DATAMODEL_ILP32)
605005d3febSMarek Pospisil 		kctx->auk_info.ai_termid.at_port =
606005d3febSMarek Pospisil 		    DEVEXPL(STRUCT_FGET(info, ai_termid.at_port));
607005d3febSMarek Pospisil 	else
608005d3febSMarek Pospisil 		kctx->auk_info.ai_termid.at_port =
609005d3febSMarek Pospisil 		    STRUCT_FGET(info, ai_termid.at_port);
610005d3febSMarek Pospisil #else
611005d3febSMarek Pospisil 	kctx->auk_info.ai_termid.at_port = STRUCT_FGET(info, ai_termid.at_port);
612005d3febSMarek Pospisil #endif
613005d3febSMarek Pospisil 	kctx->auk_info.ai_termid.at_type = STRUCT_FGET(info, ai_termid.at_type);
614005d3febSMarek Pospisil 	bzero(&kctx->auk_info.ai_termid.at_addr[0],
615005d3febSMarek Pospisil 	    sizeof (kctx->auk_info.ai_termid.at_addr));
616005d3febSMarek Pospisil 	kctx->auk_info.ai_termid.at_addr[0] =
617005d3febSMarek Pospisil 	    STRUCT_FGET(info, ai_termid.at_addr[0]);
618005d3febSMarek Pospisil 	kctx->auk_info.ai_termid.at_addr[1] =
619005d3febSMarek Pospisil 	    STRUCT_FGET(info, ai_termid.at_addr[1]);
620005d3febSMarek Pospisil 	kctx->auk_info.ai_termid.at_addr[2] =
621005d3febSMarek Pospisil 	    STRUCT_FGET(info, ai_termid.at_addr[2]);
622005d3febSMarek Pospisil 	kctx->auk_info.ai_termid.at_addr[3] =
623005d3febSMarek Pospisil 	    STRUCT_FGET(info, ai_termid.at_addr[3]);
624005d3febSMarek Pospisil 	kctx->auk_info.ai_asid = STRUCT_FGET(info, ai_asid);
625005d3febSMarek Pospisil 
626005d3febSMarek Pospisil 	if (kctx->auk_info.ai_termid.at_type == AU_IPv6 &&
627005d3febSMarek Pospisil 	    IN6_IS_ADDR_V4MAPPED(
628005d3febSMarek Pospisil 	    ((in6_addr_t *)kctx->auk_info.ai_termid.at_addr))) {
629005d3febSMarek Pospisil 		kctx->auk_info.ai_termid.at_type = AU_IPv4;
630005d3febSMarek Pospisil 		kctx->auk_info.ai_termid.at_addr[0] =
631005d3febSMarek Pospisil 		    kctx->auk_info.ai_termid.at_addr[3];
632005d3febSMarek Pospisil 		kctx->auk_info.ai_termid.at_addr[1] = 0;
633005d3febSMarek Pospisil 		kctx->auk_info.ai_termid.at_addr[2] = 0;
634005d3febSMarek Pospisil 		kctx->auk_info.ai_termid.at_addr[3] = 0;
635005d3febSMarek Pospisil 	}
636005d3febSMarek Pospisil 	if (kctx->auk_info.ai_termid.at_type == AU_IPv6)
637005d3febSMarek Pospisil 		kctx->auk_hostaddr_valid = IN6_IS_ADDR_UNSPECIFIED(
638005d3febSMarek Pospisil 		    (in6_addr_t *)kctx->auk_info.ai_termid.at_addr) ? 0 : 1;
639005d3febSMarek Pospisil 	else
640005d3febSMarek Pospisil 		kctx->auk_hostaddr_valid =
641005d3febSMarek Pospisil 		    (kctx->auk_info.ai_termid.at_addr[0] ==
642005d3febSMarek Pospisil 		    htonl(INADDR_ANY)) ? 0 : 1;
643005d3febSMarek Pospisil 
644005d3febSMarek Pospisil 	return (0);
645005d3febSMarek Pospisil }
646005d3febSMarek Pospisil 
647005d3febSMarek Pospisil static int
648005d3febSMarek Pospisil getqctrl(caddr_t data)
649005d3febSMarek Pospisil {
650005d3febSMarek Pospisil 	au_kcontext_t	*kctx = GET_KCTX_PZ;
651005d3febSMarek Pospisil 	STRUCT_DECL(au_qctrl, qctrl);
652005d3febSMarek Pospisil 	STRUCT_INIT(qctrl, get_udatamodel());
653005d3febSMarek Pospisil 
654005d3febSMarek Pospisil 	mutex_enter(&(kctx->auk_queue.lock));
655005d3febSMarek Pospisil 	STRUCT_FSET(qctrl, aq_hiwater, kctx->auk_queue.hiwater);
656005d3febSMarek Pospisil 	STRUCT_FSET(qctrl, aq_lowater, kctx->auk_queue.lowater);
657005d3febSMarek Pospisil 	STRUCT_FSET(qctrl, aq_bufsz, kctx->auk_queue.bufsz);
658005d3febSMarek Pospisil 	STRUCT_FSET(qctrl, aq_delay, kctx->auk_queue.delay);
659005d3febSMarek Pospisil 	mutex_exit(&(kctx->auk_queue.lock));
660005d3febSMarek Pospisil 
661005d3febSMarek Pospisil 	if (copyout(STRUCT_BUF(qctrl), data, STRUCT_SIZE(qctrl)))
662005d3febSMarek Pospisil 		return (EFAULT);
663005d3febSMarek Pospisil 
664005d3febSMarek Pospisil 	return (0);
665005d3febSMarek Pospisil }
666005d3febSMarek Pospisil 
667005d3febSMarek Pospisil static int
668005d3febSMarek Pospisil setqctrl(caddr_t data)
669005d3febSMarek Pospisil {
670005d3febSMarek Pospisil 	au_kcontext_t	*kctx;
671005d3febSMarek Pospisil 	struct au_qctrl qctrl_tmp;
672005d3febSMarek Pospisil 	STRUCT_DECL(au_qctrl, qctrl);
673005d3febSMarek Pospisil 	STRUCT_INIT(qctrl, get_udatamodel());
674005d3febSMarek Pospisil 
675005d3febSMarek Pospisil 	if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc))
676005d3febSMarek Pospisil 		return (EINVAL);
677005d3febSMarek Pospisil 	kctx = GET_KCTX_NGZ;
678005d3febSMarek Pospisil 
679005d3febSMarek Pospisil 	if (copyin(data, STRUCT_BUF(qctrl), STRUCT_SIZE(qctrl)))
680005d3febSMarek Pospisil 		return (EFAULT);
681005d3febSMarek Pospisil 
682005d3febSMarek Pospisil 	qctrl_tmp.aq_hiwater = (size_t)STRUCT_FGET(qctrl, aq_hiwater);
683005d3febSMarek Pospisil 	qctrl_tmp.aq_lowater = (size_t)STRUCT_FGET(qctrl, aq_lowater);
684005d3febSMarek Pospisil 	qctrl_tmp.aq_bufsz = (size_t)STRUCT_FGET(qctrl, aq_bufsz);
685005d3febSMarek Pospisil 	qctrl_tmp.aq_delay = (clock_t)STRUCT_FGET(qctrl, aq_delay);
686005d3febSMarek Pospisil 
687005d3febSMarek Pospisil 	/* enforce sane values */
688005d3febSMarek Pospisil 
689005d3febSMarek Pospisil 	if (qctrl_tmp.aq_hiwater <= qctrl_tmp.aq_lowater)
690005d3febSMarek Pospisil 		return (EINVAL);
691005d3febSMarek Pospisil 
692005d3febSMarek Pospisil 	if (qctrl_tmp.aq_hiwater < AQ_LOWATER)
693005d3febSMarek Pospisil 		return (EINVAL);
694005d3febSMarek Pospisil 
695005d3febSMarek Pospisil 	if (qctrl_tmp.aq_hiwater > AQ_MAXHIGH)
696005d3febSMarek Pospisil 		return (EINVAL);
697005d3febSMarek Pospisil 
698005d3febSMarek Pospisil 	if (qctrl_tmp.aq_bufsz < AQ_BUFSZ)
699005d3febSMarek Pospisil 		return (EINVAL);
700005d3febSMarek Pospisil 
701005d3febSMarek Pospisil 	if (qctrl_tmp.aq_bufsz > AQ_MAXBUFSZ)
702005d3febSMarek Pospisil 		return (EINVAL);
703005d3febSMarek Pospisil 
704005d3febSMarek Pospisil 	if (qctrl_tmp.aq_delay == 0)
705005d3febSMarek Pospisil 		return (EINVAL);
706005d3febSMarek Pospisil 
707005d3febSMarek Pospisil 	if (qctrl_tmp.aq_delay > AQ_MAXDELAY)
708005d3febSMarek Pospisil 		return (EINVAL);
709005d3febSMarek Pospisil 
710005d3febSMarek Pospisil 	/* update everything at once so things are consistant */
711005d3febSMarek Pospisil 	mutex_enter(&(kctx->auk_queue.lock));
712005d3febSMarek Pospisil 	kctx->auk_queue.hiwater = qctrl_tmp.aq_hiwater;
713005d3febSMarek Pospisil 	kctx->auk_queue.lowater = qctrl_tmp.aq_lowater;
714005d3febSMarek Pospisil 	kctx->auk_queue.bufsz = qctrl_tmp.aq_bufsz;
715005d3febSMarek Pospisil 	kctx->auk_queue.delay = qctrl_tmp.aq_delay;
716005d3febSMarek Pospisil 
717005d3febSMarek Pospisil 	if (kctx->auk_queue.rd_block &&
718005d3febSMarek Pospisil 	    kctx->auk_queue.cnt > kctx->auk_queue.lowater)
719005d3febSMarek Pospisil 		cv_broadcast(&(kctx->auk_queue.read_cv));
720005d3febSMarek Pospisil 
721005d3febSMarek Pospisil 	if (kctx->auk_queue.wt_block &&
722005d3febSMarek Pospisil 	    kctx->auk_queue.cnt < kctx->auk_queue.hiwater)
723005d3febSMarek Pospisil 		cv_broadcast(&(kctx->auk_queue.write_cv));
724005d3febSMarek Pospisil 
725005d3febSMarek Pospisil 	mutex_exit(&(kctx->auk_queue.lock));
726005d3febSMarek Pospisil 
727005d3febSMarek Pospisil 	return (0);
728005d3febSMarek Pospisil }
729005d3febSMarek Pospisil 
730005d3febSMarek Pospisil static int
731005d3febSMarek Pospisil getcwd(caddr_t data, int length)
732005d3febSMarek Pospisil {
733005d3febSMarek Pospisil 	struct p_audit_data	*pad;
734005d3febSMarek Pospisil 	struct audit_path	*app;
735005d3febSMarek Pospisil 	int	pathlen;
736005d3febSMarek Pospisil 
737005d3febSMarek Pospisil 	pad = P2A(curproc);
738005d3febSMarek Pospisil 	ASSERT(pad != NULL);
739005d3febSMarek Pospisil 
740005d3febSMarek Pospisil 	mutex_enter(&(pad->pad_lock));
741005d3febSMarek Pospisil 	app = pad->pad_cwd;
742005d3febSMarek Pospisil 	au_pathhold(app);
743005d3febSMarek Pospisil 	mutex_exit(&(pad->pad_lock));
744005d3febSMarek Pospisil 
745005d3febSMarek Pospisil 	pathlen = app->audp_sect[1] - app->audp_sect[0];
746005d3febSMarek Pospisil 	if (pathlen > length) {
747005d3febSMarek Pospisil 		au_pathrele(app);
748005d3febSMarek Pospisil 		return (E2BIG);
749005d3febSMarek Pospisil 	}
750005d3febSMarek Pospisil 
751005d3febSMarek Pospisil 	if (copyout(app->audp_sect[0], data, pathlen)) {
752005d3febSMarek Pospisil 		au_pathrele(app);
753005d3febSMarek Pospisil 		return (EFAULT);
754005d3febSMarek Pospisil 	}
755005d3febSMarek Pospisil 
756005d3febSMarek Pospisil 	au_pathrele(app);
757005d3febSMarek Pospisil 	return (0);
758005d3febSMarek Pospisil }
759005d3febSMarek Pospisil 
760005d3febSMarek Pospisil static int
761005d3febSMarek Pospisil getcar(caddr_t data, int length)
762005d3febSMarek Pospisil {
763005d3febSMarek Pospisil 	struct p_audit_data	*pad;
764005d3febSMarek Pospisil 	struct audit_path	*app;
765005d3febSMarek Pospisil 	int	pathlen;
766005d3febSMarek Pospisil 
767005d3febSMarek Pospisil 	pad = P2A(curproc);
768005d3febSMarek Pospisil 	ASSERT(pad != NULL);
769005d3febSMarek Pospisil 
770005d3febSMarek Pospisil 	mutex_enter(&(pad->pad_lock));
771005d3febSMarek Pospisil 	app = pad->pad_root;
772005d3febSMarek Pospisil 	au_pathhold(app);
773005d3febSMarek Pospisil 	mutex_exit(&(pad->pad_lock));
774005d3febSMarek Pospisil 
775005d3febSMarek Pospisil 	pathlen = app->audp_sect[1] - app->audp_sect[0];
776005d3febSMarek Pospisil 	if (pathlen > length) {
777005d3febSMarek Pospisil 		au_pathrele(app);
778005d3febSMarek Pospisil 		return (E2BIG);
779005d3febSMarek Pospisil 	}
780005d3febSMarek Pospisil 
781005d3febSMarek Pospisil 	if (copyout(app->audp_sect[0], data, pathlen)) {
782005d3febSMarek Pospisil 		au_pathrele(app);
783005d3febSMarek Pospisil 		return (EFAULT);
784005d3febSMarek Pospisil 	}
785005d3febSMarek Pospisil 
786005d3febSMarek Pospisil 	au_pathrele(app);
787005d3febSMarek Pospisil 	return (0);
788005d3febSMarek Pospisil }
789005d3febSMarek Pospisil 
790005d3febSMarek Pospisil static int
791005d3febSMarek Pospisil getstat(caddr_t data)
792005d3febSMarek Pospisil {
793005d3febSMarek Pospisil 	au_kcontext_t	*kctx = GET_KCTX_PZ;
794005d3febSMarek Pospisil 
795005d3febSMarek Pospisil 	membar_consumer();
796005d3febSMarek Pospisil 
797005d3febSMarek Pospisil 	if (copyout((caddr_t)&(kctx->auk_statistics), data, sizeof (au_stat_t)))
798005d3febSMarek Pospisil 		return (EFAULT);
799005d3febSMarek Pospisil 	return (0);
800005d3febSMarek Pospisil }
801005d3febSMarek Pospisil 
802005d3febSMarek Pospisil static int
803005d3febSMarek Pospisil setstat(caddr_t data)
804005d3febSMarek Pospisil {
805005d3febSMarek Pospisil 	au_kcontext_t *kctx = GET_KCTX_PZ;
806005d3febSMarek Pospisil 	au_stat_t au_stat;
807005d3febSMarek Pospisil 
808005d3febSMarek Pospisil 	if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc))
809005d3febSMarek Pospisil 		return (EINVAL);
810005d3febSMarek Pospisil 
811005d3febSMarek Pospisil 	if (copyin(data, &au_stat, sizeof (au_stat_t)))
812005d3febSMarek Pospisil 		return (EFAULT);
813005d3febSMarek Pospisil 
814005d3febSMarek Pospisil 	if (au_stat.as_generated == CLEAR_VAL)
815005d3febSMarek Pospisil 		kctx->auk_statistics.as_generated = 0;
816005d3febSMarek Pospisil 	if (au_stat.as_nonattrib == CLEAR_VAL)
817005d3febSMarek Pospisil 		kctx->auk_statistics.as_nonattrib = 0;
818005d3febSMarek Pospisil 	if (au_stat.as_kernel == CLEAR_VAL)
819005d3febSMarek Pospisil 		kctx->auk_statistics.as_kernel = 0;
820005d3febSMarek Pospisil 	if (au_stat.as_audit == CLEAR_VAL)
821005d3febSMarek Pospisil 		kctx->auk_statistics.as_audit = 0;
822005d3febSMarek Pospisil 	if (au_stat.as_auditctl == CLEAR_VAL)
823005d3febSMarek Pospisil 		kctx->auk_statistics.as_auditctl = 0;
824005d3febSMarek Pospisil 	if (au_stat.as_enqueue == CLEAR_VAL)
825005d3febSMarek Pospisil 		kctx->auk_statistics.as_enqueue = 0;
826005d3febSMarek Pospisil 	if (au_stat.as_written == CLEAR_VAL)
827005d3febSMarek Pospisil 		kctx->auk_statistics.as_written = 0;
828005d3febSMarek Pospisil 	if (au_stat.as_wblocked == CLEAR_VAL)
829005d3febSMarek Pospisil 		kctx->auk_statistics.as_wblocked = 0;
830005d3febSMarek Pospisil 	if (au_stat.as_rblocked == CLEAR_VAL)
831005d3febSMarek Pospisil 		kctx->auk_statistics.as_rblocked = 0;
832005d3febSMarek Pospisil 	if (au_stat.as_dropped == CLEAR_VAL)
833005d3febSMarek Pospisil 		kctx->auk_statistics.as_dropped = 0;
834005d3febSMarek Pospisil 	if (au_stat.as_totalsize == CLEAR_VAL)
835005d3febSMarek Pospisil 		kctx->auk_statistics.as_totalsize = 0;
836005d3febSMarek Pospisil 
837005d3febSMarek Pospisil 	membar_producer();
838005d3febSMarek Pospisil 
839005d3febSMarek Pospisil 	return (0);
840005d3febSMarek Pospisil 
841005d3febSMarek Pospisil }
842005d3febSMarek Pospisil 
843005d3febSMarek Pospisil static int
844005d3febSMarek Pospisil setumask(caddr_t data)
845005d3febSMarek Pospisil {
846005d3febSMarek Pospisil 	STRUCT_DECL(auditinfo, user_info);
847005d3febSMarek Pospisil 	struct proc *p;
848005d3febSMarek Pospisil 	const auditinfo_addr_t	*ainfo;
849005d3febSMarek Pospisil 	model_t	model;
850005d3febSMarek Pospisil 
851005d3febSMarek Pospisil 	/* setumask not applicable in non-global zones without perzone policy */
852005d3febSMarek Pospisil 	if (!(audit_policy & AUDIT_PERZONE) && (!INGLOBALZONE(curproc)))
853005d3febSMarek Pospisil 		return (EINVAL);
854005d3febSMarek Pospisil 
855005d3febSMarek Pospisil 	model = get_udatamodel();
856005d3febSMarek Pospisil 	STRUCT_INIT(user_info, model);
857005d3febSMarek Pospisil 
858005d3febSMarek Pospisil 	if (copyin(data, STRUCT_BUF(user_info), STRUCT_SIZE(user_info)))
859005d3febSMarek Pospisil 		return (EFAULT);
860005d3febSMarek Pospisil 
861005d3febSMarek Pospisil 	mutex_enter(&pidlock);	/* lock the process queue against updates */
862005d3febSMarek Pospisil 	for (p = practive; p != NULL; p = p->p_next) {
863005d3febSMarek Pospisil 		cred_t	*cr;
864005d3febSMarek Pospisil 
865005d3febSMarek Pospisil 		/* if in non-global zone only modify processes in same zone */
866005d3febSMarek Pospisil 		if (!HASZONEACCESS(curproc, p->p_zone->zone_id))
867005d3febSMarek Pospisil 			continue;
868005d3febSMarek Pospisil 
869005d3febSMarek Pospisil 		mutex_enter(&p->p_lock);	/* so process doesn't go away */
870005d3febSMarek Pospisil 
871005d3febSMarek Pospisil 		/* skip system processes and ones being created or going away */
872005d3febSMarek Pospisil 		if (p->p_stat == SIDL || p->p_stat == SZOMB ||
873005d3febSMarek Pospisil 		    (p->p_flag & (SSYS | SEXITING | SEXITLWPS))) {
874005d3febSMarek Pospisil 			mutex_exit(&p->p_lock);
875005d3febSMarek Pospisil 			continue;
876005d3febSMarek Pospisil 		}
877005d3febSMarek Pospisil 
878005d3febSMarek Pospisil 		mutex_enter(&p->p_crlock);
879005d3febSMarek Pospisil 		crhold(cr = p->p_cred);
880005d3febSMarek Pospisil 		mutex_exit(&p->p_crlock);
881005d3febSMarek Pospisil 		ainfo = crgetauinfo(cr);
882005d3febSMarek Pospisil 		if (ainfo == NULL) {
883005d3febSMarek Pospisil 			mutex_exit(&p->p_lock);
884005d3febSMarek Pospisil 			crfree(cr);
885005d3febSMarek Pospisil 			continue;
886005d3febSMarek Pospisil 		}
887005d3febSMarek Pospisil 
888005d3febSMarek Pospisil 		if (ainfo->ai_auid == STRUCT_FGET(user_info, ai_auid)) {
889005d3febSMarek Pospisil 			au_mask_t	mask;
890005d3febSMarek Pospisil 			int		err;
891005d3febSMarek Pospisil 
892005d3febSMarek Pospisil 			/*
893005d3febSMarek Pospisil 			 * Here's a process which matches the specified auid.
894005d3febSMarek Pospisil 			 * If its mask doesn't already match the new mask,
895005d3febSMarek Pospisil 			 * save the new mask in the pad, to be picked up
896005d3febSMarek Pospisil 			 * next syscall.
897005d3febSMarek Pospisil 			 */
898005d3febSMarek Pospisil 			mask = STRUCT_FGET(user_info, ai_mask);
899005d3febSMarek Pospisil 			err = bcmp(&mask, &ainfo->ai_mask, sizeof (au_mask_t));
900005d3febSMarek Pospisil 			crfree(cr);
901005d3febSMarek Pospisil 			if (err != 0) {
902005d3febSMarek Pospisil 				struct p_audit_data *pad = P2A(p);
903005d3febSMarek Pospisil 				ASSERT(pad != NULL);
904005d3febSMarek Pospisil 
905005d3febSMarek Pospisil 				mutex_enter(&(pad->pad_lock));
906005d3febSMarek Pospisil 				pad->pad_flags |= PAD_SETMASK;
907005d3febSMarek Pospisil 				pad->pad_newmask = mask;
908005d3febSMarek Pospisil 				mutex_exit(&(pad->pad_lock));
909005d3febSMarek Pospisil 
910005d3febSMarek Pospisil 				/*
911005d3febSMarek Pospisil 				 * No need to call set_proc_pre_sys(), since
912005d3febSMarek Pospisil 				 * t_pre_sys is ALWAYS on when audit is
913005d3febSMarek Pospisil 				 * enabled...due to syscall auditing.
914005d3febSMarek Pospisil 				 */
915005d3febSMarek Pospisil 			}
916005d3febSMarek Pospisil 		} else {
917005d3febSMarek Pospisil 			crfree(cr);
918005d3febSMarek Pospisil 		}
919005d3febSMarek Pospisil 		mutex_exit(&p->p_lock);
920005d3febSMarek Pospisil 	}
921005d3febSMarek Pospisil 	mutex_exit(&pidlock);
922005d3febSMarek Pospisil 
923005d3febSMarek Pospisil 	return (0);
924005d3febSMarek Pospisil }
925005d3febSMarek Pospisil 
926005d3febSMarek Pospisil static int
927005d3febSMarek Pospisil setsmask(caddr_t data)
928005d3febSMarek Pospisil {
929005d3febSMarek Pospisil 	STRUCT_DECL(auditinfo, user_info);
930005d3febSMarek Pospisil 	struct proc *p;
931005d3febSMarek Pospisil 	const auditinfo_addr_t	*ainfo;
932005d3febSMarek Pospisil 	model_t	model;
933005d3febSMarek Pospisil 
934005d3febSMarek Pospisil 	/* setsmask not applicable in non-global zones without perzone policy */
935005d3febSMarek Pospisil 	if (!(audit_policy & AUDIT_PERZONE) && (!INGLOBALZONE(curproc)))
936005d3febSMarek Pospisil 		return (EINVAL);
937005d3febSMarek Pospisil 
938005d3febSMarek Pospisil 	model = get_udatamodel();
939005d3febSMarek Pospisil 	STRUCT_INIT(user_info, model);
940005d3febSMarek Pospisil 
941005d3febSMarek Pospisil 	if (copyin(data, STRUCT_BUF(user_info), STRUCT_SIZE(user_info)))
942005d3febSMarek Pospisil 		return (EFAULT);
943005d3febSMarek Pospisil 
944005d3febSMarek Pospisil 	mutex_enter(&pidlock);	/* lock the process queue against updates */
945005d3febSMarek Pospisil 	for (p = practive; p != NULL; p = p->p_next) {
946005d3febSMarek Pospisil 		cred_t	*cr;
947005d3febSMarek Pospisil 
948005d3febSMarek Pospisil 		/* if in non-global zone only modify processes in same zone */
949005d3febSMarek Pospisil 		if (!HASZONEACCESS(curproc, p->p_zone->zone_id))
950005d3febSMarek Pospisil 			continue;
951005d3febSMarek Pospisil 
952005d3febSMarek Pospisil 		mutex_enter(&p->p_lock);	/* so process doesn't go away */
953005d3febSMarek Pospisil 
954005d3febSMarek Pospisil 		/* skip system processes and ones being created or going away */
955005d3febSMarek Pospisil 		if (p->p_stat == SIDL || p->p_stat == SZOMB ||
956005d3febSMarek Pospisil 		    (p->p_flag & (SSYS | SEXITING | SEXITLWPS))) {
957005d3febSMarek Pospisil 			mutex_exit(&p->p_lock);
958005d3febSMarek Pospisil 			continue;
959005d3febSMarek Pospisil 		}
960005d3febSMarek Pospisil 
961005d3febSMarek Pospisil 		mutex_enter(&p->p_crlock);
962005d3febSMarek Pospisil 		crhold(cr = p->p_cred);
963005d3febSMarek Pospisil 		mutex_exit(&p->p_crlock);
964005d3febSMarek Pospisil 		ainfo = crgetauinfo(cr);
965005d3febSMarek Pospisil 		if (ainfo == NULL) {
966005d3febSMarek Pospisil 			mutex_exit(&p->p_lock);
967005d3febSMarek Pospisil 			crfree(cr);
968005d3febSMarek Pospisil 			continue;
969005d3febSMarek Pospisil 		}
970005d3febSMarek Pospisil 
971005d3febSMarek Pospisil 		if (ainfo->ai_asid == STRUCT_FGET(user_info, ai_asid)) {
972005d3febSMarek Pospisil 			au_mask_t	mask;
973005d3febSMarek Pospisil 			int		err;
974005d3febSMarek Pospisil 
975005d3febSMarek Pospisil 			/*
976005d3febSMarek Pospisil 			 * Here's a process which matches the specified asid.
977005d3febSMarek Pospisil 			 * If its mask doesn't already match the new mask,
978005d3febSMarek Pospisil 			 * save the new mask in the pad, to be picked up
979005d3febSMarek Pospisil 			 * next syscall.
980005d3febSMarek Pospisil 			 */
981005d3febSMarek Pospisil 			mask = STRUCT_FGET(user_info, ai_mask);
982005d3febSMarek Pospisil 			err = bcmp(&mask, &ainfo->ai_mask, sizeof (au_mask_t));
983005d3febSMarek Pospisil 			crfree(cr);
984005d3febSMarek Pospisil 			if (err != 0) {
985005d3febSMarek Pospisil 				struct p_audit_data *pad = P2A(p);
986005d3febSMarek Pospisil 				ASSERT(pad != NULL);
987005d3febSMarek Pospisil 
988005d3febSMarek Pospisil 				mutex_enter(&(pad->pad_lock));
989005d3febSMarek Pospisil 				pad->pad_flags |= PAD_SETMASK;
990005d3febSMarek Pospisil 				pad->pad_newmask = mask;
991005d3febSMarek Pospisil 				mutex_exit(&(pad->pad_lock));
992005d3febSMarek Pospisil 
993005d3febSMarek Pospisil 				/*
994005d3febSMarek Pospisil 				 * No need to call set_proc_pre_sys(), since
995005d3febSMarek Pospisil 				 * t_pre_sys is ALWAYS on when audit is
996005d3febSMarek Pospisil 				 * enabled...due to syscall auditing.
997005d3febSMarek Pospisil 				 */
998005d3febSMarek Pospisil 			}
999005d3febSMarek Pospisil 		} else {
1000005d3febSMarek Pospisil 			crfree(cr);
1001005d3febSMarek Pospisil 		}
1002005d3febSMarek Pospisil 		mutex_exit(&p->p_lock);
1003005d3febSMarek Pospisil 	}
1004005d3febSMarek Pospisil 	mutex_exit(&pidlock);
1005005d3febSMarek Pospisil 
1006005d3febSMarek Pospisil 	return (0);
1007005d3febSMarek Pospisil }
1008005d3febSMarek Pospisil 
1009005d3febSMarek Pospisil /*
1010005d3febSMarek Pospisil  * Get the current audit state of the system
1011005d3febSMarek Pospisil  */
1012005d3febSMarek Pospisil static int
1013005d3febSMarek Pospisil getcond(caddr_t data)
1014005d3febSMarek Pospisil {
1015005d3febSMarek Pospisil 	au_kcontext_t *kctx = GET_KCTX_PZ;
1016005d3febSMarek Pospisil 
1017005d3febSMarek Pospisil 	if (copyout(&(kctx->auk_auditstate), data, sizeof (int)))
1018005d3febSMarek Pospisil 		return (EFAULT);
1019005d3febSMarek Pospisil 
1020005d3febSMarek Pospisil 	return (0);
1021005d3febSMarek Pospisil }
1022005d3febSMarek Pospisil 
1023005d3febSMarek Pospisil /*
1024005d3febSMarek Pospisil  * Set the current audit state of the system to on (AUC_AUDITING) or
1025005d3febSMarek Pospisil  * off (AUC_NOAUDIT).
1026005d3febSMarek Pospisil  */
1027005d3febSMarek Pospisil /* ARGSUSED */
1028005d3febSMarek Pospisil static int
1029005d3febSMarek Pospisil setcond(caddr_t data)
1030005d3febSMarek Pospisil {
1031005d3febSMarek Pospisil 	int auditstate;
1032005d3febSMarek Pospisil 	au_kcontext_t *kctx;
1033005d3febSMarek Pospisil 
1034005d3febSMarek Pospisil 	if (!(audit_policy & AUDIT_PERZONE) && (!INGLOBALZONE(curproc)))
1035005d3febSMarek Pospisil 		return (EINVAL);
1036005d3febSMarek Pospisil 
1037005d3febSMarek Pospisil 	kctx = GET_KCTX_NGZ;
1038005d3febSMarek Pospisil 
1039005d3febSMarek Pospisil 	if (copyin(data, &auditstate, sizeof (int)))
1040005d3febSMarek Pospisil 		return (EFAULT);
1041005d3febSMarek Pospisil 
1042005d3febSMarek Pospisil 	switch (auditstate) {
1043005d3febSMarek Pospisil 	case AUC_AUDITING:		/* Turn auditing on */
1044005d3febSMarek Pospisil 		if (audit_active == C2AUDIT_UNLOADED)
1045005d3febSMarek Pospisil 			audit_init_module();
1046005d3febSMarek Pospisil 		kctx->auk_auditstate = AUC_AUDITING;
1047005d3febSMarek Pospisil 		if (!(audit_policy & AUDIT_PERZONE) && INGLOBALZONE(curproc))
1048005d3febSMarek Pospisil 			set_all_zone_usr_proc_sys(ALL_ZONES);
1049005d3febSMarek Pospisil 		else
1050005d3febSMarek Pospisil 			set_all_zone_usr_proc_sys(curproc->p_zone->zone_id);
1051005d3febSMarek Pospisil 		break;
1052005d3febSMarek Pospisil 
1053005d3febSMarek Pospisil 	case AUC_NOAUDIT:		/* Turn auditing off */
1054005d3febSMarek Pospisil 		if (kctx->auk_auditstate == AUC_NOAUDIT)
1055005d3febSMarek Pospisil 			break;
1056005d3febSMarek Pospisil 		kctx->auk_auditstate = AUC_NOAUDIT;
1057005d3febSMarek Pospisil 
1058005d3febSMarek Pospisil 		/* clear out the audit queue */
1059005d3febSMarek Pospisil 
1060005d3febSMarek Pospisil 		mutex_enter(&(kctx->auk_queue.lock));
1061005d3febSMarek Pospisil 		if (kctx->auk_queue.wt_block)
1062005d3febSMarek Pospisil 			cv_broadcast(&(kctx->auk_queue.write_cv));
1063005d3febSMarek Pospisil 
1064005d3febSMarek Pospisil 		/* unblock au_output_thread */
1065005d3febSMarek Pospisil 		cv_broadcast(&(kctx->auk_queue.read_cv));
1066005d3febSMarek Pospisil 
1067005d3febSMarek Pospisil 		mutex_exit(&(kctx->auk_queue.lock));
1068005d3febSMarek Pospisil 		break;
1069005d3febSMarek Pospisil 
1070005d3febSMarek Pospisil 	default:
1071005d3febSMarek Pospisil 		return (EINVAL);
1072005d3febSMarek Pospisil 	}
1073005d3febSMarek Pospisil 
1074005d3febSMarek Pospisil 	return (0);
1075005d3febSMarek Pospisil }
1076005d3febSMarek Pospisil 
1077005d3febSMarek Pospisil static int
1078005d3febSMarek Pospisil getclass(caddr_t data)
1079005d3febSMarek Pospisil {
1080005d3febSMarek Pospisil 	au_evclass_map_t event;
1081005d3febSMarek Pospisil 	au_kcontext_t	*kctx = GET_KCTX_PZ;
1082005d3febSMarek Pospisil 
1083005d3febSMarek Pospisil 	if (copyin(data, &event, sizeof (au_evclass_map_t)))
1084005d3febSMarek Pospisil 		return (EFAULT);
1085005d3febSMarek Pospisil 
1086005d3febSMarek Pospisil 	if (event.ec_number > MAX_KEVENTS)
1087005d3febSMarek Pospisil 		return (EINVAL);
1088005d3febSMarek Pospisil 
1089005d3febSMarek Pospisil 	event.ec_class = kctx->auk_ets[event.ec_number];
1090005d3febSMarek Pospisil 
1091005d3febSMarek Pospisil 	if (copyout(&event, data, sizeof (au_evclass_map_t)))
1092005d3febSMarek Pospisil 		return (EFAULT);
1093005d3febSMarek Pospisil 
1094005d3febSMarek Pospisil 	return (0);
1095005d3febSMarek Pospisil }
1096005d3febSMarek Pospisil 
1097005d3febSMarek Pospisil static int
1098005d3febSMarek Pospisil setclass(caddr_t data)
1099005d3febSMarek Pospisil {
1100005d3febSMarek Pospisil 	au_evclass_map_t event;
1101005d3febSMarek Pospisil 	au_kcontext_t	*kctx;
1102005d3febSMarek Pospisil 
1103005d3febSMarek Pospisil 	if (!(audit_policy & AUDIT_PERZONE) && !INGLOBALZONE(curproc))
1104005d3febSMarek Pospisil 		return (EINVAL);
1105005d3febSMarek Pospisil 
1106005d3febSMarek Pospisil 	kctx = GET_KCTX_NGZ;
1107005d3febSMarek Pospisil 
1108005d3febSMarek Pospisil 	if (copyin(data, &event, sizeof (au_evclass_map_t)))
1109005d3febSMarek Pospisil 		return (EFAULT);
1110005d3febSMarek Pospisil 
1111005d3febSMarek Pospisil 	if (event.ec_number > MAX_KEVENTS)
1112005d3febSMarek Pospisil 		return (EINVAL);
1113005d3febSMarek Pospisil 
1114005d3febSMarek Pospisil 	kctx->auk_ets[event.ec_number] = event.ec_class;
1115005d3febSMarek Pospisil 
1116005d3febSMarek Pospisil 	return (0);
1117005d3febSMarek Pospisil }
1118005d3febSMarek Pospisil 
1119005d3febSMarek Pospisil static int
1120005d3febSMarek Pospisil getpinfo(caddr_t data)
1121005d3febSMarek Pospisil {
1122005d3febSMarek Pospisil 	STRUCT_DECL(auditpinfo, apinfo);
1123005d3febSMarek Pospisil 	proc_t *proc;
1124005d3febSMarek Pospisil 	const auditinfo_addr_t	*ainfo;
1125005d3febSMarek Pospisil 	model_t	model;
1126005d3febSMarek Pospisil 	cred_t	*cr, *newcred;
1127005d3febSMarek Pospisil 
1128005d3febSMarek Pospisil 	model = get_udatamodel();
1129005d3febSMarek Pospisil 	STRUCT_INIT(apinfo, model);
1130005d3febSMarek Pospisil 
1131005d3febSMarek Pospisil 	if (copyin(data, STRUCT_BUF(apinfo), STRUCT_SIZE(apinfo)))
1132005d3febSMarek Pospisil 		return (EFAULT);
1133005d3febSMarek Pospisil 
1134005d3febSMarek Pospisil 	newcred = cralloc();
1135005d3febSMarek Pospisil 
1136005d3febSMarek Pospisil 	mutex_enter(&pidlock);
1137005d3febSMarek Pospisil 	if ((proc = prfind(STRUCT_FGET(apinfo, ap_pid))) == NULL) {
1138005d3febSMarek Pospisil 		mutex_exit(&pidlock);
1139005d3febSMarek Pospisil 		crfree(newcred);
1140005d3febSMarek Pospisil 		return (ESRCH);		/* no such process */
1141005d3febSMarek Pospisil 	}
1142005d3febSMarek Pospisil 	mutex_enter(&proc->p_lock);	/* so process doesn't go away */
1143005d3febSMarek Pospisil 	mutex_exit(&pidlock);
1144005d3febSMarek Pospisil 
1145005d3febSMarek Pospisil 	audit_update_context(proc, newcred);	/* make sure it's up-to-date */
1146005d3febSMarek Pospisil 
1147005d3febSMarek Pospisil 	mutex_enter(&proc->p_crlock);
1148005d3febSMarek Pospisil 	crhold(cr = proc->p_cred);
1149005d3febSMarek Pospisil 	mutex_exit(&proc->p_crlock);
1150005d3febSMarek Pospisil 	mutex_exit(&proc->p_lock);
1151005d3febSMarek Pospisil 
1152005d3febSMarek Pospisil 	ainfo = crgetauinfo(cr);
1153005d3febSMarek Pospisil 	if (ainfo == NULL) {
1154005d3febSMarek Pospisil 		crfree(cr);
1155005d3febSMarek Pospisil 		return (EINVAL);
1156005d3febSMarek Pospisil 	}
1157005d3febSMarek Pospisil 
1158005d3febSMarek Pospisil 	/* designated process has an ipv6 address? */
1159005d3febSMarek Pospisil 	if (ainfo->ai_termid.at_type == AU_IPv6) {
1160005d3febSMarek Pospisil 		crfree(cr);
1161005d3febSMarek Pospisil 		return (EOVERFLOW);
1162005d3febSMarek Pospisil 	}
1163005d3febSMarek Pospisil 
1164005d3febSMarek Pospisil 	STRUCT_FSET(apinfo, ap_auid, ainfo->ai_auid);
1165005d3febSMarek Pospisil 	STRUCT_FSET(apinfo, ap_asid, ainfo->ai_asid);
1166005d3febSMarek Pospisil #ifdef _LP64
1167005d3febSMarek Pospisil 	if (model == DATAMODEL_ILP32) {
1168005d3febSMarek Pospisil 		dev32_t dev;
1169005d3febSMarek Pospisil 		/* convert internal 64 bit form to 32 bit version */
1170005d3febSMarek Pospisil 		if (cmpldev(&dev, ainfo->ai_termid.at_port) == 0) {
1171005d3febSMarek Pospisil 			crfree(cr);
1172005d3febSMarek Pospisil 			return (EOVERFLOW);
1173005d3febSMarek Pospisil 		}
1174005d3febSMarek Pospisil 		STRUCT_FSET(apinfo, ap_termid.port, dev);
1175005d3febSMarek Pospisil 	} else
1176005d3febSMarek Pospisil 		STRUCT_FSET(apinfo, ap_termid.port, ainfo->ai_termid.at_port);
1177005d3febSMarek Pospisil #else
1178005d3febSMarek Pospisil 	STRUCT_FSET(apinfo, ap_termid.port, ainfo->ai_termid.at_port);
1179005d3febSMarek Pospisil #endif
1180005d3febSMarek Pospisil 	STRUCT_FSET(apinfo, ap_termid.machine, ainfo->ai_termid.at_addr[0]);
1181005d3febSMarek Pospisil 	STRUCT_FSET(apinfo, ap_mask, ainfo->ai_mask);
1182005d3febSMarek Pospisil 
1183005d3febSMarek Pospisil 	crfree(cr);
1184005d3febSMarek Pospisil 
1185005d3febSMarek Pospisil 	if (copyout(STRUCT_BUF(apinfo), data, STRUCT_SIZE(apinfo)))
1186005d3febSMarek Pospisil 		return (EFAULT);
1187005d3febSMarek Pospisil 
1188005d3febSMarek Pospisil 	return (0);
1189005d3febSMarek Pospisil }
1190005d3febSMarek Pospisil 
1191005d3febSMarek Pospisil static int
1192005d3febSMarek Pospisil getpinfo_addr(caddr_t data, int len)
1193005d3febSMarek Pospisil {
1194005d3febSMarek Pospisil 	STRUCT_DECL(auditpinfo_addr, apinfo);
1195005d3febSMarek Pospisil 	proc_t *proc;
1196005d3febSMarek Pospisil 	const auditinfo_addr_t	*ainfo;
1197005d3febSMarek Pospisil 	model_t	model;
1198005d3febSMarek Pospisil 	cred_t	*cr, *newcred;
1199005d3febSMarek Pospisil 
1200005d3febSMarek Pospisil 	model = get_udatamodel();
1201005d3febSMarek Pospisil 	STRUCT_INIT(apinfo, model);
1202005d3febSMarek Pospisil 
1203005d3febSMarek Pospisil 	if (len < STRUCT_SIZE(apinfo))
1204005d3febSMarek Pospisil 		return (EOVERFLOW);
1205005d3febSMarek Pospisil 
1206005d3febSMarek Pospisil 	if (copyin(data, STRUCT_BUF(apinfo), STRUCT_SIZE(apinfo)))
1207005d3febSMarek Pospisil 		return (EFAULT);
1208005d3febSMarek Pospisil 
1209005d3febSMarek Pospisil 	newcred = cralloc();
1210005d3febSMarek Pospisil 
1211005d3febSMarek Pospisil 	mutex_enter(&pidlock);
1212005d3febSMarek Pospisil 	if ((proc = prfind(STRUCT_FGET(apinfo, ap_pid))) == NULL) {
1213005d3febSMarek Pospisil 		mutex_exit(&pidlock);
1214005d3febSMarek Pospisil 		crfree(newcred);
1215005d3febSMarek Pospisil 		return (ESRCH);
1216005d3febSMarek Pospisil 	}
1217005d3febSMarek Pospisil 	mutex_enter(&proc->p_lock);	/* so process doesn't go away */
1218005d3febSMarek Pospisil 	mutex_exit(&pidlock);
1219005d3febSMarek Pospisil 
1220005d3febSMarek Pospisil 	audit_update_context(proc, newcred);	/* make sure it's up-to-date */
1221005d3febSMarek Pospisil 
1222005d3febSMarek Pospisil 	mutex_enter(&proc->p_crlock);
1223005d3febSMarek Pospisil 	crhold(cr = proc->p_cred);
1224005d3febSMarek Pospisil 	mutex_exit(&proc->p_crlock);
1225005d3febSMarek Pospisil 	mutex_exit(&proc->p_lock);
1226005d3febSMarek Pospisil 
1227005d3febSMarek Pospisil 	ainfo = crgetauinfo(cr);
1228005d3febSMarek Pospisil 	if (ainfo == NULL) {
1229005d3febSMarek Pospisil 		crfree(cr);
1230005d3febSMarek Pospisil 		return (EINVAL);
1231005d3febSMarek Pospisil 	}
1232005d3febSMarek Pospisil 
1233005d3febSMarek Pospisil 	STRUCT_FSET(apinfo, ap_auid, ainfo->ai_auid);
1234005d3febSMarek Pospisil 	STRUCT_FSET(apinfo, ap_asid, ainfo->ai_asid);
1235005d3febSMarek Pospisil #ifdef _LP64
1236005d3febSMarek Pospisil 	if (model == DATAMODEL_ILP32) {
1237005d3febSMarek Pospisil 		dev32_t dev;
1238005d3febSMarek Pospisil 		/* convert internal 64 bit form to 32 bit version */
1239005d3febSMarek Pospisil 		if (cmpldev(&dev, ainfo->ai_termid.at_port) == 0) {
1240005d3febSMarek Pospisil 			crfree(cr);
1241005d3febSMarek Pospisil 			return (EOVERFLOW);
1242005d3febSMarek Pospisil 		}
1243005d3febSMarek Pospisil 		STRUCT_FSET(apinfo, ap_termid.at_port, dev);
1244005d3febSMarek Pospisil 	} else
1245005d3febSMarek Pospisil 		STRUCT_FSET(apinfo, ap_termid.at_port,
1246005d3febSMarek Pospisil 		    ainfo->ai_termid.at_port);
1247005d3febSMarek Pospisil #else
1248005d3febSMarek Pospisil 	STRUCT_FSET(apinfo, ap_termid.at_port, ainfo->ai_termid.at_port);
1249005d3febSMarek Pospisil #endif
1250005d3febSMarek Pospisil 	STRUCT_FSET(apinfo, ap_termid.at_type, ainfo->ai_termid.at_type);
1251005d3febSMarek Pospisil 	STRUCT_FSET(apinfo, ap_termid.at_addr[0], ainfo->ai_termid.at_addr[0]);
1252005d3febSMarek Pospisil 	STRUCT_FSET(apinfo, ap_termid.at_addr[1], ainfo->ai_termid.at_addr[1]);
1253005d3febSMarek Pospisil 	STRUCT_FSET(apinfo, ap_termid.at_addr[2], ainfo->ai_termid.at_addr[2]);
1254005d3febSMarek Pospisil 	STRUCT_FSET(apinfo, ap_termid.at_addr[3], ainfo->ai_termid.at_addr[3]);
1255005d3febSMarek Pospisil 	STRUCT_FSET(apinfo, ap_mask, ainfo->ai_mask);
1256005d3febSMarek Pospisil 
1257005d3febSMarek Pospisil 	crfree(cr);
1258005d3febSMarek Pospisil 
1259005d3febSMarek Pospisil 	if (copyout(STRUCT_BUF(apinfo), data, STRUCT_SIZE(apinfo)))
1260005d3febSMarek Pospisil 		return (EFAULT);
1261005d3febSMarek Pospisil 
1262005d3febSMarek Pospisil 	return (0);
1263005d3febSMarek Pospisil }
1264005d3febSMarek Pospisil 
1265005d3febSMarek Pospisil static int
1266005d3febSMarek Pospisil setpmask(caddr_t data)
1267005d3febSMarek Pospisil {
1268005d3febSMarek Pospisil 	STRUCT_DECL(auditpinfo, apinfo);
1269005d3febSMarek Pospisil 	proc_t *proc;
1270005d3febSMarek Pospisil 	cred_t	*newcred;
1271005d3febSMarek Pospisil 	auditinfo_addr_t	*ainfo;
1272005d3febSMarek Pospisil 	struct p_audit_data	*pad;
1273005d3febSMarek Pospisil 
1274005d3febSMarek Pospisil 	model_t	model;
1275005d3febSMarek Pospisil 
1276005d3febSMarek Pospisil 	model = get_udatamodel();
1277005d3febSMarek Pospisil 	STRUCT_INIT(apinfo, model);
1278005d3febSMarek Pospisil 
1279005d3febSMarek Pospisil 	if (copyin(data, STRUCT_BUF(apinfo), STRUCT_SIZE(apinfo)))
1280005d3febSMarek Pospisil 		return (EFAULT);
1281005d3febSMarek Pospisil 
1282005d3febSMarek Pospisil 	mutex_enter(&pidlock);
1283005d3febSMarek Pospisil 	if ((proc = prfind(STRUCT_FGET(apinfo, ap_pid))) == NULL) {
1284005d3febSMarek Pospisil 		mutex_exit(&pidlock);
1285005d3febSMarek Pospisil 		return (ESRCH);
1286005d3febSMarek Pospisil 	}
1287005d3febSMarek Pospisil 	mutex_enter(&proc->p_lock);	/* so process doesn't go away */
1288005d3febSMarek Pospisil 	mutex_exit(&pidlock);
1289005d3febSMarek Pospisil 
1290005d3febSMarek Pospisil 	newcred = cralloc();
1291005d3febSMarek Pospisil 	if ((ainfo = crgetauinfo_modifiable(newcred)) == NULL) {
1292005d3febSMarek Pospisil 		mutex_exit(&proc->p_lock);
1293005d3febSMarek Pospisil 		crfree(newcred);
1294005d3febSMarek Pospisil 		return (EINVAL);
1295005d3febSMarek Pospisil 	}
1296005d3febSMarek Pospisil 
1297005d3febSMarek Pospisil 	mutex_enter(&proc->p_crlock);
1298005d3febSMarek Pospisil 	crcopy_to(proc->p_cred, newcred);
1299005d3febSMarek Pospisil 	proc->p_cred = newcred;
1300005d3febSMarek Pospisil 
1301005d3febSMarek Pospisil 	ainfo->ai_mask = STRUCT_FGET(apinfo, ap_mask);
1302005d3febSMarek Pospisil 
1303005d3febSMarek Pospisil 	/*
1304005d3febSMarek Pospisil 	 * Unlock. No need to broadcast changes via set_proc_pre_sys(),
1305005d3febSMarek Pospisil 	 * since t_pre_sys is ALWAYS on when audit is enabled... due to
1306005d3febSMarek Pospisil 	 * syscall auditing.
1307005d3febSMarek Pospisil 	 */
1308005d3febSMarek Pospisil 	crfree(newcred);
1309005d3febSMarek Pospisil 	mutex_exit(&proc->p_crlock);
1310005d3febSMarek Pospisil 
1311005d3febSMarek Pospisil 	/* Reset flag for any previous pending mask change; this supercedes */
1312005d3febSMarek Pospisil 	pad = P2A(proc);
1313005d3febSMarek Pospisil 	ASSERT(pad != NULL);
1314005d3febSMarek Pospisil 	mutex_enter(&(pad->pad_lock));
1315005d3febSMarek Pospisil 	pad->pad_flags &= ~PAD_SETMASK;
1316005d3febSMarek Pospisil 	mutex_exit(&(pad->pad_lock));
1317005d3febSMarek Pospisil 
1318005d3febSMarek Pospisil 	mutex_exit(&proc->p_lock);
1319005d3febSMarek Pospisil 
1320005d3febSMarek Pospisil 	return (0);
1321005d3febSMarek Pospisil }
1322005d3febSMarek Pospisil 
1323005d3febSMarek Pospisil /*
1324005d3febSMarek Pospisil  * The out of control system call
1325005d3febSMarek Pospisil  * This is audit kitchen sink aka auditadm, aka auditon
1326005d3febSMarek Pospisil  */
1327005d3febSMarek Pospisil int
1328005d3febSMarek Pospisil auditctl(
1329005d3febSMarek Pospisil 	int	cmd,
1330005d3febSMarek Pospisil 	caddr_t data,
1331005d3febSMarek Pospisil 	int	length)
1332005d3febSMarek Pospisil {
1333005d3febSMarek Pospisil 	int result;
1334005d3febSMarek Pospisil 
1335005d3febSMarek Pospisil 	switch (cmd) {
1336005d3febSMarek Pospisil 	case A_GETCOND:
1337005d3febSMarek Pospisil 	case A_GETCAR:
1338005d3febSMarek Pospisil 	case A_GETCLASS:
1339005d3febSMarek Pospisil 	case A_GETCWD:
1340005d3febSMarek Pospisil 	case A_GETKAUDIT:
1341005d3febSMarek Pospisil 	case A_GETKMASK:
1342005d3febSMarek Pospisil 	case A_GETPINFO:
1343005d3febSMarek Pospisil 	case A_GETPINFO_ADDR:
1344005d3febSMarek Pospisil 	case A_GETPOLICY:
1345005d3febSMarek Pospisil 	case A_GETQCTRL:
1346005d3febSMarek Pospisil 	case A_GETSTAT:
1347005d3febSMarek Pospisil 		if (secpolicy_audit_getattr(CRED()) != 0)
1348005d3febSMarek Pospisil 			return (EPERM);
1349005d3febSMarek Pospisil 		break;
1350005d3febSMarek Pospisil 	default:
1351005d3febSMarek Pospisil 		if (secpolicy_audit_config(CRED()) != 0)
1352005d3febSMarek Pospisil 			return (EPERM);
1353005d3febSMarek Pospisil 		break;
1354005d3febSMarek Pospisil 	}
1355005d3febSMarek Pospisil 
1356005d3febSMarek Pospisil 	switch (cmd) {
1357005d3febSMarek Pospisil 	case A_GETPOLICY:
1358005d3febSMarek Pospisil 		result = getpolicy(data);
1359005d3febSMarek Pospisil 		break;
1360005d3febSMarek Pospisil 	case A_SETPOLICY:
1361005d3febSMarek Pospisil 		result = setpolicy(data);
1362005d3febSMarek Pospisil 		break;
1363005d3febSMarek Pospisil 	case A_GETKMASK:
1364005d3febSMarek Pospisil 		result = getkmask(data);
1365005d3febSMarek Pospisil 		break;
1366005d3febSMarek Pospisil 	case A_SETKMASK:
1367005d3febSMarek Pospisil 		result = setkmask(data);
1368005d3febSMarek Pospisil 		break;
1369005d3febSMarek Pospisil 	case A_GETKAUDIT:
1370005d3febSMarek Pospisil 		result = getkaudit(data, length);
1371005d3febSMarek Pospisil 		break;
1372005d3febSMarek Pospisil 	case A_SETKAUDIT:
1373005d3febSMarek Pospisil 		result = setkaudit(data, length);
1374005d3febSMarek Pospisil 		break;
1375005d3febSMarek Pospisil 	case A_GETQCTRL:
1376005d3febSMarek Pospisil 		result = getqctrl(data);
1377005d3febSMarek Pospisil 		break;
1378005d3febSMarek Pospisil 	case A_SETQCTRL:
1379005d3febSMarek Pospisil 		result = setqctrl(data);
1380005d3febSMarek Pospisil 		break;
1381005d3febSMarek Pospisil 	case A_GETCWD:
1382005d3febSMarek Pospisil 		result = getcwd(data, length);
1383005d3febSMarek Pospisil 		break;
1384005d3febSMarek Pospisil 	case A_GETCAR:
1385005d3febSMarek Pospisil 		result = getcar(data, length);
1386005d3febSMarek Pospisil 		break;
1387005d3febSMarek Pospisil 	case A_GETSTAT:
1388005d3febSMarek Pospisil 		result = getstat(data);
1389005d3febSMarek Pospisil 		break;
1390005d3febSMarek Pospisil 	case A_SETSTAT:
1391005d3febSMarek Pospisil 		result = setstat(data);
1392005d3febSMarek Pospisil 		break;
1393005d3febSMarek Pospisil 	case A_SETUMASK:
1394005d3febSMarek Pospisil 		result = setumask(data);
1395005d3febSMarek Pospisil 		break;
1396005d3febSMarek Pospisil 	case A_SETSMASK:
1397005d3febSMarek Pospisil 		result = setsmask(data);
1398005d3febSMarek Pospisil 		break;
1399005d3febSMarek Pospisil 	case A_GETCOND:
1400005d3febSMarek Pospisil 		result = getcond(data);
1401005d3febSMarek Pospisil 		break;
1402005d3febSMarek Pospisil 	case A_SETCOND:
1403005d3febSMarek Pospisil 		result = setcond(data);
1404005d3febSMarek Pospisil 		break;
1405005d3febSMarek Pospisil 	case A_GETCLASS:
1406005d3febSMarek Pospisil 		result = getclass(data);
1407005d3febSMarek Pospisil 		break;
1408005d3febSMarek Pospisil 	case A_SETCLASS:
1409005d3febSMarek Pospisil 		result = setclass(data);
1410005d3febSMarek Pospisil 		break;
1411005d3febSMarek Pospisil 	case A_GETPINFO:
1412005d3febSMarek Pospisil 		result = getpinfo(data);
1413005d3febSMarek Pospisil 		break;
1414005d3febSMarek Pospisil 	case A_GETPINFO_ADDR:
1415005d3febSMarek Pospisil 		result = getpinfo_addr(data, length);
1416005d3febSMarek Pospisil 		break;
1417005d3febSMarek Pospisil 	case A_SETPMASK:
1418005d3febSMarek Pospisil 		result = setpmask(data);
1419005d3febSMarek Pospisil 		break;
1420005d3febSMarek Pospisil 	default:
1421005d3febSMarek Pospisil 		result = EINVAL;
1422005d3febSMarek Pospisil 		break;
1423005d3febSMarek Pospisil 	}
1424005d3febSMarek Pospisil 	return (result);
14257c478bd9Sstevel@tonic-gate }
1426