diff mbox series

[bpf-next] bpf: Fix error checks against bpf_get_btf_vmlinux().

Message ID 20240125233105.1096036-1-thinker.li@gmail.com (mailing list archive)
State Superseded
Delegated to: BPF
Headers show
Series [bpf-next] bpf: Fix error checks against bpf_get_btf_vmlinux(). | expand

Checks

Context Check Description
bpf/vmtest-bpf-next-VM_Test-3 success Logs for Validate matrix.py
bpf/vmtest-bpf-next-VM_Test-2 success Logs for Unittests
bpf/vmtest-bpf-next-VM_Test-5 success Logs for aarch64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-1 success Logs for ShellCheck
bpf/vmtest-bpf-next-VM_Test-0 success Logs for Lint
bpf/vmtest-bpf-next-VM_Test-6 success Logs for aarch64-gcc / test (test_maps, false, 360) / test_maps on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-10 success Logs for aarch64-gcc / veristat
bpf/vmtest-bpf-next-VM_Test-4 success Logs for aarch64-gcc / build / build for aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-9 success Logs for aarch64-gcc / test (test_verifier, false, 360) / test_verifier on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-12 success Logs for s390x-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-7 success Logs for aarch64-gcc / test (test_progs, false, 360) / test_progs on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-8 success Logs for aarch64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-18 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-23 success Logs for x86_64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-17 success Logs for s390x-gcc / veristat
bpf/vmtest-bpf-next-VM_Test-24 success Logs for x86_64-gcc / test (test_progs_no_alu32_parallel, true, 30) / test_progs_no_alu32_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-20 success Logs for x86_64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-28 success Logs for x86_64-llvm-17 / build / build for x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-22 success Logs for x86_64-gcc / test (test_progs, false, 360) / test_progs on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-26 success Logs for x86_64-gcc / test (test_verifier, false, 360) / test_verifier on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-21 success Logs for x86_64-gcc / test (test_maps, false, 360) / test_maps on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-11 success Logs for s390x-gcc / build / build for s390x with gcc
bpf/vmtest-bpf-next-VM_Test-19 success Logs for x86_64-gcc / build / build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-29 success Logs for x86_64-llvm-17 / build-release / build for x86_64 with llvm-17 and -O2 optimization
bpf/vmtest-bpf-next-VM_Test-31 success Logs for x86_64-llvm-17 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-27 success Logs for x86_64-gcc / veristat / veristat on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-38 success Logs for x86_64-llvm-18 / veristat
bpf/vmtest-bpf-next-VM_Test-33 success Logs for x86_64-llvm-17 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-34 success Logs for x86_64-llvm-17 / veristat
bpf/vmtest-bpf-next-VM_Test-25 success Logs for x86_64-gcc / test (test_progs_parallel, true, 30) / test_progs_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-30 success Logs for x86_64-llvm-17 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-37 success Logs for x86_64-llvm-18 / test
bpf/vmtest-bpf-next-VM_Test-32 success Logs for x86_64-llvm-17 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-36 fail Logs for x86_64-llvm-18 / build-release / build for x86_64 with llvm-18 and -O2 optimization
bpf/vmtest-bpf-next-VM_Test-35 fail Logs for x86_64-llvm-18 / build / build for x86_64 with llvm-18
netdev/series_format success Single patches do not need cover letters
netdev/tree_selection success Clearly marked for bpf-next
netdev/ynl success SINGLE THREAD; Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 1090 this patch: 1090
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers success CCed 0 of 0 maintainers
netdev/build_clang success Errors and warnings before: 1096 this patch: 1096
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success Fixes tag looks correct
netdev/build_allmodconfig_warn success Errors and warnings before: 1108 this patch: 1108
netdev/checkpatch warning WARNING: ENOTSUPP is not a SUSV4 error code, prefer EOPNOTSUPP
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
bpf/vmtest-bpf-next-VM_Test-16 success Logs for s390x-gcc / test (test_verifier, false, 360) / test_verifier on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-14 success Logs for s390x-gcc / test (test_progs, false, 360) / test_progs on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-15 success Logs for s390x-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on s390x with gcc
bpf/vmtest-bpf-next-PR fail PR summary
bpf/vmtest-bpf-next-VM_Test-13 success Logs for s390x-gcc / test (test_maps, false, 360) / test_maps on s390x with gcc

Commit Message

Kui-Feng Lee Jan. 25, 2024, 11:31 p.m. UTC
From: Kui-Feng Lee <thinker.li@gmail.com>

Check whether the returned pointer is NULL. Previously, it was assumed that
an error code would be returned if BTF is not available or fails to
parse. However, it actually returns NULL if BTF is disabled.

In the function check_struct_ops_btf_id(), we have stopped using
btf_vmlinux as a backup because attach_btf is never null when attach_btf_id
is set. However, the function test_libbpf_probe_prog_types() in
libbpf_probes.c does not set both attach_btf_obj_fd and attach_btf_id,
resulting in attach_btf being null, and it expects ENOTSUPP as a
result. So, if attach_btf_id is not set, it will return ENOTSUPP.

Reported-by: syzbot+88f0aafe5f950d7489d7@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/bpf/00000000000040d68a060fc8db8c@google.com/
Fixes: fcc2c1fb0651 ("bpf: pass attached BTF to the bpf_struct_ops subsystem")
Signed-off-by: Kui-Feng Lee <thinker.li@gmail.com>
---
 kernel/bpf/bpf_struct_ops.c | 2 ++
 kernel/bpf/verifier.c       | 8 +++++++-
 2 files changed, 9 insertions(+), 1 deletion(-)

Comments

Martin KaFai Lau Jan. 26, 2024, 12:54 a.m. UTC | #1
On 1/25/24 3:31 PM, thinker.li@gmail.com wrote:
> From: Kui-Feng Lee <thinker.li@gmail.com>
> 
> Check whether the returned pointer is NULL. Previously, it was assumed that
> an error code would be returned if BTF is not available or fails to
> parse. However, it actually returns NULL if BTF is disabled.
> 
> In the function check_struct_ops_btf_id(), we have stopped using
> btf_vmlinux as a backup because attach_btf is never null when attach_btf_id
> is set. However, the function test_libbpf_probe_prog_types() in
> libbpf_probes.c does not set both attach_btf_obj_fd and attach_btf_id,
> resulting in attach_btf being null, and it expects ENOTSUPP as a
> result. So, if attach_btf_id is not set, it will return ENOTSUPP.
> 
> Reported-by: syzbot+88f0aafe5f950d7489d7@syzkaller.appspotmail.com
> Closes: https://lore.kernel.org/bpf/00000000000040d68a060fc8db8c@google.com/

There were two different syzbot report. Both should be tagged here as Reported-by.

> Fixes: fcc2c1fb0651 ("bpf: pass attached BTF to the bpf_struct_ops subsystem")
> Signed-off-by: Kui-Feng Lee <thinker.li@gmail.com>
> ---
>   kernel/bpf/bpf_struct_ops.c | 2 ++
>   kernel/bpf/verifier.c       | 8 +++++++-
>   2 files changed, 9 insertions(+), 1 deletion(-)
> 
> diff --git a/kernel/bpf/bpf_struct_ops.c b/kernel/bpf/bpf_struct_ops.c
> index defc052e4622..0decd862dfe0 100644
> --- a/kernel/bpf/bpf_struct_ops.c
> +++ b/kernel/bpf/bpf_struct_ops.c
> @@ -669,6 +669,8 @@ static struct bpf_map *bpf_struct_ops_map_alloc(union bpf_attr *attr)
>   		btf = bpf_get_btf_vmlinux();
>   		if (IS_ERR(btf))
>   			return ERR_CAST(btf);
> +		if (!btf)
> +			return ERR_PTR(-ENOTSUPP);
>   	}
>   
>   	st_ops_desc = bpf_struct_ops_find_value(btf, attr->btf_vmlinux_value_type_id);
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index fe833e831cb6..64a927784c54 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -20298,7 +20298,13 @@ static int check_struct_ops_btf_id(struct bpf_verifier_env *env)
>   		return -EINVAL;
>   	}
>   
> -	btf = prog->aux->attach_btf ?: bpf_get_btf_vmlinux();
> +	if (!prog->aux->attach_btf_id)
> +		return -ENOTSUPP;
> +
> +	btf = prog->aux->attach_btf;
> +	if (!btf)

The commit message mentioned "attach_btf is never null when attach_btf_id is 
set". Then why this test is still needed when the above has just tested the 
attach_btf_id. attach_btf must be valid here as long as attach_btf_id is set. 
This should have been guaranteed by syscall.c, no?

> +		return -ENOTSUPP;
> +
>   	if (btf_is_module(btf)) {
>   		/* Make sure st_ops is valid through the lifetime of env */
>   		env->attach_btf_mod = btf_try_get_module(btf);
Kui-Feng Lee Jan. 26, 2024, 2:08 a.m. UTC | #2
On 1/25/24 16:54, Martin KaFai Lau wrote:
> On 1/25/24 3:31 PM, thinker.li@gmail.com wrote:
>> From: Kui-Feng Lee <thinker.li@gmail.com>
>>
>> Check whether the returned pointer is NULL. Previously, it was assumed 
>> that
>> an error code would be returned if BTF is not available or fails to
>> parse. However, it actually returns NULL if BTF is disabled.
>>
>> In the function check_struct_ops_btf_id(), we have stopped using
>> btf_vmlinux as a backup because attach_btf is never null when 
>> attach_btf_id
>> is set. However, the function test_libbpf_probe_prog_types() in
>> libbpf_probes.c does not set both attach_btf_obj_fd and attach_btf_id,
>> resulting in attach_btf being null, and it expects ENOTSUPP as a
>> result. So, if attach_btf_id is not set, it will return ENOTSUPP.
>>
>> Reported-by: syzbot+88f0aafe5f950d7489d7@syzkaller.appspotmail.com
>> Closes: 
>> https://lore.kernel.org/bpf/00000000000040d68a060fc8db8c@google.com/
> 
> There were two different syzbot report. Both should be tagged here as 
> Reported-by.

Sure!

> 
>> Fixes: fcc2c1fb0651 ("bpf: pass attached BTF to the bpf_struct_ops 
>> subsystem")
>> Signed-off-by: Kui-Feng Lee <thinker.li@gmail.com>
>> ---
>>   kernel/bpf/bpf_struct_ops.c | 2 ++
>>   kernel/bpf/verifier.c       | 8 +++++++-
>>   2 files changed, 9 insertions(+), 1 deletion(-)
>>
>> diff --git a/kernel/bpf/bpf_struct_ops.c b/kernel/bpf/bpf_struct_ops.c
>> index defc052e4622..0decd862dfe0 100644
>> --- a/kernel/bpf/bpf_struct_ops.c
>> +++ b/kernel/bpf/bpf_struct_ops.c
>> @@ -669,6 +669,8 @@ static struct bpf_map 
>> *bpf_struct_ops_map_alloc(union bpf_attr *attr)
>>           btf = bpf_get_btf_vmlinux();
>>           if (IS_ERR(btf))
>>               return ERR_CAST(btf);
>> +        if (!btf)
>> +            return ERR_PTR(-ENOTSUPP);
>>       }
>>       st_ops_desc = bpf_struct_ops_find_value(btf, 
>> attr->btf_vmlinux_value_type_id);
>> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
>> index fe833e831cb6..64a927784c54 100644
>> --- a/kernel/bpf/verifier.c
>> +++ b/kernel/bpf/verifier.c
>> @@ -20298,7 +20298,13 @@ static int check_struct_ops_btf_id(struct 
>> bpf_verifier_env *env)
>>           return -EINVAL;
>>       }
>> -    btf = prog->aux->attach_btf ?: bpf_get_btf_vmlinux();
>> +    if (!prog->aux->attach_btf_id)
>> +        return -ENOTSUPP;
>> +
>> +    btf = prog->aux->attach_btf;
>> +    if (!btf)
> 
> The commit message mentioned "attach_btf is never null when 
> attach_btf_id is set". Then why this test is still needed when the above 
> has just tested the attach_btf_id. attach_btf must be valid here as long 
> as attach_btf_id is set. This should have been guaranteed by syscall.c, no?

Yes, you are right.

> 
>> +        return -ENOTSUPP;
>> +
>>       if (btf_is_module(btf)) {
>>           /* Make sure st_ops is valid through the lifetime of env */
>>           env->attach_btf_mod = btf_try_get_module(btf);
>
diff mbox series

Patch

diff --git a/kernel/bpf/bpf_struct_ops.c b/kernel/bpf/bpf_struct_ops.c
index defc052e4622..0decd862dfe0 100644
--- a/kernel/bpf/bpf_struct_ops.c
+++ b/kernel/bpf/bpf_struct_ops.c
@@ -669,6 +669,8 @@  static struct bpf_map *bpf_struct_ops_map_alloc(union bpf_attr *attr)
 		btf = bpf_get_btf_vmlinux();
 		if (IS_ERR(btf))
 			return ERR_CAST(btf);
+		if (!btf)
+			return ERR_PTR(-ENOTSUPP);
 	}
 
 	st_ops_desc = bpf_struct_ops_find_value(btf, attr->btf_vmlinux_value_type_id);
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index fe833e831cb6..64a927784c54 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -20298,7 +20298,13 @@  static int check_struct_ops_btf_id(struct bpf_verifier_env *env)
 		return -EINVAL;
 	}
 
-	btf = prog->aux->attach_btf ?: bpf_get_btf_vmlinux();
+	if (!prog->aux->attach_btf_id)
+		return -ENOTSUPP;
+
+	btf = prog->aux->attach_btf;
+	if (!btf)
+		return -ENOTSUPP;
+
 	if (btf_is_module(btf)) {
 		/* Make sure st_ops is valid through the lifetime of env */
 		env->attach_btf_mod = btf_try_get_module(btf);