[PATCH bpf] bpf: Fix crash due to OOB access when reg->type > __BPF_REG_TYPE_MAX

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



When commit e6ac2450d6de ("bpf: Support bpf program calling kernel
function") added kfunc support, it defined reg2btf_ids as a cheap way to
translate the verifier reg type to the appropriate btf_vmlinux BTF ID,
however commit c25b2ae13603 ("bpf: Replace PTR_TO_XXX_OR_NULL with
PTR_TO_XXX | PTR_MAYBE_NULL") moved the __BPF_REG_TYPE_MAX from the last
member of bpf_reg_type enum to after the base register types, and
defined other variants using type flag composition. However, now, the
direct usage of reg->type to index into reg2btf_ids may no longer fall
into __BPF_REG_TYPE_MAX range, and hence lead to out of bounds access
and kernel crash on dereference of bad pointer.

[   20.448584] BUG: unable to handle page fault for address: 0000000000524156
[   20.449149] #PF: supervisor read access in kernel mode
[   20.449537] #PF: error_code(0x0000) - not-present page
[   20.450025] PGD 0 P4D 0
[   20.450303] Oops: 0000 [#1] PREEMPT SMP KASAN NOPTI
[   20.450808] CPU: 0 PID: 323 Comm: test_verifier Tainted: G    B   W   E     5.17.0-rc2+ #286
[   20.451567] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS ArchLinux 1.15.0-1 04/01/2014
[   20.452364] RIP: 0010:btf_check_func_arg_match+0x651/0xe10
[   20.452868] Code: ea 04 80 fa 01 0f 87 2a 06 00 00 48 c7 c7 a0 16 f8 a5 e8 82 6d 15 00 48 8b 05 1b 3d aa 04 48 89 df 48 89 04 24 e8 2f 6c 15 00 <8b> 2b 89 ac 24 c0 00 00 00 89 ee 48 8b 2c 24 48 8d 94 24 c0 00 00
[   20.454693] RSP: 0018:ffff88800727f4f8 EFLAGS: 00010282
[   20.455232] RAX: 0000000000000000 RBX: 0000000000524156 RCX: ffffffffa14dd991
[   20.455963] RDX: 0000000000000000 RSI: 0000000000000004 RDI: 0000000000524156
[   20.456683] RBP: ffffffffa398c6d4 R08: ffffffffa14dd991 R09: 0000000000000000
[   20.457297] R10: fffffbfff484f31c R11: 0000000000000001 R12: ffff888007bf8600
[   20.457917] R13: ffff88800c2f6078 R14: 0000000000000000 R15: 0000000000000001
[   20.458596] FS:  00007fe06ae70740(0000) GS:ffff88808cc00000(0000) knlGS:0000000000000000
[   20.459303] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   20.459817] CR2: 0000000000524156 CR3: 000000000902a004 CR4: 0000000000770ef0
[   20.460527] PKRU: 55555554
[   20.460746] Call Trace:
[   20.460938]  <TASK>
[   20.461120]  ? btf_kfunc_id_set_contains+0x100/0x100
[   20.461534]  ? btf_kfunc_id_set_contains+0xd6/0x100
[   20.461996]  ? btf_try_get_module+0xc0/0xc0
[   20.462361]  do_check_common+0x3961/0x5490
[   20.462726]  ? bpf_check+0x27e0/0x4c60
[   20.463036]  ? check_helper_call+0x3050/0x3050
[   20.463435]  ? lock_is_held_type+0xe4/0x140
[   20.463873]  ? lockdep_hardirqs_on_prepare+0x129/0x220
[   20.464402]  ? kasan_quarantine_put+0x9c/0x1f0
[   20.464815]  ? lockdep_hardirqs_on+0x7e/0x100
[   20.465253]  ? kasan_quarantine_put+0x9c/0x1f0
[   20.465580]  ? slab_free_freelist_hook+0x7d/0x150
[   20.465961]  ? bpf_check+0x3ae1/0x4c60
[   20.466262]  ? kfree+0xbe/0x2d0
[   20.466518]  bpf_check+0x3da4/0x4c60
[   20.466800]  ? bpf_get_btf_vmlinux+0x50/0x50
[   20.467152]  ? lock_is_held_type+0xe4/0x140
[   20.467471]  ? lock_release+0x238/0x410
[   20.467761]  ? ktime_get_with_offset+0x3c/0xf0
[   20.468168]  ? lock_downgrade+0x390/0x390
[   20.468578]  ? __might_fault+0x57/0xb0
[   20.468974]  ? memset+0x20/0x40
[   20.469314]  bpf_prog_load+0x7b3/0xfb0
[   20.469714]  ? __bpf_prog_put.constprop.0+0x120/0x120
[   20.470235]  ? lock_is_held_type+0xe4/0x140
[   20.470641]  ? avc_has_perm+0x7e/0x110
[   20.470982]  ? avc_has_perm_noaudit+0x250/0x250
[   20.471461]  __sys_bpf+0x121b/0x3350
[   20.471826]  ? bpf_raw_tracepoint_open+0x3e0/0x3e0
[   20.472291]  ? __do_fault+0x210/0x210
[   20.472675]  ? __handle_mm_fault+0x15a0/0x1c20
[   20.473138]  ? lock_is_held_type+0xe4/0x140
[   20.473589]  ? up_write+0x270/0x270
[   20.473964]  ? mark_held_locks+0x24/0x90
[   20.474383]  __x64_sys_bpf+0x44/0x50
[   20.474765]  do_syscall_64+0x59/0x80
[   20.475066]  ? asm_exc_page_fault+0x1e/0x30
[   20.475439]  ? asm_exc_page_fault+0x8/0x30
[   20.475801]  ? lockdep_hardirqs_on+0x7e/0x100
[   20.476252]  entry_SYSCALL_64_after_hwframe+0x44/0xae
[   20.476778] RIP: 0033:0x7fe06af6e18d
[   20.477159] Code: b4 0c 00 0f 05 eb a9 66 0f 1f 44 00 00 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d b3 6c 0c 00 f7 d8 64 89 01 48
[   20.479034] RSP: 002b:00007ffcf84bbc78 EFLAGS: 00000202 ORIG_RAX: 0000000000000141
[   20.479602] RAX: ffffffffffffffda RBX: 00007fe06b16fc40 RCX: 00007fe06af6e18d
[   20.480187] RDX: 0000000000000090 RSI: 00007ffcf84bbd80 RDI: 0000000000000005
[   20.480727] RBP: 00007ffcf84bbc90 R08: 00007ffcf84bbeb0 R09: 00007ffcf84bbd80
[   20.481441] R10: 0000000000000007 R11: 0000000000000202 R12: 00007fe06b11f7b0
[   20.482127] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
[   20.482628]  </TASK>
[   20.482810] Modules linked in: crc32_pclmul(E) intel_rapl_msr(E) intel_rapl_common(E) rapl(E) ghash_clmulni_intel(E) crct10dif_pclmul(E) crc32c_intel(E) serio_raw(E)
[   20.484185] CR2: 0000000000524156
[   20.484441] ---[ end trace 0000000000000000 ]---
[   20.484900] RIP: 0010:btf_check_func_arg_match+0x651/0xe10
[   20.485401] Code: ea 04 80 fa 01 0f 87 2a 06 00 00 48 c7 c7 a0 16 f8 a5 e8 82 6d 15 00 48 8b 05 1b 3d aa 04 48 89 df 48 89 04 24 e8 2f 6c 15 00 <8b> 2b 89 ac 24 c0 00 00 00 89 ee 48 8b 2c 24 48 8d 94 24 c0 00 00
[   20.487173] RSP: 0018:ffff88800727f4f8 EFLAGS: 00010282
[   20.487709] RAX: 0000000000000000 RBX: 0000000000524156 RCX: ffffffffa14dd991
[   20.488393] RDX: 0000000000000000 RSI: 0000000000000004 RDI: 0000000000524156
[   20.489045] RBP: ffffffffa398c6d4 R08: ffffffffa14dd991 R09: 0000000000000000
[   20.489696] R10: fffffbfff484f31c R11: 0000000000000001 R12: ffff888007bf8600
[   20.490377] R13: ffff88800c2f6078 R14: 0000000000000000 R15: 0000000000000001
[   20.491065] FS:  00007fe06ae70740(0000) GS:ffff88808cc00000(0000) knlGS:0000000000000000
[   20.491782] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   20.492272] CR2: 0000000000524156 CR3: 000000000902a004 CR4: 0000000000770ef0
[   20.492925] PKRU: 55555554

Cc: Martin KaFai Lau <kafai@xxxxxx>
Cc: Hao Luo <haoluo@xxxxxxxxxx>
Fixes: c25b2ae13603 ("bpf: Replace PTR_TO_XXX_OR_NULL with PTR_TO_XXX | PTR_MAYBE_NULL")
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@xxxxxxxxx>
---
 kernel/bpf/btf.c | 22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index e16dafeb2450..416345798e0a 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -5568,13 +5568,21 @@ int btf_check_type_match(struct bpf_verifier_log *log, const struct bpf_prog *pr
 	return btf_check_func_type_match(log, btf1, t1, btf2, t2);
 }

-static u32 *reg2btf_ids[__BPF_REG_TYPE_MAX] = {
+static u32 *reg2btf_ids(enum bpf_reg_type type)
+{
+	switch (type) {
 #ifdef CONFIG_NET
-	[PTR_TO_SOCKET] = &btf_sock_ids[BTF_SOCK_TYPE_SOCK],
-	[PTR_TO_SOCK_COMMON] = &btf_sock_ids[BTF_SOCK_TYPE_SOCK_COMMON],
-	[PTR_TO_TCP_SOCK] = &btf_sock_ids[BTF_SOCK_TYPE_TCP],
+	case PTR_TO_SOCKET:
+		return &btf_sock_ids[BTF_SOCK_TYPE_SOCK];
+	case PTR_TO_SOCK_COMMON:
+		return &btf_sock_ids[BTF_SOCK_TYPE_SOCK_COMMON];
+	case PTR_TO_TCP_SOCK:
+		return &btf_sock_ids[BTF_SOCK_TYPE_TCP];
 #endif
-};
+	default:
+		return NULL;
+	}
+}

 /* Returns true if struct is composed of scalars, 4 levels of nesting allowed */
 static bool __btf_type_is_scalar_struct(struct bpf_verifier_log *log,
@@ -5688,7 +5696,7 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env,
 			}
 			if (check_ptr_off_reg(env, reg, regno))
 				return -EINVAL;
-		} else if (is_kfunc && (reg->type == PTR_TO_BTF_ID || reg2btf_ids[reg->type])) {
+		} else if (is_kfunc && (reg->type == PTR_TO_BTF_ID || reg2btf_ids(reg->type))) {
 			const struct btf_type *reg_ref_t;
 			const struct btf *reg_btf;
 			const char *reg_ref_tname;
@@ -5706,7 +5714,7 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env,
 				reg_ref_id = reg->btf_id;
 			} else {
 				reg_btf = btf_vmlinux;
-				reg_ref_id = *reg2btf_ids[reg->type];
+				reg_ref_id = *reg2btf_ids(reg->type);
 			}

 			reg_ref_t = btf_type_skip_modifiers(reg_btf, reg_ref_id,
--
2.35.1




[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux