]> www.infradead.org Git - users/willy/pagecache.git/commitdiff
bpf: fix null dereference when computing changes_pkt_data of prog w/o subprogs
authorEduard Zingerman <eddyz87@gmail.com>
Thu, 12 Dec 2024 07:07:10 +0000 (23:07 -0800)
committerAlexei Starovoitov <ast@kernel.org>
Thu, 12 Dec 2024 19:37:19 +0000 (11:37 -0800)
bpf_prog_aux->func field might be NULL if program does not have
subprograms except for main sub-program. The fixed commit does
bpf_prog_aux->func access unconditionally, which might lead to null
pointer dereference.

The bug could be triggered by replacing the following BPF program:

    SEC("tc")
    int main_changes(struct __sk_buff *sk)
    {
        bpf_skb_pull_data(sk, 0);
        return 0;
    }

With the following BPF program:

    SEC("freplace")
    long changes_pkt_data(struct __sk_buff *sk)
    {
        return bpf_skb_pull_data(sk, 0);
    }

bpf_prog_aux instance itself represents the main sub-program,
use this property to fix the bug.

Fixes: 81f6d0530ba0 ("bpf: check changes_pkt_data property for extension programs")
Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
Closes: https://lore.kernel.org/r/202412111822.qGw6tOyB-lkp@intel.com/
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20241212070711.427443-1-eddyz87@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
kernel/bpf/verifier.c

index c2e5d0e6e3d014c50a577ee58969b07061f6c910..5e541339b2f6d1870561033fd55cca7144db14bc 100644 (file)
@@ -22193,6 +22193,7 @@ int bpf_check_attach_target(struct bpf_verifier_log *log,
        }
        if (tgt_prog) {
                struct bpf_prog_aux *aux = tgt_prog->aux;
+               bool tgt_changes_pkt_data;
 
                if (bpf_prog_is_dev_bound(prog->aux) &&
                    !bpf_prog_dev_bound_match(prog, tgt_prog)) {
@@ -22227,8 +22228,10 @@ int bpf_check_attach_target(struct bpf_verifier_log *log,
                                        "Extension programs should be JITed\n");
                                return -EINVAL;
                        }
-                       if (prog->aux->changes_pkt_data &&
-                           !aux->func[subprog]->aux->changes_pkt_data) {
+                       tgt_changes_pkt_data = aux->func
+                                              ? aux->func[subprog]->aux->changes_pkt_data
+                                              : aux->changes_pkt_data;
+                       if (prog->aux->changes_pkt_data && !tgt_changes_pkt_data) {
                                bpf_log(log,
                                        "Extension program changes packet data, while original does not\n");
                                return -EINVAL;