On Fri, Oct 15, 2021 at 11:29 AM Dan Li <ashimida@xxxxxxxxxxxxxxxxx> wrote:Yes.
On 10/15/21 2:44 AM, Nick Desaulniers wrote:
On Wed, Oct 13, 2021 at 4:28 PM Dan Li <ashimida@xxxxxxxxxxxxxxxxx> wrote:Thanks Nick,
--- a/include/linux/compiler-gcc.h
+++ b/include/linux/compiler-gcc.h
@@ -50,6 +50,10 @@
#define __latent_entropy __attribute__((latent_entropy))
#endif
+#if defined(SHADOW_CALL_STACK_PLUGIN) && !defined(__CHECKER__)
+#define __noscs __attribute__((no_shadow_call_stack))
+#endif
Cool this is a nice addition, and something I don't think that clang
has. For any new feature, having a function attribute to disable it
at the function granularity is nice, and plays better with LTO than -f
group flags. Though that begs the question: what happens if a __noscs
callee is inlined into a non-__noscs caller, or vice versa?
According to my understanding, all inline optimizations in gcc should
happen before inserting scs insns (scs and paciasp/autiasp use the
same insertion point). Therefore, the check for the __noscs attribute
will also occur after all inlining is completed.
As in the following example:
- Since __noscs attribute is specified, scs_test1 does not insert scs insns
- Since normal functions scs_test2/3 uses x30, it needs to insert scs insns
- Since __noscs attribute is specified, scs_test4 after inlining does not
need to insert scs insns
__always_inline __noscs void scs_test1(void)
{
asm volatile("mov x1, x1\n\t":::"x30");
}
//scs insns inserted after function inline
void scs_test2(void)
{
scs_test1();
}
That may be surprising to developers. Perhaps __always_inline on
scs_test1 is distracting this test case, but I suspect it may not make
a difference. This particular issue comes up time and again with
stack protectors; ie. the callee is marked no stack protector, then
gets inlined into a caller and suddenly gets a stack protector.