xref: /freebsd/sys/security/audit/audit_dtrace.c (revision 7fdf597e96a02165cfe22ff357b857d5fa15ed8a)
1 /*-
2  * Copyright (c) 2016, 2018 Robert N. M. Watson
3  * All rights reserved.
4  *
5  * This software was developed by BAE Systems, the University of Cambridge
6  * Computer Laboratory, and Memorial University under DARPA/AFRL contract
7  * FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent Computing
8  * (TC) research program.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #include <sys/param.h>
33 #include <sys/conf.h>
34 #include <sys/ctype.h>
35 #include <sys/kernel.h>
36 #include <sys/malloc.h>
37 #include <sys/module.h>
38 #include <sys/queue.h>
39 #include <sys/refcount.h>
40 
41 #include <sys/dtrace.h>
42 #include <sys/dtrace_bsd.h>
43 
44 #include <bsm/audit.h>
45 #include <bsm/audit_internal.h>
46 #include <bsm/audit_kevents.h>
47 
48 #include <security/audit/audit.h>
49 #include <security/audit/audit_private.h>
50 
51 /*-
52  * Audit DTrace provider: allow DTrace to request that audit records be
53  * generated for various audit events, and then expose those records (in
54  * various forms) to probes.  The model is that each event type has two
55  * probes, which use the event's name to create the probe:
56  *
57  * - "commit" passes the kernel-internal (unserialised) kaudit_record
58  *   synchronously (from the originating thread) of the record as we prepare
59  *   to "commit" the record to the audit queue.
60  *
61  * - "bsm" also passes generated BSM, and executes asynchronously in the audit
62  *   worker thread, once it has been extracted from the audit queue.  This is
63  *   the point at which an audit record would be enqueued to the trail on
64  *   disk, or to pipes.
65  *
66  * These probes support very different goals.  The former executes in the
67  * thread originating the record, making it easier to correlate other DTrace
68  * probe activity with the event described in the record.  The latter gives
69  * access to BSM-formatted events (at a cost) allowing DTrace to extract BSM
70  * directly an alternative mechanism to the formal audit trail and audit
71  * pipes.
72  *
73  * To generate names for numeric event IDs, userspace will push the contents
74  * of /etc/security/audit_event into the kernel during audit setup, much as it
75  * does /etc/security/audit_class.  We then create the probes for each of
76  * those mappings.  If one (or both) of the probes are enabled, then we cause
77  * a record to be generated (as both normal audit preselection and audit pipes
78  * do), and catch it on the way out during commit.  There are suitable hook
79  * functions in the audit code that this provider can register to catch
80  * various events in the audit-record life cycle.
81  *
82  * Further ponderings:
83  *
84  * - How do we want to handle events for which there are not names -- perhaps
85  *   a catch-all probe for those events without mappings?
86  *
87  * - Should the evname code really be present even if DTrace isn't loaded...?
88  *   Right now, we arrange that it is so that userspace can usefully maintain
89  *   the list in case DTrace is later loaded (and to prevent userspace
90  *   confusion).
91  *
92  * - Should we add an additional set of audit:class::commit probes that use
93  *   event class names to match broader categories of events as specified in
94  *   /etc/security/event_class?
95  *
96  * - If we pursue that last point, we will want to pass the name of the event
97  *   into the probe explicitly (e.g., as arg0), since it would no longer be
98  *   available as the probe function name.
99  */
100 
101 static int	dtaudit_unload(void);
102 static void	dtaudit_getargdesc(void *, dtrace_id_t, void *,
103 		    dtrace_argdesc_t *);
104 static void	dtaudit_provide(void *, dtrace_probedesc_t *);
105 static void	dtaudit_destroy(void *, dtrace_id_t, void *);
106 static void	dtaudit_enable(void *, dtrace_id_t, void *);
107 static void	dtaudit_disable(void *, dtrace_id_t, void *);
108 static void	dtaudit_load(void *);
109 
110 static dtrace_pattr_t dtaudit_attr = {
111 { DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
112 { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
113 { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
114 { DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
115 { DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
116 };
117 
118 /*
119  * Strings for the "module" and "name" portions of the probe.  The name of the
120  * audit event will be the "function" portion of the probe.  All dtaudit
121  * probes therefore take the form audit:event:<event name>:commit.
122  */
123 static char	*dtaudit_module_str = "event";
124 static char	*dtaudit_name_commit_str = "commit";
125 static char	*dtaudit_name_bsm_str = "bsm";
126 
127 static dtrace_pops_t dtaudit_pops = {
128 	.dtps_provide =		dtaudit_provide,
129 	.dtps_provide_module =	NULL,
130 	.dtps_enable =		dtaudit_enable,
131 	.dtps_disable =		dtaudit_disable,
132 	.dtps_suspend =		NULL,
133 	.dtps_resume =		NULL,
134 	.dtps_getargdesc =	dtaudit_getargdesc,
135 	.dtps_getargval =	NULL,
136 	.dtps_usermode =	NULL,
137 	.dtps_destroy =		dtaudit_destroy
138 };
139 
140 static dtrace_provider_id_t	dtaudit_id;
141 
142 /*
143  * Because looking up entries in the event-to-name mapping is quite expensive,
144  * maintain a global flag tracking whether any dtaudit probes are enabled.  If
145  * not, don't bother doing all that work whenever potential queries about
146  * events turn up during preselection or commit.
147  *
148  * NB: We used to maintain our own variable in dtaudit, but now use the
149  * centralized audit_dtrace_enabled variable imported from the audit code.
150  *
151  * static uint_t		dtaudit_probes_enabled;
152  */
153 
154 /*
155  * Check dtaudit policy for the event to see whether this is an event we would
156  * like to preselect (i.e., cause an audit record to be generated for).  To
157  * minimise probe effect when not used at all, we not only check for the probe
158  * on the individual event, but also a global flag indicating that at least
159  * one probe is enabled, before acquiring locks, searching lists, etc.
160  *
161  * If the event is selected, return an evname_elem reference to be stored in
162  * the audit record, which we can use later to avoid further lookups.  The
163  * contents of the evname_elem must be sufficiently stable so as to not risk
164  * race conditions here.
165  *
166  * Currently, we take an interest only in the 'event' argument, but in the
167  * future might want to support other types of record selection tied to
168  * additional probe types (e.g., event clases).
169  *
170  * XXXRW: Should we have a catch-all probe here for events without registered
171  * names?
172  */
173 static void *
174 dtaudit_preselect(au_id_t auid, au_event_t event, au_class_t class)
175 {
176 	struct evname_elem *ene;
177 	int probe_enabled;
178 
179 	/*
180 	 * NB: Lockless reads here may return a slightly stale value; this is
181 	 * considered better than acquiring a lock, however.
182 	 */
183 	if (!audit_dtrace_enabled)
184 		return (NULL);
185 	ene = au_evnamemap_lookup(event);
186 	if (ene == NULL)
187 		return (NULL);
188 
189 	/*
190 	 * See if either of the two probes for the audit event are enabled.
191 	 *
192 	 * NB: Lock also not acquired here -- but perhaps it wouldn't matter
193 	 * given that we've already used the list lock above?
194 	 *
195 	 * XXXRW: Alternatively, au_evnamemap_lookup() could return these
196 	 * values while holding the list lock...?
197 	 */
198 	probe_enabled = ene->ene_commit_probe_enabled ||
199 	    ene->ene_bsm_probe_enabled;
200 	if (!probe_enabled)
201 		return (NULL);
202 	return ((void *)ene);
203 }
204 
205 /*
206  * Commit probe pre-BSM.  Fires the probe but also checks to see if we should
207  * ask the audit framework to call us again with BSM arguments in the audit
208  * worker thread.
209  *
210  * XXXRW: Should we have a catch-all probe here for events without registered
211  * names?
212  */
213 static int
214 dtaudit_commit(struct kaudit_record *kar, au_id_t auid, au_event_t event,
215     au_class_t class, int sorf)
216 {
217 	char ene_name_lower[EVNAMEMAP_NAME_SIZE];
218 	struct evname_elem *ene;
219 	int i;
220 
221 	ene = (struct evname_elem *)kar->k_dtaudit_state;
222 	if (ene == NULL)
223 		return (0);
224 
225 	/*
226 	 * Process a possibly registered commit probe.
227 	 */
228 	if (ene->ene_commit_probe_enabled) {
229 		/*
230 		 * XXXRW: Lock ene to provide stability to the name string.  A
231 		 * bit undesirable!  We may want another locking strategy
232 		 * here.  At least we don't run the DTrace probe under the
233 		 * lock.
234 		 *
235 		 * XXXRW: We provide the struct audit_record pointer -- but
236 		 * perhaps should provide the kaudit_record pointer?
237 		 */
238 		EVNAME_LOCK(ene);
239 		for (i = 0; i < sizeof(ene_name_lower); i++)
240 			ene_name_lower[i] = tolower(ene->ene_name[i]);
241 		EVNAME_UNLOCK(ene);
242 		dtrace_probe(ene->ene_commit_probe_id,
243 		    (uintptr_t)ene_name_lower, (uintptr_t)&kar->k_ar, 0, 0, 0);
244 	}
245 
246 	/*
247 	 * Return the state of the BSM probe to the caller.
248 	 */
249 	return (ene->ene_bsm_probe_enabled);
250 }
251 
252 /*
253  * Commit probe post-BSM.
254  *
255  * XXXRW: Should we have a catch-all probe here for events without registered
256  * names?
257  */
258 static void
259 dtaudit_bsm(struct kaudit_record *kar, au_id_t auid, au_event_t event,
260     au_class_t class, int sorf, void *bsm_data, size_t bsm_len)
261 {
262 	char ene_name_lower[EVNAMEMAP_NAME_SIZE];
263 	struct evname_elem *ene;
264 	int i;
265 
266 	ene = (struct evname_elem *)kar->k_dtaudit_state;
267 	if (ene == NULL)
268 		return;
269 	if (!(ene->ene_bsm_probe_enabled))
270 		return;
271 
272 	/*
273 	 * XXXRW: Lock ene to provide stability to the name string.  A bit
274 	 * undesirable!  We may want another locking strategy here.  At least
275 	 * we don't run the DTrace probe under the lock.
276 	 *
277 	 * XXXRW: We provide the struct audit_record pointer -- but perhaps
278 	 * should provide the kaudit_record pointer?
279 	 */
280 	EVNAME_LOCK(ene);
281 	for (i = 0; i < sizeof(ene_name_lower); i++)
282 		ene_name_lower[i] = tolower(ene->ene_name[i]);
283 	EVNAME_UNLOCK(ene);
284 	dtrace_probe(ene->ene_bsm_probe_id, (uintptr_t)ene_name_lower,
285 	    (uintptr_t)&kar->k_ar, (uintptr_t)bsm_data, (uintptr_t)bsm_len,
286 	    0);
287 }
288 
289 /*
290  * A very simple provider: argument types are identical across all probes: the
291  * kaudit_record, plus a BSM pointer and length.
292  */
293 static void
294 dtaudit_getargdesc(void *arg, dtrace_id_t id, void *parg,
295     dtrace_argdesc_t *desc)
296 {
297 	struct evname_elem *ene;
298 	const char *p;
299 
300 	ene = (struct evname_elem *)parg;
301 	p = NULL;
302 	switch (desc->dtargd_ndx) {
303 	case 0:
304 		/* Audit event name. */
305 		p = "char *";
306 		break;
307 
308 	case 1:
309 		/* In-kernel audit record. */
310 		p = "struct audit_record *";
311 		break;
312 
313 	case 2:
314 		/* BSM data, if present. */
315 		if (id == ene->ene_bsm_probe_id)
316 			p = "const void *";
317 		else
318 			desc->dtargd_ndx = DTRACE_ARGNONE;
319 		break;
320 
321 	case 3:
322 		/* BSM length, if present. */
323 		if (id == ene->ene_bsm_probe_id)
324 			p = "size_t";
325 		else
326 			desc->dtargd_ndx = DTRACE_ARGNONE;
327 		break;
328 
329 	default:
330 		desc->dtargd_ndx = DTRACE_ARGNONE;
331 		break;
332 	}
333 	if (p != NULL)
334 		strlcpy(desc->dtargd_native, p, sizeof(desc->dtargd_native));
335 }
336 
337 /*
338  * Callback from the event-to-name mapping code when performing
339  * evname_foreach().  Note that we may update the entry, so the foreach code
340  * must have a write lock.  However, as the synchronisation model is private
341  * to the evname code, we cannot easily assert it here.
342  *
343  * XXXRW: How do we want to handle event rename / collision issues here --
344  * e.g., if userspace was using a name to point to one event number, and then
345  * changes it so that the name points at another?  For now, paper over this by
346  * skipping event numbers that are already registered, and likewise skipping
347  * names that are already registered.  However, this could lead to confusing
348  * behaviour so possibly needs to be resolved in the longer term.
349  */
350 static void
351 dtaudit_au_evnamemap_callback(struct evname_elem *ene)
352 {
353 	char ene_name_lower[EVNAMEMAP_NAME_SIZE];
354 	int i;
355 
356 	/*
357 	 * DTrace, by convention, has lower-case probe names.  However, the
358 	 * in-kernel event-to-name mapping table must maintain event-name case
359 	 * as submitted by userspace.  Create a temporary lower-case version
360 	 * here, away from the fast path, to use when exposing the event name
361 	 * to DTrace as part of the name of a probe.
362 	 *
363 	 * NB: Convert the entire array, including the terminating nul,
364 	 * because these strings are short and it's more work not to.  If they
365 	 * become long, we might feel more guilty about this sloppiness!
366 	 */
367 	for (i = 0; i < sizeof(ene_name_lower); i++)
368 		ene_name_lower[i] = tolower(ene->ene_name[i]);
369 
370 	/*
371 	 * Don't register a new probe if this event number already has an
372 	 * associated commit probe -- or if another event has already
373 	 * registered this name.
374 	 *
375 	 * XXXRW: There is an argument that if multiple numeric events match
376 	 * a single name, they should all be exposed to the same named probe.
377 	 * In particular, we should perhaps use a probe ID returned by this
378 	 * lookup and just stick that in the saved probe ID?
379 	 */
380 	if ((ene->ene_commit_probe_id == 0) &&
381 	    (dtrace_probe_lookup(dtaudit_id, dtaudit_module_str,
382 	    ene_name_lower, dtaudit_name_commit_str) == 0)) {
383 		/*
384 		 * Create the commit probe.
385 		 *
386 		 * NB: We don't declare any extra stack frames because stack()
387 		 * will just return the path to the audit commit code, which
388 		 * is not really interesting anyway.
389 		 *
390 		 * We pass in the pointer to the evnam_elem entry so that we
391 		 * can easily change its enabled flag in the probe
392 		 * enable/disable interface.
393 		 */
394 		ene->ene_commit_probe_id = dtrace_probe_create(dtaudit_id,
395 		    dtaudit_module_str, ene_name_lower,
396 		    dtaudit_name_commit_str, 0, ene);
397 	}
398 
399 	/*
400 	 * Don't register a new probe if this event number already has an
401 	 * associated bsm probe -- or if another event has already
402 	 * registered this name.
403 	 *
404 	 * XXXRW: There is an argument that if multiple numeric events match
405 	 * a single name, they should all be exposed to the same named probe.
406 	 * In particular, we should perhaps use a probe ID returned by this
407 	 * lookup and just stick that in the saved probe ID?
408 	 */
409 	if ((ene->ene_bsm_probe_id == 0) &&
410 	    (dtrace_probe_lookup(dtaudit_id, dtaudit_module_str,
411 	    ene_name_lower, dtaudit_name_bsm_str) == 0)) {
412 		/*
413 		 * Create the bsm probe.
414 		 *
415 		 * NB: We don't declare any extra stack frames because stack()
416 		 * will just return the path to the audit commit code, which
417 		 * is not really interesting anyway.
418 		 *
419 		 * We pass in the pointer to the evnam_elem entry so that we
420 		 * can easily change its enabled flag in the probe
421 		 * enable/disable interface.
422 		 */
423 		ene->ene_bsm_probe_id = dtrace_probe_create(dtaudit_id,
424 		    dtaudit_module_str, ene_name_lower, dtaudit_name_bsm_str,
425 		    0, ene);
426 	}
427 }
428 
429 static void
430 dtaudit_provide(void *arg, dtrace_probedesc_t *desc)
431 {
432 
433 	/*
434 	 * Walk all registered number-to-name mapping entries, and ensure each
435 	 * is properly registered.
436 	 */
437 	au_evnamemap_foreach(dtaudit_au_evnamemap_callback);
438 }
439 
440 static void
441 dtaudit_destroy(void *arg, dtrace_id_t id, void *parg)
442 {
443 }
444 
445 static void
446 dtaudit_enable(void *arg, dtrace_id_t id, void *parg)
447 {
448 	struct evname_elem *ene;
449 
450 	ene = parg;
451 	KASSERT(ene->ene_commit_probe_id == id || ene->ene_bsm_probe_id == id,
452 	    ("%s: probe ID mismatch (%u, %u != %u)", __func__,
453 	    ene->ene_commit_probe_id, ene->ene_bsm_probe_id, id));
454 
455 	if (id == ene->ene_commit_probe_id)
456 		ene->ene_commit_probe_enabled = 1;
457 	else
458 		ene->ene_bsm_probe_enabled = 1;
459 	refcount_acquire(&audit_dtrace_enabled);
460 	audit_syscalls_enabled_update();
461 }
462 
463 static void
464 dtaudit_disable(void *arg, dtrace_id_t id, void *parg)
465 {
466 	struct evname_elem *ene;
467 
468 	ene = parg;
469 	KASSERT(ene->ene_commit_probe_id == id || ene->ene_bsm_probe_id == id,
470 	    ("%s: probe ID mismatch (%u, %u != %u)", __func__,
471 	    ene->ene_commit_probe_id, ene->ene_bsm_probe_id, id));
472 
473 	if (id == ene->ene_commit_probe_id)
474 		ene->ene_commit_probe_enabled = 0;
475 	else
476 		ene->ene_bsm_probe_enabled = 0;
477 	(void)refcount_release(&audit_dtrace_enabled);
478 	audit_syscalls_enabled_update();
479 }
480 
481 static void
482 dtaudit_load(void *dummy)
483 {
484 
485 	if (dtrace_register("audit", &dtaudit_attr, DTRACE_PRIV_USER, NULL,
486 	    &dtaudit_pops, NULL, &dtaudit_id) != 0)
487 		return;
488 	dtaudit_hook_preselect = dtaudit_preselect;
489 	dtaudit_hook_commit = dtaudit_commit;
490 	dtaudit_hook_bsm = dtaudit_bsm;
491 }
492 
493 static int
494 dtaudit_unload(void)
495 {
496 	int error;
497 
498 	dtaudit_hook_preselect = NULL;
499 	dtaudit_hook_commit = NULL;
500 	dtaudit_hook_bsm = NULL;
501 	if ((error = dtrace_unregister(dtaudit_id)) != 0)
502 		return (error);
503 	return (0);
504 }
505 
506 static int
507 dtaudit_modevent(module_t mod __unused, int type, void *data __unused)
508 {
509 	int error = 0;
510 
511 	switch (type) {
512 	case MOD_LOAD:
513 	case MOD_UNLOAD:
514 	case MOD_SHUTDOWN:
515 		break;
516 
517 	default:
518 		error = EOPNOTSUPP;
519 		break;
520 	}
521 
522 	return (error);
523 }
524 
525 SYSINIT(dtaudit_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, dtaudit_load,
526     NULL);
527 SYSUNINIT(dtaudit_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY,
528     dtaudit_unload, NULL);
529 
530 DEV_MODULE(dtaudit, dtaudit_modevent, NULL);
531 MODULE_VERSION(dtaudit, 1);
532 MODULE_DEPEND(dtaudit, dtrace, 1, 1, 1);
533 MODULE_DEPEND(dtaudit, opensolaris, 1, 1, 1);
534