On 01/17/2019 07:32 PM, Martin Lau wrote: > On Thu, Jan 17, 2019 at 04:34:45PM +0100, Daniel Borkmann wrote: >> During review I noticed that inner meta map setup for map in >> map is buggy in that it does not propagate all needed data >> from the reference map which the verifier is later accessing. >> >> In particular one such case is index masking to prevent out of >> bounds access under speculative execution due to missing the >> map's unpriv_array/index_mask field propagation. Fix this such >> that the verifier is generating the correct code for inlined >> lookups in case of unpriviledged use. >> >> Before patch (test_verifier's 'map in map access' dump): >> >> # bpftool prog dump xla id 3 >> 0: (62) *(u32 *)(r10 -4) = 0 >> 1: (bf) r2 = r10 >> 2: (07) r2 += -4 >> 3: (18) r1 = map[id:4] >> 5: (07) r1 += 272 | >> 6: (61) r0 = *(u32 *)(r2 +0) | >> 7: (35) if r0 >= 0x1 goto pc+6 | Inlined map in map lookup >> 8: (54) (u32) r0 &= (u32) 0 | with index masking for >> 9: (67) r0 <<= 3 | map->unpriv_array. >> 10: (0f) r0 += r1 | >> 11: (79) r0 = *(u64 *)(r0 +0) | >> 12: (15) if r0 == 0x0 goto pc+1 | >> 13: (05) goto pc+1 | >> 14: (b7) r0 = 0 | >> 15: (15) if r0 == 0x0 goto pc+11 >> 16: (62) *(u32 *)(r10 -4) = 0 >> 17: (bf) r2 = r10 >> 18: (07) r2 += -4 >> 19: (bf) r1 = r0 >> 20: (07) r1 += 272 | >> 21: (61) r0 = *(u32 *)(r2 +0) | Index masking missing (!) >> 22: (35) if r0 >= 0x1 goto pc+3 | for inner map despite >> 23: (67) r0 <<= 3 | map->unpriv_array set. >> 24: (0f) r0 += r1 | >> 25: (05) goto pc+1 | >> 26: (b7) r0 = 0 | >> 27: (b7) r0 = 0 >> 28: (95) exit >> >> After patch: >> >> # bpftool prog dump xla id 1 >> 0: (62) *(u32 *)(r10 -4) = 0 >> 1: (bf) r2 = r10 >> 2: (07) r2 += -4 >> 3: (18) r1 = map[id:2] >> 5: (07) r1 += 272 | >> 6: (61) r0 = *(u32 *)(r2 +0) | >> 7: (35) if r0 >= 0x1 goto pc+6 | Same inlined map in map lookup >> 8: (54) (u32) r0 &= (u32) 0 | with index masking due to >> 9: (67) r0 <<= 3 | map->unpriv_array. >> 10: (0f) r0 += r1 | >> 11: (79) r0 = *(u64 *)(r0 +0) | >> 12: (15) if r0 == 0x0 goto pc+1 | >> 13: (05) goto pc+1 | >> 14: (b7) r0 = 0 | >> 15: (15) if r0 == 0x0 goto pc+12 >> 16: (62) *(u32 *)(r10 -4) = 0 >> 17: (bf) r2 = r10 >> 18: (07) r2 += -4 >> 19: (bf) r1 = r0 >> 20: (07) r1 += 272 | >> 21: (61) r0 = *(u32 *)(r2 +0) | >> 22: (35) if r0 >= 0x1 goto pc+4 | Now fixed inlined inner map >> 23: (54) (u32) r0 &= (u32) 0 | lookup with proper index masking >> 24: (67) r0 <<= 3 | for map->unpriv_array. >> 25: (0f) r0 += r1 | >> 26: (05) goto pc+1 | >> 27: (b7) r0 = 0 | >> 28: (b7) r0 = 0 >> 29: (95) exit >> >> Fixes: b2157399cc98 ("bpf: prevent out-of-bounds speculation") >> Signed-off-by: Daniel Borkmann <dan...@iogearbox.net> > The fix looks great. Thanks for the fix! > In the future if there is another exception other than > array_map, a inner_map->ops->map_meta_alloc() can be introduced?
Yeah, probably makes sense if there will be more users in future. > Acked-by: Martin KaFai Lau <ka...@fb.com>