Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/common/lib/libc/misc Import micro-UBSan (ubsan.c)
details: https://anonhg.NetBSD.org/src/rev/d6ac26d2f2ba
branches: trunk
changeset: 834229:d6ac26d2f2ba
user: kamil <kamil%NetBSD.org@localhost>
date: Fri Aug 03 02:05:43 2018 +0000
description:
Import micro-UBSan (ubsan.c)
This is a reimplementation of the Undefined Behavior Sanitizer with the
following properties:
- pure and clean-room C implementation,
- no -fsanitize=vpts support, as it requires RTTI support and C++
low-level routies to validate whether C++ objects are compatible
- designed to be used inside libc and known as uUBSan or user-UBSan
- designed to be shared with kernel and known as kUBSan or kernel-UBSan
- designed to be usable with ATF tests as a standalone runtime,
reachable without any MK* switches
- designed to be safer for hardening as it does not have side effects on
executables like writing to a selected location on demand
- controllable with environment variable LIBC_UBSAN with options:
* a - abort on report
* A - do not abort on a report (unless a failure is unrecoverable)
* e - output report to stderr
* E - do not output report on stderr
* l - output report on syslog (LOG_DEBUG | LOG_USER)
* L - do not output report on syslog
* o - output report on stdout
* O - do not output report on stdout
The default options are: "AeLO".
- compatible with Clang (3.8, 7.x) and GCC (6.x) code generation
- all handlers (except =vptr) from Clang/LLVM up to 7svn are supported
Tested with Clang amd64+i386 and GCC amd64+i386.
diffstat:
common/lib/libc/misc/ubsan.c | 1640 ++++++++++++++++++++++++++++++++++++++++++
1 files changed, 1640 insertions(+), 0 deletions(-)
diffs (truncated from 1644 to 300 lines):
diff -r 89615782f063 -r d6ac26d2f2ba common/lib/libc/misc/ubsan.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/common/lib/libc/misc/ubsan.c Fri Aug 03 02:05:43 2018 +0000
@@ -0,0 +1,1640 @@
+/* $NetBSD: ubsan.c,v 1.1 2018/08/03 02:05:43 kamil Exp $ */
+
+/*-
+ * Copyright (c) 2018 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/*
+ * The micro UBSan implementation for the userland (uUBSan) and kernel (kUBSan).
+ * The uBSSan versions is suitable for inclusion into libc or used standalone
+ * with ATF tests.
+ *
+ * This file due to long symbol names and licensing reasons does not fully
+ * follow the KNF style with 80-column limit. Hungarian style variables
+ * and function names are on the same purpose (Pascal and Snake style names,
+ * are used in different implementations).
+ */
+
+#include <sys/cdefs.h>
+#if defined(_KERNEL)
+__KERNEL_RCSID(0, "$NetBSD: ubsan.c,v 1.1 2018/08/03 02:05:43 kamil Exp $");
+#else
+__RCSID("$NetBSD: ubsan.c,v 1.1 2018/08/03 02:05:43 kamil Exp $");
+#endif
+
+#if defined(_KERNEL)
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stdarg.h>
+#define ASSERT(x) KASSERT(x)
+#else
+#if defined(_LIBC)
+#include "namespace.h"
+#endif
+#include <sys/param.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <math.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#if defined(_LIBC)
+#include "extern.h"
+#define ubsan_vsyslog vsyslog_ss
+#define ASSERT(x) _DIAGASSERT(x)
+#else
+#define ubsan_vsyslog vsyslog_r
+#define ASSERT(x) assert(x)
+#endif
+/* These macros are available in _KERNEL only */
+#define SET(t, f) ((t) |= (f))
+#define ISSET(t, f) ((t) & (f))
+#define CLR(t, f) ((t) &= ~(f))
+#endif
+
+#define REINTERPRET_CAST(__dt, __st) ((__dt)(__st))
+#define STATIC_CAST(__dt, __st) ((__dt)(__st))
+
+#define ACK_REPORTED __BIT(31)
+
+#define MUL_STRING "*"
+#define PLUS_STRING "+"
+#define MINUS_STRING "-"
+#define DIVREM_STRING "divrem"
+
+#define CFI_VCALL 0
+#define CFI_NVCALL 1
+#define CFI_DERIVEDCAST 2
+#define CFI_UNRELATEDCAST 3
+#define CFI_ICALL 4
+#define CFI_NVMFCALL 5
+#define CFI_VMFCALL 6
+
+#define NUMBER_MAXLEN 128
+#define LOCATION_MAXLEN (PATH_MAX + 32 /* ':LINE:COLUMN' */)
+
+#define WIDTH_8 8
+#define WIDTH_16 16
+#define WIDTH_32 32
+#define WIDTH_64 64
+#define WIDTH_80 80
+#define WIDTH_96 96
+#define WIDTH_128 128
+
+#define NUMBER_SIGNED_BIT 1U
+
+#if __SIZEOF_INT128__
+typedef __int128 longest;
+typedef unsigned __int128 ulongest;
+#else
+typedef int64_t longest;
+typedef uint64_t ulongest;
+#endif
+
+#ifndef _KERNEL
+static int ubsan_flags = -1;
+#define UBSAN_ABORT __BIT(0)
+#define UBSAN_STDOUT __BIT(1)
+#define UBSAN_STDERR __BIT(2)
+#define UBSAN_SYSLOG __BIT(3)
+#endif
+
+/* Undefined Behavior specific defines and structures */
+
+#define KIND_INTEGER 0
+#define KIND_FLOAT 1
+#define KIND_UNKNOWN UINT16_MAX
+
+struct CSourceLocation {
+ char *mFilename;
+ uint32_t mLine;
+ uint32_t mColumn;
+};
+
+struct CTypeDescriptor {
+ uint16_t mTypeKind;
+ uint16_t mTypeInfo;
+ uint8_t mTypeName[1];
+};
+
+struct COverflowData {
+ struct CSourceLocation mLocation;
+ struct CTypeDescriptor *mType;
+};
+
+struct CUnreachableData {
+ struct CSourceLocation mLocation;
+};
+
+struct CCFICheckFailData {
+ uint8_t mCheckKind;
+ struct CSourceLocation mLocation;
+ struct CTypeDescriptor *mType;
+};
+
+struct CDynamicTypeCacheMissData {
+ struct CSourceLocation mLocation;
+ struct CTypeDescriptor *mType;
+ void *mTypeInfo;
+ uint8_t mTypeCheckKind;
+};
+
+struct CFunctionTypeMismatchData {
+ struct CSourceLocation mLocation;
+ struct CTypeDescriptor *mType;
+};
+
+struct CInvalidBuiltinData {
+ struct CSourceLocation mLocation;
+ uint8_t mKind;
+};
+
+struct CInvalidValueData {
+ struct CSourceLocation mLocation;
+ struct CTypeDescriptor *mType;
+};
+
+struct CNonNullArgData {
+ struct CSourceLocation mLocation;
+ struct CSourceLocation mAttributeLocation;
+ int mArgIndex;
+};
+
+struct CNonNullReturnData {
+ struct CSourceLocation mAttributeLocation;
+};
+
+struct COutOfBoundsData {
+ struct CSourceLocation mLocation;
+ struct CTypeDescriptor *mArrayType;
+ struct CTypeDescriptor *mIndexType;
+};
+
+struct CPointerOverflowData {
+ struct CSourceLocation mLocation;
+};
+
+struct CShiftOutOfBoundsData {
+ struct CSourceLocation mLocation;
+ struct CTypeDescriptor *mLHSType;
+ struct CTypeDescriptor *mRHSType;
+};
+
+struct CTypeMismatchData {
+ struct CSourceLocation mLocation;
+ struct CTypeDescriptor *mType;
+ unsigned long mLogAlignment;
+ uint8_t mTypeCheckKind;
+};
+
+struct CTypeMismatchData_v1 {
+ struct CSourceLocation mLocation;
+ struct CTypeDescriptor *mType;
+ uint8_t mLogAlignment;
+ uint8_t mTypeCheckKind;
+};
+
+struct CVLABoundData {
+ struct CSourceLocation mLocation;
+ struct CTypeDescriptor *mType;
+};
+
+struct CFloatCastOverflowData {
+ struct CSourceLocation mLocation; /* This field exists in this struct since 2015 August 11th */
+ struct CTypeDescriptor *mFromType;
+ struct CTypeDescriptor *mToType;
+};
+
+/* Local utility functions */
+static void Report(bool isFatal, const char *pFormat, ...) __printflike(2, 3);
+static bool isAlreadyReported(struct CSourceLocation *pLocation);
+static size_t zDeserializeTypeWidth(struct CTypeDescriptor *pType);
+static void DeserializeLocation(char *pBuffer, size_t zBUfferLength, struct CSourceLocation *pLocation);
+#ifdef __SIZEOF_INT128__
+static void DeserializeUINT128(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, __uint128_t U128);
+#endif
+static void DeserializeNumberSigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, longest L);
+static void DeserializeNumberUnsigned(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, ulongest L);
+#ifndef _KERNEL
+static void DeserializeFloatOverPointer(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long *pNumber);
+static void DeserializeFloatInlined(char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber);
+#endif
+static longest llliGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber);
+static ulongest llluGetNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber);
+#ifndef _KERNEL
+static void DeserializeNumberFloat(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber);
+#endif
+static void DeserializeNumber(char *szLocation, char *pBuffer, size_t zBUfferLength, struct CTypeDescriptor *pType, unsigned long ulNumber);
+static const char *DeserializeTypeCheckKind(uint8_t hhuTypeCheckKind);
+static const char *DeserializeBuiltinCheckKind(uint8_t hhuBuiltinCheckKind);
+static const char *DeserializeCFICheckKind(uint8_t hhuCFICheckKind);
+static bool isNegativeNumber(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber);
+static bool isShiftExponentTooLarge(char *szLocation, struct CTypeDescriptor *pType, unsigned long ulNumber, size_t zWidth);
+
+/* Unused in this implementation, emitted by the C++ check dynamic type cast. */
+intptr_t __ubsan_vptr_type_cache[128];
+
+/* Public symbols used in the instrumentation of the code generation part */
+void __ubsan_handle_add_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
+void __ubsan_handle_add_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
+void __ubsan_handle_builtin_unreachable(struct CUnreachableData *pData);
+void __ubsan_handle_cfi_bad_type(struct CCFICheckFailData *pData, unsigned long ulVtable, bool bValidVtable, bool FromUnrecoverableHandler, unsigned long ProgramCounter, unsigned long FramePointer);
+void __ubsan_handle_cfi_check_fail(struct CCFICheckFailData *pData, unsigned long ulValue, unsigned long ulValidVtable);
+void __ubsan_handle_cfi_check_fail_abort(struct CCFICheckFailData *pData, unsigned long ulValue, unsigned long ulValidVtable);
+void __ubsan_handle_divrem_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
+void __ubsan_handle_divrem_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
+void __ubsan_handle_dynamic_type_cache_miss(struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash);
+void __ubsan_handle_dynamic_type_cache_miss_abort(struct CDynamicTypeCacheMissData *pData, unsigned long ulPointer, unsigned long ulHash);
+void __ubsan_handle_float_cast_overflow(struct CFloatCastOverflowData *pData, unsigned long ulFrom);
+void __ubsan_handle_float_cast_overflow_abort(struct CFloatCastOverflowData *pData, unsigned long ulFrom);
+void __ubsan_handle_function_type_mismatch(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction);
+void __ubsan_handle_function_type_mismatch_abort(struct CFunctionTypeMismatchData *pData, unsigned long ulFunction);
+void __ubsan_handle_invalid_builtin(struct CInvalidBuiltinData *pData);
+void __ubsan_handle_invalid_builtin_abort(struct CInvalidBuiltinData *pData);
+void __ubsan_handle_load_invalid_value(struct CInvalidValueData *pData, unsigned long ulVal);
+void __ubsan_handle_load_invalid_value_abort(struct CInvalidValueData *pData, unsigned long ulVal);
+void __ubsan_handle_missing_return(struct CUnreachableData *pData);
+void __ubsan_handle_mul_overflow(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
+void __ubsan_handle_mul_overflow_abort(struct COverflowData *pData, unsigned long ulLHS, unsigned long ulRHS);
+void __ubsan_handle_negate_overflow(struct COverflowData *pData, unsigned long ulOldVal);
+void __ubsan_handle_negate_overflow_abort(struct COverflowData *pData, unsigned long ulOldVal);
+void __ubsan_handle_nonnull_arg(struct CNonNullArgData *pData);
+void __ubsan_handle_nonnull_arg_abort(struct CNonNullArgData *pData);
+void __ubsan_handle_nonnull_return_v1(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
+void __ubsan_handle_nonnull_return_v1_abort(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
+void __ubsan_handle_nullability_arg(struct CNonNullArgData *pData);
+void __ubsan_handle_nullability_arg_abort(struct CNonNullArgData *pData);
+void __ubsan_handle_nullability_return_v1(struct CNonNullReturnData *pData, struct CSourceLocation *pLocationPointer);
Home |
Main Index |
Thread Index |
Old Index