1/*-
2 * Copyright (c) 2008-2009 Apple Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1.  Redistributions of source code must retain the above copyright
9 *     notice, this list of conditions and the following disclaimer.
10 * 2.  Redistributions in binary form must reproduce the above copyright
11 *     notice, this list of conditions and the following disclaimer in the
12 *     documentation and/or other materials provided with the distribution.
13 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
14 *     its contributors may be used to endorse or promote products derived
15 *     from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
26 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#include <stdarg.h>
31
32#include <sys/kernel.h>
33#include <sys/fcntl.h>
34#include <sys/kauth.h>
35#include <sys/conf.h>
36#include <sys/poll.h>
37#include <sys/queue.h>
38#include <sys/signalvar.h>
39#include <sys/syscall.h>
40#include <sys/sysent.h>
41#include <sys/sysproto.h>
42#include <sys/systm.h>
43#include <sys/ucred.h>
44#include <sys/user.h>
45
46#include <miscfs/devfs/devfs.h>
47
48#include <libkern/OSAtomic.h>
49
50#include <bsm/audit.h>
51#include <bsm/audit_internal.h>
52#include <bsm/audit_kevents.h>
53
54#include <security/audit/audit.h>
55#include <security/audit/audit_bsd.h>
56#include <security/audit/audit_ioctl.h>
57#include <security/audit/audit_private.h>
58
59#include <vm/vm_protos.h>
60#include <mach/mach_port.h>
61#include <kern/audit_sessionport.h>
62
63#include <libkern/OSDebug.h>
64
65/*
66 * Audit Session Entry.  This is treated as an object with public and private
67 * data.   The se_auinfo field is the only information that is public and
68 * needs to be the first entry.
69 */
70struct au_sentry {
71	auditinfo_addr_t	se_auinfo;	/* Public audit session data. */
72#define	se_asid		se_auinfo.ai_asid
73#define	se_auid		se_auinfo.ai_auid
74#define	se_mask		se_auinfo.ai_mask
75#define	se_termid	se_auinfo.ai_termid
76#define	se_flags	se_auinfo.ai_flags
77
78	long			se_refcnt;	/* Reference count. */
79	long			se_procnt;	/* Processes in session. */
80	ipc_port_t		se_port;	/* Session port. */
81	LIST_ENTRY(au_sentry)	se_link; 	/* Hash bucket link list (1) */
82};
83typedef struct au_sentry au_sentry_t;
84
85#define	AU_SENTRY_PTR(aia_p)	((au_sentry_t *)(aia_p))
86
87/*
88 * The default au_sentry/auditinfo_addr entry for ucred.
89 */
90
91static au_sentry_t audit_default_se = {
92	.se_auinfo = {
93			.ai_auid = AU_DEFAUDITID,
94			.ai_asid = AU_DEFAUDITSID,
95			.ai_termid = { .at_type = AU_IPv4, },
96	},
97	.se_refcnt = 1,
98	.se_procnt = 1,
99};
100
101struct auditinfo_addr *audit_default_aia_p = &audit_default_se.se_auinfo;
102
103kern_return_t ipc_object_copyin(ipc_space_t, mach_port_name_t,
104    mach_msg_type_name_t, ipc_port_t *);
105void ipc_port_release_send(ipc_port_t);
106
107#if CONFIG_AUDIT
108
109
110/*
111 * Currently the hash table is a fixed size.
112 */
113#define HASH_TABLE_SIZE		97
114#define	HASH_ASID(asid)		(audit_session_hash(asid) % HASH_TABLE_SIZE)
115
116static struct rwlock	se_entry_lck;		/* (1) lock for se_link above */
117
118LIST_HEAD(au_sentry_head, au_sentry);
119static struct au_sentry_head *au_sentry_bucket = NULL;
120
121#define AU_HISTORY_LOGGING 0
122#if AU_HISTORY_LOGGING
123typedef enum au_history_event {
124	AU_HISTORY_EVENT_UNKNOWN = 0,
125	AU_HISTORY_EVENT_REF     = 1,
126	AU_HISTORY_EVENT_UNREF   = 2,
127	AU_HISTORY_EVENT_BIRTH   = 3,
128	AU_HISTORY_EVENT_DEATH   = 4,
129	AU_HISTORY_EVENT_FIND    = 5
130} au_history_event_t;
131
132#define AU_HISTORY_MAX_STACK_DEPTH 8
133
134struct au_history {
135	struct au_sentry	*ptr;
136	struct au_sentry	 se;
137	void			*stack[AU_HISTORY_MAX_STACK_DEPTH];
138	unsigned int		 stack_depth;
139	au_history_event_t	 event;
140};
141
142static struct au_history *au_history;
143static size_t		  au_history_size = 65536;
144static unsigned int	  au_history_index;
145
146static inline unsigned int
147au_history_entries(void)
148{
149	if (au_history_index >= au_history_size)
150		return au_history_size;
151	else
152		return au_history_index;
153}
154
155static inline void
156au_history_record(au_sentry_t *se, au_history_event_t event)
157{
158	struct au_history *p;
159	unsigned int i;
160
161	i = OSAddAtomic(1, &au_history_index);
162	p = &au_history[i % au_history_size];
163
164	bzero(p, sizeof(*p));
165	p->event = event;
166	bcopy(se, &p->se, sizeof(p->se));
167	p->stack_depth = OSBacktrace(&p->stack[0], AU_HISTORY_MAX_STACK_DEPTH);
168	p->ptr = se;
169}
170#else
171#define au_history_record(se, event) do {} while (0)
172#endif
173
174MALLOC_DEFINE(M_AU_SESSION, "audit_session", "Audit session data");
175
176static void	audit_ref_session(au_sentry_t *se);
177static void	audit_unref_session(au_sentry_t *se);
178
179static void 	audit_session_event(int event, auditinfo_addr_t *aia_p);
180
181/*
182 * Audit session device.
183 */
184
185static MALLOC_DEFINE(M_AUDIT_SDEV, "audit_sdev", "Audit sdevs");
186static MALLOC_DEFINE(M_AUDIT_SDEV_ENTRY, "audit_sdevent",
187    "Audit sdev entries and buffers");
188
189/*
190 * Default audit sdev buffer parameters.
191 */
192#define	AUDIT_SDEV_QLIMIT_DEFAULT	128
193#define	AUDIT_SDEV_QLIMIT_MIN		1
194#define	AUDIT_SDEV_QLIMIT_MAX		1024
195
196/*
197 * Entry structure.
198 */
199struct	audit_sdev_entry {
200	void				*ase_record;
201	u_int		 		 ase_record_len;
202	TAILQ_ENTRY(audit_sdev_entry)	 ase_queue;
203};
204
205/*
206 * Per audit sdev structure.
207 */
208
209struct audit_sdev {
210	int		asdev_open;
211
212#define	AUDIT_SDEV_ASYNC	0x00000001
213#define	AUDIT_SDEV_NBIO		0x00000002
214
215#define	AUDIT_SDEV_ALLSESSIONS	0x00010000
216	u_int		asdev_flags;
217
218	struct selinfo	asdev_selinfo;
219	pid_t		asdev_sigio;
220
221	au_id_t		asdev_auid;
222	au_asid_t	asdev_asid;
223
224	/* Per-sdev mutex for most fields in this struct. */
225	struct mtx	asdev_mtx;
226
227	/*
228	 * Per-sdev sleep lock serializing user-generated reads and
229	 * flushes. uiomove() is called to copy out the current head
230	 * record's data whie the record remains in the queue, so we
231	 * prevent other threads from removing it using this lock.
232	 */
233	struct slck	asdev_sx;
234
235	/*
236	 * Condition variable to signal when data has been delivered to
237	 * a sdev.
238	 */
239	struct cv	asdev_cv;
240
241	/* Count and bound of records in the queue. */
242	u_int		asdev_qlen;
243	u_int		asdev_qlimit;
244
245	/* The number of bytes of data across all records. */
246	u_int		asdev_qbyteslen;
247
248	/*
249	 * The amount read so far of the first record in the queue.
250	 * (The number of bytes available for reading in the queue is
251	 * qbyteslen - qoffset.)
252	 */
253	u_int		asdev_qoffset;
254
255	/*
256	 * Per-sdev operation statistics.
257	 */
258	u_int64_t	asdev_inserts;	/* Records added. */
259	u_int64_t	asdev_reads;	/* Records read. */
260	u_int64_t	asdev_drops;	/* Records dropped. */
261
262	/*
263	 * Current pending record list.  This is protected by a
264	 * combination of asdev_mtx and asdev_sx.  Note that both
265	 * locks are required to remove a record from the head of the
266	 * queue, as an in-progress read may sleep while copying and,
267	 * therefore, cannot hold asdev_mtx.
268	 */
269	TAILQ_HEAD(, audit_sdev_entry)	asdev_queue;
270
271	/* Global sdev list. */
272	TAILQ_ENTRY(audit_sdev)		asdev_list;
273};
274
275#define	AUDIT_SDEV_LOCK(asdev)		mtx_lock(&(asdev)->asdev_mtx)
276#define	AUDIT_SDEV_LOCK_ASSERT(asdev)	mtx_assert(&(asdev)->asdev_mtx, \
277					    MA_OWNED)
278#define	AUDIT_SDEV_LOCK_DESTROY(asdev)	mtx_destroy(&(asdev)->asdev_mtx)
279#define	AUDIT_SDEV_LOCK_INIT(asdev)	mtx_init(&(asdev)->asdev_mtx, \
280					    "audit_sdev_mtx", NULL, MTX_DEF)
281#define	AUDIT_SDEV_UNLOCK(asdev)	mtx_unlock(&(asdev)->asdev_mtx)
282#define	AUDIT_SDEV_MTX(asdev)		(&(asdev)->asdev_mtx)
283
284#define	AUDIT_SDEV_SX_LOCK_DESTROY(asd)	slck_destroy(&(asd)->asdev_sx)
285#define	AUDIT_SDEV_SX_LOCK_INIT(asd)	slck_init(&(asd)->asdev_sx, \
286    					    "audit_sdev_sx")
287#define	AUDIT_SDEV_SX_XLOCK_ASSERT(asd)	slck_assert(&(asd)->asdev_sx, \
288    					    SA_XLOCKED)
289#define	AUDIT_SDEV_SX_XLOCK_SIG(asd)	slck_lock_sig(&(asd)->asdev_sx)
290#define	AUDIT_SDEV_SX_XUNLOCK(asd)	slck_unlock(&(asd)->asdev_sx)
291
292/*
293 * Cloning variables and constants.
294 */
295#define	AUDIT_SDEV_NAME		"auditsessions"
296#define	MAX_AUDIT_SDEVS		32
297
298static int audit_sdev_major;
299static void *devnode;
300
301/*
302 * Global list of audit sdevs.  The list is protected by a rw lock.
303 * Individaul record queues are protected by  per-sdev locks.  These
304 * locks synchronize between threads walking the list to deliver to
305 * individual sdevs and adds/removes of sdevs.
306 */
307static TAILQ_HEAD(, audit_sdev) audit_sdev_list;
308static struct rwlock		audit_sdev_lock;
309
310#define	AUDIT_SDEV_LIST_LOCK_INIT()	rw_init(&audit_sdev_lock, \
311    					    "audit_sdev_list_lock")
312#define	AUDIT_SDEV_LIST_RLOCK()		rw_rlock(&audit_sdev_lock)
313#define	AUDIT_SDEV_LIST_RUNLOCK()	rw_runlock(&audit_sdev_lock)
314#define	AUDIT_SDEV_LIST_WLOCK()         rw_wlock(&audit_sdev_lock)
315#define	AUDIT_SDEV_LIST_WLOCK_ASSERT()	rw_assert(&audit_sdev_lock, \
316    					    RA_WLOCKED)
317#define	AUDIT_SDEV_LIST_WUNLOCK()       rw_wunlock(&audit_sdev_lock)
318
319/*
320 * dev_t doesn't have a pointer for "softc" data so we have to keep track of
321 * it with the following global array (indexed by the minor number).
322 *
323 * XXX We may want to dynamically grow this as need.
324 */
325static struct audit_sdev	*audit_sdev_dtab[MAX_AUDIT_SDEVS];
326
327/*
328 * Special device methods and definition.
329 */
330static open_close_fcn_t		audit_sdev_open;
331static open_close_fcn_t		audit_sdev_close;
332static read_write_fcn_t		audit_sdev_read;
333static ioctl_fcn_t		audit_sdev_ioctl;
334static select_fcn_t		audit_sdev_poll;
335
336static struct cdevsw audit_sdev_cdevsw = {
337	.d_open      =          audit_sdev_open,
338	.d_close     =          audit_sdev_close,
339	.d_read      =          audit_sdev_read,
340	.d_write     =          eno_rdwrt,
341	.d_ioctl     =          audit_sdev_ioctl,
342	.d_stop      =          eno_stop,
343	.d_reset     =          eno_reset,
344	.d_ttys      =          NULL,
345	.d_select    =          audit_sdev_poll,
346	.d_mmap      =          eno_mmap,
347	.d_strategy  =          eno_strat,
348	.d_type      =          0
349};
350
351/*
352 * Global statistics on audit sdevs.
353 */
354static int		audit_sdev_count;	/* Current number of sdevs. */
355static u_int64_t	audit_sdev_ever;	/* Sdevs ever allocated. */
356static u_int64_t	audit_sdev_records; 	/* Total records seen. */
357static u_int64_t	audit_sdev_drops;	/* Global record drop count. */
358
359static int audit_sdev_init(void);
360
361#define	AUDIT_SENTRY_RWLOCK_INIT()	rw_init(&se_entry_lck, \
362					    "se_entry_lck")
363#define	AUDIT_SENTRY_RLOCK()		rw_rlock(&se_entry_lck)
364#define	AUDIT_SENTRY_WLOCK()		rw_wlock(&se_entry_lck)
365#define	AUDIT_SENTRY_RWLOCK_ASSERT()	rw_assert(&se_entry_lck, RA_LOCKED)
366#define	AUDIT_SENTRY_RUNLOCK()		rw_runlock(&se_entry_lck)
367#define	AUDIT_SENTRY_WUNLOCK()		rw_wunlock(&se_entry_lck)
368
369/* Access control on the auditinfo_addr.ai_flags member. */
370static uint64_t audit_session_superuser_set_sflags_mask;
371static uint64_t audit_session_superuser_clear_sflags_mask;
372static uint64_t audit_session_member_set_sflags_mask;
373static uint64_t audit_session_member_clear_sflags_mask;
374SYSCTL_NODE(, OID_AUTO, audit, CTLFLAG_RW|CTLFLAG_LOCKED, 0, "Audit controls");
375SYSCTL_NODE(_audit, OID_AUTO, session, CTLFLAG_RW|CTLFLAG_LOCKED, 0, "Audit sessions");
376SYSCTL_QUAD(_audit_session, OID_AUTO, superuser_set_sflags_mask, CTLFLAG_RW | CTLFLAG_LOCKED,
377    &audit_session_superuser_set_sflags_mask,
378    "Audit session flags settable by superuser");
379SYSCTL_QUAD(_audit_session, OID_AUTO, superuser_clear_sflags_mask, CTLFLAG_RW | CTLFLAG_LOCKED,
380    &audit_session_superuser_clear_sflags_mask,
381    "Audit session flags clearable by superuser");
382SYSCTL_QUAD(_audit_session, OID_AUTO, member_set_sflags_mask, CTLFLAG_RW | CTLFLAG_LOCKED,
383    &audit_session_member_set_sflags_mask,
384    "Audit session flags settable by a session member");
385SYSCTL_QUAD(_audit_session, OID_AUTO, member_clear_sflags_mask, CTLFLAG_RW | CTLFLAG_LOCKED,
386    &audit_session_member_clear_sflags_mask,
387    "Audit session flags clearable by a session member");
388
389#define	AUDIT_SESSION_DEBUG	0
390#if	AUDIT_SESSION_DEBUG
391/*
392 * The following is debugging code that can be used to get a snapshot of the
393 * session state.  The audit session information is read out using sysctl:
394 *
395 * error = sysctlbyname("kern.audit_session_debug", buffer_ptr, &buffer_len,
396 * 		NULL, 0);
397 */
398#include <kern/kalloc.h>
399
400/*
401 * The per session record structure for the snapshot data.
402 */
403struct au_sentry_debug {
404	auditinfo_addr_t	se_auinfo;
405	int64_t			se_refcnt;	/* refereence count */
406	int64_t			se_procnt;	/* process count */
407	int64_t			se_ptcnt;	/* process count from
408						   proc table */
409};
410typedef struct au_sentry_debug au_sentry_debug_t;
411
412static int audit_sysctl_session_debug(struct sysctl_oid *oidp, void *arg1,
413    int arg2, struct sysctl_req *req);
414
415SYSCTL_PROC(_kern, OID_AUTO, audit_session_debug, CTLFLAG_RD | CTLFLAG_LOCKED,
416    NULL, 0, audit_sysctl_session_debug, "S,audit_session_debug",
417    "Current session debug info for auditing.");
418
419/*
420 * Callouts for proc_interate() which is used to reconcile the audit session
421 * proc state information with the proc table.  We get everything we need
422 * in the filterfn while the proc_lock() is held so we really don't need the
423 * callout() function.
424 */
425static int
426audit_session_debug_callout(__unused proc_t p, __unused void *arg)
427{
428
429	return (PROC_RETURNED_DONE);
430}
431
432static int
433audit_session_debug_filterfn(proc_t p, void *st)
434{
435	kauth_cred_t cred = p->p_ucred;
436	auditinfo_addr_t *aia_p = cred->cr_audit.as_aia_p;
437	au_sentry_debug_t *sed_tab = (au_sentry_debug_t *) st;
438	au_sentry_debug_t  *sdtp;
439	au_sentry_t *se;
440
441	if (IS_VALID_SESSION(aia_p)) {
442		sdtp = &sed_tab[0];
443		do {
444			if (aia_p->ai_asid == sdtp->se_asid) {
445				sdtp->se_ptcnt++;
446
447				/* Do some santy checks. */
448				se = AU_SENTRY_PTR(aia_p);
449				if (se->se_refcnt != sdtp->se_refcnt) {
450					sdtp->se_refcnt =
451					    (int64_t)se->se_refcnt;
452				}
453				if (se->se_procnt != sdtp->se_procnt) {
454					sdtp->se_procnt =
455					    (int64_t)se->se_procnt;
456				}
457				break;
458			}
459			sdtp++;
460		} while (sdtp->se_asid != 0 && sdtp->se_auid != 0);
461	} else {
462		/* add it to the default sesison */
463		sed_tab->se_ptcnt++;
464	}
465
466	return (0);
467}
468
469/*
470 * Copy out the session debug info via the sysctl interface.
471 *
472 */
473static int
474audit_sysctl_session_debug(__unused struct sysctl_oid *oidp,
475    __unused void *arg1, __unused int arg2, struct sysctl_req *req)
476{
477	au_sentry_t *se;
478	au_sentry_debug_t *sed_tab, *next_sed;
479	int i, entry_cnt = 0;
480	size_t sz;
481	int err = 0;
482
483	/*
484	 * This provides a read-only node.
485	 */
486	if (req->newptr != USER_ADDR_NULL)
487		return (EPERM);
488
489	/*
490	 * Walk the audit session hash table to determine the size.
491	 */
492	AUDIT_SENTRY_RLOCK();
493	for(i = 0; i < HASH_TABLE_SIZE; i++)
494		LIST_FOREACH(se, &au_sentry_bucket[i], se_link)
495		    if (se != NULL)
496			    entry_cnt++;
497
498	entry_cnt++;  /* add one for the default entry */
499	/*
500	 * If just querying then return the space required.  There is an
501	 * obvious race condition here so we just fudge this by 3 in case
502	 * the audit session table grows.
503	 */
504	if (req->oldptr == USER_ADDR_NULL) {
505		req->oldidx = (entry_cnt + 3) * sizeof(au_sentry_debug_t);
506		AUDIT_SENTRY_RUNLOCK();
507		return (0);
508	}
509
510	/*
511	 * Alloc a temporary buffer.
512	 */
513	if (req->oldlen < (entry_cnt * sizeof(au_sentry_debug_t))) {
514		AUDIT_SENTRY_RUNLOCK();
515		return (ENOMEM);
516	}
517	/*
518	 * We hold the lock over the alloc since we don't want the table to
519	 * grow on us.   Therefore, use the non-blocking version of kalloc().
520	 */
521	sed_tab = (au_sentry_debug_t *)kalloc_noblock(entry_cnt *
522	    sizeof(au_sentry_debug_t));
523	if (sed_tab == NULL) {
524		AUDIT_SENTRY_RUNLOCK();
525		return (ENOMEM);
526	}
527	bzero(sed_tab, entry_cnt * sizeof(au_sentry_debug_t));
528
529	/*
530	 * Walk the audit session hash table and build the record array.
531	 */
532	sz = 0;
533	next_sed = sed_tab;
534	/* add the first entry for processes not tracked in sessions. */
535	bcopy(audit_default_aia_p, &next_sed->se_auinfo, sizeof (au_sentry_t));
536	next_sed->se_refcnt = (int64_t)audit_default_se.se_refcnt;
537	next_sed->se_procnt = (int64_t)audit_default_se.se_procnt;
538	next_sed++;
539	sz += sizeof(au_sentry_debug_t);
540	for(i = 0; i < HASH_TABLE_SIZE; i++) {
541		LIST_FOREACH(se, &au_sentry_bucket[i], se_link) {
542			if (se != NULL) {
543				next_sed->se_auinfo = se->se_auinfo;
544				next_sed->se_refcnt = (int64_t)se->se_refcnt;
545				next_sed->se_procnt = (int64_t)se->se_procnt;
546				next_sed++;
547				sz += sizeof(au_sentry_debug_t);
548			}
549		}
550	}
551	AUDIT_SENTRY_RUNLOCK();
552
553	/* Reconcile with the process table. */
554	(void) proc_iterate(PROC_ALLPROCLIST | PROC_ZOMBPROCLIST,
555	    audit_session_debug_callout, NULL,
556	    audit_session_debug_filterfn, (void *)&sed_tab[0]);
557
558
559	req->oldlen = sz;
560	err = SYSCTL_OUT(req, sed_tab, sz);
561	kfree(sed_tab, entry_cnt * sizeof(au_sentry_debug_t));
562
563	return (err);
564}
565
566#endif /* AUDIT_SESSION_DEBUG */
567
568/*
569 * Create and commit a session audit event. The proc and se arguments needs to
570 * be that of the subject and not necessarily the current process.
571 */
572static void
573audit_session_event(int event, auditinfo_addr_t *aia_p)
574{
575	struct kaudit_record *ar;
576
577	KASSERT(AUE_SESSION_START == event || AUE_SESSION_UPDATE == event ||
578	    AUE_SESSION_END == event || AUE_SESSION_CLOSE == event,
579	    ("audit_session_event: invalid event: %d", event));
580
581	if (NULL == aia_p)
582		return;
583
584	/*
585	 * Create a new audit record.  The record will contain the subject
586	 * ruid, rgid, egid, pid, auid, asid, amask, and term_addr
587	 * (implicitly added by audit_new).
588	 */
589	ar = audit_new(event, PROC_NULL, /* Not used */ NULL);
590	if (NULL == ar)
591		return;
592
593	/*
594	 * Audit session events are always generated because they are used
595	 * by some userland consumers so just set the preselect flag.
596	 */
597	ar->k_ar_commit |= AR_PRESELECT_FILTER;
598
599	/*
600	 * Populate the subject information.  Note that the ruid, rgid,
601	 * egid, and pid values are incorrect. We only need the  auditinfo_addr
602	 * information.
603	 */
604	ar->k_ar.ar_subj_ruid = 0;
605	ar->k_ar.ar_subj_rgid = 0;
606	ar->k_ar.ar_subj_egid = 0;
607	ar->k_ar.ar_subj_pid = 0;
608	ar->k_ar.ar_subj_auid = aia_p->ai_auid;
609	ar->k_ar.ar_subj_asid = aia_p->ai_asid;
610	bcopy(&aia_p->ai_termid, &ar->k_ar.ar_subj_term_addr,
611	    sizeof(struct au_tid_addr));
612
613	/* Add the audit masks to the record. */
614	ar->k_ar.ar_arg_amask.am_success = aia_p->ai_mask.am_success;
615	ar->k_ar.ar_arg_amask.am_failure = aia_p->ai_mask.am_failure;
616	ARG_SET_VALID(ar, ARG_AMASK);
617
618	/* Add the audit session flags to the record. */
619	ar->k_ar.ar_arg_value64 = aia_p->ai_flags;
620	ARG_SET_VALID(ar, ARG_VALUE64);
621
622
623	/* Commit the record to the queue. */
624	audit_commit(ar, 0, 0);
625}
626
627/*
628 * Hash the audit session ID using a simple 32-bit mix.
629 */
630static inline uint32_t
631audit_session_hash(au_asid_t asid)
632{
633	uint32_t a = (uint32_t) asid;
634
635	a = (a - (a << 6)) ^ (a >> 17);
636	a = (a - (a << 9)) ^ (a << 4);
637	a = (a - (a << 3)) ^ (a << 10);
638	a = a ^ (a >> 15);
639
640	return (a);
641}
642
643/*
644 * Do an hash lookup and find the session entry for a given ASID.  Return NULL
645 * if not found. If the session is found then audit_session_find takes a
646 * reference.
647 */
648static au_sentry_t *
649audit_session_find(au_asid_t asid)
650{
651	uint32_t	 hkey;
652	au_sentry_t	*found_se;
653
654	AUDIT_SENTRY_RWLOCK_ASSERT();
655
656	hkey = HASH_ASID(asid);
657
658	LIST_FOREACH(found_se, &au_sentry_bucket[hkey], se_link)
659		if (found_se->se_asid == asid) {
660			au_history_record(found_se, AU_HISTORY_EVENT_FIND);
661			audit_ref_session(found_se);
662			return (found_se);
663		}
664	return (NULL);
665}
666
667/*
668 * Remove the given audit_session entry from the hash table.
669 */
670static void
671audit_session_remove(au_sentry_t *se)
672{
673	uint32_t	 hkey;
674	au_sentry_t	*found_se, *tmp_se;
675
676	au_history_record(se, AU_HISTORY_EVENT_DEATH);
677	KASSERT(se->se_refcnt == 0, ("audit_session_remove: ref count != 0"));
678	KASSERT(se != &audit_default_se,
679		("audit_session_remove: removing default session"));
680
681	hkey = HASH_ASID(se->se_asid);
682
683	AUDIT_SENTRY_WLOCK();
684	/*
685	 * Check and see if someone got a reference before we got the lock.
686	 */
687	if (se->se_refcnt != 0) {
688		AUDIT_SENTRY_WUNLOCK();
689		return;
690	}
691
692	audit_session_portdestroy(&se->se_port);
693	LIST_FOREACH_SAFE(found_se, &au_sentry_bucket[hkey], se_link, tmp_se) {
694		if (found_se == se) {
695
696			/*
697			 * Generate an audit event to notify userland of the
698			 * session close.
699			 */
700			audit_session_event(AUE_SESSION_CLOSE,
701			    &found_se->se_auinfo);
702
703			LIST_REMOVE(found_se, se_link);
704			AUDIT_SENTRY_WUNLOCK();
705			free(found_se, M_AU_SESSION);
706
707			return;
708		}
709	}
710	AUDIT_SENTRY_WUNLOCK();
711}
712
713/*
714 * Reference the session by incrementing the sentry ref count.
715 */
716static void
717audit_ref_session(au_sentry_t *se)
718{
719	long old_val;
720
721	if (se == NULL || se == &audit_default_se)
722		return;
723
724	au_history_record(se, AU_HISTORY_EVENT_REF);
725
726	old_val = OSAddAtomicLong(1, &se->se_refcnt);
727	KASSERT(old_val < 100000,
728	    ("audit_ref_session: Too many references on session."));
729}
730
731/*
732 * Decrement the sentry ref count and remove the session entry if last one.
733 */
734static void
735audit_unref_session(au_sentry_t *se)
736{
737	long old_val;
738
739	if (se == NULL || se == &audit_default_se)
740		return;
741
742	au_history_record(se, AU_HISTORY_EVENT_UNREF);
743
744	old_val = OSAddAtomicLong(-1, &se->se_refcnt);
745	if (old_val == 1)
746		audit_session_remove(se);
747	KASSERT(old_val > 0,
748	    ("audit_unref_session: Too few references on session."));
749}
750
751/*
752 * Increment the process count in the session.
753 */
754static void
755audit_inc_procount(au_sentry_t *se)
756{
757	long old_val;
758
759	if (se == NULL || se == &audit_default_se)
760		return;
761
762	old_val = OSAddAtomicLong(1, &se->se_procnt);
763	KASSERT(old_val <= PID_MAX,
764	    ("audit_inc_procount: proc count > PID_MAX"));
765}
766
767/*
768 * Decrement the process count and add a knote if it is the last process
769 * to exit the session.
770 */
771static void
772audit_dec_procount(au_sentry_t *se)
773{
774	long old_val;
775
776	if (se == NULL || se == &audit_default_se)
777		return;
778
779	old_val = OSAddAtomicLong(-1, &se->se_procnt);
780	/*
781	 * If this was the last process generate an audit event to notify
782	 * userland of the session ending.
783	 */
784	if (old_val == 1)
785		audit_session_event(AUE_SESSION_END, &se->se_auinfo);
786	KASSERT(old_val >= 1,
787	    ("audit_dec_procount: proc count < 0"));
788}
789
790/*
791 * Update the session entry and check to see if anything was updated.
792 * Returns:
793 *    0    Nothing was updated (We don't care about process preselection masks)
794 *    1    Something was updated.
795 */
796static int
797audit_update_sentry(au_sentry_t *se, auditinfo_addr_t *new_aia)
798{
799	auditinfo_addr_t *aia = &se->se_auinfo;
800	int update;
801
802	KASSERT(new_aia != audit_default_aia_p,
803	  ("audit_update_sentry: Trying to update the default aia."));
804
805	update = (aia->ai_auid != new_aia->ai_auid ||
806	    bcmp(&aia->ai_termid, &new_aia->ai_termid,
807		sizeof(new_aia->ai_termid)) ||
808	    aia->ai_flags != new_aia->ai_flags);
809
810	if (update)
811		bcopy(new_aia, aia, sizeof(*aia));
812
813	return (update);
814}
815
816/*
817 * Return the next session ID.  The range of kernel generated audit session IDs
818 * is ASSIGNED_ASID_MIN to ASSIGNED_ASID_MAX.
819 */
820static uint32_t
821audit_session_nextid(void)
822{
823	static uint32_t next_asid = ASSIGNED_ASID_MIN;
824
825	AUDIT_SENTRY_RWLOCK_ASSERT();
826
827	if (next_asid > ASSIGNED_ASID_MAX)
828		next_asid = ASSIGNED_ASID_MIN;
829
830	return (next_asid++);
831}
832
833/*
834 * Allocated a new audit_session entry and add it to the hash table.  If the
835 * given ASID is set to AU_ASSIGN_ASID then audit_session_new() will pick an
836 * audit session ID.  Otherwise, it attempts use the one given. It creates a
837 * reference to the entry that must be unref'ed.
838 */
839static auditinfo_addr_t *
840audit_session_new(auditinfo_addr_t *new_aia_p, auditinfo_addr_t *old_aia_p)
841{
842	au_asid_t new_asid;
843	au_sentry_t *se = NULL;
844	au_sentry_t *found_se = NULL;
845	auditinfo_addr_t *aia = NULL;
846
847	KASSERT(new_aia_p != NULL, ("audit_session_new: new_aia_p == NULL"));
848
849	new_asid = new_aia_p->ai_asid;
850
851	/*
852	 * Alloc a new session entry now so we don't wait holding the lock.
853	 */
854	se = malloc(sizeof(au_sentry_t), M_AU_SESSION, M_WAITOK | M_ZERO);
855
856	/*
857	 * Find an unique session ID, if desired.
858	 */
859	AUDIT_SENTRY_WLOCK();
860	if (new_asid == AU_ASSIGN_ASID) {
861		do {
862
863			new_asid = (au_asid_t)audit_session_nextid();
864			found_se = audit_session_find(new_asid);
865
866			/*
867			 * If the session ID is currently active then drop the
868			 * reference and try again.
869			 */
870			if (found_se != NULL)
871				audit_unref_session(found_se);
872			else
873				break;
874		} while(1);
875	} else {
876
877		/*
878		 * Check to see if the requested ASID is already in the
879		 * hash table.  If so, update it with the new auditinfo.
880		 */
881		if ((found_se = audit_session_find(new_asid)) != NULL) {
882			int updated;
883
884			updated = audit_update_sentry(found_se, new_aia_p);
885
886			AUDIT_SENTRY_WUNLOCK();
887			free(se, M_AU_SESSION);
888
889			/* If a different session then add this process in. */
890			if (new_aia_p != old_aia_p)
891				audit_inc_procount(found_se);
892
893			/*
894			 * If the session information was updated then
895			 * generate an audit event to notify userland.
896			 */
897			if (updated)
898				audit_session_event(AUE_SESSION_UPDATE,
899				    &found_se->se_auinfo);
900
901			return (&found_se->se_auinfo);
902		}
903	}
904
905	/*
906	 * Start the reference and proc count at 1 to account for the process
907	 * that invoked this via setaudit_addr() (or friends).
908	 */
909	se->se_refcnt = se->se_procnt = 1;
910
911	/*
912	 * Populate the new session entry.  Note that process masks are stored
913	 * in kauth ucred so just zero them here.
914	 */
915	se->se_port = IPC_PORT_NULL;
916	aia = &se->se_auinfo;
917	aia->ai_asid = new_asid;
918	aia->ai_auid = new_aia_p->ai_auid;
919	bzero(&new_aia_p->ai_mask, sizeof(new_aia_p->ai_mask));
920	bcopy(&new_aia_p->ai_termid, &aia->ai_termid, sizeof(aia->ai_termid));
921	aia->ai_flags = new_aia_p->ai_flags;
922
923	/*
924	 * Add it to the hash table.
925	 */
926	LIST_INSERT_HEAD(&au_sentry_bucket[HASH_ASID(new_asid)], se, se_link);
927	AUDIT_SENTRY_WUNLOCK();
928
929	/*
930	 * Generate an audit event to notify userland of the new session.
931	 */
932	audit_session_event(AUE_SESSION_START, aia);
933	au_history_record(se, AU_HISTORY_EVENT_BIRTH);
934	return (aia);
935}
936
937/*
938 * Lookup an existing session.  A copy of the audit session info for a given
939 * ASID is returned in ret_aia.  Returns 0 on success.
940 */
941int
942audit_session_lookup(au_asid_t asid, auditinfo_addr_t *ret_aia)
943{
944	au_sentry_t *se = NULL;
945
946	if ((uint32_t)asid > ASSIGNED_ASID_MAX)
947		return (-1);
948	AUDIT_SENTRY_RLOCK();
949	if ((se = audit_session_find(asid)) == NULL) {
950		AUDIT_SENTRY_RUNLOCK();
951		return (1);
952	}
953	/* We have a reference on the session so it is safe to drop the lock. */
954	AUDIT_SENTRY_RUNLOCK();
955	if (ret_aia != NULL)
956		bcopy(&se->se_auinfo, ret_aia, sizeof(*ret_aia));
957	audit_unref_session(se);
958
959	return (0);
960}
961
962void
963audit_session_aiaref(auditinfo_addr_t *aia_p)
964{
965
966	audit_ref_session(AU_SENTRY_PTR(aia_p));
967}
968
969/*
970 * Add a reference to the session entry.
971 */
972void
973audit_session_ref(kauth_cred_t cred)
974{
975	auditinfo_addr_t *aia_p;
976
977	KASSERT(IS_VALID_CRED(cred),
978	    ("audit_session_ref: Invalid kauth_cred."));
979
980 	aia_p = cred->cr_audit.as_aia_p;
981	audit_session_aiaref(aia_p);
982}
983
984void audit_session_aiaunref(auditinfo_addr_t *aia_p)
985{
986
987	audit_unref_session(AU_SENTRY_PTR(aia_p));
988}
989
990/*
991 * Remove a reference to the session entry.
992 */
993void
994audit_session_unref(kauth_cred_t cred)
995{
996	auditinfo_addr_t *aia_p;
997
998	KASSERT(IS_VALID_CRED(cred),
999	    ("audit_session_unref: Invalid kauth_cred."));
1000
1001 	aia_p = cred->cr_audit.as_aia_p;
1002	audit_session_aiaunref(aia_p);
1003}
1004
1005/*
1006 * Increment the per audit session process count.  Assumes that the caller has
1007 * a reference on the process' cred.
1008 */
1009void
1010audit_session_procnew(proc_t p)
1011{
1012	kauth_cred_t cred = p->p_ucred;
1013	auditinfo_addr_t *aia_p;
1014
1015	KASSERT(IS_VALID_CRED(cred),
1016	    ("audit_session_procnew: Invalid kauth_cred."));
1017
1018	aia_p = cred->cr_audit.as_aia_p;
1019
1020	audit_inc_procount(AU_SENTRY_PTR(aia_p));
1021}
1022
1023/*
1024 * Decrement the per audit session process count.  Assumes that the caller has
1025 * a reference on the cred.
1026 */
1027void
1028audit_session_procexit(proc_t p)
1029{
1030	kauth_cred_t cred = p->p_ucred;
1031	auditinfo_addr_t *aia_p;
1032
1033	KASSERT(IS_VALID_CRED(cred),
1034	    ("audit_session_procexit: Invalid kauth_cred."));
1035
1036	aia_p = cred->cr_audit.as_aia_p;
1037
1038	audit_dec_procount(AU_SENTRY_PTR(aia_p));
1039}
1040
1041/*
1042 * Init the audit session code.
1043 */
1044void
1045audit_session_init(void)
1046{
1047	int i;
1048
1049	KASSERT((ASSIGNED_ASID_MAX - ASSIGNED_ASID_MIN) > PID_MAX,
1050	    ("audit_session_init: ASSIGNED_ASID_MAX is not large enough."));
1051
1052	AUDIT_SENTRY_RWLOCK_INIT();
1053
1054	au_sentry_bucket = malloc( sizeof(struct au_sentry) *
1055	    HASH_TABLE_SIZE, M_AU_SESSION, M_WAITOK | M_ZERO);
1056
1057	for (i = 0; i < HASH_TABLE_SIZE; i++)
1058		LIST_INIT(&au_sentry_bucket[i]);
1059
1060	(void)audit_sdev_init();
1061#if AU_HISTORY_LOGGING
1062	au_history = malloc(sizeof(struct au_history) * au_history_size,
1063	    M_AU_SESSION, M_WAITOK|M_ZERO);
1064#endif
1065}
1066
1067static int
1068audit_session_update_check(kauth_cred_t cred, auditinfo_addr_t *old,
1069    auditinfo_addr_t *new)
1070{
1071	uint64_t n;
1072
1073	/* If the current audit ID is not the default then it is immutable. */
1074	if (old->ai_auid != AU_DEFAUDITID && old->ai_auid != new->ai_auid)
1075		return (EINVAL);
1076
1077	/* If the current termid is not the default then it is immutable. */
1078	if ((old->ai_termid.at_type != AU_IPv4 ||
1079	     old->ai_termid.at_port != 0 ||
1080	     old->ai_termid.at_addr[0] != 0) &&
1081	    (old->ai_termid.at_port != new->ai_termid.at_port ||
1082	     old->ai_termid.at_type != new->ai_termid.at_type ||
1083	     0 != bcmp(&old->ai_termid.at_addr, &new->ai_termid.at_addr,
1084		 sizeof (old->ai_termid.at_addr))))
1085		return (EINVAL);
1086
1087	/* The flags may be set only according to the
1088	 * audit_session_*_set_sflags_masks.
1089	 */
1090	n = ~old->ai_flags & new->ai_flags;
1091	if (0 != n &&
1092	    !((n == (audit_session_superuser_set_sflags_mask & n) &&
1093		kauth_cred_issuser(cred)) ||
1094	      (n == (audit_session_member_set_sflags_mask & n)    &&
1095		old->ai_asid == new->ai_asid)))
1096		return (EINVAL);
1097
1098	/* The flags may be cleared only according to the
1099	 * audit_session_*_clear_sflags_masks.
1100	 */
1101	n = ~new->ai_flags & old->ai_flags;
1102	if (0 != n &&
1103	    !((n == (audit_session_superuser_clear_sflags_mask & n) &&
1104		kauth_cred_issuser(cred)) ||
1105	      (n == (audit_session_member_clear_sflags_mask & n)    &&
1106		old->ai_asid == new->ai_asid)))
1107		return (EINVAL);
1108
1109	/* The audit masks are mutable. */
1110	return (0);
1111}
1112
1113/*
1114 * Safely update kauth cred of the given process with new the given audit info.
1115 */
1116int
1117audit_session_setaia(proc_t p, auditinfo_addr_t *new_aia_p)
1118{
1119	kauth_cred_t my_cred, my_new_cred;
1120	struct au_session  as;
1121	struct au_session  tmp_as;
1122	auditinfo_addr_t caia, *old_aia_p;
1123	int ret;
1124
1125	/*
1126	 * If this is going to modify an existing session then do some
1127	 * immutable checks.
1128	 */
1129	if (audit_session_lookup(new_aia_p->ai_asid, &caia) == 0) {
1130		my_cred = kauth_cred_proc_ref(p);
1131		ret = audit_session_update_check(my_cred, &caia, new_aia_p);
1132		kauth_cred_unref(&my_cred);
1133		if (ret)
1134			return (ret);
1135	}
1136
1137	my_cred = kauth_cred_proc_ref(p);
1138	bcopy(&new_aia_p->ai_mask, &as.as_mask, sizeof(as.as_mask));
1139	old_aia_p = my_cred->cr_audit.as_aia_p;
1140	/* audit_session_new() adds a reference on the session */
1141	as.as_aia_p = audit_session_new(new_aia_p, old_aia_p);
1142
1143	/* If the process left a session then update the process count. */
1144	if (old_aia_p != new_aia_p)
1145		audit_dec_procount(AU_SENTRY_PTR(old_aia_p));
1146
1147
1148	/*
1149	 * We are modifying the audit info in a credential so we need a new
1150	 * credential (or take another reference on an existing credential that
1151	 * matches our new one).  We must do this because the audit info in the
1152	 * credential is used as part of our hash key.	Get current credential
1153	 * in the target process and take a reference while we muck with it.
1154	 */
1155	for (;;) {
1156
1157		/*
1158		 * Set the credential with new info.  If there is no change,
1159		 * we get back the same credential we passed in; if there is
1160		 * a change, we drop the reference on the credential we
1161		 * passed in.  The subsequent compare is safe, because it is
1162		 * a pointer compare rather than a contents compare.
1163		 */
1164		bcopy(&as, &tmp_as, sizeof(tmp_as));
1165		my_new_cred = kauth_cred_setauditinfo(my_cred, &tmp_as);
1166
1167		if (my_cred != my_new_cred) {
1168			proc_lock(p);
1169			/* Need to protect for a race where another thread also
1170			 * changed the credential after we took our reference.
1171			 * If p_ucred has changed then we should restart this
1172			 * again with the new cred.
1173			 */
1174			if (p->p_ucred != my_cred) {
1175				proc_unlock(p);
1176				audit_session_unref(my_new_cred);
1177				kauth_cred_unref(&my_new_cred);
1178				/* try again */
1179				my_cred = kauth_cred_proc_ref(p);
1180				continue;
1181			}
1182			p->p_ucred = my_new_cred;
1183			/* update cred on proc */
1184			PROC_UPDATE_CREDS_ONPROC(p);
1185			proc_unlock(p);
1186		}
1187		/*
1188		 * Drop old proc reference or our extra reference.
1189		 */
1190		kauth_cred_unref(&my_cred);
1191		break;
1192	}
1193
1194	/* Drop the reference taken by audit_session_new() above. */
1195	audit_unref_session(AU_SENTRY_PTR(as.as_aia_p));
1196
1197	/* Propagate the change from the process to the Mach task. */
1198	set_security_token(p);
1199
1200	return (0);
1201}
1202
1203/*
1204 * audit_session_self  (system call)
1205 *
1206 * Description: Obtain a Mach send right for the current session.
1207 *
1208 * Parameters:	p		Process calling audit_session_self().
1209 *
1210 * Returns:	*ret_port	Named Mach send right, which may be
1211 * 				MACH_PORT_NULL in the failure case.
1212 *
1213 * Errno:	0		Success
1214 * 		EINVAL		The calling process' session has not be set.
1215 * 		ESRCH		Bad process, can't get valid cred for process.
1216 * 		ENOMEM		Port allocation failed due to no free memory.
1217 */
1218int
1219audit_session_self(proc_t p, __unused struct audit_session_self_args *uap,
1220    mach_port_name_t *ret_port)
1221{
1222	ipc_port_t sendport = IPC_PORT_NULL;
1223	kauth_cred_t cred = NULL;
1224	auditinfo_addr_t *aia_p;
1225	au_sentry_t *se;
1226	int err = 0;
1227
1228	cred = kauth_cred_proc_ref(p);
1229	if (!IS_VALID_CRED(cred)) {
1230		err = ESRCH;
1231		goto done;
1232	}
1233
1234	aia_p = cred->cr_audit.as_aia_p;
1235	if (!IS_VALID_SESSION(aia_p)) {
1236		/* Can't join the default session. */
1237		err = EINVAL;
1238		goto done;
1239	}
1240
1241	se = AU_SENTRY_PTR(aia_p);
1242
1243	/*
1244	 * Processes that join using this mach port will inherit this process'
1245	 * pre-selection masks.
1246	 */
1247	if (se->se_port == IPC_PORT_NULL)
1248		bcopy(&cred->cr_audit.as_mask, &se->se_mask,
1249		    sizeof(se->se_mask));
1250
1251	/*
1252	 * Get a send right to the session's Mach port and insert it in the
1253	 * process' mach port namespace.
1254	 */
1255	sendport = audit_session_mksend(aia_p, &se->se_port);
1256	*ret_port = ipc_port_copyout_send(sendport, get_task_ipcspace(p->task));
1257
1258done:
1259	if (cred != NULL)
1260		kauth_cred_unref(&cred);
1261	if (err != 0)
1262		*ret_port = MACH_PORT_NULL;
1263	return (err);
1264}
1265
1266/*
1267 * audit_session_port  (system call)
1268 *
1269 * Description: Obtain a Mach send right for the given session ID.
1270 *
1271 * Parameters:	p		Process calling audit_session_port().
1272 *              uap->asid       The target audit session ID.  The special
1273 *              		value -1 can be used to target the process's
1274 *              		own session.
1275 *              uap->portnamep  User address at which to place port name.
1276 *
1277 * Returns:	0		Success
1278 * 		EINVAL		The calling process' session has not be set.
1279 * 		EINVAL		The given session ID could not be found.
1280 * 		EINVAL		The Mach port right could not be copied out.
1281 * 		ESRCH		Bad process, can't get valid cred for process.
1282 * 		EPERM		Only the superuser can reference sessions other
1283 * 				than the process's own.
1284 * 		ENOMEM		Port allocation failed due to no free memory.
1285 */
1286int
1287audit_session_port(proc_t p, struct audit_session_port_args *uap,
1288    __unused int *retval)
1289{
1290	ipc_port_t sendport = IPC_PORT_NULL;
1291	mach_port_name_t portname = MACH_PORT_NULL;
1292	kauth_cred_t cred = NULL;
1293	auditinfo_addr_t *aia_p = NULL;
1294	au_sentry_t *se = NULL;
1295	int err = 0;
1296
1297	/* Note: Currently this test will never be true, because
1298	 * ASSIGNED_ASID_MAX is effectively (uint32_t)-2.
1299	 */
1300	if (uap->asid != -1 && (uint32_t)uap->asid > ASSIGNED_ASID_MAX) {
1301		err = EINVAL;
1302		goto done;
1303	}
1304	cred = kauth_cred_proc_ref(p);
1305	if (!IS_VALID_CRED(cred)) {
1306		err = ESRCH;
1307		goto done;
1308	}
1309	aia_p = cred->cr_audit.as_aia_p;
1310
1311	/* Find the session corresponding to the requested audit
1312	 * session ID.  If found, take a reference on it so that
1313	 * the session is not dropped until the join is later done.
1314	 */
1315	if (uap->asid == (au_asid_t)-1 ||
1316	    uap->asid == aia_p->ai_asid) {
1317
1318		if (!IS_VALID_SESSION(aia_p)) {
1319			/* Can't join the default session. */
1320			err = EINVAL;
1321			goto done;
1322		}
1323
1324		/* No privilege is required to obtain a port for our
1325		 * own session.
1326		 */
1327		se = AU_SENTRY_PTR(aia_p);
1328		audit_ref_session(se);
1329	} else if (kauth_cred_issuser(cred)) {
1330		/* The superuser may obtain a port for any existing
1331		 * session.
1332		 */
1333		AUDIT_SENTRY_RLOCK();
1334		se = audit_session_find(uap->asid);
1335		AUDIT_SENTRY_RUNLOCK();
1336		if (NULL == se) {
1337			err = EINVAL;
1338			goto done;
1339		}
1340		aia_p = &se->se_auinfo;
1341	} else {
1342		err = EPERM;
1343		goto done;
1344	}
1345
1346	/*
1347	 * Processes that join using this mach port will inherit this process'
1348	 * pre-selection masks.
1349	 */
1350	if (se->se_port == IPC_PORT_NULL)
1351		bcopy(&cred->cr_audit.as_mask, &se->se_mask,
1352		    sizeof(se->se_mask));
1353
1354	/*
1355	 * Use the session reference to create a mach port reference for the
1356	 * session (at which point we are free to drop the session reference)
1357	 * and then copy out the mach port to the process' mach port namespace.
1358	 */
1359	sendport = audit_session_mksend(aia_p, &se->se_port);
1360	portname = ipc_port_copyout_send(sendport, get_task_ipcspace(p->task));
1361	if (!MACH_PORT_VALID(portname)) {
1362		err = EINVAL;
1363		goto done;
1364	}
1365	err = copyout(&portname, uap->portnamep, sizeof(mach_port_name_t));
1366done:
1367	if (cred != NULL)
1368		kauth_cred_unref(&cred);
1369	if (NULL != se)
1370		audit_unref_session(se);
1371	if (MACH_PORT_VALID(portname) && 0 != err)
1372                (void)mach_port_deallocate(get_task_ipcspace(p->task),
1373		    portname);
1374
1375	return (err);
1376}
1377
1378static int
1379audit_session_join_internal(proc_t p, ipc_port_t port, au_asid_t *new_asid)
1380{
1381	auditinfo_addr_t *new_aia_p, *old_aia_p;
1382	kauth_cred_t my_cred = NULL;
1383	au_asid_t old_asid;
1384	int err = 0;
1385
1386	*new_asid = AU_DEFAUDITSID;
1387
1388	if ((new_aia_p = audit_session_porttoaia(port)) == NULL) {
1389		err = EINVAL;
1390		goto done;
1391	}
1392
1393	proc_lock(p);
1394	kauth_cred_ref(p->p_ucred);
1395	my_cred = p->p_ucred;
1396	if (!IS_VALID_CRED(my_cred)) {
1397		kauth_cred_unref(&my_cred);
1398		proc_unlock(p);
1399		err = ESRCH;
1400		goto done;
1401	}
1402	old_aia_p = my_cred->cr_audit.as_aia_p;
1403	old_asid = old_aia_p->ai_asid;
1404	*new_asid = new_aia_p->ai_asid;
1405
1406	/*
1407	 * Add process in if not already in the session.
1408	 */
1409	if (*new_asid != old_asid) {
1410		kauth_cred_t my_new_cred;
1411		struct au_session new_as;
1412
1413		bcopy(&new_aia_p->ai_mask, &new_as.as_mask,
1414			sizeof(new_as.as_mask));
1415		new_as.as_aia_p = new_aia_p;
1416
1417		my_new_cred = kauth_cred_setauditinfo(my_cred, &new_as);
1418		p->p_ucred = my_new_cred;
1419		PROC_UPDATE_CREDS_ONPROC(p);
1420
1421		/* Increment the proc count of new session */
1422		audit_inc_procount(AU_SENTRY_PTR(new_aia_p));
1423
1424		proc_unlock(p);
1425
1426		/* Propagate the change from the process to the Mach task. */
1427		set_security_token(p);
1428
1429		/* Decrement the process count of the former session. */
1430		audit_dec_procount(AU_SENTRY_PTR(old_aia_p));
1431	} else  {
1432		proc_unlock(p);
1433	}
1434	kauth_cred_unref(&my_cred);
1435
1436done:
1437	if (port != IPC_PORT_NULL)
1438		ipc_port_release_send(port);
1439
1440	return (err);
1441}
1442
1443/*
1444 * audit_session_spawnjoin
1445 *
1446 * Description: posix_spawn() interface to audit_session_join_internal().
1447 *
1448 * Returns:	0		Success
1449 * 		EINVAL		Invalid Mach port name.
1450 * 		ESRCH		Invalid calling process/cred.
1451 */
1452int
1453audit_session_spawnjoin(proc_t p, ipc_port_t port)
1454{
1455	au_asid_t new_asid;
1456
1457	return (audit_session_join_internal(p, port, &new_asid));
1458}
1459
1460/*
1461 * audit_session_join  (system call)
1462 *
1463 * Description:	Join the session for a given Mach port send right.
1464 *
1465 * Parameters:	p		Process calling session join.
1466 * 		uap->port	A Mach send right.
1467 *
1468 * Returns:	*ret_asid	Audit session ID of new session.
1469 *				In the failure case the return value will be -1
1470 *				and 'errno' will be set to a non-zero value
1471 *				described below.
1472 *
1473 * Errno:	0		Success
1474 * 		EINVAL		Invalid Mach port name.
1475 * 		ESRCH		Invalid calling process/cred.
1476 */
1477int
1478audit_session_join(proc_t p, struct audit_session_join_args *uap,
1479    au_asid_t *ret_asid)
1480{
1481	ipc_port_t port = IPC_PORT_NULL;
1482	mach_port_name_t send = uap->port;
1483	int err = 0;
1484
1485
1486	if (ipc_object_copyin(get_task_ipcspace(p->task), send,
1487		MACH_MSG_TYPE_COPY_SEND, &port) != KERN_SUCCESS) {
1488		*ret_asid = AU_DEFAUDITSID;
1489		err = EINVAL;
1490	} else
1491		err = audit_session_join_internal(p, port, ret_asid);
1492
1493	return (err);
1494}
1495
1496/*
1497 * Audit session device.
1498 */
1499
1500/*
1501 * Free an audit sdev entry.
1502 */
1503static void
1504audit_sdev_entry_free(struct audit_sdev_entry *ase)
1505{
1506
1507	free(ase->ase_record, M_AUDIT_SDEV_ENTRY);
1508	free(ase, M_AUDIT_SDEV_ENTRY);
1509}
1510
1511/*
1512 * Append individual record to a queue.  Allocate queue-local buffer and
1513 * add to the queue.  If the queue is full or we can't allocate memory,
1514 * drop the newest record.
1515 */
1516static void
1517audit_sdev_append(struct audit_sdev *asdev, void *record, u_int record_len)
1518{
1519	struct audit_sdev_entry *ase;
1520
1521	AUDIT_SDEV_LOCK_ASSERT(asdev);
1522
1523	if (asdev->asdev_qlen >= asdev->asdev_qlimit) {
1524		asdev->asdev_drops++;
1525		audit_sdev_drops++;
1526		return;
1527	}
1528
1529	ase = malloc(sizeof (*ase), M_AUDIT_SDEV_ENTRY, M_NOWAIT | M_ZERO);
1530	if (NULL == ase) {
1531		asdev->asdev_drops++;
1532		audit_sdev_drops++;
1533		return;
1534	}
1535
1536	ase->ase_record = malloc(record_len, M_AUDIT_SDEV_ENTRY, M_NOWAIT);
1537	if (NULL == ase->ase_record) {
1538		free(ase, M_AUDIT_SDEV_ENTRY);
1539		asdev->asdev_drops++;
1540		audit_sdev_drops++;
1541		return;
1542	}
1543
1544	bcopy(record, ase->ase_record, record_len);
1545	ase->ase_record_len = record_len;
1546
1547	TAILQ_INSERT_TAIL(&asdev->asdev_queue, ase, ase_queue);
1548	asdev->asdev_inserts++;
1549	asdev->asdev_qlen++;
1550	asdev->asdev_qbyteslen += ase->ase_record_len;
1551	selwakeup(&asdev->asdev_selinfo);
1552	if (asdev->asdev_flags & AUDIT_SDEV_ASYNC)
1553		pgsigio(asdev->asdev_sigio, SIGIO);
1554
1555	cv_broadcast(&asdev->asdev_cv);
1556}
1557
1558/*
1559 * Submit an audit record to be queued in the audit session device.
1560 */
1561void
1562audit_sdev_submit(__unused au_id_t auid, __unused au_asid_t asid, void *record,
1563    u_int record_len)
1564{
1565	struct audit_sdev *asdev;
1566
1567	/*
1568	 * Lockless read to avoid lock overhead if sessio devices are not in
1569	 * use.
1570	 */
1571	if (NULL == TAILQ_FIRST(&audit_sdev_list))
1572		return;
1573
1574	AUDIT_SDEV_LIST_RLOCK();
1575	TAILQ_FOREACH(asdev, &audit_sdev_list, asdev_list) {
1576		AUDIT_SDEV_LOCK(asdev);
1577
1578		/*
1579		 * Only append to the sdev queue if the AUID and ASID match that
1580		 * of the process that opened this session device or if the
1581		 * ALLSESSIONS flag is set.
1582		 */
1583		if ((/* XXXss auid == asdev->asdev_auid && */
1584			asid == asdev->asdev_asid) ||
1585		    (asdev->asdev_flags & AUDIT_SDEV_ALLSESSIONS) != 0)
1586			audit_sdev_append(asdev, record, record_len);
1587		AUDIT_SDEV_UNLOCK(asdev);
1588	}
1589	AUDIT_SDEV_LIST_RUNLOCK();
1590
1591	/* Unlocked increment. */
1592	audit_sdev_records++;
1593}
1594
1595/*
1596 * Allocate a new audit sdev.  Connects the sdev, on succes, to the global
1597 * list and updates statistics.
1598 */
1599static struct audit_sdev *
1600audit_sdev_alloc(void)
1601{
1602	struct audit_sdev *asdev;
1603
1604	AUDIT_SDEV_LIST_WLOCK_ASSERT();
1605
1606	asdev = malloc(sizeof (*asdev), M_AUDIT_SDEV, M_WAITOK | M_ZERO);
1607	if (NULL == asdev)
1608		return (NULL);
1609
1610	asdev->asdev_qlimit = AUDIT_SDEV_QLIMIT_DEFAULT;
1611	TAILQ_INIT(&asdev->asdev_queue);
1612	AUDIT_SDEV_LOCK_INIT(asdev);
1613	AUDIT_SDEV_SX_LOCK_INIT(asdev);
1614	cv_init(&asdev->asdev_cv, "audit_sdev_cv");
1615
1616	/*
1617	 * Add to global list and update global statistics.
1618	 */
1619	TAILQ_INSERT_HEAD(&audit_sdev_list, asdev, asdev_list);
1620	audit_sdev_count++;
1621	audit_sdev_ever++;
1622
1623	return (asdev);
1624}
1625
1626/*
1627 * Flush all records currently present in an audit sdev.
1628 */
1629static void
1630audit_sdev_flush(struct audit_sdev *asdev)
1631{
1632	struct audit_sdev_entry *ase;
1633
1634	AUDIT_SDEV_LOCK_ASSERT(asdev);
1635
1636	while ((ase = TAILQ_FIRST(&asdev->asdev_queue)) != NULL) {
1637		TAILQ_REMOVE(&asdev->asdev_queue, ase, ase_queue);
1638		asdev->asdev_qbyteslen -= ase->ase_record_len;
1639		audit_sdev_entry_free(ase);
1640		asdev->asdev_qlen--;
1641	}
1642	asdev->asdev_qoffset = 0;
1643
1644	KASSERT(0 == asdev->asdev_qlen, ("audit_sdev_flush: asdev_qlen"));
1645	KASSERT(0 == asdev->asdev_qbyteslen,
1646	    ("audit_sdev_flush: asdev_qbyteslen"));
1647}
1648
1649/*
1650 * Free an audit sdev.
1651 */
1652static void
1653audit_sdev_free(struct audit_sdev *asdev)
1654{
1655
1656	AUDIT_SDEV_LIST_WLOCK_ASSERT();
1657	AUDIT_SDEV_LOCK_ASSERT(asdev);
1658
1659	/* XXXss - preselect hook here */
1660	audit_sdev_flush(asdev);
1661	cv_destroy(&asdev->asdev_cv);
1662	AUDIT_SDEV_SX_LOCK_DESTROY(asdev);
1663	AUDIT_SDEV_UNLOCK(asdev);
1664	AUDIT_SDEV_LOCK_DESTROY(asdev);
1665
1666	TAILQ_REMOVE(&audit_sdev_list, asdev, asdev_list);
1667	free(asdev, M_AUDIT_SDEV);
1668	audit_sdev_count--;
1669}
1670
1671/*
1672 * Get the auditinfo_addr of the proc and check to see if suser.  Will return
1673 * non-zero if not suser.
1674 */
1675static int
1676audit_sdev_get_aia(proc_t p, struct auditinfo_addr *aia_p)
1677{
1678	int error;
1679	kauth_cred_t scred;
1680
1681	scred = kauth_cred_proc_ref(p);
1682	error = suser(scred, &p->p_acflag);
1683
1684	if (NULL != aia_p)
1685		bcopy(scred->cr_audit.as_aia_p, aia_p, sizeof (*aia_p));
1686	kauth_cred_unref(&scred);
1687
1688	return (error);
1689}
1690
1691/*
1692 * Audit session dev open method.
1693 */
1694static int
1695audit_sdev_open(dev_t dev, __unused int flags,  __unused int devtype, proc_t p)
1696{
1697	struct audit_sdev *asdev;
1698	struct auditinfo_addr aia;
1699	int u;
1700
1701	u = minor(dev);
1702	if (u < 0 || u > MAX_AUDIT_SDEVS)
1703		return (ENXIO);
1704
1705	(void) audit_sdev_get_aia(p, &aia);
1706
1707	AUDIT_SDEV_LIST_WLOCK();
1708	asdev = audit_sdev_dtab[u];
1709	if (NULL == asdev) {
1710		asdev = audit_sdev_alloc();
1711		if (NULL == asdev) {
1712			AUDIT_SDEV_LIST_WUNLOCK();
1713			return (ENOMEM);
1714		}
1715		audit_sdev_dtab[u] = asdev;
1716	} else {
1717		KASSERT(asdev->asdev_open, ("audit_sdev_open: Already open"));
1718		AUDIT_SDEV_LIST_WUNLOCK();
1719		return (EBUSY);
1720	}
1721	asdev->asdev_open = 1;
1722	asdev->asdev_auid = aia.ai_auid;
1723	asdev->asdev_asid = aia.ai_asid;
1724	asdev->asdev_flags = 0;
1725
1726	AUDIT_SDEV_LIST_WUNLOCK();
1727
1728	return (0);
1729}
1730
1731/*
1732 * Audit session dev close method.
1733 */
1734static int
1735audit_sdev_close(dev_t dev, __unused int flags, __unused int devtype,
1736    __unused proc_t p)
1737{
1738	struct audit_sdev *asdev;
1739	int u;
1740
1741	u = minor(dev);
1742	asdev = audit_sdev_dtab[u];
1743
1744	KASSERT(asdev != NULL, ("audit_sdev_close: asdev == NULL"));
1745	KASSERT(asdev->asdev_open, ("audit_sdev_close: !asdev_open"));
1746
1747	AUDIT_SDEV_LIST_WLOCK();
1748	AUDIT_SDEV_LOCK(asdev);
1749	asdev->asdev_open = 0;
1750	audit_sdev_free(asdev);  /* sdev lock unlocked in audit_sdev_free() */
1751	audit_sdev_dtab[u] = NULL;
1752	AUDIT_SDEV_LIST_WUNLOCK();
1753
1754	return (0);
1755}
1756
1757/*
1758 * Audit session dev ioctl method.
1759 */
1760static int
1761audit_sdev_ioctl(dev_t dev, u_long cmd, caddr_t data,
1762    __unused int flag, proc_t p)
1763{
1764	struct audit_sdev *asdev;
1765	int error;
1766
1767	asdev = audit_sdev_dtab[minor(dev)];
1768	KASSERT(asdev != NULL, ("audit_sdev_ioctl: asdev == NULL"));
1769
1770	error = 0;
1771
1772	switch (cmd) {
1773	case FIONBIO:
1774		AUDIT_SDEV_LOCK(asdev);
1775		if (*(int *)data)
1776			asdev->asdev_flags |= AUDIT_SDEV_NBIO;
1777		else
1778			asdev->asdev_flags &= ~AUDIT_SDEV_NBIO;
1779		AUDIT_SDEV_UNLOCK(asdev);
1780		break;
1781
1782	case FIONREAD:
1783		AUDIT_SDEV_LOCK(asdev);
1784		*(int *)data = asdev->asdev_qbyteslen - asdev->asdev_qoffset;
1785		AUDIT_SDEV_UNLOCK(asdev);
1786		break;
1787
1788	case AUDITSDEV_GET_QLEN:
1789		*(u_int *)data = asdev->asdev_qlen;
1790		break;
1791
1792	case AUDITSDEV_GET_QLIMIT:
1793		*(u_int *)data = asdev->asdev_qlimit;
1794		break;
1795
1796	case AUDITSDEV_SET_QLIMIT:
1797		if (*(u_int *)data >= AUDIT_SDEV_QLIMIT_MIN ||
1798		    *(u_int *)data <= AUDIT_SDEV_QLIMIT_MAX) {
1799			asdev->asdev_qlimit = *(u_int *)data;
1800		} else
1801			error = EINVAL;
1802		break;
1803
1804	case AUDITSDEV_GET_QLIMIT_MIN:
1805		*(u_int *)data = AUDIT_SDEV_QLIMIT_MIN;
1806		break;
1807
1808	case AUDITSDEV_GET_QLIMIT_MAX:
1809		*(u_int *)data = AUDIT_SDEV_QLIMIT_MAX;
1810		break;
1811
1812	case AUDITSDEV_FLUSH:
1813		if (AUDIT_SDEV_SX_XLOCK_SIG(asdev) != 0)
1814			return (EINTR);
1815		AUDIT_SDEV_LOCK(asdev);
1816		audit_sdev_flush(asdev);
1817		AUDIT_SDEV_UNLOCK(asdev);
1818		AUDIT_SDEV_SX_XUNLOCK(asdev);
1819		break;
1820
1821	case AUDITSDEV_GET_MAXDATA:
1822		*(u_int *)data = MAXAUDITDATA;
1823		break;
1824
1825	/* XXXss these should be 64 bit, maybe. */
1826	case AUDITSDEV_GET_INSERTS:
1827		*(u_int *)data = asdev->asdev_inserts;
1828		break;
1829
1830	case AUDITSDEV_GET_READS:
1831		*(u_int *)data = asdev->asdev_reads;
1832		break;
1833
1834	case AUDITSDEV_GET_DROPS:
1835		*(u_int *)data = asdev->asdev_drops;
1836		break;
1837
1838	case AUDITSDEV_GET_ALLSESSIONS:
1839		error = audit_sdev_get_aia(p, NULL);
1840		if (error)
1841			break;
1842		*(u_int *)data = (asdev->asdev_flags & AUDIT_SDEV_ALLSESSIONS) ?
1843		    1 : 0;
1844		break;
1845
1846	case AUDITSDEV_SET_ALLSESSIONS:
1847		error = audit_sdev_get_aia(p, NULL);
1848		if (error)
1849			break;
1850
1851		AUDIT_SDEV_LOCK(asdev);
1852		if (*(int *)data)
1853			asdev->asdev_flags |= AUDIT_SDEV_ALLSESSIONS;
1854		else
1855			asdev->asdev_flags &= ~AUDIT_SDEV_ALLSESSIONS;
1856		AUDIT_SDEV_UNLOCK(asdev);
1857		break;
1858
1859	default:
1860		error = ENOTTY;
1861	}
1862
1863	return (error);
1864}
1865
1866/*
1867 * Audit session dev read method.
1868 */
1869static int
1870audit_sdev_read(dev_t dev, struct uio *uio, __unused int flag)
1871{
1872	struct audit_sdev_entry *ase;
1873	struct audit_sdev *asdev;
1874	u_int toread;
1875	int error;
1876
1877	asdev = audit_sdev_dtab[minor(dev)];
1878	KASSERT(NULL != asdev, ("audit_sdev_read: asdev == NULL"));
1879
1880	/*
1881	 * We hold a sleep lock over read and flush because we rely on the
1882	 * stability of a record in the queue during uiomove.
1883	 */
1884	if (0 != AUDIT_SDEV_SX_XLOCK_SIG(asdev))
1885		return (EINTR);
1886	AUDIT_SDEV_LOCK(asdev);
1887	while (TAILQ_EMPTY(&asdev->asdev_queue)) {
1888		if (asdev->asdev_flags & AUDIT_SDEV_NBIO) {
1889			AUDIT_SDEV_UNLOCK(asdev);
1890			AUDIT_SDEV_SX_XUNLOCK(asdev);
1891			return (EAGAIN);
1892		}
1893		error = cv_wait_sig(&asdev->asdev_cv, AUDIT_SDEV_MTX(asdev));
1894		if (error) {
1895			AUDIT_SDEV_UNLOCK(asdev);
1896			AUDIT_SDEV_SX_XUNLOCK(asdev);
1897			return (error);
1898		}
1899	}
1900
1901	/*
1902	 * Copy as many remaining bytes from the current record to userspace
1903	 * as we can. Keep processing records until we run out of records in
1904	 * the queue or until the user buffer runs out of space.
1905	 *
1906	 * We rely on the sleep lock to maintain ase's stability here.
1907	 */
1908	asdev->asdev_reads++;
1909	while ((ase = TAILQ_FIRST(&asdev->asdev_queue)) != NULL &&
1910	    uio_resid(uio) > 0) {
1911		AUDIT_SDEV_LOCK_ASSERT(asdev);
1912
1913		KASSERT(ase->ase_record_len > asdev->asdev_qoffset,
1914		    ("audit_sdev_read: record_len > qoffset (1)"));
1915		toread = MIN((int)(ase->ase_record_len - asdev->asdev_qoffset),
1916		    uio_resid(uio));
1917		AUDIT_SDEV_UNLOCK(asdev);
1918		error = uiomove((char *) ase->ase_record + asdev->asdev_qoffset,
1919		    toread, uio);
1920		if (error) {
1921			AUDIT_SDEV_SX_XUNLOCK(asdev);
1922			return (error);
1923		}
1924
1925		/*
1926		 * If the copy succeeded then update book-keeping, and if no
1927		 * bytes remain in the current record then free it.
1928		 */
1929		AUDIT_SDEV_LOCK(asdev);
1930		KASSERT(TAILQ_FIRST(&asdev->asdev_queue) == ase,
1931		    ("audit_sdev_read: queue out of sync after uiomove"));
1932		asdev->asdev_qoffset += toread;
1933		KASSERT(ase->ase_record_len >= asdev->asdev_qoffset,
1934		     ("audit_sdev_read: record_len >= qoffset (2)"));
1935		 if (asdev->asdev_qoffset == ase->ase_record_len) {
1936			 TAILQ_REMOVE(&asdev->asdev_queue, ase, ase_queue);
1937			 asdev->asdev_qbyteslen -= ase->ase_record_len;
1938			 audit_sdev_entry_free(ase);
1939			 asdev->asdev_qlen--;
1940			 asdev->asdev_qoffset = 0;
1941		 }
1942	}
1943	AUDIT_SDEV_UNLOCK(asdev);
1944	AUDIT_SDEV_SX_XUNLOCK(asdev);
1945	return (0);
1946}
1947
1948/*
1949 * Audit session device poll method.
1950 */
1951static int
1952audit_sdev_poll(dev_t dev, int events, void *wql, struct proc *p)
1953{
1954	struct audit_sdev *asdev;
1955	int revents;
1956
1957	revents = 0;
1958	asdev = audit_sdev_dtab[minor(dev)];
1959	KASSERT(NULL != asdev, ("audit_sdev_poll: asdev == NULL"));
1960
1961	if (events & (POLLIN | POLLRDNORM)) {
1962		AUDIT_SDEV_LOCK(asdev);
1963		if (NULL != TAILQ_FIRST(&asdev->asdev_queue))
1964			revents |= events & (POLLIN | POLLRDNORM);
1965		else
1966			selrecord(p, &asdev->asdev_selinfo, wql);
1967		AUDIT_SDEV_UNLOCK(asdev);
1968	}
1969	return (revents);
1970}
1971
1972/*
1973 * Audit sdev clone routine.  Provides a new minor number or returns -1.
1974 * This called with DEVFS_LOCK held.
1975 */
1976static int
1977audit_sdev_clone(__unused dev_t dev, int action)
1978{
1979	int i;
1980
1981	if (DEVFS_CLONE_ALLOC == action) {
1982		for(i = 0; i < MAX_AUDIT_SDEVS; i++)
1983			if (NULL == audit_sdev_dtab[i])
1984				return (i);
1985
1986		/*
1987		 * This really should return -1 here but that seems to
1988		 * hang things in devfs.  We instead return 0 and let
1989		 * audit_sdev_open tell userland the bad news.
1990		 */
1991		return (0);
1992	}
1993
1994	return (-1);
1995}
1996
1997static int
1998audit_sdev_init(void)
1999{
2000	dev_t dev;
2001
2002	TAILQ_INIT(&audit_sdev_list);
2003	AUDIT_SDEV_LIST_LOCK_INIT();
2004
2005	audit_sdev_major = cdevsw_add(-1, &audit_sdev_cdevsw);
2006	if (audit_sdev_major < 0)
2007		return (KERN_FAILURE);
2008
2009	dev = makedev(audit_sdev_major, 0);
2010	devnode = devfs_make_node_clone(dev, DEVFS_CHAR, UID_ROOT, GID_WHEEL,
2011	    0644, audit_sdev_clone, AUDIT_SDEV_NAME, 0);
2012
2013	if (NULL == devnode)
2014		return (KERN_FAILURE);
2015
2016	return (KERN_SUCCESS);
2017}
2018
2019/* XXXss
2020static int
2021audit_sdev_shutdown(void)
2022{
2023
2024	devfs_remove(devnode);
2025	(void) cdevsw_remove(audit_sdev_major, &audit_sdev_cdevsw);
2026
2027	return (KERN_SUCCESS);
2028}
2029*/
2030
2031#else
2032
2033int
2034audit_session_self(proc_t p, struct audit_session_self_args *uap,
2035    mach_port_name_t *ret_port)
2036{
2037#pragma unused(p, uap, ret_port)
2038
2039	return (ENOSYS);
2040}
2041
2042int
2043audit_session_join(proc_t p, struct audit_session_join_args *uap,
2044    au_asid_t *ret_asid)
2045{
2046#pragma unused(p, uap, ret_asid)
2047
2048	return (ENOSYS);
2049}
2050
2051int
2052audit_session_port(proc_t p, struct audit_session_port_args *uap, int *retval)
2053{
2054#pragma unused(p, uap, retval)
2055
2056	return (ENOSYS);
2057}
2058
2059#endif /* CONFIG_AUDIT */
2060