Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -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,
				       const struct bpf_insn *patch, u32 len);

static inline int __xdp_generic_ok_fwd_dev(struct sk_buff *skb,
					   struct net_device *fwd)
static inline int xdp_ok_fwd_dev(const struct net_device *fwd,
				 unsigned int pktlen)
{
	unsigned int len;

@@ -774,7 +774,7 @@ static inline int __xdp_generic_ok_fwd_dev(struct sk_buff *skb,
		return -ENETDOWN;

	len = fwd->mtu + fwd->hard_header_len + VLAN_HLEN;
	if (skb->len > len)
	if (pktlen > len)
		return -EMSGSIZE;

	return 0;
+6 −1
Original line number Diff line number Diff line
@@ -334,10 +334,15 @@ int dev_map_enqueue(struct bpf_dtab_netdev *dst, struct xdp_buff *xdp,
{
	struct net_device *dev = dst->dev;
	struct xdp_frame *xdpf;
	int err;

	if (!dev->netdev_ops->ndo_xdp_xmit)
		return -EOPNOTSUPP;

	err = xdp_ok_fwd_dev(dev, xdp->data_end - xdp->data);
	if (unlikely(err))
		return err;

	xdpf = convert_to_xdp_frame(xdp);
	if (unlikely(!xdpf))
		return -EOVERFLOW;
@@ -350,7 +355,7 @@ int dev_map_generic_redirect(struct bpf_dtab_netdev *dst, struct sk_buff *skb,
{
	int err;

	err = __xdp_generic_ok_fwd_dev(skb, dst->dev);
	err = xdp_ok_fwd_dev(dst->dev, skb->len);
	if (unlikely(err))
		return err;
	skb->dev = dst->dev;
+7 −2
Original line number Diff line number Diff line
@@ -3128,12 +3128,16 @@ static int __bpf_tx_xdp(struct net_device *dev,
			u32 index)
{
	struct xdp_frame *xdpf;
	int sent;
	int err, sent;

	if (!dev->netdev_ops->ndo_xdp_xmit) {
		return -EOPNOTSUPP;
	}

	err = xdp_ok_fwd_dev(dev, xdp->data_end - xdp->data);
	if (unlikely(err))
		return err;

	xdpf = convert_to_xdp_frame(xdp);
	if (unlikely(!xdpf))
		return -EOVERFLOW;
@@ -3367,7 +3371,8 @@ int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb,
		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;

	skb->dev = fwd;