]>
Commit | Line | Data |
---|---|---|
37554d48 SL |
1 | From 0f2c873122abd31fc364dd9aef452ae94c80d50b Mon Sep 17 00:00:00 2001 |
2 | From: Krzesimir Nowak <krzesimir@kinvolk.io> | |
3 | Date: Wed, 8 May 2019 18:08:58 +0200 | |
4 | Subject: bpf: fix undefined behavior in narrow load handling | |
5 | MIME-Version: 1.0 | |
6 | Content-Type: text/plain; charset=UTF-8 | |
7 | Content-Transfer-Encoding: 8bit | |
8 | ||
9 | [ Upstream commit e2f7fc0ac6957cabff4cecf6c721979b571af208 ] | |
10 | ||
11 | Commit 31fd85816dbe ("bpf: permits narrower load from bpf program | |
12 | context fields") made the verifier add AND instructions to clear the | |
13 | unwanted bits with a mask when doing a narrow load. The mask is | |
14 | computed with | |
15 | ||
16 | (1 << size * 8) - 1 | |
17 | ||
18 | where "size" is the size of the narrow load. When doing a 4 byte load | |
19 | of a an 8 byte field the verifier shifts the literal 1 by 32 places to | |
20 | the left. This results in an overflow of a signed integer, which is an | |
21 | undefined behavior. Typically, the computed mask was zero, so the | |
22 | result of the narrow load ended up being zero too. | |
23 | ||
24 | Cast the literal to long long to avoid overflows. Note that narrow | |
25 | load of the 4 byte fields does not have the undefined behavior, | |
26 | because the load size can only be either 1 or 2 bytes, so shifting 1 | |
27 | by 8 or 16 places will not overflow it. And reading 4 bytes would not | |
28 | be a narrow load of a 4 bytes field. | |
29 | ||
30 | Fixes: 31fd85816dbe ("bpf: permits narrower load from bpf program context fields") | |
31 | Reviewed-by: Alban Crequy <alban@kinvolk.io> | |
32 | Reviewed-by: Iago López Galeiras <iago@kinvolk.io> | |
33 | Signed-off-by: Krzesimir Nowak <krzesimir@kinvolk.io> | |
34 | Cc: Yonghong Song <yhs@fb.com> | |
35 | Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> | |
36 | Signed-off-by: Sasha Levin <sashal@kernel.org> | |
37 | --- | |
38 | kernel/bpf/verifier.c | 2 +- | |
39 | 1 file changed, 1 insertion(+), 1 deletion(-) | |
40 | ||
41 | diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c | |
42 | index acc2305ad895..d3580a68dbef 100644 | |
43 | --- a/kernel/bpf/verifier.c | |
44 | +++ b/kernel/bpf/verifier.c | |
45 | @@ -5743,7 +5743,7 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env) | |
46 | insn->dst_reg, | |
47 | shift); | |
48 | insn_buf[cnt++] = BPF_ALU64_IMM(BPF_AND, insn->dst_reg, | |
49 | - (1 << size * 8) - 1); | |
50 | + (1ULL << size * 8) - 1); | |
51 | } | |
52 | } | |
53 | ||
54 | -- | |
55 | 2.20.1 | |
56 |