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