Skip to content

Commit 7c30013

Browse files
borkmanndavem330
authored andcommitted
bpf: fix ri->map_owner pointer on bpf_prog_realloc
Commit 109980b ("bpf: don't select potentially stale ri->map from buggy xdp progs") passed the pointer to the prog itself to be loaded into r4 prior on bpf_redirect_map() helper call, so that we can store the owner into ri->map_owner out of the helper. Issue with that is that the actual address of the prog is still subject to change when subsequent rewrites occur that require slow path in bpf_prog_realloc() to alloc more memory, e.g. from patching inlining helper functions or constant blinding. Thus, we really need to take prog->aux as the address we're holding, which also works with prog clones as they share the same aux object. Instead of then fetching aux->prog during runtime, which could potentially incur cache misses due to false sharing, we are going to just use aux for comparison on the map owner. This will also keep the patchlet of the same size, and later check in xdp_map_invalid() only accesses read-only aux pointer from the prog, it's also in the same cacheline already from prior access when calling bpf_func. Fixes: 109980b ("bpf: don't select potentially stale ri->map from buggy xdp progs") Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent f559560 commit 7c30013

File tree

2 files changed

+21
-10
lines changed

2 files changed

+21
-10
lines changed

kernel/bpf/verifier.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4205,7 +4205,12 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env)
42054205
}
42064206

42074207
if (insn->imm == BPF_FUNC_redirect_map) {
4208-
u64 addr = (unsigned long)prog;
4208+
/* Note, we cannot use prog directly as imm as subsequent
4209+
* rewrites would still change the prog pointer. The only
4210+
* stable address we can use is aux, which also works with
4211+
* prog clones during blinding.
4212+
*/
4213+
u64 addr = (unsigned long)prog->aux;
42094214
struct bpf_insn r4_ld[] = {
42104215
BPF_LD_IMM64(BPF_REG_4, addr),
42114216
*insn,

net/core/filter.c

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1794,7 +1794,7 @@ struct redirect_info {
17941794
u32 flags;
17951795
struct bpf_map *map;
17961796
struct bpf_map *map_to_flush;
1797-
const struct bpf_prog *map_owner;
1797+
unsigned long map_owner;
17981798
};
17991799

18001800
static DEFINE_PER_CPU(struct redirect_info, redirect_info);
@@ -2500,21 +2500,27 @@ void xdp_do_flush_map(void)
25002500
}
25012501
EXPORT_SYMBOL_GPL(xdp_do_flush_map);
25022502

2503+
static inline bool xdp_map_invalid(const struct bpf_prog *xdp_prog,
2504+
unsigned long aux)
2505+
{
2506+
return (unsigned long)xdp_prog->aux != aux;
2507+
}
2508+
25032509
static int xdp_do_redirect_map(struct net_device *dev, struct xdp_buff *xdp,
25042510
struct bpf_prog *xdp_prog)
25052511
{
25062512
struct redirect_info *ri = this_cpu_ptr(&redirect_info);
2507-
const struct bpf_prog *map_owner = ri->map_owner;
2513+
unsigned long map_owner = ri->map_owner;
25082514
struct bpf_map *map = ri->map;
25092515
struct net_device *fwd = NULL;
25102516
u32 index = ri->ifindex;
25112517
int err;
25122518

25132519
ri->ifindex = 0;
25142520
ri->map = NULL;
2515-
ri->map_owner = NULL;
2521+
ri->map_owner = 0;
25162522

2517-
if (unlikely(map_owner != xdp_prog)) {
2523+
if (unlikely(xdp_map_invalid(xdp_prog, map_owner))) {
25182524
err = -EFAULT;
25192525
map = NULL;
25202526
goto err;
@@ -2574,7 +2580,7 @@ int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb,
25742580
struct bpf_prog *xdp_prog)
25752581
{
25762582
struct redirect_info *ri = this_cpu_ptr(&redirect_info);
2577-
const struct bpf_prog *map_owner = ri->map_owner;
2583+
unsigned long map_owner = ri->map_owner;
25782584
struct bpf_map *map = ri->map;
25792585
struct net_device *fwd = NULL;
25802586
u32 index = ri->ifindex;
@@ -2583,10 +2589,10 @@ int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb,
25832589

25842590
ri->ifindex = 0;
25852591
ri->map = NULL;
2586-
ri->map_owner = NULL;
2592+
ri->map_owner = 0;
25872593

25882594
if (map) {
2589-
if (unlikely(map_owner != xdp_prog)) {
2595+
if (unlikely(xdp_map_invalid(xdp_prog, map_owner))) {
25902596
err = -EFAULT;
25912597
map = NULL;
25922598
goto err;
@@ -2632,7 +2638,7 @@ BPF_CALL_2(bpf_xdp_redirect, u32, ifindex, u64, flags)
26322638
ri->ifindex = ifindex;
26332639
ri->flags = flags;
26342640
ri->map = NULL;
2635-
ri->map_owner = NULL;
2641+
ri->map_owner = 0;
26362642

26372643
return XDP_REDIRECT;
26382644
}
@@ -2646,7 +2652,7 @@ static const struct bpf_func_proto bpf_xdp_redirect_proto = {
26462652
};
26472653

26482654
BPF_CALL_4(bpf_xdp_redirect_map, struct bpf_map *, map, u32, ifindex, u64, flags,
2649-
const struct bpf_prog *, map_owner)
2655+
unsigned long, map_owner)
26502656
{
26512657
struct redirect_info *ri = this_cpu_ptr(&redirect_info);
26522658

0 commit comments

Comments
 (0)