public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* SLUB: Return ZERO_SIZE_PTR for kmalloc(0)
@ 2007-06-02  1:37 Christoph Lameter
  2007-06-02  2:09 ` John Anthony Kazos Jr.
                   ` (3 more replies)
  0 siblings, 4 replies; 49+ messages in thread
From: Christoph Lameter @ 2007-06-02  1:37 UTC (permalink / raw)
  To: akpm; +Cc: linux-kernel, Linus Torvalds, Jeremy Fitzhardinge

Instead of returning the smallest available object return ZERO_SIZE_PTR.

A ZERO_SIZE_PTR can be legitimately used as an object pointer as long
as it is not deferenced. The dereference of ZERO_SIZE_PTR causes a
distinctive fault. kfree will handle a ZERO_SIZE_PTR in the same way as 
NULL.

This enables functions to transparently use zero sized object. F.e.
if n = number of objects then the following code snippet will work
wether n = 0 or larger.

	objects = kmalloc(n * sizeof(object), GFP_KERNEL);

	for (i = 0; i < n; i++)
		objects[i].x = y;

	kfree(objects);

In addition to the warning for kmalloc(0) that is already there this patch 
will cause a failure if there is an attempt to access objects in the zero 
sized array.

Signed-off-by: Christoph Lameter <clameter@sgi.com>

---
 include/linux/slub_def.h |   29 ++++++++++++++++++++++-------
 mm/slub.c                |   10 +++++-----
 2 files changed, 27 insertions(+), 12 deletions(-)

Index: slub/include/linux/slub_def.h
===================================================================
--- slub.orig/include/linux/slub_def.h	2007-06-01 18:08:32.000000000 -0700
+++ slub/include/linux/slub_def.h	2007-06-01 18:22:56.000000000 -0700
@@ -74,14 +74,17 @@ extern struct kmem_cache kmalloc_caches[
  */
 static inline int kmalloc_index(size_t size)
 {
+
 	/*
-	 * We should return 0 if size == 0 (which would result in the
-	 * kmalloc caller to get NULL) but we use the smallest object
-	 * here for legacy reasons. Just issue a warning so that
-	 * we can discover locations where we do 0 sized allocations.
+	 * The behavior for zero sized allocs changes. We no longer
+	 * allocate memory but return ZERO_SIZE_PTR.
+	 * WARN so that people can review and fix their code.
 	 */
 	WARN_ON_ONCE(size == 0);
 
+	if (!size)
+		return 0;
+
 	if (size > KMALLOC_MAX_SIZE)
 		return -1;
 
@@ -127,13 +130,25 @@ static inline struct kmem_cache *kmalloc
 #define SLUB_DMA 0
 #endif
 
+
+/*
+ * ZERO_SIZE_PTR will be returned for zero sized kmalloc requests.
+ *
+ * Dereferencing ZERO_SIZE_PTR will lead to a distinct access fault.
+ *
+ * ZERO_SIZE_PTR can be passed to kfree() in the same way that NULL can.
+ * Both make kfree() a no-op.
+ */
+#define ZERO_SIZE_PTR ((void *)16)
+
+
 static inline void *kmalloc(size_t size, gfp_t flags)
 {
 	if (__builtin_constant_p(size) && !(flags & SLUB_DMA)) {
 		struct kmem_cache *s = kmalloc_slab(size);
 
 		if (!s)
-			return NULL;
+			return ZERO_SIZE_PTR;
 
 		return kmem_cache_alloc(s, flags);
 	} else
@@ -146,7 +161,7 @@ static inline void *kzalloc(size_t size,
 		struct kmem_cache *s = kmalloc_slab(size);
 
 		if (!s)
-			return NULL;
+			return ZERO_SIZE_PTR;
 
 		return kmem_cache_zalloc(s, flags);
 	} else
@@ -162,7 +177,7 @@ static inline void *kmalloc_node(size_t 
 		struct kmem_cache *s = kmalloc_slab(size);
 
 		if (!s)
-			return NULL;
+			return ZERO_SIZE_PTR;
 
 		return kmem_cache_alloc_node(s, flags, node);
 	} else
Index: slub/mm/slub.c
===================================================================
--- slub.orig/mm/slub.c	2007-06-01 18:08:32.000000000 -0700
+++ slub/mm/slub.c	2007-06-01 18:22:56.000000000 -0700
@@ -2286,7 +2286,7 @@ void *__kmalloc(size_t size, gfp_t flags
 
 	if (s)
 		return slab_alloc(s, flags, -1, __builtin_return_address(0));
-	return NULL;
+	return ZERO_SIZE_PTR;
 }
 EXPORT_SYMBOL(__kmalloc);
 
@@ -2297,7 +2297,7 @@ void *__kmalloc_node(size_t size, gfp_t 
 
 	if (s)
 		return slab_alloc(s, flags, node, __builtin_return_address(0));
-	return NULL;
+	return ZERO_SIZE_PTR;
 }
 EXPORT_SYMBOL(__kmalloc_node);
 #endif
@@ -2338,7 +2338,7 @@ void kfree(const void *x)
 	struct kmem_cache *s;
 	struct page *page;
 
-	if (!x)
+	if (x <= ZERO_SIZE_PTR)
 		return;
 
 	page = virt_to_head_page(x);
@@ -2707,7 +2707,7 @@ void *__kmalloc_track_caller(size_t size
 	struct kmem_cache *s = get_slab(size, gfpflags);
 
 	if (!s)
-		return NULL;
+		return ZERO_SIZE_PTR;
 
 	return slab_alloc(s, gfpflags, -1, caller);
 }
@@ -2718,7 +2718,7 @@ void *__kmalloc_node_track_caller(size_t
 	struct kmem_cache *s = get_slab(size, gfpflags);
 
 	if (!s)
-		return NULL;
+		return ZERO_SIZE_PTR;
 
 	return slab_alloc(s, gfpflags, node, caller);
 }

^ permalink raw reply	[flat|nested] 49+ messages in thread

end of thread, other threads:[~2007-06-06 22:02 UTC | newest]

Thread overview: 49+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-06-02  1:37 SLUB: Return ZERO_SIZE_PTR for kmalloc(0) Christoph Lameter
2007-06-02  2:09 ` John Anthony Kazos Jr.
2007-06-02  2:15   ` Christoph Lameter
2007-06-02  2:21     ` John Anthony Kazos Jr.
2007-06-02  2:54 ` Linus Torvalds
2007-06-02  3:06   ` Christoph Lameter
2007-06-02  3:41 ` Andrew Morton
2007-06-02  4:01   ` Christoph Lameter
2007-06-02  4:31     ` Andrew Morton
2007-06-02  4:45       ` Christoph Lameter
2007-06-02  4:54         ` Andrew Morton
2007-06-03 16:17           ` Matt Mackall
2007-06-04 17:59           ` William Lee Irwin III
2007-06-03 16:15         ` Matt Mackall
2007-06-04 14:44           ` Alan Cox
2007-06-04 15:08         ` Pekka Enberg
2007-06-04 16:16           ` Christoph Lameter
2007-06-04 16:22             ` Pekka Enberg
2007-06-04 16:26               ` Linus Torvalds
2007-06-04 16:32                 ` Jeremy Fitzhardinge
2007-06-04 16:37                 ` Pekka Enberg
2007-06-04 16:38                   ` Jeremy Fitzhardinge
2007-06-04 16:43                   ` Roland Dreier
2007-06-04 17:02                     ` Pekka Enberg
2007-06-04 16:48                   ` Linus Torvalds
2007-06-04 18:22                   ` Cyrill Gorcunov
2007-06-04 17:20                 ` Alan Cox
2007-06-04 17:50                   ` Linus Torvalds
2007-06-04 18:05                     ` William Lee Irwin III
2007-06-04 18:47 ` Linus Torvalds
2007-06-04 19:01   ` Christoph Lameter
2007-06-04 19:13     ` Pekka Enberg
2007-06-04 19:14       ` Christoph Lameter
2007-06-04 19:25         ` Pekka Enberg
2007-06-04 22:39           ` Christoph Lameter
2007-06-04 22:53             ` Andrew Morton
2007-06-04 23:09               ` Christoph Lameter
2007-06-05  5:27                 ` Pekka Enberg
2007-06-05 17:23                   ` Christoph Lameter
2007-06-05  8:50                 ` Rene Herman
2007-06-05 12:07                   ` John Anthony Kazos Jr.
2007-06-05 12:54                     ` Rene Herman
2007-06-05 13:58                       ` John Anthony Kazos Jr.
2007-06-05 14:32                         ` Rene Herman
2007-06-05 19:07                           ` Pekka Enberg
2007-06-05 14:40                       ` Jeremy Fitzhardinge
2007-06-05 14:56                         ` Rene Herman
2007-06-06 21:26                           ` Pavel Machek
2007-06-06 21:58                             ` Rene Herman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox