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