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