ubsan.c revision 1.5 1 /* $NetBSD: ubsan.c,v 1.5 2019/02/13 17:17:02 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.5 2019/02/13 17:17:02 kamil Exp $");
42 #else
43 __RCSID("$NetBSD: ubsan.c,v 1.5 2019/02/13 17:17:02 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 #ifdef __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 __unreachable();
1196 /* NOTREACHED */
1197 }
1198 #endif
1199 va_end(ap);
1200 }
1201
1202 static bool
1203 isAlreadyReported(struct CSourceLocation *pLocation)
1204 {
1205 /*
1206 * This code is shared between libc, kernel and standalone usage.
1207 * It shall work in early bootstrap phase of both of them.
1208 */
1209
1210 uint32_t siOldValue;
1211 volatile uint32_t *pLine;
1212
1213 ASSERT(pLocation);
1214
1215 pLine = &pLocation->mLine;
1216
1217 do {
1218 siOldValue = *pLine;
1219 } while (__sync_val_compare_and_swap(pLine, siOldValue, siOldValue | ACK_REPORTED) != siOldValue);
1220
1221 return ISSET(siOldValue, ACK_REPORTED);
1222 }
1223
1224 static size_t
1225 zDeserializeTypeWidth(struct CTypeDescriptor *pType)
1226 {
1227 size_t zWidth = 0;
1228
1229 ASSERT(pType);
1230
1231 switch (pType->mTypeKind) {
1232 case KIND_INTEGER:
1233 zWidth = __BIT(__SHIFTOUT(pType->mTypeInfo, ~NUMBER_SIGNED_BIT));
1234 break;
1235 case KIND_FLOAT:
1236 zWidth = pType->mTypeInfo;
1237 break;
1238 default:
1239 Report(true, "UBSan: Unknown variable type %#04" PRIx16 "\n", pType->mTypeKind);
1240 __unreachable();
1241 /* NOTREACHED */
1242 }
1243
1244 /* Invalid width will be transformed to 0 */
1245 ASSERT(zWidth > 0);
1246
1247 return zWidth;
1248 }
1249
1250 static void
1251 DeserializeLocation(char *pBuffer, size_t zBUfferLength, struct CSourceLocation *pLocation)
1252 {
1253
1254 ASSERT(pLocation);
1255 ASSERT(pLocation->mFilename);
1256
1257 snprintf(pBuffer, zBUfferLength, "%s:%" PRIu32 ":%" PRIu32, pLocation->mFilename, pLocation->mLine & (uint32_t)~ACK_REPORTED, pLocation->mColumn);
1258 }
1259
1260 #ifdef __SIZEOF_INT128__
1261 static void
1262 DeserializeUINT128(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, __uint128_t U128)
1263 {
1264 char szBuf[3]; /* 'XX\0' */
1265 char rgNumber[sizeof(ulongest)];
1266 ssize_t zI;
1267
1268 memcpy(rgNumber, &U128, sizeof(U128));
1269
1270 strlcpy(pBuffer, "Undecoded-128-bit-Integer-Type (0x", zBUfferLength);
1271 #if BYTE_ORDER == LITTLE_ENDIAN
1272 for (zI = sizeof(ulongest) - 1; zI >= 0; zI--) {
1273 #else
1274 for (zI = 0; zI < (ssize_t)sizeof(ulongest); zI++) {
1275 #endif
1276 snprintf(szBuf, sizeof(szBuf), "%02" PRIx8, rgNumber[zI]);
1277 strlcat(pBuffer, szBuf, zBUfferLength);
1278 }
1279 strlcat(pBuffer, ")", zBUfferLength);
1280 }
1281 #endif
1282
1283 static void
1284 DeserializeNumberSigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, longest L)
1285 {
1286
1287 ASSERT(pBuffer);
1288 ASSERT(zBUfferLength > 0);
1289 ASSERT(pType);
1290 ASSERT(ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT));
1291
1292 switch (zDeserializeTypeWidth(pType)) {
1293 default:
1294 ASSERT(0 && "Invalid codepath");
1295 __unreachable();
1296 /* NOTREACHED */
1297 #ifdef __SIZEOF_INT128__
1298 case WIDTH_128:
1299 DeserializeUINT128(pBuffer, zBUfferLength, pType, STATIC_CAST(__uint128_t, L));
1300 break;
1301 #endif
1302 case WIDTH_64:
1303 /* FALLTHROUGH */
1304 case WIDTH_32:
1305 /* FALLTHROUGH */
1306 case WIDTH_16:
1307 /* FALLTHROUGH */
1308 case WIDTH_8:
1309 snprintf(pBuffer, zBUfferLength, "%" PRId64, STATIC_CAST(int64_t, L));
1310 break;
1311 }
1312 }
1313
1314 static void
1315 DeserializeNumberUnsigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, ulongest L)
1316 {
1317
1318 ASSERT(pBuffer);
1319 ASSERT(zBUfferLength > 0);
1320 ASSERT(pType);
1321 ASSERT(!ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT));
1322
1323 switch (zDeserializeTypeWidth(pType)) {
1324 default:
1325 ASSERT(0 && "Invalid codepath");
1326 __unreachable();
1327 /* NOTREACHED */
1328 #ifdef __SIZEOF_INT128__
1329 case WIDTH_128:
1330 DeserializeUINT128(pBuffer, zBUfferLength, pType, STATIC_CAST(__uint128_t, L));
1331 break;
1332 #endif
1333 case WIDTH_64:
1334 /* FALLTHROUGH */
1335 case WIDTH_32:
1336 /* FALLTHROUGH */
1337 case WIDTH_16:
1338 /* FALLTHROUGH */
1339 case WIDTH_8:
1340 snprintf(pBuffer, zBUfferLength, "%" PRIu64, STATIC_CAST(uint64_t, L));
1341 break;
1342 }
1343 }
1344
1345 #ifndef _KERNEL
1346 static void
1347 DeserializeFloatOverPointer(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long *pNumber)
1348 {
1349 double D;
1350 #ifdef __HAVE_LONG_DOUBLE
1351 long double LD;
1352 #endif
1353
1354 ASSERT(pBuffer);
1355 ASSERT(zBUfferLength > 0);
1356 ASSERT(pType);
1357 ASSERT(pNumber);
1358 /*
1359 * This function handles 64-bit number over a pointer on 32-bit CPUs.
1360 */
1361 ASSERT((sizeof(*pNumber) * CHAR_BIT < WIDTH_64) || (zDeserializeTypeWidth(pType) >= WIDTH_64));
1362 ASSERT(sizeof(D) == sizeof(uint64_t));
1363 #ifdef __HAVE_LONG_DOUBLE
1364 ASSERT(sizeof(LD) > sizeof(uint64_t));
1365 #endif
1366
1367 switch (zDeserializeTypeWidth(pType)) {
1368 #ifdef __HAVE_LONG_DOUBLE
1369 case WIDTH_128:
1370 /* FALLTHROUGH */
1371 case WIDTH_96:
1372 /* FALLTHROUGH */
1373 case WIDTH_80:
1374 memcpy(&LD, pNumber, sizeof(long double));
1375 snprintf(pBuffer, zBUfferLength, "%Lg", LD);
1376 break;
1377 #endif
1378 case WIDTH_64:
1379 memcpy(&D, pNumber, sizeof(double));
1380 snprintf(pBuffer, zBUfferLength, "%g", D);
1381 break;
1382 }
1383 }
1384
1385 static void
1386 DeserializeFloatInlined(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber)
1387 {
1388 float F;
1389 double D;
1390 uint32_t U32;
1391
1392 ASSERT(pBuffer);
1393 ASSERT(zBUfferLength > 0);
1394 ASSERT(pType);
1395 ASSERT(sizeof(F) == sizeof(uint32_t));
1396 ASSERT(sizeof(D) == sizeof(uint64_t));
1397
1398 switch (zDeserializeTypeWidth(pType)) {
1399 case WIDTH_64:
1400 memcpy(&D, &ulNumber, sizeof(double));
1401 snprintf(pBuffer, zBUfferLength, "%g", D);
1402 break;
1403 case WIDTH_32:
1404 /*
1405 * On supported platforms sizeof(float)==sizeof(uint32_t)
1406 * unsigned long is either 32 or 64-bit, cast it to 32-bit
1407 * value in order to call memcpy(3) in an Endian-aware way.
1408 */
1409 U32 = STATIC_CAST(uint32_t, ulNumber);
1410 memcpy(&F, &U32, sizeof(float));
1411 snprintf(pBuffer, zBUfferLength, "%g", F);
1412 break;
1413 case WIDTH_16:
1414 snprintf(pBuffer, zBUfferLength, "Undecoded-16-bit-Floating-Type (%#04" PRIx16 ")", STATIC_CAST(uint16_t, ulNumber));
1415 break;
1416 }
1417 }
1418 #endif
1419
1420 static longest
1421 llliGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber)
1422 {
1423 size_t zNumberWidth;
1424 longest L = 0;
1425
1426 ASSERT(szLocation);
1427 ASSERT(pType);
1428
1429 zNumberWidth = zDeserializeTypeWidth(pType);
1430 switch (zNumberWidth) {
1431 default:
1432 Report(true, "UBSan: Unexpected %zu-Bit Type in %s\n", zNumberWidth, szLocation);
1433 __unreachable();
1434 /* NOTREACHED */
1435 case WIDTH_128:
1436 #ifdef __SIZEOF_INT128__
1437 memcpy(&L, REINTERPRET_CAST(longest *, ulNumber), sizeof(longest));
1438 break;
1439 #else
1440 Report(true, "UBSan: Unexpected 128-Bit Type in %s\n", szLocation);
1441 __unreachable();
1442 /* NOTREACHED */
1443 #endif
1444 case WIDTH_64:
1445 if (sizeof(ulNumber) * CHAR_BIT < WIDTH_64) {
1446 L = *REINTERPRET_CAST(int64_t *, ulNumber);
1447 } else {
1448 L = STATIC_CAST(int64_t, STATIC_CAST(uint64_t, ulNumber));
1449 }
1450 break;
1451 case WIDTH_32:
1452 L = STATIC_CAST(int32_t, STATIC_CAST(uint32_t, ulNumber));
1453 break;
1454 case WIDTH_16:
1455 L = STATIC_CAST(int16_t, STATIC_CAST(uint16_t, ulNumber));
1456 break;
1457 case WIDTH_8:
1458 L = STATIC_CAST(int8_t, STATIC_CAST(uint8_t, ulNumber));
1459 break;
1460 }
1461
1462 return L;
1463 }
1464
1465 static ulongest
1466 llluGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber)
1467 {
1468 size_t zNumberWidth;
1469 ulongest UL = 0;
1470
1471 ASSERT(pType);
1472
1473 zNumberWidth = zDeserializeTypeWidth(pType);
1474 switch (zNumberWidth) {
1475 default:
1476 Report(true, "UBSan: Unexpected %zu-Bit Type in %s\n", zNumberWidth, szLocation);
1477 __unreachable();
1478 /* NOTREACHED */
1479 case WIDTH_128:
1480 #ifdef __SIZEOF_INT128__
1481 memcpy(&UL, REINTERPRET_CAST(ulongest *, ulNumber), sizeof(ulongest));
1482 break;
1483 #else
1484 Report(true, "UBSan: Unexpected 128-Bit Type in %s\n", szLocation);
1485 __unreachable();
1486 /* NOTREACHED */
1487 #endif
1488 case WIDTH_64:
1489 if (sizeof(ulNumber) * CHAR_BIT < WIDTH_64) {
1490 UL = *REINTERPRET_CAST(uint64_t *, ulNumber);
1491 break;
1492 }
1493 /* FALLTHROUGH */
1494 case WIDTH_32:
1495 /* FALLTHROUGH */
1496 case WIDTH_16:
1497 /* FALLTHROUGH */
1498 case WIDTH_8:
1499 UL = ulNumber;
1500 break;
1501 }
1502
1503 return UL;
1504 }
1505
1506 #ifndef _KERNEL
1507 static void
1508 DeserializeNumberFloat(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber)
1509 {
1510 size_t zNumberWidth;
1511
1512 ASSERT(szLocation);
1513 ASSERT(pBuffer);
1514 ASSERT(zBUfferLength > 0);
1515 ASSERT(pType);
1516 ASSERT(pType->mTypeKind == KIND_FLOAT);
1517
1518 zNumberWidth = zDeserializeTypeWidth(pType);
1519 switch (zNumberWidth) {
1520 default:
1521 Report(true, "UBSan: Unexpected %zu-Bit Type in %s\n", zNumberWidth, szLocation);
1522 __unreachable();
1523 /* NOTREACHED */
1524 #ifdef __HAVE_LONG_DOUBLE
1525 case WIDTH_128:
1526 /* FALLTHROUGH */
1527 case WIDTH_96:
1528 /* FALLTHROUGH */
1529 case WIDTH_80:
1530 DeserializeFloatOverPointer(pBuffer, zBUfferLength, pType, REINTERPRET_CAST(unsigned long *, ulNumber));
1531 break;
1532 #endif
1533 case WIDTH_64:
1534 if (sizeof(ulNumber) * CHAR_BIT < WIDTH_64) {
1535 DeserializeFloatOverPointer(pBuffer, zBUfferLength, pType, REINTERPRET_CAST(unsigned long *, ulNumber));
1536 break;
1537 }
1538 /* FALLTHROUGH */
1539 case WIDTH_32:
1540 /* FALLTHROUGH */
1541 case WIDTH_16:
1542 DeserializeFloatInlined(pBuffer, zBUfferLength, pType, ulNumber);
1543 break;
1544 }
1545 }
1546 #endif
1547
1548 static void
1549 DeserializeNumber(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber)
1550 {
1551
1552 ASSERT(szLocation);
1553 ASSERT(pBuffer);
1554 ASSERT(zBUfferLength > 0);
1555 ASSERT(pType);
1556
1557 switch(pType->mTypeKind) {
1558 case KIND_INTEGER:
1559 if (ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT)) {
1560 longest L = llliGetNumber(szLocation, pType, ulNumber);
1561 DeserializeNumberSigned(pBuffer, zBUfferLength, pType, L);
1562 } else {
1563 ulongest UL = llluGetNumber(szLocation, pType, ulNumber);
1564 DeserializeNumberUnsigned(pBuffer, zBUfferLength, pType, UL);
1565 }
1566 break;
1567 case KIND_FLOAT:
1568 #ifdef _KERNEL
1569 Report(true, "UBSan: Unexpected Float Type in %s\n", szLocation);
1570 __unreachable();
1571 /* NOTREACHED */
1572 #else
1573 DeserializeNumberFloat(szLocation, pBuffer, zBUfferLength, pType, ulNumber);
1574 break;
1575 #endif
1576 case KIND_UNKNOWN:
1577 Report(true, "UBSan: Unknown Type in %s\n", szLocation);
1578 __unreachable();
1579 /* NOTREACHED */
1580 }
1581 }
1582
1583 static const char *
1584 DeserializeTypeCheckKind(uint8_t hhuTypeCheckKind)
1585 {
1586 const char *rgczTypeCheckKinds[] = {
1587 "load of",
1588 "store to",
1589 "reference binding to",
1590 "member access within",
1591 "member call on",
1592 "constructor call on",
1593 "downcast of",
1594 "downcast of",
1595 "upcast of",
1596 "cast to virtual base of",
1597 "_Nonnull binding to",
1598 "dynamic operation on"
1599 };
1600
1601 ASSERT(__arraycount(rgczTypeCheckKinds) > hhuTypeCheckKind);
1602
1603 return rgczTypeCheckKinds[hhuTypeCheckKind];
1604 }
1605
1606 static const char *
1607 DeserializeBuiltinCheckKind(uint8_t hhuBuiltinCheckKind)
1608 {
1609 const char *rgczBuiltinCheckKinds[] = {
1610 "ctz()",
1611 "clz()"
1612 };
1613
1614 ASSERT(__arraycount(rgczBuiltinCheckKinds) > hhuBuiltinCheckKind);
1615
1616 return rgczBuiltinCheckKinds[hhuBuiltinCheckKind];
1617 }
1618
1619 static const char *
1620 DeserializeCFICheckKind(uint8_t hhuCFICheckKind)
1621 {
1622 const char *rgczCFICheckKinds[] = {
1623 "virtual call", // CFI_VCALL
1624 "non-virtual call", // CFI_NVCALL
1625 "base-to-derived cast", // CFI_DERIVEDCAST
1626 "cast to unrelated type", // CFI_UNRELATEDCAST
1627 "indirect function call", // CFI_ICALL
1628 "non-virtual pointer to member function call", // CFI_NVMFCALL
1629 "virtual pointer to member function call", // CFI_VMFCALL
1630 };
1631
1632 ASSERT(__arraycount(rgczCFICheckKinds) > hhuCFICheckKind);
1633
1634 return rgczCFICheckKinds[hhuCFICheckKind];
1635 }
1636
1637 static bool
1638 isNegativeNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber)
1639 {
1640
1641 ASSERT(szLocation);
1642 ASSERT(pType);
1643 ASSERT(pType->mTypeKind == KIND_INTEGER);
1644
1645 if (!ISSET(pType->mTypeInfo, NUMBER_SIGNED_BIT))
1646 return false;
1647
1648 return llliGetNumber(szLocation, pType, ulNumber) < 0;
1649 }
1650
1651 static bool
1652 isShiftExponentTooLarge(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber, size_t zWidth)
1653 {
1654
1655 ASSERT(szLocation);
1656 ASSERT(pType);
1657 ASSERT(pType->mTypeKind == KIND_INTEGER);
1658
1659 return llluGetNumber(szLocation, pType, ulNumber) >= zWidth;
1660 }
1661