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