From: "Uladzislau Rezki (Sony)" urezki@gmail.com
mainline inclusion from mainline-5.2-rc1 commit bb850f4dae4abb18c5ee727bb2d6df9ca47ede49 category: bugfix bugzilla: 15766 CVE: NA
------------------------------------------------- This macro adds some debug code to check that the augment tree is maintained correctly, meaning that every node contains valid subtree_max_size value.
By default this option is set to 0 and not active. It requires recompilation of the kernel to activate it. Set to 1, compile the kernel.
[urezki@gmail.com: v4] Link: http://lkml.kernel.org/r/20190406183508.25273-3-urezki@gmail.com Link: http://lkml.kernel.org/r/20190402162531.10888-3-urezki@gmail.com Signed-off-by: Uladzislau Rezki (Sony) urezki@gmail.com Reviewed-by: Roman Gushchin guro@fb.com Cc: Ingo Molnar mingo@elte.hu Cc: Joel Fernandes joelaf@google.com Cc: Matthew Wilcox willy@infradead.org Cc: Michal Hocko mhocko@suse.com Cc: Oleksiy Avramchenko oleksiy.avramchenko@sonymobile.com Cc: Steven Rostedt rostedt@goodmis.org Cc: Tejun Heo tj@kernel.org Cc: Thomas Garnier thgarnie@google.com Cc: Thomas Gleixner tglx@linutronix.de Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org (cherry picked from commit bb850f4dae4abb18c5ee727bb2d6df9ca47ede49) Signed-off-by: Kefeng Wang wangkefeng.wang@huawei.com Reviewed-by: Hanjun Guo guohanjun@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- mm/vmalloc.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+)
diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 8b134c0..09f1ebe 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -324,6 +324,8 @@ unsigned long vmalloc_to_pfn(const void *vmalloc_addr)
/*** Global kva allocator ***/
+#define DEBUG_AUGMENT_PROPAGATE_CHECK 0 + #define VM_LAZY_FREE 0x02 #define VM_VM_AREA 0x04
@@ -538,6 +540,48 @@ static struct vmap_area *__find_vmap_area(unsigned long addr) } }
+#if DEBUG_AUGMENT_PROPAGATE_CHECK +static void +augment_tree_propagate_check(struct rb_node *n) +{ + struct vmap_area *va; + struct rb_node *node; + unsigned long size; + bool found = false; + + if (n == NULL) + return; + + va = rb_entry(n, struct vmap_area, rb_node); + size = va->subtree_max_size; + node = n; + + while (node) { + va = rb_entry(node, struct vmap_area, rb_node); + + if (get_subtree_max_size(node->rb_left) == size) { + node = node->rb_left; + } else { + if (va_size(va) == size) { + found = true; + break; + } + + node = node->rb_right; + } + } + + if (!found) { + va = rb_entry(n, struct vmap_area, rb_node); + pr_emerg("tree is corrupted: %lu, %lu\n", + va_size(va), va->subtree_max_size); + } + + augment_tree_propagate_check(n->rb_left); + augment_tree_propagate_check(n->rb_right); +} +#endif + /* * This function populates subtree_max_size from bottom to upper * levels starting from VA point. The propagation must be done @@ -587,6 +631,10 @@ static struct vmap_area *__find_vmap_area(unsigned long addr) va->subtree_max_size = new_va_sub_max_size; node = rb_parent(&va->rb_node); } + +#if DEBUG_AUGMENT_PROPAGATE_CHECK + augment_tree_propagate_check(free_vmap_area_root.rb_node); +#endif }
static void