.gitlab-ci.yml export-ignore
.pylintrc export-ignore
.readthedocs.yaml export-ignore
-.tsan-suppress export-ignore
.uncrustify.cfg export-ignore
dangerfile.py export-ignore
/.github/** export-ignore
CFLAGS_COMMON: -fno-omit-frame-pointer -fno-optimize-sibling-calls
- UBASAN_CONFIGURE_FLAGS_COMMON: "-Db_sanitize=address,undefined -Didn=enabled -Djemalloc=disabled -Dtracing=disabled"
- TSAN_CONFIGURE_FLAGS_COMMON: "-Db_sanitize=thread -Doptimization=2 -Ddebug=true -Didn=enabled -Dlocktype=system -Djemalloc=disabled --pkg-config-path /opt/tsan/lib/pkgconfig"
-
- # Pass run-time flags to AddressSanitizer to get core dumps on error.
- ASAN_OPTIONS: abort_on_error=1:disable_coredump=0:unmap_shadow_on_exit=1:detect_odr_violation=0
- ASAN_SYMBOLIZER_PATH: "${LLVM_SYMBOLIZER}"
-
- TSAN_OPTIONS_COMMON: "disable_coredump=0 second_deadlock_stack=1 atexit_sleep_ms=1000 history_size=7 log_exe_name=true log_path=tsan"
- TSAN_SUPPRESSIONS: "suppressions=${CI_PROJECT_DIR}/.tsan-suppress"
- TSAN_OPTIONS_DEBIAN: "${TSAN_OPTIONS_COMMON} ${TSAN_SUPPRESSIONS} external_symbolizer_path=${LLVM_SYMBOLIZER}"
- TSAN_OPTIONS_FEDORA: "${TSAN_OPTIONS_COMMON} ${TSAN_SUPPRESSIONS} external_symbolizer_path=/usr/bin/llvm-symbolizer"
-
- UBSAN_OPTIONS: "halt_on_error=1:abort_on_error=1:disable_coredump=0"
+ TSAN_CONFIGURE_FLAGS_COMMON: "-Db_sanitize=thread -Doptimization=2 -Ddebug=true -Didn=enabled -Dlocktype=system -Djemalloc=disabled -Dnamed-lto=disabled --pkg-config-path /opt/tsan/lib/pkgconfig"
+ TSAN_SYMBOLIZER_PATH_DEBIAN: "${LLVM_SYMBOLIZER}"
+ TSAN_SYMBOLIZER_PATH_FEDORA: "/usr/bin/llvm-symbolizer"
WITHOUT_LIBEDIT: "-Dline=disabled"
WITH_LIBEDIT: "-Dline=enabled"
#- test -z "${CROSS_COMPILATION}" || grep -F -A 1 "checking whether we are cross compiling" config.log | grep -q "result.*yes"
- test -z "${CROSS_COMPILATION}" || file build/lib/dns/gen | grep -F -q "ELF 64-bit LSB"
#- test -z "${CROSS_COMPILATION}" || ( ! git ls-files -z --others --exclude lib/dns/gen | xargs -0 file | grep "ELF 64-bit LSB" )
+ - *find_python
+ # Check that embedded sanitizer flags are in sync with the `meson.build` file.
+ - $PYTHON ${CI_PROJECT_DIR}/ci/sanitizer_default_check.py build
- build/named -V
- *fips_feature_test
needs: []
<<: *build_job
system:gcc:asan:
- variables:
- LSAN_OPTIONS: "suppressions=$CI_PROJECT_DIR/suppr-lsan.txt"
<<: *fedora_43_amd64_image
<<: *system_test_job
needs:
<<: *build_job
system:clang:asan:
- variables:
- LSAN_OPTIONS: "suppressions=$CI_PROJECT_DIR/suppr-lsan.txt"
<<: *base_image
<<: *system_test_job
<<: *extra_system_tests_triggering_rules
system:gcc:tsan:
variables:
- TSAN_OPTIONS: "${TSAN_OPTIONS_FEDORA}"
<<: *tsan_fedora_43_amd64_image
<<: *system_test_tsan_job
<<: *extra_system_tests_triggering_rules
unit:gcc:tsan:
variables:
- TSAN_OPTIONS: "${TSAN_OPTIONS_FEDORA}"
+ TSAN_SYMBOLIZER_PATH: "${TSAN_SYMBOLIZER_PATH_FEDORA}"
<<: *tsan_fedora_43_amd64_image
<<: *unit_test_tsan_job
<<: *api_pipelines_schedules_tags_triggers_web_triggering_rules
CC: "${CLANG}"
CFLAGS: "${CFLAGS_COMMON}"
LDFLAGS: "-Wl,--disable-new-dtags"
- EXTRA_CONFIGURE: "${TSAN_CONFIGURE_FLAGS_COMMON} -Db_lundef=false -Dnamed-lto=disabled --native-file ci/clang-trixie.ini"
+ EXTRA_CONFIGURE: "${TSAN_CONFIGURE_FLAGS_COMMON} -Db_lundef=false --native-file ci/clang-trixie.ini"
<<: *build_job
system:clang:tsan:
variables:
- TSAN_OPTIONS: "${TSAN_OPTIONS_DEBIAN}"
+ TSAN_SYMBOLIZER_PATH: "${TSAN_SYMBOLIZER_PATH_DEBIAN}"
<<: *tsan_debian_trixie_amd64_image
<<: *system_test_tsan_job
needs:
unit:clang:tsan:
variables:
- TSAN_OPTIONS: "${TSAN_OPTIONS_DEBIAN}"
+ TSAN_SYMBOLIZER_PATH: "${TSAN_SYMBOLIZER_PATH_DEBIAN}"
<<: *tsan_debian_trixie_amd64_image
<<: *unit_test_tsan_job
needs:
CC: "${CLANG}"
CFLAGS: "${CFLAGS_COMMON}"
LDFLAGS: "-Wl,--disable-new-dtags"
- EXTRA_CONFIGURE: "${TSAN_CONFIGURE_FLAGS_COMMON} -Dnamed-lto=disabled -Db_lundef=false"
+ EXTRA_CONFIGURE: "${TSAN_CONFIGURE_FLAGS_COMMON} -Db_lundef=false"
MAX_DISAGREEMENTS_PERCENTAGE: "0.3"
- TSAN_OPTIONS: "${TSAN_OPTIONS_DEBIAN}"
+ TSAN_SYMBOLIZER_PATH: "${TSAN_SYMBOLIZER_PATH_DEBIAN}"
script:
- bash respdiff.sh -s named -q "${PWD}/100k_mixed.txt" -c 3 -w "${PWD}/rspworkdir" "${CI_PROJECT_DIR}" "/usr/local/respdiff-reference-bind/sbin/named"
- cd ../.. && ninja -C build clean >/dev/null 2>&1
+++ /dev/null
-# Uninstrumented libraries
-called_from_lib:libfstrm.so
-race:dummyrpz
-
-# FreeBSD false-positive, see GL#5267
-race:libexec/rtld-elf/rtld_malloc.c
-
-# FreeBSD false-positive, see GL#5266
-deadlock:add_trace_entry
--- /dev/null
+#!/usr/bin/env python
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+
+from pathlib import Path
+
+import argparse
+import json
+import subprocess
+import sys
+
+ASAN = False
+UBSAN = False
+TSAN = False
+
+args = argparse.ArgumentParser()
+args.add_argument("build")
+args = args.parse_args()
+
+build = Path(args.build)
+
+# https://mesonbuild.com/IDE-integration.html#build-options
+#
+# e.g. { "name": "b_sanitize", "value": ["address", "undefined"], ... }
+#
+with (build / "meson-info" / "intro-buildoptions.json").open() as f:
+ options = json.load(f)
+
+ for opt in options:
+ if opt["name"] == "b_sanitize":
+ ASAN = "address" in opt["value"]
+ UBSAN = "undefined" in opt["value"]
+ TSAN = "thread" in opt["value"]
+ break
+
+if not (ASAN or UBSAN or TSAN):
+ print("no sanitizer check necessary")
+ sys.exit(0)
+
+with (build / "meson-info" / "intro-targets.json").open() as f:
+ targets = json.load(f)
+
+ for target in targets:
+ if target["type"] == "executable" and Path(target["filename"][0]).exists():
+ nm = subprocess.run(
+ ["nm", target["filename"][0]],
+ stdin=None,
+ stdout=subprocess.PIPE,
+ timeout=1,
+ check=True,
+ shell=False,
+ )
+
+ if ASAN and b"__asan_default_options" not in nm.stdout:
+ print(f"Default ASAN options missing for executable '{target['name']}'")
+ sys.exit(1)
+
+ if UBSAN and b"__ubsan_default_options" not in nm.stdout:
+ print(
+ f"Default UBSAN options missing for executable '{target['name']}'"
+ )
+ sys.exit(1)
+
+ if TSAN and b"__tsan_default_options" not in nm.stdout:
+ print(f"Default TSAN options missing for executable '{target['name']}'")
+ sys.exit(1)
+
+print("all relevant sanitizer defaults are set")
'cfg_test',
files('cfg_test.c'),
install: false,
+ sources: default_sanitize_options,
dependencies: [
libisc_dep,
libisccfg_dep,
dns_header_gen = executable(
'gen',
files('gen.c'),
+ sources: default_sanitize_options,
install: false,
native: true,
)
add_project_arguments(sys_defines, language: 'c')
+### Sanitizer
+asan_options = 'abort_on_error=1:disable_coredump=0:unmap_shadow_on_exit=1:detect_odr_violation=0'
+tsan_options = 'disable_coredump=0:second_deadlock_stack=1:atexit_sleep_ms=1000:history_size=7:log_exe_name=true:log_path=tsan'
+ubsan_options = 'halt_on_error=1:abort_on_error=1:disable_coredump=0'
+
+# Refer to sanitize.c.in for the justification
+config_sanitize = configuration_data()
+
+config_sanitize.set10('BIND_ASAN_ENABLED', 'address' in sanitizer)
+config_sanitize.set10('BIND_LSAN_ENABLED', 'leak' in sanitizer)
+config_sanitize.set10('BIND_TSAN_ENABLED', 'thread' in sanitizer)
+config_sanitize.set10('BIND_UBSAN_ENABLED', 'undefined' in sanitizer)
+config_sanitize.set('BIND_ASAN_OPTIONS', asan_options)
+config_sanitize.set('BIND_TSAN_OPTIONS', tsan_options)
+config_sanitize.set('BIND_UBSAN_OPTIONS', ubsan_options)
+
### Environment
env = environment(
},
)
+# Meson defines these variables in unit tests when not set
+test_env = environment(
+ {
+ 'ASAN_OPTIONS': asan_options,
+ 'TSAN_OPTIONS': tsan_options,
+ 'UBSAN_OPTIONS': ubsan_options,
+ },
+)
+
### Configuration
config = configuration_data()
],
)
+default_sanitize_options = configure_file(
+ input: files('sanitize.c.in'),
+ output: 'sanitize.c',
+ configuration: config_sanitize,
+)
+
# Headers
dns_inc = include_directories('lib' / 'dns' / 'include')
isc_inc = include_directories('lib' / 'isc' / 'include')
export_dynamic: true,
implicit_include_directories: false,
install: true,
+ sources: default_sanitize_options,
dependencies: [
libisc_dep,
],
export_dynamic: true,
implicit_include_directories: true,
install: true,
- sources: bind_keys,
+ sources: [bind_keys, default_sanitize_options],
dependencies: [
libisc_dep,
libisccfg_dep,
export_dynamic: true,
implicit_include_directories: false,
install: true,
+ sources: default_sanitize_options,
dependencies: [
libdns_dep,
libisc_dep,
export_dynamic: true,
implicit_include_directories: false,
install: true,
+ sources: default_sanitize_options,
dependencies: [
libdns_dep,
libisc_dep,
export_dynamic: true,
implicit_include_directories: false,
install: true,
+ sources: default_sanitize_options,
dependencies: [
libdns_dep,
libisc_dep,
export_dynamic: true,
implicit_include_directories: false,
install: true,
+ sources: default_sanitize_options,
dependencies: [
libdns_dep,
libisc_dep,
export_dynamic: true,
implicit_include_directories: false,
install: true,
+ sources: default_sanitize_options,
dependencies: [
libdns_dep,
libisc_dep,
export_dynamic: true,
implicit_include_directories: false,
install: true,
+ sources: default_sanitize_options,
dependencies: [
libdns_dep,
libisc_dep,
export_dynamic: true,
implicit_include_directories: false,
install: true,
+ sources: default_sanitize_options,
dependencies: [
libdns_dep,
libisc_dep,
export_dynamic: true,
implicit_include_directories: false,
install: true,
+ sources: default_sanitize_options,
dependencies: [
libdns_dep,
libisc_dep,
export_dynamic: true,
implicit_include_directories: false,
install: true,
+ sources: default_sanitize_options,
dependencies: [
libdns_dep,
libisc_dep,
export_dynamic: true,
implicit_include_directories: false,
install: true,
+ sources: default_sanitize_options,
dependencies: [
libdns_dep,
libisc_dep,
export_dynamic: true,
implicit_include_directories: false,
install: true,
+ sources: default_sanitize_options,
dependencies: [
libdns_dep,
libisc_dep,
export_dynamic: true,
implicit_include_directories: true,
install: true,
+ sources: default_sanitize_options,
dependencies: [
libdns_dep,
libisc_dep,
export_dynamic: true,
implicit_include_directories: false,
install: true,
+ sources: default_sanitize_options,
dependencies: [
libdns_dep,
libisc_dep,
export_dynamic: true,
implicit_include_directories: false,
install: true,
+ sources: default_sanitize_options,
dependencies: [
libdns_dep,
libisc_dep,
implicit_include_directories: true,
include_directories: [bin_inc],
install: true,
- sources: bind_keys,
+ sources: [bind_keys, default_sanitize_options],
dependencies: [
libisc_dep,
libdns_dep,
export_dynamic: true,
implicit_include_directories: false,
install: true,
+ sources: default_sanitize_options,
dependencies: [
libisc_dep,
libdns_dep,
export_dynamic: true,
implicit_include_directories: false,
install: true,
+ sources: default_sanitize_options,
dependencies: [
libdns_dep,
libisc_dep,
export_dynamic: true,
implicit_include_directories: false,
install: true,
+ sources: default_sanitize_options,
dependencies: [
libdns_dep,
libisc_dep,
export_dynamic: true,
implicit_include_directories: false,
install: true,
+ sources: default_sanitize_options,
dependencies: [
libdns_dep,
libisc_dep,
export_dynamic: true,
implicit_include_directories: false,
install: true,
+ sources: default_sanitize_options,
dependencies: [
libdns_dep,
libisc_dep,
include_directories: [named_inc, bin_inc],
install: true,
install_dir: sbindir,
- sources: bind_keys,
+ sources: [bind_keys, default_sanitize_options],
dependencies: named_deps
+ [
openssl_dep,
export_dynamic: true,
implicit_include_directories: false,
install: true,
+ sources: default_sanitize_options,
dependencies: [
libdns_dep,
libisc_dep,
export_dynamic: true,
implicit_include_directories: false,
install: true,
+ sources: default_sanitize_options,
dependencies: [
libdns_dep,
libisc_dep,
export_dynamic: true,
implicit_include_directories: false,
install: true,
+ sources: default_sanitize_options,
dependencies: [
libdns_dep,
libisc_dep,
include_directories: confgen_inc_p,
install: true,
install_dir: sbindir,
+ sources: default_sanitize_options,
dependencies: [
libdns_dep,
libisc_dep,
implicit_include_directories: false,
install: true,
install_dir: sbindir,
+ sources: default_sanitize_options,
dependencies: [
libdns_dep,
libisc_dep,
include_directories: confgen_inc_p,
install: true,
install_dir: sbindir,
+ sources: default_sanitize_options,
dependencies: [
libdns_dep,
libisc_dep,
install: false,
c_args: ['-Wno-vla'],
link_args: fuzz_link_args,
+ sources: default_sanitize_options,
dependencies: [
libdns_dep,
libisc_dep,
export_dynamic: true,
implicit_include_directories: false,
install: false,
+ sources: default_sanitize_options,
dependencies: [
libdns_dep,
libisc_dep,
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * We do not use `__SANITIZE_XXXX__` or `__has_feature` for the following
+ * reasons:
+ *
+ * - `__SANITIZE_UNDEFINED__` doesn't exist at all (currently GCC 15 & clang 21)
+ * - Other `__SANITIZE_XXXX__` macros don't exist in clang <23 [1]
+ * - `__has_feature` doesn't exist in GCC <14 [2]
+ *
+ * [1]: https://github.com/llvm/llvm-project/pull/153888
+ * [2]: https://gcc.gnu.org/gcc-14/changes.html#c-family
+ */
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmissing-prototypes"
+
+#if @BIND_ASAN_ENABLED@
+__attribute__((no_sanitize("address", "leak", "thread", "undefined")))
+const char *
+__asan_default_options(void) {
+ return "@BIND_ASAN_OPTIONS@";
+}
+#endif
+
+/* ASAN will usually also enable LSAN */
+#if @BIND_ASAN_ENABLED@ || @BIND_LSAN_ENABLED@
+__attribute__((no_sanitize("address", "leak", "thread", "undefined")))
+const char *
+__lsan_default_suppressions(void) {
+ return
+ /* These are known leaks in libp11 */
+ "leak:BN_MONT_CTX_new\n"
+ "leak:C_LoadModule\n"
+ "leak:ctx_new\n"
+ "leak:ctx_try_load_object\n"
+ "leak:dlfcn_name_converter\n"
+ "leak:EC_GROUP_set_seed\n"
+ "leak:CRYPTO_strdup\n"
+ "leak:CRYPTO_zalloc\n"
+ "leak:pkcs11_check_token\n"
+ "leak:pkcs11_CTX_new\n"
+ "leak:pkcs11_enumerate_slots\n"
+ "leak:pkcs11_getattr_alloc\n"
+ "leak:pkcs11_init_key\n"
+ "leak:pkcs11_strdup\n"
+ "leak:xmlGetGlobalState\n"
+ "leak:xmlNewGlobalState\n"
+ "leak:__xmlDefaultBufferSize\n";
+}
+#endif
+
+#if @BIND_TSAN_ENABLED@
+__attribute__((no_sanitize("address", "leak", "thread", "undefined")))
+const char *
+__tsan_default_options(void) {
+ return "@BIND_TSAN_OPTIONS@";
+}
+
+__attribute__((no_sanitize("address", "leak", "thread", "undefined")))
+const char *
+__tsan_default_suppressions(void) {
+ return
+ /* Uninstrumented libraries */
+ "called_from_lib:libfstrm.so\n"
+ "race:dummyrpz\n"
+ /* FreeBSD false-positive, see GL#5267 */
+ "race:libexec/rtld-elf/rtld_malloc.c\n"
+ /* FreeBSD false-positive, see GL#5266 */
+ "deadlock:add_trace_entry";
+}
+#endif
+
+#if @BIND_UBSAN_ENABLED@
+__attribute__((no_sanitize("address", "leak", "thread", "undefined")))
+const char *
+__ubsan_default_options(void) {
+ return "@BIND_UBSAN_OPTIONS@";
+}
+#endif
+
+#pragma GCC diagnostic pop
+++ /dev/null
-# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
-#
-# SPDX-License-Identifier: MPL-2.0
-#
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, you can obtain one at https://mozilla.org/MPL/2.0/.
-#
-# See the COPYRIGHT file distributed with this work for additional
-# information regarding copyright ownership.
-
-# These are known leaks in libp11.
-leak:BN_MONT_CTX_new
-leak:C_LoadModule
-leak:ctx_new
-leak:ctx_try_load_object
-leak:dlfcn_name_converter
-leak:EC_GROUP_set_seed
-leak:CRYPTO_strdup
-leak:CRYPTO_zalloc
-leak:pkcs11_check_token
-leak:pkcs11_CTX_new
-leak:pkcs11_enumerate_slots
-leak:pkcs11_getattr_alloc
-leak:pkcs11_init_key
-leak:pkcs11_strdup
-leak:xmlGetGlobalState
-leak:xmlNewGlobalState
-leak:__xmlDefaultBufferSize
files(fs.replace_suffix(bench, '.c')),
export_dynamic: true,
install: false,
+ sources: default_sanitize_options,
dependencies: [
libisc_dep,
libdns_dep,
export_dynamic: true,
include_directories: '..' / '..' / 'fuzz',
install: false,
+ sources: default_sanitize_options,
dependencies: [
libisc_dep,
libdns_dep,
meson.project_source_root() / 'bin' / 'tests' / 'system' / 'geoip2' / 'data',
),
],
+ sources: default_sanitize_options,
dependencies: [
libisc_dep,
libdns_dep,
unit,
test_bin,
depends: master_data,
+ env: test_env,
suite: ['dns', 'cmocka'],
timeout: 300,
workdir: meson.current_source_dir(),
build_by_default: false,
export_dynamic: true,
install: false,
+ sources: default_sanitize_options,
dependencies: [
libisc_dep,
libtest_dep,
test(
unit,
test_bin,
+ env: test_env,
suite: suites,
timeout: timeout,
workdir: meson.current_source_dir(),
- env: env,
)
endforeach
build_by_default: false,
export_dynamic: true,
install: false,
+ sources: default_sanitize_options,
dependencies: [
libisc_dep,
libisccfg_dep,
test(
unit,
test_bin,
+ env: test_env,
suite: ['isccfg', 'cmocka'],
timeout: 300,
workdir: meson.current_source_dir(),
build_by_default: false,
export_dynamic: true,
install: false,
+ sources: default_sanitize_options,
dependencies: [
libisc_dep,
libdns_dep,
test(
unit,
test_bin,
+ env: test_env,
suite: ['ns', 'cmocka'],
timeout: 300,
workdir: meson.current_source_dir(),