Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support -fsanitizer=address on ztest #6884

Closed
wants to merge 2 commits into from

Conversation

DeHackEd
Copy link
Contributor

Requires minimum of gcc version 4.8. Only available to ztest
right now, but easily added to other user applications. For
kernel support use the Linux KASAN feature instead.

Signed-off-by: DHE git@dehacked.net

Description

If your compiler supports -fsanitize=address and you configure with --enable-debug most libraries, zdb and ztest will be built with it enabled.

Motivation and Context

By request from @behlendorf in #6877

How Has This Been Tested?

Build testing for the disabled path, full test of executable launch abilities for the debug path.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Performance enhancement (non-breaking change which improves efficiency)
  • Code cleanup (non-breaking change which makes code smaller or more readable)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation (a change to man pages or other documentation)

Checklist:

  • My code follows the ZFS on Linux code style requirements.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • All commit messages are properly formatted and contain Signed-off-by.
  • Change has been approved by a ZFS on Linux member.

@DeHackEd
Copy link
Contributor Author

Surprises:

  • -fsanitize=address adds a lot to the stack sizes of functions. When building with ASAN I raised the stack size from 1024 to 3072. The highest stack size I noticed when building was 2832.
  • To be useful, both ztest and libzpool at a minimum would require ASAN enabled. In the end it just made sense to enable it for all the libraries and to LDFLAGS for binaries in general.

In a little while I will push a revert to #6877 to see it in action on the buildbots. :)

@DeHackEd DeHackEd changed the title Ztest asan Support -fsanitizer=address on ztest Nov 18, 2017
@DeHackEd
Copy link
Contributor Author

Buildbots failing becuase libasan is not installed by defualt. On CentOS 7 libasan needs to be installed. :/

@behlendorf
Copy link
Contributor

@DeHackEd thanks! You can add libasan to the installed dependencies by opening a PR to update this script and tagging @dinatale2 for a review to get it merged.

https://github.com/zfsonlinux/zfs-buildbot/blob/master/scripts/bb-dependencies.sh

@dinatale2
Copy link
Contributor

FYI @DeHackEd openzfs/zfs-buildbot#123 was just merged.

@codecov
Copy link

codecov bot commented Nov 20, 2017

Codecov Report

❗ No coverage uploaded for pull request base (master@ed15d54). Click here to learn what that means.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff            @@
##             master    #6884   +/-   ##
=========================================
  Coverage          ?   71.67%           
=========================================
  Files             ?      296           
  Lines             ?    95015           
  Branches          ?        0           
=========================================
  Hits              ?    68098           
  Misses            ?    26917           
  Partials          ?        0
Flag Coverage Δ
#kernel 70.84% <100%> (?)
#user 64.93% <100%> (?)
Impacted Files Coverage Δ
module/zfs/spa.c 74.81% <100%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update ed15d54...44617d9. Read the comment docs.

@DeHackEd
Copy link
Contributor Author

Thanks. I've pushed a rebase and fix for minor issues in the PR to kick off the buildbots again.

@DeHackEd DeHackEd force-pushed the ztest-asan branch 3 times, most recently from f003d45 to 524c401 Compare November 22, 2017 02:26
@DeHackEd
Copy link
Contributor Author

Update pushed. This version tries a full link in the configure script to detect systems where libasan is missing or broken and doesn't prevent building.

module/zfs/spa.c Outdated
/*
* -fsanitize in userspace will detect kmem_alloc(0, ...)
* as a leak
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No comment needed, it is a leak and should be fixed.

module/zfs/spa.c Outdated
* as a leak
*/
if (sav->sav_count > 0)
l2cache = kmem_alloc(sav->sav_count * sizeof (void *),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this same issue can occur on line 1588, I'm surprised it wasn't also flagged.

Copy link
Contributor

@behlendorf behlendorf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's good to see that enabling this functionality in ztest didn't expose any new issues. Since that went smoothly have you by chance looked in to enabling for all of user space for debug builds? We could do that right away by adding it to DEBUG_CFLAGS assuming it doesn't identify a slew of issues which would need to be resolved first.

I'm not sure why but this patch appears to break the ZFS_ABORT functionality, calling abort() no longer generates a core causing several test cases to fail.

@@ -2,7 +2,7 @@ include $(top_srcdir)/config/Rules.am

# -Wnoformat-truncation to get rid of compiler warning for unchecked
# truncating snprintfs on gcc 7.1.1.
AM_CFLAGS += $(DEBUG_STACKFLAGS) $(FRAME_LARGER_THAN) $(NO_FORMAT_TRUNCATION)
AM_CFLAGS += $(DEBUG_STACKFLAGS) $(FRAME_LARGER_THAN) $(NO_FORMAT_TRUNCATION) $(COMPILER_FSANITIZE_ADDRESS)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's pull $(COMPILER_FSANITIZE_ADDRESS) down on to it's own line to mind the 80 character limit. Here and elsewhere.

AM_CFLAGS += $(DEBUG_STACKFLAGS) $(FRAME_LARGER_THAN) $(NO_FORMAT_TRUNCATION)
AM_CFLAGS += $(COMPILER_FSANITIZE_ADDRESS)

])

CFLAGS="$saved_flags"
AC_SUBST([FRAME_LARGER_THAN])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No objection to consolidating these, but please fix the whitespace on this line while you're here. Let's also pull in user-no-format-truncation.m4.


AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])],
[
if test -z "$COMPILER_FSANITIZE_ADDRESS"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AS_IF macro if available for the conditional. However, I think it'd be reasonable to simply bump this unconditionally to 4096 to cover both cases. This only applies to user space where we have headroom, and this was originally added before the kernel build system set -Wframe-larger-than by default.

CFLAGS="$saved_flags"
LDFLAGS="$saved_ldflags"
fi
AC_SUBST([COMPILER_FSANITIZE_ADDRESS])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest either dropping the COMPILER_ prefix, which isn't super useful and would be my preference. Or alternately adding it to NO_FORMAT_TRUNCATION and FRAME_LARGER_THAN for consistency.

@@ -27,7 +27,7 @@ AC_DEFUN([ZFS_AC_DEBUG], [
AC_MSG_CHECKING([whether assertion support will be enabled])
AC_ARG_ENABLE([debug],
[AS_HELP_STRING([--enable-debug],
[Enable assertion support @<:@default=no@:>@])],
[Enable assertion support and compiler features where available @<:@default=no@:>@])],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way you've implemented this setting --enable-debug has no effect of this compiler feature. It only defines DEBUG and sets -Werror, so I'm assuming this is an unrelated bit of clarification. In which case, how about the following message instead.

Enable assertions and -Werror @<:@default=no@:>@

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually it does. -fsanitize is only checked for and hence enabled when a debug build is performed. The whole new m4 block is guarded with

if test "$enable_debug" = "yes"

This allows a normal build to operate without -fsanitize even on systems which support it.

But I agree, this text needs rewording.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh, I see. I glossed over that in my initial reading. What do you think about moving the call points for these debug-only compiler checks in to ZFS_AC_DEBUG_ENABLE. This way these M4 macro's will only run for debug builds where they're needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to keep the stack size check together with this one for the sake of coherence and so that non-debug builds would still use a sane stack size check value. m4 is new to me so I'm sure my style is horrible.

kmem_alloc(0, ...) in userspace returns a leakable pointer.

Signed-off-by: DHE <git@dehacked.net>
@DeHackEd
Copy link
Contributor Author

Regarding the memory leak, the l2cache variable is stack-local whereas newvdevs will be assigned to sav->sav_vdevs to be freed later in spa_unload().

That said I have been hitting another leak in the refcount code but I'm not getting much information about where the allocation is coming from yet. We still need that fixed before we push this branch.

Requires minimum of gcc version 4.8. Only available to ztest
right now, but easily added to other user applications. For
kernel support use the Linux KASAN feature instead.

Signed-off-by: DHE <git@dehacked.net>
@behlendorf behlendorf added the Status: Work in Progress Not yet ready for general review label Nov 30, 2017
@behlendorf
Copy link
Contributor

Closing, replaced by #6941

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Work in Progress Not yet ready for general review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants