ubsan.c revision 1.7 1 /* $NetBSD: ubsan.c,v 1.7 2019/10/04 12:12:47 mrg Exp $ */
2
3 /*-
4 * Copyright (c) 2018 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29
30 /*
31 * The micro UBSan implementation for the userland (uUBSan) and kernel (kUBSan).
32 * The uBSSan versions is suitable for inclusion into libc or used standalone
33 * with ATF tests.
34 *
35 * This file due to long symbol names generated by a compiler during the
36 * instrumentation process does not follow the KNF style with 80-column limit.
37 */
38
39 #include <sys/cdefs.h>
40 #if defined(_KERNEL)
41 __KERNEL_RCSID(0, "$NetBSD: ubsan.c,v 1.7 2019/10/04 12:12:47 mrg Exp $");
42 #else
43 __RCSID("$NetBSD: ubsan.c,v 1.7 2019/10/04 12:12:47 mrg Exp $");
44 #endif
45
46 #if defined(_KERNEL)
47 #include <sys/param.h>
48 #include <sys/types.h>
49 #include <sys/stdarg.h>
50 #define ASSERT(x) KASSERT(x)
51 #else
52 #if defined(_LIBC)
53 #include "namespace.h"
54 #endif
55 #include <sys/param.h>
56 #include <assert.h>
57 #include <inttypes.h>
58 #include <math.h>
59 #include <signal.h>
60 #include <stdarg.h>
61 #include <stdbool.h>
62 #include <stdint.h>
63 #include <stdio.h>
64 #include <stdlib.h>
65 #include <string.h>
66 #include <syslog.h>
67 #include <unistd.h>
68 #if defined(_LIBC)
69 #include "extern.h"
70 #define ubsan_vsyslog vsyslog_ss
71 #define ASSERT(x) _DIAGASSERT(x)
72 #else
73 #define ubsan_vsyslog vsyslog_r
74 #define ASSERT(x) assert(x)
75 #endif
76 /* These macros are available in _KERNEL only */
77 #define SET(t, f) ((t) |= (f))
78 #define ISSET(t, f) ((t) & (f))
79 #define CLR(t, f) ((t) &= ~(f))
80 #endif
81
82 #ifdef UBSAN_ALWAYS_FATAL
83 static const bool alwaysFatal = true;
84 #else
85 static const bool alwaysFatal = false;
86 #endif
87
88 #define REINTERPRET_CAST(__dt, __st) ((__dt)(__st))
89 #define STATIC_CAST(__dt, __st) ((__dt)(__st))
90
91 #define ACK_REPORTED __BIT(31)
92
93 #define MUL_STRING "*"
94 #define PLUS_STRING "+"
95 #define MINUS_STRING "-"
96 #define DIVREM_STRING "divrem"
97
98 #define CFI_VCALL 0
99 #define CFI_NVCALL 1
100 #define CFI_DERIVEDCAST 2
101 #define CFI_UNRELATEDCAST 3
102 #define CFI_ICALL 4
103 #define CFI_NVMFCALL 5
104 #define CFI_VMFCALL 6
105
106 #define NUMBER_MAXLEN 128
107 #define LOCATION_MAXLEN (PATH_MAX + 32 /* ':LINE:COLUMN' */)
108
109 #define WIDTH_8 8
110 #define WIDTH_16 16
111 #define WIDTH_32 32
112 #define WIDTH_64 64
113 #define WIDTH_80 80
114 #define WIDTH_96 96
115 #define WIDTH_128 128
116
117 #define NUMBER_SIGNED_BIT 1U
118
119 #ifdef __SIZEOF_INT128__
120 typedef __int128 longest;
121 typedef unsigned __int128 ulongest;
122 #else
123 typedef int64_t longest;
124 typedef uint64_t ulongest;
125 #endif
126
127 #ifndef _KERNEL
128 static int ubsan_flags = -1;
129 #define UBSAN_ABORT __BIT(0)
130 #define UBSAN_STDOUT __BIT(1)
131 #define UBSAN_STDERR __BIT(2)
132 #define UBSAN_SYSLOG __BIT(3)
133 #endif
134
135 /* Undefined Behavior specific defines and structures */
136
137 #define KIND_INTEGER 0
138 #define KIND_FLOAT 1
139 #define KIND_UNKNOWN UINT16_MAX
140
141 struct CSourceLocation {
142 char *mFilename;
143 uint32_t mLine;
144 uint32_t mColumn;
145 };
146
147 struct CTypeDescriptor {
148 uint16_t mTypeKind;
149 uint16_t mTypeInfo;
150 uint8_t mTypeName[1];
151 };
152
153 struct COverflowData {
154 struct CSourceLocation mLocation;
155 struct CTypeDescriptor *mType;
156 };
157
158 struct CUnreachableData {
159 struct CSourceLocation mLocation;
160 };
161
162 struct CCFICheckFailData {
163 uint8_t mCheckKind;
164 struct CSourceLocation mLocation;
165 struct CTypeDescriptor *mType;
166 };
167
168 struct CDynamicTypeCacheMissData {
169 struct CSourceLocation mLocation;
170 struct CTypeDescriptor *mType;
171 void *mTypeInfo;
172 uint8_t mTypeCheckKind;
173 };
174
175 struct CFunctionTypeMismatchData {
176 struct CSourceLocation mLocation;
177 struct CTypeDescriptor *mType;
178 };
179
180 struct CInvalidBuiltinData {
181 struct CSourceLocation mLocation;
182 uint8_t mKind;
183 };
184
185 struct CInvalidValueData {
186 struct CSourceLocation mLocation;
187 struct CTypeDescriptor *mType;
188 };
189
190 struct CNonNullArgData {
191 struct CSourceLocation mLocation;
192 struct CSourceLocation mAttributeLocation;
193 int mArgIndex;
194 };
195
196 struct CNonNullReturnData {
197 struct CSourceLocation mAttributeLocation;
198 };
199
200 struct COutOfBoundsData {
201 struct CSourceLocation mLocation;
202 struct CTypeDescriptor *mArrayType;
203 struct CTypeDescriptor *mIndexType;
204 };
205
206 struct CPointerOverflowData {
207 struct CSourceLocation mLocation;
208 };
209
210 struct CShiftOutOfBoundsData {
211 struct CSourceLocation mLocation;
212 struct CTypeDescriptor *mLHSType;
213 struct CTypeDescriptor *mRHSType;
214 };
215
216 struct CTypeMismatchData {
217 struct CSourceLocation mLocation;
218 struct CTypeDescriptor *mType;
219 unsigned long mLogAlignment;
220 uint8_t mTypeCheckKind;
221 };
222
223 struct CTypeMismatchData_v1 {
224 struct CSourceLocation mLocation;
225 struct CTypeDescriptor *mType;
226 uint8_t mLogAlignment;
227 uint8_t mTypeCheckKind;
228 };
229
230 struct CVLABoundData {
231 struct CSourceLocation mLocation;
232 struct CTypeDescriptor *mType;
233 };
234
235 struct CFloatCastOverflowData {
236 struct CSourceLocation mLocation; /* This field exists in this struct since 2015 August 11th */
237 struct CTypeDescriptor *mFromType;
238 struct CTypeDescriptor *mToType;
239 };
240
241 /* Local utility functions */
242 static void Report(bool isFatal, const char *pFormat, ...) __printflike(2, 3);
243 static bool isAlreadyReported(struct CSourceLocation *pLocation);
244 static size_t zDeserializeTypeWidth(struct CTypeDescriptor *pType);
245 static void DeserializeLocation(char *pBuffer, size_t zBUfferLength, struct CSourceLocation *pLocation);
246 #ifdef __SIZEOF_INT128__
247 static void DeserializeUINT128(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, __uint128_t U128);
248 #endif
249 static void DeserializeNumberSigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, longest L);
250 static void DeserializeNumberUnsigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, ulongest L);
251 #ifndef _KERNEL
252 static void DeserializeFloatOverPointer(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long *pNumber);
253 static void DeserializeFloatInlined(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber);
254 #endif
255 static longest llliGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber);
256 static ulongest llluGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber);
257 #ifndef _KERNEL
258 static void DeserializeNumberFloat(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber);
259 #endif
260 static void DeserializeNumber(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber);
261 static const char *DeserializeTypeCheckKind(uint8_t hhuTypeCheckKind);
262 static const char *DeserializeBuiltinCheckKind(uint8_t hhuBuiltinCheckKind);
263 static const char *DeserializeCFICheckKind(uint8_t hhuCFICheckKind);
264 static bool isNegativeNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber);
265 static bool isShiftExponentTooLarge(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber, size_t zWidth);
266
267 /* Unused in this implementation, emitted by the C++ check dynamic type cast. */
268 intptr_t __ubsan_vptr_type_cache[128];
269
270 /* Public symbols used in the instrumentation of the code generation part */
271 void __ubsan_handle_add_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
272 void __ubsan_handle_add_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
273 void __ubsan_handle_builtin_unreachable(struct CUnreachableData *pData);
274 void __ubsan_handle_cfi_bad_type(struct CCFICheckFailData *pData, unsigned long ulVtable, bool bValidVtable, bool FromUnrecoverableHandler, unsigned long ProgramCounter, unsigned long FramePointer);
275 void __ubsan_handle_cfi_check_fail(struct CCFICheckFailData *pData, unsigned long ulValue, unsigned long ulValidVtable);
276 void __ubsan_handle_cfi_check_fail_abort(struct CCFICheckFailData *pData, unsigned long ulValue, unsigned long ulValidVtable);
277 void __ubsan_handle_divrem_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
278 void __ubsan_handle_divrem_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
279 void __ubsan_handle_dynamic_type_cache_miss(struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash);
280 void __ubsan_handle_dynamic_type_cache_miss_abort(struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash);
281 void __ubsan_handle_float_cast_overflow(struct CFloatCastOverflowData *pData, unsigned long ulFrom);
282 void __ubsan_handle_float_cast_overflow_abort(struct CFloatCastOverflowData *pData, unsigned long ulFrom);
283 void __ubsan_handle_function_type_mismatch(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction);
284 void __ubsan_handle_function_type_mismatch_abort(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction);
285 void __ubsan_handle_invalid_builtin(struct CInvalidBuiltinData *pData);
286 void __ubsan_handle_invalid_builtin_abort(struct CInvalidBuiltinData *pData);
287 void __ubsan_handle_load_invalid_value(struct CInvalidValueData *pData, unsigned long ulVal);
288 void __ubsan_handle_load_invalid_value_abort(struct CInvalidValueData *pData, unsigned long ulVal);
289 void __ubsan_handle_missing_return(struct CUnreachableData *pData);
290 void __ubsan_handle_mul_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
291 void __ubsan_handle_mul_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
292 void __ubsan_handle_negate_overflow(struct COverflowData *pData, unsigned long ulOldVal);
293 void __ubsan_handle_negate_overflow_abort(struct COverflowData *pData, unsigned long ulOldVal);
294 void __ubsan_handle_nonnull_arg(struct CNonNullArgData *pData);
295 void __ubsan_handle_nonnull_arg_abort(struct CNonNullArgData *pData);
296 void __ubsan_handle_nonnull_return_v1(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
297 void __ubsan_handle_nonnull_return_v1_abort(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
298 void __ubsan_handle_nullability_arg(struct CNonNullArgData *pData);
299 void __ubsan_handle_nullability_arg_abort(struct CNonNullArgData *pData);
300 void __ubsan_handle_nullability_return_v1(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
301 void __ubsan_handle_nullability_return_v1_abort(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
302 void __ubsan_handle_out_of_bounds(struct COutOfBoundsData *pData, unsigned long ulIndex);
303 void __ubsan_handle_out_of_bounds_abort(struct COutOfBoundsData *pData, unsigned long ulIndex);
304 void __ubsan_handle_pointer_overflow(struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult);
305 void __ubsan_handle_pointer_overflow_abort(struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult);
306 void __ubsan_handle_shift_out_of_bounds(struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS);
307 void __ubsan_handle_shift_out_of_bounds_abort(struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS);
308 void __ubsan_handle_sub_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
309 void __ubsan_handle_sub_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
310 void __ubsan_handle_type_mismatch(struct CTypeMismatchData *pData, unsigned long ulPointer);
311 void __ubsan_handle_type_mismatch_abort(struct CTypeMismatchData *pData, unsigned long ulPointer);
312 void __ubsan_handle_type_mismatch_v1(struct CTypeMismatchData_v1 *pData, unsigned long ulPointer);
313 void __ubsan_handle_type_mismatch_v1_abort(struct CTypeMismatchData_v1 *pData, unsigned long ulPointer);
314 void __ubsan_handle_vla_bound_not_positive(struct CVLABoundData *pData, unsigned long ulBound);
315 void __ubsan_handle_vla_bound_not_positive_abort(struct CVLABoundData *pData, unsigned long ulBound);
316 void __ubsan_get_current_report_data(const char **ppOutIssueKind, const char **ppOutMessage, const char **ppOutFilename, uint32_t *pOutLine, uint32_t *pOutCol, char **ppOutMemoryAddr);
317
318 static void HandleOverflow(bool isFatal, struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS, const char *szOperation);
319 static void HandleNegateOverflow(bool isFatal, struct COverflowData *pData, unsigned long ulOldValue);
320 static void HandleBuiltinUnreachable(bool isFatal, struct CUnreachableData *pData);
321 static void HandleTypeMismatch(bool isFatal, struct CSourceLocation *mLocation, struct CTypeDescriptor *mType, unsigned long mLogAlignment, uint8_t mTypeCheckKind, unsigned long ulPointer);
322 static void HandleVlaBoundNotPositive(bool isFatal, struct CVLABoundData *pData, unsigned long ulBound);
323 static void HandleOutOfBounds(bool isFatal, struct COutOfBoundsData *pData, unsigned long ulIndex);
324 static void HandleShiftOutOfBounds(bool isFatal, struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS);
325 static void HandleLoadInvalidValue(bool isFatal, struct CInvalidValueData *pData, unsigned long ulValue);
326 static void HandleInvalidBuiltin(bool isFatal, struct CInvalidBuiltinData *pData);
327 static void HandleFunctionTypeMismatch(bool isFatal, struct CFunctionTypeMismatchData *pData, unsigned long ulFunction);
328 static void HandleCFIBadType(bool isFatal, struct CCFICheckFailData *pData, unsigned long ulVtable, bool *bValidVtable, bool *FromUnrecoverableHandler, unsigned long *ProgramCounter, unsigned long *FramePointer);
329 static void HandleDynamicTypeCacheMiss(bool isFatal, struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash);
330 static void HandleFloatCastOverflow(bool isFatal, struct CFloatCastOverflowData *pData, unsigned long ulFrom);
331 static void HandleMissingReturn(bool isFatal, struct CUnreachableData *pData);
332 static void HandleNonnullArg(bool isFatal, struct CNonNullArgData *pData);
333 static void HandleNonnullReturn(bool isFatal, struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
334 static void HandlePointerOverflow(bool isFatal, struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult);
335
336 static void
337 HandleOverflow(bool isFatal, struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS, const char *szOperation)
338 {
339 char szLocation[LOCATION_MAXLEN];
340 char szLHS[NUMBER_MAXLEN];
341 char szRHS[NUMBER_MAXLEN];
342
343 ASSERT(pData);
344
345 if (isAlreadyReported(&pData->mLocation))
346 return;
347
348 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
349 DeserializeNumber(szLocation, szLHS, NUMBER_MAXLEN, pData->mType, ulLHS);
350 DeserializeNumber(szLocation, szRHS, NUMBER_MAXLEN, pData->mType, ulRHS);
351
352 Report(isFatal, "UBSan: Undefined Behavior in %s, %s integer overflow: %s %s %s cannot be represented in type %s\n",
353 szLocation, ISSET(pData->mType->mTypeInfo, NUMBER_SIGNED_BIT) ? "signed" : "unsigned", szLHS, szOperation, szRHS, pData->mType->mTypeName);
354 }
355
356 static void
357 HandleNegateOverflow(bool isFatal, struct COverflowData *pData, unsigned long ulOldValue)
358 {
359 char szLocation[LOCATION_MAXLEN];
360 char szOldValue[NUMBER_MAXLEN];
361
362 ASSERT(pData);
363
364 if (isAlreadyReported(&pData->mLocation))
365 return;
366
367 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
368 DeserializeNumber(szLocation, szOldValue, NUMBER_MAXLEN, pData->mType, ulOldValue);
369
370 Report(isFatal, "UBSan: Undefined Behavior in %s, negation of %s cannot be represented in type %s\n",
371 szLocation, szOldValue, pData->mType->mTypeName);
372 }
373
374 static void
375 HandleBuiltinUnreachable(bool isFatal, struct CUnreachableData *pData)
376 {
377 char szLocation[LOCATION_MAXLEN];
378
379 ASSERT(pData);
380
381 if (isAlreadyReported(&pData->mLocation))
382 return;
383
384 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
385
386 Report(isFatal, "UBSan: Undefined Behavior in %s, calling __builtin_unreachable()\n",
387 szLocation);
388 }
389
390 static void
391 HandleTypeMismatch(bool isFatal, struct CSourceLocation *mLocation, struct CTypeDescriptor *mType, unsigned long mLogAlignment, uint8_t mTypeCheckKind, unsigned long ulPointer)
392 {
393 char szLocation[LOCATION_MAXLEN];
394
395 ASSERT(mLocation);
396 ASSERT(mType);
397
398 if (isAlreadyReported(mLocation))
399 return;
400
401 DeserializeLocation(szLocation, LOCATION_MAXLEN, mLocation);
402
403 if (ulPointer == 0) {
404 Report(isFatal, "UBSan: Undefined Behavior in %s, %s null pointer of type %s\n",
405 szLocation, DeserializeTypeCheckKind(mTypeCheckKind), mType->mTypeName);
406 } else if ((mLogAlignment - 1) & ulPointer) {
407 Report(isFatal, "UBSan: Undefined Behavior in %s, %s misaligned address %p for type %s which requires %ld byte alignment\n",
408 szLocation, DeserializeTypeCheckKind(mTypeCheckKind), REINTERPRET_CAST(void *, ulPointer), mType->mTypeName, mLogAlignment);
409 } else {
410 Report(isFatal, "UBSan: Undefined Behavior in %s, %s address %p with insufficient space for an object of type %s\n",
411 szLocation, DeserializeTypeCheckKind(mTypeCheckKind), REINTERPRET_CAST(void *, ulPointer), mType->mTypeName);
412 }
413 }
414
415 static void
416 HandleVlaBoundNotPositive(bool isFatal, struct CVLABoundData *pData, unsigned long ulBound)
417 {
418 char szLocation[LOCATION_MAXLEN];
419 char szBound[NUMBER_MAXLEN];
420
421 ASSERT(pData);
422
423 if (isAlreadyReported(&pData->mLocation))
424 return;
425
426 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
427 DeserializeNumber(szLocation, szBound, NUMBER_MAXLEN, pData->mType, ulBound);
428
429 Report(isFatal, "UBSan: Undefined Behavior in %s, variable length array bound value %s <= 0\n",
430 szLocation, szBound);
431 }
432
433 static void
434 HandleOutOfBounds(bool isFatal, struct COutOfBoundsData *pData, unsigned long ulIndex)
435 {
436 char szLocation[LOCATION_MAXLEN];
437 char szIndex[NUMBER_MAXLEN];
438
439 ASSERT(pData);
440
441 if (isAlreadyReported(&pData->mLocation))
442 return;
443
444 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
445 DeserializeNumber(szLocation, szIndex, NUMBER_MAXLEN, pData->mIndexType, ulIndex);
446
447 Report(isFatal, "UBSan: Undefined Behavior in %s, index %s is out of range for type %s\n",
448 szLocation, szIndex, pData->mArrayType->mTypeName);
449 }
450
451 static void
452 HandleShiftOutOfBounds(bool isFatal, struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS)
453 {
454 char szLocation[LOCATION_MAXLEN];
455 char szLHS[NUMBER_MAXLEN];
456 char szRHS[NUMBER_MAXLEN];
457
458 ASSERT(pData);
459
460 if (isAlreadyReported(&pData->mLocation))
461 return;
462
463 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
464 DeserializeNumber(szLocation, szLHS, NUMBER_MAXLEN, pData->mLHSType, ulLHS);
465 DeserializeNumber(szLocation, szRHS, NUMBER_MAXLEN, pData->mRHSType, ulRHS);
466
467 if (isNegativeNumber(szLocation, pData->mRHSType, ulRHS))
468 Report(isFatal, "UBSan: Undefined Behavior in %s, shift exponent %s is negative\n",
469 szLocation, szRHS);
470 else if (isShiftExponentTooLarge(szLocation, pData->mRHSType, ulRHS, zDeserializeTypeWidth(pData->mLHSType)))
471 Report(isFatal, "UBSan: Undefined Behavior in %s, shift exponent %s is too large for %zu-bit type %s\n",
472 szLocation, szRHS, zDeserializeTypeWidth(pData->mLHSType), pData->mLHSType->mTypeName);
473 else if (isNegativeNumber(szLocation, pData->mLHSType, ulLHS))
474 Report(isFatal, "UBSan: Undefined Behavior in %s, left shift of negative value %s\n",
475 szLocation, szLHS);
476 else
477 Report(isFatal, "UBSan: Undefined Behavior in %s, left shift of %s by %s places cannot be represented in type %s\n",
478 szLocation, szLHS, szRHS, pData->mLHSType->mTypeName);
479 }
480
481 static void
482 HandleLoadInvalidValue(bool isFatal, struct CInvalidValueData *pData, unsigned long ulValue)
483 {
484 char szLocation[LOCATION_MAXLEN];
485 char szValue[NUMBER_MAXLEN];
486
487 ASSERT(pData);
488
489 if (isAlreadyReported(&pData->mLocation))
490 return;
491
492 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
493 DeserializeNumber(szLocation, szValue, NUMBER_MAXLEN, pData->mType, ulValue);
494
495 Report(isFatal, "UBSan: Undefined Behavior in %s, load of value %s is not a valid value for type %s\n",
496 szLocation, szValue, pData->mType->mTypeName);
497 }
498
499 static void
500 HandleInvalidBuiltin(bool isFatal, struct CInvalidBuiltinData *pData)
501 {
502 char szLocation[LOCATION_MAXLEN];
503
504 ASSERT(pData);
505
506 if (isAlreadyReported(&pData->mLocation))
507 return;
508
509 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
510
511 Report(isFatal, "UBSan: Undefined Behavior in %s, passing zero to %s, which is not a valid argument\n",
512 szLocation, DeserializeBuiltinCheckKind(pData->mKind));
513 }
514
515 static void
516 HandleFunctionTypeMismatch(bool isFatal, struct CFunctionTypeMismatchData *pData, unsigned long ulFunction)
517 {
518 char szLocation[LOCATION_MAXLEN];
519
520 /*
521 * There is no a portable C solution to translate an address of a
522 * function to its name. On the cost of getting this routine simple
523 * and portable without ifdefs between the userland and the kernel
524 * just print the address of the function as-is.
525 *
526 * For better diagnostic messages in the userland, users shall use
527 * the full upstream version shipped along with the compiler toolchain.
528 */
529
530 ASSERT(pData);
531
532 if (isAlreadyReported(&pData->mLocation))
533 return;
534
535 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
536
537 Report(isFatal, "UBSan: Undefined Behavior in %s, call to function %#lx through pointer to incorrect function type %s\n",
538 szLocation, ulFunction, pData->mType->mTypeName);
539 }
540
541 static void
542 HandleCFIBadType(bool isFatal, struct CCFICheckFailData *pData, unsigned long ulVtable, bool *bValidVtable, bool *FromUnrecoverableHandler, unsigned long *ProgramCounter, unsigned long *FramePointer)
543 {
544 char szLocation[LOCATION_MAXLEN];
545
546 /*
547 * This is a minimal implementation without diving into C++
548 * specifics and (Itanium) ABI deserialization.
549 */
550
551 ASSERT(pData);
552
553 if (isAlreadyReported(&pData->mLocation))
554 return;
555
556 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
557
558 if (pData->mCheckKind == CFI_ICALL || pData->mCheckKind == CFI_VMFCALL) {
559 Report(isFatal, "UBSan: Undefined Behavior in %s, control flow integrity check for type %s failed during %s (vtable address %#lx)\n",
560 szLocation, pData->mType->mTypeName, DeserializeCFICheckKind(pData->mCheckKind), ulVtable);
561 } else {
562 Report(isFatal || FromUnrecoverableHandler, "UBSan: Undefined Behavior in %s, control flow integrity check for type %s failed during %s (vtable address %#lx; %s vtable; from %s handler; Program Counter %#lx; Frame Pointer %#lx)\n",
563 szLocation, pData->mType->mTypeName, DeserializeCFICheckKind(pData->mCheckKind), ulVtable, *bValidVtable ? "valid" : "invalid", *FromUnrecoverableHandler ? "unrecoverable" : "recoverable", *ProgramCounter, *FramePointer);
564 }
565 }
566
567 static void
568 HandleDynamicTypeCacheMiss(bool isFatal, struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash)
569 {
570 #if 0
571 char szLocation[LOCATION_MAXLEN];
572
573 /*
574 * Unimplemented.
575 *
576 * This UBSan handler is special as the check has to be impelemented
577 * in an implementation. In order to handle it there is need to
578 * introspect into C++ ABI internals (RTTI) and use low-level
579 * C++ runtime interfaces.
580 */
581
582 ASSERT(pData);
583
584 if (isAlreadyReported(&pData->mLocation))
585 return;
586
587 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
588
589 Report(isFatal, "UBSan: Undefined Behavior in %s, %s address %#lx which might not point to an object of type %s\n"
590 szLocation, DeserializeTypeCheckKind(pData->mTypeCheckKind), ulPointer, pData->mType);
591 #endif
592 }
593
594 static void
595 HandleFloatCastOverflow(bool isFatal, struct CFloatCastOverflowData *pData, unsigned long ulFrom)
596 {
597 char szLocation[LOCATION_MAXLEN];
598 char szFrom[NUMBER_MAXLEN];
599
600 ASSERT(pData);
601
602 if (isAlreadyReported(&pData->mLocation))
603 return;
604
605 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
606 DeserializeNumber(szLocation, szFrom, NUMBER_MAXLEN, pData->mFromType, ulFrom);
607
608 Report(isFatal, "UBSan: Undefined Behavior in %s, %s (of type %s) is outside the range of representable values of type %s\n",
609 szLocation, szFrom, pData->mFromType->mTypeName, pData->mToType->mTypeName);
610 }
611
612 static void
613 HandleMissingReturn(bool isFatal, struct CUnreachableData *pData)
614 {
615 char szLocation[LOCATION_MAXLEN];
616
617 ASSERT(pData);
618
619 if (isAlreadyReported(&pData->mLocation))
620 return;
621
622 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
623
624 Report(isFatal, "UBSan: Undefined Behavior in %s, execution reached the end of a value-returning function without returning a value\n",
625 szLocation);
626 }
627
628 static void
629 HandleNonnullArg(bool isFatal, struct CNonNullArgData *pData)
630 {
631 char szLocation[LOCATION_MAXLEN];
632 char szAttributeLocation[LOCATION_MAXLEN];
633
634 ASSERT(pData);
635
636 if (isAlreadyReported(&pData->mLocation))
637 return;
638
639 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
640 if (pData->mAttributeLocation.mFilename)
641 DeserializeLocation(szAttributeLocation, LOCATION_MAXLEN, &pData->mAttributeLocation);
642 else
643 szAttributeLocation[0] = '\0';
644
645 Report(isFatal, "UBSan: Undefined Behavior in %s, null pointer passed as argument %d, which is declared to never be null%s%s\n",
646 szLocation, pData->mArgIndex, pData->mAttributeLocation.mFilename ? ", nonnull/_Nonnull specified in " : "", szAttributeLocation);
647 }
648
649 static void
650 HandleNonnullReturn(bool isFatal, struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
651 {
652 char szLocation[LOCATION_MAXLEN];
653 char szAttributeLocation[LOCATION_MAXLEN];
654
655 ASSERT(pData);
656 ASSERT(pLocationPointer);
657
658 if (isAlreadyReported(pLocationPointer))
659 return;
660
661 DeserializeLocation(szLocation, LOCATION_MAXLEN, pLocationPointer);
662 if (pData->mAttributeLocation.mFilename)
663 DeserializeLocation(szAttributeLocation, LOCATION_MAXLEN, &pData->mAttributeLocation);
664 else
665 szAttributeLocation[0] = '\0';
666
667 Report(isFatal, "UBSan: Undefined Behavior in %s, null pointer returned from function declared to never return null%s%s\n",
668 szLocation, pData->mAttributeLocation.mFilename ? ", nonnull/_Nonnull specified in " : "", szAttributeLocation);
669 }
670
671 static void
672 HandlePointerOverflow(bool isFatal, struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult)
673 {
674 char szLocation[LOCATION_MAXLEN];
675
676 ASSERT(pData);
677
678 if (isAlreadyReported(&pData->mLocation))
679 return;
680
681 DeserializeLocation(szLocation, LOCATION_MAXLEN, &pData->mLocation);
682
683 Report(isFatal, "UBSan: Undefined Behavior in %s, pointer expression with base %#lx overflowed to %#lx\n",
684 szLocation, ulBase, ulResult);
685 }
686
687 /* Definions of public symbols emitted by the instrumentation code */
688 void
689 __ubsan_handle_add_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
690 {
691
692 ASSERT(pData);
693
694 HandleOverflow(false, pData, ulLHS, ulRHS, PLUS_STRING);
695 }
696
697 void
698 __ubsan_handle_add_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
699 {
700
701 ASSERT(pData);
702
703 HandleOverflow(true, pData, ulLHS, ulRHS, PLUS_STRING);
704 }
705
706 void
707 __ubsan_handle_builtin_unreachable(struct CUnreachableData *pData)
708 {
709
710 ASSERT(pData);
711
712 HandleBuiltinUnreachable(true, pData);
713 }
714
715 void
716 __ubsan_handle_cfi_bad_type(struct CCFICheckFailData *pData, unsigned long ulVtable, bool bValidVtable, bool FromUnrecoverableHandler, unsigned long ProgramCounter, unsigned long FramePointer)
717 {
718
719 ASSERT(pData);
720
721 HandleCFIBadType(false, pData, ulVtable, &bValidVtable, &FromUnrecoverableHandler, &ProgramCounter, &FramePointer);
722 }
723
724 void
725 __ubsan_handle_cfi_check_fail(struct CCFICheckFailData *pData, unsigned long ulValue, unsigned long ulValidVtable)
726 {
727
728 ASSERT(pData);
729
730 HandleCFIBadType(false, pData, ulValue, 0, 0, 0, 0);
731 }
732
733 void
734 __ubsan_handle_cfi_check_fail_abort(struct CCFICheckFailData *pData, unsigned long ulValue, unsigned long ulValidVtable)
735 {
736
737 ASSERT(pData);
738
739 HandleCFIBadType(true, pData, ulValue, 0, 0, 0, 0);
740 }
741
742 void
743 __ubsan_handle_divrem_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
744 {
745
746 ASSERT(pData);
747
748 HandleOverflow(false, pData, ulLHS, ulRHS, DIVREM_STRING);
749 }
750
751 void
752 __ubsan_handle_divrem_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
753 {
754
755 ASSERT(pData);
756
757 HandleOverflow(true, pData, ulLHS, ulRHS, DIVREM_STRING);
758 }
759
760 void
761 __ubsan_handle_dynamic_type_cache_miss(struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash)
762 {
763
764 ASSERT(pData);
765
766 HandleDynamicTypeCacheMiss(false, pData, ulPointer, ulHash);
767 }
768
769 void
770 __ubsan_handle_dynamic_type_cache_miss_abort(struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash)
771 {
772
773 ASSERT(pData);
774
775 HandleDynamicTypeCacheMiss(false, pData, ulPointer, ulHash);
776 }
777
778 void
779 __ubsan_handle_float_cast_overflow(struct CFloatCastOverflowData *pData, unsigned long ulFrom)
780 {
781
782 ASSERT(pData);
783
784 HandleFloatCastOverflow(false, pData, ulFrom);
785 }
786
787 void
788 __ubsan_handle_float_cast_overflow_abort(struct CFloatCastOverflowData *pData, unsigned long ulFrom)
789 {
790
791 ASSERT(pData);
792
793 HandleFloatCastOverflow(true, pData, ulFrom);
794 }
795
796 void
797 __ubsan_handle_function_type_mismatch(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction)
798 {
799
800 ASSERT(pData);
801
802 HandleFunctionTypeMismatch(false, pData, ulFunction);
803 }
804
805 void
806 __ubsan_handle_function_type_mismatch_abort(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction)
807 {
808
809 ASSERT(pData);
810
811 HandleFunctionTypeMismatch(false, pData, ulFunction);
812 }
813
814 void
815 __ubsan_handle_invalid_builtin(struct CInvalidBuiltinData *pData)
816 {
817
818 ASSERT(pData);
819
820 HandleInvalidBuiltin(true, pData);
821 }
822
823 void
824 __ubsan_handle_invalid_builtin_abort(struct CInvalidBuiltinData *pData)
825 {
826
827 ASSERT(pData);
828
829 HandleInvalidBuiltin(true, pData);
830 }
831
832 void
833 __ubsan_handle_load_invalid_value(struct CInvalidValueData *pData, unsigned long ulValue)
834 {
835
836 ASSERT(pData);
837
838 HandleLoadInvalidValue(false, pData, ulValue);
839 }
840
841 void
842 __ubsan_handle_load_invalid_value_abort(struct CInvalidValueData *pData, unsigned long ulValue)
843 {
844
845 ASSERT(pData);
846
847 HandleLoadInvalidValue(true, pData, ulValue);
848 }
849
850 void
851 __ubsan_handle_missing_return(struct CUnreachableData *pData)
852 {
853
854 ASSERT(pData);
855
856 HandleMissingReturn(true, pData);
857 }
858
859 void
860 __ubsan_handle_mul_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
861 {
862
863 ASSERT(pData);
864
865 HandleOverflow(false, pData, ulLHS, ulRHS, MUL_STRING);
866 }
867
868 void
869 __ubsan_handle_mul_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
870 {
871
872 ASSERT(pData);
873
874 HandleOverflow(true, pData, ulLHS, ulRHS, MUL_STRING);
875 }
876
877 void
878 __ubsan_handle_negate_overflow(struct COverflowData *pData, unsigned long ulOldValue)
879 {
880
881 ASSERT(pData);
882
883 HandleNegateOverflow(false, pData, ulOldValue);
884 }
885
886 void
887 __ubsan_handle_negate_overflow_abort(struct COverflowData *pData, unsigned long ulOldValue)
888 {
889
890 ASSERT(pData);
891
892 HandleNegateOverflow(true, pData, ulOldValue);
893 }
894
895 void
896 __ubsan_handle_nonnull_arg(struct CNonNullArgData *pData)
897 {
898
899 ASSERT(pData);
900
901 HandleNonnullArg(false, pData);
902 }
903
904 void
905 __ubsan_handle_nonnull_arg_abort(struct CNonNullArgData *pData)
906 {
907
908 ASSERT(pData);
909
910 HandleNonnullArg(true, pData);
911 }
912
913 void
914 __ubsan_handle_nonnull_return_v1(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
915 {
916
917 ASSERT(pData);
918 ASSERT(pLocationPointer);
919
920 HandleNonnullReturn(false, pData, pLocationPointer);
921 }
922
923 void
924 __ubsan_handle_nonnull_return_v1_abort(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
925 {
926
927 ASSERT(pData);
928 ASSERT(pLocationPointer);
929
930 HandleNonnullReturn(true, pData, pLocationPointer);
931 }
932
933 void
934 __ubsan_handle_nullability_arg(struct CNonNullArgData *pData)
935 {
936
937 ASSERT(pData);
938
939 HandleNonnullArg(false, pData);
940 }
941
942 void
943 __ubsan_handle_nullability_arg_abort(struct CNonNullArgData *pData)
944 {
945
946 ASSERT(pData);
947
948 HandleNonnullArg(true, pData);
949 }
950
951 void
952 __ubsan_handle_nullability_return_v1(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
953 {
954
955 ASSERT(pData);
956 ASSERT(pLocationPointer);
957
958 HandleNonnullReturn(false, pData, pLocationPointer);
959 }
960
961 void
962 __ubsan_handle_nullability_return_v1_abort(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer)
963 {
964
965 ASSERT(pData);
966 ASSERT(pLocationPointer);
967
968 HandleNonnullReturn(true, pData, pLocationPointer);
969 }
970
971 void
972 __ubsan_handle_out_of_bounds(struct COutOfBoundsData *pData, unsigned long ulIndex)
973 {
974
975 ASSERT(pData);
976
977 HandleOutOfBounds(false, pData, ulIndex);
978 }
979
980 void
981 __ubsan_handle_out_of_bounds_abort(struct COutOfBoundsData *pData, unsigned long ulIndex)
982 {
983
984 ASSERT(pData);
985
986 HandleOutOfBounds(true, pData, ulIndex);
987 }
988
989 void
990 __ubsan_handle_pointer_overflow(struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult)
991 {
992
993 ASSERT(pData);
994
995 HandlePointerOverflow(false, pData, ulBase, ulResult);
996 }
997
998 void
999 __ubsan_handle_pointer_overflow_abort(struct CPointerOverflowData *pData, unsigned long ulBase, unsigned long ulResult)
1000 {
1001
1002 ASSERT(pData);
1003
1004 HandlePointerOverflow(true, pData, ulBase, ulResult);
1005 }
1006
1007 void
1008 __ubsan_handle_shift_out_of_bounds(struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS)
1009 {
1010
1011 ASSERT(pData);
1012
1013 HandleShiftOutOfBounds(false, pData, ulLHS, ulRHS);
1014 }
1015
1016 void
1017 __ubsan_handle_shift_out_of_bounds_abort(struct CShiftOutOfBoundsData *pData, unsigned long ulLHS, unsigned long ulRHS)
1018 {
1019
1020 ASSERT(pData);
1021
1022 HandleShiftOutOfBounds(true, pData, ulLHS, ulRHS);
1023 }
1024
1025 void
1026 __ubsan_handle_sub_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
1027 {
1028
1029 ASSERT(pData);
1030
1031 HandleOverflow(false, pData, ulLHS, ulRHS, MINUS_STRING);
1032 }
1033
1034 void
1035 __ubsan_handle_sub_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS)
1036 {
1037
1038 ASSERT(pData);
1039
1040 HandleOverflow(true, pData, ulLHS, ulRHS, MINUS_STRING);
1041 }
1042
1043 void
1044 __ubsan_handle_type_mismatch(struct CTypeMismatchData *pData, unsigned long ulPointer)
1045 {
1046
1047 ASSERT(pData);
1048
1049 HandleTypeMismatch(false, &pData->mLocation, pData->mType, pData->mLogAlignment, pData->mTypeCheckKind, ulPointer);
1050 }
1051
1052 void
1053 __ubsan_handle_type_mismatch_abort(struct CTypeMismatchData *pData, unsigned long ulPointer)
1054 {
1055
1056 ASSERT(pData);
1057
1058 HandleTypeMismatch(true, &pData->mLocation, pData->mType, pData->mLogAlignment, pData->mTypeCheckKind, ulPointer);
1059 }
1060
1061 void
1062 __ubsan_handle_type_mismatch_v1(struct CTypeMismatchData_v1 *pData, unsigned long ulPointer)
1063 {
1064
1065 ASSERT(pData);
1066
1067 HandleTypeMismatch(false, &pData->mLocation, pData->mType, __BIT(pData->mLogAlignment), pData->mTypeCheckKind, ulPointer);
1068 }
1069
1070 void
1071 __ubsan_handle_type_mismatch_v1_abort(struct CTypeMismatchData_v1 *pData, unsigned long ulPointer)
1072 {
1073
1074 ASSERT(pData);
1075
1076 HandleTypeMismatch(true, &pData->mLocation, pData->mType, __BIT(pData->mLogAlignment), pData->mTypeCheckKind, ulPointer);
1077 }
1078
1079 void
1080 __ubsan_handle_vla_bound_not_positive(struct CVLABoundData *pData, unsigned long ulBound)
1081 {
1082
1083 ASSERT(pData);
1084
1085 HandleVlaBoundNotPositive(false, pData, ulBound);
1086 }
1087
1088 void
1089 __ubsan_handle_vla_bound_not_positive_abort(struct CVLABoundData *pData, unsigned long ulBound)
1090 {
1091
1092 ASSERT(pData);
1093
1094 HandleVlaBoundNotPositive(true, pData, ulBound);
1095 }
1096
1097 void
1098 __ubsan_get_current_report_data(const char **ppOutIssueKind, const char **ppOutMessage, const char **ppOutFilename, uint32_t *pOutLine, uint32_t *pOutCol, char **ppOutMemoryAddr)
1099 {
1100 /*
1101 * Unimplemented.
1102 *
1103 * The __ubsan_on_report() feature is non trivial to implement in a
1104 * shared code between the kernel and userland. It's also opening
1105 * new sets of potential problems as we are not expected to slow down
1106 * execution of certain kernel subsystems (synchronization issues,
1107 * interrupt handling etc).
1108 *
1109 * A proper solution would need probably a lock-free bounded queue built
1110 * with atomic operations with the property of miltiple consumers and
1111 * multiple producers. Maintaining and validating such code is not
1112 * worth the effort.
1113 *
1114 * A legitimate user - besides testing framework - is a debugger plugin
1115 * intercepting reports from the UBSan instrumentation. For such
1116 * scenarios it is better to run the Clang/GCC version.
1117 */
1118 }
1119
1120 /* Local utility functions */
1121
1122 static void
1123 Report(bool isFatal, const char *pFormat, ...)
1124 {
1125 va_list ap;
1126
1127 ASSERT(pFormat);
1128
1129 va_start(ap, pFormat);
1130 #if defined(_KERNEL)
1131 if (isFatal || alwaysFatal)
1132 vpanic(pFormat, ap);
1133 else
1134 vprintf(pFormat, ap);
1135 #else
1136 if (ubsan_flags == -1) {
1137 char buf[1024];
1138 char *p;
1139
1140 ubsan_flags = UBSAN_STDERR;
1141
1142 if (getenv_r("LIBC_UBSAN", buf, sizeof(buf)) != -1) {
1143 for (p = buf; *p; p++) {
1144 switch (*p) {
1145 case 'a':
1146 SET(ubsan_flags, UBSAN_ABORT);
1147 break;
1148 case 'A':
1149 CLR(ubsan_flags, UBSAN_ABORT);
1150 break;
1151 case 'e':
1152 SET(ubsan_flags, UBSAN_STDERR);
1153 break;
1154 case 'E':
1155 CLR(ubsan_flags, UBSAN_STDERR);
1156 break;
1157 case 'l':
1158 SET(ubsan_flags, UBSAN_SYSLOG);
1159 break;
1160 case 'L':
1161 CLR(ubsan_flags, UBSAN_SYSLOG);
1162 break;
1163 case 'o':
1164 SET(ubsan_flags, UBSAN_STDOUT);
1165 break;
1166 case 'O':
1167 CLR(ubsan_flags, UBSAN_STDOUT);
1168 break;
1169 default:
1170 break;
1171 }
1172 }
1173 }
1174 }
1175
1176 // The *v*print* functions can flush the va_list argument.
1177 // Create a local copy for each call to prevent invalid read.
1178 if (ISSET(ubsan_flags, UBSAN_STDOUT)) {
1179 va_list tmp;
1180 va_copy(tmp, ap);
1181 vprintf(pFormat, tmp);
1182 va_end(tmp);
1183 fflush(stdout);
1184 }
1185 if (ISSET(ubsan_flags, UBSAN_STDERR)) {
1186 va_list tmp;
1187 va_copy(tmp, ap);
1188 vfprintf(stderr, pFormat, tmp);
1189 va_end(tmp);
1190 fflush(stderr);
1191 }
1192 if (ISSET(ubsan_flags, UBSAN_SYSLOG)) {
1193 va_list tmp;
1194 va_copy(tmp, ap);
1195 struct syslog_data SyslogData = SYSLOG_DATA_INIT;
1196 ubsan_vsyslog(LOG_DEBUG | LOG_USER, &SyslogData, pFormat, tmp);
1197 va_end(tmp);
1198 }
1199 if (isFatal || alwaysFatal || ISSET(ubsan_flags, UBSAN_ABORT)) {
1200 abort();
1201 __unreachable();
1202 /* NOTREACHED */
1203 }
1204 #endif
1205 va_end(ap);
1206 }
1207
1208 static bool
1209 isAlreadyReported(struct CSourceLocation *pLocation)
1210 {
1211 /*
1212 * This code is shared between libc, kernel and standalone usage.
1213 * It shall work in early bootstrap phase of both of them.
1214 */
1215
1216 uint32_t siOldValue;
1217 volatile uint32_t *pLine;
1218
1219 ASSERT(pLocation);
1220
1221 pLine = &pLocation->mLine;
1222
1223 do {
1224 siOldValue = *pLine;
1225 } while (__sync_val_compare_and_swap(pLine, siOldValue, siOldValue | ACK_REPORTED) != siOldValue);
1226
1227 return ISSET(siOldValue, ACK_REPORTED);
1228 }
1229
1230 static size_t
1231 zDeserializeTypeWidth(struct CTypeDescriptor *pType)
1232 {
1233 size_t zWidth = 0;
1234
1235 ASSERT(pType);
1236
1237 switch (pType->mTypeKind) {
1238 case KIND_INTEGER:
1239 zWidth = __BIT(__SHIFTOUT(pType->mTypeInfo, ~NUMBER_SIGNED_BIT));
1240 break;
1241 case KIND_FLOAT:
1242 zWidth = pType->mTypeInfo;
1243 break;
1244 default:
1245 Report(true, "UBSan: Unknown variable type %#04" PRIx16 "\n", pType->mTypeKind);
1246 __unreachable();
1247 /* NOTREACHED */
1248 }
1249
1250 /* Invalid width will be transformed to 0 */
1251 ASSERT(zWidth > 0);
1252
1253 return zWidth;
1254 }
1255
1256 static void
1257 DeserializeLocation(char *pBuffer, size_t zBUfferLength, struct CSourceLocation *pLocation)
1258 {
1259
1260 ASSERT(pLocation);
1261 ASSERT(pLocation->mFilename);
1262
1263 snprintf(pBuffer, zBUfferLength, "%s:%" PRIu32 ":%" PRIu32, pLocation->mFilename, pLocation->mLine & (uint32_t)~ACK_REPORTED, pLocation->mColumn);
1264 }
1265
1266 #ifdef __SIZEOF_INT128__
1267 static void
1268 DeserializeUINT128(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, __uint128_t U128)
1269 {
1270 char szBuf[3]; /* 'XX\0' */
1271 char rgNumber[sizeof(ulongest)];
1272 ssize_t zI;
1273
1274 memcpy(rgNumber, &U128, sizeof(U128));
1275
1276 strlcpy(pBuffer, "Undecoded-128-bit-Integer-Type (0x", zBUfferLength);
1277 #if BYTE_ORDER == LITTLE_ENDIAN
1278 for (zI = sizeof(ulongest) - 1; zI >= 0; zI--) {
1279 #else
1280 for (zI = 0; zI < (ssize_t)sizeof(ulongest); zI++) {
1281 #endif
1282 snprintf(szBuf, sizeof(szBuf), "%02" PRIx8, rgNumber[zI]);
1283 strlcat(pBuffer, szBuf, zBUfferLength);
1284 }
1285 strlcat(pBuffer, ")", zBUfferLength);
1286 }
1287 #endif
1288
1289 static void
1290 DeserializeNumberSigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, longest L)
1291 {
1292
1293 ASSERT(pBuffer);
1294 ASSERT(zBUfferLength > 0);
1295 ASSERT(pType);
1296 ASSERT(ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT));
1297
1298 switch (zDeserializeTypeWidth(pType)) {
1299 default:
1300 ASSERT(0 && "Invalid codepath");
1301 __unreachable();
1302 /* NOTREACHED */
1303 #ifdef __SIZEOF_INT128__
1304 case WIDTH_128:
1305 DeserializeUINT128(pBuffer, zBUfferLength, pType, STATIC_CAST(__uint128_t, L));
1306 break;
1307 #endif
1308 case WIDTH_64:
1309 /* FALLTHROUGH */
1310 case WIDTH_32:
1311 /* FALLTHROUGH */
1312 case WIDTH_16:
1313 /* FALLTHROUGH */
1314 case WIDTH_8:
1315 snprintf(pBuffer, zBUfferLength, "%" PRId64, STATIC_CAST(int64_t, L));
1316 break;
1317 }
1318 }
1319
1320 static void
1321 DeserializeNumberUnsigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, ulongest L)
1322 {
1323
1324 ASSERT(pBuffer);
1325 ASSERT(zBUfferLength > 0);
1326 ASSERT(pType);
1327 ASSERT(!ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT));
1328
1329 switch (zDeserializeTypeWidth(pType)) {
1330 default:
1331 ASSERT(0 && "Invalid codepath");
1332 __unreachable();
1333 /* NOTREACHED */
1334 #ifdef __SIZEOF_INT128__
1335 case WIDTH_128:
1336 DeserializeUINT128(pBuffer, zBUfferLength, pType, STATIC_CAST(__uint128_t, L));
1337 break;
1338 #endif
1339 case WIDTH_64:
1340 /* FALLTHROUGH */
1341 case WIDTH_32:
1342 /* FALLTHROUGH */
1343 case WIDTH_16:
1344 /* FALLTHROUGH */
1345 case WIDTH_8:
1346 snprintf(pBuffer, zBUfferLength, "%" PRIu64, STATIC_CAST(uint64_t, L));
1347 break;
1348 }
1349 }
1350
1351 #ifndef _KERNEL
1352 static void
1353 DeserializeFloatOverPointer(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long *pNumber)
1354 {
1355 double D;
1356 #ifdef __HAVE_LONG_DOUBLE
1357 long double LD;
1358 #endif
1359
1360 ASSERT(pBuffer);
1361 ASSERT(zBUfferLength > 0);
1362 ASSERT(pType);
1363 ASSERT(pNumber);
1364 /*
1365 * This function handles 64-bit number over a pointer on 32-bit CPUs.
1366 */
1367 ASSERT((sizeof(*pNumber) * CHAR_BIT < WIDTH_64) || (zDeserializeTypeWidth(pType) >= WIDTH_64));
1368 ASSERT(sizeof(D) == sizeof(uint64_t));
1369 #ifdef __HAVE_LONG_DOUBLE
1370 ASSERT(sizeof(LD) > sizeof(uint64_t));
1371 #endif
1372
1373 switch (zDeserializeTypeWidth(pType)) {
1374 #ifdef __HAVE_LONG_DOUBLE
1375 case WIDTH_128:
1376 /* FALLTHROUGH */
1377 case WIDTH_96:
1378 /* FALLTHROUGH */
1379 case WIDTH_80:
1380 memcpy(&LD, pNumber, sizeof(long double));
1381 snprintf(pBuffer, zBUfferLength, "%Lg", LD);
1382 break;
1383 #endif
1384 case WIDTH_64:
1385 memcpy(&D, pNumber, sizeof(double));
1386 snprintf(pBuffer, zBUfferLength, "%g", D);
1387 break;
1388 }
1389 }
1390
1391 static void
1392 DeserializeFloatInlined(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber)
1393 {
1394 float F;
1395 double D;
1396 uint32_t U32;
1397
1398 ASSERT(pBuffer);
1399 ASSERT(zBUfferLength > 0);
1400 ASSERT(pType);
1401 ASSERT(sizeof(F) == sizeof(uint32_t));
1402 ASSERT(sizeof(D) == sizeof(uint64_t));
1403
1404 switch (zDeserializeTypeWidth(pType)) {
1405 case WIDTH_64:
1406 ASSERT(sizeof(D) == sizeof(ulNumber));
1407 memcpy(&D, &ulNumber, sizeof(ulNumber));
1408 snprintf(pBuffer, zBUfferLength, "%g", D);
1409 break;
1410 case WIDTH_32:
1411 /*
1412 * On supported platforms sizeof(float)==sizeof(uint32_t)
1413 * unsigned long is either 32 or 64-bit, cast it to 32-bit
1414 * value in order to call memcpy(3) in an Endian-aware way.
1415 */
1416 U32 = STATIC_CAST(uint32_t, ulNumber);
1417 memcpy(&F, &U32, sizeof(float));
1418 snprintf(pBuffer, zBUfferLength, "%g", F);
1419 break;
1420 case WIDTH_16:
1421 snprintf(pBuffer, zBUfferLength, "Undecoded-16-bit-Floating-Type (%#04" PRIx16 ")", STATIC_CAST(uint16_t, ulNumber));
1422 break;
1423 }
1424 }
1425 #endif
1426
1427 static longest
1428 llliGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber)
1429 {
1430 size_t zNumberWidth;
1431 longest L = 0;
1432
1433 ASSERT(szLocation);
1434 ASSERT(pType);
1435
1436 zNumberWidth = zDeserializeTypeWidth(pType);
1437 switch (zNumberWidth) {
1438 default:
1439 Report(true, "UBSan: Unexpected %zu-Bit Type in %s\n", zNumberWidth, szLocation);
1440 __unreachable();
1441 /* NOTREACHED */
1442 case WIDTH_128:
1443 #ifdef __SIZEOF_INT128__
1444 memcpy(&L, REINTERPRET_CAST(longest *, ulNumber), sizeof(longest));
1445 break;
1446 #else
1447 Report(true, "UBSan: Unexpected 128-Bit Type in %s\n", szLocation);
1448 __unreachable();
1449 /* NOTREACHED */
1450 #endif
1451 case WIDTH_64:
1452 if (sizeof(ulNumber) * CHAR_BIT < WIDTH_64) {
1453 L = *REINTERPRET_CAST(int64_t *, ulNumber);
1454 } else {
1455 L = STATIC_CAST(int64_t, STATIC_CAST(uint64_t, ulNumber));
1456 }
1457 break;
1458 case WIDTH_32:
1459 L = STATIC_CAST(int32_t, STATIC_CAST(uint32_t, ulNumber));
1460 break;
1461 case WIDTH_16:
1462 L = STATIC_CAST(int16_t, STATIC_CAST(uint16_t, ulNumber));
1463 break;
1464 case WIDTH_8:
1465 L = STATIC_CAST(int8_t, STATIC_CAST(uint8_t, ulNumber));
1466 break;
1467 }
1468
1469 return L;
1470 }
1471
1472 static ulongest
1473 llluGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber)
1474 {
1475 size_t zNumberWidth;
1476 ulongest UL = 0;
1477
1478 ASSERT(pType);
1479
1480 zNumberWidth = zDeserializeTypeWidth(pType);
1481 switch (zNumberWidth) {
1482 default:
1483 Report(true, "UBSan: Unexpected %zu-Bit Type in %s\n", zNumberWidth, szLocation);
1484 __unreachable();
1485 /* NOTREACHED */
1486 case WIDTH_128:
1487 #ifdef __SIZEOF_INT128__
1488 memcpy(&UL, REINTERPRET_CAST(ulongest *, ulNumber), sizeof(ulongest));
1489 break;
1490 #else
1491 Report(true, "UBSan: Unexpected 128-Bit Type in %s\n", szLocation);
1492 __unreachable();
1493 /* NOTREACHED */
1494 #endif
1495 case WIDTH_64:
1496 if (sizeof(ulNumber) * CHAR_BIT < WIDTH_64) {
1497 UL = *REINTERPRET_CAST(uint64_t *, ulNumber);
1498 break;
1499 }
1500 /* FALLTHROUGH */
1501 case WIDTH_32:
1502 /* FALLTHROUGH */
1503 case WIDTH_16:
1504 /* FALLTHROUGH */
1505 case WIDTH_8:
1506 UL = ulNumber;
1507 break;
1508 }
1509
1510 return UL;
1511 }
1512
1513 #ifndef _KERNEL
1514 static void
1515 DeserializeNumberFloat(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber)
1516 {
1517 size_t zNumberWidth;
1518
1519 ASSERT(szLocation);
1520 ASSERT(pBuffer);
1521 ASSERT(zBUfferLength > 0);
1522 ASSERT(pType);
1523 ASSERT(pType->mTypeKind == KIND_FLOAT);
1524
1525 zNumberWidth = zDeserializeTypeWidth(pType);
1526 switch (zNumberWidth) {
1527 default:
1528 Report(true, "UBSan: Unexpected %zu-Bit Type in %s\n", zNumberWidth, szLocation);
1529 __unreachable();
1530 /* NOTREACHED */
1531 #ifdef __HAVE_LONG_DOUBLE
1532 case WIDTH_128:
1533 /* FALLTHROUGH */
1534 case WIDTH_96:
1535 /* FALLTHROUGH */
1536 case WIDTH_80:
1537 DeserializeFloatOverPointer(pBuffer, zBUfferLength, pType, REINTERPRET_CAST(unsigned long *, ulNumber));
1538 break;
1539 #endif
1540 case WIDTH_64:
1541 if (sizeof(ulNumber) * CHAR_BIT < WIDTH_64) {
1542 DeserializeFloatOverPointer(pBuffer, zBUfferLength, pType, REINTERPRET_CAST(unsigned long *, ulNumber));
1543 break;
1544 }
1545 /* FALLTHROUGH */
1546 case WIDTH_32:
1547 /* FALLTHROUGH */
1548 case WIDTH_16:
1549 DeserializeFloatInlined(pBuffer, zBUfferLength, pType, ulNumber);
1550 break;
1551 }
1552 }
1553 #endif
1554
1555 static void
1556 DeserializeNumber(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber)
1557 {
1558
1559 ASSERT(szLocation);
1560 ASSERT(pBuffer);
1561 ASSERT(zBUfferLength > 0);
1562 ASSERT(pType);
1563
1564 switch(pType->mTypeKind) {
1565 case KIND_INTEGER:
1566 if (ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT)) {
1567 longest L = llliGetNumber(szLocation, pType, ulNumber);
1568 DeserializeNumberSigned(pBuffer, zBUfferLength, pType, L);
1569 } else {
1570 ulongest UL = llluGetNumber(szLocation, pType, ulNumber);
1571 DeserializeNumberUnsigned(pBuffer, zBUfferLength, pType, UL);
1572 }
1573 break;
1574 case KIND_FLOAT:
1575 #ifdef _KERNEL
1576 Report(true, "UBSan: Unexpected Float Type in %s\n", szLocation);
1577 __unreachable();
1578 /* NOTREACHED */
1579 #else
1580 DeserializeNumberFloat(szLocation, pBuffer, zBUfferLength, pType, ulNumber);
1581 break;
1582 #endif
1583 case KIND_UNKNOWN:
1584 Report(true, "UBSan: Unknown Type in %s\n", szLocation);
1585 __unreachable();
1586 /* NOTREACHED */
1587 }
1588 }
1589
1590 static const char *
1591 DeserializeTypeCheckKind(uint8_t hhuTypeCheckKind)
1592 {
1593 const char *rgczTypeCheckKinds[] = {
1594 "load of",
1595 "store to",
1596 "reference binding to",
1597 "member access within",
1598 "member call on",
1599 "constructor call on",
1600 "downcast of",
1601 "downcast of",
1602 "upcast of",
1603 "cast to virtual base of",
1604 "_Nonnull binding to",
1605 "dynamic operation on"
1606 };
1607
1608 ASSERT(__arraycount(rgczTypeCheckKinds) > hhuTypeCheckKind);
1609
1610 return rgczTypeCheckKinds[hhuTypeCheckKind];
1611 }
1612
1613 static const char *
1614 DeserializeBuiltinCheckKind(uint8_t hhuBuiltinCheckKind)
1615 {
1616 const char *rgczBuiltinCheckKinds[] = {
1617 "ctz()",
1618 "clz()"
1619 };
1620
1621 ASSERT(__arraycount(rgczBuiltinCheckKinds) > hhuBuiltinCheckKind);
1622
1623 return rgczBuiltinCheckKinds[hhuBuiltinCheckKind];
1624 }
1625
1626 static const char *
1627 DeserializeCFICheckKind(uint8_t hhuCFICheckKind)
1628 {
1629 const char *rgczCFICheckKinds[] = {
1630 "virtual call", // CFI_VCALL
1631 "non-virtual call", // CFI_NVCALL
1632 "base-to-derived cast", // CFI_DERIVEDCAST
1633 "cast to unrelated type", // CFI_UNRELATEDCAST
1634 "indirect function call", // CFI_ICALL
1635 "non-virtual pointer to member function call", // CFI_NVMFCALL
1636 "virtual pointer to member function call", // CFI_VMFCALL
1637 };
1638
1639 ASSERT(__arraycount(rgczCFICheckKinds) > hhuCFICheckKind);
1640
1641 return rgczCFICheckKinds[hhuCFICheckKind];
1642 }
1643
1644 static bool
1645 isNegativeNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber)
1646 {
1647
1648 ASSERT(szLocation);
1649 ASSERT(pType);
1650 ASSERT(pType->mTypeKind == KIND_INTEGER);
1651
1652 if (!ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT))
1653 return false;
1654
1655 return llliGetNumber(szLocation, pType, ulNumber) < 0;
1656 }
1657
1658 static bool
1659 isShiftExponentTooLarge(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber, size_t zWidth)
1660 {
1661
1662 ASSERT(szLocation);
1663 ASSERT(pType);
1664 ASSERT(pType->mTypeKind == KIND_INTEGER);
1665
1666 return llluGetNumber(szLocation, pType, ulNumber) >= zWidth;
1667 }
1668