mm/percpu.c: append alignment sanity checkup to avoid memory leakage
Subsystems (2)
PATCH 1/1 mm/percpu.c: append alignment sanity checkup to avoid memory leakage
From: zijun_hu <[email protected]>
the percpu allocator only works well currently when allocates a power of 2 aligned area, but there aren't any hints for alignment requirement, so memory leakage maybe be caused if allocate other alignment areas
the alignment must be a even at least since the LSB of a chunk->map element is used as free/in-use flag of a area; besides, the alignment must be a power of 2 too since ALIGN() doesn't work well for other alignment always but is adopted by pcpu_fit_in_area(). IOW, the current allocator only works well for a power of 2 aligned area allocation.
see below opposite example for why a odd alignment doesn't work lets assume area [16, 36) is free but its previous one is in-use, we want to allocate a @size == 8 and @align == 7 area. the larger area [16, 36) is split to three areas [16, 21), [21, 29), [29, 36) eventually. however, due to the usage for a chunk->map element, the actual offset of the aim area [21, 29) is 21 but is recorded in relevant element as 20; moreover the residual tail free area [29, 36) is mistook as in-use and is lost silently
unlike macro roundup(), ALIGN(x, a) doesn't work if @a isn't a power of 2 for example, roundup(10, 6) == 12 but ALIGN(10, 6) == 10, and the latter result isn't desired obviously.
fix it by appending sanity checkup for alignment requirement
--- include/linux/kernel.h | 1 + mm/percpu.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-)
include/linux/kernel.h +1 -0
@@ -45,6 +45,7 @@#define REPEAT_BYTE (x) ((~0ul / 0xff) * (x)) +/* @a is a power of 2 value */ #define ALIGN (x, a) __ALIGN_KERNEL((x), (a))#define __ALIGN_MASK (x, mask) __ALIGN_KERNEL_MASK((x), (mask))#define PTR_ALIGN (p, a) ((typeof(p))ALIGN((unsigned long)(p), (a)))
mm/percpu.c +2 -1
@@ -886,7 +886,8 @@ static void __percpu *pcpu_alloc(size_t size, size_t align, bool reserved, size =ALIGN (size,2 ); -if (unlikely (!size || size >PCPU_MIN_UNIT_SIZE || align >PAGE_SIZE )) { +if (unlikely (!size || size >PCPU_MIN_UNIT_SIZE || align >PAGE_SIZE + || !is_power_of_2 (align))) {WARN (true,"illegal size (%zu) or align (%zu) for percpu allocation\n" , size, align);return NULL ;
Signature · 7 lines
1.9.1 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Tejun Heo
maintainerHello,
I updated the patch description and code style a bit and applied to percpu/for-4.10.
Thanks.
------ 8< ------