Skip to content

Commit 16f6bf2

Browse files
Len Bakertorvalds
authored andcommitted
mm/list_lru.c: prefer struct_size over open coded arithmetic
As noted in the "Deprecated Interfaces, Language Features, Attributes, and Conventions" documentation [1], size calculations (especially multiplication) should not be performed in memory allocator (or similar) function arguments due to the risk of them overflowing. This could lead to values wrapping around and a smaller allocation being made than the caller was expecting. Using those allocations could lead to linear overflows of heap memory and other misbehaviors. So, use the struct_size() helper to do the arithmetic instead of the argument "size + count * size" in the kvmalloc() functions. Also, take the opportunity to refactor the memcpy() call to use the flex_array_size() helper. This code was detected with the help of Coccinelle and audited and fixed manually. [1] https://www.kernel.org/doc/html/latest/process/deprecated.html#open-coded-arithmetic-in-allocator-arguments Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Len Baker <[email protected]> Cc: Kees Cook <[email protected]> Cc: "Gustavo A. R. Silva" <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 38d4ef4 commit 16f6bf2

File tree

1 file changed

+3
-4
lines changed

1 file changed

+3
-4
lines changed

mm/list_lru.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -354,8 +354,7 @@ static int memcg_init_list_lru_node(struct list_lru_node *nlru)
354354
struct list_lru_memcg *memcg_lrus;
355355
int size = memcg_nr_cache_ids;
356356

357-
memcg_lrus = kvmalloc(sizeof(*memcg_lrus) +
358-
size * sizeof(void *), GFP_KERNEL);
357+
memcg_lrus = kvmalloc(struct_size(memcg_lrus, lru, size), GFP_KERNEL);
359358
if (!memcg_lrus)
360359
return -ENOMEM;
361360

@@ -389,7 +388,7 @@ static int memcg_update_list_lru_node(struct list_lru_node *nlru,
389388

390389
old = rcu_dereference_protected(nlru->memcg_lrus,
391390
lockdep_is_held(&list_lrus_mutex));
392-
new = kvmalloc(sizeof(*new) + new_size * sizeof(void *), GFP_KERNEL);
391+
new = kvmalloc(struct_size(new, lru, new_size), GFP_KERNEL);
393392
if (!new)
394393
return -ENOMEM;
395394

@@ -398,7 +397,7 @@ static int memcg_update_list_lru_node(struct list_lru_node *nlru,
398397
return -ENOMEM;
399398
}
400399

401-
memcpy(&new->lru, &old->lru, old_size * sizeof(void *));
400+
memcpy(&new->lru, &old->lru, flex_array_size(new, lru, old_size));
402401

403402
/*
404403
* The locking below allows readers that hold nlru->lock avoid taking

0 commit comments

Comments
 (0)