llvm-project/llvm/lib
Hans Wennborg 2bc57d85eb Don't override __attribute__((no_stack_protector)) by inlining (PR52886)
Since 26c6a3e736, LLVM's inliner will "upgrade" the caller's stack protector
attribute based on the callee. This lead to surprising results with Clang's
no_stack_protector attribute added in 4fbf84c173 (D46300). Consider the
following code compiled with clang -fstack-protector-strong -Os
(https://godbolt.org/z/7s3rW7a1q).

  extern void h(int* p);

  inline __attribute__((always_inline)) int g() {
    return 0;
  }

  int __attribute__((__no_stack_protector__)) f() {
    int a[1];
    h(a);
    return g();
  }

LLVM will inline g() into f(), and f() would get a stack protector, against the
users explicit wishes, potentially breaking the program e.g. if h() changes the
value of the stack cookie. That's a miscompile.

More recently, bc044a88ee (D91816) addressed this problem by preventing
inlining when the stack protector is disabled in the caller and enabled in the
callee or vice versa. However, the problem remained if the callee is marked
always_inline as in the example above. This affected users, see e.g.
http://crbug.com/1274129 and http://llvm.org/pr52886.

One way to fix this would be to prevent inlining also in the always_inline
case. Despite the name, always_inline does not guarantee inlining, so this
would be legal but potentially surprising to users.

However, I think the better fix is to not enable the stack protector in a
caller based on the callee. The motivation for the old behaviour is unclear, it
seems counter-intuitive, and causes real problems as we've seen.

This commit implements that fix, which means in the example above, g() gets
inlined into f() (also without always_inline), and f() is emitted without stack
protector. I think that matches most developers' expectations, and that's also
what GCC does.

Another effect of this change is that a no_stack_protector function can now be
inlined into a stack protected function, e.g. (https://godbolt.org/z/hafP6W856):

  extern void h(int* p);

  inline int __attribute__((__no_stack_protector__)) __attribute__((always_inline)) g() {
    return 0;
  }

  int f() {
    int a[1];
    h(a);
    return g();
  }

I think that's fine. Such code would be unusual since no_stack_protector is
normally applied to a program entry point which sets up the stack canary. And
even if such code exists, inlining doesn't change the semantics: there is still
no stack cookie setup/check around entry/exit of the g() code region, but there
may be in the surrounding context, as there was before inlining. This also
matches GCC.

See also the discussion at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94722

Differential revision: https://reviews.llvm.org/D116589
2022-01-13 12:04:49 +01:00
..
Analysis Don't override __attribute__((no_stack_protector)) by inlining (PR52886) 2022-01-13 12:04:49 +01:00
AsmParser Use a sorted array instead of a map to store AttrBuilder string attributes 2022-01-10 14:49:53 +01:00
BinaryFormat Use llvm::any_of and llvm::all_of (NFC) 2021-12-11 11:54:37 -08:00
Bitcode Use a sorted array instead of a map to store AttrBuilder string attributes 2022-01-10 14:49:53 +01:00
Bitstream
CodeGen [Docs] Fix IR and TableGen grammar inconsistencies 2022-01-13 11:55:13 +01:00
DWARFLinker [llvm] Fix bugprone argument comments (NFC) 2022-01-08 11:56:38 -08:00
DWP
DebugInfo [llvm] Remove redundant member initialization (NFC) 2022-01-07 17:45:09 -08:00
Debuginfod [llvm] Use nullptr instead of 0 (NFC) 2021-12-28 08:52:25 -08:00
Demangle [Demangle] Pass Ret parameter from decodeNumber by reference 2022-01-12 21:57:31 +00:00
ExecutionEngine RuntimeDyldELF: Don't abort on R_AARCH64_NONE relocation 2022-01-13 11:54:48 +03:00
Extensions
FileCheck [FileCheck] Allow literal '['s before "[[var...]]" 2022-01-13 09:47:37 +00:00
Frontend [llvm] Fix bugprone argument comments (NFC) 2022-01-08 11:56:38 -08:00
FuzzMutate
Fuzzer
IR Don't override __attribute__((no_stack_protector)) by inlining (PR52886) 2022-01-13 12:04:49 +01:00
IRReader
InterfaceStub [llvm] Remove redundant member initialization (NFC) 2022-01-07 17:45:09 -08:00
LTO [LTO][codegen] Add TargetLibraryInfoWrapperPass initially 2022-01-06 09:24:35 +08:00
LineEditor [llvm] Use range-based for loops (NFC) 2021-12-09 09:37:29 -08:00
Linker [NFC] Replace some deprecated getAlignment() calls with getAlign() 2021-12-09 08:43:19 -08:00
MC [MachO] Port call graph profile section and directive 2022-01-12 09:22:26 -05:00
MCA [MCA] Switching from conservatively guessing which instructions are 2022-01-11 13:50:14 -08:00
Object Revert "[llvm-readobj][XCOFF] dump auxiliary symbols." 2022-01-12 09:42:05 -05:00
ObjectYAML [yaml2obj][XCOFF] parsing auxiliary symbols. 2022-01-10 02:38:49 +00:00
Option [llvm] Use range-based for loops (NFC) 2021-12-09 09:37:29 -08:00
Passes Add 'eager-checks' as a module parameter to MSAN. 2022-01-11 14:30:49 -08:00
ProfileData [llvm] Use true/false instead of 1/0 (NFC) 2022-01-07 00:39:14 -08:00
Remarks [llvm] Remove redundant member initialization (NFC) 2022-01-07 17:45:09 -08:00
Support clang support for Armv8.8/9.3 HBC 2022-01-12 22:07:35 +00:00
TableGen [llvm] Use true/false instead of 1/0 (NFC) 2022-01-07 00:39:14 -08:00
Target [ARM] fix bug causing shrinkwrapping not always being off using PAC 2022-01-13 10:37:00 +00:00
Testing
TextAPI
ToolDrivers
Transforms [GlobalOpt] Fix global to select transform under opaque pointers 2022-01-13 11:13:06 +01:00
WindowsManifest [llvm] Use nullptr instead of 0 (NFC) 2021-12-28 08:52:25 -08:00
XRay Support: Use Expected<T>::moveInto() in a few places 2021-10-22 12:40:10 -07:00
CMakeLists.txt [llvm] [Debuginfo] Debuginfod client library. 2021-12-06 21:52:38 +00:00