xref: /onnv-gate/usr/src/uts/common/os/audit_core.c (revision 13126:222ede23af01)
111861SMarek.Pospisil@Sun.COM /*
211861SMarek.Pospisil@Sun.COM  * CDDL HEADER START
311861SMarek.Pospisil@Sun.COM  *
411861SMarek.Pospisil@Sun.COM  * The contents of this file are subject to the terms of the
511861SMarek.Pospisil@Sun.COM  * Common Development and Distribution License (the "License").
611861SMarek.Pospisil@Sun.COM  * You may not use this file except in compliance with the License.
711861SMarek.Pospisil@Sun.COM  *
811861SMarek.Pospisil@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
911861SMarek.Pospisil@Sun.COM  * or http://www.opensolaris.org/os/licensing.
1011861SMarek.Pospisil@Sun.COM  * See the License for the specific language governing permissions
1111861SMarek.Pospisil@Sun.COM  * and limitations under the License.
1211861SMarek.Pospisil@Sun.COM  *
1311861SMarek.Pospisil@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
1411861SMarek.Pospisil@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1511861SMarek.Pospisil@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
1611861SMarek.Pospisil@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
1711861SMarek.Pospisil@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
1811861SMarek.Pospisil@Sun.COM  *
1911861SMarek.Pospisil@Sun.COM  * CDDL HEADER END
2011861SMarek.Pospisil@Sun.COM  */
2111861SMarek.Pospisil@Sun.COM /*
22*13126SMarek.Pospisil@Sun.COM  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
2311861SMarek.Pospisil@Sun.COM  */
2411861SMarek.Pospisil@Sun.COM 
2511861SMarek.Pospisil@Sun.COM #include <sys/param.h>
2611861SMarek.Pospisil@Sun.COM #include <sys/types.h>
2711861SMarek.Pospisil@Sun.COM #include <sys/time.h>
2811861SMarek.Pospisil@Sun.COM #include <sys/kmem.h>
2911861SMarek.Pospisil@Sun.COM #include <sys/proc.h>
3011861SMarek.Pospisil@Sun.COM #include <sys/vnode.h>
3111861SMarek.Pospisil@Sun.COM #include <sys/file.h>
3211861SMarek.Pospisil@Sun.COM #include <sys/user.h>
3311861SMarek.Pospisil@Sun.COM #include <sys/stropts.h>
3411861SMarek.Pospisil@Sun.COM #include <sys/systm.h>
3511861SMarek.Pospisil@Sun.COM #include <sys/pathname.h>
3611861SMarek.Pospisil@Sun.COM #include <sys/debug.h>
3711861SMarek.Pospisil@Sun.COM #include <sys/cred_impl.h>
3811861SMarek.Pospisil@Sun.COM #include <sys/zone.h>
3911861SMarek.Pospisil@Sun.COM #include <sys/modctl.h>
4011861SMarek.Pospisil@Sun.COM #include <sys/sysconf.h>
4111861SMarek.Pospisil@Sun.COM #include <c2/audit.h>
4211861SMarek.Pospisil@Sun.COM #include <c2/audit_kernel.h>
4311861SMarek.Pospisil@Sun.COM #include <c2/audit_kevents.h>
4411861SMarek.Pospisil@Sun.COM #include <c2/audit_record.h>
4511861SMarek.Pospisil@Sun.COM 
4611861SMarek.Pospisil@Sun.COM 
4711861SMarek.Pospisil@Sun.COM struct p_audit_data *pad0;
4811861SMarek.Pospisil@Sun.COM struct t_audit_data *tad0;
4911861SMarek.Pospisil@Sun.COM 
5011861SMarek.Pospisil@Sun.COM extern uint_t num_syscall;		/* size of audit_s2e table */
5111861SMarek.Pospisil@Sun.COM extern kmutex_t pidlock;		/* proc table lock */
5211861SMarek.Pospisil@Sun.COM 
5311861SMarek.Pospisil@Sun.COM 
5411861SMarek.Pospisil@Sun.COM void
audit_init()5511861SMarek.Pospisil@Sun.COM audit_init()
5611861SMarek.Pospisil@Sun.COM {
5711861SMarek.Pospisil@Sun.COM 	kthread_t	    *au_thread;
5811861SMarek.Pospisil@Sun.COM 	auditinfo_addr_t    *ainfo;
5911861SMarek.Pospisil@Sun.COM 	struct audit_path   apempty;
6011861SMarek.Pospisil@Sun.COM 
6111861SMarek.Pospisil@Sun.COM 	/*
6211861SMarek.Pospisil@Sun.COM 	 * If the c2audit module is explicitely excluded in /etc/system,
6311861SMarek.Pospisil@Sun.COM 	 * it cannot be loaded later (e.g. using modload). Make a notice
6411861SMarek.Pospisil@Sun.COM 	 * that the module won't be present and do nothing.
6511861SMarek.Pospisil@Sun.COM 	 */
6611861SMarek.Pospisil@Sun.COM 
6711861SMarek.Pospisil@Sun.COM 	if (mod_sysctl(SYS_CHECK_EXCLUDE, "c2audit") != 0) {
6811861SMarek.Pospisil@Sun.COM 		audit_active = C2AUDIT_DISABLED;
6911861SMarek.Pospisil@Sun.COM 		return;
7011861SMarek.Pospisil@Sun.COM 	}
7111861SMarek.Pospisil@Sun.COM 
7211861SMarek.Pospisil@Sun.COM 	/* c2audit module can be loaded anytime */
7311861SMarek.Pospisil@Sun.COM 	audit_active = C2AUDIT_UNLOADED;
7411861SMarek.Pospisil@Sun.COM 
7511861SMarek.Pospisil@Sun.COM 	/* initialize the process audit data (pad) memory allocator */
7611861SMarek.Pospisil@Sun.COM 	au_pad_init();
7711861SMarek.Pospisil@Sun.COM 
7811861SMarek.Pospisil@Sun.COM 	/* initialize the zone audit context */
7911861SMarek.Pospisil@Sun.COM 	au_zone_setup();
8011861SMarek.Pospisil@Sun.COM 
8111861SMarek.Pospisil@Sun.COM 	/* inital thread structure */
8211861SMarek.Pospisil@Sun.COM 	tad0 = kmem_zalloc(sizeof (struct t_audit_data), KM_SLEEP);
8311861SMarek.Pospisil@Sun.COM 
8411861SMarek.Pospisil@Sun.COM 	/* initial process structure */
8511861SMarek.Pospisil@Sun.COM 	pad0 = kmem_cache_alloc(au_pad_cache, KM_SLEEP);
8611861SMarek.Pospisil@Sun.COM 	bzero(&pad0->pad_data, sizeof (pad0->pad_data));
8711861SMarek.Pospisil@Sun.COM 
8811861SMarek.Pospisil@Sun.COM 	curthread->t_audit_data = tad0;
8911861SMarek.Pospisil@Sun.COM 	curproc->p_audit_data = pad0;
9011861SMarek.Pospisil@Sun.COM 
9111861SMarek.Pospisil@Sun.COM 	/*
9211861SMarek.Pospisil@Sun.COM 	 * The kernel allocates a bunch of threads make sure they have
9311861SMarek.Pospisil@Sun.COM 	 * a valid tad
9411861SMarek.Pospisil@Sun.COM 	 */
9511861SMarek.Pospisil@Sun.COM 
9611861SMarek.Pospisil@Sun.COM 	mutex_enter(&pidlock);
9711861SMarek.Pospisil@Sun.COM 
9811861SMarek.Pospisil@Sun.COM 	au_thread = curthread;
9911861SMarek.Pospisil@Sun.COM 	do {
10011861SMarek.Pospisil@Sun.COM 		if (T2A(au_thread) == NULL) {
10111861SMarek.Pospisil@Sun.COM 			T2A(au_thread) = tad0;
10211861SMarek.Pospisil@Sun.COM 		}
10311861SMarek.Pospisil@Sun.COM 		au_thread = au_thread->t_next;
10411861SMarek.Pospisil@Sun.COM 	} while (au_thread != curthread);
10511861SMarek.Pospisil@Sun.COM 
10611861SMarek.Pospisil@Sun.COM 	tad0->tad_ad = NULL;
10711861SMarek.Pospisil@Sun.COM 	mutex_exit(&pidlock);
10811861SMarek.Pospisil@Sun.COM 
10911861SMarek.Pospisil@Sun.COM 	/*
11011861SMarek.Pospisil@Sun.COM 	 * Initialize audit context in our cred (kcred).
11111861SMarek.Pospisil@Sun.COM 	 * No copy-on-write needed here because it's so early in init.
11211861SMarek.Pospisil@Sun.COM 	 */
11311861SMarek.Pospisil@Sun.COM 
11411861SMarek.Pospisil@Sun.COM 	ainfo = crgetauinfo_modifiable(kcred);
11511861SMarek.Pospisil@Sun.COM 	ASSERT(ainfo != NULL);
11611861SMarek.Pospisil@Sun.COM 	bzero(ainfo, sizeof (auditinfo_addr_t));
11711861SMarek.Pospisil@Sun.COM 	ainfo->ai_auid = AU_NOAUDITID;
11811861SMarek.Pospisil@Sun.COM 
11911861SMarek.Pospisil@Sun.COM 	/* fabricate an empty audit_path to extend */
12011861SMarek.Pospisil@Sun.COM 	apempty.audp_cnt = 0;
12111861SMarek.Pospisil@Sun.COM 	apempty.audp_sect[0] = (char *)(&apempty.audp_sect[1]);
12211861SMarek.Pospisil@Sun.COM 	pad0->pad_root = au_pathdup(&apempty, 1, 2);
12311861SMarek.Pospisil@Sun.COM 	bcopy("/", pad0->pad_root->audp_sect[0], 2);
12411861SMarek.Pospisil@Sun.COM 	au_pathhold(pad0->pad_root);
12511861SMarek.Pospisil@Sun.COM 	pad0->pad_cwd = pad0->pad_root;
12611861SMarek.Pospisil@Sun.COM }
12711861SMarek.Pospisil@Sun.COM 
12811861SMarek.Pospisil@Sun.COM /*
12911861SMarek.Pospisil@Sun.COM  * Check for any pending changes to the audit context for the given proc.
13011861SMarek.Pospisil@Sun.COM  * p_crlock and pad_lock for the process are acquired here. Caller is
13111861SMarek.Pospisil@Sun.COM  * responsible for assuring the process doesn't go away. If context is
13211861SMarek.Pospisil@Sun.COM  * updated, the specified cralloc'ed cred will be used, otherwise it's freed.
13311861SMarek.Pospisil@Sun.COM  * If no cred is given, it will be cralloc'ed here and caller assures that
13411861SMarek.Pospisil@Sun.COM  * it is safe to allocate memory.
13511861SMarek.Pospisil@Sun.COM  */
13611861SMarek.Pospisil@Sun.COM 
13711861SMarek.Pospisil@Sun.COM void
audit_update_context(proc_t * p,cred_t * ncr)13811861SMarek.Pospisil@Sun.COM audit_update_context(proc_t *p, cred_t *ncr)
13911861SMarek.Pospisil@Sun.COM {
14011861SMarek.Pospisil@Sun.COM 	struct p_audit_data *pad;
14111861SMarek.Pospisil@Sun.COM 	cred_t *newcred = ncr;
14211861SMarek.Pospisil@Sun.COM 
14311861SMarek.Pospisil@Sun.COM 	pad = P2A(p);
14411861SMarek.Pospisil@Sun.COM 	if (pad == NULL) {
14511861SMarek.Pospisil@Sun.COM 		if (newcred != NULL)
14611861SMarek.Pospisil@Sun.COM 			crfree(newcred);
14711861SMarek.Pospisil@Sun.COM 		return;
14811861SMarek.Pospisil@Sun.COM 	}
14911861SMarek.Pospisil@Sun.COM 
15011861SMarek.Pospisil@Sun.COM 	/* If a mask update is pending, take care of it. */
15111861SMarek.Pospisil@Sun.COM 	if (pad->pad_flags & PAD_SETMASK) {
15211861SMarek.Pospisil@Sun.COM 		auditinfo_addr_t *ainfo;
15311861SMarek.Pospisil@Sun.COM 
15411861SMarek.Pospisil@Sun.COM 		if (newcred == NULL)
15511861SMarek.Pospisil@Sun.COM 			newcred = cralloc();
15611861SMarek.Pospisil@Sun.COM 
15711861SMarek.Pospisil@Sun.COM 		mutex_enter(&pad->pad_lock);
15811861SMarek.Pospisil@Sun.COM 		/* the condition may have been handled by the time we lock */
15911861SMarek.Pospisil@Sun.COM 		if (pad->pad_flags & PAD_SETMASK) {
16011861SMarek.Pospisil@Sun.COM 			ainfo = crgetauinfo_modifiable(newcred);
16111861SMarek.Pospisil@Sun.COM 			if (ainfo == NULL) {
162*13126SMarek.Pospisil@Sun.COM 				mutex_exit(&pad->pad_lock);
16311861SMarek.Pospisil@Sun.COM 				crfree(newcred);
16411861SMarek.Pospisil@Sun.COM 				return;
16511861SMarek.Pospisil@Sun.COM 			}
16611861SMarek.Pospisil@Sun.COM 
16711861SMarek.Pospisil@Sun.COM 			mutex_enter(&p->p_crlock);
16811861SMarek.Pospisil@Sun.COM 			crcopy_to(p->p_cred, newcred);
16911861SMarek.Pospisil@Sun.COM 			p->p_cred = newcred;
17011861SMarek.Pospisil@Sun.COM 
17111861SMarek.Pospisil@Sun.COM 			ainfo->ai_mask = pad->pad_newmask;
17211861SMarek.Pospisil@Sun.COM 
17311861SMarek.Pospisil@Sun.COM 			/* Unlock and cleanup. */
17411861SMarek.Pospisil@Sun.COM 			mutex_exit(&p->p_crlock);
17511861SMarek.Pospisil@Sun.COM 			pad->pad_flags &= ~PAD_SETMASK;
17611861SMarek.Pospisil@Sun.COM 
17711861SMarek.Pospisil@Sun.COM 			/*
17811861SMarek.Pospisil@Sun.COM 			 * For curproc, assure that our thread points to right
17911861SMarek.Pospisil@Sun.COM 			 * cred, so CRED() will be correct. Otherwise, no need
18011861SMarek.Pospisil@Sun.COM 			 * to broadcast changes (via set_proc_pre_sys), since
18111861SMarek.Pospisil@Sun.COM 			 * t_pre_sys is ALWAYS on when audit is enabled... due
18211861SMarek.Pospisil@Sun.COM 			 * to syscall auditing.
18311861SMarek.Pospisil@Sun.COM 			 */
18411861SMarek.Pospisil@Sun.COM 			if (p == curproc)
18511861SMarek.Pospisil@Sun.COM 				crset(p, newcred);
18611861SMarek.Pospisil@Sun.COM 			else
18711861SMarek.Pospisil@Sun.COM 				crfree(newcred);
18811861SMarek.Pospisil@Sun.COM 		} else {
18911861SMarek.Pospisil@Sun.COM 			crfree(newcred);
19011861SMarek.Pospisil@Sun.COM 		}
19111861SMarek.Pospisil@Sun.COM 		mutex_exit(&pad->pad_lock);
19211861SMarek.Pospisil@Sun.COM 	} else {
19311861SMarek.Pospisil@Sun.COM 		if (newcred != NULL)
19411861SMarek.Pospisil@Sun.COM 			crfree(newcred);
19511861SMarek.Pospisil@Sun.COM 	}
19611861SMarek.Pospisil@Sun.COM }
19711861SMarek.Pospisil@Sun.COM 
19811861SMarek.Pospisil@Sun.COM /*
19911861SMarek.Pospisil@Sun.COM  * ROUTINE:	AUDIT_NEWPROC
20011861SMarek.Pospisil@Sun.COM  * PURPOSE:	initialize the child p_audit_data structure
20111861SMarek.Pospisil@Sun.COM  * CALLBY:	GETPROC
20211861SMarek.Pospisil@Sun.COM  * NOTE:	All threads for the parent process are locked at this point.
20311861SMarek.Pospisil@Sun.COM  *		We are essentially running singled threaded for this reason.
20411861SMarek.Pospisil@Sun.COM  *		GETPROC is called when system creates a new process.
20511861SMarek.Pospisil@Sun.COM  *		By the time AUDIT_NEWPROC is called, the child proc
20611861SMarek.Pospisil@Sun.COM  *		structure has already been initialized. What we need
20711861SMarek.Pospisil@Sun.COM  *		to do is to allocate the child p_audit_data and
20811861SMarek.Pospisil@Sun.COM  *		initialize it with the content of current parent process.
20911861SMarek.Pospisil@Sun.COM  */
21011861SMarek.Pospisil@Sun.COM 
21111861SMarek.Pospisil@Sun.COM void
audit_newproc(struct proc * cp)21211861SMarek.Pospisil@Sun.COM audit_newproc(struct proc *cp)	/* initialized child proc structure */
21311861SMarek.Pospisil@Sun.COM {
21411861SMarek.Pospisil@Sun.COM 	p_audit_data_t *pad;	/* child process audit data */
21511861SMarek.Pospisil@Sun.COM 	p_audit_data_t *opad;	/* parent process audit data */
21611861SMarek.Pospisil@Sun.COM 
21711861SMarek.Pospisil@Sun.COM 	pad = kmem_cache_alloc(au_pad_cache, KM_SLEEP);
21811861SMarek.Pospisil@Sun.COM 
21911861SMarek.Pospisil@Sun.COM 	P2A(cp) = pad;
22011861SMarek.Pospisil@Sun.COM 
22111861SMarek.Pospisil@Sun.COM 	opad = P2A(curproc);
22211861SMarek.Pospisil@Sun.COM 
22311861SMarek.Pospisil@Sun.COM 	/*
22411861SMarek.Pospisil@Sun.COM 	 * copy the audit data. Note that all threads of current
22511861SMarek.Pospisil@Sun.COM 	 *   process have been "held". Thus there is no race condition
22611861SMarek.Pospisil@Sun.COM 	 *   here with mutiple threads trying to alter the cwrd
22711861SMarek.Pospisil@Sun.COM 	 *   structure (such as releasing it).
22811861SMarek.Pospisil@Sun.COM 	 *
22911861SMarek.Pospisil@Sun.COM 	 *   The audit context in the cred is "duplicated" for the new
23011861SMarek.Pospisil@Sun.COM 	 *   proc by elsewhere crhold'ing the parent's cred which it shares.
23111861SMarek.Pospisil@Sun.COM 	 *
23211861SMarek.Pospisil@Sun.COM 	 *   We still want to hold things since auditon() [A_SETUMASK,
23311861SMarek.Pospisil@Sun.COM 	 *   A_SETSMASK] could be walking through the processes to
23411861SMarek.Pospisil@Sun.COM 	 *   update things.
23511861SMarek.Pospisil@Sun.COM 	 */
23611861SMarek.Pospisil@Sun.COM 	mutex_enter(&opad->pad_lock);	/* lock opad structure during copy */
23711861SMarek.Pospisil@Sun.COM 	pad->pad_data = opad->pad_data;	/* copy parent's process audit data */
23811861SMarek.Pospisil@Sun.COM 	au_pathhold(pad->pad_root);
23911861SMarek.Pospisil@Sun.COM 	au_pathhold(pad->pad_cwd);
24011861SMarek.Pospisil@Sun.COM 	mutex_exit(&opad->pad_lock);	/* current proc will keep cwrd open */
24111861SMarek.Pospisil@Sun.COM 
24211861SMarek.Pospisil@Sun.COM 	/*
24311861SMarek.Pospisil@Sun.COM 	 * If we are in the limited mode, there is nothing to audit and
24411861SMarek.Pospisil@Sun.COM 	 * there could not have been anything to audit, since it is not
24511861SMarek.Pospisil@Sun.COM 	 * possible to switch from the full mode into the limited mode
24611861SMarek.Pospisil@Sun.COM 	 * once the full mode is set.
24711861SMarek.Pospisil@Sun.COM 	 */
24811861SMarek.Pospisil@Sun.COM 	if (audit_active != C2AUDIT_LOADED)
24911861SMarek.Pospisil@Sun.COM 		return;
25011861SMarek.Pospisil@Sun.COM 
25111861SMarek.Pospisil@Sun.COM 	/*
25211861SMarek.Pospisil@Sun.COM 	 * finish auditing of parent here so that it will be done
25311861SMarek.Pospisil@Sun.COM 	 * before child has a chance to run. We include the child
25411861SMarek.Pospisil@Sun.COM 	 * pid since the return value in the return token is a dummy
25511861SMarek.Pospisil@Sun.COM 	 * one and contains no useful information (it is included to
25611861SMarek.Pospisil@Sun.COM 	 * make the audit record structure consistant).
25711861SMarek.Pospisil@Sun.COM 	 *
25811861SMarek.Pospisil@Sun.COM 	 * tad_flag is set if auditing is on
25911861SMarek.Pospisil@Sun.COM 	 */
26011861SMarek.Pospisil@Sun.COM 	if (((t_audit_data_t *)T2A(curthread))->tad_flag)
26111861SMarek.Pospisil@Sun.COM 		au_uwrite(au_to_arg32(0, "child PID", (uint32_t)cp->p_pid));
26211861SMarek.Pospisil@Sun.COM 
26311861SMarek.Pospisil@Sun.COM 	/*
26411861SMarek.Pospisil@Sun.COM 	 * finish up audit record generation here because child process
26511861SMarek.Pospisil@Sun.COM 	 * is set to run before parent process. We distinguish here
26611861SMarek.Pospisil@Sun.COM 	 * between FORK, FORK1, or VFORK by the saved system call ID.
26711861SMarek.Pospisil@Sun.COM 	 */
26811861SMarek.Pospisil@Sun.COM 	audit_finish(0, ((t_audit_data_t *)T2A(curthread))->tad_scid, 0, 0);
26911861SMarek.Pospisil@Sun.COM }
27011861SMarek.Pospisil@Sun.COM 
27111861SMarek.Pospisil@Sun.COM /*
27211861SMarek.Pospisil@Sun.COM  * ROUTINE:	AUDIT_PFREE
27311861SMarek.Pospisil@Sun.COM  * PURPOSE:	deallocate the per-process udit data structure
27411861SMarek.Pospisil@Sun.COM  * CALLBY:	EXIT
27511861SMarek.Pospisil@Sun.COM  *		FORK_FAIL
27611861SMarek.Pospisil@Sun.COM  * NOTE:	all lwp except current one have stopped in SEXITLWPS
27711861SMarek.Pospisil@Sun.COM  * 		why we are single threaded?
27811861SMarek.Pospisil@Sun.COM  *		. all lwp except current one have stopped in SEXITLWPS.
27911861SMarek.Pospisil@Sun.COM  */
28011861SMarek.Pospisil@Sun.COM 
28111861SMarek.Pospisil@Sun.COM void
audit_pfree(struct proc * p)28211861SMarek.Pospisil@Sun.COM audit_pfree(struct proc *p)		/* proc structure to be freed */
28311861SMarek.Pospisil@Sun.COM 
28411861SMarek.Pospisil@Sun.COM {	/* AUDIT_PFREE */
28511861SMarek.Pospisil@Sun.COM 
28611861SMarek.Pospisil@Sun.COM 	p_audit_data_t *pad;
28711861SMarek.Pospisil@Sun.COM 
28811861SMarek.Pospisil@Sun.COM 	pad = P2A(p);
28911861SMarek.Pospisil@Sun.COM 
29011861SMarek.Pospisil@Sun.COM 	/* better be a per process audit data structure */
29111861SMarek.Pospisil@Sun.COM 	ASSERT(pad != (p_audit_data_t *)0);
29211861SMarek.Pospisil@Sun.COM 
29311861SMarek.Pospisil@Sun.COM 	if (pad == pad0) {
29411861SMarek.Pospisil@Sun.COM 		return;
29511861SMarek.Pospisil@Sun.COM 	}
29611861SMarek.Pospisil@Sun.COM 
29711861SMarek.Pospisil@Sun.COM 	/* deallocate all auditing resources for this process */
29811861SMarek.Pospisil@Sun.COM 	au_pathrele(pad->pad_root);
29911861SMarek.Pospisil@Sun.COM 	au_pathrele(pad->pad_cwd);
30011861SMarek.Pospisil@Sun.COM 
30111861SMarek.Pospisil@Sun.COM 	/*
30211861SMarek.Pospisil@Sun.COM 	 * Since the pad structure is completely overwritten after alloc,
30311861SMarek.Pospisil@Sun.COM 	 * we don't bother to clear it.
30411861SMarek.Pospisil@Sun.COM 	 */
30511861SMarek.Pospisil@Sun.COM 
30611861SMarek.Pospisil@Sun.COM 	kmem_cache_free(au_pad_cache, pad);
30711861SMarek.Pospisil@Sun.COM }
30811861SMarek.Pospisil@Sun.COM 
30911861SMarek.Pospisil@Sun.COM /*
31011861SMarek.Pospisil@Sun.COM  * ROUTINE:	AUDIT_THREAD_CREATE
31111861SMarek.Pospisil@Sun.COM  * PURPOSE:	allocate per-process thread audit data structure
31211861SMarek.Pospisil@Sun.COM  * CALLBY:	THREAD_CREATE
31311861SMarek.Pospisil@Sun.COM  * NOTE:	This is called just after *t was bzero'd.
31411861SMarek.Pospisil@Sun.COM  *		We are single threaded in this routine.
31511861SMarek.Pospisil@Sun.COM  * TODO:
31611861SMarek.Pospisil@Sun.COM  * QUESTION:
31711861SMarek.Pospisil@Sun.COM  */
31811861SMarek.Pospisil@Sun.COM 
31911861SMarek.Pospisil@Sun.COM void
audit_thread_create(kthread_id_t t)32011861SMarek.Pospisil@Sun.COM audit_thread_create(kthread_id_t t)
32111861SMarek.Pospisil@Sun.COM {
32211861SMarek.Pospisil@Sun.COM 	t_audit_data_t *tad;	/* per-thread audit data */
32311861SMarek.Pospisil@Sun.COM 
32411861SMarek.Pospisil@Sun.COM 	tad = kmem_zalloc(sizeof (struct t_audit_data), KM_SLEEP);
32511861SMarek.Pospisil@Sun.COM 
32611861SMarek.Pospisil@Sun.COM 	T2A(t) = tad;		/* set up thread audit data ptr */
32711861SMarek.Pospisil@Sun.COM 	tad->tad_thread = t;	/* back ptr to thread: DEBUG */
32811861SMarek.Pospisil@Sun.COM }
32911861SMarek.Pospisil@Sun.COM 
33011861SMarek.Pospisil@Sun.COM /*
33111861SMarek.Pospisil@Sun.COM  * ROUTINE:	AUDIT_THREAD_FREE
33211861SMarek.Pospisil@Sun.COM  * PURPOSE:	free the per-thread audit data structure
33311861SMarek.Pospisil@Sun.COM  * CALLBY:	THREAD_FREE
33411861SMarek.Pospisil@Sun.COM  * NOTE:	most thread data is clear after return
33511861SMarek.Pospisil@Sun.COM  */
33611861SMarek.Pospisil@Sun.COM 
33711861SMarek.Pospisil@Sun.COM void
audit_thread_free(kthread_t * t)33811861SMarek.Pospisil@Sun.COM audit_thread_free(kthread_t *t)
33911861SMarek.Pospisil@Sun.COM {
34011861SMarek.Pospisil@Sun.COM 	t_audit_data_t *tad;
34111861SMarek.Pospisil@Sun.COM 	au_defer_info_t	*attr;
34211861SMarek.Pospisil@Sun.COM 
34311861SMarek.Pospisil@Sun.COM 	tad = T2A(t);
34411861SMarek.Pospisil@Sun.COM 
34511861SMarek.Pospisil@Sun.COM 	/* thread audit data must still be set */
34611861SMarek.Pospisil@Sun.COM 
34711861SMarek.Pospisil@Sun.COM 	if (tad == tad0) {
34811861SMarek.Pospisil@Sun.COM 		return;
34911861SMarek.Pospisil@Sun.COM 	}
35011861SMarek.Pospisil@Sun.COM 
35111861SMarek.Pospisil@Sun.COM 	if (tad == NULL) {
35211861SMarek.Pospisil@Sun.COM 		return;
35311861SMarek.Pospisil@Sun.COM 	}
35411861SMarek.Pospisil@Sun.COM 
35511861SMarek.Pospisil@Sun.COM 	t->t_audit_data = 0;
35611861SMarek.Pospisil@Sun.COM 
35711861SMarek.Pospisil@Sun.COM 	/* must not have any audit record residual */
35811861SMarek.Pospisil@Sun.COM 	ASSERT(tad->tad_ad == NULL);
35911861SMarek.Pospisil@Sun.COM 
36011861SMarek.Pospisil@Sun.COM 	/* saved path must be empty */
36111861SMarek.Pospisil@Sun.COM 	ASSERT(tad->tad_aupath == NULL);
36211861SMarek.Pospisil@Sun.COM 
36311861SMarek.Pospisil@Sun.COM 	if (tad->tad_atpath)
36411861SMarek.Pospisil@Sun.COM 		au_pathrele(tad->tad_atpath);
36511861SMarek.Pospisil@Sun.COM 
36611861SMarek.Pospisil@Sun.COM 	if (audit_active == C2AUDIT_LOADED) {
36711861SMarek.Pospisil@Sun.COM 		attr = tad->tad_defer_head;
36811861SMarek.Pospisil@Sun.COM 		while (attr != NULL) {
36911861SMarek.Pospisil@Sun.COM 			au_defer_info_t	*tmp_attr = attr;
37011861SMarek.Pospisil@Sun.COM 
37111861SMarek.Pospisil@Sun.COM 			au_free_rec(attr->audi_ad);
37211861SMarek.Pospisil@Sun.COM 
37311861SMarek.Pospisil@Sun.COM 			attr = attr->audi_next;
37411861SMarek.Pospisil@Sun.COM 			kmem_free(tmp_attr, sizeof (au_defer_info_t));
37511861SMarek.Pospisil@Sun.COM 		}
37611861SMarek.Pospisil@Sun.COM 	}
37711861SMarek.Pospisil@Sun.COM 
37811861SMarek.Pospisil@Sun.COM 	kmem_free(tad, sizeof (*tad));
37911861SMarek.Pospisil@Sun.COM }
38011861SMarek.Pospisil@Sun.COM 
38111861SMarek.Pospisil@Sun.COM /*
38211861SMarek.Pospisil@Sun.COM  * ROUTINE:	AUDIT_FALLOC
38311861SMarek.Pospisil@Sun.COM  * PURPOSE:	allocating a new file structure
38411861SMarek.Pospisil@Sun.COM  * CALLBY:	FALLOC
38511861SMarek.Pospisil@Sun.COM  * NOTE:	file structure already initialized
38611861SMarek.Pospisil@Sun.COM  * TODO:
38711861SMarek.Pospisil@Sun.COM  * QUESTION:
38811861SMarek.Pospisil@Sun.COM  */
38911861SMarek.Pospisil@Sun.COM 
39011861SMarek.Pospisil@Sun.COM void
audit_falloc(struct file * fp)39111861SMarek.Pospisil@Sun.COM audit_falloc(struct file *fp)
39211861SMarek.Pospisil@Sun.COM {	/* AUDIT_FALLOC */
39311861SMarek.Pospisil@Sun.COM 
39411861SMarek.Pospisil@Sun.COM 	f_audit_data_t *fad;
39511861SMarek.Pospisil@Sun.COM 
39611861SMarek.Pospisil@Sun.COM 	/* allocate per file audit structure if there a'int any */
39711861SMarek.Pospisil@Sun.COM 	ASSERT(F2A(fp) == NULL);
39811861SMarek.Pospisil@Sun.COM 
39911861SMarek.Pospisil@Sun.COM 	fad = kmem_zalloc(sizeof (struct f_audit_data), KM_SLEEP);
40011861SMarek.Pospisil@Sun.COM 
40111861SMarek.Pospisil@Sun.COM 	F2A(fp) = fad;
40211861SMarek.Pospisil@Sun.COM 
40311861SMarek.Pospisil@Sun.COM 	fad->fad_thread = curthread; 	/* file audit data back ptr; DEBUG */
40411861SMarek.Pospisil@Sun.COM }
40511861SMarek.Pospisil@Sun.COM 
40611861SMarek.Pospisil@Sun.COM /*
40711861SMarek.Pospisil@Sun.COM  * ROUTINE:	AUDIT_UNFALLOC
40811861SMarek.Pospisil@Sun.COM  * PURPOSE:	deallocate file audit data structure
40911861SMarek.Pospisil@Sun.COM  * CALLBY:	CLOSEF
41011861SMarek.Pospisil@Sun.COM  *		UNFALLOC
41111861SMarek.Pospisil@Sun.COM  * NOTE:
41211861SMarek.Pospisil@Sun.COM  * TODO:
41311861SMarek.Pospisil@Sun.COM  * QUESTION:
41411861SMarek.Pospisil@Sun.COM  */
41511861SMarek.Pospisil@Sun.COM 
41611861SMarek.Pospisil@Sun.COM void
audit_unfalloc(struct file * fp)41711861SMarek.Pospisil@Sun.COM audit_unfalloc(struct file *fp)
41811861SMarek.Pospisil@Sun.COM {
41911861SMarek.Pospisil@Sun.COM 	f_audit_data_t *fad;
42011861SMarek.Pospisil@Sun.COM 
42111861SMarek.Pospisil@Sun.COM 	fad = F2A(fp);
42211861SMarek.Pospisil@Sun.COM 
42311861SMarek.Pospisil@Sun.COM 	if (!fad) {
42411861SMarek.Pospisil@Sun.COM 		return;
42511861SMarek.Pospisil@Sun.COM 	}
42611861SMarek.Pospisil@Sun.COM 	if (fad->fad_aupath != NULL) {
42711861SMarek.Pospisil@Sun.COM 		au_pathrele(fad->fad_aupath);
42811861SMarek.Pospisil@Sun.COM 	}
42911861SMarek.Pospisil@Sun.COM 	fp->f_audit_data = 0;
43011861SMarek.Pospisil@Sun.COM 	kmem_free(fad, sizeof (struct f_audit_data));
43111861SMarek.Pospisil@Sun.COM }
43211861SMarek.Pospisil@Sun.COM 
43311861SMarek.Pospisil@Sun.COM uint32_t
audit_getstate()43411861SMarek.Pospisil@Sun.COM audit_getstate()
43511861SMarek.Pospisil@Sun.COM {
43611861SMarek.Pospisil@Sun.COM 	return (audit_active == C2AUDIT_LOADED &&
43711861SMarek.Pospisil@Sun.COM 	    ((AU_AUDIT_MASK) & U2A(u)->tad_audit));
43811861SMarek.Pospisil@Sun.COM }
439