mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] genalloc: fix overflow of ending address of memory chunk
@ 2013-08-07  5:26 Joonyoung Shim
  2013-08-09 23:13 ` Andrew Morton
  0 siblings, 1 reply; 2+ messages in thread
From: Joonyoung Shim @ 2013-08-07  5:26 UTC (permalink / raw)
  To: linux-kernel; +Cc: akpm

In struct gen_pool_chunk, end_addr means ending address of memory chunk,
but actually it is starting address + size of memory chunk in codes, so
it points the address increased one instead of correct ending address.

The ending address of memory chunk increased one will cause overflow on
the case to use memory chunk including last address of memory map, e.g.
when starting address is 0xFFF00000 and size is 0x100000 on 32bit
machine, ending address will be 0x100000000.

Use correct ending address like starting address + size - 1.

Signed-off-by: Joonyoung Shim <jy0922.shim@samsung.com>
---
 lib/genalloc.c | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/lib/genalloc.c b/lib/genalloc.c
index b35cfa9..2a39bf6 100644
--- a/lib/genalloc.c
+++ b/lib/genalloc.c
@@ -37,6 +37,11 @@
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 
+static inline size_t chunk_size(const struct gen_pool_chunk *chunk)
+{
+	return chunk->end_addr - chunk->start_addr + 1;
+}
+
 static int set_bits_ll(unsigned long *addr, unsigned long mask_to_set)
 {
 	unsigned long val, nval;
@@ -188,7 +193,7 @@ int gen_pool_add_virt(struct gen_pool *pool, unsigned long virt, phys_addr_t phy
 
 	chunk->phys_addr = phys;
 	chunk->start_addr = virt;
-	chunk->end_addr = virt + size;
+	chunk->end_addr = virt + size - 1;
 	atomic_set(&chunk->avail, size);
 
 	spin_lock(&pool->lock);
@@ -213,7 +218,7 @@ phys_addr_t gen_pool_virt_to_phys(struct gen_pool *pool, unsigned long addr)
 
 	rcu_read_lock();
 	list_for_each_entry_rcu(chunk, &pool->chunks, next_chunk) {
-		if (addr >= chunk->start_addr && addr < chunk->end_addr) {
+		if (addr >= chunk->start_addr && addr <= chunk->end_addr) {
 			paddr = chunk->phys_addr + (addr - chunk->start_addr);
 			break;
 		}
@@ -242,7 +247,7 @@ void gen_pool_destroy(struct gen_pool *pool)
 		chunk = list_entry(_chunk, struct gen_pool_chunk, next_chunk);
 		list_del(&chunk->next_chunk);
 
-		end_bit = (chunk->end_addr - chunk->start_addr) >> order;
+		end_bit = chunk_size(chunk) >> order;
 		bit = find_next_bit(chunk->bits, end_bit, 0);
 		BUG_ON(bit < end_bit);
 
@@ -283,7 +288,7 @@ unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size)
 		if (size > atomic_read(&chunk->avail))
 			continue;
 
-		end_bit = (chunk->end_addr - chunk->start_addr) >> order;
+		end_bit = chunk_size(chunk) >> order;
 retry:
 		start_bit = pool->algo(chunk->bits, end_bit, start_bit, nbits,
 				pool->data);
@@ -330,8 +335,8 @@ void gen_pool_free(struct gen_pool *pool, unsigned long addr, size_t size)
 	nbits = (size + (1UL << order) - 1) >> order;
 	rcu_read_lock();
 	list_for_each_entry_rcu(chunk, &pool->chunks, next_chunk) {
-		if (addr >= chunk->start_addr && addr < chunk->end_addr) {
-			BUG_ON(addr + size > chunk->end_addr);
+		if (addr >= chunk->start_addr && addr <= chunk->end_addr) {
+			BUG_ON(addr + size - 1 > chunk->end_addr);
 			start_bit = (addr - chunk->start_addr) >> order;
 			remain = bitmap_clear_ll(chunk->bits, start_bit, nbits);
 			BUG_ON(remain);
@@ -400,7 +405,7 @@ size_t gen_pool_size(struct gen_pool *pool)
 
 	rcu_read_lock();
 	list_for_each_entry_rcu(chunk, &pool->chunks, next_chunk)
-		size += chunk->end_addr - chunk->start_addr;
+		size += chunk_size(chunk);
 	rcu_read_unlock();
 	return size;
 }
-- 
1.8.1.2


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

* Re: [PATCH] genalloc: fix overflow of ending address of memory chunk
  2013-08-07  5:26 [PATCH] genalloc: fix overflow of ending address of memory chunk Joonyoung Shim
@ 2013-08-09 23:13 ` Andrew Morton
  0 siblings, 0 replies; 2+ messages in thread
From: Andrew Morton @ 2013-08-09 23:13 UTC (permalink / raw)
  To: Joonyoung Shim; +Cc: linux-kernel

On Wed, 07 Aug 2013 14:26:18 +0900 Joonyoung Shim <jy0922.shim@samsung.com> wrote:

> In struct gen_pool_chunk, end_addr means ending address of memory chunk,
> but actually it is starting address + size of memory chunk in codes, so
> it points the address increased one instead of correct ending address.
> 
> The ending address of memory chunk increased one will cause overflow on
> the case to use memory chunk including last address of memory map, e.g.
> when starting address is 0xFFF00000 and size is 0x100000 on 32bit
> machine, ending address will be 0x100000000.
> 
> Use correct ending address like starting address + size - 1.

This might help:

From: Andrew Morton <akpm@linux-foundation.org>
Subject: genalloc-fix-overflow-of-ending-address-of-memory-chunk-fix

add comment to struct gen_pool_chunk:end_addr

Cc: Joonyoung Shim <jy0922.shim@samsung.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---

 include/linux/genalloc.h |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff -puN lib/genalloc.c~genalloc-fix-overflow-of-ending-address-of-memory-chunk-fix lib/genalloc.c
diff -puN include/linux/genalloc.h~genalloc-fix-overflow-of-ending-address-of-memory-chunk-fix include/linux/genalloc.h
--- a/include/linux/genalloc.h~genalloc-fix-overflow-of-ending-address-of-memory-chunk-fix
+++ a/include/linux/genalloc.h
@@ -66,8 +66,8 @@ struct gen_pool_chunk {
 	struct list_head next_chunk;	/* next chunk in pool */
 	atomic_t avail;
 	phys_addr_t phys_addr;		/* physical starting address of memory chunk */
-	unsigned long start_addr;	/* starting address of memory chunk */
-	unsigned long end_addr;		/* ending address of memory chunk */
+	unsigned long start_addr;	/* start address of memory chunk */
+	unsigned long end_addr;		/* end address of memory chunk (inclusive) */
 	unsigned long bits[0];		/* bitmap for allocating memory chunk */
 };
 
_


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

end of thread, other threads:[~2013-08-09 23:13 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-08-07  5:26 [PATCH] genalloc: fix overflow of ending address of memory chunk Joonyoung Shim
2013-08-09 23:13 ` Andrew Morton

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

all inboxes | Powered by JetHome®