xref: /freebsd/sys/kern/kern_kcov.c (revision f0483545503a78e16e256d46d458a2faae2f07ea)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (C) 2018 The FreeBSD Foundation. All rights reserved.
5  * Copyright (C) 2018, 2019 Andrew Turner
6  *
7  * This software was developed by Mitchell Horne under sponsorship of
8  * the FreeBSD Foundation.
9  *
10  * This software was developed by SRI International and the University of
11  * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
12  * ("CTSRD"), as part of the DARPA CRASH research programme.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  * $FreeBSD$
36  */
37 
38 #include <sys/cdefs.h>
39 __FBSDID("$FreeBSD$");
40 
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/conf.h>
44 #include <sys/kcov.h>
45 #include <sys/kernel.h>
46 #include <sys/limits.h>
47 #include <sys/lock.h>
48 #include <sys/malloc.h>
49 #include <sys/mman.h>
50 #include <sys/mutex.h>
51 #include <sys/proc.h>
52 #include <sys/rwlock.h>
53 #include <sys/sysctl.h>
54 
55 #include <vm/vm.h>
56 #include <vm/pmap.h>
57 #include <vm/vm_extern.h>
58 #include <vm/vm_object.h>
59 #include <vm/vm_page.h>
60 #include <vm/vm_pager.h>
61 
62 MALLOC_DEFINE(M_KCOV_INFO, "kcovinfo", "KCOV info type");
63 
64 #define	KCOV_ELEMENT_SIZE	sizeof(uint64_t)
65 
66 /*
67  * To know what the code can safely perform at any point in time we use a
68  * state machine. In the normal case the state transitions are:
69  *
70  * OPEN -> READY -> RUNNING -> DYING
71  *  |       | ^        |        ^ ^
72  *  |       | +--------+        | |
73  *  |       +-------------------+ |
74  *  +-----------------------------+
75  *
76  * The states are:
77  *  OPEN:   The kcov fd has been opened, but no buffer is available to store
78  *          coverage data.
79  *  READY:  The buffer to store coverage data has been allocated. Userspace
80  *          can set this by using ioctl(fd, KIOSETBUFSIZE, entries);. When
81  *          this has been set the buffer can be written to by the kernel,
82  *          and mmaped by userspace.
83  * RUNNING: The coverage probes are able to store coverage data in the buffer.
84  *          This is entered with ioctl(fd, KIOENABLE, mode);. The READY state
85  *          can be exited by ioctl(fd, KIODISABLE); or exiting the thread to
86  *          return to the READY state to allow tracing to be reused, or by
87  *          closing the kcov fd to enter the DYING state.
88  * DYING:   The fd has been closed. All states can enter into this state when
89  *          userspace closes the kcov fd.
90  *
91  * We need to be careful when moving into and out of the RUNNING state. As
92  * an interrupt may happen while this is happening the ordering of memory
93  * operations is important so struct kcov_info is valid for the tracing
94  * functions.
95  *
96  * When moving into the RUNNING state prior stores to struct kcov_info need
97  * to be observed before the state is set. This allows for interrupts that
98  * may call into one of the coverage functions to fire at any point while
99  * being enabled and see a consistent struct kcov_info.
100  *
101  * When moving out of the RUNNING state any later stores to struct kcov_info
102  * need to be observed after the state is set. As with entering this is to
103  * present a consistent struct kcov_info to interrupts.
104  */
105 typedef enum {
106 	KCOV_STATE_INVALID,
107 	KCOV_STATE_OPEN,	/* The device is open, but with no buffer */
108 	KCOV_STATE_READY,	/* The buffer has been allocated */
109 	KCOV_STATE_RUNNING,	/* Recording trace data */
110 	KCOV_STATE_DYING,	/* The fd was closed */
111 } kcov_state_t;
112 
113 /*
114  * (l) Set while holding the kcov_lock mutex and not in the RUNNING state.
115  * (o) Only set once while in the OPEN state. Cleaned up while in the DYING
116  *     state, and with no thread associated with the struct kcov_info.
117  * (s) Set atomically to enter or exit the RUNNING state, non-atomically
118  *     otherwise. See above for a description of the other constraints while
119  *     moving into or out of the RUNNING state.
120  */
121 struct kcov_info {
122 	struct thread	*thread;	/* (l) */
123 	vm_object_t	bufobj;		/* (o) */
124 	vm_offset_t	kvaddr;		/* (o) */
125 	size_t		entries;	/* (o) */
126 	size_t		bufsize;	/* (o) */
127 	kcov_state_t	state;		/* (s) */
128 	int		mode;		/* (l) */
129 	bool		mmap;
130 };
131 
132 /* Prototypes */
133 static d_open_t		kcov_open;
134 static d_close_t	kcov_close;
135 static d_mmap_single_t	kcov_mmap_single;
136 static d_ioctl_t	kcov_ioctl;
137 
138 static int  kcov_alloc(struct kcov_info *info, size_t entries);
139 static void kcov_init(const void *unused);
140 
141 static struct cdevsw kcov_cdevsw = {
142 	.d_version =	D_VERSION,
143 	.d_open =	kcov_open,
144 	.d_close =	kcov_close,
145 	.d_mmap_single = kcov_mmap_single,
146 	.d_ioctl =	kcov_ioctl,
147 	.d_name =	"kcov",
148 };
149 
150 SYSCTL_NODE(_kern, OID_AUTO, kcov, CTLFLAG_RW, 0, "Kernel coverage");
151 
152 static u_int kcov_max_entries = KCOV_MAXENTRIES;
153 SYSCTL_UINT(_kern_kcov, OID_AUTO, max_entries, CTLFLAG_RW,
154     &kcov_max_entries, 0,
155     "Maximum number of entries in the kcov buffer");
156 
157 static struct mtx kcov_lock;
158 static int active_count;
159 
160 static struct kcov_info *
161 get_kinfo(struct thread *td)
162 {
163 	struct kcov_info *info;
164 
165 	/* We might have a NULL thread when releasing the secondary CPUs */
166 	if (td == NULL)
167 		return (NULL);
168 
169 	/*
170 	 * We are in an interrupt, stop tracing as it is not explicitly
171 	 * part of a syscall.
172 	 */
173 	if (td->td_intr_nesting_level > 0 || td->td_intr_frame != NULL)
174 		return (NULL);
175 
176 	/*
177 	 * If info is NULL or the state is not running we are not tracing.
178 	 */
179 	info = td->td_kcov_info;
180 	if (info == NULL ||
181 	    atomic_load_acq_int(&info->state) != KCOV_STATE_RUNNING)
182 		return (NULL);
183 
184 	return (info);
185 }
186 
187 static void
188 trace_pc(uintptr_t ret)
189 {
190 	struct thread *td;
191 	struct kcov_info *info;
192 	uint64_t *buf, index;
193 
194 	td = curthread;
195 	info = get_kinfo(td);
196 	if (info == NULL)
197 		return;
198 
199 	/*
200 	 * Check we are in the PC-trace mode.
201 	 */
202 	if (info->mode != KCOV_MODE_TRACE_PC)
203 		return;
204 
205 	KASSERT(info->kvaddr != 0,
206 	    ("__sanitizer_cov_trace_pc: NULL buf while running"));
207 
208 	buf = (uint64_t *)info->kvaddr;
209 
210 	/* The first entry of the buffer holds the index */
211 	index = buf[0];
212 	if (index + 2 > info->entries)
213 		return;
214 
215 	buf[index + 1] = ret;
216 	buf[0] = index + 1;
217 }
218 
219 static bool
220 trace_cmp(uint64_t type, uint64_t arg1, uint64_t arg2, uint64_t ret)
221 {
222 	struct thread *td;
223 	struct kcov_info *info;
224 	uint64_t *buf, index;
225 
226 	td = curthread;
227 	info = get_kinfo(td);
228 	if (info == NULL)
229 		return (false);
230 
231 	/*
232 	 * Check we are in the comparison-trace mode.
233 	 */
234 	if (info->mode != KCOV_MODE_TRACE_CMP)
235 		return (false);
236 
237 	KASSERT(info->kvaddr != 0,
238 	    ("__sanitizer_cov_trace_pc: NULL buf while running"));
239 
240 	buf = (uint64_t *)info->kvaddr;
241 
242 	/* The first entry of the buffer holds the index */
243 	index = buf[0];
244 
245 	/* Check we have space to store all elements */
246 	if (index * 4 + 4 + 1 > info->entries)
247 		return (false);
248 
249 	buf[index * 4 + 1] = type;
250 	buf[index * 4 + 2] = arg1;
251 	buf[index * 4 + 3] = arg2;
252 	buf[index * 4 + 4] = ret;
253 	buf[0] = index + 1;
254 
255 	return (true);
256 }
257 
258 /*
259  * The fd is being closed, cleanup everything we can.
260  */
261 static void
262 kcov_mmap_cleanup(void *arg)
263 {
264 	struct kcov_info *info = arg;
265 	struct thread *thread;
266 
267 	mtx_lock_spin(&kcov_lock);
268 	/*
269 	 * Move to KCOV_STATE_DYING to stop adding new entries.
270 	 *
271 	 * If the thread is running we need to wait until thread exit to
272 	 * clean up as it may currently be adding a new entry. If this is
273 	 * the case being in KCOV_STATE_DYING will signal that the buffer
274 	 * needs to be cleaned up.
275 	 */
276 	atomic_store_int(&info->state, KCOV_STATE_DYING);
277 	atomic_thread_fence_seq_cst();
278 	thread = info->thread;
279 	mtx_unlock_spin(&kcov_lock);
280 
281 	if (thread != NULL)
282 		return;
283 
284 	/*
285 	 * We can safely clean up the info struct as it is in the
286 	 * KCOV_STATE_DYING state with no thread associated.
287 	 *
288 	 * The KCOV_STATE_DYING stops new threads from using it.
289 	 * The lack of a thread means nothing is currently using the buffers.
290 	 */
291 
292 	if (info->kvaddr != 0) {
293 		pmap_qremove(info->kvaddr, info->bufsize / PAGE_SIZE);
294 		kva_free(info->kvaddr, info->bufsize);
295 	}
296 	if (info->bufobj != NULL && !info->mmap)
297 		vm_object_deallocate(info->bufobj);
298 	free(info, M_KCOV_INFO);
299 }
300 
301 static int
302 kcov_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
303 {
304 	struct kcov_info *info;
305 	int error;
306 
307 	info = malloc(sizeof(struct kcov_info), M_KCOV_INFO, M_ZERO | M_WAITOK);
308 	info->state = KCOV_STATE_OPEN;
309 	info->thread = NULL;
310 	info->mode = -1;
311 	info->mmap = false;
312 
313 	if ((error = devfs_set_cdevpriv(info, kcov_mmap_cleanup)) != 0)
314 		kcov_mmap_cleanup(info);
315 
316 	return (error);
317 }
318 
319 static int
320 kcov_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
321 {
322 	struct kcov_info *info;
323 	int error;
324 
325 
326 	if ((error = devfs_get_cdevpriv((void **)&info)) != 0)
327 		return (error);
328 
329 	KASSERT(info != NULL, ("kcov_close with no kcov_info structure"));
330 
331 	/* Trying to close, but haven't disabled */
332 	if (info->state == KCOV_STATE_RUNNING)
333 		return (EBUSY);
334 
335 	return (0);
336 }
337 
338 static int
339 kcov_mmap_single(struct cdev *dev, vm_ooffset_t *offset, vm_size_t size,
340     struct vm_object **object, int nprot)
341 {
342 	struct kcov_info *info;
343 	int error;
344 
345 	if ((nprot & (PROT_EXEC | PROT_READ | PROT_WRITE)) !=
346 	    (PROT_READ | PROT_WRITE))
347 		return (EINVAL);
348 
349 	if ((error = devfs_get_cdevpriv((void **)&info)) != 0)
350 		return (error);
351 
352 	if (info->kvaddr == 0 || size / KCOV_ELEMENT_SIZE != info->entries ||
353 	    info->mmap != false)
354 		return (EINVAL);
355 
356 	info->mmap = true;
357 	*offset = 0;
358 	*object = info->bufobj;
359 	return (0);
360 }
361 
362 static int
363 kcov_alloc(struct kcov_info *info, size_t entries)
364 {
365 	size_t n, pages;
366 	vm_page_t *m;
367 
368 	KASSERT(info->kvaddr == 0, ("kcov_alloc: Already have a buffer"));
369 	KASSERT(info->state == KCOV_STATE_OPEN,
370 	    ("kcov_alloc: Not in open state (%x)", info->state));
371 
372 	if (entries < 2 || entries > kcov_max_entries)
373 		return (EINVAL);
374 
375 	/* Align to page size so mmap can't access other kernel memory */
376 	info->bufsize = roundup2(entries * KCOV_ELEMENT_SIZE, PAGE_SIZE);
377 	pages = info->bufsize / PAGE_SIZE;
378 
379 	if ((info->kvaddr = kva_alloc(info->bufsize)) == 0)
380 		return (ENOMEM);
381 
382 	info->bufobj = vm_pager_allocate(OBJT_PHYS, 0, info->bufsize,
383 	    PROT_READ | PROT_WRITE, 0, curthread->td_ucred);
384 
385 	m = malloc(sizeof(*m) * pages, M_TEMP, M_WAITOK);
386 	VM_OBJECT_WLOCK(info->bufobj);
387 	for (n = 0; n < pages; n++) {
388 		m[n] = vm_page_grab(info->bufobj, n,
389 		    VM_ALLOC_NOBUSY | VM_ALLOC_ZERO | VM_ALLOC_WIRED);
390 		m[n]->valid = VM_PAGE_BITS_ALL;
391 	}
392 	VM_OBJECT_WUNLOCK(info->bufobj);
393 	pmap_qenter(info->kvaddr, m, pages);
394 	free(m, M_TEMP);
395 
396 	info->entries = entries;
397 
398 	return (0);
399 }
400 
401 static int
402 kcov_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag __unused,
403     struct thread *td)
404 {
405 	struct kcov_info *info;
406 	int mode, error;
407 
408 	if ((error = devfs_get_cdevpriv((void **)&info)) != 0)
409 		return (error);
410 
411 	if (cmd == KIOSETBUFSIZE) {
412 		/*
413 		 * Set the size of the coverage buffer. Should be called
414 		 * before enabling coverage collection for that thread.
415 		 */
416 		if (info->state != KCOV_STATE_OPEN) {
417 			return (EBUSY);
418 		}
419 		error = kcov_alloc(info, *(u_int *)data);
420 		if (error == 0)
421 			info->state = KCOV_STATE_READY;
422 		return (error);
423 	}
424 
425 	mtx_lock_spin(&kcov_lock);
426 	switch (cmd) {
427 	case KIOENABLE:
428 		if (info->state != KCOV_STATE_READY) {
429 			error = EBUSY;
430 			break;
431 		}
432 		if (td->td_kcov_info != NULL) {
433 			error = EINVAL;
434 			break;
435 		}
436 		mode = *(int *)data;
437 		if (mode != KCOV_MODE_TRACE_PC && mode != KCOV_MODE_TRACE_CMP) {
438 			error = EINVAL;
439 			break;
440 		}
441 
442 		/* Lets hope nobody opens this 2 billion times */
443 		KASSERT(active_count < INT_MAX,
444 		    ("%s: Open too many times", __func__));
445 		active_count++;
446 		if (active_count == 1) {
447 			cov_register_pc(&trace_pc);
448 			cov_register_cmp(&trace_cmp);
449 		}
450 
451 		KASSERT(info->thread == NULL,
452 		    ("Enabling kcov when already enabled"));
453 		info->thread = td;
454 		info->mode = mode;
455 		/*
456 		 * Ensure the mode has been set before starting coverage
457 		 * tracing.
458 		 */
459 		atomic_store_rel_int(&info->state, KCOV_STATE_RUNNING);
460 		td->td_kcov_info = info;
461 		break;
462 	case KIODISABLE:
463 		/* Only the currently enabled thread may disable itself */
464 		if (info->state != KCOV_STATE_RUNNING ||
465 		    info != td->td_kcov_info) {
466 			error = EINVAL;
467 			break;
468 		}
469 		KASSERT(active_count > 0, ("%s: Open count is zero", __func__));
470 		active_count--;
471 		if (active_count == 0) {
472 			cov_register_pc(&trace_pc);
473 			cov_register_cmp(&trace_cmp);
474 		}
475 
476 		td->td_kcov_info = NULL;
477 		atomic_store_int(&info->state, KCOV_STATE_READY);
478 		/*
479 		 * Ensure we have exited the READY state before clearing the
480 		 * rest of the info struct.
481 		 */
482 		atomic_thread_fence_rel();
483 		info->mode = -1;
484 		info->thread = NULL;
485 		break;
486 	default:
487 		error = EINVAL;
488 		break;
489 	}
490 	mtx_unlock_spin(&kcov_lock);
491 
492 	return (error);
493 }
494 
495 static void
496 kcov_thread_dtor(void *arg __unused, struct thread *td)
497 {
498 	struct kcov_info *info;
499 
500 	info = td->td_kcov_info;
501 	if (info == NULL)
502 		return;
503 
504 	mtx_lock_spin(&kcov_lock);
505 	KASSERT(active_count > 0, ("%s: Open count is zero", __func__));
506 	active_count--;
507 	if (active_count == 0) {
508 		cov_register_pc(&trace_pc);
509 		cov_register_cmp(&trace_cmp);
510 	}
511 	td->td_kcov_info = NULL;
512 	if (info->state != KCOV_STATE_DYING) {
513 		/*
514 		 * The kcov file is still open. Mark it as unused and
515 		 * wait for it to be closed before cleaning up.
516 		 */
517 		atomic_store_int(&info->state, KCOV_STATE_READY);
518 		atomic_thread_fence_seq_cst();
519 		/* This info struct is unused */
520 		info->thread = NULL;
521 		mtx_unlock_spin(&kcov_lock);
522 		return;
523 	}
524 	mtx_unlock_spin(&kcov_lock);
525 
526 	/*
527 	 * We can safely clean up the info struct as it is in the
528 	 * KCOV_STATE_DYING state where the info struct is associated with
529 	 * the current thread that's about to exit.
530 	 *
531 	 * The KCOV_STATE_DYING stops new threads from using it.
532 	 * It also stops the current thread from trying to use the info struct.
533 	 */
534 
535 	if (info->kvaddr != 0) {
536 		pmap_qremove(info->kvaddr, info->bufsize / PAGE_SIZE);
537 		kva_free(info->kvaddr, info->bufsize);
538 	}
539 	if (info->bufobj != NULL && !info->mmap)
540 		vm_object_deallocate(info->bufobj);
541 	free(info, M_KCOV_INFO);
542 }
543 
544 static void
545 kcov_init(const void *unused)
546 {
547 	struct make_dev_args args;
548 	struct cdev *dev;
549 
550 	mtx_init(&kcov_lock, "kcov lock", NULL, MTX_SPIN);
551 
552 	make_dev_args_init(&args);
553 	args.mda_devsw = &kcov_cdevsw;
554 	args.mda_uid = UID_ROOT;
555 	args.mda_gid = GID_WHEEL;
556 	args.mda_mode = 0600;
557 	if (make_dev_s(&args, &dev, "kcov") != 0) {
558 		printf("%s", "Failed to create kcov device");
559 		return;
560 	}
561 
562 	EVENTHANDLER_REGISTER(thread_dtor, kcov_thread_dtor, NULL,
563 	    EVENTHANDLER_PRI_ANY);
564 }
565 
566 SYSINIT(kcovdev, SI_SUB_LAST, SI_ORDER_ANY, kcov_init, NULL);
567