Skip to content

Commit 6d5fc19

Browse files
Toshiaki Makitaborkmann
authored andcommitted
xdp: Fix handling of devmap in generic XDP
Commit 67f29e0 ("bpf: devmap introduce dev_map_enqueue") changed the return value type of __devmap_lookup_elem() from struct net_device * to struct bpf_dtab_netdev * but forgot to modify generic XDP code accordingly. Thus generic XDP incorrectly used struct bpf_dtab_netdev where struct net_device is expected, then skb->dev was set to invalid value. v2: - Fix compiler warning without CONFIG_BPF_SYSCALL. Fixes: 67f29e0 ("bpf: devmap introduce dev_map_enqueue") Signed-off-by: Toshiaki Makita <[email protected]> Acked-by: Yonghong Song <[email protected]> Acked-by: Jesper Dangaard Brouer <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]>
1 parent b5518c7 commit 6d5fc19

File tree

4 files changed

+46
-17
lines changed

4 files changed

+46
-17
lines changed

include/linux/bpf.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,12 +488,15 @@ void bpf_patch_call_args(struct bpf_insn *insn, u32 stack_depth);
488488

489489
/* Map specifics */
490490
struct xdp_buff;
491+
struct sk_buff;
491492

492493
struct bpf_dtab_netdev *__dev_map_lookup_elem(struct bpf_map *map, u32 key);
493494
void __dev_map_insert_ctx(struct bpf_map *map, u32 index);
494495
void __dev_map_flush(struct bpf_map *map);
495496
int dev_map_enqueue(struct bpf_dtab_netdev *dst, struct xdp_buff *xdp,
496497
struct net_device *dev_rx);
498+
int dev_map_generic_redirect(struct bpf_dtab_netdev *dst, struct sk_buff *skb,
499+
struct bpf_prog *xdp_prog);
497500

498501
struct bpf_cpu_map_entry *__cpu_map_lookup_elem(struct bpf_map *map, u32 key);
499502
void __cpu_map_insert_ctx(struct bpf_map *map, u32 index);
@@ -586,6 +589,15 @@ int dev_map_enqueue(struct bpf_dtab_netdev *dst, struct xdp_buff *xdp,
586589
return 0;
587590
}
588591

592+
struct sk_buff;
593+
594+
static inline int dev_map_generic_redirect(struct bpf_dtab_netdev *dst,
595+
struct sk_buff *skb,
596+
struct bpf_prog *xdp_prog)
597+
{
598+
return 0;
599+
}
600+
589601
static inline
590602
struct bpf_cpu_map_entry *__cpu_map_lookup_elem(struct bpf_map *map, u32 key)
591603
{

include/linux/filter.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <linux/cryptohash.h>
2020
#include <linux/set_memory.h>
2121
#include <linux/kallsyms.h>
22+
#include <linux/if_vlan.h>
2223

2324
#include <net/sch_generic.h>
2425

@@ -802,6 +803,21 @@ static inline bool bpf_dump_raw_ok(void)
802803
struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off,
803804
const struct bpf_insn *patch, u32 len);
804805

806+
static inline int __xdp_generic_ok_fwd_dev(struct sk_buff *skb,
807+
struct net_device *fwd)
808+
{
809+
unsigned int len;
810+
811+
if (unlikely(!(fwd->flags & IFF_UP)))
812+
return -ENETDOWN;
813+
814+
len = fwd->mtu + fwd->hard_header_len + VLAN_HLEN;
815+
if (skb->len > len)
816+
return -EMSGSIZE;
817+
818+
return 0;
819+
}
820+
805821
/* The pair of xdp_do_redirect and xdp_do_flush_map MUST be called in the
806822
* same cpu context. Further for best results no more than a single map
807823
* for the do_redirect/do_flush pair should be used. This limitation is

kernel/bpf/devmap.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,20 @@ int dev_map_enqueue(struct bpf_dtab_netdev *dst, struct xdp_buff *xdp,
345345
return bq_enqueue(dst, xdpf, dev_rx);
346346
}
347347

348+
int dev_map_generic_redirect(struct bpf_dtab_netdev *dst, struct sk_buff *skb,
349+
struct bpf_prog *xdp_prog)
350+
{
351+
int err;
352+
353+
err = __xdp_generic_ok_fwd_dev(skb, dst->dev);
354+
if (unlikely(err))
355+
return err;
356+
skb->dev = dst->dev;
357+
generic_xdp_tx(skb, xdp_prog);
358+
359+
return 0;
360+
}
361+
348362
static void *dev_map_lookup_elem(struct bpf_map *map, void *key)
349363
{
350364
struct bpf_dtab_netdev *obj = __dev_map_lookup_elem(map, *(u32 *)key);

net/core/filter.c

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3214,20 +3214,6 @@ int xdp_do_redirect(struct net_device *dev, struct xdp_buff *xdp,
32143214
}
32153215
EXPORT_SYMBOL_GPL(xdp_do_redirect);
32163216

3217-
static int __xdp_generic_ok_fwd_dev(struct sk_buff *skb, struct net_device *fwd)
3218-
{
3219-
unsigned int len;
3220-
3221-
if (unlikely(!(fwd->flags & IFF_UP)))
3222-
return -ENETDOWN;
3223-
3224-
len = fwd->mtu + fwd->hard_header_len + VLAN_HLEN;
3225-
if (skb->len > len)
3226-
return -EMSGSIZE;
3227-
3228-
return 0;
3229-
}
3230-
32313217
static int xdp_do_generic_redirect_map(struct net_device *dev,
32323218
struct sk_buff *skb,
32333219
struct xdp_buff *xdp,
@@ -3256,10 +3242,11 @@ static int xdp_do_generic_redirect_map(struct net_device *dev,
32563242
}
32573243

32583244
if (map->map_type == BPF_MAP_TYPE_DEVMAP) {
3259-
if (unlikely((err = __xdp_generic_ok_fwd_dev(skb, fwd))))
3245+
struct bpf_dtab_netdev *dst = fwd;
3246+
3247+
err = dev_map_generic_redirect(dst, skb, xdp_prog);
3248+
if (unlikely(err))
32603249
goto err;
3261-
skb->dev = fwd;
3262-
generic_xdp_tx(skb, xdp_prog);
32633250
} else if (map->map_type == BPF_MAP_TYPE_XSKMAP) {
32643251
struct xdp_sock *xs = fwd;
32653252

0 commit comments

Comments
 (0)