]> git.saurik.com Git - apple/xnu.git/blame - bsd/security/audit/audit_pipe.c
xnu-6153.141.1.tar.gz
[apple/xnu.git] / bsd / security / audit / audit_pipe.c
CommitLineData
b0d623f7
A
1/*-
2 * Copyright (c) 2006 Robert N. M. Watson
3 * Copyright (c) 2008-2009 Apple, Inc.
4 * All rights reserved.
5 *
6 * This software was developed by Robert Watson for the TrustedBSD Project.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND 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 THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR 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, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <stdarg.h>
31#include <sys/param.h>
32#include <sys/systm.h>
33#include <sys/kernel.h>
34#include <sys/fcntl.h>
35#include <sys/conf.h>
36#include <sys/poll.h>
37#include <sys/user.h>
38#include <sys/signalvar.h>
39#include <miscfs/devfs/devfs.h>
40
41#include <bsm/audit.h>
42#include <security/audit/audit.h>
43#include <security/audit/audit_ioctl.h>
44#include <security/audit/audit_bsd.h>
45#include <security/audit/audit_private.h>
46
47#if CONFIG_AUDIT
48/*
49 * Implementation of a clonable special device providing a live stream of BSM
50 * audit data. Consumers receive a "tee" of the system audit trail by
51 * default, but may also define alternative event selections using ioctls.
52 * This interface provides unreliable but timely access to audit events.
53 * Consumers should be very careful to avoid introducing event cycles.
54 */
55
56/*
57 * Memory types.
58 */
59static MALLOC_DEFINE(M_AUDIT_PIPE, "audit_pipe", "Audit pipes");
60static MALLOC_DEFINE(M_AUDIT_PIPE_ENTRY, "audit_pipeent",
61 "Audit pipe entries and buffers");
62static MALLOC_DEFINE(M_AUDIT_PIPE_PRESELECT, "audit_pipe_presel",
63 "Audit pipe preselection structure");
64
65/*
66 * Audit pipe buffer parameters.
67 */
0a7de745
A
68#define AUDIT_PIPE_QLIMIT_DEFAULT (128)
69#define AUDIT_PIPE_QLIMIT_MIN (1)
70#define AUDIT_PIPE_QLIMIT_MAX (1024)
b0d623f7
A
71
72/*
73 * Description of an entry in an audit_pipe.
74 */
75struct audit_pipe_entry {
0a7de745
A
76 void *ape_record;
77 u_int ape_record_len;
78 TAILQ_ENTRY(audit_pipe_entry) ape_queue;
b0d623f7
A
79};
80
81/*
82 * Audit pipes allow processes to express "interest" in the set of records
83 * that are delivered via the pipe. They do this in a similar manner to the
84 * mechanism for audit trail configuration, by expressing two global masks,
85 * and optionally expressing per-auid masks. The following data structure is
86 * the per-auid mask description. The global state is stored in the audit
87 * pipe data structure.
88 *
89 * We may want to consider a more space/time-efficient data structure once
90 * usage patterns for per-auid specifications are clear.
91 */
92struct audit_pipe_preselect {
0a7de745
A
93 au_id_t app_auid;
94 au_mask_t app_mask;
95 TAILQ_ENTRY(audit_pipe_preselect) app_list;
b0d623f7
A
96};
97
98/*
99 * Description of an individual audit_pipe. Consists largely of a bounded
100 * length queue.
101 */
0a7de745
A
102#define AUDIT_PIPE_ASYNC 0x00000001
103#define AUDIT_PIPE_NBIO 0x00000002
b0d623f7 104struct audit_pipe {
0a7de745
A
105 int ap_open; /* Device open? */
106 u_int ap_flags;
b0d623f7 107
0a7de745
A
108 struct selinfo ap_selinfo;
109 pid_t ap_sigio;
b0d623f7
A
110
111 /*
112 * Per-pipe mutex protecting most fields in this data structure.
113 */
0a7de745 114 struct mtx ap_mtx;
b0d623f7
A
115
116 /*
117 * Per-pipe sleep lock serializing user-generated reads and flushes.
118 * uiomove() is called to copy out the current head record's data
119 * while the record remains in the queue, so we prevent other threads
120 * from removing it using this lock.
121 */
0a7de745 122 struct slck ap_sx;
b0d623f7
A
123
124 /*
125 * Condition variable to signal when data has been delivered to a
126 * pipe.
127 */
0a7de745 128 struct cv ap_cv;
b0d623f7
A
129
130 /*
131 * Various queue-related variables: qlen and qlimit are a count of
132 * records in the queue; qbyteslen is the number of bytes of data
133 * across all records, and qoffset is the amount read so far of the
134 * first record in the queue. The number of bytes available for
135 * reading in the queue is qbyteslen - qoffset.
136 */
0a7de745
A
137 u_int ap_qlen;
138 u_int ap_qlimit;
139 u_int ap_qbyteslen;
140 u_int ap_qoffset;
b0d623f7
A
141
142 /*
143 * Per-pipe operation statistics.
144 */
0a7de745
A
145 u_int64_t ap_inserts; /* Records added. */
146 u_int64_t ap_reads; /* Records read. */
147 u_int64_t ap_drops; /* Records dropped. */
b0d623f7
A
148
149 /*
150 * Fields relating to pipe interest: global masks for unmatched
151 * processes (attributable, non-attributable), and a list of specific
152 * interest specifications by auid.
153 */
0a7de745
A
154 int ap_preselect_mode;
155 au_mask_t ap_preselect_flags;
156 au_mask_t ap_preselect_naflags;
157 TAILQ_HEAD(, audit_pipe_preselect) ap_preselect_list;
b0d623f7
A
158
159 /*
160 * Current pending record list. Protected by a combination of ap_mtx
161 * and ap_sx. Note particularly that *both* locks are required to
162 * remove a record from the head of the queue, as an in-progress read
163 * may sleep while copying and therefore cannot hold ap_mtx.
164 */
0a7de745 165 TAILQ_HEAD(, audit_pipe_entry) ap_queue;
b0d623f7
A
166
167 /*
168 * Global pipe list.
169 */
0a7de745 170 TAILQ_ENTRY(audit_pipe) ap_list;
b0d623f7
A
171};
172
0a7de745
A
173#define AUDIT_PIPE_LOCK(ap) mtx_lock(&(ap)->ap_mtx)
174#define AUDIT_PIPE_LOCK_ASSERT(ap) mtx_assert(&(ap)->ap_mtx, MA_OWNED)
175#define AUDIT_PIPE_LOCK_DESTROY(ap) mtx_destroy(&(ap)->ap_mtx)
176#define AUDIT_PIPE_LOCK_INIT(ap) mtx_init(&(ap)->ap_mtx, \
177 "audit_pipe_mtx", NULL, MTX_DEF)
178#define AUDIT_PIPE_UNLOCK(ap) mtx_unlock(&(ap)->ap_mtx)
179#define AUDIT_PIPE_MTX(ap) (&(ap)->ap_mtx)
b0d623f7 180
0a7de745
A
181#define AUDIT_PIPE_SX_LOCK_DESTROY(ap) slck_destroy(&(ap)->ap_sx)
182#define AUDIT_PIPE_SX_LOCK_INIT(ap) slck_init(&(ap)->ap_sx, "audit_pipe_sx")
183#define AUDIT_PIPE_SX_XLOCK_ASSERT(ap) slck_assert(&(ap)->ap_sx, SA_XLOCKED)
184#define AUDIT_PIPE_SX_XLOCK_SIG(ap) slck_lock_sig(&(ap)->ap_sx)
185#define AUDIT_PIPE_SX_XUNLOCK(ap) slck_unlock(&(ap)->ap_sx)
b0d623f7
A
186
187
188/*
189 * Global list of audit pipes, rwlock to protect it. Individual record
190 * queues on pipes are protected by per-pipe locks; these locks synchronize
191 * between threads walking the list to deliver to individual pipes and add/
192 * remove of pipes, and are mostly acquired for read.
193 */
0a7de745
A
194static TAILQ_HEAD(, audit_pipe) audit_pipe_list;
195static struct rwlock audit_pipe_lock;
196
197#define AUDIT_PIPE_LIST_LOCK_INIT() rw_init(&audit_pipe_lock, \
198 "audit_pipe_list_lock")
199#define AUDIT_PIPE_LIST_RLOCK() rw_rlock(&audit_pipe_lock)
200#define AUDIT_PIPE_LIST_RUNLOCK() rw_runlock(&audit_pipe_lock)
201#define AUDIT_PIPE_LIST_WLOCK() rw_wlock(&audit_pipe_lock)
202#define AUDIT_PIPE_LIST_WLOCK_ASSERT() rw_assert(&audit_pipe_lock, \
203 RA_WLOCKED)
204#define AUDIT_PIPE_LIST_WUNLOCK() rw_wunlock(&audit_pipe_lock)
b0d623f7
A
205
206/*
207 * Cloning related variables and constants.
208 */
0a7de745
A
209#define AUDIT_PIPE_NAME "auditpipe"
210#define MAX_AUDIT_PIPES 32
b0d623f7
A
211static int audit_pipe_major;
212
213/*
214 * dev_t doesn't have a pointer for "softc" data. So we have to keep track of
215 * it with the following global array (indexed by the minor number).
216 *
217 * XXX We may want to dynamically grow this as needed.
218 */
0a7de745 219static struct audit_pipe *audit_pipe_dtab[MAX_AUDIT_PIPES];
b0d623f7
A
220
221
222/*
223 * Special device methods and definition.
224 */
0a7de745
A
225static open_close_fcn_t audit_pipe_open;
226static open_close_fcn_t audit_pipe_close;
227static read_write_fcn_t audit_pipe_read;
228static ioctl_fcn_t audit_pipe_ioctl;
229static select_fcn_t audit_pipe_poll;
b0d623f7
A
230
231static struct cdevsw audit_pipe_cdevsw = {
232 .d_open = audit_pipe_open,
233 .d_close = audit_pipe_close,
234 .d_read = audit_pipe_read,
235 .d_write = eno_rdwrt,
236 .d_ioctl = audit_pipe_ioctl,
237 .d_stop = eno_stop,
238 .d_reset = eno_reset,
239 .d_ttys = NULL,
240 .d_select = audit_pipe_poll,
241 .d_mmap = eno_mmap,
242 .d_strategy = eno_strat,
243 .d_type = 0
244};
245
246/*
247 * Some global statistics on audit pipes.
248 */
0a7de745
A
249static int audit_pipe_count; /* Current number of pipes. */
250static u_int64_t audit_pipe_ever; /* Pipes ever allocated. */
251static u_int64_t audit_pipe_records; /* Records seen. */
252static u_int64_t audit_pipe_drops; /* Global record drop count. */
b0d623f7
A
253
254/*
255 * Free an audit pipe entry.
256 */
257static void
258audit_pipe_entry_free(struct audit_pipe_entry *ape)
259{
b0d623f7
A
260 free(ape->ape_record, M_AUDIT_PIPE_ENTRY);
261 free(ape, M_AUDIT_PIPE_ENTRY);
262}
263
264/*
265 * Find an audit pipe preselection specification for an auid, if any.
266 */
267static struct audit_pipe_preselect *
268audit_pipe_preselect_find(struct audit_pipe *ap, au_id_t auid)
269{
270 struct audit_pipe_preselect *app;
271
272 AUDIT_PIPE_LOCK_ASSERT(ap);
273
274 TAILQ_FOREACH(app, &ap->ap_preselect_list, app_list) {
0a7de745
A
275 if (app->app_auid == auid) {
276 return app;
277 }
b0d623f7 278 }
0a7de745 279 return NULL;
b0d623f7
A
280}
281
282/*
283 * Query the per-pipe mask for a specific auid.
284 */
285static int
286audit_pipe_preselect_get(struct audit_pipe *ap, au_id_t auid,
287 au_mask_t *maskp)
288{
289 struct audit_pipe_preselect *app;
290 int error;
291
292 AUDIT_PIPE_LOCK(ap);
293 app = audit_pipe_preselect_find(ap, auid);
294 if (app != NULL) {
295 *maskp = app->app_mask;
296 error = 0;
0a7de745 297 } else {
b0d623f7 298 error = ENOENT;
0a7de745 299 }
b0d623f7 300 AUDIT_PIPE_UNLOCK(ap);
0a7de745 301 return error;
b0d623f7
A
302}
303
304/*
305 * Set the per-pipe mask for a specific auid. Add a new entry if needed;
306 * otherwise, update the current entry.
307 */
308static void
309audit_pipe_preselect_set(struct audit_pipe *ap, au_id_t auid, au_mask_t mask)
310{
311 struct audit_pipe_preselect *app, *app_new;
312
313 /*
314 * Pessimistically assume that the auid doesn't already have a mask
315 * set, and allocate. We will free it if it is unneeded.
316 */
317 app_new = malloc(sizeof(*app_new), M_AUDIT_PIPE_PRESELECT, M_WAITOK);
318 AUDIT_PIPE_LOCK(ap);
319 app = audit_pipe_preselect_find(ap, auid);
320 if (app == NULL) {
321 app = app_new;
322 app_new = NULL;
323 app->app_auid = auid;
324 TAILQ_INSERT_TAIL(&ap->ap_preselect_list, app, app_list);
325 }
326 app->app_mask = mask;
327 AUDIT_PIPE_UNLOCK(ap);
0a7de745 328 if (app_new != NULL) {
b0d623f7 329 free(app_new, M_AUDIT_PIPE_PRESELECT);
0a7de745 330 }
b0d623f7
A
331}
332
333/*
334 * Delete a per-auid mask on an audit pipe.
335 */
336static int
337audit_pipe_preselect_delete(struct audit_pipe *ap, au_id_t auid)
338{
339 struct audit_pipe_preselect *app;
340 int error;
341
342 AUDIT_PIPE_LOCK(ap);
343 app = audit_pipe_preselect_find(ap, auid);
344 if (app != NULL) {
345 TAILQ_REMOVE(&ap->ap_preselect_list, app, app_list);
346 error = 0;
0a7de745 347 } else {
b0d623f7 348 error = ENOENT;
0a7de745 349 }
b0d623f7 350 AUDIT_PIPE_UNLOCK(ap);
0a7de745 351 if (app != NULL) {
b0d623f7 352 free(app, M_AUDIT_PIPE_PRESELECT);
0a7de745
A
353 }
354 return error;
b0d623f7
A
355}
356
357/*
358 * Delete all per-auid masks on an audit pipe.
359 */
360static void
361audit_pipe_preselect_flush_locked(struct audit_pipe *ap)
362{
363 struct audit_pipe_preselect *app;
364
365 AUDIT_PIPE_LOCK_ASSERT(ap);
366
367 while ((app = TAILQ_FIRST(&ap->ap_preselect_list)) != NULL) {
368 TAILQ_REMOVE(&ap->ap_preselect_list, app, app_list);
369 free(app, M_AUDIT_PIPE_PRESELECT);
370 }
371}
372
373static void
374audit_pipe_preselect_flush(struct audit_pipe *ap)
375{
b0d623f7
A
376 AUDIT_PIPE_LOCK(ap);
377 audit_pipe_preselect_flush_locked(ap);
378 AUDIT_PIPE_UNLOCK(ap);
379}
380
381/*-
382 * Determine whether a specific audit pipe matches a record with these
383 * properties. Algorithm is as follows:
384 *
385 * - If the pipe is configured to track the default trail configuration, then
386 * use the results of global preselection matching.
387 * - If not, search for a specifically configured auid entry matching the
388 * event. If an entry is found, use that.
389 * - Otherwise, use the default flags or naflags configured for the pipe.
390 */
391static int
392audit_pipe_preselect_check(struct audit_pipe *ap, au_id_t auid,
393 au_event_t event, au_class_t class, int sorf, int trail_preselect)
394{
395 struct audit_pipe_preselect *app;
396
397 AUDIT_PIPE_LOCK_ASSERT(ap);
398
399 switch (ap->ap_preselect_mode) {
400 case AUDITPIPE_PRESELECT_MODE_TRAIL:
0a7de745 401 return trail_preselect;
b0d623f7
A
402
403 case AUDITPIPE_PRESELECT_MODE_LOCAL:
404 app = audit_pipe_preselect_find(ap, auid);
405 if (app == NULL) {
0a7de745
A
406 if (auid == (uid_t)AU_DEFAUDITID) {
407 return au_preselect(event, class,
408 &ap->ap_preselect_naflags, sorf);
409 } else {
410 return au_preselect(event, class,
411 &ap->ap_preselect_flags, sorf);
412 }
413 } else {
414 return au_preselect(event, class, &app->app_mask,
415 sorf);
416 }
b0d623f7
A
417
418 default:
419 panic("audit_pipe_preselect_check: mode %d",
420 ap->ap_preselect_mode);
421 }
422
0a7de745 423 return 0;
b0d623f7
A
424}
425
426/*
427 * Determine whether there exists a pipe interested in a record with specific
428 * properties.
429 */
430int
431audit_pipe_preselect(au_id_t auid, au_event_t event, au_class_t class,
432 int sorf, int trail_preselect)
433{
434 struct audit_pipe *ap;
435
436 /* Lockless read to avoid acquiring the global lock if not needed. */
0a7de745
A
437 if (TAILQ_EMPTY(&audit_pipe_list)) {
438 return 0;
439 }
b0d623f7
A
440
441 AUDIT_PIPE_LIST_RLOCK();
442 TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) {
0a7de745 443 AUDIT_PIPE_LOCK(ap);
b0d623f7
A
444 if (audit_pipe_preselect_check(ap, auid, event, class, sorf,
445 trail_preselect)) {
446 AUDIT_PIPE_UNLOCK(ap);
447 AUDIT_PIPE_LIST_RUNLOCK();
0a7de745 448 return 1;
b0d623f7
A
449 }
450 AUDIT_PIPE_UNLOCK(ap);
451 }
452 AUDIT_PIPE_LIST_RUNLOCK();
0a7de745 453 return 0;
b0d623f7
A
454}
455
456/*
457 * Append individual record to a queue -- allocate queue-local buffer, and
458 * add to the queue. If the queue is full or we can't allocate memory, drop
459 * the newest record.
460 */
461static void
462audit_pipe_append(struct audit_pipe *ap, void *record, u_int record_len)
463{
464 struct audit_pipe_entry *ape;
465
466 AUDIT_PIPE_LOCK_ASSERT(ap);
467
468 if (ap->ap_qlen >= ap->ap_qlimit) {
469 ap->ap_drops++;
470 audit_pipe_drops++;
471 return;
472 }
473
474 ape = malloc(sizeof(*ape), M_AUDIT_PIPE_ENTRY, M_NOWAIT | M_ZERO);
475 if (ape == NULL) {
476 ap->ap_drops++;
477 audit_pipe_drops++;
478 return;
479 }
480
481 ape->ape_record = malloc(record_len, M_AUDIT_PIPE_ENTRY, M_NOWAIT);
482 if (ape->ape_record == NULL) {
483 free(ape, M_AUDIT_PIPE_ENTRY);
484 ap->ap_drops++;
485 audit_pipe_drops++;
486 return;
487 }
488
489 bcopy(record, ape->ape_record, record_len);
490 ape->ape_record_len = record_len;
491
492 TAILQ_INSERT_TAIL(&ap->ap_queue, ape, ape_queue);
493 ap->ap_inserts++;
494 ap->ap_qlen++;
495 ap->ap_qbyteslen += ape->ape_record_len;
496 selwakeup(&ap->ap_selinfo);
0a7de745 497 if (ap->ap_flags & AUDIT_PIPE_ASYNC) {
b0d623f7 498 pgsigio(ap->ap_sigio, SIGIO);
0a7de745 499 }
b0d623f7
A
500#if 0 /* XXX - fix select */
501 selwakeuppri(&ap->ap_selinfo, PSOCK);
502 KNOTE_LOCKED(&ap->ap_selinfo.si_note, 0);
0a7de745 503 if (ap->ap_flags & AUDIT_PIPE_ASYNC) {
b0d623f7 504 pgsigio(&ap->ap_sigio, SIGIO, 0);
0a7de745 505 }
b0d623f7
A
506#endif
507 cv_broadcast(&ap->ap_cv);
508}
509
510/*
511 * audit_pipe_submit(): audit_worker submits audit records via this
512 * interface, which arranges for them to be delivered to pipe queues.
513 */
514void
515audit_pipe_submit(au_id_t auid, au_event_t event, au_class_t class, int sorf,
516 int trail_select, void *record, u_int record_len)
517{
518 struct audit_pipe *ap;
519
520 /*
521 * Lockless read to avoid lock overhead if pipes are not in use.
522 */
0a7de745 523 if (TAILQ_FIRST(&audit_pipe_list) == NULL) {
b0d623f7 524 return;
0a7de745 525 }
b0d623f7
A
526
527 AUDIT_PIPE_LIST_RLOCK();
528 TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) {
529 AUDIT_PIPE_LOCK(ap);
530 if (audit_pipe_preselect_check(ap, auid, event, class, sorf,
0a7de745 531 trail_select)) {
b0d623f7 532 audit_pipe_append(ap, record, record_len);
0a7de745 533 }
b0d623f7
A
534 AUDIT_PIPE_UNLOCK(ap);
535 }
536 AUDIT_PIPE_LIST_RUNLOCK();
537
538 /* Unlocked increment. */
539 audit_pipe_records++;
540}
541
542/*
543 * audit_pipe_submit_user(): the same as audit_pipe_submit(), except that
544 * since we don't currently have selection information available, it is
545 * delivered to the pipe unconditionally.
546 *
547 * XXXRW: This is a bug. The BSM check routine for submitting a user record
548 * should parse that information and return it.
549 */
550void
551audit_pipe_submit_user(void *record, u_int record_len)
552{
553 struct audit_pipe *ap;
554
555 /*
556 * Lockless read to avoid lock overhead if pipes are not in use.
557 */
0a7de745 558 if (TAILQ_FIRST(&audit_pipe_list) == NULL) {
b0d623f7 559 return;
0a7de745 560 }
b0d623f7
A
561
562 AUDIT_PIPE_LIST_RLOCK();
563 TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) {
564 AUDIT_PIPE_LOCK(ap);
565 audit_pipe_append(ap, record, record_len);
566 AUDIT_PIPE_UNLOCK(ap);
567 }
568 AUDIT_PIPE_LIST_RUNLOCK();
569
570 /* Unlocked increment. */
571 audit_pipe_records++;
572}
573
574/*
575 * Allocate a new audit pipe. Connects the pipe, on success, to the global
576 * list and updates statistics.
577 */
578static struct audit_pipe *
579audit_pipe_alloc(void)
580{
581 struct audit_pipe *ap;
582
583 AUDIT_PIPE_LIST_WLOCK_ASSERT();
584
316670eb 585 ap = malloc(sizeof(*ap), M_AUDIT_PIPE, M_WAITOK | M_ZERO);
0a7de745
A
586 if (ap == NULL) {
587 return NULL;
588 }
b0d623f7
A
589
590 ap->ap_qlimit = AUDIT_PIPE_QLIMIT_DEFAULT;
591 TAILQ_INIT(&ap->ap_queue);
592#ifndef __APPLE__
593 knlist_init(&ap->ap_selinfo.si_note, AUDIT_PIPE_MTX(ap), NULL, NULL,
594 NULL);
595#endif
596 AUDIT_PIPE_LOCK_INIT(ap);
597 AUDIT_PIPE_SX_LOCK_INIT(ap);
598 cv_init(&ap->ap_cv, "audit_pipe");
599
600 /*
601 * Default flags, naflags, and auid-specific preselection settings to
602 * 0. Initialize the mode to the global trail so that if praudit(1)
603 * is run on /dev/auditpipe, it sees events associated with the
604 * default trail. Pipe-aware application can clear the flag, set
605 * custom masks, and flush the pipe as needed.
606 */
607 bzero(&ap->ap_preselect_flags, sizeof(ap->ap_preselect_flags));
608 bzero(&ap->ap_preselect_naflags, sizeof(ap->ap_preselect_naflags));
609 TAILQ_INIT(&ap->ap_preselect_list);
610 ap->ap_preselect_mode = AUDITPIPE_PRESELECT_MODE_TRAIL;
611
612 /*
613 * Add to global list and update global statistics.
614 */
615 TAILQ_INSERT_HEAD(&audit_pipe_list, ap, ap_list);
616 audit_pipe_count++;
617 audit_pipe_ever++;
618
0a7de745 619 return ap;
b0d623f7
A
620}
621
622/*
623 * Flush all records currently present in an audit pipe; assume mutex is held.
624 */
625static void
626audit_pipe_flush(struct audit_pipe *ap)
627{
628 struct audit_pipe_entry *ape;
629
630 AUDIT_PIPE_LOCK_ASSERT(ap);
631
632 while ((ape = TAILQ_FIRST(&ap->ap_queue)) != NULL) {
633 TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue);
634 ap->ap_qbyteslen -= ape->ape_record_len;
635 audit_pipe_entry_free(ape);
636 ap->ap_qlen--;
637 }
638 ap->ap_qoffset = 0;
639
640 KASSERT(ap->ap_qlen == 0, ("audit_pipe_free: ap_qbyteslen"));
641 KASSERT(ap->ap_qbyteslen == 0, ("audit_pipe_flush: ap_qbyteslen"));
642}
643
644/*
645 * Free an audit pipe; this means freeing all preselection state and all
646 * records in the pipe. Assumes global write lock and pipe mutex are held to
647 * revent any new records from being inserted during the free, and that the
648 * audit pipe is still on the global list.
649 */
650static void
651audit_pipe_free(struct audit_pipe *ap)
652{
b0d623f7
A
653 AUDIT_PIPE_LIST_WLOCK_ASSERT();
654 AUDIT_PIPE_LOCK_ASSERT(ap);
655
656 audit_pipe_preselect_flush_locked(ap);
657 audit_pipe_flush(ap);
658 cv_destroy(&ap->ap_cv);
659 AUDIT_PIPE_SX_LOCK_DESTROY(ap);
39236c6e 660 AUDIT_PIPE_UNLOCK(ap);
b0d623f7
A
661 AUDIT_PIPE_LOCK_DESTROY(ap);
662#ifndef __APPLE__
663 knlist_destroy(&ap->ap_selinfo.si_note);
664#endif
665 TAILQ_REMOVE(&audit_pipe_list, ap, ap_list);
666 free(ap, M_AUDIT_PIPE);
667 audit_pipe_count--;
668}
669
670/*
671 * Audit pipe clone routine -- provides a new minor number, or to return (-1),
672 * if one can't be provided. Called with DEVFS_LOCK held.
673 */
674static int
675audit_pipe_clone(__unused dev_t dev, int action)
676{
677 int i;
678
679 if (action == DEVFS_CLONE_ALLOC) {
0a7de745
A
680 for (i = 0; i < MAX_AUDIT_PIPES; i++) {
681 if (audit_pipe_dtab[i] == NULL) {
682 return i;
683 }
684 }
b0d623f7
A
685
686 /*
687 * XXX Should really return -1 here but that seems to hang
688 * things in devfs. Instead return 0 and let _open() tell
689 * userland the bad news.
690 */
0a7de745 691 return 0;
b0d623f7
A
692 }
693
0a7de745 694 return -1;
b0d623f7
A
695}
696
697/*
698 * Audit pipe open method. Explicit privilege check isn't used as this
699 * allows file permissions on the special device to be used to grant audit
700 * review access. Those file permissions should be managed carefully.
701 */
702static int
0a7de745 703audit_pipe_open(dev_t dev, __unused int flags, __unused int devtype,
b0d623f7
A
704 __unused proc_t p)
705{
706 struct audit_pipe *ap;
707 int u;
708
709 u = minor(dev);
0a7de745
A
710 if (u < 0 || u >= MAX_AUDIT_PIPES) {
711 return ENXIO;
712 }
b0d623f7
A
713
714 AUDIT_PIPE_LIST_WLOCK();
715 ap = audit_pipe_dtab[u];
716 if (ap == NULL) {
717 ap = audit_pipe_alloc();
718 if (ap == NULL) {
719 AUDIT_PIPE_LIST_WUNLOCK();
0a7de745 720 return ENOMEM;
b0d623f7
A
721 }
722 audit_pipe_dtab[u] = ap;
723 } else {
724 KASSERT(ap->ap_open, ("audit_pipe_open: ap && !ap_open"));
725 AUDIT_PIPE_LIST_WUNLOCK();
0a7de745 726 return EBUSY;
b0d623f7
A
727 }
728 ap->ap_open = 1;
729 AUDIT_PIPE_LIST_WUNLOCK();
730#ifndef __APPLE__
731 fsetown(td->td_proc->p_pid, &ap->ap_sigio);
732#endif
0a7de745 733 return 0;
b0d623f7
A
734}
735
736/*
737 * Close audit pipe, tear down all records, etc.
738 */
739static int
740audit_pipe_close(dev_t dev, __unused int flags, __unused int devtype,
741 __unused proc_t p)
742{
743 struct audit_pipe *ap;
744 int u;
745
746 u = minor(dev);
747 ap = audit_pipe_dtab[u];
748 KASSERT(ap != NULL, ("audit_pipe_close: ap == NULL"));
749 KASSERT(ap->ap_open, ("audit_pipe_close: !ap_open"));
750
751#ifndef __APPLE__
752 funsetown(&ap->ap_sigio);
753#endif
754 AUDIT_PIPE_LIST_WLOCK();
755 AUDIT_PIPE_LOCK(ap);
756 ap->ap_open = 0;
757 audit_pipe_free(ap);
758 audit_pipe_dtab[u] = NULL;
759 AUDIT_PIPE_LIST_WUNLOCK();
0a7de745 760 return 0;
b0d623f7
A
761}
762
763/*
764 * Audit pipe ioctl() routine. Handle file descriptor and audit pipe layer
765 * commands.
766 */
767static int
768audit_pipe_ioctl(dev_t dev, u_long cmd, caddr_t data,
769 __unused int flag, __unused proc_t p)
770{
771 struct auditpipe_ioctl_preselect *aip;
772 struct audit_pipe *ap;
773 au_mask_t *maskp;
774 int error, mode;
775 au_id_t auid;
776
777 ap = audit_pipe_dtab[minor(dev)];
778 KASSERT(ap != NULL, ("audit_pipe_ioctl: ap == NULL"));
779
780 /*
781 * Audit pipe ioctls: first come standard device node ioctls, then
782 * manipulation of pipe settings, and finally, statistics query
783 * ioctls.
784 */
785 switch (cmd) {
786 case FIONBIO:
787 AUDIT_PIPE_LOCK(ap);
0a7de745 788 if (*(int *)data) {
b0d623f7 789 ap->ap_flags |= AUDIT_PIPE_NBIO;
0a7de745 790 } else {
b0d623f7 791 ap->ap_flags &= ~AUDIT_PIPE_NBIO;
0a7de745 792 }
b0d623f7
A
793 AUDIT_PIPE_UNLOCK(ap);
794 error = 0;
795 break;
796
797 case FIONREAD:
798 AUDIT_PIPE_LOCK(ap);
799 *(int *)data = ap->ap_qbyteslen - ap->ap_qoffset;
800 AUDIT_PIPE_UNLOCK(ap);
801 error = 0;
802 break;
803
804 case FIOASYNC:
805 AUDIT_PIPE_LOCK(ap);
0a7de745 806 if (*(int *)data) {
b0d623f7 807 ap->ap_flags |= AUDIT_PIPE_ASYNC;
0a7de745 808 } else {
b0d623f7 809 ap->ap_flags &= ~AUDIT_PIPE_ASYNC;
0a7de745 810 }
b0d623f7
A
811 AUDIT_PIPE_UNLOCK(ap);
812 error = 0;
813 break;
814
815#ifndef __APPLE__
816 case FIOSETOWN:
817 error = fsetown(*(int *)data, &ap->ap_sigio);
818 break;
819
820 case FIOGETOWN:
821 *(int *)data = fgetown(&ap->ap_sigio);
822 error = 0;
823 break;
824#endif /* !__APPLE__ */
825
826 case AUDITPIPE_GET_QLEN:
827 *(u_int *)data = ap->ap_qlen;
828 error = 0;
829 break;
830
831 case AUDITPIPE_GET_QLIMIT:
832 *(u_int *)data = ap->ap_qlimit;
833 error = 0;
834 break;
835
836 case AUDITPIPE_SET_QLIMIT:
837 /* Lockless integer write. */
838 if (*(u_int *)data >= AUDIT_PIPE_QLIMIT_MIN ||
839 *(u_int *)data <= AUDIT_PIPE_QLIMIT_MAX) {
840 ap->ap_qlimit = *(u_int *)data;
841 error = 0;
0a7de745 842 } else {
b0d623f7 843 error = EINVAL;
0a7de745 844 }
b0d623f7
A
845 break;
846
847 case AUDITPIPE_GET_QLIMIT_MIN:
848 *(u_int *)data = AUDIT_PIPE_QLIMIT_MIN;
849 error = 0;
850 break;
851
852 case AUDITPIPE_GET_QLIMIT_MAX:
853 *(u_int *)data = AUDIT_PIPE_QLIMIT_MAX;
854 error = 0;
855 break;
856
857 case AUDITPIPE_GET_PRESELECT_FLAGS:
858 AUDIT_PIPE_LOCK(ap);
859 maskp = (au_mask_t *)data;
860 *maskp = ap->ap_preselect_flags;
861 AUDIT_PIPE_UNLOCK(ap);
862 error = 0;
863 break;
864
865 case AUDITPIPE_SET_PRESELECT_FLAGS:
866 AUDIT_PIPE_LOCK(ap);
867 maskp = (au_mask_t *)data;
868 ap->ap_preselect_flags = *maskp;
869 AUDIT_CHECK_IF_KEVENTS_MASK(ap->ap_preselect_flags);
870 AUDIT_PIPE_UNLOCK(ap);
871 error = 0;
872 break;
873
874 case AUDITPIPE_GET_PRESELECT_NAFLAGS:
875 AUDIT_PIPE_LOCK(ap);
876 maskp = (au_mask_t *)data;
877 *maskp = ap->ap_preselect_naflags;
878 AUDIT_PIPE_UNLOCK(ap);
879 error = 0;
880 break;
881
882 case AUDITPIPE_SET_PRESELECT_NAFLAGS:
883 AUDIT_PIPE_LOCK(ap);
884 maskp = (au_mask_t *)data;
885 ap->ap_preselect_naflags = *maskp;
886 AUDIT_CHECK_IF_KEVENTS_MASK(ap->ap_preselect_naflags);
887 AUDIT_PIPE_UNLOCK(ap);
888 error = 0;
889 break;
890
891 case AUDITPIPE_GET_PRESELECT_AUID:
892 aip = (struct auditpipe_ioctl_preselect *)data;
893 error = audit_pipe_preselect_get(ap, aip->aip_auid,
894 &aip->aip_mask);
895 break;
896
897 case AUDITPIPE_SET_PRESELECT_AUID:
898 aip = (struct auditpipe_ioctl_preselect *)data;
899 audit_pipe_preselect_set(ap, aip->aip_auid, aip->aip_mask);
900 error = 0;
901 break;
902
903 case AUDITPIPE_DELETE_PRESELECT_AUID:
904 auid = *(au_id_t *)data;
905 error = audit_pipe_preselect_delete(ap, auid);
906 break;
907
908 case AUDITPIPE_FLUSH_PRESELECT_AUID:
909 audit_pipe_preselect_flush(ap);
910 error = 0;
911 break;
912
913 case AUDITPIPE_GET_PRESELECT_MODE:
914 AUDIT_PIPE_LOCK(ap);
915 *(int *)data = ap->ap_preselect_mode;
916 AUDIT_PIPE_UNLOCK(ap);
917 error = 0;
918 break;
919
920 case AUDITPIPE_SET_PRESELECT_MODE:
921 mode = *(int *)data;
922 switch (mode) {
923 case AUDITPIPE_PRESELECT_MODE_TRAIL:
924 case AUDITPIPE_PRESELECT_MODE_LOCAL:
925 AUDIT_PIPE_LOCK(ap);
926 ap->ap_preselect_mode = mode;
927 AUDIT_PIPE_UNLOCK(ap);
928 error = 0;
929 break;
930
931 default:
932 error = EINVAL;
933 }
934 break;
935
936 case AUDITPIPE_FLUSH:
0a7de745
A
937 if (AUDIT_PIPE_SX_XLOCK_SIG(ap) != 0) {
938 return EINTR;
939 }
b0d623f7
A
940 AUDIT_PIPE_LOCK(ap);
941 audit_pipe_flush(ap);
942 AUDIT_PIPE_UNLOCK(ap);
943 AUDIT_PIPE_SX_XUNLOCK(ap);
944 error = 0;
945 break;
946
947 case AUDITPIPE_GET_MAXAUDITDATA:
948 *(u_int *)data = MAXAUDITDATA;
949 error = 0;
950 break;
951
952 case AUDITPIPE_GET_INSERTS:
953 *(u_int *)data = ap->ap_inserts;
954 error = 0;
955 break;
956
957 case AUDITPIPE_GET_READS:
958 *(u_int *)data = ap->ap_reads;
959 error = 0;
960 break;
961
962 case AUDITPIPE_GET_DROPS:
963 *(u_int *)data = ap->ap_drops;
964 error = 0;
965 break;
966
967 case AUDITPIPE_GET_TRUNCATES:
968 *(u_int *)data = 0;
969 error = 0;
970 break;
971
972 default:
973 error = ENOTTY;
974 }
0a7de745 975 return error;
b0d623f7
A
976}
977
978/*
979 * Audit pipe read. Read one or more partial or complete records to user
980 * memory.
981 */
982static int
983audit_pipe_read(dev_t dev, struct uio *uio, __unused int flag)
984{
985 struct audit_pipe_entry *ape;
986 struct audit_pipe *ap;
987 u_int toread;
988 int error;
989
990 ap = audit_pipe_dtab[minor(dev)];
991 KASSERT(ap != NULL, ("audit_pipe_read: ap == NULL"));
992
993 /*
994 * We hold an sleep lock over read and flush because we rely on the
995 * stability of a record in the queue during uiomove(9).
996 */
0a7de745
A
997 if (AUDIT_PIPE_SX_XLOCK_SIG(ap) != 0) {
998 return EINTR;
999 }
b0d623f7
A
1000 AUDIT_PIPE_LOCK(ap);
1001 while (TAILQ_EMPTY(&ap->ap_queue)) {
1002 if (ap->ap_flags & AUDIT_PIPE_NBIO) {
1003 AUDIT_PIPE_UNLOCK(ap);
1004 AUDIT_PIPE_SX_XUNLOCK(ap);
0a7de745 1005 return EAGAIN;
b0d623f7
A
1006 }
1007 error = cv_wait_sig(&ap->ap_cv, AUDIT_PIPE_MTX(ap));
1008 if (error) {
1009 AUDIT_PIPE_UNLOCK(ap);
1010 AUDIT_PIPE_SX_XUNLOCK(ap);
0a7de745 1011 return error;
b0d623f7
A
1012 }
1013 }
1014
1015 /*
1016 * Copy as many remaining bytes from the current record to userspace
1017 * as we can. Keep processing records until we run out of records in
1018 * the queue, or until the user buffer runs out of space.
1019 *
1020 * Note: we rely on the sleep lock to maintain ape's stability here.
1021 */
1022 ap->ap_reads++;
1023 while ((ape = TAILQ_FIRST(&ap->ap_queue)) != NULL &&
1024 uio_resid(uio) > 0) {
1025 AUDIT_PIPE_LOCK_ASSERT(ap);
1026
1027 KASSERT(ape->ape_record_len > ap->ap_qoffset,
1028 ("audit_pipe_read: record_len > qoffset (1)"));
39236c6e 1029 toread = MIN((int)(ape->ape_record_len - ap->ap_qoffset),
b0d623f7
A
1030 uio_resid(uio));
1031 AUDIT_PIPE_UNLOCK(ap);
1032 error = uiomove((char *)ape->ape_record + ap->ap_qoffset,
1033 toread, uio);
1034 if (error) {
1035 AUDIT_PIPE_SX_XUNLOCK(ap);
0a7de745 1036 return error;
b0d623f7
A
1037 }
1038
1039 /*
1040 * If the copy succeeded, update book-keeping, and if no
1041 * bytes remain in the current record, free it.
1042 */
1043 AUDIT_PIPE_LOCK(ap);
1044 KASSERT(TAILQ_FIRST(&ap->ap_queue) == ape,
1045 ("audit_pipe_read: queue out of sync after uiomove"));
1046 ap->ap_qoffset += toread;
1047 KASSERT(ape->ape_record_len >= ap->ap_qoffset,
1048 ("audit_pipe_read: record_len >= qoffset (2)"));
1049 if (ap->ap_qoffset == ape->ape_record_len) {
1050 TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue);
1051 ap->ap_qbyteslen -= ape->ape_record_len;
1052 audit_pipe_entry_free(ape);
1053 ap->ap_qlen--;
1054 ap->ap_qoffset = 0;
1055 }
1056 }
1057 AUDIT_PIPE_UNLOCK(ap);
1058 AUDIT_PIPE_SX_XUNLOCK(ap);
0a7de745 1059 return 0;
b0d623f7
A
1060}
1061
1062/*
1063 * Audit pipe poll.
1064 */
1065static int
1066audit_pipe_poll(dev_t dev, int events, void *wql, struct proc *p)
1067{
1068 struct audit_pipe *ap;
1069 int revents;
1070
1071 revents = 0;
1072 ap = audit_pipe_dtab[minor(dev)];
1073 KASSERT(ap != NULL, ("audit_pipe_poll: ap == NULL"));
1074
1075 if (events & (POLLIN | POLLRDNORM)) {
1076 AUDIT_PIPE_LOCK(ap);
0a7de745 1077 if (TAILQ_FIRST(&ap->ap_queue) != NULL) {
b0d623f7 1078 revents |= events & (POLLIN | POLLRDNORM);
0a7de745 1079 } else {
b0d623f7 1080 selrecord(p, &ap->ap_selinfo, wql);
0a7de745 1081 }
b0d623f7
A
1082 AUDIT_PIPE_UNLOCK(ap);
1083 }
0a7de745 1084 return revents;
b0d623f7
A
1085}
1086
b0d623f7
A
1087static void *devnode;
1088
1089int
1090audit_pipe_init(void)
1091{
1092 dev_t dev;
1093
1094 TAILQ_INIT(&audit_pipe_list);
1095 AUDIT_PIPE_LIST_LOCK_INIT();
1096
1097 audit_pipe_major = cdevsw_add(-1, &audit_pipe_cdevsw);
0a7de745
A
1098 if (audit_pipe_major < 0) {
1099 return KERN_FAILURE;
1100 }
b0d623f7
A
1101
1102 dev = makedev(audit_pipe_major, 0);
1103 devnode = devfs_make_node_clone(dev, DEVFS_CHAR, UID_ROOT, GID_WHEEL,
1104 0600, audit_pipe_clone, "auditpipe", 0);
1105
0a7de745
A
1106 if (devnode == NULL) {
1107 return KERN_FAILURE;
1108 }
b0d623f7 1109
0a7de745 1110 return KERN_SUCCESS;
b0d623f7
A
1111}
1112
1113int
1114audit_pipe_shutdown(void)
1115{
b0d623f7
A
1116 /* unwind everything */
1117 devfs_remove(devnode);
1118 (void) cdevsw_remove(audit_pipe_major, &audit_pipe_cdevsw);
1119
0a7de745 1120 return KERN_SUCCESS;
b0d623f7
A
1121}
1122
1123#endif /* CONFIG_AUDIT */