cgroup.c (5bf7a60b8e70969f65c961d7e2c4eb40eb2c664d) | cgroup.c (8bad74f9840f87661f20ced3dc80c84ab4fd55a1) |
---|---|
1/* 2 * Functions to manage eBPF programs attached to cgroups 3 * 4 * Copyright (c) 2016 Daniel Mack 5 * 6 * This file is subject to the terms and conditions of version 2 of the GNU 7 * General Public License. See the file COPYING in the main directory of the 8 * Linux distribution for more details. --- 11 unchanged lines hidden (view full) --- 20EXPORT_SYMBOL(cgroup_bpf_enabled_key); 21 22/** 23 * cgroup_bpf_put() - put references of all bpf programs 24 * @cgrp: the cgroup to modify 25 */ 26void cgroup_bpf_put(struct cgroup *cgrp) 27{ | 1/* 2 * Functions to manage eBPF programs attached to cgroups 3 * 4 * Copyright (c) 2016 Daniel Mack 5 * 6 * This file is subject to the terms and conditions of version 2 of the GNU 7 * General Public License. See the file COPYING in the main directory of the 8 * Linux distribution for more details. --- 11 unchanged lines hidden (view full) --- 20EXPORT_SYMBOL(cgroup_bpf_enabled_key); 21 22/** 23 * cgroup_bpf_put() - put references of all bpf programs 24 * @cgrp: the cgroup to modify 25 */ 26void cgroup_bpf_put(struct cgroup *cgrp) 27{ |
28 enum bpf_cgroup_storage_type stype; |
|
28 unsigned int type; 29 30 for (type = 0; type < ARRAY_SIZE(cgrp->bpf.progs); type++) { 31 struct list_head *progs = &cgrp->bpf.progs[type]; 32 struct bpf_prog_list *pl, *tmp; 33 34 list_for_each_entry_safe(pl, tmp, progs, node) { 35 list_del(&pl->node); 36 bpf_prog_put(pl->prog); | 29 unsigned int type; 30 31 for (type = 0; type < ARRAY_SIZE(cgrp->bpf.progs); type++) { 32 struct list_head *progs = &cgrp->bpf.progs[type]; 33 struct bpf_prog_list *pl, *tmp; 34 35 list_for_each_entry_safe(pl, tmp, progs, node) { 36 list_del(&pl->node); 37 bpf_prog_put(pl->prog); |
37 bpf_cgroup_storage_unlink(pl->storage); 38 bpf_cgroup_storage_free(pl->storage); | 38 for_each_cgroup_storage_type(stype) { 39 bpf_cgroup_storage_unlink(pl->storage[stype]); 40 bpf_cgroup_storage_free(pl->storage[stype]); 41 } |
39 kfree(pl); 40 static_branch_dec(&cgroup_bpf_enabled_key); 41 } 42 bpf_prog_array_free(cgrp->bpf.effective[type]); 43 } 44} 45 46/* count number of elements in the list. --- 45 unchanged lines hidden (view full) --- 92 * all parent programs. 93 * Note that parent's F_ALLOW_OVERRIDE-type program is yielding 94 * to programs in this cgroup 95 */ 96static int compute_effective_progs(struct cgroup *cgrp, 97 enum bpf_attach_type type, 98 struct bpf_prog_array __rcu **array) 99{ | 42 kfree(pl); 43 static_branch_dec(&cgroup_bpf_enabled_key); 44 } 45 bpf_prog_array_free(cgrp->bpf.effective[type]); 46 } 47} 48 49/* count number of elements in the list. --- 45 unchanged lines hidden (view full) --- 95 * all parent programs. 96 * Note that parent's F_ALLOW_OVERRIDE-type program is yielding 97 * to programs in this cgroup 98 */ 99static int compute_effective_progs(struct cgroup *cgrp, 100 enum bpf_attach_type type, 101 struct bpf_prog_array __rcu **array) 102{ |
103 enum bpf_cgroup_storage_type stype; |
|
100 struct bpf_prog_array *progs; 101 struct bpf_prog_list *pl; 102 struct cgroup *p = cgrp; 103 int cnt = 0; 104 105 /* count number of effective programs by walking parents */ 106 do { 107 if (cnt == 0 || (p->bpf.flags[type] & BPF_F_ALLOW_MULTI)) --- 12 unchanged lines hidden (view full) --- 120 if (cnt > 0 && !(p->bpf.flags[type] & BPF_F_ALLOW_MULTI)) 121 continue; 122 123 list_for_each_entry(pl, &p->bpf.progs[type], node) { 124 if (!pl->prog) 125 continue; 126 127 progs->items[cnt].prog = pl->prog; | 104 struct bpf_prog_array *progs; 105 struct bpf_prog_list *pl; 106 struct cgroup *p = cgrp; 107 int cnt = 0; 108 109 /* count number of effective programs by walking parents */ 110 do { 111 if (cnt == 0 || (p->bpf.flags[type] & BPF_F_ALLOW_MULTI)) --- 12 unchanged lines hidden (view full) --- 124 if (cnt > 0 && !(p->bpf.flags[type] & BPF_F_ALLOW_MULTI)) 125 continue; 126 127 list_for_each_entry(pl, &p->bpf.progs[type], node) { 128 if (!pl->prog) 129 continue; 130 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++; 130 } 131 } while ((p = cgroup_parent(p))); 132 133 rcu_assign_pointer(*array, progs); 134 return 0; 135} 136 --- 90 unchanged lines hidden (view full) --- 227 * 228 * Must be called with cgroup_mutex held. 229 */ 230int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog, 231 enum bpf_attach_type type, u32 flags) 232{ 233 struct list_head *progs = &cgrp->bpf.progs[type]; 234 struct bpf_prog *old_prog = NULL; | 135 cnt++; 136 } 137 } while ((p = cgroup_parent(p))); 138 139 rcu_assign_pointer(*array, progs); 140 return 0; 141} 142 --- 90 unchanged lines hidden (view full) --- 233 * 234 * Must be called with cgroup_mutex held. 235 */ 236int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog, 237 enum bpf_attach_type type, u32 flags) 238{ 239 struct list_head *progs = &cgrp->bpf.progs[type]; 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; 237 bool pl_was_allocated; 238 int err; 239 240 if ((flags & BPF_F_ALLOW_OVERRIDE) && (flags & BPF_F_ALLOW_MULTI)) 241 /* invalid combination */ 242 return -EINVAL; 243 --- 5 unchanged lines hidden (view full) --- 249 * of existing overridable in this cgroup. 250 * Disallow attaching multi-prog if overridable or none 251 */ 252 return -EPERM; 253 254 if (prog_list_length(progs) >= BPF_CGROUP_MAX_PROGS) 255 return -E2BIG; 256 | 244 struct bpf_prog_list *pl; 245 bool pl_was_allocated; 246 int err; 247 248 if ((flags & BPF_F_ALLOW_OVERRIDE) && (flags & BPF_F_ALLOW_MULTI)) 249 /* invalid combination */ 250 return -EINVAL; 251 --- 5 unchanged lines hidden (view full) --- 257 * of existing overridable in this cgroup. 258 * Disallow attaching multi-prog if overridable or none 259 */ 260 return -EPERM; 261 262 if (prog_list_length(progs) >= BPF_CGROUP_MAX_PROGS) 263 return -E2BIG; 264 |
257 storage = bpf_cgroup_storage_alloc(prog); 258 if (IS_ERR(storage)) 259 return -ENOMEM; | 265 for_each_cgroup_storage_type(stype) { 266 storage[stype] = bpf_cgroup_storage_alloc(prog, stype); 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 261 if (flags & BPF_F_ALLOW_MULTI) { 262 list_for_each_entry(pl, progs, node) { 263 if (pl->prog == prog) { 264 /* disallow attaching the same prog twice */ | 274 275 if (flags & BPF_F_ALLOW_MULTI) { 276 list_for_each_entry(pl, progs, node) { 277 if (pl->prog == prog) { 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; 267 } 268 } 269 270 pl = kmalloc(sizeof(*pl), GFP_KERNEL); 271 if (!pl) { | 281 return -EINVAL; 282 } 283 } 284 285 pl = kmalloc(sizeof(*pl), GFP_KERNEL); 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; 274 } 275 276 pl_was_allocated = true; 277 pl->prog = prog; | 289 return -ENOMEM; 290 } 291 292 pl_was_allocated = true; 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); 280 } else { 281 if (list_empty(progs)) { 282 pl = kmalloc(sizeof(*pl), GFP_KERNEL); 283 if (!pl) { | 296 list_add_tail(&pl->node, progs); 297 } else { 298 if (list_empty(progs)) { 299 pl = kmalloc(sizeof(*pl), GFP_KERNEL); 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; 286 } 287 pl_was_allocated = true; 288 list_add_tail(&pl->node, progs); 289 } else { 290 pl = list_first_entry(progs, typeof(*pl), node); 291 old_prog = pl->prog; | 303 return -ENOMEM; 304 } 305 pl_was_allocated = true; 306 list_add_tail(&pl->node, progs); 307 } else { 308 pl = list_first_entry(progs, typeof(*pl), node); 309 old_prog = pl->prog; |
292 old_storage = pl->storage; 293 bpf_cgroup_storage_unlink(old_storage); | 310 for_each_cgroup_storage_type(stype) { 311 old_storage[stype] = pl->storage[stype]; 312 bpf_cgroup_storage_unlink(old_storage[stype]); 313 } |
294 pl_was_allocated = false; 295 } 296 pl->prog = prog; | 314 pl_was_allocated = false; 315 } 316 pl->prog = prog; |
297 pl->storage = storage; | 317 for_each_cgroup_storage_type(stype) 318 pl->storage[stype] = storage[stype]; |
298 } 299 300 cgrp->bpf.flags[type] = flags; 301 302 err = update_effective_progs(cgrp, type); 303 if (err) 304 goto cleanup; 305 306 static_branch_inc(&cgroup_bpf_enabled_key); | 319 } 320 321 cgrp->bpf.flags[type] = flags; 322 323 err = update_effective_progs(cgrp, type); 324 if (err) 325 goto cleanup; 326 327 static_branch_inc(&cgroup_bpf_enabled_key); |
307 if (old_storage) 308 bpf_cgroup_storage_free(old_storage); | 328 for_each_cgroup_storage_type(stype) { 329 if (!old_storage[stype]) 330 continue; 331 bpf_cgroup_storage_free(old_storage[stype]); 332 } |
309 if (old_prog) { 310 bpf_prog_put(old_prog); 311 static_branch_dec(&cgroup_bpf_enabled_key); 312 } | 333 if (old_prog) { 334 bpf_prog_put(old_prog); 335 static_branch_dec(&cgroup_bpf_enabled_key); 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; 315 316cleanup: 317 /* and cleanup the prog list */ 318 pl->prog = old_prog; | 339 return 0; 340 341cleanup: 342 /* and cleanup the prog list */ 343 pl->prog = old_prog; |
319 bpf_cgroup_storage_free(pl->storage); 320 pl->storage = old_storage; 321 bpf_cgroup_storage_link(old_storage, cgrp, type); | 344 for_each_cgroup_storage_type(stype) { 345 bpf_cgroup_storage_free(pl->storage[stype]); 346 pl->storage[stype] = old_storage[stype]; 347 bpf_cgroup_storage_link(old_storage[stype], cgrp, type); 348 } |
322 if (pl_was_allocated) { 323 list_del(&pl->node); 324 kfree(pl); 325 } 326 return err; 327} 328 329/** --- 4 unchanged lines hidden (view full) --- 334 * @type: Type of detach operation 335 * 336 * Must be called with cgroup_mutex held. 337 */ 338int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog, 339 enum bpf_attach_type type, u32 unused_flags) 340{ 341 struct list_head *progs = &cgrp->bpf.progs[type]; | 349 if (pl_was_allocated) { 350 list_del(&pl->node); 351 kfree(pl); 352 } 353 return err; 354} 355 356/** --- 4 unchanged lines hidden (view full) --- 361 * @type: Type of detach operation 362 * 363 * Must be called with cgroup_mutex held. 364 */ 365int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog, 366 enum bpf_attach_type type, u32 unused_flags) 367{ 368 struct list_head *progs = &cgrp->bpf.progs[type]; |
369 enum bpf_cgroup_storage_type stype; |
|
342 u32 flags = cgrp->bpf.flags[type]; 343 struct bpf_prog *old_prog = NULL; 344 struct bpf_prog_list *pl; 345 int err; 346 347 if (flags & BPF_F_ALLOW_MULTI) { 348 if (!prog) 349 /* to detach MULTI prog the user has to specify valid FD --- 30 unchanged lines hidden (view full) --- 380 } 381 382 err = update_effective_progs(cgrp, type); 383 if (err) 384 goto cleanup; 385 386 /* now can actually delete it from this cgroup list */ 387 list_del(&pl->node); | 370 u32 flags = cgrp->bpf.flags[type]; 371 struct bpf_prog *old_prog = NULL; 372 struct bpf_prog_list *pl; 373 int err; 374 375 if (flags & BPF_F_ALLOW_MULTI) { 376 if (!prog) 377 /* to detach MULTI prog the user has to specify valid FD --- 30 unchanged lines hidden (view full) --- 408 } 409 410 err = update_effective_progs(cgrp, type); 411 if (err) 412 goto cleanup; 413 414 /* now can actually delete it from this cgroup list */ 415 list_del(&pl->node); |
388 bpf_cgroup_storage_unlink(pl->storage); 389 bpf_cgroup_storage_free(pl->storage); | 416 for_each_cgroup_storage_type(stype) { 417 bpf_cgroup_storage_unlink(pl->storage[stype]); 418 bpf_cgroup_storage_free(pl->storage[stype]); 419 } |
390 kfree(pl); 391 if (list_empty(progs)) 392 /* last program was detached, reset flags to zero */ 393 cgrp->bpf.flags[type] = 0; 394 395 bpf_prog_put(old_prog); 396 static_branch_dec(&cgroup_bpf_enabled_key); 397 return 0; --- 329 unchanged lines hidden --- | 420 kfree(pl); 421 if (list_empty(progs)) 422 /* last program was detached, reset flags to zero */ 423 cgrp->bpf.flags[type] = 0; 424 425 bpf_prog_put(old_prog); 426 static_branch_dec(&cgroup_bpf_enabled_key); 427 return 0; --- 329 unchanged lines hidden --- |