mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-04-10 08:13:50 +00:00
bpf: don't rely on the verifier lock for metadata_dst allocation
bpf_skb_set_tunnel_*() functions require allocation of per-cpu metadata_dst. The allocation happens upon verification of the first program using those helpers. In preparation for removing the verifier lock, use cmpxchg() to make sure we only allocate the metadata_dsts once. Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com> Reviewed-by: Simon Horman <simon.horman@netronome.com> Acked-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Daniel Borkmann <daniel@iogearbox.net> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
c9c35995bc
commit
d66f2b91f9
3 changed files with 26 additions and 7 deletions
|
@ -87,6 +87,7 @@ static inline int skb_metadata_dst_cmp(const struct sk_buff *skb_a,
|
||||||
void metadata_dst_free(struct metadata_dst *);
|
void metadata_dst_free(struct metadata_dst *);
|
||||||
struct metadata_dst *metadata_dst_alloc(u8 optslen, enum metadata_type type,
|
struct metadata_dst *metadata_dst_alloc(u8 optslen, enum metadata_type type,
|
||||||
gfp_t flags);
|
gfp_t flags);
|
||||||
|
void metadata_dst_free_percpu(struct metadata_dst __percpu *md_dst);
|
||||||
struct metadata_dst __percpu *
|
struct metadata_dst __percpu *
|
||||||
metadata_dst_alloc_percpu(u8 optslen, enum metadata_type type, gfp_t flags);
|
metadata_dst_alloc_percpu(u8 optslen, enum metadata_type type, gfp_t flags);
|
||||||
|
|
||||||
|
|
|
@ -322,3 +322,19 @@ metadata_dst_alloc_percpu(u8 optslen, enum metadata_type type, gfp_t flags)
|
||||||
return md_dst;
|
return md_dst;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(metadata_dst_alloc_percpu);
|
EXPORT_SYMBOL_GPL(metadata_dst_alloc_percpu);
|
||||||
|
|
||||||
|
void metadata_dst_free_percpu(struct metadata_dst __percpu *md_dst)
|
||||||
|
{
|
||||||
|
int cpu;
|
||||||
|
|
||||||
|
#ifdef CONFIG_DST_CACHE
|
||||||
|
for_each_possible_cpu(cpu) {
|
||||||
|
struct metadata_dst *one_md_dst = per_cpu_ptr(md_dst, cpu);
|
||||||
|
|
||||||
|
if (one_md_dst->type == METADATA_IP_TUNNEL)
|
||||||
|
dst_cache_destroy(&one_md_dst->u.tun_info.dst_cache);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
free_percpu(md_dst);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(metadata_dst_free_percpu);
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#include <linux/timer.h>
|
#include <linux/timer.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <asm/unaligned.h>
|
#include <asm/unaligned.h>
|
||||||
|
#include <asm/cmpxchg.h>
|
||||||
#include <linux/filter.h>
|
#include <linux/filter.h>
|
||||||
#include <linux/ratelimit.h>
|
#include <linux/ratelimit.h>
|
||||||
#include <linux/seccomp.h>
|
#include <linux/seccomp.h>
|
||||||
|
@ -2987,14 +2988,15 @@ static const struct bpf_func_proto *
|
||||||
bpf_get_skb_set_tunnel_proto(enum bpf_func_id which)
|
bpf_get_skb_set_tunnel_proto(enum bpf_func_id which)
|
||||||
{
|
{
|
||||||
if (!md_dst) {
|
if (!md_dst) {
|
||||||
/* Race is not possible, since it's called from verifier
|
struct metadata_dst __percpu *tmp;
|
||||||
* that is holding verifier mutex.
|
|
||||||
*/
|
tmp = metadata_dst_alloc_percpu(IP_TUNNEL_OPTS_MAX,
|
||||||
md_dst = metadata_dst_alloc_percpu(IP_TUNNEL_OPTS_MAX,
|
|
||||||
METADATA_IP_TUNNEL,
|
METADATA_IP_TUNNEL,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!md_dst)
|
if (!tmp)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
if (cmpxchg(&md_dst, NULL, tmp))
|
||||||
|
metadata_dst_free_percpu(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (which) {
|
switch (which) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue