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