diff options
author | Ilya Leoshkevich <iii@linux.ibm.com> | 2019-10-28 08:29:02 -0400 |
---|---|---|
committer | Alexei Starovoitov <ast@kernel.org> | 2019-10-30 15:49:13 -0400 |
commit | 7541c87c9b7a7e07c84481f37f2c19063b44469b (patch) | |
tree | a1f47ae889424c14ebb736a51a075ac3ac2dd017 /tools/testing/selftests | |
parent | 050668c10047802a2b62cbf8db834c2c84042b87 (diff) |
bpf: Allow narrow loads of bpf_sysctl fields with offset > 0
"ctx:file_pos sysctl:read read ok narrow" works on s390 by accident: it
reads the wrong byte, which happens to have the expected value of 0.
Improve the test by seeking to the 4th byte and expecting 4 instead of
0.
This makes the latent problem apparent: the test attempts to read the
first byte of bpf_sysctl.file_pos, assuming this is the least-significant
byte, which is not the case on big-endian machines: a non-zero offset is
needed.
The point of the test is to verify narrow loads, so we cannot cheat our
way out by simply using BPF_W. The existence of the test means that such
loads have to be supported, most likely because llvm can generate them.
Fix the test by adding a big-endian variant, which uses an offset to
access the least-significant byte of bpf_sysctl.file_pos.
This reveals the final problem: verifier rejects accesses to bpf_sysctl
fields with offset > 0. Such accesses are already allowed for a wide
range of structs: __sk_buff, bpf_sock_addr and sk_msg_md to name a few.
Extend this support to bpf_sysctl by using bpf_ctx_range instead of
offsetof when matching field offsets.
Fixes: 7b146cebe30c ("bpf: Sysctl hook")
Fixes: e1550bfe0de4 ("bpf: Add file_pos field to bpf_sysctl ctx")
Fixes: 9a1027e52535 ("selftests/bpf: Test file_pos field in bpf_sysctl ctx")
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Andrey Ignatov <rdna@fb.com>
Acked-by: Andrii Nakryiko <andriin@fb.com>
Link: https://lore.kernel.org/bpf/20191028122902.9763-1-iii@linux.ibm.com
Diffstat (limited to 'tools/testing/selftests')
-rw-r--r-- | tools/testing/selftests/bpf/test_sysctl.c | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/tools/testing/selftests/bpf/test_sysctl.c b/tools/testing/selftests/bpf/test_sysctl.c index a320e3844b17..7c6e5b173f33 100644 --- a/tools/testing/selftests/bpf/test_sysctl.c +++ b/tools/testing/selftests/bpf/test_sysctl.c | |||
@@ -161,9 +161,14 @@ static struct sysctl_test tests[] = { | |||
161 | .descr = "ctx:file_pos sysctl:read read ok narrow", | 161 | .descr = "ctx:file_pos sysctl:read read ok narrow", |
162 | .insns = { | 162 | .insns = { |
163 | /* If (file_pos == X) */ | 163 | /* If (file_pos == X) */ |
164 | #if __BYTE_ORDER == __LITTLE_ENDIAN | ||
164 | BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_1, | 165 | BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_1, |
165 | offsetof(struct bpf_sysctl, file_pos)), | 166 | offsetof(struct bpf_sysctl, file_pos)), |
166 | BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0, 2), | 167 | #else |
168 | BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_1, | ||
169 | offsetof(struct bpf_sysctl, file_pos) + 3), | ||
170 | #endif | ||
171 | BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 4, 2), | ||
167 | 172 | ||
168 | /* return ALLOW; */ | 173 | /* return ALLOW; */ |
169 | BPF_MOV64_IMM(BPF_REG_0, 1), | 174 | BPF_MOV64_IMM(BPF_REG_0, 1), |
@@ -176,6 +181,7 @@ static struct sysctl_test tests[] = { | |||
176 | .attach_type = BPF_CGROUP_SYSCTL, | 181 | .attach_type = BPF_CGROUP_SYSCTL, |
177 | .sysctl = "kernel/ostype", | 182 | .sysctl = "kernel/ostype", |
178 | .open_flags = O_RDONLY, | 183 | .open_flags = O_RDONLY, |
184 | .seek = 4, | ||
179 | .result = SUCCESS, | 185 | .result = SUCCESS, |
180 | }, | 186 | }, |
181 | { | 187 | { |