diff options
author | Florian Westphal <fw@strlen.de> | 2023-01-03 13:47:15 +0100 |
---|---|---|
committer | Florian Westphal <fw@strlen.de> | 2023-01-18 13:05:25 +0100 |
commit | d8d76062785548167cbc01eb5aaae2ae0665b5da (patch) | |
tree | 8c5e07d81e9163e50d801361e4cd79d486caf281 /net | |
parent | 9db5d918e2c07fa09fab18bc7addf3408da0c76f (diff) | |
download | lwn-d8d76062785548167cbc01eb5aaae2ae0665b5da.tar.gz lwn-d8d76062785548167cbc01eb5aaae2ae0665b5da.zip |
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 <eric.dumazet@gmail.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Diffstat (limited to 'net')
-rw-r--r-- | net/netfilter/nf_tables_core.c | 30 |
1 files changed, 29 insertions, 1 deletions
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c index 709a736c301c..0f26d002d8b3 100644 --- a/net/netfilter/nf_tables_core.c +++ b/net/netfilter/nf_tables_core.c @@ -21,6 +21,26 @@ #include <net/netfilter/nf_log.h> #include <net/netfilter/nft_meta.h> +#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: |