Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mm/memcg: v1: account event registrations and drop world-writable cgroup.event_control

In cgroup v1, the legacy cgroup.event_control file is world-writable and
allows unprivileged users to register unbounded events and thresholds.
Each registration allocates kernel memory without capping or memcg
charging, which can be abused to exhaust kernel memory in affected
configurations.

Make the following minimal changes:
- Account allocations with __GFP_ACCOUNT in event and threshold registration.
- Remove CFTYPE_WORLD_WRITABLE from cgroup.event_control to make it
owner-writable.

This does not affect cgroup v2. Allocations are still subject to kmem
accounting being enabled, but this reduces unbounded global growth.

Link: https://lkml.kernel.org/r/20250905093851.80596-1-disclosure@aisle.com
Signed-off-by: Stanislav Fort <disclosure@aisle.com>
Acked-by: Roman Gushchin <roman.gushchin@linux.dev>
Acked-by: Shakeel Butt <shakeel.butt@linux.dev>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Muchun Song <muchun.song@linux.dev>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Stanislav Fort and committed by
Andrew Morton
72797d21 f83938e4

+4 -4
+4 -4
mm/memcontrol-v1.c
··· 761 761 size = thresholds->primary ? thresholds->primary->size + 1 : 1; 762 762 763 763 /* Allocate memory for new array of thresholds */ 764 - new = kmalloc(struct_size(new, entries, size), GFP_KERNEL); 764 + new = kmalloc(struct_size(new, entries, size), GFP_KERNEL_ACCOUNT); 765 765 if (!new) { 766 766 ret = -ENOMEM; 767 767 goto unlock; ··· 924 924 { 925 925 struct mem_cgroup_eventfd_list *event; 926 926 927 - event = kmalloc(sizeof(*event), GFP_KERNEL); 927 + event = kmalloc(sizeof(*event), GFP_KERNEL_ACCOUNT); 928 928 if (!event) 929 929 return -ENOMEM; 930 930 ··· 1087 1087 1088 1088 CLASS(fd, cfile)(cfd); 1089 1089 1090 - event = kzalloc(sizeof(*event), GFP_KERNEL); 1090 + event = kzalloc(sizeof(*event), GFP_KERNEL_ACCOUNT); 1091 1091 if (!event) 1092 1092 return -ENOMEM; 1093 1093 ··· 2053 2053 { 2054 2054 .name = "cgroup.event_control", /* XXX: for compat */ 2055 2055 .write = memcg_write_event_control, 2056 - .flags = CFTYPE_NO_PREFIX | CFTYPE_WORLD_WRITABLE, 2056 + .flags = CFTYPE_NO_PREFIX, 2057 2057 }, 2058 2058 { 2059 2059 .name = "swappiness",