mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 08:38:45 +02:00 
			
		
		
		
	cgroup: Fixes for v6.12-rc5
- cgroup_bpf_release_fn() could saturate system_wq with cgrp->bpf.release_work which can then form a circular dependency leading to deadlocks. Fix by using a dedicated workqueue. The system_wq's max concurrency limit is being increased separately. - Fix theoretical off-by-one bug when enforcing max cgroup hierarchy depth. -----BEGIN PGP SIGNATURE----- iIQEABYKACwWIQTfIjM1kS57o3GsC/uxYfJx3gVYGQUCZyGCPA4cdGpAa2VybmVs Lm9yZwAKCRCxYfJx3gVYGS2MAQDmtRNBlDYl36fiLAsylU4Coz5P0Y4ISmtSWT+c zrEUZAD/WKSlCfy4RFngmnfkYbrJ+tWOVTMtsDqby8IzYLDGBw8= =glRQ -----END PGP SIGNATURE----- Merge tag 'cgroup-for-6.12-rc5-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup Pull cgroup fixes from Tejun Heo: - cgroup_bpf_release_fn() could saturate system_wq with cgrp->bpf.release_work which can then form a circular dependency leading to deadlocks. Fix by using a dedicated workqueue. The system_wq's max concurrency limit is being increased separately. - Fix theoretical off-by-one bug when enforcing max cgroup hierarchy depth * tag 'cgroup-for-6.12-rc5-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup: cgroup: Fix potential overflow issue when checking max_depth cgroup/bpf: use a dedicated workqueue for cgroup bpf destruction
This commit is contained in:
		
						commit
						c1e939a21e
					
				
					 2 changed files with 20 additions and 3 deletions
				
			
		|  | @ -24,6 +24,23 @@ | ||||||
| DEFINE_STATIC_KEY_ARRAY_FALSE(cgroup_bpf_enabled_key, MAX_CGROUP_BPF_ATTACH_TYPE); | DEFINE_STATIC_KEY_ARRAY_FALSE(cgroup_bpf_enabled_key, MAX_CGROUP_BPF_ATTACH_TYPE); | ||||||
| EXPORT_SYMBOL(cgroup_bpf_enabled_key); | EXPORT_SYMBOL(cgroup_bpf_enabled_key); | ||||||
| 
 | 
 | ||||||
|  | /*
 | ||||||
|  |  * cgroup bpf destruction makes heavy use of work items and there can be a lot | ||||||
|  |  * of concurrent destructions.  Use a separate workqueue so that cgroup bpf | ||||||
|  |  * destruction work items don't end up filling up max_active of system_wq | ||||||
|  |  * which may lead to deadlock. | ||||||
|  |  */ | ||||||
|  | static struct workqueue_struct *cgroup_bpf_destroy_wq; | ||||||
|  | 
 | ||||||
|  | static int __init cgroup_bpf_wq_init(void) | ||||||
|  | { | ||||||
|  | 	cgroup_bpf_destroy_wq = alloc_workqueue("cgroup_bpf_destroy", 0, 1); | ||||||
|  | 	if (!cgroup_bpf_destroy_wq) | ||||||
|  | 		panic("Failed to alloc workqueue for cgroup bpf destroy.\n"); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | core_initcall(cgroup_bpf_wq_init); | ||||||
|  | 
 | ||||||
| /* __always_inline is necessary to prevent indirect call through run_prog
 | /* __always_inline is necessary to prevent indirect call through run_prog
 | ||||||
|  * function pointer. |  * function pointer. | ||||||
|  */ |  */ | ||||||
|  | @ -334,7 +351,7 @@ static void cgroup_bpf_release_fn(struct percpu_ref *ref) | ||||||
| 	struct cgroup *cgrp = container_of(ref, struct cgroup, bpf.refcnt); | 	struct cgroup *cgrp = container_of(ref, struct cgroup, bpf.refcnt); | ||||||
| 
 | 
 | ||||||
| 	INIT_WORK(&cgrp->bpf.release_work, cgroup_bpf_release); | 	INIT_WORK(&cgrp->bpf.release_work, cgroup_bpf_release); | ||||||
| 	queue_work(system_wq, &cgrp->bpf.release_work); | 	queue_work(cgroup_bpf_destroy_wq, &cgrp->bpf.release_work); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Get underlying bpf_prog of bpf_prog_list entry, regardless if it's through
 | /* Get underlying bpf_prog of bpf_prog_list entry, regardless if it's through
 | ||||||
|  |  | ||||||
|  | @ -5789,7 +5789,7 @@ static bool cgroup_check_hierarchy_limits(struct cgroup *parent) | ||||||
| { | { | ||||||
| 	struct cgroup *cgroup; | 	struct cgroup *cgroup; | ||||||
| 	int ret = false; | 	int ret = false; | ||||||
| 	int level = 1; | 	int level = 0; | ||||||
| 
 | 
 | ||||||
| 	lockdep_assert_held(&cgroup_mutex); | 	lockdep_assert_held(&cgroup_mutex); | ||||||
| 
 | 
 | ||||||
|  | @ -5797,7 +5797,7 @@ static bool cgroup_check_hierarchy_limits(struct cgroup *parent) | ||||||
| 		if (cgroup->nr_descendants >= cgroup->max_descendants) | 		if (cgroup->nr_descendants >= cgroup->max_descendants) | ||||||
| 			goto fail; | 			goto fail; | ||||||
| 
 | 
 | ||||||
| 		if (level > cgroup->max_depth) | 		if (level >= cgroup->max_depth) | ||||||
| 			goto fail; | 			goto fail; | ||||||
| 
 | 
 | ||||||
| 		level++; | 		level++; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Linus Torvalds
						Linus Torvalds