This is an archive of the discontinued LLVM Phabricator instance.

Protection against stack-based memory corruption errors using SafeStack: Clang command line option and function attribute
ClosedPublic

Authored by pcc on Nov 3 2014, 9:41 AM.

Details

Summary

This patch adds the -fsafe-stack command line argument for clang, which enables the Safe Stack protection (see http://reviews.llvm.org/D6094 for the detailed description of the Safe Stack).

This patch is our implementation of the safe stack on top of the current SVN HEAD of Clang (r221154). The patches make the following changes:

  • Add -fsafe-stack and -fno-safe-stack options to clang to control safe stack usage (the safe stack is disabled by default).
  • Add attribute((no_safe_stack)) attribute to clang that can be used to disable the safe stack for individual functions even when enabled globally.

Diff Detail

Repository
rL LLVM

Event Timeline

ksvladimir updated this revision to Diff 15718.Nov 3 2014, 9:41 AM
ksvladimir retitled this revision from to Protection against stack-based memory corruption errors using SafeStack: Clang command line option and function attribute.
ksvladimir updated this object.
ksvladimir edited the test plan for this revision. (Show Details)
ksvladimir added a reviewer: theraven.
ksvladimir added a subscriber: Unknown Object (MLST).
colinl added a subscriber: colinl.Nov 3 2014, 10:25 AM
theraven added inline comments.Nov 3 2014, 10:44 AM
include/clang/Basic/AttrDocs.td
868 ↗(On Diff #15718)

It would be nice if this documentation didn't assume that everyone reading it knew what the safe stack instrumentation was. In particular, it should say what kind of functions might need to use this attribute (ones that do stack introspection?).

lib/Driver/Tools.cpp
2189 ↗(On Diff #15718)

This is Linux specific. Most other platforms don't need anything explicitly linked to support dl*()

lib/Frontend/InitPreprocessor.cpp
830 ↗(On Diff #15718)

It would be worth surveying a corpus of code and seeing what uses the __SSP defines. We may find that it's worth defining some of them in SafeStack mode, as it may cause the same kind of breakage.

kcc added a subscriber: kcc.Nov 3 2014, 3:18 PM
kcc added inline comments.Nov 3 2014, 3:18 PM
lib/Frontend/InitPreprocessor.cpp
830 ↗(On Diff #15718)

Note that AddressSanitizer does not define any preprocessor symbol.
I tried to introduce ADDRESS_SANITIZER but failed to convince the clang folks.
Instead, we use hasfeature(address_sanitizer), which is sadly incompatible with GCC's asan implementation, but works fine.

emaste added a subscriber: emaste.Nov 3 2014, 8:43 PM
ksvladimir updated this revision to Diff 15776.Nov 4 2014, 11:20 AM

Addresses comments on the previous submission.

You can find the detailed changelog since the previous submission in our repo: https://github.com/cpi-llvm/clang/commits/safestack-r221153

amanone added a subscriber: amanone.Nov 6 2014, 2:26 AM
ksvladimir updated this revision to Diff 15992.Nov 10 2014, 9:45 AM

Added unittests for the -fsafe-stack and -fno-safe-stack options in clang and -fstack-protector 4 option in clang-cc1.

ksvladimir updated this revision to Diff 16078.Nov 12 2014, 2:34 AM

Added tests for attribute((no_safe_stack)).

abique added a subscriber: abique.Nov 14 2014, 12:16 AM
ksvladimir edited the test plan for this revision. (Show Details)

Added documentation for the no_safe_stack attribute. Simplified safestack public symbol names.

ksvladimir updated this revision to Diff 16262.Nov 14 2014, 9:54 PM

Fixed symbol naming on Mac.

pcc commandeered this revision.Apr 23 2015, 3:42 PM
pcc added a reviewer: ksvladimir.
pcc updated this revision to Diff 24338.Apr 23 2015, 3:45 PM

Refresh

kcc added a reviewer: samsonov.May 5 2015, 4:21 PM

I'd like Alexey to co-review the clang part.

A top-level comment so far: don't we want to have the flag as -f[no-]sanitize=safe_stack?
This will make it consistent with the rest of sanitizers, including cfi

kcc added a comment.May 5 2015, 4:39 PM

more comments

docs/SafeStack.rst
12 ↗(On Diff #24338)

.. based on stack-based...

I'd remove the second "based"

44 ↗(On Diff #24338)

is this true about libc?

83 ↗(On Diff #24338)

See my previous comment about macros and ADDRESS_SANITIZER.
You may have to change this to __has_feature(safe_stack)

gribozavr added inline comments.
test/SemaCXX/attr-no-safestack.cpp
12 ↗(On Diff #24338)

Rather than relying on line continuations, you could use expected-error@-1.

pcc updated this revision to Diff 25097.May 6 2015, 3:43 PM
  • Rename flag to -fsanitize=safe-stack
  • SAFESTACK -> __has_feature(safe_stack), doc updates
pcc added inline comments.May 6 2015, 3:45 PM
docs/SafeStack.rst
12 ↗(On Diff #24338)

Done

44 ↗(On Diff #24338)

Not currently. Removed.

83 ↗(On Diff #24338)

Done

test/SemaCXX/attr-no-safestack.cpp
12 ↗(On Diff #24338)

Done

samsonov added inline comments.May 6 2015, 4:15 PM
docs/AttributeReference.rst
486 ↗(On Diff #25097)

Do you need this attribute right now? If we decide to finally implement universal no_sanitize attribute, this attribute will become deprecated in favor of __attribute__((no_sanitize("safe-stack"))).

lib/CodeGen/CodeGenModule.cpp
747 ↗(On Diff #25097)

Do you need to respect -fsanitize-blacklist for this?

lib/Driver/ToolChains.cpp
13 ↗(On Diff #25097)

Accidental change?

lib/Driver/Tools.cpp
2296 ↗(On Diff #25097)

Note that you're adding -ldl here, but we tend to add dependencies of compiler-rt runtimes later in the linker invocation (see NeedsSanitizerDeps vars) - so that they are added after AddLinkerInputs is called.

8392 ↗(On Diff #25097)

Do we really want to support OS we don't build safestack runtime for? I'd just use Linux/MacOS for a start.

pcc updated this revision to Diff 25220.May 7 2015, 1:11 PM
  • Move safestack driver code to collectSanitizerRuntimes; eliminate SSPSafeStack
  • Revert unnecessary change
  • Update tests for new flags
  • Revert changes to AttributeReference.rst (updated automatically)
docs/AttributeReference.rst
486 ↗(On Diff #25097)

It's needed for Chromium and FreeBSD so far as I understand it.

lib/CodeGen/CodeGenModule.cpp
747 ↗(On Diff #25097)

Done

lib/Driver/ToolChains.cpp
13 ↗(On Diff #25097)

Reverted

lib/Driver/Tools.cpp
2296 ↗(On Diff #25097)

This now works like the other sanitizers.

8392 ↗(On Diff #25097)

addSafeStackRT is now gone, as well as these call sites.

samsonov edited edge metadata.May 7 2015, 5:12 PM

I understand that you probably need no_safe_stack attribute for Chromium/FreeBSD integration *right now*, and rather proceed with this and not wait until someone implements generic no_sanitize attribute, but... maybe we should at least not document it?

lib/CodeGen/CodeGenModule.cpp
765 ↗(On Diff #25220)

Do you also need to add it to CodeGenModule::CreateGlobalInitOrDestructFunction?

lib/Driver/Tools.cpp
2354 ↗(On Diff #25220)

This code is now dead - presence of -shared is checked at the top of this function. Can we silently discard -fsanitize=safe-stack while linking DSO?

6251 ↗(On Diff #25220)

Looks like you should set AlwaysLink argument of AddLinkRuntimeLib to true.

pcc updated this revision to Diff 25273.May 7 2015, 6:30 PM
pcc edited edge metadata.
  • Address review comments
pcc added a comment.May 7 2015, 6:30 PM

maybe we should at least not document it?

I'd rather document it than have some undocumented attribute in use somewhere.

I'll take a shot at implementing no_sanitize tomorrow and hopefully make this a moot point.

lib/CodeGen/CodeGenModule.cpp
765 ↗(On Diff #25220)

Yes, done.

lib/Driver/Tools.cpp
2354 ↗(On Diff #25220)

We can, but only if the DSO is linked against a main executable that is linked against the safe stack runtime. (Generally for the other sanitizers we can make this true, but in deployment scenarios you might not be able to control the main executable.)

There are a number of possible solutions to this problem, which we plan to deal with in a future change, but at least removing the check makes things work in that specific scenario. So I've removed it.

6251 ↗(On Diff #25220)

Done

I'm fine with this patch, modulo the attribute issue.

pcc updated this revision to Diff 25533.May 11 2015, 5:19 PM
  • Remove no_safe_stack attribute
samsonov accepted this revision.May 12 2015, 10:14 AM
samsonov edited edge metadata.

LGTM

This revision is now accepted and ready to land.May 12 2015, 10:14 AM
pcc updated this revision to Diff 25887.May 15 2015, 11:59 AM
pcc edited edge metadata.
  • Implement attribute((no_sanitize("safe-stack")))
pcc updated this revision to Diff 25889.May 15 2015, 12:18 PM
  • Fix documentation typo
ksvladimir added inline comments.May 19 2015, 3:51 PM
include/clang/Basic/LangOptions.def
202 ↗(On Diff #25889)

Since SSPSafeStack no longer exists, this should be reverted as well.

lib/Driver/Tools.cpp
6283 ↗(On Diff #25889)

Is this still required, even though we have AlwaysLink=true above?

pcc updated this revision to Diff 26105.May 19 2015, 4:42 PM
  • Remove unnecessary linker flag
  • Revert langopts change
  • Improve precision of safestack-attr.cpp test
include/clang/Basic/LangOptions.def
202 ↗(On Diff #25889)

Done

lib/Driver/Tools.cpp
6283 ↗(On Diff #25889)

No, removed.

jfb added a subscriber: jfb.May 21 2015, 9:04 AM

The patch description mentions `__attribute__((no_safe_stack))` which isn't the name used anymore.

docs/SafeStack.rst
18 ↗(On Diff #26105)

It would be good to document the limitations that this approach has.

Off the top of my head:

  • The safe stack is merely hidden from attackers by being somewhere in the address space. That's nice, but can be predictable even on 64-bit address spaces because not all the bits are addressable, multiple threads each have their stack, ...
  • This approach doesn't prevent an attacker from "imbalancing" the safe stack by say having just one call, and doing two rets (thereby returning to an address that wasn't meant as a return address).
51 ↗(On Diff #26105)

Does this have any security implications by making Oilpan spill the SafeStack address? I'm assuming that care must be taken not to do so!

55 ↗(On Diff #26105)

Format `dlopen()`

97 ↗(On Diff #26105)

What implications does this attribute have on the overall system's security?

109 ↗(On Diff #26105)

What happens when calling `__builtin_frame_address` with SafeStack?

pcc updated this revision to Diff 26542.May 26 2015, 3:02 PM
  • Implement attribute((no_sanitize("safe-stack")))
  • Fix documentation typo
  • Remove unnecessary linker flag
  • Revert langopts change
  • Improve precision of safestack-attr.cpp test
  • Document limitations
  • More documentation updates
  • More updates
pcc added inline comments.May 26 2015, 3:07 PM
docs/SafeStack.rst
18 ↗(On Diff #26105)

Done

51 ↗(On Diff #26105)

Yes. I now mention this in the limitations section.

55 ↗(On Diff #26105)

Done

97 ↗(On Diff #26105)

Added a relevant paragraph.

109 ↗(On Diff #26105)

I believe it will return a pointer to the safe stack. I've added some stuff to the Limitations section about this.

jfb added a comment.May 27 2015, 6:00 PM

You should also update the patch description.

Besides my new comment on warnings (which could be added separately), this patch LGTM.

docs/SafeStack.rst
109 ↗(On Diff #26105)

Would it be possible to have clang warn when doing safe-stack and __builtin_frame_address is used, or the stack leaks in other inadvertent ways? We want to avoid noisy warnings, but converting an existing codebase should probably require explicitly adding no-safe-stack attributes where required.

jfb added inline comments.May 28 2015, 2:10 PM
docs/SafeStack.rst
72 ↗(On Diff #26542)

Could you document the current limitations on DSO?

pcc updated this revision to Diff 26833.May 29 2015, 4:07 PM
  • Add a note regarding leak detection
  • Document DSO limitation
docs/SafeStack.rst
72 ↗(On Diff #26542)

Done

This revision was automatically updated to reflect the committed changes.
jfb added a reviewer: jfb.Sep 13 2015, 6:21 PM