From patchwork Wed May 7 14:17:19 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Adhemerval Zanella X-Patchwork-Id: 888069 Delivered-To: patch@linaro.org Received: by 2002:a5d:4683:0:b0:38f:210b:807b with SMTP id u3csp408103wrq; Wed, 7 May 2025 07:25:32 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCUBU5EavfXbFZSpCF7S7pi6qfUjElZNnvcZmoRoplTOCGvWWrpzEJxxUFVmvjmqvc+pPfi/AQ==@linaro.org X-Google-Smtp-Source: AGHT+IHOjOPkHLmjmjiYcn6+Dzzhxj1gCXnG1KkoRaU35JrVbzEogjOT3ARgIEumdCb1ZKsysRYF X-Received: by 2002:ad4:5dc3:0:b0:6ed:1681:4846 with SMTP id 6a1803df08f44-6f542a74c11mr63226736d6.24.1746627932094; Wed, 07 May 2025 07:25:32 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1746627932; cv=pass; d=google.com; s=arc-20240605; b=VkfdCquqDtX32m1oJsPuYyhw1y1/LvUpsI+kD1ZvVj4Z0kb80BW3JTDDFaNc9gA+L0 +yQvTCRC7LQ10IVxBTdOtVI8W3/M/2Df0C0qGYy79HC0Viu1p7CN6oG5J9JTszaW76L2 4LOYYr80ynGD6cAo/V5OaiPTzk0zwvUC72+9xUNwMjXu32Ogh7WVFRZ0sjNGXSDckyvF fQtdVhGoOx/++h9u5v2vKLDxOIqaYEylC/OuS2YWPonsEnG1gRrgX+ZJLC8y499RyvlK P6KitFhxakx4aHtxL/VVTcowNFhaEUcTz09NHGDK+02a+HmjhGk/EPA9+gU6W8cH1E07 gHcw== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature:dkim-filter:arc-filter:dmarc-filter :delivered-to:dkim-filter; bh=hn38aUOHhHcvSWsYSfBkryGJAsQmbkDdnhJnIREaSB8=; fh=v2Nv3k9i7Amxu65q1mEuFELTOLzYYycJBMRhbhFxZhE=; b=DhmMvllzhj0v3nGpNQDeLY2suGEjsWzr5129aXCfLH5IziSehv8HWUuJkaK7I3G+Id 5UkoapIKYNyvk6x3tSFF8h2BsNFirxqKxpW0gx3Naq1QE/eHswOjYtLq7Jf1wYlkiHpL nF5079LvqScVW4wtJr2dGE4ZvDvtWYakjW7izTHkpw8L9wnvLs2SLadz863uRqvcZd/+ s2CvVe86+W6pq2kqYQ4Nlvojos9JdTGxJXV0oGlDWcZP9uuVXqU92bCBbU8cbfyorjmr cPICnbn3tSZZ8n9HeUekdHPr4C8CEDbOxB6nNKIe63kQzFcOqT9VmaIMMcvUFqj6rdvR Hi3w==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=DeFMe6G7; arc=pass (i=1); spf=pass (google.com: domain of libc-alpha-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="libc-alpha-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id 6a1803df08f44-6f5427fa386si19772676d6.410.2025.05.07.07.25.31 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 07 May 2025 07:25:32 -0700 (PDT) Received-SPF: pass (google.com: domain of libc-alpha-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=DeFMe6G7; arc=pass (i=1); spf=pass (google.com: domain of libc-alpha-bounces~patch=linaro.org@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="libc-alpha-bounces~patch=linaro.org@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 8B0FA3857711 for ; Wed, 7 May 2025 14:25:31 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 8B0FA3857711 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=DeFMe6G7 X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pj1-x1032.google.com (mail-pj1-x1032.google.com [IPv6:2607:f8b0:4864:20::1032]) by sourceware.org (Postfix) with ESMTPS id 0EFF83858CD1 for ; Wed, 7 May 2025 14:21:19 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 0EFF83858CD1 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 0EFF83858CD1 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::1032 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1746627679; cv=none; b=nS769JnEweXStzEiPtYg/CekKByPY2bVd7SREtYLUZN4n8ZEzdF/JcOeOTbHzAykHeuQIFcAhDvV3qdIu6J/9Frbl39X29EevnFnKpv3F1PfWwHhJPJRT4k5ooz/ctLLR/2XojaiB/xU4o2vVVTcX4LKfhPlkFeke/N1hlLZjLQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1746627679; c=relaxed/simple; bh=X5DHL9cQ0C3dJ4EqXF83XnbXPLQRPRh+V8inXD7EwkQ=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=Mq1W4XQxull4b7Mqeo//+R6uFWD4SBeLlFINA7vpQ6ikqEc/ueDA2Q90aDho11yhZPeyMpx8TnljDOPNV/kNNhQVHATUyBP0yrxwB0aoO1egsTxvVZpKxS37S7pI6IoGuLPLMUJQ/bEnBQFRF1F2ZXltFbE/HQxYG186eoGJ5Fo= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 0EFF83858CD1 Received: by mail-pj1-x1032.google.com with SMTP id 98e67ed59e1d1-30ac5cc0df4so580668a91.2 for ; Wed, 07 May 2025 07:21:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1746627678; x=1747232478; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=hn38aUOHhHcvSWsYSfBkryGJAsQmbkDdnhJnIREaSB8=; b=DeFMe6G7f0Bh5bsBUyKTdkLb3gDtGH10hnF/8zpVEtDwka089KmFOCFt3yf+Qq4rmc lSijyrPM1qAeZkRA9vjTjbM3v5YVL1PkPk5d0VodaLUGSHe/aHHibMJy1ks6fsPE+cRQ 3xs6SGsbdxlGL9u53V6ouiK/llMrYFEw/YTa8dwj1k3tO4OJpToIxJwvAC8MfKFJJuxg vGTnzJnyNrJODzNFuRV7n5KuhpzGETVKArajbDhmTuvJ0KI0MHGla9iSd6yFLo/1I/e/ +vhdQtKwLCRfwlTqFTERLkdwG0IEg/5f8xv5FvRngbpSgbN1D+m0tbsD3+y7rKvtvChv myDg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1746627678; x=1747232478; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=hn38aUOHhHcvSWsYSfBkryGJAsQmbkDdnhJnIREaSB8=; b=KV3kZOr3g7tnHkQh6wEB4twkepW68ltRMFxiLNZBh381znqloNwyxSFDrQzwQhQGD6 lP9J7xWCsJ3pQhHF5HoH0G05bxrllqftjZ9aAFf5amBG7fNxmzqrSW6vHTQpBiznVME7 Oico8Xqev95tVA21//cwwC5aq1h91CS26Aa0oQWWTIZ4FlGnFRSBZi+fUl86jvZ9XrQE fDmoHj30CrjPUje54zRxpC32+CIYaDYG6ePZcrLBe/LL+TYOlXz7EoZqv+O2SmyCQ2lD FfFNMvEpyGKFNpy3KpiSL0h1hg3ahTiO2RwqLMkCUOLrFMrjyX6CsApxhRqqdtcVg0Zd jZcQ== X-Gm-Message-State: AOJu0YzAIU65+5aMZoXrnNDrlCJxBxCpTDzRSi7ZpNq1CDU6/RFRhBNm GdsetHgT8uFojgcXAQM6/eEsoZHOse7VkPPMwqMvWbWRydDb5iXQGe3e2sXJPSPrrke2LfvnG6S x304= X-Gm-Gg: ASbGnctq46jGQ289BMzVSHrki7rIERy1EMRGepJHPu+4kVfLi23xHpKlW/AVn5lgsra FVqshsKHGvhcmQfoibhuqZqbZZBFjRfJhZJq6v/9OBYEfM10wnMzxLyqlkTE1VaUKy688iz5yqK qAHVVcjx28YDUwfAGXylqrKxoB48SwLGIFEzXjA1ZHw1CdGgvjqrYI/bd4jG354rdp8IqmqS2xN mMgfn/ScgnemYwkUu0rqDz7e0BLDRjCylK+CNsI7ZUJ8I9M7d9iW2GT1CIzq/ZnDl1S3odSIS1J Myvj8klbA/nCUk+OtFVhjYHQ15BAQwFv/BTuuLoGAjsHOy1lOn+70g== X-Received: by 2002:a17:90a:da87:b0:2ff:72f8:3708 with SMTP id 98e67ed59e1d1-30aac1adc25mr6150036a91.17.1746627676604; Wed, 07 May 2025 07:21:16 -0700 (PDT) Received: from mandiga.. ([2804:1b3:a7c0:2a60:2bef:3994:10d0:59c9]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-30ad474a050sm179453a91.8.2025.05.07.07.21.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 07 May 2025 07:21:16 -0700 (PDT) From: Adhemerval Zanella To: libc-alpha@sourceware.org Cc: Carlos O'Donell Subject: [PATCH 01/11] ubsan: Add initial support for -fsanitize=undefined Date: Wed, 7 May 2025 11:17:19 -0300 Message-ID: <20250507142110.3452012-2-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250507142110.3452012-1-adhemerval.zanella@linaro.org> References: <20250507142110.3452012-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces~patch=linaro.org@sourceware.org It is enabled through a new configure flag, --enable-ubsan, and should be used for debugging and/or testing. Not all ubsan handlers are implemented, only those generated/required by glibc libraries, programs, and tests. Some extra handlers might be needed in future C++ tests, and __ubsan_handle_dynamic_type_cache_miss also needs a proper implementation. The ubsan handlers are exported from ld.so since they are used on all libraries and tests. This might interfere with ubsan from compiler runtime (when programs are built with libubsan in shared mode), and this is completely untested and/or not supported at the moment. There is no support for the UBSAN_OPTIONS environment variable, although some options are supported through glibc.ubsan tunables. Currently, glibc.ubsan.halt_on_errors can be used to avoid the process halt when any UB handler is issued. Using -fsanitize=undefined enables some extra compiler checks that are not easily enabled through the libc-diag.h macro. For instance on iconv/iconvconfig.c, gcc 14.2.1 shows: In file included from ../include/bits/string_fortified.h:1, from ../string/string.h:548, from ../include/string.h:60, from iconvconfig.c:32: In function ‘strcpy’, inlined from ‘write_output’ at iconvconfig.c:1033:7, inlined from ‘main’ at iconvconfig.c:340:14: ../string/bits/string_fortified.h:81:10: error: ‘__builtin_memcpy’ offset [0, 7] is out of the bounds [0, 0] [-Werror=array-bounds=] 81 | return __builtin___strcpy_chk (__dest, __src, __glibc_objsize (__dest)); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../string/bits/string_fortified.h:81:10: error: ‘__builtin_memcpy’ offset [0, 7] is out of the bounds [0, 0] [-Werror=array-bounds=] cc1: all warnings being treated as errors Some extra code adjustments are required to fix such cases. This preliminary support is still incomplete: * Not all targets are supported, nor have I checked the test suitei on all successful targets. Also, I only checked with limited gcc versions (only gcc 14.2.1 and for some targets 15.0.0). Currently --enable-ubsan builds on Linux for aarch64, arm, hppa, i686, powerpc64, microblaze, mips64, loongarch64, sparc, s390x, and x86_64. * The instrumentation is disabled on rltd.c, although it is enabled on other loaders functions. * A lot of test cases show failures due to UB. Also, gcc-14 triggers an ICE building math routines. gcc-15 works correctly. --- INSTALL | 9 + Makeconfig | 6 +- config.h.in | 3 + configure | 30 ++ configure.ac | 18 + elf/Makefile | 32 +- elf/Versions | 19 + elf/dl-printf.c | 6 + elf/dl-tunables.list | 9 + elf/tst-_dl_addr_inside_object.c | 12 + elf/ubsan_error.c | 57 +++ elf/ubsan_handle_add_overflow.c | 26 ++ elf/ubsan_handle_builtin_unreachable.c | 27 ++ elf/ubsan_handle_divrem_overflow.c | 40 +++ elf/ubsan_handle_dynamic_type_cache_miss.c | 28 ++ elf/ubsan_handle_invalid_builtin.c | 39 +++ elf/ubsan_handle_load_invalid_value.c | 33 ++ elf/ubsan_handle_mul_overflow.c | 26 ++ elf/ubsan_handle_negate_overflow.c | 34 ++ elf/ubsan_handle_nonnull_arg.c | 34 ++ elf/ubsan_handle_nonnull_return_v1.c | 34 ++ elf/ubsan_handle_out_of_bounds.c | 34 ++ elf/ubsan_handle_overflow.c | 39 +++ elf/ubsan_handle_pointer_overflow.c | 62 ++++ elf/ubsan_handle_shift_out_of_bounds.c | 53 +++ elf/ubsan_handle_sub_overflow.c | 26 ++ elf/ubsan_handle_type_mismatch_v1.c | 75 ++++ elf/ubsan_handle_vla_bound_not_positive.c | 34 ++ elf/ubsan_val_to_string.c | 189 ++++++++++ elf/ubsan_vptr_type_cache.c | 21 ++ iconv/iconvconfig.c | 13 +- include/libintl.h | 3 + include/sys/cdefs.h | 6 + include/ubsan.h | 327 ++++++++++++++++++ locale/programs/locfile.h | 3 +- manual/install.texi | 8 + nss/test-netdb.c | 6 + posix/glob.c | 5 +- resolv/res_send.c | 11 +- stdio-common/tst-printf-format-s.h | 4 + stdio-common/tst-printf-format-vs.h | 4 + stdlib/stdbit.h | 9 +- sysdeps/arm/Makefile | 5 + sysdeps/generic/ldconfig.h | 3 +- sysdeps/generic/ldsodefs.h | 3 + sysdeps/generic/symbol-hacks.h | 36 ++ .../powerpc64/multiarch/stpncpy-ppc64.c | 3 +- 47 files changed, 1473 insertions(+), 31 deletions(-) create mode 100644 elf/ubsan_error.c create mode 100644 elf/ubsan_handle_add_overflow.c create mode 100644 elf/ubsan_handle_builtin_unreachable.c create mode 100644 elf/ubsan_handle_divrem_overflow.c create mode 100644 elf/ubsan_handle_dynamic_type_cache_miss.c create mode 100644 elf/ubsan_handle_invalid_builtin.c create mode 100644 elf/ubsan_handle_load_invalid_value.c create mode 100644 elf/ubsan_handle_mul_overflow.c create mode 100644 elf/ubsan_handle_negate_overflow.c create mode 100644 elf/ubsan_handle_nonnull_arg.c create mode 100644 elf/ubsan_handle_nonnull_return_v1.c create mode 100644 elf/ubsan_handle_out_of_bounds.c create mode 100644 elf/ubsan_handle_overflow.c create mode 100644 elf/ubsan_handle_pointer_overflow.c create mode 100644 elf/ubsan_handle_shift_out_of_bounds.c create mode 100644 elf/ubsan_handle_sub_overflow.c create mode 100644 elf/ubsan_handle_type_mismatch_v1.c create mode 100644 elf/ubsan_handle_vla_bound_not_positive.c create mode 100644 elf/ubsan_val_to_string.c create mode 100644 elf/ubsan_vptr_type_cache.c create mode 100644 include/ubsan.h diff --git a/INSTALL b/INSTALL index d3200f271f..50466cbfba 100644 --- a/INSTALL +++ b/INSTALL @@ -292,6 +292,15 @@ passed to 'configure'. For example: Default is to disable fortification. +'--enable-ubsan' + Build the GNU C library with, along with tests, with the + -fsanitize=undefined compiler option. The compiler runtime is not + used, instead UBSAN functions called by the compiler instrumentation + is provided by glibc itself. + + This is a debug/development option and the default is to disable + the instrumentation. + To build the library and related programs, type 'make'. This will produce a lot of output, some of which may look like errors from 'make' but aren't. Look for error messages from 'make' containing '***'. diff --git a/Makeconfig b/Makeconfig index a2ea4f6a33..110ae79063 100644 --- a/Makeconfig +++ b/Makeconfig @@ -995,12 +995,14 @@ ifeq "$(strip $(+cflags))" "" +cflags := $(default_cflags) endif # $(+cflags) == "" ++ubsan-flags = $(cflags-enable-ubsan) + # Force building with -fno-common because hidden_def, compat_symbol # and other constructs do not work for common symbols (and would # otherwise require specifying __attribute__ ((nocommon)) on a # case-by-case basis). +cflags += $(cflags-cpu) $(+gccwarn) $(+merge-constants) $(+math-flags) \ - $(+stack-protector) -fno-common + $(+stack-protector) $(+ubsan-flags) -fno-common +gcc-nowarn := -w # We must filter out elf because the early bootstrap of the dynamic loader @@ -1046,7 +1048,7 @@ libio-include = -I$(..)libio built-modules = iconvprogs iconvdata ldconfig libmemusage \ libpcprofile librpcsvc locale-programs \ memusagestat nonlib nscd extramodules libnldbl libsupport \ - testsuite testsuite-internal + testsuite testsuite-internal libubsan in-module = $(subst -,_,$(firstword $(libof-$(basename $(@F))) \ $(libof-$(. */ + +#include +#include +#include +#include +#include +#include + +static void _Noreturn +ubsan_abort (void) +{ + /* abort() pulls a lot of extra definition from libc (rwlock, signal + hanlding, pthread, etc.; so use a more simpler implementation for + now. */ + raise (SIGABRT); + +#ifdef ABORT_INSTRUCTION + ABORT_INSTRUCTION; +#endif + _exit (127); +} + +void +__ubsan_error (const struct source_location *source, + const char *fmt, + ...) +{ + _dl_debug_printf_c ("UBSAN: Undefined behaviour in %s:%u:%u ", + get_source_location_file_name (source), + get_source_location_line (source), + get_source_location_column (source)); + + va_list ap; + va_start (ap, fmt); + _dl_debug_vprintf_c (fmt, ap); + va_end (ap); + + if (TUNABLE_GET (glibc, ubsan, halt_on_errors, int32_t, NULL)) + ubsan_abort (); +} diff --git a/elf/ubsan_handle_add_overflow.c b/elf/ubsan_handle_add_overflow.c new file mode 100644 index 0000000000..b2463268cf --- /dev/null +++ b/elf/ubsan_handle_add_overflow.c @@ -0,0 +1,26 @@ +/* Undefined Behavior Sanitizer support. + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include "ubsan.h" + +void +__ubsan_handle_add_overflow (void *_data, void *lhs, void *rhs) +{ + __ubsan_handle_overflow (_data, lhs, rhs, "+"); +} +rtld_hidden_def (__ubsan_handle_add_overflow) diff --git a/elf/ubsan_handle_builtin_unreachable.c b/elf/ubsan_handle_builtin_unreachable.c new file mode 100644 index 0000000000..b2a7dde5c7 --- /dev/null +++ b/elf/ubsan_handle_builtin_unreachable.c @@ -0,0 +1,27 @@ +/* Undefined Behavior Sanitizer support. + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include "ubsan.h" + +void +__ubsan_handle_builtin_unreachable (void *_data) +{ + struct unreachable_data *data = _data; + __ubsan_error (&data->location, "calling __builtin_unreachable()\n"); +} +rtld_hidden_def (__ubsan_handle_builtin_unreachable) diff --git a/elf/ubsan_handle_divrem_overflow.c b/elf/ubsan_handle_divrem_overflow.c new file mode 100644 index 0000000000..bf5788c2fd --- /dev/null +++ b/elf/ubsan_handle_divrem_overflow.c @@ -0,0 +1,40 @@ +/* Undefined Behavior Sanitizer support. + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include "ubsan.h" + +void +__ubsan_handle_divrem_overflow (void *_data, void *lhs, void *rhs) +{ + struct overflow_data *data = _data; + char lhs_str[UBSAN_VAL_STR_LEN]; + char rhs_str[UBSAN_VAL_STR_LEN]; + + __ubsan_val_to_string (lhs_str, data->type, lhs); + __ubsan_val_to_string (rhs_str, data->type, rhs); + + if (ubsan_type_is_signed (data->type) + && ubsan_get_signed_val (data->type, rhs)) + __ubsan_error (&data->location, + "division overflow: division of %s by -1 cannot be " + "represented in type %s\n", + rhs_str, data->type->type_name); + else + __ubsan_error (&data->location, "division by zero"); +} +rtld_hidden_def (__ubsan_handle_divrem_overflow) diff --git a/elf/ubsan_handle_dynamic_type_cache_miss.c b/elf/ubsan_handle_dynamic_type_cache_miss.c new file mode 100644 index 0000000000..b5be609a0d --- /dev/null +++ b/elf/ubsan_handle_dynamic_type_cache_miss.c @@ -0,0 +1,28 @@ +/* Undefined Behavior Sanitizer support. + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include + + +void +__ubsan_handle_dynamic_type_cache_miss (void *_data, void *pointer, void *hash) +{ + /* TODO: this failure requires additional check to check for real + issues. Ignore for now. */ +} +rtld_hidden_def (__ubsan_handle_dynamic_type_cache_miss) diff --git a/elf/ubsan_handle_invalid_builtin.c b/elf/ubsan_handle_invalid_builtin.c new file mode 100644 index 0000000000..4518408ab1 --- /dev/null +++ b/elf/ubsan_handle_invalid_builtin.c @@ -0,0 +1,39 @@ +/* Undefined Behavior Sanitizer support. + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include + +void +__ubsan_handle_invalid_builtin (void *_data) +{ + struct invalid_builtin_data *data = _data; + switch (data->kind) + { + case ubsan_builtin_check_kind_assume_passed_false: + __ubsan_error (&data->location, + "assumption is violated during execution\n"); + break; + default: + __ubsan_error (&data->location, + "passing zero to __builtin_%s()\n", + data->kind == ubsan_builtin_check_kind_ctz_passed_zero + ? "ctz" : "clz"); + break; + } +} +rtld_hidden_def (__ubsan_handle_invalid_builtin) diff --git a/elf/ubsan_handle_load_invalid_value.c b/elf/ubsan_handle_load_invalid_value.c new file mode 100644 index 0000000000..b2b2e9b3cd --- /dev/null +++ b/elf/ubsan_handle_load_invalid_value.c @@ -0,0 +1,33 @@ +/* Undefined Behavior Sanitizer support. + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include "ubsan.h" + +void +__ubsan_handle_load_invalid_value (void *_data, void *val) +{ + struct invalid_value_data *data = _data; + char val_str[UBSAN_VAL_STR_LEN]; + + __ubsan_val_to_string (val_str, data->type, val); + __ubsan_error (&data->location, + "load of value %s is not a valid value for type %s\n", + val_str, + data->type->type_name); +} +rtld_hidden_def (__ubsan_handle_load_invalid_value) diff --git a/elf/ubsan_handle_mul_overflow.c b/elf/ubsan_handle_mul_overflow.c new file mode 100644 index 0000000000..b0010b9329 --- /dev/null +++ b/elf/ubsan_handle_mul_overflow.c @@ -0,0 +1,26 @@ +/* Undefined Behavior Sanitizer support. + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include "ubsan.h" + +void +__ubsan_handle_mul_overflow (void *_data, void *lhs, void *rhs) +{ + __ubsan_handle_overflow (_data, lhs, rhs, "*"); +} +rtld_hidden_def (__ubsan_handle_mul_overflow) diff --git a/elf/ubsan_handle_negate_overflow.c b/elf/ubsan_handle_negate_overflow.c new file mode 100644 index 0000000000..bb0c12ea5e --- /dev/null +++ b/elf/ubsan_handle_negate_overflow.c @@ -0,0 +1,34 @@ +/* Undefined Behavior Sanitizer support. + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include "ubsan.h" + +void +__ubsan_handle_negate_overflow (void *_data, void *val) +{ + struct overflow_data *data = _data; + char val_str[UBSAN_VAL_STR_LEN]; + + __ubsan_val_to_string(val_str, data->type, val); + + __ubsan_error (&data->location, + "negation of %s cannot be represented in type %s\n", + val_str, + data->type->type_name); +} +rtld_hidden_def (__ubsan_handle_negate_overflow) diff --git a/elf/ubsan_handle_nonnull_arg.c b/elf/ubsan_handle_nonnull_arg.c new file mode 100644 index 0000000000..a5104fd49d --- /dev/null +++ b/elf/ubsan_handle_nonnull_arg.c @@ -0,0 +1,34 @@ +/* Undefined Behavior Sanitizer support. + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include "ubsan.h" + +void +__ubsan_handle_nonnull_arg (void *_data) +{ + struct nonnull_arg_data *data = _data; + + __ubsan_error (&data->location, + "null pointer passed as argument %u, nonnull attribute " + "declared at %s:%u:%u\n", + data->arg_index, + get_source_location_file_name (&data->attr_location), + get_source_location_line (&data->attr_location), + get_source_location_column (&data->attr_location)); +} +rtld_hidden_def (__ubsan_handle_nonnull_arg) diff --git a/elf/ubsan_handle_nonnull_return_v1.c b/elf/ubsan_handle_nonnull_return_v1.c new file mode 100644 index 0000000000..a6e0d73fef --- /dev/null +++ b/elf/ubsan_handle_nonnull_return_v1.c @@ -0,0 +1,34 @@ +/* Undefined Behavior Sanitizer support. + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include + +void +__ubsan_handle_nonnull_return_v1 (void *_data, void *_location) +{ + struct nonnull_return_data *data = _data; + struct source_location *location = _location; + + __ubsan_error (&data->location, + "null pointer returned from function declared as " + "returns_nonnull: source %s:%u:%u\n", + get_source_location_file_name (location), + get_source_location_line (location), + get_source_location_column (location)); +} +rtld_hidden_def (__ubsan_handle_nonnull_return_v1) diff --git a/elf/ubsan_handle_out_of_bounds.c b/elf/ubsan_handle_out_of_bounds.c new file mode 100644 index 0000000000..469682ddfd --- /dev/null +++ b/elf/ubsan_handle_out_of_bounds.c @@ -0,0 +1,34 @@ +/* Undefined Behavior Sanitizer support. + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include "ubsan.h" + +void +__ubsan_handle_out_of_bounds (void *_data, void *index) +{ + struct out_of_bounds_data *data = _data; + char index_str[UBSAN_VAL_STR_LEN]; + + __ubsan_val_to_string (index_str, data->index_type, index); + + __ubsan_error (&data->location, + "index %s is out of bounds for type %s\n", + index_str, + data->array_type->type_name); +} +rtld_hidden_def (__ubsan_handle_out_of_bounds) diff --git a/elf/ubsan_handle_overflow.c b/elf/ubsan_handle_overflow.c new file mode 100644 index 0000000000..865ad76e49 --- /dev/null +++ b/elf/ubsan_handle_overflow.c @@ -0,0 +1,39 @@ +/* Undefined Behavior Sanitizer support. + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include "ubsan.h" + +void +__ubsan_handle_overflow (const struct overflow_data * data, void *lhs, + void *rhs, const char *op) +{ + char lhs_str[UBSAN_VAL_STR_LEN]; + char rhs_str[UBSAN_VAL_STR_LEN]; + + __ubsan_val_to_string (lhs_str, data->type, lhs); + __ubsan_val_to_string (rhs_str, data->type, rhs); + + __ubsan_error (&data->location, + "%s integer overflow: %s %s %s cannot be represened in " + "type %s\n", + ubsan_type_is_signed (data->type) ? "signed" : "unsigned", + lhs_str, + op, + rhs_str, + data->type->type_name); +} diff --git a/elf/ubsan_handle_pointer_overflow.c b/elf/ubsan_handle_pointer_overflow.c new file mode 100644 index 0000000000..8d0c4db739 --- /dev/null +++ b/elf/ubsan_handle_pointer_overflow.c @@ -0,0 +1,62 @@ +/* Undefined Behavior Sanitizer support. + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include + +void +__ubsan_handle_pointer_overflow (void *_data, void *val, void *result) +{ + struct pointer_overflow_data *data = _data; + + if (val == NULL && result == NULL) + __ubsan_error (&data->location, + "applying zero offset to a NULL pointer\n"); + else if (val == NULL && result != NULL) + __ubsan_error (&data->location, + "applying non-zero offset to a NULL pointer\n"); + else if (val != NULL && result == NULL) + __ubsan_error (&data->location, + "applying non-zero offset to non-NULL pointer 0x%0*lx " + "produced NULL pointer\n", + (int) sizeof (void *) * 2, + (unsigned long int) val); + else if (((intptr_t)val >= 0) == ((intptr_t)result >= 0)) + { + const char *operation = ((uintptr_t)val > (uintptr_t)result) + ? "addition" : "subtraction"; + + __ubsan_error (&data->location, + "%s of unsigned offset to 0x%0*lx overflowed " + "to 0x%0*lx\n", + operation, + (int) sizeof (void *) * 2, + (unsigned long int) val, + (int) sizeof (void *) * 2, + (unsigned long int) result); + } + else + __ubsan_error (&data->location, + "pointer index expression with base 0x%0*lx overflowed " + "to 0x%0*lx\n", + (int) sizeof (void *) * 2, + (unsigned long int) val, + (int) sizeof (void *) * 2, + (unsigned long int) result); +} +rtld_hidden_def (__ubsan_handle_pointer_overflow) diff --git a/elf/ubsan_handle_shift_out_of_bounds.c b/elf/ubsan_handle_shift_out_of_bounds.c new file mode 100644 index 0000000000..f8402778ba --- /dev/null +++ b/elf/ubsan_handle_shift_out_of_bounds.c @@ -0,0 +1,53 @@ +/* Undefined Behavior Sanitizer support. + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include + +void +__ubsan_handle_shift_out_of_bounds (void *_data, void *lhs, void *rhs) +{ + struct shift_out_of_bounds_data *data = _data; + char lhs_str[UBSAN_VAL_STR_LEN]; + char rhs_str[UBSAN_VAL_STR_LEN]; + + __ubsan_val_to_string (lhs_str, data->lhs_type, lhs); + __ubsan_val_to_string (rhs_str, data->rhs_type, rhs); + + if (ubsan_val_is_negative (data->rhs_type, rhs)) + __ubsan_error (&data->location, + "shift expoenent %s is negative\n", + rhs_str); + else if (ubsan_get_unsigned_val (data->rhs_type, rhs) >= + ubsan_type_bit_width (data->lhs_type)) + __ubsan_error (&data->location, + "shift exponent %s is too large for %u-bit type %s\n", + rhs_str, + ubsan_type_bit_width (data->lhs_type), + data->lhs_type->type_name); + else if (ubsan_val_is_negative (data->lhs_type, lhs)) + __ubsan_error (&data->location, + "left shift of negative valor %s\n", + lhs_str); + else + __ubsan_error (&data->location, + "left shift of %s by %s cannot be represented in type %s\n", + lhs_str, + rhs_str, + data->lhs_type->type_name); +} +rtld_hidden_def (__ubsan_handle_shift_out_of_bounds) diff --git a/elf/ubsan_handle_sub_overflow.c b/elf/ubsan_handle_sub_overflow.c new file mode 100644 index 0000000000..8b576dae14 --- /dev/null +++ b/elf/ubsan_handle_sub_overflow.c @@ -0,0 +1,26 @@ +/* Undefined Behavior Sanitizer support. + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include + +void +__ubsan_handle_sub_overflow (void *_data, void *lhs, void *rhs) +{ + __ubsan_handle_overflow (_data, lhs, rhs, "-"); +} +rtld_hidden_def (__ubsan_handle_sub_overflow) diff --git a/elf/ubsan_handle_type_mismatch_v1.c b/elf/ubsan_handle_type_mismatch_v1.c new file mode 100644 index 0000000000..de459b99f4 --- /dev/null +++ b/elf/ubsan_handle_type_mismatch_v1.c @@ -0,0 +1,75 @@ +/* Undefined Behavior Sanitizer support. + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include + +static const char * +type_check_to_string (unsigned char type_check_kind) +{ + switch (type_check_kind) + { + case ubsan_type_check_load: return "load of"; + case ubsan_type_check_store: return "store to"; + case ubsan_type_check_reference_binding: return "reference binding to"; + case ubsan_type_check_member_access: return "member access within"; + case ubsan_type_check_member_call: return "member call on"; + case ubsan_type_check_constructor_call: return "constructor call on"; + case ubsan_type_check_downcast_pointer: + case ubsan_type_check_downcast_reference: return "downcast of"; + case ubsan_type_check_upcast: return "upcast of"; + case ubsan_type_check_upcast_to_virtual_base: return "cast to virtual base of"; + case ubsan_type_check_nonnull_assign: return "_Nonnull binding to"; + case ubsan_type_check_dynamic_operation: return "dynamic operation on"; + default: return "unknown"; + } +} + +static inline bool +is_misaligned_pointer (const struct type_mismatch_data_v1 *data, void *ptr) +{ + uintptr_t alignment = 1UL << data->log_alignment; + return (uintptr_t) ptr & (alignment - 1); +} + +void +__ubsan_handle_type_mismatch_v1 (void *_data, void *ptr) +{ + struct type_mismatch_data_v1 *data = _data; + + if (data->type_check_kind == ubsan_type_check_nonnull_assign) + __ubsan_error (&data->location, + "%s null pointer of type %s\n", + type_check_to_string (data->type_check_kind), + data->type->type_name); + else if (is_misaligned_pointer (data, ptr)) + __ubsan_error (&data->location, + "%s misaligned address 0x%0*lx for type %s\n", + type_check_to_string (data->type_check_kind), + (int) sizeof (void *) * 2, + (unsigned long int) ptr, + data->type->type_name); + else + __ubsan_error (&data->location, + "%s address 0x%0*lx with insufficient space for an " + "object of type %s\n", + type_check_to_string (data->type_check_kind), + (int) sizeof (void *) * 2, + (unsigned long int) ptr, + data->type->type_name); +} +rtld_hidden_def (__ubsan_handle_type_mismatch_v1) diff --git a/elf/ubsan_handle_vla_bound_not_positive.c b/elf/ubsan_handle_vla_bound_not_positive.c new file mode 100644 index 0000000000..e2b3f5232d --- /dev/null +++ b/elf/ubsan_handle_vla_bound_not_positive.c @@ -0,0 +1,34 @@ +/* Undefined Behavior Sanitizer support. + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include + +void +__ubsan_handle_vla_bound_not_positive (void *_data, void *bound) +{ + struct vla_bound_not_positive_data *data = _data; + char bound_str[UBSAN_VAL_STR_LEN]; + + __ubsan_val_to_string (bound_str, data->type, bound); + + __ubsan_error (&data->location, + "variable length array bound evaluates to " + "non-positive value %s\n", + bound_str); +} +rtld_hidden_def (__ubsan_handle_vla_bound_not_positive) diff --git a/elf/ubsan_val_to_string.c b/elf/ubsan_val_to_string.c new file mode 100644 index 0000000000..f354eed49d --- /dev/null +++ b/elf/ubsan_val_to_string.c @@ -0,0 +1,189 @@ +/* Undefined Behavior Sanitizer support. + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include + +#include "ubsan.h" + +static const char lower_digits[] = "0123456789"; + +enum { BASE = 10 }; + +static char * +utoa (unsigned long long int value, char *buf, size_t len) +{ + if (len == 0) + return buf; + + char *ptr = buf; + do + { + if (len-- == 0) + break; + *ptr++ = lower_digits[value % BASE]; + value /= BASE; + } + while (value != 0); + char *r = ptr; + *ptr-- = '\0'; + + while (buf < ptr) + { + char t = *ptr; + *ptr-- = *buf; + *buf++ = t; + } + + return r; +} + +static char * +itoa (long long int value, char *buf, size_t len) +{ + if (len == 0) + return buf; + + bool isneg = value < 0; + char *ptr = buf; + do + { + if (len-- == 0) + break; + *ptr++ = lower_digits[abs (value % BASE)]; + value /= BASE; + } + while (value != 0); + if (isneg) + *ptr++ = '-'; + char *r = ptr; + *ptr-- = '\0'; + + while (buf < ptr) + { + char t = *ptr; + *ptr-- = *buf; + *buf++ = t; + } + + return r; +} + +static long long int +ubsan_val_to_ll (int width, void *value, long long int def) +{ + switch (width) + { + case 8: + return (int8_t) (intptr_t) value; + case 16: + return (int16_t) (intptr_t) value; + case 32: + if (sizeof (value) >= sizeof (int32_t)) + return (int32_t) (intptr_t) value; + else + return *(int32_t *) value; + case 64: + if (sizeof (value) >= sizeof (int64_t)) + return (int64_t) (intptr_t) value; + else + return *(int64_t *) value; + default: + return def; + } +} + +static unsigned long long int +ubsan_val_to_ull (int width, void *value, unsigned long long int def) +{ + switch (width) + { + case 8: + return (uint8_t) (uintptr_t) value; + case 16: + return (uint16_t) (uintptr_t) value; + case 32: + if (sizeof (value) >= sizeof (uint32_t)) + return (uint32_t) (uintptr_t) value; + else + return *(uint32_t *) value; + case 64: + if (sizeof (value) >= sizeof (uint64_t)) + return (uint64_t) (uintptr_t) value; + else + return *(uint64_t *) value; + default: + return def; + } +} + +static inline char * +add_string (char *str, const char *s, size_t *len) +{ + char *endp = __stpncpy (str, s, *len); + *len -= endp - str; + return endp; +} + +static inline char * +add_uint (char *str, unsigned long long int value, size_t *len) +{ + char *endp = utoa (value, str, *len); + *len -= endp - str; + return endp; +} + +void +__ubsan_val_to_string (char str[static UBSAN_VAL_STR_LEN], + struct type_descriptor *type, void *value) +{ + int width = ubsan_type_bit_width (type); + switch (type->type_kind) + { + case ubsan_type_kind_int: + if (ubsan_type_is_signed (type)) + { + long long int v = ubsan_val_to_ll (width, value, 0); + itoa (v, str, UBSAN_VAL_STR_LEN); + } + else + { + unsigned long long int v = ubsan_val_to_ull (width, value, 0); + utoa (v, str, UBSAN_VAL_STR_LEN); + } + break; + case ubsan_type_kind_float: + { + char *endp = __stpcpy (str, "float size "); + utoa (width, endp, UBSAN_VAL_STR_LEN); + } + break; + default: + { + size_t size = UBSAN_VAL_STR_LEN; + char *endp = add_string (str, "kind ", &size); + endp = add_uint (endp, type->type_kind, &size); + endp = add_string (endp, " (width ", &size); + endp = add_uint (endp, width, &size); + add_string (endp, " )", &size); + } + break; + } +} diff --git a/elf/ubsan_vptr_type_cache.c b/elf/ubsan_vptr_type_cache.c new file mode 100644 index 0000000000..77572b2487 --- /dev/null +++ b/elf/ubsan_vptr_type_cache.c @@ -0,0 +1,21 @@ +/* Undefined Behavior Sanitizer support. + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include + +unsigned int __ubsan_vptr_type_cache[UBSAN_VPTR_TYPE_CACHE_SIZE]; diff --git a/iconv/iconvconfig.c b/iconv/iconvconfig.c index aa6f381266..8975aa086e 100644 --- a/iconv/iconvconfig.c +++ b/iconv/iconvconfig.c @@ -1019,11 +1019,14 @@ write_output (void) /* Open the output file. */ if (output_file == NULL) { - assert (GCONV_MODULES_CACHE[0] == '/'); - strcpy (stpcpy (mempcpy (tmpfname, prefix, prefix_len), - GCONV_MODULES_CACHE), - ".XXXXXX"); - strcpy (mempcpy (finalname, prefix, prefix_len), GCONV_MODULES_CACHE); + snprintf (tmpfname, sizeof tmpfname, "%.*s%s.XXXXXX", + (int) prefix_len, + prefix, + GCONV_MODULES_CACHE); + snprintf (finalname, sizeof finalname, "%.*s%s", + (int) prefix_len, + prefix, + GCONV_MODULES_CACHE); } else strcpy (mempcpy (tmpfname, output_file, output_file_len), ".XXXXXX"); diff --git a/include/libintl.h b/include/libintl.h index 3d63b7abbd..57039f1fc1 100644 --- a/include/libintl.h +++ b/include/libintl.h @@ -65,5 +65,8 @@ libc_hidden_proto (_libc_intl_domainname) # undef N_ # define N_(msgid) msgid +# undef gettext +# define gettext(msgid) (dgettext (NULL, msgid) ?: (char *)msgid) + # endif /* !_ISOMAC */ #endif diff --git a/include/sys/cdefs.h b/include/sys/cdefs.h index a676f75f62..8ec2079fa4 100644 --- a/include/sys/cdefs.h +++ b/include/sys/cdefs.h @@ -63,4 +63,10 @@ rtld_hidden_proto (__chk_fail) # define __attribute_optimization_barrier__ __attribute__ ((noinline, noclone)) #endif +#ifdef ENABLE_UBSAN +# define __attribute_disable_ubsan__ __attribute__((no_sanitize("undefined"))) +#else +# define __attribute_disable_ubsan__ +#endif + #endif diff --git a/include/ubsan.h b/include/ubsan.h new file mode 100644 index 0000000000..56d8721507 --- /dev/null +++ b/include/ubsan.h @@ -0,0 +1,327 @@ +/* Undefined Behavior Sanitizer support. + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef __UBSAN_H__ +#define __UBSAN_H__ + +#include +#include +#include + +#ifdef __SIZEOF_INT128__ +typedef __int128 ubsan_s_max; +typedef unsigned __int128 ubsan_u_max; +#else +typedef int64_t ubsan_u_max; +typedef uint64_t ubsan_s_max; +#endif + +#define REPORTED_BIT 31 +#if (__WORDSIZE == 64 && BYTE_ORDER == BIG_ENDIAN) +# define COLUMN_MASK (~(1U << REPORTED_BIT)) +# define LINE_MASK (~0U) +#else +# define COLUMN_MASK (~0U) +# define LINE_MASK (~(1U << REPORTED_BIT)) +#endif + +struct source_location +{ + const char *file_name; + unsigned int line; + unsigned int column; +}; + +static inline const char * +get_source_location_file_name (const struct source_location *location) +{ + return location->file_name ? location->file_name : "unknown"; +} + +static inline unsigned int +get_source_location_line (const struct source_location *location) +{ + return location->line & LINE_MASK; +} + +static inline unsigned int +get_source_location_column (const struct source_location *location) +{ + return location->column & COLUMN_MASK; +} + +struct nonnull_arg_data +{ + struct source_location location; + struct source_location attr_location; + int arg_index; +}; + +struct type_descriptor +{ + uint16_t type_kind; + uint16_t type_info; + char type_name[]; +}; + +static inline bool +ubsan_type_is_signed (const struct type_descriptor *type) +{ + return type->type_kind & 1; +} + +static inline unsigned int +ubsan_type_bit_width (const struct type_descriptor *type) +{ + return 1 << (type->type_info >> 1); +} + +static inline bool +ubsan_is_inline_int (const struct type_descriptor *type) +{ + unsigned int inline_bits = sizeof (unsigned long) * 8; + unsigned int bits = ubsan_type_bit_width (type); + + return bits <= inline_bits; +} + +static inline ubsan_s_max +ubsan_get_signed_val (const struct type_descriptor *type, void *val) +{ + if (ubsan_is_inline_int (type)) + { + unsigned int extra_bits = sizeof (ubsan_s_max) * 8 + - ubsan_type_bit_width (type); + unsigned long ul_val = (unsigned long) val; + return ((ubsan_s_max) ul_val) << extra_bits >> extra_bits; + } + + if (ubsan_type_bit_width (type) == 64) + return *(int64_t*) val; + + return *(ubsan_s_max *) val; +} + +static inline ubsan_u_max +ubsan_get_unsigned_val (const struct type_descriptor *type, void *val) +{ + if (ubsan_is_inline_int (type)) + return (unsigned long) val; + + if (ubsan_type_bit_width (type) == 64) + return *(uint64_t*) val; + + return *(ubsan_u_max *)val; +} + +static inline bool +ubsan_val_is_negative (const struct type_descriptor *type, void *val) +{ + return ubsan_type_is_signed (type) && ubsan_get_signed_val (type, val) < 0; +} + +struct invalid_value_data +{ + struct source_location location; + struct type_descriptor *type; +}; + +/* The type_mismatch_data_v1::type_check_kind */ +enum +{ + ubsan_type_check_load, + ubsan_type_check_store, + ubsan_type_check_reference_binding, + ubsan_type_check_member_access, + ubsan_type_check_member_call, + ubsan_type_check_constructor_call, + ubsan_type_check_downcast_pointer, + ubsan_type_check_downcast_reference, + ubsan_type_check_upcast, + ubsan_type_check_upcast_to_virtual_base, + ubsan_type_check_nonnull_assign, + ubsan_type_check_dynamic_operation +}; + +struct type_mismatch_data_v1 +{ + struct source_location location; + struct type_descriptor *type; + unsigned char log_alignment; + unsigned char type_check_kind; +}; + +struct pointer_overflow_data +{ + struct source_location location; +}; + +struct overflow_data +{ + struct source_location location; + struct type_descriptor *type; +}; + +struct out_of_bounds_data +{ + struct source_location location; + struct type_descriptor *array_type; + struct type_descriptor *index_type; +}; + +struct shift_out_of_bounds_data +{ + struct source_location location; + struct type_descriptor *lhs_type; + struct type_descriptor *rhs_type; +}; + +struct vla_bound_not_positive_data +{ + struct source_location location; + struct type_descriptor *type; +}; + +struct unreachable_data +{ + struct source_location location; +}; + +struct invalid_builtin_data +{ + struct source_location location; + unsigned char kind; +}; + +struct nonnull_return_data +{ + struct source_location location; +}; + +struct dynamic_type_cache_miss_data +{ + struct source_location location; + struct type_descriptor *type; + void *info; + unsigned char kind; +}; + +enum +{ + ubsan_type_kind_int = 0, + ubsan_type_kind_float = 1, + ubsan_type_unknown = 0xffff +}; + +enum +{ + ubsan_builtin_check_kind_ctz_passed_zero, + ubsan_builtin_check_kind_clz_passed_zero, + ubsan_builtin_check_kind_assume_passed_false, +}; + +#define UBSAN_VAL_STR_LEN 32 + +void +__ubsan_val_to_string (char str[static UBSAN_VAL_STR_LEN], + struct type_descriptor *type, void *value) + attribute_hidden; + +#define UBSAN_VPTR_TYPE_CACHE_SIZE 128 + +extern unsigned int __ubsan_vptr_type_cache[UBSAN_VPTR_TYPE_CACHE_SIZE]; + +#if IS_IN(rtld) +# define ubsan_hidden attribute_hidden +#else +# define ubsan_hidden +#endif + +void __ubsan_error (const struct source_location *source, + const char *fmt, ...) + __attribute__ ((__format__ (__printf__, 2, 3))) + attribute_hidden; + +void __ubsan_handle_overflow (const struct overflow_data *, void *, + void *, const char *op) + attribute_hidden; + +void __ubsan_handle_load_invalid_value (void *data, void *value) + ubsan_hidden; +rtld_hidden_proto (__ubsan_handle_load_invalid_value) + +void __ubsan_handle_type_mismatch_v1 (void *data, void *ptr) + ubsan_hidden; +rtld_hidden_proto (__ubsan_handle_type_mismatch_v1) + +void __ubsan_handle_pointer_overflow (void *data, void *val, void *result) + ubsan_hidden; +rtld_hidden_proto (__ubsan_handle_pointer_overflow) + +void __ubsan_handle_add_overflow (void *data, void *lhs, void *rhs) + ubsan_hidden; +rtld_hidden_proto (__ubsan_handle_add_overflow) + +void __ubsan_handle_sub_overflow (void *data, void *lhs, void *rhs) + ubsan_hidden; +rtld_hidden_proto (__ubsan_handle_sub_overflow) + +void __ubsan_handle_mul_overflow (void *data, void *lhs, void *rhs) + attribute_hidden; +rtld_hidden_proto (__ubsan_handle_mul_overflow) + +void __ubsan_handle_out_of_bounds (void *data, void *index) + ubsan_hidden; +rtld_hidden_proto (__ubsan_handle_out_of_bounds) + +void __ubsan_handle_negate_overflow (void *data, void *val) + ubsan_hidden; +rtld_hidden_proto (__ubsan_handle_negate_overflow) + +void __ubsan_handle_shift_out_of_bounds (void *_data, void *lhs, void *rhs) + ubsan_hidden; +rtld_hidden_proto (__ubsan_handle_shift_out_of_bounds) + +void __ubsan_handle_divrem_overflow (void *_data, void *lhs, void *rhs) + ubsan_hidden; +rtld_hidden_proto (__ubsan_handle_divrem_overflow) + +void __ubsan_handle_vla_bound_not_positive (void *data, void *bound) + ubsan_hidden; +rtld_hidden_proto (__ubsan_handle_vla_bound_not_positive) + +void __ubsan_handle_builtin_unreachable (void *data) + ubsan_hidden; +rtld_hidden_proto (__ubsan_handle_builtin_unreachable) + +void __ubsan_handle_invalid_builtin (void *data) + ubsan_hidden; +rtld_hidden_proto (__ubsan_handle_invalid_builtin) + +void __ubsan_handle_nonnull_arg (void *data) + ubsan_hidden; +rtld_hidden_proto (__ubsan_handle_nonnull_arg); + +void __ubsan_handle_nonnull_return_v1 (void *data, void *location) + ubsan_hidden; +rtld_hidden_proto (__ubsan_handle_nonnull_return_v1) + +void __ubsan_handle_dynamic_type_cache_miss (void *, void *, void *); +rtld_hidden_proto (__ubsan_handle_dynamic_type_cache_miss) + +#endif /* __UBSAN_H__ */ diff --git a/locale/programs/locfile.h b/locale/programs/locfile.h index 9103fade14..e0000bc392 100644 --- a/locale/programs/locfile.h +++ b/locale/programs/locfile.h @@ -124,7 +124,8 @@ extern void end_locale_structure (struct locale_file *file); extern void start_locale_prelude (struct locale_file *file); extern void end_locale_prelude (struct locale_file *file); extern void write_locale_data (const char *output_path, int catidx, - const char *category, struct locale_file *file); + const char *category, struct locale_file *file) + __attribute__ ((nonnull (1, 3, 4))); /* Entrypoints for the parsers of the individual categories. */ diff --git a/manual/install.texi b/manual/install.texi index 7fcdda9146..1e4242dff4 100644 --- a/manual/install.texi +++ b/manual/install.texi @@ -320,6 +320,14 @@ If not provided, @option{LEVEL} defaults to highest possible value supported by the build compiler. Default is to disable fortification. + +@item --enable-ubsan +Build @theglibc{}, along with tests, with the @code{-fsanitize=undefined} +compiler option. The compiler runtime is not used, instead UBSAN functions +called by the compiler instrumentation is provided by glibc itself. + +This is a debug/development option and the default is to disable +the instrumentation. @end table To build the library and related programs, type @code{make}. This will diff --git a/nss/test-netdb.c b/nss/test-netdb.c index 3fb9ba0a42..3911c3c42a 100644 --- a/nss/test-netdb.c +++ b/nss/test-netdb.c @@ -41,6 +41,9 @@ #include +#define assume(R) ((R) ? (void) 0 : __builtin_unreachable ()) +#define assume_nonnull(x) assume ((x) != NULL) + /* The following define is necessary for glibc 2.0.6 */ @@ -180,6 +183,9 @@ test_hosts (void) namelen += 2; /* tiny increments to test a lot */ name = xrealloc (name, namelen); } + + assume_nonnull (name); + if (gethostname (name, namelen) == 0) { printf ("Hostname: %s\n", name); diff --git a/posix/glob.c b/posix/glob.c index a7c7dd1ebe..60ca0147ac 100644 --- a/posix/glob.c +++ b/posix/glob.c @@ -1397,9 +1397,10 @@ glob_in_dir (const char *pattern, const char *directory, int flags, if (s.length < need && !scratch_buffer_set_array_size (&s, need, 1)) goto memory_error; - char *p = mempcpy (s.data, directory, dirlen); + char *pdata = s.data; + char *p = mempcpy (pdata, directory, dirlen); *p = '/'; - p += p[-1] != '/'; + p += pdata[p - pdata - 1] != '/'; memcpy (p, d.name, namelen + 1); if (! is_dir (s.data, flags, pglob)) continue; diff --git a/resolv/res_send.c b/resolv/res_send.c index 802675995d..37444fc925 100644 --- a/resolv/res_send.c +++ b/resolv/res_send.c @@ -801,7 +801,7 @@ reopen (res_state statp, int *terrno, int ns) { if (EXT(statp).nssocks[ns] == -1) { struct sockaddr *nsap = __res_get_nsaddr (statp, ns); - socklen_t slen; + socklen_t slen = 0; /* only try IPv6 if IPv6 NS and if not failed before */ if (nsap->sa_family == AF_INET6 && !statp->ipv6_unavail) { @@ -845,16 +845,7 @@ reopen (res_state statp, int *terrno, int ns) * error message is received. We can thus detect * the absence of a nameserver without timing out. */ - /* With GCC 5.3 when compiling with -Os the compiler - emits a warning that slen may be used uninitialized, - but that is never true. Both slen and - EXT(statp).nssocks[ns] are initialized together or - the function return -1 before control flow reaches - the call to connect with slen. */ - DIAG_PUSH_NEEDS_COMMENT; - DIAG_IGNORE_Os_NEEDS_COMMENT (5, "-Wmaybe-uninitialized"); if (__connect (EXT (statp).nssocks[ns], nsap, slen) < 0) { - DIAG_POP_NEEDS_COMMENT; __res_iclose(statp, false); return (0); } diff --git a/stdio-common/tst-printf-format-s.h b/stdio-common/tst-printf-format-s.h index 20369b8e86..92946cbcba 100644 --- a/stdio-common/tst-printf-format-s.h +++ b/stdio-common/tst-printf-format-s.h @@ -21,6 +21,9 @@ #include +#define assume(R) ((R) ? (void) 0 : __builtin_unreachable ()) +#define assume_nonnull(x) assume ((x) != NULL) + #define SPRINTF_BUFFER_SIZE 65536 static struct support_next_to_fault ntf; @@ -42,6 +45,7 @@ printf_under_test_fini (void) ({ \ __label__ out; \ char *str = ntf.buffer; \ + assume_nonnull (str); \ int result; \ \ result = sprintf (str, __VA_ARGS__); \ diff --git a/stdio-common/tst-printf-format-vs.h b/stdio-common/tst-printf-format-vs.h index f99747a924..15d5341f80 100644 --- a/stdio-common/tst-printf-format-vs.h +++ b/stdio-common/tst-printf-format-vs.h @@ -22,6 +22,9 @@ #include +#define assume(R) ((R) ? (void) 0 : __builtin_unreachable ()) +#define assume_nonnull(x) assume ((x) != NULL) + #define SPRINTF_BUFFER_SIZE 65536 static struct support_next_to_fault ntf; @@ -43,6 +46,7 @@ static int printf_under_test (const char *restrict fmt, ...) { char *str = ntf.buffer; + assume_nonnull (str); va_list ap; int result; diff --git a/stdlib/stdbit.h b/stdlib/stdbit.h index 4afa4362d1..36b92901e5 100644 --- a/stdlib/stdbit.h +++ b/stdlib/stdbit.h @@ -44,13 +44,8 @@ __BEGIN_DECLS /* Use __pacify_uint16 (N) instead of (uint16_t) (N) when the cast is helpful only to pacify older GCC (e.g., GCC 10 -Wconversion) or non-GCC (e.g clang -Wimplicit-int-conversion). */ -#if __GNUC_PREREQ (11, 0) -# define __pacify_uint8(n) (n) -# define __pacify_uint16(n) (n) -#else -# define __pacify_uint8(n) ((uint8_t) (n)) -# define __pacify_uint16(n) ((uint16_t) (n)) -#endif +#define __pacify_uint8(n) ((uint8_t) (n)) +#define __pacify_uint16(n) ((uint16_t) (n)) /* Count leading zeros. */ extern unsigned int stdc_leading_zeros_uc (unsigned char __x) diff --git a/sysdeps/arm/Makefile b/sysdeps/arm/Makefile index 9c4fd6b236..c7e92da053 100644 --- a/sysdeps/arm/Makefile +++ b/sysdeps/arm/Makefile @@ -31,6 +31,11 @@ $(objpfx)tst-armtlsdescextnow: $(objpfx)tst-armtlsdescextnowmod.so $(objpfx)tst-armtlsdescextlazy: $(objpfx)tst-armtlsdescextlazymod.so endif endif + +ifeq ($(enable-ubsan),yes) +# aeabi_unwind_cpp_pr1 is built as rtld module +CFLAGS-aeabi_unwind_cpp_pr1.c += -DDISABLE_USAN_INTERNAL_REDIR +endif endif ifeq ($(subdir),csu) diff --git a/sysdeps/generic/ldconfig.h b/sysdeps/generic/ldconfig.h index 7bc8788647..78e43d7038 100644 --- a/sysdeps/generic/ldconfig.h +++ b/sysdeps/generic/ldconfig.h @@ -84,7 +84,8 @@ extern int search_aux_cache (struct stat *stat_buf, int *flags, extern void add_to_aux_cache (struct stat *stat_buf, int flags, unsigned int isa_level, const char *soname); -extern void save_aux_cache (const char *aux_cache_name); +extern void save_aux_cache (const char *aux_cache_name) + __attribute__((nonnull (1))); /* Declared in readlib.c. */ extern int process_file (const char *real_file_name, const char *file_name, diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index fc4a3de767..527381222f 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -773,6 +774,8 @@ extern void _dl_debug_printf (const char *fmt, ...) extern void _dl_debug_printf_c (const char *fmt, ...) __attribute__ ((__format__ (__printf__, 1, 2))) attribute_hidden; +extern void _dl_debug_vprintf_c (const char *fmt, va_list ap) + __attribute__ ((__format__ (__printf__, 1, 0))) attribute_hidden; /* Write a message on the specified descriptor FD. The parameters are interpreted as for a `printf' call. */ diff --git a/sysdeps/generic/symbol-hacks.h b/sysdeps/generic/symbol-hacks.h index 1115e4c0a7..10a3a5388d 100644 --- a/sysdeps/generic/symbol-hacks.h +++ b/sysdeps/generic/symbol-hacks.h @@ -18,3 +18,39 @@ asm (".hidden __stack_chk_fail_local\n" "__stack_chk_fail = __stack_chk_fail_local"); # endif #endif + +#if !defined __ASSEMBLER__ && IS_IN(rtld) && defined ENABLE_UBSAN \ + && !defined DISABLE_USAN_INTERNAL_REDIR +/* These are autogenerated by the compiler, so no subject to either + hidden_attribute or hidden_proto alias definition. */ +asm ("__ubsan_handle_negate_overflow = " + "__GI___ubsan_handle_negate_overflow"); +asm ("__ubsan_handle_shift_out_of_bounds = " + "__GI___ubsan_handle_shift_out_of_bounds"); +asm ("__ubsan_handle_divrem_overflow = " + "__GI___ubsan_handle_divrem_overflow"); +asm ("__ubsan_handle_vla_bound_not_positive = " + "__GI___ubsan_handle_vla_bound_not_positive"); +asm ("__ubsan_handle_pointer_overflow = " + "__GI___ubsan_handle_pointer_overflow"); +asm ("__ubsan_handle_load_invalid_value =" + "__GI___ubsan_handle_load_invalid_value"); +asm ("__ubsan_handle_out_of_bounds = " + "__GI___ubsan_handle_out_of_bounds"); +asm ("__ubsan_handle_sub_overflow = " + "__GI___ubsan_handle_sub_overflow"); +asm ("__ubsan_handle_add_overflow = " + "__GI___ubsan_handle_add_overflow"); +asm ("__ubsan_handle_mul_overflow = " + "__GI___ubsan_handle_mul_overflow"); +asm ("__ubsan_handle_type_mismatch_v1 = " + "__GI___ubsan_handle_type_mismatch_v1"); +asm ("__ubsan_handle_nonnull_return_v1 = " + "__GI___ubsan_handle_nonnull_return_v1"); +asm ("__ubsan_handle_nonnull_arg = " + "__GI___ubsan_handle_nonnull_arg"); +asm ("__ubsan_handle_invalid_builtin = " + "__GI___ubsan_handle_invalid_builtin"); +asm ("__ubsan_handle_builtin_unreachable = " + "__GI___ubsan_handle_builtin_unreachable"); +#endif diff --git a/sysdeps/powerpc/powerpc64/multiarch/stpncpy-ppc64.c b/sysdeps/powerpc/powerpc64/multiarch/stpncpy-ppc64.c index e0a8747884..6dec085cb7 100644 --- a/sysdeps/powerpc/powerpc64/multiarch/stpncpy-ppc64.c +++ b/sysdeps/powerpc/powerpc64/multiarch/stpncpy-ppc64.c @@ -20,7 +20,8 @@ #ifdef SHARED #undef libc_hidden_def #define libc_hidden_def(name) \ - __hidden_ver1 (__stpncpy_ppc, __GI___stpncpy, __stpncpy_ppc); + __hidden_ver1 (__stpncpy_ppc, __GI___stpncpy, __stpncpy_ppc); \ + weak_alias (__stpncpy_ppc, __stpncpy) #endif #include