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