[PATCH] D147975: [StackProtector] don't check stack protector before calling nounwind functions
Nick Desaulniers via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 11 15:08:16 PDT 2023
nickdesaulniers marked an inline comment as done.
nickdesaulniers added a comment.
In D147975#4256991 <https://reviews.llvm.org/D147975#4256991>, @LuoYuanke wrote:
> It seems the noreturn call do miss the stack canary checking. Is it the expected behaviour in security point of view?
It's my opinion, and I acknowledge that folks can have a reasonable disagreement, but reading https://download.vusec.net/papers/chop_ndss23.pdf, I think `noreturn` is a red-herring. The attack relies on `__cxa_throw` being `noreturn`, and no stack check being emitted before that. Once your in a function, it's hard to know if the callers stack frame has been corrupted, so it's better to check the stack canary in the call before the caller.
I agree with this point: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58245#c6. Why don't we check the stack canary before non-noreturn calls? Why not before EVERY operation involving stack memory? //performance//
Whether the called function is noreturn or not is kind of irrelevant. Consider the following case:
void caller () {
int arr [42] = {};
int (*callee)() = get_callback();
vuln();
callee(arr);
}
`callee` may make control flow decisions based on stack allocated variables in `caller`. Those values may have been corrupted. (A traditional JOP attack) Does it matter if `callee` is `noreturn`? (I think not) So I think CHOP is a cute name, but it's just a JOP attack that finds gadgets in the C++ exception handling runtime.
My change undoes the excessive canary checking to C code (and `noexcept` C++ functions, or C++ code built with `-fno-exceptions`), but `-fexceptions` C++ code will have a penalty larger than just before calls to `__cxa_throw`, such as calls to explicitly marked `noreturn` functions. I think the penalty introduced in https://reviews.llvm.org/rGd656ae28095726830f9beb8dbd4d69f5144ef821 (and https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=a25982ada523689c8745d7fb4b1b93c8f5dab2e7) could be reduced by simply checking the stack canary before a call to `__cxa_throw` alone (and whatever the equivalent is on non-Itanium ABI systems) since the CHOP paper demonstrates how powerful the C++ exception handling gadgets may be. I'm just trying to undo the unreasonable cost for C programs with this change.
---
Android undid https://reviews.llvm.org/rGd656ae28095726830f9beb8dbd4d69f5144ef821 here due to measured 2% RSS increase: https://android-review.git.corp.google.com/c/platform/build/soong/+/2524336. I will add that note to the commit message. Unless there's more feedback about this change, such as something I may be missing, I plan to commit this tomorrow and request a cherry-pick to the release/16.x branch.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D147975/new/
https://reviews.llvm.org/D147975
More information about the llvm-commits
mailing list