From d8d76062785548167cbc01eb5aaae2ae0665b5da Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Tue, 3 Jan 2023 13:47:15 +0100 Subject: [PATCH] netfilter: nf_tables: add static key to skip retpoline workarounds If CONFIG_RETPOLINE is enabled nf_tables avoids indirect calls for builtin expressions. On newer cpus indirect calls do not go through the retpoline thunk anymore, even for RETPOLINE=y builds. Just like with the new tc retpoline wrappers: Add a static key to skip the if / else if cascade if the cpu does not require retpolines. Suggested-by: Eric Dumazet Signed-off-by: Florian Westphal --- net/netfilter/nf_tables_core.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c index 709a736..0f26d00 100644 --- a/net/netfilter/nf_tables_core.c +++ b/net/netfilter/nf_tables_core.c @@ -21,6 +21,26 @@ #include #include +#if defined(CONFIG_RETPOLINE) && defined(CONFIG_X86) + +static struct static_key_false nf_tables_skip_direct_calls; + +static bool nf_skip_indirect_calls(void) +{ + return static_branch_likely(&nf_tables_skip_direct_calls); +} + +static void __init nf_skip_indirect_calls_enable(void) +{ + if (!cpu_feature_enabled(X86_FEATURE_RETPOLINE)) + static_branch_enable(&nf_tables_skip_direct_calls); +} +#else +static inline bool nf_skip_indirect_calls(void) { return false; } + +static inline void nf_skip_indirect_calls_enable(void) { } +#endif + static noinline void __nft_trace_packet(struct nft_traceinfo *info, const struct nft_chain *chain, enum nft_trace_types type) @@ -193,7 +213,12 @@ static void expr_call_ops_eval(const struct nft_expr *expr, struct nft_pktinfo *pkt) { #ifdef CONFIG_RETPOLINE - unsigned long e = (unsigned long)expr->ops->eval; + unsigned long e; + + if (nf_skip_indirect_calls()) + goto indirect_call; + + e = (unsigned long)expr->ops->eval; #define X(e, fun) \ do { if ((e) == (unsigned long)(fun)) \ return fun(expr, regs, pkt); } while (0) @@ -210,6 +235,7 @@ static void expr_call_ops_eval(const struct nft_expr *expr, X(e, nft_rt_get_eval); X(e, nft_bitwise_eval); #undef X +indirect_call: #endif /* CONFIG_RETPOLINE */ expr->ops->eval(expr, regs, pkt); } @@ -369,6 +395,8 @@ int __init nf_tables_core_module_init(void) goto err; } + nf_skip_indirect_calls_enable(); + return 0; err: -- 2.7.4