| From c5588929a64ca65b0d596d496c04105e67dce509 Mon Sep 17 00:00:00 2001 |
| From: Eugeniu Rosca <erosca@de.adit-jv.com> |
| Date: Fri, 4 Sep 2020 16:35:30 -0700 |
| Subject: [PATCH] mm: slub: fix conversion of freelist_corrupted() |
| |
| commit dc07a728d49cf025f5da2c31add438d839d076c0 upstream. |
| |
| Commit 52f23478081ae0 ("mm/slub.c: fix corrupted freechain in |
| deactivate_slab()") suffered an update when picked up from LKML [1]. |
| |
| Specifically, relocating 'freelist = NULL' into 'freelist_corrupted()' |
| created a no-op statement. Fix it by sticking to the behavior intended |
| in the original patch [1]. In addition, make freelist_corrupted() |
| immune to passing NULL instead of &freelist. |
| |
| The issue has been spotted via static analysis and code review. |
| |
| [1] https://lore.kernel.org/linux-mm/20200331031450.12182-1-dongli.zhang@oracle.com/ |
| |
| Fixes: 52f23478081ae0 ("mm/slub.c: fix corrupted freechain in deactivate_slab()") |
| Signed-off-by: Eugeniu Rosca <erosca@de.adit-jv.com> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Cc: Dongli Zhang <dongli.zhang@oracle.com> |
| Cc: Joe Jin <joe.jin@oracle.com> |
| Cc: Christoph Lameter <cl@linux.com> |
| Cc: Pekka Enberg <penberg@kernel.org> |
| Cc: David Rientjes <rientjes@google.com> |
| Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com> |
| Cc: <stable@vger.kernel.org> |
| Link: https://lkml.kernel.org/r/20200824130643.10291-1-erosca@de.adit-jv.com |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/mm/slub.c b/mm/slub.c |
| index 9e7da3b8bd0a..04a46eaea862 100644 |
| --- a/mm/slub.c |
| +++ b/mm/slub.c |
| @@ -645,12 +645,12 @@ static void slab_fix(struct kmem_cache *s, char *fmt, ...) |
| } |
| |
| static bool freelist_corrupted(struct kmem_cache *s, struct page *page, |
| - void *freelist, void *nextfree) |
| + void **freelist, void *nextfree) |
| { |
| if ((s->flags & SLAB_CONSISTENCY_CHECKS) && |
| - !check_valid_pointer(s, page, nextfree)) { |
| - object_err(s, page, freelist, "Freechain corrupt"); |
| - freelist = NULL; |
| + !check_valid_pointer(s, page, nextfree) && freelist) { |
| + object_err(s, page, *freelist, "Freechain corrupt"); |
| + *freelist = NULL; |
| slab_fix(s, "Isolate corrupted freechain"); |
| return true; |
| } |
| @@ -1391,7 +1391,7 @@ static inline void dec_slabs_node(struct kmem_cache *s, int node, |
| int objects) {} |
| |
| static bool freelist_corrupted(struct kmem_cache *s, struct page *page, |
| - void *freelist, void *nextfree) |
| + void **freelist, void *nextfree) |
| { |
| return false; |
| } |
| @@ -2089,7 +2089,7 @@ static void deactivate_slab(struct kmem_cache *s, struct page *page, |
| * 'freelist' is already corrupted. So isolate all objects |
| * starting at 'freelist'. |
| */ |
| - if (freelist_corrupted(s, page, freelist, nextfree)) |
| + if (freelist_corrupted(s, page, &freelist, nextfree)) |
| break; |
| |
| do { |
| -- |
| 2.27.0 |
| |