From cb7386d37eae20141cbc292a883e5e358cb5a929 Mon Sep 17 00:00:00 2001 From: Brenden Blanco Date: Wed, 20 Jul 2016 17:22:33 -0700 Subject: [PATCH 1/3] net/mlx4_en: use READ_ONCE when freeing xdp_prog For consistency, and in order to hint at the synchronous nature of the xdp_prog field, use READ_ONCE in the destroy path of the ring. All occurrences should now use either READ_ONCE or xchg. Signed-off-by: Brenden Blanco Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_rx.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c index 11d88c817137..a02dec6fb256 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c @@ -535,9 +535,11 @@ void mlx4_en_destroy_rx_ring(struct mlx4_en_priv *priv, { struct mlx4_en_dev *mdev = priv->mdev; struct mlx4_en_rx_ring *ring = *pring; + struct bpf_prog *old_prog; - if (ring->xdp_prog) - bpf_prog_put(ring->xdp_prog); + old_prog = READ_ONCE(ring->xdp_prog); + if (old_prog) + bpf_prog_put(old_prog); mlx4_free_hwq_res(mdev->dev, &ring->wqres, size * stride + TXBB_SIZE); vfree(ring->rx_info); ring->rx_info = NULL; From 262d8625045e0c81b7859ecd192e9811710f19da Mon Sep 17 00:00:00 2001 From: Brenden Blanco Date: Wed, 20 Jul 2016 17:22:34 -0700 Subject: [PATCH 2/3] rtnl: protect do_setlink from IFLA_XDP_ATTACHED The IFLA_XDP_ATTACHED nested attribute is meant for read-only, and while do_setlink properly ignores it, it should be more paranoid and reject commands that try to set it. Signed-off-by: Brenden Blanco Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller --- net/core/rtnetlink.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index eba2b8260dbd..189cc78c77eb 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -2109,6 +2109,10 @@ static int do_setlink(const struct sk_buff *skb, if (err < 0) goto errout; + if (xdp[IFLA_XDP_ATTACHED]) { + err = -EINVAL; + goto errout; + } if (xdp[IFLA_XDP_FD]) { err = dev_change_xdp_fd(dev, nla_get_s32(xdp[IFLA_XDP_FD])); From d9094bda5c985d1f9da66e9e3fd6323b49dee44d Mon Sep 17 00:00:00 2001 From: Brenden Blanco Date: Wed, 20 Jul 2016 17:22:35 -0700 Subject: [PATCH 3/3] bpf: make xdp sample variable names more meaningful The naming choice of index is not terribly descriptive, and dropcnt is in fact incorrect for xdp2. Pick better names for these: ipproto and rxcnt. Signed-off-by: Brenden Blanco Acked-by: Alexei Starovoitov Signed-off-by: David S. Miller --- samples/bpf/xdp1_kern.c | 12 ++++++------ samples/bpf/xdp2_kern.c | 14 +++++++------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/samples/bpf/xdp1_kern.c b/samples/bpf/xdp1_kern.c index e7dd8ac40d12..219742106bfd 100644 --- a/samples/bpf/xdp1_kern.c +++ b/samples/bpf/xdp1_kern.c @@ -14,7 +14,7 @@ #include #include "bpf_helpers.h" -struct bpf_map_def SEC("maps") dropcnt = { +struct bpf_map_def SEC("maps") rxcnt = { .type = BPF_MAP_TYPE_PERCPU_ARRAY, .key_size = sizeof(u32), .value_size = sizeof(long), @@ -49,7 +49,7 @@ int xdp_prog1(struct xdp_md *ctx) long *value; u16 h_proto; u64 nh_off; - u32 index; + u32 ipproto; nh_off = sizeof(*eth); if (data + nh_off > data_end) @@ -77,13 +77,13 @@ int xdp_prog1(struct xdp_md *ctx) } if (h_proto == htons(ETH_P_IP)) - index = parse_ipv4(data, nh_off, data_end); + ipproto = parse_ipv4(data, nh_off, data_end); else if (h_proto == htons(ETH_P_IPV6)) - index = parse_ipv6(data, nh_off, data_end); + ipproto = parse_ipv6(data, nh_off, data_end); else - index = 0; + ipproto = 0; - value = bpf_map_lookup_elem(&dropcnt, &index); + value = bpf_map_lookup_elem(&rxcnt, &ipproto); if (value) *value += 1; diff --git a/samples/bpf/xdp2_kern.c b/samples/bpf/xdp2_kern.c index 38fe7e1d0db4..e01288867d15 100644 --- a/samples/bpf/xdp2_kern.c +++ b/samples/bpf/xdp2_kern.c @@ -14,7 +14,7 @@ #include #include "bpf_helpers.h" -struct bpf_map_def SEC("maps") dropcnt = { +struct bpf_map_def SEC("maps") rxcnt = { .type = BPF_MAP_TYPE_PERCPU_ARRAY, .key_size = sizeof(u32), .value_size = sizeof(long), @@ -65,7 +65,7 @@ int xdp_prog1(struct xdp_md *ctx) long *value; u16 h_proto; u64 nh_off; - u32 index; + u32 ipproto; nh_off = sizeof(*eth); if (data + nh_off > data_end) @@ -93,17 +93,17 @@ int xdp_prog1(struct xdp_md *ctx) } if (h_proto == htons(ETH_P_IP)) - index = parse_ipv4(data, nh_off, data_end); + ipproto = parse_ipv4(data, nh_off, data_end); else if (h_proto == htons(ETH_P_IPV6)) - index = parse_ipv6(data, nh_off, data_end); + ipproto = parse_ipv6(data, nh_off, data_end); else - index = 0; + ipproto = 0; - value = bpf_map_lookup_elem(&dropcnt, &index); + value = bpf_map_lookup_elem(&rxcnt, &ipproto); if (value) *value += 1; - if (index == 17) { + if (ipproto == IPPROTO_UDP) { swap_src_dst_mac(data); rc = XDP_TX; }