mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-11 19:55:14 -04:00
bpf: Convert bpf_prog refcnt to atomic64_t
Similarly to bpf_map's refcnt/usercnt, convert bpf_prog's refcnt to atomic64 and remove artificial 32k limit. This allows to make bpf_prog's refcounting non-failing, simplifying logic of users of bpf_prog_add/bpf_prog_inc. Validated compilation by running allyesconfig kernel build. Suggested-by: Daniel Borkmann <daniel@iogearbox.net> Signed-off-by: Andrii Nakryiko <andriin@fb.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Link: https://lore.kernel.org/bpf/20191117172806.2195367-3-andriin@fb.com
This commit is contained in:
committed by
Daniel Borkmann
parent
1e0bd5a091
commit
85192dbf4d
@@ -31,7 +31,7 @@ static void *bpf_any_get(void *raw, enum bpf_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case BPF_TYPE_PROG:
|
||||
raw = bpf_prog_inc(raw);
|
||||
bpf_prog_inc(raw);
|
||||
break;
|
||||
case BPF_TYPE_MAP:
|
||||
bpf_map_inc_with_uref(raw);
|
||||
@@ -534,7 +534,8 @@ static struct bpf_prog *__get_prog_inode(struct inode *inode, enum bpf_prog_type
|
||||
if (!bpf_prog_get_ok(prog, &type, false))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
return bpf_prog_inc(prog);
|
||||
bpf_prog_inc(prog);
|
||||
return prog;
|
||||
}
|
||||
|
||||
struct bpf_prog *bpf_prog_get_type_path(const char *name, enum bpf_prog_type type)
|
||||
|
||||
@@ -1339,7 +1339,7 @@ static void __bpf_prog_put_noref(struct bpf_prog *prog, bool deferred)
|
||||
|
||||
static void __bpf_prog_put(struct bpf_prog *prog, bool do_idr_lock)
|
||||
{
|
||||
if (atomic_dec_and_test(&prog->aux->refcnt)) {
|
||||
if (atomic64_dec_and_test(&prog->aux->refcnt)) {
|
||||
perf_event_bpf_event(prog, PERF_BPF_EVENT_PROG_UNLOAD, 0);
|
||||
/* bpf_prog_free_id() must be called first */
|
||||
bpf_prog_free_id(prog, do_idr_lock);
|
||||
@@ -1445,16 +1445,9 @@ static struct bpf_prog *____bpf_prog_get(struct fd f)
|
||||
return f.file->private_data;
|
||||
}
|
||||
|
||||
/* prog's refcnt limit */
|
||||
#define BPF_MAX_REFCNT 32768
|
||||
|
||||
struct bpf_prog *bpf_prog_add(struct bpf_prog *prog, int i)
|
||||
void bpf_prog_add(struct bpf_prog *prog, int i)
|
||||
{
|
||||
if (atomic_add_return(i, &prog->aux->refcnt) > BPF_MAX_REFCNT) {
|
||||
atomic_sub(i, &prog->aux->refcnt);
|
||||
return ERR_PTR(-EBUSY);
|
||||
}
|
||||
return prog;
|
||||
atomic64_add(i, &prog->aux->refcnt);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bpf_prog_add);
|
||||
|
||||
@@ -1465,13 +1458,13 @@ void bpf_prog_sub(struct bpf_prog *prog, int i)
|
||||
* path holds a reference to the program, thus atomic_sub() can
|
||||
* be safely used in such cases!
|
||||
*/
|
||||
WARN_ON(atomic_sub_return(i, &prog->aux->refcnt) == 0);
|
||||
WARN_ON(atomic64_sub_return(i, &prog->aux->refcnt) == 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bpf_prog_sub);
|
||||
|
||||
struct bpf_prog *bpf_prog_inc(struct bpf_prog *prog)
|
||||
void bpf_prog_inc(struct bpf_prog *prog)
|
||||
{
|
||||
return bpf_prog_add(prog, 1);
|
||||
atomic64_inc(&prog->aux->refcnt);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bpf_prog_inc);
|
||||
|
||||
@@ -1480,12 +1473,7 @@ struct bpf_prog *bpf_prog_inc_not_zero(struct bpf_prog *prog)
|
||||
{
|
||||
int refold;
|
||||
|
||||
refold = atomic_fetch_add_unless(&prog->aux->refcnt, 1, 0);
|
||||
|
||||
if (refold >= BPF_MAX_REFCNT) {
|
||||
__bpf_prog_put(prog, false);
|
||||
return ERR_PTR(-EBUSY);
|
||||
}
|
||||
refold = atomic64_fetch_add_unless(&prog->aux->refcnt, 1, 0);
|
||||
|
||||
if (!refold)
|
||||
return ERR_PTR(-ENOENT);
|
||||
@@ -1523,7 +1511,7 @@ static struct bpf_prog *__bpf_prog_get(u32 ufd, enum bpf_prog_type *attach_type,
|
||||
goto out;
|
||||
}
|
||||
|
||||
prog = bpf_prog_inc(prog);
|
||||
bpf_prog_inc(prog);
|
||||
out:
|
||||
fdput(f);
|
||||
return prog;
|
||||
@@ -1714,7 +1702,7 @@ static int bpf_prog_load(union bpf_attr *attr, union bpf_attr __user *uattr)
|
||||
prog->orig_prog = NULL;
|
||||
prog->jited = 0;
|
||||
|
||||
atomic_set(&prog->aux->refcnt, 1);
|
||||
atomic64_set(&prog->aux->refcnt, 1);
|
||||
prog->gpl_compatible = is_gpl ? 1 : 0;
|
||||
|
||||
if (bpf_prog_is_dev_bound(prog->aux)) {
|
||||
|
||||
@@ -10477,12 +10477,9 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
|
||||
context = parent_event->overflow_handler_context;
|
||||
#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_EVENT_TRACING)
|
||||
if (overflow_handler == bpf_overflow_handler) {
|
||||
struct bpf_prog *prog = bpf_prog_inc(parent_event->prog);
|
||||
struct bpf_prog *prog = parent_event->prog;
|
||||
|
||||
if (IS_ERR(prog)) {
|
||||
err = PTR_ERR(prog);
|
||||
goto err_ns;
|
||||
}
|
||||
bpf_prog_inc(prog);
|
||||
event->prog = prog;
|
||||
event->orig_overflow_handler =
|
||||
parent_event->orig_overflow_handler;
|
||||
|
||||
Reference in New Issue
Block a user