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