]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
bpf: Fix handling maps with no BTF and non-constant offsets for the bpf_wq
authorMykyta Yatsenko <yatsenko@meta.com>
Fri, 10 Oct 2025 16:46:04 +0000 (17:46 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 18 Dec 2025 13:02:27 +0000 (14:02 +0100)
[ Upstream commit 5f8d41172931a92339c5cce81a3142065fa56e45 ]

Fix handling maps with no BTF and non-constant offsets for the bpf_wq.

This de-duplicates logic with other internal structs (task_work, timer),
keeps error reporting consistent, and makes future changes to the layout
handling centralized.

Fixes: d940c9b94d7e ("bpf: add support for KF_ARG_PTR_TO_WORKQUEUE")
Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20251010164606.147298-1-mykyta.yatsenko5@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
kernel/bpf/verifier.c

index 460107b0449fecde28484a78b576c5ca85a78bc2..52c01c011c6fb7dc81ceab75f75d8ecea5b9a818 100644 (file)
@@ -8479,6 +8479,9 @@ static int check_map_field_pointer(struct bpf_verifier_env *env, u32 regno,
        case BPF_TASK_WORK:
                field_off = map->record->task_work_off;
                break;
+       case BPF_WORKQUEUE:
+               field_off = map->record->wq_off;
+               break;
        default:
                verifier_bug(env, "unsupported BTF field type: %s\n", struct_name);
                return -EINVAL;
@@ -8520,13 +8523,17 @@ static int process_wq_func(struct bpf_verifier_env *env, int regno,
 {
        struct bpf_reg_state *regs = cur_regs(env), *reg = &regs[regno];
        struct bpf_map *map = reg->map_ptr;
-       u64 val = reg->var_off.value;
+       int err;
 
-       if (map->record->wq_off != val + reg->off) {
-               verbose(env, "off %lld doesn't point to 'struct bpf_wq' that is at %d\n",
-                       val + reg->off, map->record->wq_off);
-               return -EINVAL;
+       err = check_map_field_pointer(env, regno, BPF_WORKQUEUE);
+       if (err)
+               return err;
+
+       if (meta->map.ptr) {
+               verifier_bug(env, "Two map pointers in a bpf_wq helper");
+               return -EFAULT;
        }
+
        meta->map.uid = reg->map_uid;
        meta->map.ptr = map;
        return 0;