Add --enable-asan and --enable-ubsan switches

`configure` now accepts `--enable-asan` and `--enable-ubsan` switches
which results in passing `-fsanitize=address`
and `-fsanitize=undefined`, respectively, to the compiler. Those
flags are enabled in GitHub workflows for ZTS and zloop. Errors
reported by both instrumentations are corrected, except for:

- Memory leak reporting is (temporarily) suppressed. The cost of
  fixing them is relatively high compared to the gains.

- Checksum computing functions in `module/zcommon/zfs_fletcher*`
  have UBSan errors suppressed. It is completely impractical
  to enforce 64-byte payload alignment there due to performance
  impact.

- There's no ASan heap poisoning in `module/zstd/lib/zstd.c`. A custom
  memory allocator is used there rendering that measure
  unfeasible.

- Memory leaks detection has to be suppressed for `cmd/zvol_id`.
  `zvol_id` is run by udev with the help of `ptrace(2)`. Tracing is
  incompatible with memory leaks detection.

Reviewed-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
Reviewed-by: George Melikov <mail@gmelikov.ru>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: szubersk <szuberskidamian@gmail.com>
Closes #12928
This commit is contained in:
Damian Szuberski 2022-02-03 23:35:38 +01:00 committed by GitHub
parent aa9905d89b
commit 63652e1546
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
50 changed files with 253 additions and 62 deletions

View File

@ -32,7 +32,7 @@ jobs:
sh autogen.sh
- name: Configure
run: |
./configure --enable-debug --enable-debuginfo
./configure --enable-debug --enable-debuginfo --enable-asan --enable-ubsan
- name: Make
run: |
make --no-print-directory -s pkg-utils pkg-kmod

View File

@ -28,7 +28,7 @@ jobs:
sh autogen.sh
- name: Configure
run: |
./configure --enable-debug --enable-debuginfo
./configure --enable-debug --enable-debuginfo --enable-asan --enable-ubsan
- name: Make
run: |
make --no-print-directory -s pkg-utils pkg-kmod

View File

@ -28,7 +28,7 @@ jobs:
sh autogen.sh
- name: Configure
run: |
./configure --enable-debug --enable-debuginfo
./configure --enable-debug --enable-debuginfo --enable-asan --enable-ubsan
- name: Make
run: |
make --no-print-directory -s pkg-utils pkg-kmod

View File

@ -8654,7 +8654,7 @@ main(int argc, char **argv)
dump_opt[c] += verbose;
}
libspl_assert_ok = (dump_opt['A'] == 1) || (dump_opt['A'] > 2);
libspl_set_assert_ok((dump_opt['A'] == 1) || (dump_opt['A'] > 2));
zfs_recover = (dump_opt['A'] > 1);
argc -= optind;

View File

@ -575,8 +575,9 @@ usage(boolean_t requested)
(void) fprintf(fp, gettext("\nSizes are specified in bytes "
"with standard units such as K, M, G, etc.\n"));
(void) fprintf(fp, gettext("\nUser-defined properties can "
"be specified by using a name containing a colon (:).\n"));
(void) fprintf(fp, "%s", gettext("\nUser-defined properties "
"can be specified by using a name containing a colon "
"(:).\n"));
(void) fprintf(fp, gettext("\nThe {user|group|project}"
"[obj]{used|quota}@ properties must be appended with\n"
"a user|group|project specifier of one of these forms:\n"

View File

@ -1760,17 +1760,19 @@ zpool_do_create(int argc, char **argv)
"feature@%s", feat->fi_uname);
if (!nvlist_lookup_string(props, propname, &propval)) {
if (strcmp(propval, ZFS_FEATURE_DISABLED) == 0)
if (strcmp(propval,
ZFS_FEATURE_DISABLED) == 0) {
(void) nvlist_remove_all(props,
propname);
if (strcmp(propval,
} else if (strcmp(propval,
ZFS_FEATURE_ENABLED) == 0 &&
!requested_features[i])
!requested_features[i]) {
(void) fprintf(stderr, gettext(
"Warning: feature \"%s\" enabled "
"but is not in specified "
"'compatibility' feature set.\n"),
feat->fi_uname);
}
} else if (
enable_pool_features &&
feat->fi_zfs_mod_supported &&
@ -9210,7 +9212,7 @@ zpool_do_upgrade(int argc, char **argv)
}
}
(void) printf(gettext("This system supports ZFS pool feature "
(void) printf("%s", gettext("This system supports ZFS pool feature "
"flags.\n\n"));
if (showversions) {
int i;

View File

@ -631,6 +631,8 @@ fatal(int do_perror, char *message, ...)
(void) fflush(stdout);
buf = umem_alloc(FATAL_MSG_SZ, UMEM_NOFAIL);
if (buf == NULL)
goto out;
va_start(args, message);
(void) sprintf(buf, "ztest: ");
@ -644,6 +646,7 @@ fatal(int do_perror, char *message, ...)
(void) fprintf(stderr, "%s\n", buf);
fatal_msg = buf; /* to ease debugging */
out:
if (ztest_dump_core)
abort();
else

View File

@ -35,6 +35,21 @@
#include <sys/zfs_znode.h>
#include <sys/fs/zfs.h>
#if defined(ZFS_ASAN_ENABLED)
/*
* zvol_id is invoked by udev with the help of ptrace()
* making sanitized binary with leak detection croak
* because of tracing mechanisms collision
*/
extern const char *__asan_default_options(void);
const char *__asan_default_options(void) {
return ("abort_on_error=true:halt_on_error=true:"
"allocator_may_return_null=true:disable_coredump=false:"
"detect_stack_use_after_return=true:detect_leaks=false");
}
#endif
static int
ioctl_get_msg(char *var, int fd)
{

View File

@ -29,6 +29,7 @@ AM_CFLAGS += $(NO_OMIT_FRAME_POINTER)
AM_CFLAGS += $(IMPLICIT_FALLTHROUGH)
AM_CFLAGS += $(DEBUG_CFLAGS)
AM_CFLAGS += $(ASAN_CFLAGS)
AM_CFLAGS += $(UBSAN_CFLAGS)
AM_CFLAGS += $(CODE_COVERAGE_CFLAGS) $(NO_FORMAT_ZERO_LENGTH)
if BUILD_FREEBSD
AM_CFLAGS += -fPIC -Werror -Wno-unknown-pragmas -Wno-enum-conversion
@ -58,8 +59,17 @@ AM_CPPFLAGS += -D"__xpg_basename(...)=__xpg_basename(__VA_ARGS__) __attribute__(
AM_CPPFLAGS += -D"basename(...)=basename(__VA_ARGS__) __attribute__((deprecated(\"basename(3) is underspecified. Use zfs_basename() instead!\")))"
AM_CPPFLAGS += -D"dirname(...)=dirname(__VA_ARGS__) __attribute__((deprecated(\"dirname(3) is underspecified. Use zfs_dirnamelen() instead!\")))"
if ASAN_ENABLED
AM_CPPFLAGS += -DZFS_ASAN_ENABLED
endif
if UBSAN_ENABLED
AM_CPPFLAGS += -DZFS_UBSAN_ENABLED
endif
AM_LDFLAGS = $(DEBUG_LDFLAGS)
AM_LDFLAGS += $(ASAN_LDFLAGS)
AM_LDFLAGS += $(UBSAN_LDFLAGS)
if BUILD_FREEBSD
AM_LDFLAGS += -fstack-protector-strong -shared

View File

@ -17,7 +17,9 @@ subst_sed_cmd = \
-e 's|@DEFAULT_INIT_NFS_SERVER[@]|$(DEFAULT_INIT_NFS_SERVER)|g' \
-e 's|@DEFAULT_INIT_SHELL[@]|$(DEFAULT_INIT_SHELL)|g' \
-e 's|@LIBFETCH_DYNAMIC[@]|$(LIBFETCH_DYNAMIC)|g' \
-e 's|@LIBFETCH_SONAME[@]|$(LIBFETCH_SONAME)|g'
-e 's|@LIBFETCH_SONAME[@]|$(LIBFETCH_SONAME)|g' \
-e 's|@ASAN_ENABLED[@]|$(ASAN_ENABLED)|g' \
-e 's|@UBSAN_ENABLED[@]|$(UBSAN_ENABLED)|g'
SUBSTFILES =
CLEANFILES = $(SUBSTFILES)

View File

@ -45,6 +45,53 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_CC_ASAN], [
AC_SUBST([ASAN_ZFS])
])
dnl #
dnl # Enabled -fsanitize=undefined if supported by gcc.
dnl #
dnl # LDFLAGS needs -fsanitize=undefined at all times so libraries compiled with
dnl # it will be linked successfully. CFLAGS will vary by binary being built.
dnl #
dnl # The UBSAN_OPTIONS environment variable can be used to further control
dnl # the behavior of binaries and libraries build with -fsanitize=undefined.
dnl #
AC_DEFUN([ZFS_AC_CONFIG_ALWAYS_CC_UBSAN], [
AC_MSG_CHECKING([whether to build with -fsanitize=undefined support])
AC_ARG_ENABLE([ubsan],
[AS_HELP_STRING([--enable-ubsan],
[Enable -fsanitize=undefined support @<:@default=no@:>@])],
[],
[enable_ubsan=no])
AM_CONDITIONAL([UBSAN_ENABLED], [test x$enable_ubsan = xyes])
AC_SUBST([UBSAN_ENABLED], [$enable_ubsan])
AC_MSG_RESULT($enable_ubsan)
AS_IF([ test "$enable_ubsan" = "yes" ], [
AC_MSG_CHECKING([whether $CC supports -fsanitize=undefined])
saved_cflags="$CFLAGS"
CFLAGS="$CFLAGS -Werror -fsanitize=undefined"
AC_LINK_IFELSE([
AC_LANG_SOURCE([[ int main() { return 0; } ]])
], [
UBSAN_CFLAGS="-fsanitize=undefined"
UBSAN_LDFLAGS="-fsanitize=undefined"
UBSAN_ZFS="_with_ubsan"
AC_MSG_RESULT([yes])
], [
AC_MSG_ERROR([$CC does not support -fsanitize=undefined])
])
CFLAGS="$saved_cflags"
], [
UBSAN_CFLAGS=""
UBSAN_LDFLAGS=""
UBSAN_ZFS="_without_ubsan"
])
AC_SUBST([UBSAN_CFLAGS])
AC_SUBST([UBSAN_LDFLAGS])
AC_SUBST([UBSAN_ZFS])
])
dnl #
dnl # Check if gcc supports -Wframe-larger-than=<size> option.
dnl #

View File

@ -218,6 +218,7 @@ AC_DEFUN([ZFS_AC_CONFIG_ALWAYS], [
ZFS_AC_CONFIG_ALWAYS_CC_NO_OMIT_FRAME_POINTER
ZFS_AC_CONFIG_ALWAYS_CC_NO_IPA_SRA
ZFS_AC_CONFIG_ALWAYS_CC_ASAN
ZFS_AC_CONFIG_ALWAYS_CC_UBSAN
ZFS_AC_CONFIG_ALWAYS_TOOLCHAIN_SIMD
ZFS_AC_CONFIG_ALWAYS_SYSTEM
ZFS_AC_CONFIG_ALWAYS_ARCH
@ -323,6 +324,7 @@ AC_DEFUN([ZFS_AC_RPM], [
RPM_DEFINE_COMMON=${RPM_DEFINE_COMMON}' --define "$(DEBUG_KMEM_ZFS) 1"'
RPM_DEFINE_COMMON=${RPM_DEFINE_COMMON}' --define "$(DEBUG_KMEM_TRACKING_ZFS) 1"'
RPM_DEFINE_COMMON=${RPM_DEFINE_COMMON}' --define "$(ASAN_ZFS) 1"'
RPM_DEFINE_COMMON=${RPM_DEFINE_COMMON}' --define "$(UBSAN_ZFS) 1"'
RPM_DEFINE_UTIL=' --define "_initconfdir $(initconfdir)"'

View File

@ -160,4 +160,20 @@ _ZFS_FLETCHER_H const fletcher_4_ops_t fletcher_4_aarch64_neon_ops;
}
#endif
#if defined(ZFS_UBSAN_ENABLED)
#if defined(__has_attribute)
#if __has_attribute(no_sanitize_undefined)
#define ZFS_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize_undefined))
#elif __has_attribute(no_sanitize)
#define ZFS_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize("undefined")))
#else
#error "Compiler has to support attribute "
"`no_sanitize_undefined` or `no_sanitize(\"undefined\")`"
"when compiling with UBSan enabled"
#endif /* __has_attribute(no_sanitize_undefined) */
#endif /* defined(__has_attribute) */
#else
#define ZFS_NO_SANITIZE_UNDEFINED
#endif /* defined(ZFS_UBSAN_ENABLED) */
#endif /* _ZFS_FLETCHER_H */

View File

@ -78,6 +78,7 @@
<elf-symbol name='fnvpair_value_uint64' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='fnvpair_value_uint8' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libspl_assertf' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libspl_set_assert_ok' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='nv_alloc_fini' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='nv_alloc_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='nv_alloc_reset' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@ -230,7 +231,6 @@
<elf-symbol name='nvpair_value_uint8_array' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
</elf-function-symbols>
<elf-variable-symbols>
<elf-symbol name='libspl_assert_ok' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='nv_alloc_nosleep' size='8' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='nv_fixed_ops' size='8' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
</elf-variable-symbols>
@ -2793,7 +2793,10 @@
</function-type>
</abi-instr>
<abi-instr address-size='64' path='assert.c' language='LANG_C99'>
<var-decl name='libspl_assert_ok' type-id='95e97e5e' mangled-name='libspl_assert_ok' visibility='default' elf-symbol-id='libspl_assert_ok'/>
<function-decl name='libspl_set_assert_ok' mangled-name='libspl_set_assert_ok' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_set_assert_ok'>
<parameter type-id='f58c8277' name='val'/>
<return type-id='48b5725f'/>
</function-decl>
<function-decl name='libspl_assertf' mangled-name='libspl_assertf' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_assertf'>
<parameter type-id='80f4b756' name='file'/>
<parameter type-id='80f4b756' name='func'/>

View File

@ -25,7 +25,13 @@
#include <assert.h>
int libspl_assert_ok = 0;
static boolean_t libspl_assert_ok = B_FALSE;
void
libspl_set_assert_ok(boolean_t val)
{
libspl_assert_ok = val;
}
/* printf version of libspl_assert */
void

View File

@ -32,9 +32,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <sys/types.h>
/* Set to non-zero to avoid abort()ing on an assertion failure */
extern int libspl_assert_ok;
extern void libspl_set_assert_ok(boolean_t val);
/* printf version of libspl_assert */
extern void libspl_assertf(const char *file, const char *func, int line,

View File

@ -152,6 +152,7 @@
<elf-symbol name='getmntany' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='getzoneid' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libspl_assertf' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libspl_set_assert_ok' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='list_create' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='list_destroy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='list_head' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@ -255,7 +256,6 @@
<elf-symbol name='uu_zalloc' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
</elf-function-symbols>
<elf-variable-symbols>
<elf-symbol name='libspl_assert_ok' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='uu_exit_fatal_value' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='uu_exit_ok_value' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='uu_exit_usage_value' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@ -365,7 +365,10 @@
</function-type>
</abi-instr>
<abi-instr address-size='64' path='assert.c' language='LANG_C99'>
<var-decl name='libspl_assert_ok' type-id='95e97e5e' mangled-name='libspl_assert_ok' visibility='default' elf-symbol-id='libspl_assert_ok'/>
<function-decl name='libspl_set_assert_ok' mangled-name='libspl_set_assert_ok' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_set_assert_ok'>
<parameter type-id='f58c8277' name='val'/>
<return type-id='48b5725f'/>
</function-decl>
<function-decl name='libspl_assertf' mangled-name='libspl_assertf' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_assertf'>
<parameter type-id='80f4b756' name='file'/>
<parameter type-id='80f4b756' name='func'/>

View File

@ -88,6 +88,7 @@ uu_warn_internal(int err, const char *format, va_list alist)
if (pname != NULL)
(void) fprintf(stderr, "%s: ", pname);
if (format != NULL)
(void) vfprintf(stderr, format, alist);
if (strrchr(format, '\n') == NULL)

View File

@ -191,6 +191,7 @@
<elf-symbol name='is_mounted' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='is_mpath_whole_disk' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libspl_assertf' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libspl_set_assert_ok' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libzfs_add_handle' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libzfs_envvar_is_set' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libzfs_errno' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@ -593,7 +594,6 @@
<elf-symbol name='fletcher_4_ssse3_ops' size='64' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='fletcher_4_superscalar4_ops' size='64' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='fletcher_4_superscalar_ops' size='64' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libspl_assert_ok' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libzfs_config_ops' size='16' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='spa_feature_table' size='1904' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='zfeature_checks_disable' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@ -906,7 +906,10 @@
<var-decl name='smb_shares' type-id='a3e5c654' visibility='default'/>
</abi-instr>
<abi-instr address-size='64' path='assert.c' language='LANG_C99'>
<var-decl name='libspl_assert_ok' type-id='95e97e5e' mangled-name='libspl_assert_ok' visibility='default' elf-symbol-id='libspl_assert_ok'/>
<function-decl name='libspl_set_assert_ok' mangled-name='libspl_set_assert_ok' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_set_assert_ok'>
<parameter type-id='f58c8277' name='val'/>
<return type-id='48b5725f'/>
</function-decl>
<function-decl name='libspl_assertf' mangled-name='libspl_assertf' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_assertf'>
<parameter type-id='80f4b756' name='file'/>
<parameter type-id='80f4b756' name='func'/>

View File

@ -1611,6 +1611,7 @@ zpool_disable_datasets(zpool_handle_t *zhp, boolean_t force)
* At this point, we have the entire list of filesystems, so sort it by
* mountpoint.
*/
if (used != 0)
qsort(sets, used, sizeof (struct sets_s), mountpoint_compare);
/*

View File

@ -2899,22 +2899,24 @@ recv_destroy(libzfs_handle_t *hdl, const char *name, int baselen,
zhp = zfs_open(hdl, name, ZFS_TYPE_DATASET);
if (zhp == NULL)
return (-1);
clp = changelist_gather(zhp, ZFS_PROP_NAME, 0,
flags->force ? MS_FORCE : 0);
if (zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT &&
zfs_type_t type = zfs_get_type(zhp);
if (type == ZFS_TYPE_SNAPSHOT &&
zfs_spa_version(zhp, &spa_version) == 0 &&
spa_version >= SPA_VERSION_USERREFS)
defer = B_TRUE;
clp = changelist_gather(zhp, ZFS_PROP_NAME, 0,
flags->force ? MS_FORCE : 0);
zfs_close(zhp);
if (clp == NULL)
return (-1);
err = changelist_prefix(clp);
if (err)
return (err);
if (flags->verbose)
(void) printf("attempting destroy %s\n", name);
if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) {
if (type == ZFS_TYPE_SNAPSHOT) {
nvlist_t *nv = fnvlist_alloc();
fnvlist_add_boolean(nv, name);
err = lzc_destroy_snaps(nv, defer, NULL);
@ -4075,8 +4077,8 @@ zfs_setup_cmdline_props(libzfs_handle_t *hdl, zfs_type_t type,
* properties: if we're asked to exclude this kind of
* values we remove them from "recvprops" input nvlist.
*/
if (!zfs_prop_inheritable(prop) &&
!zfs_prop_user(name) && /* can be inherited too */
if (!zfs_prop_user(name) && /* can be inherited too */
!zfs_prop_inheritable(prop) &&
nvlist_exists(recvprops, newname))
fnvlist_remove(recvprops, newname);
else

View File

@ -135,6 +135,7 @@
<elf-symbol name='getmntany' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='getzoneid' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libspl_assertf' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libspl_set_assert_ok' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libzfs_core_fini' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libzfs_core_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='list_create' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@ -215,11 +216,13 @@
<elf-symbol name='strlcpy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
</elf-function-symbols>
<elf-variable-symbols>
<elf-symbol name='libspl_assert_ok' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
</elf-variable-symbols>
<abi-instr address-size='64' path='assert.c' language='LANG_C99'>
<function-decl name='libspl_set_assert_ok' mangled-name='libspl_set_assert_ok' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_set_assert_ok'>
<parameter type-id='f58c8277' name='val'/>
<return type-id='48b5725f'/>
</function-decl>
<type-decl name='variadic parameter type' id='2c1145c5'/>
<var-decl name='libspl_assert_ok' type-id='95e97e5e' mangled-name='libspl_assert_ok' visibility='default' elf-symbol-id='libspl_assert_ok'/>
<function-decl name='libspl_assertf' mangled-name='libspl_assertf' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_assertf'>
<parameter type-id='80f4b756' name='file'/>
<parameter type-id='80f4b756' name='func'/>

View File

@ -348,8 +348,14 @@ gcm_mode_decrypt_contiguous_blocks(gcm_ctx_t *ctx, char *data, size_t length,
ctx->gcm_pt_buf = NULL;
return (CRYPTO_HOST_MEMORY);
}
if (ctx->gcm_pt_buf != NULL) {
bcopy(ctx->gcm_pt_buf, new, ctx->gcm_pt_buf_len);
vmem_free(ctx->gcm_pt_buf, ctx->gcm_pt_buf_len);
} else {
ASSERT0(ctx->gcm_pt_buf_len);
}
ctx->gcm_pt_buf = new;
ctx->gcm_pt_buf_len = new_len;
bcopy(data, &ctx->gcm_pt_buf[ctx->gcm_processed_data_len],
@ -554,8 +560,15 @@ gcm_init(gcm_ctx_t *ctx, unsigned char *iv, size_t iv_len,
* There's not a block full of data, pad rest of
* buffer with zero
*/
if (auth_data != NULL) {
bzero(authp, block_size);
bcopy(&(auth_data[processed]), authp, remainder);
bcopy(&(auth_data[processed]),
authp, remainder);
} else {
ASSERT0(remainder);
}
datap = (uint8_t *)authp;
remainder = 0;
} else {

View File

@ -710,8 +710,13 @@ sha2_mac_init_ctx(sha2_hmac_ctx_t *ctx, void *keyval, uint_t length_in_bytes)
(void) bzero(ipad, block_size);
(void) bzero(opad, block_size);
if (keyval != NULL) {
(void) bcopy(keyval, ipad, length_in_bytes);
(void) bcopy(keyval, opad, length_in_bytes);
} else {
ASSERT0(length_in_bytes);
}
/* XOR key with ipad (0x36) and opad (0x5c) */
for (i = 0; i < blocks_per_int64; i ++) {

View File

@ -300,18 +300,21 @@ fletcher_2_byteswap(const void *buf, uint64_t size,
(void) fletcher_2_incremental_byteswap((void *) buf, size, zcp);
}
ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_scalar_init(fletcher_4_ctx_t *ctx)
{
ZIO_SET_CHECKSUM(&ctx->scalar, 0, 0, 0, 0);
}
ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_scalar_fini(fletcher_4_ctx_t *ctx, zio_cksum_t *zcp)
{
memcpy(zcp, &ctx->scalar, sizeof (zio_cksum_t));
}
ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_scalar_native(fletcher_4_ctx_t *ctx, const void *buf,
uint64_t size)
@ -335,6 +338,7 @@ fletcher_4_scalar_native(fletcher_4_ctx_t *ctx, const void *buf,
ZIO_SET_CHECKSUM(&ctx->scalar, a, b, c, d);
}
ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_scalar_byteswap(fletcher_4_ctx_t *ctx, const void *buf,
uint64_t size)

View File

@ -48,12 +48,14 @@
#include <sys/strings.h>
#include <zfs_fletcher.h>
ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_aarch64_neon_init(fletcher_4_ctx_t *ctx)
{
bzero(ctx->aarch64_neon, 4 * sizeof (zfs_fletcher_aarch64_neon_t));
}
ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_aarch64_neon_fini(fletcher_4_ctx_t *ctx, zio_cksum_t *zcp)
{

View File

@ -35,12 +35,14 @@
#define __asm __asm__ __volatile__
#endif
ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_avx512f_init(fletcher_4_ctx_t *ctx)
{
bzero(ctx->avx512, 4 * sizeof (zfs_fletcher_avx512_t));
}
ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_avx512f_fini(fletcher_4_ctx_t *ctx, zio_cksum_t *zcp)
{

View File

@ -47,12 +47,14 @@
#include <sys/strings.h>
#include <zfs_fletcher.h>
ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_avx2_init(fletcher_4_ctx_t *ctx)
{
bzero(ctx->avx, 4 * sizeof (zfs_fletcher_avx_t));
}
ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_avx2_fini(fletcher_4_ctx_t *ctx, zio_cksum_t *zcp)
{

View File

@ -49,12 +49,14 @@
#include <sys/strings.h>
#include <zfs_fletcher.h>
ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_sse2_init(fletcher_4_ctx_t *ctx)
{
bzero(ctx->sse, 4 * sizeof (zfs_fletcher_sse_t));
}
ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_sse2_fini(fletcher_4_ctx_t *ctx, zio_cksum_t *zcp)
{

View File

@ -47,12 +47,14 @@
#include <sys/strings.h>
#include <zfs_fletcher.h>
ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_superscalar_init(fletcher_4_ctx_t *ctx)
{
bzero(ctx->superscalar, 4 * sizeof (zfs_fletcher_superscalar_t));
}
ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_superscalar_fini(fletcher_4_ctx_t *ctx, zio_cksum_t *zcp)
{
@ -68,6 +70,7 @@ fletcher_4_superscalar_fini(fletcher_4_ctx_t *ctx, zio_cksum_t *zcp)
ZIO_SET_CHECKSUM(zcp, A, B, C, D);
}
ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_superscalar_native(fletcher_4_ctx_t *ctx,
const void *buf, uint64_t size)
@ -107,6 +110,7 @@ fletcher_4_superscalar_native(fletcher_4_ctx_t *ctx,
ctx->superscalar[3].v[1] = d2;
}
ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_superscalar_byteswap(fletcher_4_ctx_t *ctx,
const void *buf, uint64_t size)

View File

@ -47,12 +47,14 @@
#include <sys/strings.h>
#include <zfs_fletcher.h>
ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_superscalar4_init(fletcher_4_ctx_t *ctx)
{
bzero(ctx->superscalar, 4 * sizeof (zfs_fletcher_superscalar_t));
}
ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_superscalar4_fini(fletcher_4_ctx_t *ctx, zio_cksum_t *zcp)
{
@ -82,6 +84,7 @@ fletcher_4_superscalar4_fini(fletcher_4_ctx_t *ctx, zio_cksum_t *zcp)
ZIO_SET_CHECKSUM(zcp, A, B, C, D);
}
ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_superscalar4_native(fletcher_4_ctx_t *ctx,
const void *buf, uint64_t size)
@ -147,6 +150,7 @@ fletcher_4_superscalar4_native(fletcher_4_ctx_t *ctx,
ctx->superscalar[3].v[3] = d4;
}
ZFS_NO_SANITIZE_UNDEFINED
static void
fletcher_4_superscalar4_byteswap(fletcher_4_ctx_t *ctx,
const void *buf, uint64_t size)

View File

@ -536,7 +536,6 @@ zfs_btree_insert_into_parent(zfs_btree_t *tree, zfs_btree_hdr_t *old_node,
ASSERT3P(old_node->bth_parent, ==, new_node->bth_parent);
uint64_t size = tree->bt_elem_size;
zfs_btree_core_t *parent = old_node->bth_parent;
zfs_btree_hdr_t *par_hdr = &parent->btc_hdr;
/*
* If this is the root node we were splitting, we create a new root
@ -568,6 +567,7 @@ zfs_btree_insert_into_parent(zfs_btree_t *tree, zfs_btree_hdr_t *old_node,
* Since we have the new separator, binary search for where to put
* new_node.
*/
zfs_btree_hdr_t *par_hdr = &parent->btc_hdr;
zfs_btree_index_t idx;
ASSERT(par_hdr->bth_core);
VERIFY3P(zfs_btree_find_in_buf(tree, parent->btc_elems,
@ -1898,7 +1898,8 @@ static uint64_t
zfs_btree_verify_counts_helper(zfs_btree_t *tree, zfs_btree_hdr_t *hdr)
{
if (!hdr->bth_core) {
if (tree->bt_root != hdr && hdr != &tree->bt_bulk->btl_hdr) {
if (tree->bt_root != hdr && tree->bt_bulk &&
hdr != &tree->bt_bulk->btl_hdr) {
uint64_t capacity = P2ALIGN((BTREE_LEAF_SIZE -
sizeof (zfs_btree_hdr_t)) / tree->bt_elem_size, 2);
VERIFY3U(hdr->bth_count, >=, (capacity / 2) - 1);

View File

@ -4531,8 +4531,8 @@ vdev_stat_update(zio_t *zio, uint64_t psize)
vdev_t *vd = zio->io_vd ? zio->io_vd : rvd;
vdev_t *pvd;
uint64_t txg = zio->io_txg;
vdev_stat_t *vs = &vd->vdev_stat;
vdev_stat_ex_t *vsx = &vd->vdev_stat_ex;
vdev_stat_t *vs = vd ? &vd->vdev_stat : NULL;
vdev_stat_ex_t *vsx = vd ? &vd->vdev_stat_ex : NULL;
zio_type_t type = zio->io_type;
int flags = zio->io_flags;

View File

@ -279,12 +279,9 @@ intptr_t __msan_test_shadow(const volatile void *x, size_t size);
#endif
/* detects whether we are being compiled under asan */
#if defined (__has_feature)
# if __has_feature(address_sanitizer)
# define ADDRESS_SANITIZER 1
# endif
#elif defined(__SANITIZE_ADDRESS__)
#if defined (ZFS_ASAN_ENABLED)
# define ADDRESS_SANITIZER 1
# define ZSTD_ASAN_DONT_POISON_WORKSPACE
#endif
#if defined (ADDRESS_SANITIZER)

View File

@ -207,11 +207,7 @@ static struct zstd_pool *zstd_mempool_dctx;
* and while ASAN does this, KASAN defines that and does not. So to avoid
* changing the external code, we do this.
*/
#if defined(__has_feature)
#if __has_feature(address_sanitizer)
#define ADDRESS_SANITIZER 1
#endif
#elif defined(__SANITIZE_ADDRESS__)
#if defined(ZFS_ASAN_ENABLED)
#define ADDRESS_SANITIZER 1
#endif
#if defined(_KERNEL) && defined(ADDRESS_SANITIZER)

View File

@ -55,6 +55,7 @@
%bcond_with debug
%bcond_with debuginfo
%bcond_with asan
%bcond_with ubsan
%bcond_with systemd
%bcond_with pam
%bcond_without pyzfs
@ -344,6 +345,12 @@ image which is ZFS aware.
%define asan --disable-asan
%endif
%if %{with ubsan}
%define ubsan --enable-ubsan
%else
%define ubsan --disable-ubsan
%endif
%if 0%{?_systemd}
%define systemd --enable-systemd --with-systemdunitdir=%{_unitdir} --with-systemdpresetdir=%{_presetdir} --with-systemdmodulesloaddir=%{_modulesloaddir} --with-systemdgeneratordir=%{_systemdgeneratordir} --disable-sysvinit
%define systemd_svcs zfs-import-cache.service zfs-import-scan.service zfs-mount.service zfs-share.service zfs-zed.service zfs.target zfs-import.target zfs-volume-wait.service zfs-volumes.target
@ -379,6 +386,7 @@ image which is ZFS aware.
%{debug} \
%{debuginfo} \
%{asan} \
%{ubsan} \
%{systemd} \
%{pam} \
%{pyzfs}

View File

@ -148,7 +148,7 @@ trap cleanup EXIT
# be dangerous and should only be used in a dedicated test environment.
#
cleanup_all() {
TEST_POOLS=$(sudo "$ZPOOL" list -H -o name | grep testpool)
TEST_POOLS=$(sudo env ASAN_OPTIONS=detect_leaks=false "$ZPOOL" list -H -o name | grep testpool)
if [ "$UNAME" = "FreeBSD" ] ; then
TEST_LOOPBACKS=$(sudo "${LOSETUP}" -l)
else
@ -160,7 +160,7 @@ cleanup_all() {
msg "--- Cleanup ---"
msg "Removing pool(s): $(echo "${TEST_POOLS}" | tr '\n' ' ')"
for TEST_POOL in $TEST_POOLS; do
sudo "$ZPOOL" destroy "${TEST_POOL}"
sudo env ASAN_OPTIONS=detect_leaks=false "$ZPOOL" destroy "${TEST_POOL}"
done
if [ "$UNAME" != "FreeBSD" ] ; then
@ -554,7 +554,7 @@ fi
# space-delimited to newline-delimited.
#
if [ -z "${KEEP}" ]; then
KEEP="$(sudo "$ZPOOL" list -H -o name)"
KEEP="$(sudo env ASAN_OPTIONS=detect_leaks=false "$ZPOOL" list -H -o name)"
if [ -z "${KEEP}" ]; then
KEEP="rpool"
fi

View File

@ -215,7 +215,8 @@ shift $((OPTIND - 1))
# enable core dumps
ulimit -c unlimited
export ASAN_OPTIONS=abort_on_error=1:disable_coredump=0
export ASAN_OPTIONS=abort_on_error=true:halt_on_error=true:allocator_may_return_null=true:disable_coredump=false:detect_stack_use_after_return=true
export UBSAN_OPTIONS=abort_on_error=true:halt_on_error=true:print_stacktrace=true
if [[ -f "$(core_file)" ]]; then
echo -n "There's a core dump here you might want to look at first... "

View File

@ -51,6 +51,7 @@ export SYSTEM_FILES_COMMON='arp
iostat
kill
ksh
ldd
ln
logname
ls

View File

@ -155,6 +155,21 @@ done
export MAX_PARTITIONS=8
if [ "@ASAN_ENABLED@" = "yes" ]; then
export ASAN_OPTIONS=abort_on_error=true:halt_on_error=true:allocator_may_return_null=true:disable_coredump=false:detect_stack_use_after_return=true
# TODO
# disable memory leaks detection
# there are quite many of them and they are not as
# destructive to CLI programs as they are to daemons
export ASAN_OPTIONS="$ASAN_OPTIONS:detect_leaks=false"
fi
if [ "@UBSAN_ENABLED@" = "yes" ]; then
export UBSAN_OPTIONS=abort_on_error=true:halt_on_error=true:print_stacktrace=true
fi
case $(uname -o) in
GNU/Linux)
unpack_opts="--sparse -xf"

View File

@ -41,8 +41,8 @@ log_must display_status "$TESTPOOL"
#
log_must zfs create -o dedup=on -V 2G $TESTPOOL/$TESTVOL
log_must eval "new_fs $ZVOL_DEVDIR/$TESTPOOL/$TESTVOL >/dev/null 2>&1"
block_device_wait "$ZVOL_DEVDIR/$TESTPOOL/$TESTVOL"
log_must eval "new_fs $ZVOL_DEVDIR/$TESTPOOL/$TESTVOL >/dev/null"
sync_pool
log_must zpool list -v $TESTPOOL

View File

@ -97,7 +97,6 @@ if is_linux; then
ulimit -c unlimited
echo "$corefile" >/proc/sys/kernel/core_pattern
echo 0 >/proc/sys/kernel/core_uses_pid
export ASAN_OPTIONS="abort_on_error=1:disable_coredump=0"
elif is_freebsd; then
ulimit -c unlimited
savedcorefile=$(sysctl -n kern.corefile)

View File

@ -95,7 +95,6 @@ elif is_freebsd; then
fi
ulimit -c unlimited
export ASAN_OPTIONS="abort_on_error=1:disable_coredump=0"
export ZFS_ABORT=yes
for subcmd in "${cmds[@]}" "${badparams[@]}"; do

View File

@ -89,7 +89,6 @@ elif is_freebsd; then
fi
ulimit -c unlimited
export ASAN_OPTIONS="abort_on_error=1:disable_coredump=0"
export ZFS_ABORT=yes
zpool >/dev/null 2>&1

View File

@ -35,7 +35,7 @@
DISK1=${DISKS%% *}
log_must zpool create -f $TESTPOOL $DISK1
log_must zpool trim $TESTPOOL
log_must zpool trim -r 1 "$TESTPOOL"
[[ -z "$(trim_progress $TESTPOOL $DISK1)" ]] && \
log_fail "TRIM did not start"

View File

@ -22,6 +22,10 @@
. $STF_SUITE/tests/functional/pam/utilities.kshlib
if [ -n "$ASAN_OPTIONS" ]; then
export LD_PRELOAD=$(ldd "$(command -v zfs)" | awk '/libasan\.so/ {print $3}')
fi
log_mustnot ismounted "$TESTPOOL/pam/${username}"
keystatus unavailable

View File

@ -22,6 +22,10 @@
. $STF_SUITE/tests/functional/pam/utilities.kshlib
if [ -n "$ASAN_OPTIONS" ]; then
export LD_PRELOAD=$(ldd "$(command -v zfs)" | awk '/libasan\.so/ {print $3}')
fi
log_mustnot ismounted "$TESTPOOL/pam/${username}"
keystatus unavailable

View File

@ -27,6 +27,10 @@
. $STF_SUITE/tests/functional/pam/utilities.kshlib
if [ -n "$ASAN_OPTIONS" ]; then
export LD_PRELOAD=$(ldd "$(command -v zfs)" | awk '/libasan\.so/ {print $3}')
fi
if [[ -z pamservice ]]; then
pamservice=pam_zfs_key_test
fi

View File

@ -16,6 +16,10 @@
. $STF_SUITE/include/libtest.shlib
if [ -n "$ASAN_OPTIONS" ]; then
export LD_PRELOAD=$(ldd "$(command -v zfs)" | awk '/libasan\.so/ {print $3}')
fi
#
# DESCRIPTION:
# Verify the libzfs_core Python test suite can be run successfully

View File

@ -58,7 +58,7 @@ main(void)
exit(3);
}
if ((ret = system("sudo zpool freeze $TESTPOOL"))) {
if ((ret = system("sudo -E zpool freeze $TESTPOOL"))) {
if (ret == -1)
perror("system \"zpool freeze\"");
else
@ -69,7 +69,7 @@ main(void)
close(fd);
if ((ret = system("sudo zpool export $TESTPOOL"))) {
if ((ret = system("sudo -E zpool export $TESTPOOL"))) {
if (ret == -1)
perror("system \"zpool export\"");
else
@ -78,7 +78,7 @@ main(void)
exit(4);
}
if ((ret = system("sudo zpool import $TESTPOOL"))) {
if ((ret = system("sudo -E zpool import $TESTPOOL"))) {
if (ret == -1)
perror("system \"zpool import\"");
else