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