Messages in this thread | | | Date | Fri, 10 Mar 2023 21:59:26 +0100 | From | Peter Zijlstra <> | Subject | Re: [RFC][PATCH 1/5] static_call: Make NULL static calls consistent |
| |
On Fri, Mar 10, 2023 at 12:31:13PM -0800, Josh Poimboeuf wrote:
> -/* > - * This horrific hack takes care of two things: > - * > - * - it ensures the compiler will only load the function pointer ONCE, > - * which avoids a reload race. > - * > - * - it ensures the argument evaluation is unconditional, similar > - * to the HAVE_STATIC_CALL variant. > - * > - * Sadly current GCC/Clang (10 for both) do not optimize this properly > - * and will emit an indirect call for the NULL case :-( > - */ > -#define __static_call_cond(name) \ > -({ \ > - void *func = READ_ONCE(STATIC_CALL_KEY(name).func); \ > - if (!func) \ > - func = &__static_call_nop; \ > - (typeof(STATIC_CALL_TRAMP(name))*)func; \ > -})
So a sufficiently clever compiler can optimize the above to avoid the actual indirect call (and resulting CFI violation, see below), because __static_call_nop() is inline and hence visible as an empty stub function. Currently none of the compilers are that clever :/
> -#define static_call_cond(name) (void)__static_call_cond(name) > +#define static_call_cond(name) (void)static_call(name) > > static inline > void __static_call_update(struct static_call_key *key, void *tramp, void *func) > { > - WRITE_ONCE(key->func, func); > + WRITE_ONCE(key->func, func ? : (void *)__static_call_nop); > }
This will break ARM64 I think, they don't HAVE_STATIC_CALL but do have CLANG_CFI, which means the above will end up being a runtime indirect call to a non-matching signature function.
Now, I suppose we don't actually have this happen in current code by the simple expedient of not actually having any static_call_cond() usage outside of arch code.
(/me git-grep's some and *arrrggh* trusted-keys)
I really don't think we can do this though, must not promote CFI violations.
| |