lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <201304300645.FCE37285.tVHJLSOMQFOFFO@I-love.SAKURA.ne.jp>
Date:	Tue, 30 Apr 2013 06:45:59 +0900
From:	Tetsuo Handa <penguin-kernel@...ove.SAKURA.ne.jp>
To:	cl@...ux.com
Cc:	glommer@...allels.com, penberg@...nel.org,
	linux-kernel@...r.kernel.org
Subject: Re: [linux-next-20130422] Bug in SLAB?

Christoph Lameter wrote:
> Ok so the maximum allocation is 11+12=23 which is 8M. KMALLOC_MAX_SIZE
> amd KMALLOC_SHIFT_HIGH are wrong.
> 
> Take the -1 off the constants under #ifdef CONFIG_SLAB in

Current diff is:

---------- patch start ----------
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 0c62175..889d6ef 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -189,8 +189,8 @@ struct kmem_cache {
  * to do various tricks to work around compiler limitations in order to
  * ensure proper constant folding.
  */
-#define KMALLOC_SHIFT_HIGH	((MAX_ORDER + PAGE_SHIFT - 1) <= 25 ? \
-				(MAX_ORDER + PAGE_SHIFT - 1) : 25)
+#define KMALLOC_SHIFT_HIGH	((MAX_ORDER + PAGE_SHIFT) <= 26 ? \
+				(MAX_ORDER + PAGE_SHIFT) : 26)
 #define KMALLOC_SHIFT_MAX	KMALLOC_SHIFT_HIGH
 #ifndef KMALLOC_SHIFT_LOW
 #define KMALLOC_SHIFT_LOW	5
@@ -221,9 +221,9 @@ struct kmem_cache {
 #define KMALLOC_MIN_SIZE (1 << KMALLOC_SHIFT_LOW)
 #endif
 
-extern struct kmem_cache *kmalloc_caches[KMALLOC_SHIFT_HIGH + 1];
+extern struct kmem_cache *kmalloc_caches[KMALLOC_SHIFT_HIGH];
 #ifdef CONFIG_ZONE_DMA
-extern struct kmem_cache *kmalloc_dma_caches[KMALLOC_SHIFT_HIGH + 1];
+extern struct kmem_cache *kmalloc_dma_caches[KMALLOC_SHIFT_HIGH];
 #endif
 
 /*
diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h
index 113ec08..be1446a 100644
--- a/include/linux/slab_def.h
+++ b/include/linux/slab_def.h
@@ -126,6 +126,9 @@ static __always_inline void *kmalloc(size_t size, gfp_t flags)
 		if (!size)
 			return ZERO_SIZE_PTR;
 
+		if (size > KMALLOC_MAX_SIZE)
+			goto not_found;
+
 		i = kmalloc_index(size);
 
 #ifdef CONFIG_ZONE_DMA
@@ -139,6 +142,7 @@ static __always_inline void *kmalloc(size_t size, gfp_t flags)
 
 		return ret;
 	}
+not_found:
 	return __kmalloc(size, flags);
 }
 
@@ -172,8 +176,10 @@ static __always_inline void *kmalloc_node(size_t size, gfp_t flags, int node)
 		if (!size)
 			return ZERO_SIZE_PTR;
 
-		i = kmalloc_index(size);
+		if (size > KMALLOC_MAX_SIZE)
+			goto not_found;
 
+		i = kmalloc_index(size);
 #ifdef CONFIG_ZONE_DMA
 		if (flags & GFP_DMA)
 			cachep = kmalloc_dma_caches[i];
@@ -183,6 +189,7 @@ static __always_inline void *kmalloc_node(size_t size, gfp_t flags, int node)
 
 		return kmem_cache_alloc_node_trace(cachep, flags, node, size);
 	}
+not_found:
 	return __kmalloc_node(size, flags, node);
 }
 
diff --git a/mm/slab_common.c b/mm/slab_common.c
index 2f0e7d5..083e7c7 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -319,11 +319,11 @@ struct kmem_cache *__init create_kmalloc_cache(const char *name, size_t size,
 	return s;
 }
 
-struct kmem_cache *kmalloc_caches[KMALLOC_SHIFT_HIGH + 1];
+struct kmem_cache *kmalloc_caches[KMALLOC_SHIFT_HIGH];
 EXPORT_SYMBOL(kmalloc_caches);
 
 #ifdef CONFIG_ZONE_DMA
-struct kmem_cache *kmalloc_dma_caches[KMALLOC_SHIFT_HIGH + 1];
+struct kmem_cache *kmalloc_dma_caches[KMALLOC_SHIFT_HIGH];
 EXPORT_SYMBOL(kmalloc_dma_caches);
 #endif
 
---------- patch end ----------

Current testcases are:

---------- testcases start ----------
	volatile unsigned int size;
	void *ptr;
	ptr = kmalloc(0, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 0, ptr);
	kfree(ptr);
	ptr = kmalloc(1, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 1, ptr);
	kfree(ptr);
	ptr = kmalloc(2, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 2, ptr);
	kfree(ptr);
	ptr = kmalloc(4, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 4, ptr);
	kfree(ptr);
	ptr = kmalloc(8, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 8, ptr);
	kfree(ptr);
	ptr = kmalloc(16, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 16, ptr);
	kfree(ptr);
	ptr = kmalloc(32, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 32, ptr);
	kfree(ptr);
	ptr = kmalloc(64, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 64, ptr);
	kfree(ptr);
	ptr = kmalloc(128, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 128, ptr);
	kfree(ptr);
	ptr = kmalloc(256, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 256, ptr);
	kfree(ptr);
	ptr = kmalloc(512, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 512, ptr);
	kfree(ptr);
	ptr = kmalloc(1024, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 1024, ptr);
	kfree(ptr);
	ptr = kmalloc(2 * 1024, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 2 * 1024, ptr);
	kfree(ptr);
	ptr = kmalloc(4 * 1024, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 4 * 1024, ptr);
	kfree(ptr);
	ptr = kmalloc(8 * 1024, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 8 * 1024, ptr);
	kfree(ptr);
	ptr = kmalloc(16 * 1024, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 16 * 1024, ptr);
	kfree(ptr);
	ptr = kmalloc(32 * 1024, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 32 * 1024, ptr);
	kfree(ptr);
	ptr = kmalloc(64 * 1024, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 64 * 1024, ptr);
	kfree(ptr);
	ptr = kmalloc(128 * 1024, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 128 * 1024, ptr);
	kfree(ptr);
	ptr = kmalloc(256 * 1024, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 256 * 1024, ptr);
	kfree(ptr);
	ptr = kmalloc(512 * 1024, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 512 * 1024, ptr);
	kfree(ptr);
	ptr = kmalloc(1024 * 1024, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 1024 * 1024, ptr);
	kfree(ptr);
	ptr = kmalloc(2 * 1024 * 1024, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 2 * 1024 * 1024, ptr);
	kfree(ptr);
	ptr = kmalloc(4 * 1024 * 1024, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 4 * 1024 * 1024, ptr);
	kfree(ptr);
	ptr = kmalloc(8 * 1024 * 1024, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 8 * 1024 * 1024, ptr);
	kfree(ptr);
	ptr = kmalloc(16 * 1024 * 1024, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 16 * 1024 * 1024, ptr);
	kfree(ptr);
	ptr = kmalloc(32 * 1024 * 1024, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 32 * 1024 * 1024, ptr);
	kfree(ptr);
	ptr = kmalloc(64 * 1024 * 1024, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 64 * 1024 * 1024, ptr);
	kfree(ptr);
	ptr = kmalloc(128 * 1024 * 1024, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 128 * 1024 * 1024, ptr);
	kfree(ptr);
	ptr = kmalloc(256 * 1024 * 1024, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 256 * 1024 * 1024, ptr);
	kfree(ptr);
	ptr = kmalloc(512 * 1024 * 1024, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 512 * 1024 * 1024, ptr);
	kfree(ptr);
	ptr = kmalloc(1024 * 1024 * 1024, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 1024 * 1024 * 1024, ptr);
	kfree(ptr);
	ptr = kmalloc(2 * 1024 * 1024 * 1024, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 2 * 1024 * 1024 * 1024, ptr);
	kfree(ptr);
	ptr = kmalloc(2 * 1024 * 1024 * 1024 + 1, GFP_KERNEL);
	printk("kmalloc(%u)=%p\n", 2 * 1024 * 1024 * 1024 + 1, ptr);
	kfree(ptr);
	for (size = 0; size; size <<= 1) {
		ptr = kmalloc(size, GFP_KERNEL);
		printk("kmalloc(%u)=%p\n", size, ptr);
		kfree(ptr);
		if (!size)
			size = 1;
	}
	for (size = 1; size; size <<= 1) {
		ptr = kmalloc(size + 1, GFP_KERNEL);
		printk("kmalloc(%u)=%p\n", size + 1, ptr);
		kfree(ptr);
	}
---------- testcases end ----------

The testcases still trigger BUG() at 32M:

---------- dmesg start ----------
(...snipped...)
kmalloc(2097152)=dde00000
kmalloc(4194304)=d9c00000
------------[ cut here ]------------
WARNING: at mm/page_alloc.c:2410 __alloc_pages_nodemask+0x179/0x650()
(...snipped...)
---[ end trace c08f36179e2d8ff2 ]---
SLAB: Unable to allocate memory on node 0 (gfp=0xd0)
  cache: kmalloc-8388608, object size: 8388608, order: 11
  node 0: slabs: 0/0, objs: 0/0, free: 0
kmalloc(8388608)=  (null)
kmalloc(16777216)=  (null)
------------[ cut here ]------------
Kernel BUG at c10b9c9b [verbose debug info unavailable]
invalid opcode: 0000 [#1] SMP
(...snipped...)
---------- dmesg end ----------

This means that redirecting to !__builtin_constant_p(size) case does not help.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ