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