From c6325b075d714f78cf6f23b759221ca3aec29204 Mon Sep 17 00:00:00 2001 From: "Isaac J. Manjarres" Date: Fri, 6 Jun 2025 01:59:54 +0000 Subject: [PATCH] ANDROID: cgroup: Fix cgroup_root backport padding calculation ANDROID_BACKPORT_USE_ARRAY() needs to reserve enough space to fit a struct rcu_head at a minimum, and it reserves enough space for CGROUP_SUBSYS_COUNT atomic_ts. This works well on kernel configurations where the number of CGROUP_SUBSYS_COUNT is big enough to cause more space than what is needed for struct rcu_head to be reserved. However, for kernel configurations where CGROUP_SUBSYS_COUNT is too small and doesn't reserve enough space, the following build error is triggered: error: static assertion failed due to requirement 'sizeof(struct cgroup_root::(unnamed ...) <= sizeof(struct cgroup_root::(unnamed at ...))': struct callback_head rcu is larger than u8 __attribute__((__aligned__(8))) android_backport_reserved1[CGROUP_SUBSYS_COUNT * sizeof(atomic_t)] Instead of assuming CGROUP_SUBSYS_COUNT is large enough, given that the minimum size if the size of struct rcu_head, always make sure that much space is reserved if CGROUP_SUBSYS_COUNT is too small. Bug: 422866230 Fixes: d66e9166bfa1 ("ANDROID: fix ABI-break in struct cgroup_root") Change-Id: Ib34c9249c05c4ecfbf9c6d18b613afdd7dff5cb2 Signed-off-by: Isaac J. Manjarres --- include/linux/cgroup-defs.h | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h index 87c57b18b899..78320acce7b0 100644 --- a/include/linux/cgroup-defs.h +++ b/include/linux/cgroup-defs.h @@ -41,6 +41,24 @@ struct poll_table_struct; /* define the enumeration of all cgroup subsystems */ #define SUBSYS(_x) _x ## _cgrp_id, + +#define CSS_COUNTERS_SIZE (CGROUP_SUBSYS_COUNT * sizeof(atomic_t)) + +/* + * This should just use max(), but max() doesn't work in struct definitions. + * + * Originally, the space was reserved for per cgroup subsystem counters, where each counter was + * the size of an atomic_t variable. However, it was later reused to fit a struct rcu_head + * which is why the calculation considers the size of struct rcu_head. + * + * This macro is provided to ANDROID_BACKPORT_USE_ARRAY() which needs to reserve at least + * enough memory to accommodate struct rcu_head. However, if we only reserve CSS_COUNTERS_SIZE, + * that may not be enough space on kernels with a small amount of cgroup subsystems enabled. So, + * we take the max between the two values to use in ANDROID_BACKPORT_USE_ARRAY(). + */ +#define CGROUP_ROOT_BACKPORT_PADDING_SIZE \ + (CSS_COUNTERS_SIZE > sizeof(struct rcu_head) ? CSS_COUNTERS_SIZE : sizeof(struct rcu_head)) + enum cgroup_subsys_id { #include CGROUP_SUBSYS_COUNT, @@ -585,8 +603,12 @@ struct cgroup_root { /* The name for this hierarchy - may be empty */ char name[MAX_CGROUP_ROOT_NAMELEN]; - ANDROID_BACKPORT_USE_ARRAY(1, CGROUP_SUBSYS_COUNT * sizeof(atomic_t), - struct rcu_head rcu); + /* Use the original calculation to preserve the CRC value for the ABI. */ +#ifndef __GENKSYMS__ + ANDROID_BACKPORT_USE_ARRAY(1, CGROUP_ROOT_BACKPORT_PADDING_SIZE, struct rcu_head rcu); +#else + ANDROID_BACKPORT_USE_ARRAY(1, CGROUP_SUBSYS_COUNT * sizeof(atomic_t), struct rcu_head rcu); +#endif }; /*