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