[Devel] [PATCH rh7 3/5] slub_debug: fail allocation on a bad freelist pointer

Konstantin Khorenko khorenko at virtuozzo.com
Fri Sep 6 20:34:08 MSK 2024


From: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>

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>
---
 mm/slub.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/mm/slub.c b/mm/slub.c
index 7633fd7ffa8d..630d39a0d63f 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1095,6 +1095,19 @@ 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)
 {
@@ -1353,6 +1366,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; }
 
@@ -2527,6 +2544,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.24.3



More information about the Devel mailing list