From: Yang Yingliang <yangyingliang(a)huawei.com>
hulk inclusion
category: bugfix
bugzilla: 47452
CVE: NA
-------------------------------------------------
Change control methods of check validity of freelist and
connector debug to sysctl.
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Reviewed-by: Kefeng Wang <wangkefeng.wang(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Signed-off-by: Cheng Jian <cj.chengjian(a)huawei.com>
---
drivers/connector/connector.c | 1 +
include/linux/slab.h | 4 ---
kernel/sysctl.c | 20 +++++++++++
mm/slub.c | 63 ++++++++++++++---------------------
4 files changed, 46 insertions(+), 42 deletions(-)
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
index a8df9ecbf42b..b5cdd0b99736 100644
--- a/drivers/connector/connector.c
+++ b/drivers/connector/connector.c
@@ -42,6 +42,7 @@ MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_CONNECTOR);
static struct cn_dev cdev;
static int cn_already_initialized;
+int sysctl_connector_debug = 0;
/*
* Sends mult (multiple) cn_msg at a time.
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 1ab5fd97dec8..d6393413ef09 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -24,8 +24,6 @@
*/
/* DEBUG: Perform (expensive) checks on alloc/free */
#define SLAB_CONSISTENCY_CHECKS ((slab_flags_t __force)0x00000100U)
-/* Check if freelist is valid */
-#define SLAB_NO_FREELIST_CHECKS ((slab_flags_t __force)0x00000200U)
/* DEBUG: Red zone objs in a cache */
#define SLAB_RED_ZONE ((slab_flags_t __force)0x00000400U)
/* DEBUG: Poison objects */
@@ -113,8 +111,6 @@
#define SLAB_KASAN 0
#endif
-#define SLAB_CONNECTOR_DEBUG ((slab_flags_t __force)0x10000000U)
-
/* The following flags affect the page allocator grouping pages by mobility */
/* Objects are reclaimable */
#define SLAB_RECLAIM_ACCOUNT ((slab_flags_t __force)0x00020000U)
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 665c9e2a8802..c921ee10615a 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1245,6 +1245,7 @@ static struct ctl_table kern_table[] = {
{ }
};
+extern int sysctl_isolate_corrupted_freelist;
static struct ctl_table vm_table[] = {
{
.procname = "overcommit_memory",
@@ -1714,6 +1715,15 @@ static struct ctl_table vm_table[] = {
.extra2 = (void *)&mmap_rnd_compat_bits_max,
},
#endif
+ {
+ .procname = "isolate_corrupted_freelist",
+ .data = &sysctl_isolate_corrupted_freelist,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = &zero,
+ .extra2 = &one,
+ },
{ }
};
@@ -1925,6 +1935,7 @@ static struct ctl_table fs_table[] = {
{ }
};
+extern int sysctl_connector_debug;
static struct ctl_table debug_table[] = {
#ifdef CONFIG_SYSCTL_EXCEPTION_TRACE
{
@@ -1946,6 +1957,15 @@ static struct ctl_table debug_table[] = {
.extra2 = &one,
},
#endif
+ {
+ .procname = "connector-debug",
+ .data = &sysctl_connector_debug,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = &zero,
+ .extra2 = &one,
+ },
{ }
};
diff --git a/mm/slub.c b/mm/slub.c
index ee0d18699bde..2301c04353d0 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1221,30 +1221,6 @@ static noinline int free_debug_processing(
return ret;
}
-/*
- * Check if the next object in freechain is
- * valid, then isolate the corrupted freelist.
- */
-int isolate_cnt = 0;
-static bool isolate_corrupted_freelist(struct kmem_cache *s, struct page *page,
- void **freelist, void *next)
-{
- if (!(slub_debug & SLAB_NO_FREELIST_CHECKS) &&
- (!check_valid_pointer(s, page, next))) {
- /* Need caller make sure freelist is not NULL */
- *freelist = NULL;
- isolate_cnt++;
-
- slab_fix(s, "Freelist corrupt,isolate corrupted freechain.");
- pr_info("freelist=%lx object=%lx, page->base=%lx, page->objects=%u, objsize=%u, s->offset=%d page:%llx\n",
- (long)freelist, (long)next, (long)page_address(page), page->objects, s->size, s->offset, (u64)page);
-
- return true;
- }
-
- return false;
-}
-
static int __init setup_slub_debug(char *str)
{
slub_debug = DEBUG_DEFAULT_FLAGS;
@@ -1291,14 +1267,6 @@ static int __init setup_slub_debug(char *str)
case 'a':
slub_debug |= SLAB_FAILSLAB;
break;
- case 'n':
- slub_debug |= SLAB_NO_FREELIST_CHECKS;
- pr_info("Freelist pointer check disabled.");
- break;
- case 'd':
- slub_debug |= SLAB_CONNECTOR_DEBUG;
- pr_info("Connector debug enabled.\n");
- break;
case 'o':
/*
* Avoid enabling debugging on caches if its minimum
@@ -1311,8 +1279,6 @@ static int __init setup_slub_debug(char *str)
*str);
}
}
- if (!(slub_debug & SLAB_NO_FREELIST_CHECKS))
- pr_info("Freelist pointer check enabled.");
check_slabs:
if (*str == ',')
@@ -1380,12 +1346,33 @@ static bool freelist_corrupted(struct kmem_cache *s, struct page *page,
{
return false;
}
+#endif /* CONFIG_SLUB_DEBUG */
+
+extern int sysctl_connector_debug;
+/*
+ * Check if the next object in freechain is
+ * valid, then isolate the corrupted freelist.
+ */
+int isolate_cnt = 0;
+int sysctl_isolate_corrupted_freelist = 1;
static bool isolate_corrupted_freelist(struct kmem_cache *s, struct page *page,
- void **freelist, void *nextfree)
+ void **freelist, void *next)
{
+ if (sysctl_isolate_corrupted_freelist &&
+ (!check_valid_pointer(s, page, next))) {
+ /* Need caller make sure freelist is not NULL */
+ *freelist = NULL;
+ isolate_cnt++;
+
+ slab_fix(s, "Freelist corrupt,isolate corrupted freechain.");
+ pr_info("freelist=%lx object=%lx, page->base=%lx, page->objects=%u, objsize=%u, s->offset=%d page:%llx\n",
+ (long)freelist, (long)next, (long)page_address(page), page->objects, s->size, s->offset, (u64)page);
+
+ return true;
+ }
+
return false;
}
-#endif /* CONFIG_SLUB_DEBUG */
/*
* Hooks for other subsystems that check memory allocations. In a typical
@@ -2798,7 +2785,7 @@ static __always_inline void *slab_alloc_node(struct kmem_cache *s,
if (unlikely(gfpflags & __GFP_ZERO) && object)
memset(object, 0, s->object_size);
- if ((slub_debug & SLAB_CONNECTOR_DEBUG) &&
+ if (sysctl_connector_debug &&
unlikely(gfpflags & __GFP_CONNECTOR) && object) {
if (s->object_size == 512)
memset(object + 504, 0xad, 8);
@@ -4015,7 +4002,7 @@ void kfree(const void *x)
__free_pages(page, compound_order(page));
return;
}
- if ((slub_debug & SLAB_CONNECTOR_DEBUG) &&
+ if (sysctl_connector_debug &&
unlikely(page->slab_cache->object_size == 512)) {
u64 *tail = (u64 *)(x + 504);
--
2.25.1