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