audit_pipe.c revision 156884
1/*-
2 * Copyright (c) 2006 Robert N. M. Watson
3 * All rights reserved.
4 *
5 * This software was developed by Robert Watson for the TrustedBSD Project.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * $FreeBSD: head/sys/security/audit/audit_pipe.c 156884 2006-03-19 15:39:03Z rwatson $
29 */
30
31#include <sys/param.h>
32#include <sys/condvar.h>
33#include <sys/conf.h>
34#include <sys/eventhandler.h>
35#include <sys/filio.h>
36#include <sys/kernel.h>
37#include <sys/lock.h>
38#include <sys/malloc.h>
39#include <sys/mutex.h>
40#include <sys/poll.h>
41#include <sys/proc.h>
42#include <sys/queue.h>
43#include <sys/selinfo.h>
44#include <sys/sigio.h>
45#include <sys/signal.h>
46#include <sys/signalvar.h>
47#include <sys/systm.h>
48#include <sys/uio.h>
49
50#include <security/audit/audit.h>
51#include <security/audit/audit_ioctl.h>
52#include <security/audit/audit_private.h>
53
54/*
55 * Implementation of a clonable special device providing a live stream of BSM
56 * audit data.  This is a "tee" of the data going to the file.  It provides
57 * unreliable but timely access to audit events.  Consumers of this interface
58 * should be very careful to avoid introducing event cycles.
59 */
60
61/*
62 * Memory types.
63 */
64static MALLOC_DEFINE(M_AUDIT_PIPE, "audit_pipe", "Audit pipes");
65static MALLOC_DEFINE(M_AUDIT_PIPE_ENTRY, "audit_pipeent",
66    "Audit pipe entries and buffers");
67
68/*
69 * Audit pipe buffer parameters.
70 */
71#define	AUDIT_PIPE_QLIMIT_DEFAULT	(128)
72#define	AUDIT_PIPE_QLIMIT_MIN		(0)
73#define	AUDIT_PIPE_QLIMIT_MAX		(1024)
74
75/*
76 * Description of an entry in an audit_pipe.
77 */
78struct audit_pipe_entry {
79	void				*ape_record;
80	u_int				 ape_record_len;
81	TAILQ_ENTRY(audit_pipe_entry)	 ape_queue;
82};
83
84/*
85 * Description of an individual audit_pipe.  Consists largely of a bounded
86 * length queue.
87 */
88#define	AUDIT_PIPE_ASYNC	0x00000001
89#define	AUDIT_PIPE_NBIO		0x00000002
90struct audit_pipe {
91	int				 ap_open;	/* Device open? */
92	u_int				 ap_flags;
93
94	struct selinfo			 ap_selinfo;
95	struct sigio			*ap_sigio;
96
97	u_int				 ap_qlen;
98	u_int				 ap_qlimit;
99
100	u_int64_t			 ap_inserts;	/* Records added. */
101	u_int64_t			 ap_reads;	/* Records read. */
102	u_int64_t			 ap_drops;	/* Records dropped. */
103	u_int64_t			 ap_truncates;	/* Records too long. */
104
105	TAILQ_HEAD(, audit_pipe_entry)	 ap_queue;
106
107	TAILQ_ENTRY(audit_pipe)		 ap_list;
108};
109
110/*
111 * Global list of audit pipes, mutex to protect it and the pipes.  Finder
112 * grained locking may be desirable at some point.
113 */
114static TAILQ_HEAD(, audit_pipe)	 audit_pipe_list;
115static struct mtx		 audit_pipe_mtx;
116
117/*
118 * This CV is used to wakeup on an audit record write.  Eventually, it should
119 * probably be per-pipe.
120 */
121static struct cv		 audit_pipe_cv;
122
123/*
124 * Cloning related variables and constants.
125 */
126#define	AUDIT_PIPE_NAME		"auditpipe"
127static eventhandler_tag		 audit_pipe_eh_tag;
128static struct clonedevs		*audit_pipe_clones;
129
130/*
131 * Special device methods and definition.
132 */
133static d_open_t		audit_pipe_open;
134static d_close_t	audit_pipe_close;
135static d_read_t		audit_pipe_read;
136static d_ioctl_t	audit_pipe_ioctl;
137static d_poll_t		audit_pipe_poll;
138
139static struct cdevsw	audit_pipe_cdevsw = {
140	.d_version =	D_VERSION,
141	.d_flags =	D_PSEUDO,
142	.d_open =	audit_pipe_open,
143	.d_close =	audit_pipe_close,
144	.d_read =	audit_pipe_read,
145	.d_ioctl =	audit_pipe_ioctl,
146	.d_poll =	audit_pipe_poll,
147	.d_name =	AUDIT_PIPE_NAME,
148};
149
150/*
151 * Some global statistics on audit pipes.
152 */
153static int		audit_pipe_count;	/* Current number of pipes. */
154static u_int64_t	audit_pipe_ever;	/* Pipes ever allocated. */
155static u_int64_t	audit_pipe_records;	/* Records seen. */
156static u_int64_t	audit_pipe_drops;	/* Global record drop count. */
157
158/*
159 * Free an audit pipe entry.
160 */
161static void
162audit_pipe_entry_free(struct audit_pipe_entry *ape)
163{
164
165	free(ape->ape_record, M_AUDIT_PIPE_ENTRY);
166	free(ape, M_AUDIT_PIPE_ENTRY);
167}
168
169/*
170 * Apparent individual record to a queue -- allocate queue-local buffer, and
171 * add to the queue.  We try to drop from the head of the queue so that more
172 * recent events take precedence over older ones, but if allocation fails we
173 * do drop the new event.
174 */
175static void
176audit_pipe_append(struct audit_pipe *ap, void *record, u_int record_len)
177{
178	struct audit_pipe_entry *ape, *ape_remove;
179
180	mtx_assert(&audit_pipe_mtx, MA_OWNED);
181
182	ape = malloc(sizeof(*ape), M_AUDIT_PIPE_ENTRY, M_NOWAIT | M_ZERO);
183	if (ape == NULL) {
184		ap->ap_drops++;
185		audit_pipe_drops++;
186		return;
187	}
188
189	ape->ape_record = malloc(record_len, M_AUDIT_PIPE_ENTRY, M_NOWAIT);
190	if (ape->ape_record == NULL) {
191		free(ape, M_AUDIT_PIPE_ENTRY);
192		ap->ap_drops++;
193		audit_pipe_drops++;
194		return;
195	}
196
197	bcopy(record, ape->ape_record, record_len);
198	ape->ape_record_len = record_len;
199
200	if (ap->ap_qlen >= ap->ap_qlimit) {
201		ape_remove = TAILQ_FIRST(&ap->ap_queue);
202		TAILQ_REMOVE(&ap->ap_queue, ape_remove, ape_queue);
203		audit_pipe_entry_free(ape_remove);
204		ap->ap_qlen--;
205		ap->ap_drops++;
206		audit_pipe_drops++;
207	}
208
209	TAILQ_INSERT_TAIL(&ap->ap_queue, ape, ape_queue);
210	ap->ap_inserts++;
211	ap->ap_qlen++;
212	selwakeuppri(&ap->ap_selinfo, PSOCK);
213	if (ap->ap_flags & AUDIT_PIPE_ASYNC)
214		pgsigio(&ap->ap_sigio, SIGIO, 0);
215}
216
217/*
218 * audit_pipe_submit(): audit_worker submits audit records via this
219 * interface, which arranges for them to be delivered to pipe queues.
220 */
221void
222audit_pipe_submit(void *record, u_int record_len)
223{
224	struct audit_pipe *ap;
225
226	/*
227	 * Lockless read to avoid mutex overhead if pipes are not in use.
228	 */
229	if (TAILQ_FIRST(&audit_pipe_list) == NULL)
230		return;
231
232	mtx_lock(&audit_pipe_mtx);
233	TAILQ_FOREACH(ap, &audit_pipe_list, ap_list)
234		audit_pipe_append(ap, record, record_len);
235	audit_pipe_records++;
236	mtx_unlock(&audit_pipe_mtx);
237	cv_signal(&audit_pipe_cv);
238}
239
240/*
241 * Read the next record off of an audit pipe.
242 */
243static struct audit_pipe_entry *
244audit_pipe_pop(struct audit_pipe *ap)
245{
246	struct audit_pipe_entry *ape;
247
248	mtx_assert(&audit_pipe_mtx, MA_OWNED);
249
250	ape = TAILQ_FIRST(&ap->ap_queue);
251	KASSERT((ape == NULL && ap->ap_qlen == 0) ||
252	    (ape != NULL && ap->ap_qlen != 0), ("audit_pipe_pop: qlen"));
253	if (ape == NULL)
254		return (NULL);
255	TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue);
256	ap->ap_qlen--;
257	return (ape);
258}
259
260/*
261 * Allocate a new audit pipe.  Connects the pipe, on success, to the global
262 * list and updates statistics.
263 */
264static struct audit_pipe *
265audit_pipe_alloc(void)
266{
267	struct audit_pipe *ap;
268
269	mtx_assert(&audit_pipe_mtx, MA_OWNED);
270
271	ap = malloc(sizeof(*ap), M_AUDIT_PIPE, M_NOWAIT | M_ZERO);
272	if (ap == NULL)
273		return (NULL);
274	ap->ap_qlimit = AUDIT_PIPE_QLIMIT_DEFAULT;
275	TAILQ_INIT(&ap->ap_queue);
276	TAILQ_INSERT_HEAD(&audit_pipe_list, ap, ap_list);
277	audit_pipe_count++;
278	audit_pipe_ever++;
279	return (ap);
280}
281
282/*
283 * Free an audit pipe.  Assumes mutex is held, audit_pipe is still on the
284 * global list.  Frees any audit pipe entries in the queue.
285 */
286static void
287audit_pipe_free(struct audit_pipe *ap)
288{
289	struct audit_pipe_entry *ape;
290
291	mtx_assert(&audit_pipe_mtx, MA_OWNED);
292
293	TAILQ_REMOVE(&audit_pipe_list, ap, ap_list);
294	while ((ape = TAILQ_FIRST(&ap->ap_queue)) != NULL) {
295		TAILQ_REMOVE(&ap->ap_queue, ape, ape_queue);
296		audit_pipe_entry_free(ape);
297		ap->ap_qlen--;
298	}
299	KASSERT(ap->ap_qlen == 0, ("audit_pipe_free: ap_qlen"));
300	free(ap, M_AUDIT_PIPE);
301	audit_pipe_count--;
302}
303
304/*
305 * Audit pipe clone routine -- provide specific requested audit pipe, or a
306 * fresh one if a specific one is not requested.
307 */
308static void
309audit_pipe_clone(void *arg, struct ucred *cred, char *name, int namelen,
310    struct cdev **dev)
311{
312	int i, u;
313
314	if (*dev != NULL)
315		return;
316
317	if (strcmp(name, AUDIT_PIPE_NAME) == 0)
318		u = -1;
319	else if (dev_stdclone(name, NULL, AUDIT_PIPE_NAME, &u) != 1)
320		return;
321
322	i = clone_create(&audit_pipe_clones, &audit_pipe_cdevsw, &u, dev, 0);
323	if (i) {
324		*dev = make_dev(&audit_pipe_cdevsw, unit2minor(u), UID_ROOT,
325		    GID_WHEEL, 0600, "%s%d", AUDIT_PIPE_NAME, u);
326		if (*dev != NULL) {
327			dev_ref(*dev);
328			(*dev)->si_flags |= SI_CHEAPCLONE;
329		}
330	}
331}
332
333/*
334 * Audit pipe open method.  Explicit suser check isn't used as this allows
335 * file permissions on the special device to be used to grant audit review
336 * access.
337 */
338static int
339audit_pipe_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
340{
341	struct audit_pipe *ap;
342
343	mtx_lock(&audit_pipe_mtx);
344	ap = dev->si_drv1;
345	if (ap == NULL) {
346		ap = audit_pipe_alloc();
347		if (ap == NULL) {
348			mtx_unlock(&audit_pipe_mtx);
349			return (ENOMEM);
350		}
351		dev->si_drv1 = ap;
352	} else {
353		KASSERT(ap->ap_open, ("audit_pipe_open: ap && !ap_open"));
354		mtx_unlock(&audit_pipe_mtx);
355		return (EBUSY);
356	}
357	ap->ap_open = 1;
358	mtx_unlock(&audit_pipe_mtx);
359	fsetown(td->td_proc->p_pid, &ap->ap_sigio);
360	return (0);
361}
362
363/*
364 * Close audit pipe, tear down all records, etc.
365 */
366static int
367audit_pipe_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
368{
369	struct audit_pipe *ap;
370
371	ap = dev->si_drv1;
372	KASSERT(ap != NULL, ("audit_pipe_close: ap == NULL"));
373	KASSERT(ap->ap_open, ("audit_pipe_close: !ap_open"));
374	funsetown(&ap->ap_sigio);
375	mtx_lock(&audit_pipe_mtx);
376	ap->ap_open = 0;
377	audit_pipe_free(ap);
378	dev->si_drv1 = NULL;
379	mtx_unlock(&audit_pipe_mtx);
380	return (0);
381}
382
383/*
384 * Audit pipe ioctl() routine.  Handle file descriptor and audit pipe layer
385 * commands.
386 *
387 * Would be desirable to support filtering, although perhaps something simple
388 * like an event mask, as opposed to something complicated like BPF.
389 */
390static int
391audit_pipe_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag,
392    struct thread *td)
393{
394	struct audit_pipe *ap;
395	int error;
396
397	ap = dev->si_drv1;
398	KASSERT(ap != NULL, ("audit_pipe_ioctl: ap == NULL"));
399	switch (cmd) {
400	case FIONBIO:
401		mtx_lock(&audit_pipe_mtx);
402		if (*(int *)data)
403			ap->ap_flags |= AUDIT_PIPE_NBIO;
404		else
405			ap->ap_flags &= ~AUDIT_PIPE_NBIO;
406		mtx_unlock(&audit_pipe_mtx);
407		error = 0;
408		break;
409
410	case FIONREAD:
411		mtx_lock(&audit_pipe_mtx);
412		if (TAILQ_FIRST(&ap->ap_queue) != NULL)
413			*(int *)data =
414			    TAILQ_FIRST(&ap->ap_queue)->ape_record_len;
415		else
416			*(int *)data = 0;
417		mtx_unlock(&audit_pipe_mtx);
418		error = 0;
419		break;
420
421	case FIOASYNC:
422		mtx_lock(&audit_pipe_mtx);
423		if (*(int *)data)
424			ap->ap_flags |= AUDIT_PIPE_ASYNC;
425		else
426			ap->ap_flags &= ~AUDIT_PIPE_ASYNC;
427		mtx_unlock(&audit_pipe_mtx);
428		error = 0;
429		break;
430
431	case FIOSETOWN:
432		error = fsetown(*(int *)data, &ap->ap_sigio);
433		break;
434
435	case FIOGETOWN:
436		*(int *)data = fgetown(&ap->ap_sigio);
437		error = 0;
438		break;
439
440	case AUDITPIPE_GET_QLEN:
441		*(u_int *)data = ap->ap_qlen;
442		error = 0;
443		break;
444
445	case AUDITPIPE_GET_QLIMIT:
446		*(u_int *)data = ap->ap_qlimit;
447		error = 0;
448		break;
449
450	case AUDITPIPE_SET_QLIMIT:
451		/* Lockless integer write. */
452		if (*(u_int *)data >= AUDIT_PIPE_QLIMIT_MIN ||
453		    *(u_int *)data <= AUDIT_PIPE_QLIMIT_MAX) {
454			ap->ap_qlimit = *(u_int *)data;
455			error = 0;
456		} else
457			error = EINVAL;
458		break;
459
460	case AUDITPIPE_GET_QLIMIT_MIN:
461		*(u_int *)data = AUDIT_PIPE_QLIMIT_MIN;
462		error = 0;
463		break;
464
465	case AUDITPIPE_GET_QLIMIT_MAX:
466		*(u_int *)data = AUDIT_PIPE_QLIMIT_MAX;
467		error = 0;
468		break;
469
470	case AUDITPIPE_GET_INSERTS:
471		*(u_int *)data = ap->ap_inserts;
472		error = 0;
473		break;
474
475	case AUDITPIPE_GET_READS:
476		*(u_int *)data = ap->ap_reads;
477		error = 0;
478		break;
479
480	case AUDITPIPE_GET_DROPS:
481		*(u_int *)data = ap->ap_drops;
482		error = 0;
483		break;
484
485	case AUDITPIPE_GET_TRUNCATES:
486		*(u_int *)data = ap->ap_truncates;
487		error = 0;
488		break;
489
490	default:
491		error = ENOTTY;
492	}
493	return (error);
494}
495
496/*
497 * Audit pipe read.  Pull one record off the queue and copy to user space.
498 * On error, the record is dropped.
499 */
500static int
501audit_pipe_read(struct cdev *dev, struct uio *uio, int flag)
502{
503	struct audit_pipe_entry *ape;
504	struct audit_pipe *ap;
505	int error;
506
507	ap = dev->si_drv1;
508	KASSERT(ap != NULL, ("audit_pipe_read: ap == NULL"));
509	mtx_lock(&audit_pipe_mtx);
510	do {
511		/*
512		 * Wait for a record that fits into the read buffer, dropping
513		 * records that would be truncated if actually passed to the
514		 * process.  This helps maintain the discreet record read
515		 * interface.
516		 */
517		while ((ape = audit_pipe_pop(ap)) == NULL) {
518			if (ap->ap_flags & AUDIT_PIPE_NBIO) {
519				mtx_unlock(&audit_pipe_mtx);
520				return (EAGAIN);
521			}
522			error = cv_wait_sig(&audit_pipe_cv, &audit_pipe_mtx);
523			if (error) {
524				mtx_unlock(&audit_pipe_mtx);
525				return (error);
526			}
527		}
528		if (ape->ape_record_len <= uio->uio_resid)
529			break;
530		audit_pipe_entry_free(ape);
531		ap->ap_truncates++;
532	} while (1);
533	mtx_unlock(&audit_pipe_mtx);
534
535	/*
536	 * Now read record to user space memory.  Even if the read is short,
537	 * we abandon the remainder of the record, supporting only discreet
538	 * record reads.
539	 */
540	error = uiomove(ape->ape_record, ape->ape_record_len, uio);
541	audit_pipe_entry_free(ape);
542	return (error);
543}
544
545/*
546 * Audit pipe poll.
547 */
548static int
549audit_pipe_poll(struct cdev *dev, int events, struct thread *td)
550{
551	struct audit_pipe *ap;
552	int revents;
553
554	revents = 0;
555	ap = dev->si_drv1;
556	KASSERT(ap != NULL, ("audit_pipe_poll: ap == NULL"));
557	if (events & (POLLIN | POLLRDNORM)) {
558		mtx_lock(&audit_pipe_mtx);
559		if (TAILQ_FIRST(&ap->ap_queue) != NULL)
560			revents |= events & (POLLIN | POLLRDNORM);
561		else
562			selrecord(td, &ap->ap_selinfo);
563		mtx_unlock(&audit_pipe_mtx);
564	}
565	return (revents);
566}
567
568/*
569 * Initialize the audit pipe system.
570 */
571static void
572audit_pipe_init(void *unused)
573{
574
575	TAILQ_INIT(&audit_pipe_list);
576	mtx_init(&audit_pipe_mtx, "audit_pipe_mtx", NULL, MTX_DEF);
577	cv_init(&audit_pipe_cv, "audit_pipe_cv");
578
579	clone_setup(&audit_pipe_clones);
580	audit_pipe_eh_tag = EVENTHANDLER_REGISTER(dev_clone,
581	    audit_pipe_clone, 0, 1000);
582	if (audit_pipe_eh_tag == NULL)
583		panic("audit_pipe_init: EVENTHANDLER_REGISTER");
584}
585
586SYSINIT(audit_pipe_init, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, audit_pipe_init,
587    NULL);
588