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