From: Pavel Tikhomirov <ptikhomi...@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 <ptikhomi...@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

_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to