diff options
Diffstat (limited to 'kernel/bpf/cgroup.c')
-rw-r--r-- | kernel/bpf/cgroup.c | 74 |
1 files changed, 52 insertions, 22 deletions
diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c index 549f6fbcc461..00f6ed2e4f9a 100644 --- a/kernel/bpf/cgroup.c +++ b/kernel/bpf/cgroup.c | |||
@@ -25,6 +25,7 @@ EXPORT_SYMBOL(cgroup_bpf_enabled_key); | |||
25 | */ | 25 | */ |
26 | void cgroup_bpf_put(struct cgroup *cgrp) | 26 | void cgroup_bpf_put(struct cgroup *cgrp) |
27 | { | 27 | { |
28 | enum bpf_cgroup_storage_type stype; | ||
28 | unsigned int type; | 29 | unsigned int type; |
29 | 30 | ||
30 | for (type = 0; type < ARRAY_SIZE(cgrp->bpf.progs); type++) { | 31 | for (type = 0; type < ARRAY_SIZE(cgrp->bpf.progs); type++) { |
@@ -34,8 +35,10 @@ void cgroup_bpf_put(struct cgroup *cgrp) | |||
34 | list_for_each_entry_safe(pl, tmp, progs, node) { | 35 | list_for_each_entry_safe(pl, tmp, progs, node) { |
35 | list_del(&pl->node); | 36 | list_del(&pl->node); |
36 | bpf_prog_put(pl->prog); | 37 | bpf_prog_put(pl->prog); |
37 | bpf_cgroup_storage_unlink(pl->storage); | 38 | for_each_cgroup_storage_type(stype) { |
38 | bpf_cgroup_storage_free(pl->storage); | 39 | bpf_cgroup_storage_unlink(pl->storage[stype]); |
40 | bpf_cgroup_storage_free(pl->storage[stype]); | ||
41 | } | ||
39 | kfree(pl); | 42 | kfree(pl); |
40 | static_branch_dec(&cgroup_bpf_enabled_key); | 43 | static_branch_dec(&cgroup_bpf_enabled_key); |
41 | } | 44 | } |
@@ -97,6 +100,7 @@ static int compute_effective_progs(struct cgroup *cgrp, | |||
97 | enum bpf_attach_type type, | 100 | enum bpf_attach_type type, |
98 | struct bpf_prog_array __rcu **array) | 101 | struct bpf_prog_array __rcu **array) |
99 | { | 102 | { |
103 | enum bpf_cgroup_storage_type stype; | ||
100 | struct bpf_prog_array *progs; | 104 | struct bpf_prog_array *progs; |
101 | struct bpf_prog_list *pl; | 105 | struct bpf_prog_list *pl; |
102 | struct cgroup *p = cgrp; | 106 | struct cgroup *p = cgrp; |
@@ -125,7 +129,9 @@ static int compute_effective_progs(struct cgroup *cgrp, | |||
125 | continue; | 129 | continue; |
126 | 130 | ||
127 | progs->items[cnt].prog = pl->prog; | 131 | progs->items[cnt].prog = pl->prog; |
128 | progs->items[cnt].cgroup_storage = pl->storage; | 132 | for_each_cgroup_storage_type(stype) |
133 | progs->items[cnt].cgroup_storage[stype] = | ||
134 | pl->storage[stype]; | ||
129 | cnt++; | 135 | cnt++; |
130 | } | 136 | } |
131 | } while ((p = cgroup_parent(p))); | 137 | } while ((p = cgroup_parent(p))); |
@@ -232,7 +238,9 @@ int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog, | |||
232 | { | 238 | { |
233 | struct list_head *progs = &cgrp->bpf.progs[type]; | 239 | struct list_head *progs = &cgrp->bpf.progs[type]; |
234 | struct bpf_prog *old_prog = NULL; | 240 | struct bpf_prog *old_prog = NULL; |
235 | struct bpf_cgroup_storage *storage, *old_storage = NULL; | 241 | struct bpf_cgroup_storage *storage[MAX_BPF_CGROUP_STORAGE_TYPE], |
242 | *old_storage[MAX_BPF_CGROUP_STORAGE_TYPE] = {NULL}; | ||
243 | enum bpf_cgroup_storage_type stype; | ||
236 | struct bpf_prog_list *pl; | 244 | struct bpf_prog_list *pl; |
237 | bool pl_was_allocated; | 245 | bool pl_was_allocated; |
238 | int err; | 246 | int err; |
@@ -254,34 +262,44 @@ int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog, | |||
254 | if (prog_list_length(progs) >= BPF_CGROUP_MAX_PROGS) | 262 | if (prog_list_length(progs) >= BPF_CGROUP_MAX_PROGS) |
255 | return -E2BIG; | 263 | return -E2BIG; |
256 | 264 | ||
257 | storage = bpf_cgroup_storage_alloc(prog); | 265 | for_each_cgroup_storage_type(stype) { |
258 | if (IS_ERR(storage)) | 266 | storage[stype] = bpf_cgroup_storage_alloc(prog, stype); |
259 | return -ENOMEM; | 267 | if (IS_ERR(storage[stype])) { |
268 | storage[stype] = NULL; | ||
269 | for_each_cgroup_storage_type(stype) | ||
270 | bpf_cgroup_storage_free(storage[stype]); | ||
271 | return -ENOMEM; | ||
272 | } | ||
273 | } | ||
260 | 274 | ||
261 | if (flags & BPF_F_ALLOW_MULTI) { | 275 | if (flags & BPF_F_ALLOW_MULTI) { |
262 | list_for_each_entry(pl, progs, node) { | 276 | list_for_each_entry(pl, progs, node) { |
263 | if (pl->prog == prog) { | 277 | if (pl->prog == prog) { |
264 | /* disallow attaching the same prog twice */ | 278 | /* disallow attaching the same prog twice */ |
265 | bpf_cgroup_storage_free(storage); | 279 | for_each_cgroup_storage_type(stype) |
280 | bpf_cgroup_storage_free(storage[stype]); | ||
266 | return -EINVAL; | 281 | return -EINVAL; |
267 | } | 282 | } |
268 | } | 283 | } |
269 | 284 | ||
270 | pl = kmalloc(sizeof(*pl), GFP_KERNEL); | 285 | pl = kmalloc(sizeof(*pl), GFP_KERNEL); |
271 | if (!pl) { | 286 | if (!pl) { |
272 | bpf_cgroup_storage_free(storage); | 287 | for_each_cgroup_storage_type(stype) |
288 | bpf_cgroup_storage_free(storage[stype]); | ||
273 | return -ENOMEM; | 289 | return -ENOMEM; |
274 | } | 290 | } |
275 | 291 | ||
276 | pl_was_allocated = true; | 292 | pl_was_allocated = true; |
277 | pl->prog = prog; | 293 | pl->prog = prog; |
278 | pl->storage = storage; | 294 | for_each_cgroup_storage_type(stype) |
295 | pl->storage[stype] = storage[stype]; | ||
279 | list_add_tail(&pl->node, progs); | 296 | list_add_tail(&pl->node, progs); |
280 | } else { | 297 | } else { |
281 | if (list_empty(progs)) { | 298 | if (list_empty(progs)) { |
282 | pl = kmalloc(sizeof(*pl), GFP_KERNEL); | 299 | pl = kmalloc(sizeof(*pl), GFP_KERNEL); |
283 | if (!pl) { | 300 | if (!pl) { |
284 | bpf_cgroup_storage_free(storage); | 301 | for_each_cgroup_storage_type(stype) |
302 | bpf_cgroup_storage_free(storage[stype]); | ||
285 | return -ENOMEM; | 303 | return -ENOMEM; |
286 | } | 304 | } |
287 | pl_was_allocated = true; | 305 | pl_was_allocated = true; |
@@ -289,12 +307,15 @@ int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog, | |||
289 | } else { | 307 | } else { |
290 | pl = list_first_entry(progs, typeof(*pl), node); | 308 | pl = list_first_entry(progs, typeof(*pl), node); |
291 | old_prog = pl->prog; | 309 | old_prog = pl->prog; |
292 | old_storage = pl->storage; | 310 | for_each_cgroup_storage_type(stype) { |
293 | bpf_cgroup_storage_unlink(old_storage); | 311 | old_storage[stype] = pl->storage[stype]; |
312 | bpf_cgroup_storage_unlink(old_storage[stype]); | ||
313 | } | ||
294 | pl_was_allocated = false; | 314 | pl_was_allocated = false; |
295 | } | 315 | } |
296 | pl->prog = prog; | 316 | pl->prog = prog; |
297 | pl->storage = storage; | 317 | for_each_cgroup_storage_type(stype) |
318 | pl->storage[stype] = storage[stype]; | ||
298 | } | 319 | } |
299 | 320 | ||
300 | cgrp->bpf.flags[type] = flags; | 321 | cgrp->bpf.flags[type] = flags; |
@@ -304,21 +325,27 @@ int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog, | |||
304 | goto cleanup; | 325 | goto cleanup; |
305 | 326 | ||
306 | static_branch_inc(&cgroup_bpf_enabled_key); | 327 | static_branch_inc(&cgroup_bpf_enabled_key); |
307 | if (old_storage) | 328 | for_each_cgroup_storage_type(stype) { |
308 | bpf_cgroup_storage_free(old_storage); | 329 | if (!old_storage[stype]) |
330 | continue; | ||
331 | bpf_cgroup_storage_free(old_storage[stype]); | ||
332 | } | ||
309 | if (old_prog) { | 333 | if (old_prog) { |
310 | bpf_prog_put(old_prog); | 334 | bpf_prog_put(old_prog); |
311 | static_branch_dec(&cgroup_bpf_enabled_key); | 335 | static_branch_dec(&cgroup_bpf_enabled_key); |
312 | } | 336 | } |
313 | bpf_cgroup_storage_link(storage, cgrp, type); | 337 | for_each_cgroup_storage_type(stype) |
338 | bpf_cgroup_storage_link(storage[stype], cgrp, type); | ||
314 | return 0; | 339 | return 0; |
315 | 340 | ||
316 | cleanup: | 341 | cleanup: |
317 | /* and cleanup the prog list */ | 342 | /* and cleanup the prog list */ |
318 | pl->prog = old_prog; | 343 | pl->prog = old_prog; |
319 | bpf_cgroup_storage_free(pl->storage); | 344 | for_each_cgroup_storage_type(stype) { |
320 | pl->storage = old_storage; | 345 | bpf_cgroup_storage_free(pl->storage[stype]); |
321 | bpf_cgroup_storage_link(old_storage, cgrp, type); | 346 | pl->storage[stype] = old_storage[stype]; |
347 | bpf_cgroup_storage_link(old_storage[stype], cgrp, type); | ||
348 | } | ||
322 | if (pl_was_allocated) { | 349 | if (pl_was_allocated) { |
323 | list_del(&pl->node); | 350 | list_del(&pl->node); |
324 | kfree(pl); | 351 | kfree(pl); |
@@ -339,6 +366,7 @@ int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog, | |||
339 | enum bpf_attach_type type, u32 unused_flags) | 366 | enum bpf_attach_type type, u32 unused_flags) |
340 | { | 367 | { |
341 | struct list_head *progs = &cgrp->bpf.progs[type]; | 368 | struct list_head *progs = &cgrp->bpf.progs[type]; |
369 | enum bpf_cgroup_storage_type stype; | ||
342 | u32 flags = cgrp->bpf.flags[type]; | 370 | u32 flags = cgrp->bpf.flags[type]; |
343 | struct bpf_prog *old_prog = NULL; | 371 | struct bpf_prog *old_prog = NULL; |
344 | struct bpf_prog_list *pl; | 372 | struct bpf_prog_list *pl; |
@@ -385,8 +413,10 @@ int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog, | |||
385 | 413 | ||
386 | /* now can actually delete it from this cgroup list */ | 414 | /* now can actually delete it from this cgroup list */ |
387 | list_del(&pl->node); | 415 | list_del(&pl->node); |
388 | bpf_cgroup_storage_unlink(pl->storage); | 416 | for_each_cgroup_storage_type(stype) { |
389 | bpf_cgroup_storage_free(pl->storage); | 417 | bpf_cgroup_storage_unlink(pl->storage[stype]); |
418 | bpf_cgroup_storage_free(pl->storage[stype]); | ||
419 | } | ||
390 | kfree(pl); | 420 | kfree(pl); |
391 | if (list_empty(progs)) | 421 | if (list_empty(progs)) |
392 | /* last program was detached, reset flags to zero */ | 422 | /* last program was detached, reset flags to zero */ |