An offloaded program runs on the NIC, so its bpf_func is set to
bpf_prog_warn_on_exec(). tcx and netkit run programs on the host with
bpf_prog_run(), so attaching an offloaded program to them hits the WARN
on the first packet.

Both tcx and netkit go through bpf_mprog_attach(), so add the check there
once instead of in every attach path. Only check SCHED_CLS programs, so a
future mprog user that wants offloaded programs still works.

Fixes: 053c8e1f235dc ("bpf: Add generic attach/detach/query API for 
multi-progs")
Reported-by: Yinhao Hu <[email protected]>
Reported-by: Kaiyan Mei <[email protected]>
Reported-by: Dongliang Mu <[email protected]>
Closes: 
https://lore.kernel.org/bpf/[email protected]/
Signed-off-by: Jiayuan Chen <[email protected]>
---
 kernel/bpf/mprog.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/kernel/bpf/mprog.c b/kernel/bpf/mprog.c
index 1394168062e8..0b50464ec902 100644
--- a/kernel/bpf/mprog.c
+++ b/kernel/bpf/mprog.c
@@ -222,6 +222,14 @@ static int bpf_mprog_pos_after(struct bpf_mprog_entry 
*entry,
        return tuple->prog ? -ENOENT : bpf_mprog_total(entry);
 }
 
+static int bpf_mprog_check_prog(const struct bpf_prog *prog)
+{
+       if (prog->type == BPF_PROG_TYPE_SCHED_CLS &&
+           bpf_prog_is_offloaded(prog->aux))
+               return -EINVAL;
+       return 0;
+}
+
 int bpf_mprog_attach(struct bpf_mprog_entry *entry,
                     struct bpf_mprog_entry **entry_new,
                     struct bpf_prog *prog_new, struct bpf_link *link,
@@ -237,6 +245,9 @@ int bpf_mprog_attach(struct bpf_mprog_entry *entry,
        };
        int ret, idx = -ERANGE, tidx;
 
+       ret = bpf_mprog_check_prog(prog_new);
+       if (ret)
+               return ret;
        if (revision && revision != bpf_mprog_revision(entry))
                return -ESTALE;
        if (bpf_mprog_exists(entry, prog_new))
-- 
2.43.0


Reply via email to