Skip to content

Commit b78b34c

Browse files
author
Alexei Starovoitov
committed
Merge branch 'bpf: fix NULL dereference during extable search'
Krister Johansen says: ==================== Hi, Enclosed are a pair of patches for an oops that can occur if an exception is generated while a bpf subprogram is running. One of the bpf_prog_aux entries for the subprograms are missing an extable. This can lead to an exception that would otherwise be handled turning into a NULL pointer bug. These changes were tested via the verifier and progs selftests and no regressions were observed. Changes from v4: - Ensure that num_exentries is copied to prog->aux from func[0] (Feedback from Ilya Leoshkevich) Changes from v3: - Selftest style fixups (Feedback from Yonghong Song) - Selftest needs to assert that test bpf program executed (Feedback from Yonghong Song) - Selftest should combine open and load using open_and_load (Feedback from Yonghong Song) Changes from v2: - Insert only the main program's kallsyms (Feedback from Yonghong Song and Alexei Starovoitov) - Selftest should use ASSERT instead of CHECK (Feedback from Yonghong Song) - Selftest needs some cleanup (Feedback from Yonghong Song) - Switch patch order (Feedback from Alexei Starovoitov) Changes from v1: - Add a selftest (Feedback From Alexei Starovoitov) - Move to a 1-line verifier change instead of searching multiple extables ==================== Signed-off-by: Alexei Starovoitov <[email protected]>
2 parents ad96f1c + 84a62b4 commit b78b34c

File tree

3 files changed

+85
-2
lines changed

3 files changed

+85
-2
lines changed

kernel/bpf/verifier.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17217,9 +17217,10 @@ static int jit_subprogs(struct bpf_verifier_env *env)
1721717217
}
1721817218

1721917219
/* finally lock prog and jit images for all functions and
17220-
* populate kallsysm
17220+
* populate kallsysm. Begin at the first subprogram, since
17221+
* bpf_prog_load will add the kallsyms for the main program.
1722117222
*/
17222-
for (i = 0; i < env->subprog_cnt; i++) {
17223+
for (i = 1; i < env->subprog_cnt; i++) {
1722317224
bpf_prog_lock_ro(func[i]);
1722417225
bpf_prog_kallsyms_add(func[i]);
1722517226
}
@@ -17245,6 +17246,8 @@ static int jit_subprogs(struct bpf_verifier_env *env)
1724517246
prog->jited = 1;
1724617247
prog->bpf_func = func[0]->bpf_func;
1724717248
prog->jited_len = func[0]->jited_len;
17249+
prog->aux->extable = func[0]->aux->extable;
17250+
prog->aux->num_exentries = func[0]->aux->num_exentries;
1724817251
prog->aux->func = func;
1724917252
prog->aux->func_cnt = env->subprog_cnt;
1725017253
bpf_prog_jit_attempt_done(prog);
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <test_progs.h>
4+
#include "test_subprogs_extable.skel.h"
5+
6+
void test_subprogs_extable(void)
7+
{
8+
const int read_sz = 456;
9+
struct test_subprogs_extable *skel;
10+
int err;
11+
12+
skel = test_subprogs_extable__open_and_load();
13+
if (!ASSERT_OK_PTR(skel, "skel_open_and_load"))
14+
return;
15+
16+
err = test_subprogs_extable__attach(skel);
17+
if (!ASSERT_OK(err, "skel_attach"))
18+
goto cleanup;
19+
20+
/* trigger tracepoint */
21+
ASSERT_OK(trigger_module_test_read(read_sz), "trigger_read");
22+
23+
ASSERT_NEQ(skel->bss->triggered, 0, "verify at least one program ran");
24+
25+
test_subprogs_extable__detach(skel);
26+
27+
cleanup:
28+
test_subprogs_extable__destroy(skel);
29+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include "vmlinux.h"
4+
#include <bpf/bpf_helpers.h>
5+
#include <bpf/bpf_tracing.h>
6+
7+
struct {
8+
__uint(type, BPF_MAP_TYPE_ARRAY);
9+
__uint(max_entries, 8);
10+
__type(key, __u32);
11+
__type(value, __u64);
12+
} test_array SEC(".maps");
13+
14+
unsigned int triggered;
15+
16+
static __u64 test_cb(struct bpf_map *map, __u32 *key, __u64 *val, void *data)
17+
{
18+
return 1;
19+
}
20+
21+
SEC("fexit/bpf_testmod_return_ptr")
22+
int BPF_PROG(handle_fexit_ret_subprogs, int arg, struct file *ret)
23+
{
24+
*(volatile long *)ret;
25+
*(volatile int *)&ret->f_mode;
26+
bpf_for_each_map_elem(&test_array, test_cb, NULL, 0);
27+
triggered++;
28+
return 0;
29+
}
30+
31+
SEC("fexit/bpf_testmod_return_ptr")
32+
int BPF_PROG(handle_fexit_ret_subprogs2, int arg, struct file *ret)
33+
{
34+
*(volatile long *)ret;
35+
*(volatile int *)&ret->f_mode;
36+
bpf_for_each_map_elem(&test_array, test_cb, NULL, 0);
37+
triggered++;
38+
return 0;
39+
}
40+
41+
SEC("fexit/bpf_testmod_return_ptr")
42+
int BPF_PROG(handle_fexit_ret_subprogs3, int arg, struct file *ret)
43+
{
44+
*(volatile long *)ret;
45+
*(volatile int *)&ret->f_mode;
46+
bpf_for_each_map_elem(&test_array, test_cb, NULL, 0);
47+
triggered++;
48+
return 0;
49+
}
50+
51+
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)