Re: [PATCH bpf] xdp: XDP_REDIRECT should check IFF_UP and MTU

2018-07-07 Thread Alexei Starovoitov
On Fri, Jul 06, 2018 at 11:49:00AM +0900, Toshiaki Makita wrote:
> 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: 814abfabef3c ("xdp: add bpf_redirect helper function")
> Signed-off-by: Toshiaki Makita 

Applied, Thanks



[PATCH bpf] xdp: XDP_REDIRECT should check IFF_UP and MTU

2018-07-05 Thread Toshiaki Makita
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: 814abfabef3c ("xdp: add bpf_redirect helper function")
Signed-off-by: Toshiaki Makita 
---
 include/linux/filter.h | 6 +++---
 kernel/bpf/devmap.c| 7 ++-
 net/core/filter.c  | 9 +++--
 3 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/include/linux/filter.h b/include/linux/filter.h
index 300baad..c73dd73 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -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;
diff --git a/kernel/bpf/devmap.c b/kernel/bpf/devmap.c
index 642c97f..d361fc1 100644
--- a/kernel/bpf/devmap.c
+++ b/kernel/bpf/devmap.c
@@ -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;
diff --git a/net/core/filter.c b/net/core/filter.c
index 0ca6907..2303f73 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -3046,12 +3046,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;
@@ -3285,7 +3289,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;
-- 
1.8.3.1