[Devel] [PATCH RH7] slub_debug: fail allocation on a bad freelist pointer

Pavel Tikhomirov ptikhomirov at virtuozzo.com
Wed Jul 3 11:11:58 MSK 2024


We saw crashes where slub percpu freelist was corrupted, this may catch
the problem earlier where we first time see bad freelist, and suppress
further corruption.

This is enabled with 'slub_debug=F'.

https://virtuozzo.atlassian.net/browse/PSBM-155867

Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
---
v2: fixed compilation in case !CONFIG_SLUB_DEBUG
---
 mm/slub.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/mm/slub.c b/mm/slub.c
index d4392708a0148..748a4a036ff35 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1085,6 +1085,20 @@ static void setup_object_debug(struct kmem_cache *s, struct page *page,
 	init_tracking(s, object);
 }
 
+
+static inline int alloc_valid_pointer_check(struct kmem_cache *s,
+					    struct page *page, void *object)
+{
+	if (s->flags & SLAB_CONSISTENCY_CHECKS &&
+	    !check_valid_pointer(s, page, object)) {
+		if (printk_ratelimit())
+			object_err(s, page, object, "Freelist Pointer corrupted");
+		return 0;
+	}
+
+	return 1;
+}
+
 static inline int alloc_consistency_checks(struct kmem_cache *s, struct page *page,
 					void *object)
 {
@@ -1343,6 +1357,10 @@ static unsigned long kmem_cache_flags(unsigned long object_size,
 static inline void setup_object_debug(struct kmem_cache *s,
 			struct page *page, void *object) {}
 
+static inline int alloc_valid_pointer_check(struct kmem_cache *s,
+					    struct page *page,
+					    void *object) { return 0; }
+
 static inline int alloc_debug_processing(struct kmem_cache *s,
 	struct page *page, void *object, unsigned long addr) { return 0; }
 
@@ -2517,6 +2535,10 @@ static void *___slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
 	 * That page must be frozen for per cpu allocations to work.
 	 */
 	VM_BUG_ON(!c->page->frozen);
+
+	if (kmem_cache_debug(s) && !alloc_valid_pointer_check(s, c->page, freelist))
+		return NULL;
+
 	c->freelist = get_freepointer(s, freelist);
 	c->tid = next_tid(c->tid);
 	return freelist;
-- 
2.45.2



More information about the Devel mailing list