Commit d8d7218a authored by Toshiaki Makita's avatar Toshiaki Makita Committed by Alexei Starovoitov

xdp: XDP_REDIRECT should check IFF_UP and MTU

Otherwise we end up with attempting to send packets from down devices
or to send oversized packets, which may cause unexpected driver/device
behaviour. Generic XDP has already done this check, so reuse the logic
in native XDP.

Fixes: 814abfab ("xdp: add bpf_redirect helper function")
Signed-off-by: default avatarToshiaki Makita <makita.toshiaki@lab.ntt.co.jp>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 4fb126cb
...@@ -765,8 +765,8 @@ static inline bool bpf_dump_raw_ok(void) ...@@ -765,8 +765,8 @@ static inline bool bpf_dump_raw_ok(void)
struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off, struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off,
const struct bpf_insn *patch, u32 len); const struct bpf_insn *patch, u32 len);
static inline int __xdp_generic_ok_fwd_dev(struct sk_buff *skb, static inline int xdp_ok_fwd_dev(const struct net_device *fwd,
struct net_device *fwd) unsigned int pktlen)
{ {
unsigned int len; unsigned int len;
...@@ -774,7 +774,7 @@ static inline int __xdp_generic_ok_fwd_dev(struct sk_buff *skb, ...@@ -774,7 +774,7 @@ static inline int __xdp_generic_ok_fwd_dev(struct sk_buff *skb,
return -ENETDOWN; return -ENETDOWN;
len = fwd->mtu + fwd->hard_header_len + VLAN_HLEN; len = fwd->mtu + fwd->hard_header_len + VLAN_HLEN;
if (skb->len > len) if (pktlen > len)
return -EMSGSIZE; return -EMSGSIZE;
return 0; return 0;
......
...@@ -334,10 +334,15 @@ int dev_map_enqueue(struct bpf_dtab_netdev *dst, struct xdp_buff *xdp, ...@@ -334,10 +334,15 @@ int dev_map_enqueue(struct bpf_dtab_netdev *dst, struct xdp_buff *xdp,
{ {
struct net_device *dev = dst->dev; struct net_device *dev = dst->dev;
struct xdp_frame *xdpf; struct xdp_frame *xdpf;
int err;
if (!dev->netdev_ops->ndo_xdp_xmit) if (!dev->netdev_ops->ndo_xdp_xmit)
return -EOPNOTSUPP; return -EOPNOTSUPP;
err = xdp_ok_fwd_dev(dev, xdp->data_end - xdp->data);
if (unlikely(err))
return err;
xdpf = convert_to_xdp_frame(xdp); xdpf = convert_to_xdp_frame(xdp);
if (unlikely(!xdpf)) if (unlikely(!xdpf))
return -EOVERFLOW; return -EOVERFLOW;
...@@ -350,7 +355,7 @@ int dev_map_generic_redirect(struct bpf_dtab_netdev *dst, struct sk_buff *skb, ...@@ -350,7 +355,7 @@ int dev_map_generic_redirect(struct bpf_dtab_netdev *dst, struct sk_buff *skb,
{ {
int err; int err;
err = __xdp_generic_ok_fwd_dev(skb, dst->dev); err = xdp_ok_fwd_dev(dst->dev, skb->len);
if (unlikely(err)) if (unlikely(err))
return err; return err;
skb->dev = dst->dev; skb->dev = dst->dev;
......
...@@ -3128,12 +3128,16 @@ static int __bpf_tx_xdp(struct net_device *dev, ...@@ -3128,12 +3128,16 @@ static int __bpf_tx_xdp(struct net_device *dev,
u32 index) u32 index)
{ {
struct xdp_frame *xdpf; struct xdp_frame *xdpf;
int sent; int err, sent;
if (!dev->netdev_ops->ndo_xdp_xmit) { if (!dev->netdev_ops->ndo_xdp_xmit) {
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
err = xdp_ok_fwd_dev(dev, xdp->data_end - xdp->data);
if (unlikely(err))
return err;
xdpf = convert_to_xdp_frame(xdp); xdpf = convert_to_xdp_frame(xdp);
if (unlikely(!xdpf)) if (unlikely(!xdpf))
return -EOVERFLOW; return -EOVERFLOW;
...@@ -3367,7 +3371,8 @@ int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb, ...@@ -3367,7 +3371,8 @@ int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb,
goto err; goto err;
} }
if (unlikely((err = __xdp_generic_ok_fwd_dev(skb, fwd)))) err = xdp_ok_fwd_dev(fwd, skb->len);
if (unlikely(err))
goto err; goto err;
skb->dev = fwd; skb->dev = fwd;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment