* [PATCH bpf-next v2 0/3] libbpf: fix fuzzer-reported issues
@ 2022-10-12 2:23 Shung-Hsi Yu
2022-10-12 2:23 ` [PATCH bpf-next v2 1/3] libbpf: use elf_getshdrnum() instead of e_shnum Shung-Hsi Yu
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Shung-Hsi Yu @ 2022-10-12 2:23 UTC (permalink / raw)
To: bpf, Andrii Nakryiko
Cc: Shung-Hsi Yu, Alexei Starovoitov, Daniel Borkmann,
Martin KaFai Lau, Song Liu, Yonghong Song, John Fastabend,
KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa
Hi, this patch set fixes several fuzzer-reported issues of libbpf when
dealing with (malformed) BPF object file:
- patch #1 fix out-of-bound heap write reported by oss-fuzz (currently
incorrectly marked as fixed)
- patch #2 and #3 fix null-pointer dereference found by locally-run
fuzzer.
v2:
- Rebase to bpf-next
- Move elf_getshdrnum() closer to where it's result is used in patch #1, as
suggested by Andrii
- Touch up the comment in bpf_object__elf_collect(), replacing mention of
e_shnum with elf_getshdrnum()
- Minor wording change in commit message of patch #1 to for better readability
- Remove extra note that comes after commit message in patch #1
v1: https://lore.kernel.org/bpf/20221007174816.17536-1-shung-hsi.yu@suse.com/
Shung-Hsi Yu (3):
libbpf: use elf_getshdrnum() instead of e_shnum
libbpf: deal with section with no data gracefully
libbpf: fix null-pointer dereference in find_prog_by_sec_insn()
tools/lib/bpf/libbpf.c | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
base-commit: 0326074ff4652329f2a1a9c8685104576bd8d131
--
2.37.3
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH bpf-next v2 1/3] libbpf: use elf_getshdrnum() instead of e_shnum
2022-10-12 2:23 [PATCH bpf-next v2 0/3] libbpf: fix fuzzer-reported issues Shung-Hsi Yu
@ 2022-10-12 2:23 ` Shung-Hsi Yu
2022-10-12 2:23 ` [PATCH bpf-next v2 2/3] libbpf: deal with section with no data gracefully Shung-Hsi Yu
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Shung-Hsi Yu @ 2022-10-12 2:23 UTC (permalink / raw)
To: bpf, Andrii Nakryiko
Cc: Shung-Hsi Yu, Alexei Starovoitov, Daniel Borkmann,
Martin KaFai Lau, Song Liu, Yonghong Song, John Fastabend,
KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa
This commit replace e_shnum with the elf_getshdrnum() helper to fix two
oss-fuzz-reported heap-buffer overflow in __bpf_object__open. Both
reports are incorrectly marked as fixed and while still being
reproducible in the latest libbpf.
# clusterfuzz-testcase-minimized-bpf-object-fuzzer-5747922482888704
libbpf: loading object 'fuzz-object' from buffer
libbpf: sec_cnt is 0
libbpf: elf: section(1) .data, size 0, link 538976288, flags 2020202020202020, type=2
libbpf: elf: section(2) .data, size 32, link 538976288, flags 202020202020ff20, type=1
=================================================================
==13==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6020000000c0 at pc 0x0000005a7b46 bp 0x7ffd12214af0 sp 0x7ffd12214ae8
WRITE of size 4 at 0x6020000000c0 thread T0
SCARINESS: 46 (4-byte-write-heap-buffer-overflow-far-from-bounds)
#0 0x5a7b45 in bpf_object__elf_collect /src/libbpf/src/libbpf.c:3414:24
#1 0x5733c0 in bpf_object_open /src/libbpf/src/libbpf.c:7223:16
#2 0x5739fd in bpf_object__open_mem /src/libbpf/src/libbpf.c:7263:20
...
The issue lie in libbpf's direct use of e_shnum field in ELF header as
the section header count. Where as libelf implemented an extra logic
that, when e_shnum == 0 && e_shoff != 0, will use sh_size member of the
initial section header as the real section header count (part of ELF
spec to accommodate situation where section header counter is larger
than SHN_LORESERVE).
The above inconsistency lead to libbpf writing into a zero-entry calloc
area. So intead of using e_shnum directly, use the elf_getshdrnum()
helper provided by libelf to retrieve the section header counter into
sec_cnt.
Link: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=40868
Link: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=40957
Fixes: 0d6988e16a12 ("libbpf: Fix section counting logic")
Fixes: 25bbbd7a444b ("libbpf: Remove assumptions about uniqueness of .rodata/.data/.bss maps")
Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
---
tools/lib/bpf/libbpf.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 184ce1684dcd..2e8ac13de6a0 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -597,7 +597,7 @@ struct elf_state {
size_t shstrndx; /* section index for section name strings */
size_t strtabidx;
struct elf_sec_desc *secs;
- int sec_cnt;
+ size_t sec_cnt;
int btf_maps_shndx;
__u32 btf_maps_sec_btf_id;
int text_shndx;
@@ -3312,10 +3312,15 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
Elf64_Shdr *sh;
/* ELF section indices are 0-based, but sec #0 is special "invalid"
- * section. e_shnum does include sec #0, so e_shnum is the necessary
- * size of an array to keep all the sections.
+ * section. Since section count retrieved by elf_getshdrnum() does
+ * include sec #0, it is already the necessary size of an array to keep
+ * all the sections.
*/
- obj->efile.sec_cnt = obj->efile.ehdr->e_shnum;
+ if (elf_getshdrnum(obj->efile.elf, &obj->efile.sec_cnt)) {
+ pr_warn("elf: failed to get the number of sections for %s: %s\n",
+ obj->path, elf_errmsg(-1));
+ return -LIBBPF_ERRNO__FORMAT;
+ }
obj->efile.secs = calloc(obj->efile.sec_cnt, sizeof(*obj->efile.secs));
if (!obj->efile.secs)
return -ENOMEM;
--
2.37.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH bpf-next v2 2/3] libbpf: deal with section with no data gracefully
2022-10-12 2:23 [PATCH bpf-next v2 0/3] libbpf: fix fuzzer-reported issues Shung-Hsi Yu
2022-10-12 2:23 ` [PATCH bpf-next v2 1/3] libbpf: use elf_getshdrnum() instead of e_shnum Shung-Hsi Yu
@ 2022-10-12 2:23 ` Shung-Hsi Yu
2022-10-12 2:23 ` [PATCH bpf-next v2 3/3] libbpf: fix null-pointer dereference in find_prog_by_sec_insn() Shung-Hsi Yu
2022-10-13 16:00 ` [PATCH bpf-next v2 0/3] libbpf: fix fuzzer-reported issues patchwork-bot+netdevbpf
3 siblings, 0 replies; 5+ messages in thread
From: Shung-Hsi Yu @ 2022-10-12 2:23 UTC (permalink / raw)
To: bpf, Andrii Nakryiko
Cc: Shung-Hsi Yu, Alexei Starovoitov, Daniel Borkmann,
Martin KaFai Lau, Song Liu, Yonghong Song, John Fastabend,
KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa
ELF section data pointer returned by libelf may be NULL (if section has
SHT_NOBITS), so null check section data pointer before attempting to
copy license and kversion section.
Fixes: cb1e5e961991 ("bpf tools: Collect version and license from ELF sections")
Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
---
tools/lib/bpf/libbpf.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 2e8ac13de6a0..29e9df0c232b 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -1408,6 +1408,10 @@ static int bpf_object__check_endianness(struct bpf_object *obj)
static int
bpf_object__init_license(struct bpf_object *obj, void *data, size_t size)
{
+ if (!data) {
+ pr_warn("invalid license section in %s\n", obj->path);
+ return -LIBBPF_ERRNO__FORMAT;
+ }
/* libbpf_strlcpy() only copies first N - 1 bytes, so size + 1 won't
* go over allowed ELF data section buffer
*/
@@ -1421,7 +1425,7 @@ bpf_object__init_kversion(struct bpf_object *obj, void *data, size_t size)
{
__u32 kver;
- if (size != sizeof(kver)) {
+ if (!data || size != sizeof(kver)) {
pr_warn("invalid kver section in %s\n", obj->path);
return -LIBBPF_ERRNO__FORMAT;
}
--
2.37.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH bpf-next v2 3/3] libbpf: fix null-pointer dereference in find_prog_by_sec_insn()
2022-10-12 2:23 [PATCH bpf-next v2 0/3] libbpf: fix fuzzer-reported issues Shung-Hsi Yu
2022-10-12 2:23 ` [PATCH bpf-next v2 1/3] libbpf: use elf_getshdrnum() instead of e_shnum Shung-Hsi Yu
2022-10-12 2:23 ` [PATCH bpf-next v2 2/3] libbpf: deal with section with no data gracefully Shung-Hsi Yu
@ 2022-10-12 2:23 ` Shung-Hsi Yu
2022-10-13 16:00 ` [PATCH bpf-next v2 0/3] libbpf: fix fuzzer-reported issues patchwork-bot+netdevbpf
3 siblings, 0 replies; 5+ messages in thread
From: Shung-Hsi Yu @ 2022-10-12 2:23 UTC (permalink / raw)
To: bpf, Andrii Nakryiko
Cc: Shung-Hsi Yu, Alexei Starovoitov, Daniel Borkmann,
Martin KaFai Lau, Song Liu, Yonghong Song, John Fastabend,
KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa
When there are no program sections, obj->programs is left unallocated,
and find_prog_by_sec_insn()'s search lands on &obj->programs[0] == NULL,
and will cause null-pointer dereference in the following access to
prog->sec_idx.
Guard the search with obj->nr_programs similar to what's being done in
__bpf_program__iter() to prevent null-pointer access from happening.
Fixes: db2b8b06423c ("libbpf: Support CO-RE relocations for multi-prog sections")
Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
---
tools/lib/bpf/libbpf.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 29e9df0c232b..8c3f236c86e4 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -4115,6 +4115,9 @@ static struct bpf_program *find_prog_by_sec_insn(const struct bpf_object *obj,
int l = 0, r = obj->nr_programs - 1, m;
struct bpf_program *prog;
+ if (!obj->nr_programs)
+ return NULL;
+
while (l < r) {
m = l + (r - l + 1) / 2;
prog = &obj->programs[m];
--
2.37.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH bpf-next v2 0/3] libbpf: fix fuzzer-reported issues
2022-10-12 2:23 [PATCH bpf-next v2 0/3] libbpf: fix fuzzer-reported issues Shung-Hsi Yu
` (2 preceding siblings ...)
2022-10-12 2:23 ` [PATCH bpf-next v2 3/3] libbpf: fix null-pointer dereference in find_prog_by_sec_insn() Shung-Hsi Yu
@ 2022-10-13 16:00 ` patchwork-bot+netdevbpf
3 siblings, 0 replies; 5+ messages in thread
From: patchwork-bot+netdevbpf @ 2022-10-13 16:00 UTC (permalink / raw)
To: Shung-Hsi Yu
Cc: bpf, andrii, ast, daniel, martin.lau, song, yhs, john.fastabend,
kpsingh, sdf, haoluo, jolsa
Hello:
This series was applied to bpf/bpf-next.git (master)
by Andrii Nakryiko <andrii@kernel.org>:
On Wed, 12 Oct 2022 10:23:50 +0800 you wrote:
> Hi, this patch set fixes several fuzzer-reported issues of libbpf when
> dealing with (malformed) BPF object file:
>
> - patch #1 fix out-of-bound heap write reported by oss-fuzz (currently
> incorrectly marked as fixed)
>
> - patch #2 and #3 fix null-pointer dereference found by locally-run
> fuzzer.
>
> [...]
Here is the summary with links:
- [bpf-next,v2,1/3] libbpf: use elf_getshdrnum() instead of e_shnum
https://git.kernel.org/bpf/bpf-next/c/ea306bb65ff8
- [bpf-next,v2,2/3] libbpf: deal with section with no data gracefully
https://git.kernel.org/bpf/bpf-next/c/662e24598d8c
- [bpf-next,v2,3/3] libbpf: fix null-pointer dereference in find_prog_by_sec_insn()
https://git.kernel.org/bpf/bpf-next/c/79d0ca2d19bf
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2022-10-13 16:00 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-10-12 2:23 [PATCH bpf-next v2 0/3] libbpf: fix fuzzer-reported issues Shung-Hsi Yu
2022-10-12 2:23 ` [PATCH bpf-next v2 1/3] libbpf: use elf_getshdrnum() instead of e_shnum Shung-Hsi Yu
2022-10-12 2:23 ` [PATCH bpf-next v2 2/3] libbpf: deal with section with no data gracefully Shung-Hsi Yu
2022-10-12 2:23 ` [PATCH bpf-next v2 3/3] libbpf: fix null-pointer dereference in find_prog_by_sec_insn() Shung-Hsi Yu
2022-10-13 16:00 ` [PATCH bpf-next v2 0/3] libbpf: fix fuzzer-reported issues patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox