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