1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26 /*
27 * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
28 * Copyright 2015 Joyent, Inc.
29 * Copyright 2020 Oxide Computer Company
30 */
31
32 #include "lint.h"
33 #include "libc.h"
34 #include "thr_uberdata.h"
35 #include <upanic.h>
36
37 const char *panicstr;
38 ulwp_t *panic_thread;
39
40 static mutex_t assert_lock = DEFAULTMUTEX;
41 static ulwp_t *assert_thread = NULL;
42
43 mutex_t *panic_mutex = NULL;
44
45 static void Abort(const char *, size_t) __NORETURN;
46
47 /*
48 * Called from __assert() to set panicstr and panic_thread.
49 */
50 void
__set_panicstr(const char * msg)51 __set_panicstr(const char *msg)
52 {
53 panicstr = msg;
54 panic_thread = __curthread();
55 }
56
57 /*
58 * Called from exit() (atexit function) to give precedence
59 * to assertion failures and a core dump over _exit().
60 */
61 void
grab_assert_lock()62 grab_assert_lock()
63 {
64 (void) _lwp_mutex_lock(&assert_lock);
65 }
66
67 static void
Abort(const char * msg,size_t buflen)68 Abort(const char *msg, size_t buflen)
69 {
70 ulwp_t *self;
71
72 /* to help with core file debugging */
73 panicstr = msg;
74 if ((self = __curthread()) != NULL) {
75 panic_thread = self;
76 }
77
78 upanic(msg, buflen);
79 }
80
81 /*
82 * Write a panic message w/o grabbing any locks other than assert_lock.
83 * We have no idea what locks are held at this point.
84 */
85 void
common_panic(const char * head,const char * why)86 common_panic(const char *head, const char *why)
87 {
88 char msg[400]; /* no panic() message in the library is this long */
89 ulwp_t *self;
90 size_t len1, len2;
91
92 if ((self = __curthread()) != NULL)
93 enter_critical(self);
94 (void) _lwp_mutex_lock(&assert_lock);
95
96 (void) memset(msg, 0, sizeof (msg));
97 (void) strcpy(msg, head);
98 len1 = strlen(msg);
99 len2 = strlen(why);
100 if (len1 + len2 >= sizeof (msg))
101 len2 = sizeof (msg) - len1 - 1;
102 (void) strncat(msg, why, len2);
103 len1 = strlen(msg);
104 if (msg[len1 - 1] != '\n')
105 msg[len1++] = '\n';
106 (void) __write(2, msg, len1);
107 Abort(msg, sizeof (msg));
108 }
109
110 void
thr_panic(const char * why)111 thr_panic(const char *why)
112 {
113 common_panic("*** libc thread failure: ", why);
114 }
115
116 void
aio_panic(const char * why)117 aio_panic(const char *why)
118 {
119 common_panic("*** libc aio system failure: ", why);
120 }
121
122 void
mutex_panic(mutex_t * mp,const char * why)123 mutex_panic(mutex_t *mp, const char *why)
124 {
125 panic_mutex = mp;
126 common_panic("*** libc mutex system failure: ", why);
127 }
128
129 /*
130 * Utility function for converting a long integer to a string, avoiding stdio.
131 * 'base' must be one of 10 or 16
132 */
133 void
ultos(uint64_t n,int base,char * s)134 ultos(uint64_t n, int base, char *s)
135 {
136 char lbuf[24]; /* 64 bits fits in 16 hex digits, 20 decimal */
137 char *cp = lbuf;
138
139 do {
140 *cp++ = "0123456789abcdef"[n%base];
141 n /= base;
142 } while (n);
143 if (base == 16) {
144 *s++ = '0';
145 *s++ = 'x';
146 }
147 do {
148 *s++ = *--cp;
149 } while (cp > lbuf);
150 *s = '\0';
151 }
152
153 /*
154 * Report application lock usage error for mutexes and condvars.
155 * Not called if _THREAD_ERROR_DETECTION=0.
156 * Continue execution if _THREAD_ERROR_DETECTION=1.
157 * Dump core if _THREAD_ERROR_DETECTION=2.
158 */
159 void
lock_error(const mutex_t * mp,const char * who,void * cv,const char * msg)160 lock_error(const mutex_t *mp, const char *who, void *cv, const char *msg)
161 {
162 mutex_t mcopy;
163 char buf[800];
164 uberdata_t *udp;
165 ulwp_t *self;
166 lwpid_t lwpid;
167 pid_t pid;
168
169 /*
170 * Take a snapshot of the mutex before it changes (we hope!).
171 * Use memcpy() rather than 'mcopy = *mp' in case mp is unaligned.
172 */
173 (void) memcpy(&mcopy, mp, sizeof (mcopy));
174
175 /* avoid recursion deadlock */
176 if ((self = __curthread()) != NULL) {
177 if (assert_thread == self)
178 _exit(127);
179 enter_critical(self);
180 (void) _lwp_mutex_lock(&assert_lock);
181 assert_thread = self;
182 lwpid = self->ul_lwpid;
183 udp = self->ul_uberdata;
184 pid = udp->pid;
185 } else {
186 self = NULL;
187 (void) _lwp_mutex_lock(&assert_lock);
188 lwpid = _lwp_self();
189 udp = &__uberdata;
190 pid = getpid();
191 }
192
193 (void) strcpy(buf,
194 "\n*** _THREAD_ERROR_DETECTION: lock usage error detected ***\n");
195 (void) strcat(buf, who);
196 (void) strcat(buf, "(");
197 if (cv != NULL) {
198 ultos((uint64_t)(uintptr_t)cv, 16, buf + strlen(buf));
199 (void) strcat(buf, ", ");
200 }
201 ultos((uint64_t)(uintptr_t)mp, 16, buf + strlen(buf));
202 (void) strcat(buf, ")");
203 if (msg != NULL) {
204 (void) strcat(buf, ": ");
205 (void) strcat(buf, msg);
206 } else if (!mutex_held(&mcopy)) {
207 (void) strcat(buf, ": calling thread does not own the lock");
208 } else if (mcopy.mutex_rcount) {
209 (void) strcat(buf, ": mutex rcount = ");
210 ultos((uint64_t)mcopy.mutex_rcount, 10, buf + strlen(buf));
211 } else {
212 (void) strcat(buf, ": calling thread already owns the lock");
213 }
214 (void) strcat(buf, "\ncalling thread is ");
215 ultos((uint64_t)(uintptr_t)self, 16, buf + strlen(buf));
216 (void) strcat(buf, " thread-id ");
217 ultos((uint64_t)lwpid, 10, buf + strlen(buf));
218 if (msg != NULL || mutex_held(&mcopy))
219 /* EMPTY */;
220 else if (mcopy.mutex_lockw == 0)
221 (void) strcat(buf, "\nthe lock is unowned");
222 else if (!(mcopy.mutex_type & USYNC_PROCESS)) {
223 (void) strcat(buf, "\nthe lock owner is ");
224 ultos((uint64_t)mcopy.mutex_owner, 16, buf + strlen(buf));
225 } else {
226 (void) strcat(buf, " in process ");
227 ultos((uint64_t)pid, 10, buf + strlen(buf));
228 (void) strcat(buf, "\nthe lock owner is ");
229 ultos((uint64_t)mcopy.mutex_owner, 16, buf + strlen(buf));
230 (void) strcat(buf, " in process ");
231 ultos((uint64_t)mcopy.mutex_ownerpid, 10, buf + strlen(buf));
232 }
233 (void) strcat(buf, "\n\n");
234 (void) __write(2, buf, strlen(buf));
235 if (udp->uberflags.uf_thread_error_detection >= 2)
236 Abort(buf, sizeof (buf));
237 assert_thread = NULL;
238 (void) _lwp_mutex_unlock(&assert_lock);
239 if (self != NULL)
240 exit_critical(self);
241 }
242
243 /*
244 * Report application lock usage error for rwlocks.
245 * Not called if _THREAD_ERROR_DETECTION=0.
246 * Continue execution if _THREAD_ERROR_DETECTION=1.
247 * Dump core if _THREAD_ERROR_DETECTION=2.
248 */
249 void
rwlock_error(const rwlock_t * rp,const char * who,const char * msg)250 rwlock_error(const rwlock_t *rp, const char *who, const char *msg)
251 {
252 rwlock_t rcopy;
253 uint32_t rwstate;
254 char buf[800];
255 uberdata_t *udp;
256 ulwp_t *self;
257 lwpid_t lwpid;
258 pid_t pid;
259 int process;
260
261 /*
262 * Take a snapshot of the rwlock before it changes (we hope!).
263 * Use memcpy() rather than 'rcopy = *rp' in case rp is unaligned.
264 */
265 (void) memcpy(&rcopy, rp, sizeof (rcopy));
266
267 /* avoid recursion deadlock */
268 if ((self = __curthread()) != NULL) {
269 if (assert_thread == self)
270 _exit(127);
271 enter_critical(self);
272 (void) _lwp_mutex_lock(&assert_lock);
273 assert_thread = self;
274 lwpid = self->ul_lwpid;
275 udp = self->ul_uberdata;
276 pid = udp->pid;
277 } else {
278 self = NULL;
279 (void) _lwp_mutex_lock(&assert_lock);
280 lwpid = _lwp_self();
281 udp = &__uberdata;
282 pid = getpid();
283 }
284
285 rwstate = (uint32_t)rcopy.rwlock_readers;
286 process = (rcopy.rwlock_type & USYNC_PROCESS);
287
288 (void) strcpy(buf,
289 "\n*** _THREAD_ERROR_DETECTION: lock usage error detected ***\n");
290 (void) strcat(buf, who);
291 (void) strcat(buf, "(");
292 ultos((uint64_t)(uintptr_t)rp, 16, buf + strlen(buf));
293 (void) strcat(buf, "): ");
294 (void) strcat(buf, msg);
295 (void) strcat(buf, "\ncalling thread is ");
296 ultos((uint64_t)(uintptr_t)self, 16, buf + strlen(buf));
297 (void) strcat(buf, " thread-id ");
298 ultos((uint64_t)lwpid, 10, buf + strlen(buf));
299 if (process) {
300 (void) strcat(buf, " in process ");
301 ultos((uint64_t)pid, 10, buf + strlen(buf));
302 }
303 if (rwstate & URW_WRITE_LOCKED) {
304 (void) strcat(buf, "\nthe writer lock owner is ");
305 ultos((uint64_t)rcopy.rwlock_owner, 16,
306 buf + strlen(buf));
307 if (process) {
308 (void) strcat(buf, " in process ");
309 ultos((uint64_t)rcopy.rwlock_ownerpid, 10,
310 buf + strlen(buf));
311 }
312 } else if (rwstate & URW_READERS_MASK) {
313 (void) strcat(buf, "\nthe reader lock is held by ");
314 ultos((uint64_t)(rwstate & URW_READERS_MASK), 10,
315 buf + strlen(buf));
316 (void) strcat(buf, " readers");
317 } else {
318 (void) strcat(buf, "\nthe lock is unowned");
319 }
320 if (rwstate & URW_HAS_WAITERS)
321 (void) strcat(buf, "\nand the lock appears to have waiters");
322 (void) strcat(buf, "\n\n");
323 (void) __write(2, buf, strlen(buf));
324 if (udp->uberflags.uf_thread_error_detection >= 2)
325 Abort(buf, sizeof (buf));
326 assert_thread = NULL;
327 (void) _lwp_mutex_unlock(&assert_lock);
328 if (self != NULL)
329 exit_critical(self);
330 }
331
332 /*
333 * Report a thread usage error.
334 * Not called if _THREAD_ERROR_DETECTION=0.
335 * Writes message and continues execution if _THREAD_ERROR_DETECTION=1.
336 * Writes message and dumps core if _THREAD_ERROR_DETECTION=2.
337 */
338 void
thread_error(const char * msg)339 thread_error(const char *msg)
340 {
341 char buf[800];
342 uberdata_t *udp;
343 ulwp_t *self;
344 lwpid_t lwpid;
345
346 /* avoid recursion deadlock */
347 if ((self = __curthread()) != NULL) {
348 if (assert_thread == self)
349 _exit(127);
350 enter_critical(self);
351 (void) _lwp_mutex_lock(&assert_lock);
352 assert_thread = self;
353 lwpid = self->ul_lwpid;
354 udp = self->ul_uberdata;
355 } else {
356 self = NULL;
357 (void) _lwp_mutex_lock(&assert_lock);
358 lwpid = _lwp_self();
359 udp = &__uberdata;
360 }
361
362 (void) strcpy(buf, "\n*** _THREAD_ERROR_DETECTION: "
363 "thread usage error detected ***\n*** ");
364 (void) strcat(buf, msg);
365
366 (void) strcat(buf, "\n*** calling thread is ");
367 ultos((uint64_t)(uintptr_t)self, 16, buf + strlen(buf));
368 (void) strcat(buf, " thread-id ");
369 ultos((uint64_t)lwpid, 10, buf + strlen(buf));
370 (void) strcat(buf, "\n\n");
371 (void) __write(2, buf, strlen(buf));
372 if (udp->uberflags.uf_thread_error_detection >= 2)
373 Abort(buf, sizeof (buf));
374 assert_thread = NULL;
375 (void) _lwp_mutex_unlock(&assert_lock);
376 if (self != NULL)
377 exit_critical(self);
378 }
379
380 /*
381 * We use __assfail() because the libc __assert() calls
382 * gettext() which calls malloc() which grabs a mutex.
383 * We do everything without calling standard i/o.
384 * assfail() and _assfail() are exported functions;
385 * __assfail() is private to libc.
386 */
387 #pragma weak _assfail = __assfail
388 void
__assfail(const char * assertion,const char * filename,int line_num)389 __assfail(const char *assertion, const char *filename, int line_num)
390 {
391 char buf[800]; /* no assert() message in the library is this long */
392 ulwp_t *self;
393 lwpid_t lwpid;
394
395 /* avoid recursion deadlock */
396 if ((self = __curthread()) != NULL) {
397 if (assert_thread == self)
398 _exit(127);
399 enter_critical(self);
400 (void) _lwp_mutex_lock(&assert_lock);
401 assert_thread = self;
402 lwpid = self->ul_lwpid;
403 } else {
404 self = NULL;
405 (void) _lwp_mutex_lock(&assert_lock);
406 lwpid = _lwp_self();
407 }
408
409 /*
410 * This is a hack, but since the Abort function isn't exported
411 * to outside consumers, libzpool's vpanic() function calls
412 * assfail() with a filename set to NULL. In that case, it'd be
413 * best not to print "assertion failed" since it was a panic and
414 * not an assertion failure.
415 */
416 if (filename == NULL) {
417 (void) strcpy(buf, "failure for thread ");
418 } else {
419 (void) strcpy(buf, "assertion failed for thread ");
420 }
421
422 ultos((uint64_t)(uintptr_t)self, 16, buf + strlen(buf));
423 (void) strcat(buf, ", thread-id ");
424 ultos((uint64_t)lwpid, 10, buf + strlen(buf));
425 (void) strcat(buf, ": ");
426 (void) strcat(buf, assertion);
427
428 if (filename != NULL) {
429 (void) strcat(buf, ", file ");
430 (void) strcat(buf, filename);
431 (void) strcat(buf, ", line ");
432 ultos((uint64_t)line_num, 10, buf + strlen(buf));
433 }
434
435 (void) strcat(buf, "\n");
436 (void) __write(2, buf, strlen(buf));
437 /*
438 * We could replace the call to Abort() with the following code
439 * if we want just to issue a warning message and not die.
440 * assert_thread = NULL;
441 * _lwp_mutex_unlock(&assert_lock);
442 * if (self != NULL)
443 * exit_critical(self);
444 */
445 Abort(buf, sizeof (buf));
446 }
447
448 /*
449 * We define and export this version of assfail() just because libaio
450 * used to define and export it, needlessly. Now that libaio is folded
451 * into libc, we need to continue this for ABI/version reasons.
452 * We don't use "#pragma weak assfail __assfail" in order to avoid
453 * warnings from the check_fnames utility at build time for libraries
454 * that define their own version of assfail().
455 *
456 * Additionally, ASSERT() and VERIFY() in <sys/debug.h> can invoke assfail().
457 *
458 * We would like this to be declared _NORETURN, but some caution is in order
459 * as alternate implementations of assfail() exist -- notably the one in
460 * libfakekernel -- which can return under some circumstances.
461 */
462 void
assfail(const char * assertion,const char * filename,int line_num)463 assfail(const char *assertion, const char *filename, int line_num)
464 {
465 __assfail(assertion, filename, line_num);
466 /* NOTREACHED */
467 }
468
469 void
assfail3(const char * assertion,uintmax_t lv,const char * op,uintmax_t rv,const char * filename,int line_num)470 assfail3(const char *assertion, uintmax_t lv, const char *op, uintmax_t rv,
471 const char *filename, int line_num)
472 {
473 char buf[1000];
474 (void) strcpy(buf, assertion);
475 (void) strcat(buf, " (");
476 ultos((uint64_t)lv, 16, buf + strlen(buf));
477 (void) strcat(buf, " ");
478 (void) strcat(buf, op);
479 (void) strcat(buf, " ");
480 ultos((uint64_t)rv, 16, buf + strlen(buf));
481 (void) strcat(buf, ")");
482 __assfail(buf, filename, line_num);
483 }
484