Skip to content

Commit af6eea5

Browse files
anakryikoAlexei Starovoitov
authored andcommitted
bpf: Implement bpf_link-based cgroup BPF program attachment
Implement new sub-command to attach cgroup BPF programs and return FD-based bpf_link back on success. bpf_link, once attached to cgroup, cannot be replaced, except by owner having its FD. Cgroup bpf_link supports only BPF_F_ALLOW_MULTI semantics. Both link-based and prog-based BPF_F_ALLOW_MULTI attachments can be freely intermixed. To prevent bpf_cgroup_link from keeping cgroup alive past the point when no BPF program can be executed, implement auto-detachment of link. When cgroup_bpf_release() is called, all attached bpf_links are forced to release cgroup refcounts, but they leave bpf_link otherwise active and allocated, as well as still owning underlying bpf_prog. This is because user-space might still have FDs open and active, so bpf_link as a user-referenced object can't be freed yet. Once last active FD is closed, bpf_link will be freed and underlying bpf_prog refcount will be dropped. But cgroup refcount won't be touched, because cgroup is released already. The inherent race between bpf_cgroup_link release (from closing last FD) and cgroup_bpf_release() is resolved by both operations taking cgroup_mutex. So the only additional check required is when bpf_cgroup_link attempts to detach itself from cgroup. At that time we need to check whether there is still cgroup associated with that link. And if not, exit with success, because bpf_cgroup_link was already successfully detached. Signed-off-by: Andrii Nakryiko <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Acked-by: Roman Gushchin <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent e5ffcc9 commit af6eea5

File tree

7 files changed

+354
-98
lines changed

7 files changed

+354
-98
lines changed

include/linux/bpf-cgroup.h

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,18 @@ struct bpf_cgroup_storage {
5151
struct rcu_head rcu;
5252
};
5353

54+
struct bpf_cgroup_link {
55+
struct bpf_link link;
56+
struct cgroup *cgroup;
57+
enum bpf_attach_type type;
58+
};
59+
60+
extern const struct bpf_link_ops bpf_cgroup_link_lops;
61+
5462
struct bpf_prog_list {
5563
struct list_head node;
5664
struct bpf_prog *prog;
65+
struct bpf_cgroup_link *link;
5766
struct bpf_cgroup_storage *storage[MAX_BPF_CGROUP_STORAGE_TYPE];
5867
};
5968

@@ -84,20 +93,23 @@ struct cgroup_bpf {
8493
int cgroup_bpf_inherit(struct cgroup *cgrp);
8594
void cgroup_bpf_offline(struct cgroup *cgrp);
8695

87-
int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog,
88-
struct bpf_prog *replace_prog,
96+
int __cgroup_bpf_attach(struct cgroup *cgrp,
97+
struct bpf_prog *prog, struct bpf_prog *replace_prog,
98+
struct bpf_cgroup_link *link,
8999
enum bpf_attach_type type, u32 flags);
90100
int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog,
101+
struct bpf_cgroup_link *link,
91102
enum bpf_attach_type type);
92103
int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
93104
union bpf_attr __user *uattr);
94105

95106
/* Wrapper for __cgroup_bpf_*() protected by cgroup_mutex */
96-
int cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog,
97-
struct bpf_prog *replace_prog, enum bpf_attach_type type,
107+
int cgroup_bpf_attach(struct cgroup *cgrp,
108+
struct bpf_prog *prog, struct bpf_prog *replace_prog,
109+
struct bpf_cgroup_link *link, enum bpf_attach_type type,
98110
u32 flags);
99111
int cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog,
100-
enum bpf_attach_type type, u32 flags);
112+
enum bpf_attach_type type);
101113
int cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
102114
union bpf_attr __user *uattr);
103115

@@ -332,6 +344,7 @@ int cgroup_bpf_prog_attach(const union bpf_attr *attr,
332344
enum bpf_prog_type ptype, struct bpf_prog *prog);
333345
int cgroup_bpf_prog_detach(const union bpf_attr *attr,
334346
enum bpf_prog_type ptype);
347+
int cgroup_bpf_link_attach(const union bpf_attr *attr, struct bpf_prog *prog);
335348
int cgroup_bpf_prog_query(const union bpf_attr *attr,
336349
union bpf_attr __user *uattr);
337350
#else
@@ -354,6 +367,12 @@ static inline int cgroup_bpf_prog_detach(const union bpf_attr *attr,
354367
return -EINVAL;
355368
}
356369

370+
static inline int cgroup_bpf_link_attach(const union bpf_attr *attr,
371+
struct bpf_prog *prog)
372+
{
373+
return -EINVAL;
374+
}
375+
357376
static inline int cgroup_bpf_prog_query(const union bpf_attr *attr,
358377
union bpf_attr __user *uattr)
359378
{

include/linux/bpf.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1082,15 +1082,23 @@ extern int sysctl_unprivileged_bpf_disabled;
10821082
int bpf_map_new_fd(struct bpf_map *map, int flags);
10831083
int bpf_prog_new_fd(struct bpf_prog *prog);
10841084

1085-
struct bpf_link;
1085+
struct bpf_link {
1086+
atomic64_t refcnt;
1087+
const struct bpf_link_ops *ops;
1088+
struct bpf_prog *prog;
1089+
struct work_struct work;
1090+
};
10861091

10871092
struct bpf_link_ops {
10881093
void (*release)(struct bpf_link *link);
10891094
void (*dealloc)(struct bpf_link *link);
1095+
10901096
};
10911097

10921098
void bpf_link_init(struct bpf_link *link, const struct bpf_link_ops *ops,
10931099
struct bpf_prog *prog);
1100+
void bpf_link_cleanup(struct bpf_link *link, struct file *link_file,
1101+
int link_fd);
10941102
void bpf_link_inc(struct bpf_link *link);
10951103
void bpf_link_put(struct bpf_link *link);
10961104
int bpf_link_new_fd(struct bpf_link *link);

include/uapi/linux/bpf.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ enum bpf_cmd {
111111
BPF_MAP_LOOKUP_AND_DELETE_BATCH,
112112
BPF_MAP_UPDATE_BATCH,
113113
BPF_MAP_DELETE_BATCH,
114+
BPF_LINK_CREATE,
114115
};
115116

116117
enum bpf_map_type {
@@ -541,7 +542,7 @@ union bpf_attr {
541542
__u32 prog_cnt;
542543
} query;
543544

544-
struct {
545+
struct { /* anonymous struct used by BPF_RAW_TRACEPOINT_OPEN command */
545546
__u64 name;
546547
__u32 prog_fd;
547548
} raw_tracepoint;
@@ -569,6 +570,13 @@ union bpf_attr {
569570
__u64 probe_offset; /* output: probe_offset */
570571
__u64 probe_addr; /* output: probe_addr */
571572
} task_fd_query;
573+
574+
struct { /* struct used by BPF_LINK_CREATE command */
575+
__u32 prog_fd; /* eBPF program to attach */
576+
__u32 target_fd; /* object to attach to */
577+
__u32 attach_type; /* attach type */
578+
__u32 flags; /* extra flags */
579+
} link_create;
572580
} __attribute__((aligned(8)));
573581

574582
/* The description below is an attempt at providing documentation to eBPF

0 commit comments

Comments
 (0)