Bound programs are quite useless after their device disappears.
They are simply waiting for reference count to go to zero,
don't list them in BPF_PROG_GET_NEXT_ID by freeing their ID
early.
Note that orphaned offload programs will return -ENODEV on
BPF_OBJ_GET_INFO_BY_FD so user will never see ID 0.
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
 int __bpf_prog_charge(struct user_struct *user, u32 pages);
 void __bpf_prog_uncharge(struct user_struct *user, u32 pages);
 
+void bpf_prog_free_id(struct bpf_prog *prog, bool do_idr_lock);
+
 struct bpf_map *bpf_map_get_with_uref(u32 ufd);
 struct bpf_map *__bpf_map_get(struct fd f);
 struct bpf_map * __must_check bpf_map_inc(struct bpf_map *map, bool uref);
 
        if (offload->dev_state)
                WARN_ON(__bpf_offload_ndo(prog, BPF_OFFLOAD_DESTROY, &data));
 
+       /* Make sure BPF_PROG_GET_NEXT_ID can't find this dead program */
+       bpf_prog_free_id(prog, true);
+
        list_del_init(&offload->offloads);
        kfree(offload);
        prog->aux->offload = NULL;
 
        return id > 0 ? 0 : id;
 }
 
-static void bpf_prog_free_id(struct bpf_prog *prog, bool do_idr_lock)
+void bpf_prog_free_id(struct bpf_prog *prog, bool do_idr_lock)
 {
-       /* cBPF to eBPF migrations are currently not in the idr store. */
+       /* cBPF to eBPF migrations are currently not in the idr store.
+        * Offloaded programs are removed from the store when their device
+        * disappears - even if someone grabs an fd to them they are unusable,
+        * simply waiting for refcnt to drop to be freed.
+        */
        if (!prog->aux->id)
                return;
 
                __acquire(&prog_idr_lock);
 
        idr_remove(&prog_idr, prog->aux->id);
+       prog->aux->id = 0;
 
        if (do_idr_lock)
                spin_unlock_bh(&prog_idr_lock);