-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[Sanitizers] Add Scudo support #28538
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
Conversation
@swift-ci please smoke test |
I should note that, when we update the version of llvm we're using, enabling Scudo will also enable GWP-Asan, which provides not just mitigation but active detection of problems. |
The Swift PR swiftlang/swift#28538 adds support for the Scudo hardened allocator to swiftc. This patch adds support for it to Swift Package Manager, allowing the Package Manager to correctly plumb Scudo through the entire build pipeline. See the aforementioned PR for more discussion on the value of supporting Scudo.
@Lukasa Thanks for the patch. There are something things that need to be addressed before this can land.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See my initial comments.
Thanks @danliew-apple!
I don't believe this is true. There are separate Sanitizer whitelists for Darwin and Windows which explicitly whitelist the sanitisers they support. I have observed that with this toolchain built on Darwin the Scudo flag is rejected: I believe this is true for Windows as well, though @compnerd could further clarify.
It turns out it already is. On Linux the driver will simply pass the sanitizer option through to clang, which drives the actual linking process. This results in the sanitising being applied. Again, I've verified this in live code.
Fantastic. Can you point me to places in the code that do similar testing? I wasn't able to find them, and that made it very hard to write more. |
@Lukasa Here are some examples:
Note that
|
Thanks @danliew-apple, I’ll write some tests to cover this and ping for re-review when I’ve done so. |
The code you link to is related to linking. The driver should fail compilation much earlier than that. If someone passes
Interesting. I would not have expected that given that the Swift compiler shouldn't know what to do with this new enum member you've added. You'll need to show me working tests to convince me. |
@Lukasa Just to be clear I'm only giving you a review the code as I see it. I don't work on the swift compiler very frequently so I think you will need approval from others to land this. Given that this is very untested I suspect we might want to label it as experimental. |
@danliew-apple Totally understood, and I’m very appreciative of your time. I’m confident the patch-as-written works in the straightforward cases because I tested it live, but I also totally agree that without the tests it is hard for anyone else to validate my confidence! So I absolutely appreciate the feedback. I’ll work on adding those tests, and we can worry about wider approval once I’ve dealt with this feedback. |
@airspeedswift @mikeash Does adopting the hardened Scudo on Linux seem a reasonable thing to support? |
@Lukasa I just noticed that the Scudo documentation says.. "Compiling with Scudo will also enforce PIE for the output binary". That's the behaviour for Clang. Do you know why they do this? If there's a good reason for this we might need to do the same thing for Swift. I don't know if Swift has an equivalent PIE mode. |
@swift-ci please smoke test |
@swift-ci please smoke test |
@danliew-apple I'm not too familiar with it, but reading through the link you provided, this seems like a great thing to support. Especially since the hard work is in LLVM and we apparently just need to support the option and pass it along. @weissi Any additional thoughts? |
@swift-ci please smoke test |
3 similar comments
@swift-ci please smoke test |
@swift-ci please smoke test |
@swift-ci please smoke test |
@swift-ci please smoke test |
@swift-ci please test |
Build failed |
Build failed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's still an issue with the test that needs to be resolved.
I also have a very minor nit with the commit message.
The result of this patch matches the API of clang, which supports
-fsanitize=scudo
.
Technically -fsanitize=scudo
isn't really an API and even then its not an exact match because the command line flag name is different.
Maybe when you say
This patch enables -sanitize=scudo
as an extra swiftc
flag.
You could say as the next sentence.
This is similar to Clang's -fsanitize=scudo
flag.
test/Driver/sanitize_scudo.swift
Outdated
/* | ||
* Make sure we don't accidentally add the sanitizer library path when building libraries or modules | ||
*/ | ||
// RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -emit-library -sanitize=scudo -target x86_64-unknown-linux-gnu %s 2>&1 | %FileCheck --implicit-check-not=SCUDO_LINUX %s |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is right: when building only libraries, we don't want to add the sanitiser because it should only be added when building the main binary. This is the same as the requirement on all the other sanitisers with runtime libraries: only the main binary actually invokes the linker to link the sanitiser runtime.
I wasn't questioning that aspect. I was questioning the FileCheck invocation which I'm fairly certain is wrong because you're not using --implicit-check-not
as intended (see the FileCheck documentation). You're supposed to give it a pattern and not a check prefix which is what the current patch does.
Sure the test currently passes but that's because the Swift compiler isn't producing the text SWIFT_LINUX
in its output. So the test is passing by accident and you're not testing what you actually testing what you want to test.
LLVM ships a hardened memory allocator called Scudo: https://llvm.org/docs/ScudoHardenedAllocator.html. This allocator provides additional mitigations against heap-based vulnerabilities, but retains sufficient performance to be safely run in production applications. While ideal Swift applications are obviously written in pure Swift, in practice most applications contain some amount of code written in less-safe languages. Additionally, plenty of Swift programs themselves contain unsafe code, particularly when attempting to implement high-performance data structures. These sources of unsafety introduce the risk of memory issues, and having the option to use the Scudo allocator is a useful defense-in-depth tool. This patch enables `-sanitize=scudo` as an extra `swiftc` flag. This sanitizer is only supported on Linux, so no further work is required to enable it on Windows or Apple platforms. As this "sanitizer" is only a runtime component, we do not require any wider changes to instrument code. This is similar to clang's `-fsanitize=scudo` flag. The Swift driver rejects platforms that don't support Scudo using an existing mechanism in the Driver that is not part of this patch. This mechanism is in swift::parseSanitizerArgValues(...) (lib/Option/SanitizerOptions.cpp). The mechanism determines if a sanitizer is supported by checking for the existence of the corresponding sanitizer runtime library in the compiler's resource directory. The Scudo runtime library currently only exists in the Linux compiler resource directory. This results in the driver only allowing Scudo when targeting Linux.
@swift-ci please smoke test |
Thanks for that clarification @danliew-apple, that helped a lot! I have rewritten that test and also updated the commit message, please take another look. |
@swift-ci please test |
Build failed |
Build failed |
@swift-ci please test |
@Lukasa Sorry for being slow. I've approved the changes. Thanks for being patient. |
No need to apologise, I understand completely that we’re all busy! Thanks so much for your time on this. |
Build failed |
@swift-ci please test |
I believe that this has caused a regression on Windows: https://ci-external.swift.org/job/oss-swift-windows-x86_64/2607/ |
Good catch @compnerd, that fix looks right. Sorry about that! |
The Swift PR swiftlang/swift#28538 adds support for the Scudo hardened allocator to swiftc. This patch adds support for it to Swift Package Manager, allowing the Package Manager to correctly plumb Scudo through the entire build pipeline. See the aforementioned PR for more discussion on the value of supporting Scudo.
The Swift PR swiftlang/swift#28538 adds support for the Scudo hardened allocator to swiftc. This patch adds support for it to Swift Package Manager, allowing the Package Manager to correctly plumb Scudo through the entire build pipeline. See the aforementioned PR for more discussion on the value of supporting Scudo.
The Swift PR swiftlang/swift#28538 adds support for the Scudo hardened allocator to swiftc. This patch adds support for it to Swift Package Manager, allowing the Package Manager to correctly plumb Scudo through the entire build pipeline. See the aforementioned PR for more discussion on the value of supporting Scudo. (cherry picked from commit 594ccaa)
The Swift PR swiftlang/swift#28538 adds support for the Scudo hardened allocator to swiftc. This patch adds support for it to Swift Package Manager, allowing the Package Manager to correctly plumb Scudo through the entire build pipeline. It also brings in the testing strategy from See the aforementioned PR for more discussion on the value of supporting Scudo. (cherry picked from commit 594ccaa)
The Swift PR swiftlang/swift#28538 adds support for the Scudo hardened allocator to swiftc. This patch adds support for it to Swift Package Manager, allowing the Package Manager to correctly plumb Scudo through the entire build pipeline. See the aforementioned PR for more discussion on the value of supporting Scudo. (cherry picked from commit 594ccaa)
* Add support for the Scudo sanitizer. + Test sanitizers with build plans The Swift PR swiftlang/swift#28538 adds support for the Scudo hardened allocator to swiftc. This patch adds support for it to Swift Package Manager, allowing the Package Manager to correctly plumb Scudo through the entire build pipeline. See the aforementioned PR for more discussion on the value of supporting Scudo. (cherry picked from commit 594ccaa) * Test sanitizers with build plans. (#2720) The current tests for sanitizers in SwiftPM are essentially "live": they build a package that will do something to trigger a sanitizer, and then run it and confirm it fails. This is a pretty fragile way to test, and it exposes SwiftPM to a number of possible test failures that don't have anything to do with the core mission (exposing the sanitizer). This patch replaces those tests with build plan tests that validate that SwiftPM correctly invokes swiftc and clang. These tests are acceptable because for now SwiftPM doesn't have any smarts with the sanitizers: it just passes them all through to swiftc and clang. This patch also deletes the current live tests, as they are no longer necessary. (cherry picked from commit 984618b)
LLVM ships a hardened memory allocator called Scudo:
https://llvm.org/docs/ScudoHardenedAllocator.html. This allocator
provides additional mitigations against heap-based vulnerabilities, but
retains sufficient performance to be safely run in production
applications.
While ideal Swift applications are obviously written in pure Swift, in
practice most applications contain some amount of code written in
less-safe languages. Additionally, plenty of Swift programs themselves
contain unsafe code, particularly when attempting to implement
high-performance data structures. These sources of unsafety introduce
the risk of memory issues, and having the option to use the Scudo
allocator is a useful defense-in-depth tool.
This patch enables
-sanitize=scudo
as an extraswiftc
flag. Thissanitizer is only supported on Linux, so no further work is required to
enable it on Windows or Apple platforms. As this "sanitizer" is only a
runtime component, we do not require any wider changes to instrument
code.
The result of this patch matches the API of clang, which supports
-fsanitize=scudo
.I do have one question: currently this patch contains no regression tests. I was fundamentally unsure of where to place these regression tests, but I think we should have them, so please do as part of your review suggest a location and form for the regression tests.