1/*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1999 Eivind Eklund <eivind@FreeBSD.org>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University nor the names of its contributors
15 *    may be used to endorse or promote products derived from this software
16 *    without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#ifndef _SYS_KASSERT_H_
32#define	_SYS_KASSERT_H_
33
34#include <sys/cdefs.h>
35
36#ifdef _KERNEL
37extern const char *panicstr;	/* panic message */
38#define	KERNEL_PANICKED()	__predict_false(panicstr != NULL)
39
40/*
41 * Trap accesses going through a pointer. Moreover if kasan is available trap
42 * reading the pointer itself.
43 *
44 * Sample usage: you have a struct with numerous fields and by API contract
45 * only some of them get populated, even if the implementation temporary writes
46 * to them. You can use DEBUG_POISON_POINTER so that the consumer which should
47 * no be looking at the field gets caught.
48 *
49 * DEBUG_POISON_POINTER(obj->ptr);
50 * ....
51 * if (obj->ptr != NULL) // traps with kasan, does not trap otherwise
52 * ....
53 * if (obj->ptr->field) // traps with and without kasan
54 */
55#ifdef	INVARIANTS
56
57#include <sys/asan.h>
58
59extern caddr_t poisoned_buf;
60#define DEBUG_POISON_POINTER_VALUE poisoned_buf
61
62#define DEBUG_POISON_POINTER(x) ({				\
63	x = (void *)(DEBUG_POISON_POINTER_VALUE);		\
64	kasan_mark(&x, 0, sizeof(x), KASAN_GENERIC_REDZONE);	\
65})
66
67#else
68#define DEBUG_POISON_POINTER(x)
69#endif
70
71#ifdef	INVARIANTS		/* The option is always available */
72#define	VNASSERT(exp, vp, msg) do {					\
73	if (__predict_false(!(exp))) {					\
74		vn_printf(vp, "VNASSERT failed: %s not true at %s:%d (%s)\n",\
75		   #exp, __FILE__, __LINE__, __func__);	 		\
76		kassert_panic msg;					\
77	}								\
78} while (0)
79#define	MPASSERT(exp, mp, msg) do {					\
80	if (__predict_false(!(exp))) {					\
81		printf("MPASSERT mp %p failed: %s not true at %s:%d (%s)\n",\
82		    (mp), #exp, __FILE__, __LINE__, __func__);		\
83		kassert_panic msg;					\
84	}								\
85} while (0)
86#define	VNPASS(exp, vp)	do {						\
87	const char *_exp = #exp;					\
88	VNASSERT(exp, vp, ("condition %s not met at %s:%d (%s)",	\
89	    _exp, __FILE__, __LINE__, __func__));			\
90} while (0)
91#define	MPPASS(exp, mp)	do {						\
92	const char *_exp = #exp;					\
93	MPASSERT(exp, mp, ("condition %s not met at %s:%d (%s)",	\
94	    _exp, __FILE__, __LINE__, __func__));			\
95} while (0)
96#define	__assert_unreachable() \
97	panic("executing segment marked as unreachable at %s:%d (%s)\n", \
98	    __FILE__, __LINE__, __func__)
99#else	/* INVARIANTS */
100#define	VNASSERT(exp, vp, msg) do { \
101} while (0)
102#define	MPASSERT(exp, mp, msg) do { \
103} while (0)
104#define	VNPASS(exp, vp) do { \
105} while (0)
106#define	MPPASS(exp, mp) do { \
107} while (0)
108#define	__assert_unreachable()	__unreachable()
109#endif	/* INVARIANTS */
110
111#ifndef CTASSERT	/* Allow lint to override */
112#define	CTASSERT(x)	_Static_assert(x, "compile-time assertion failed")
113#endif
114
115/*
116 * These functions need to be declared before the KASSERT macro is invoked in
117 * !KASSERT_PANIC_OPTIONAL builds, so their declarations are sort of out of
118 * place compared to other function definitions in this header.  On the other
119 * hand, this header is a bit disorganized anyway.
120 */
121void	panic(const char *, ...) __dead2 __printflike(1, 2);
122void	vpanic(const char *, __va_list) __dead2 __printflike(1, 0);
123#endif	/* _KERNEL */
124
125#if defined(_STANDALONE)
126/*
127 * Until we have more experience with KASSERTS that are called
128 * from the boot loader, they are off. The bootloader does this
129 * a little differently than the kernel (we just call printf atm).
130 * we avoid most of the common functions in the boot loader, so
131 * declare printf() here too.
132 */
133int	printf(const char *, ...) __printflike(1, 2);
134#  define kassert_panic printf
135#else /* !_STANDALONE */
136#  if defined(WITNESS) || defined(INVARIANT_SUPPORT)
137#    ifdef KASSERT_PANIC_OPTIONAL
138void	kassert_panic(const char *fmt, ...)  __printflike(1, 2);
139#    else
140#      define kassert_panic	panic
141#    endif /* KASSERT_PANIC_OPTIONAL */
142#  endif /* defined(WITNESS) || defined(INVARIANT_SUPPORT) */
143#endif /* _STANDALONE */
144
145/*
146 * Kernel assertion; see KASSERT(9) for details.
147 */
148#if (defined(_KERNEL) && defined(INVARIANTS)) || defined(_STANDALONE)
149#define	KASSERT(exp,msg) do {						\
150	if (__predict_false(!(exp)))					\
151		kassert_panic msg;					\
152} while (0)
153#else /* !(KERNEL && INVARIANTS) && !_STANDALONE */
154#define	KASSERT(exp,msg) do { \
155} while (0)
156#endif /* (_KERNEL && INVARIANTS) || _STANDALONE */
157
158#ifdef _KERNEL
159/*
160 * Macros for generating panic messages based on the exact condition text.
161 *
162 * NOTE: Use these with care, as the resulting message might omit key
163 * information required to understand the assertion failure. Consult the
164 * MPASS(9) man page for guidance.
165 */
166#define MPASS(ex)		MPASS4(ex, #ex, __FILE__, __LINE__)
167#define MPASS2(ex, what)	MPASS4(ex, what, __FILE__, __LINE__)
168#define MPASS3(ex, file, line)	MPASS4(ex, #ex, file, line)
169#define MPASS4(ex, what, file, line)					\
170	KASSERT((ex), ("Assertion %s failed at %s:%d", what, file, line))
171
172/*
173 * Assert that a pointer can be loaded from memory atomically.
174 *
175 * This assertion enforces stronger alignment than necessary.  For example,
176 * on some architectures, atomicity for unaligned loads will depend on
177 * whether or not the load spans multiple cache lines.
178 */
179#define	ASSERT_ATOMIC_LOAD_PTR(var, msg)				\
180	KASSERT(sizeof(var) == sizeof(void *) &&			\
181	    ((uintptr_t)&(var) & (sizeof(void *) - 1)) == 0, msg)
182/*
183 * Assert that a thread is in critical(9) section.
184 */
185#define	CRITICAL_ASSERT(td)						\
186	KASSERT((td)->td_critnest >= 1, ("Not in critical section"))
187
188#endif /* _KERNEL */
189
190#endif	/* _SYS_KASSERT_H_ */
191