summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/trace/events/xdp.h4
-rw-r--r--net/core/filter.c38
2 files changed, 28 insertions, 14 deletions
diff --git a/include/trace/events/xdp.h b/include/trace/events/xdp.h
index 862575ac8da9..4e16c43fba10 100644
--- a/include/trace/events/xdp.h
+++ b/include/trace/events/xdp.h
@@ -138,11 +138,11 @@ DEFINE_EVENT_PRINT(xdp_redirect_template, xdp_redirect_map_err,
#define _trace_xdp_redirect_map(dev, xdp, fwd, map, idx) \
trace_xdp_redirect_map(dev, xdp, fwd ? fwd->ifindex : 0, \
- 0, map, idx);
+ 0, map, idx)
#define _trace_xdp_redirect_map_err(dev, xdp, fwd, map, idx, err) \
trace_xdp_redirect_map_err(dev, xdp, fwd ? fwd->ifindex : 0, \
- err, map, idx);
+ err, map, idx)
#endif /* _TRACE_XDP_H */
diff --git a/net/core/filter.c b/net/core/filter.c
index 3a50a9b021e2..24dd33dd9f04 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -2506,21 +2506,19 @@ static int xdp_do_redirect_map(struct net_device *dev, struct xdp_buff *xdp,
struct redirect_info *ri = this_cpu_ptr(&redirect_info);
const struct bpf_prog *map_owner = ri->map_owner;
struct bpf_map *map = ri->map;
+ struct net_device *fwd = NULL;
u32 index = ri->ifindex;
- struct net_device *fwd;
int err;
ri->ifindex = 0;
ri->map = NULL;
ri->map_owner = NULL;
- /* This is really only caused by a deliberately crappy
- * BPF program, normally we would never hit that case,
- * so no need to inform someone via tracepoints either,
- * just bail out.
- */
- if (unlikely(map_owner != xdp_prog))
- return -EINVAL;
+ if (unlikely(map_owner != xdp_prog)) {
+ err = -EFAULT;
+ map = NULL;
+ goto err;
+ }
fwd = __dev_map_lookup_elem(map, index);
if (!fwd) {
@@ -2576,13 +2574,27 @@ int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb,
struct bpf_prog *xdp_prog)
{
struct redirect_info *ri = this_cpu_ptr(&redirect_info);
+ const struct bpf_prog *map_owner = ri->map_owner;
+ struct bpf_map *map = ri->map;
+ struct net_device *fwd = NULL;
u32 index = ri->ifindex;
- struct net_device *fwd;
unsigned int len;
int err = 0;
- fwd = dev_get_by_index_rcu(dev_net(dev), index);
ri->ifindex = 0;
+ ri->map = NULL;
+ ri->map_owner = NULL;
+
+ if (map) {
+ if (unlikely(map_owner != xdp_prog)) {
+ err = -EFAULT;
+ map = NULL;
+ goto err;
+ }
+ fwd = __dev_map_lookup_elem(map, index);
+ } else {
+ fwd = dev_get_by_index_rcu(dev_net(dev), index);
+ }
if (unlikely(!fwd)) {
err = -EINVAL;
goto err;
@@ -2600,10 +2612,12 @@ int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb,
}
skb->dev = fwd;
- _trace_xdp_redirect(dev, xdp_prog, index);
+ map ? _trace_xdp_redirect_map(dev, xdp_prog, fwd, map, index)
+ : _trace_xdp_redirect(dev, xdp_prog, index);
return 0;
err:
- _trace_xdp_redirect_err(dev, xdp_prog, index, err);
+ map ? _trace_xdp_redirect_map_err(dev, xdp_prog, fwd, map, index, err)
+ : _trace_xdp_redirect_err(dev, xdp_prog, index, err);
return err;
}
EXPORT_SYMBOL_GPL(xdp_do_generic_redirect);