From: Tom M. <tj...@sg...> - 2007-10-12 21:07:50
|
Attached is a fix for a problem that can cause corruption of memory... Here is a description of the problem: When allocating an oversized block using alloc_block(), If there are any free blocks, a comparison is made between the desired block size and the chunk size (data block + block header) of all free blocks. It's possible that a block will be found on the free list that is less than chunk size but greater than block size. When this happens, it's possible for the next block of memory to be corrupted when the allocated block is written. Depending on the size of the block originally allocated by malloc(), corruption may or may not occur. This problem was discovered when trying to load in the runqueue for a cpu to determine if a task was running or not. I have checked the following fix into the tree... The fix takes care of the free block size check and it plugs a hole that can cause memory bloat (a TEMP bloc is allocated in task_has_cpu() but not freed until all TEMP blocks are freed). diff -Naur -x CVS -x .svn -x '*.gz' -Naur LKCD_TRUNK/lkcd/trunk/lkcdutils/lcrash/util.c LKCD1/lkcd/trunk/lkcdutils/lcrash/util.c --- LKCD_TRUNK/lkcd/trunk/lkcdutils/lcrash/util.c 2007-09-13 23:17:40.837347259 -0700 +++ LKCD1/lkcd/trunk/lkcdutils/lcrash/util.c 2007-10-12 11:05:52.541314725 -0700 @@ -357,6 +357,9 @@ GET_BLOCK(sp->s_addr + rq_size * cpu ,rq_size,runqueue); if(KL_ERROR){ rc = 0; + if (runqueue) { + kl_free_block(runqueue); + } goto out; } if(kl_kaddr(runqueue,"runqueue","curr") == tsp_addr){ @@ -364,6 +367,7 @@ } else { rc = 0; } + kl_free_block(runqueue); } else if((sp = kl_lkup_symname("per_cpu__runqueues"))){ /* Linux 2.6 Scheduler */ @@ -396,9 +400,10 @@ goto out; } runqueue = (char *)kl_alloc_block(rq_size, K_TEMP); - GET_BLOCK(rq_addr, rq_size,runqueue); + GET_BLOCK(rq_addr, rq_size, runqueue); if(KL_ERROR){ rc = 0; + kl_free_block(runqueue); goto out; } if(use_rq_type) @@ -410,6 +415,7 @@ } else { rc = 0; } + kl_free_block(runqueue); } else { fprintf(KL_ERRORFP,"Unknown kernel - cannot find out if task is running\n"); rc = 0; diff -Naur -x CVS -x .svn -x '*.gz' -Naur LKCD_TRUNK/lkcd/trunk/lkcdutils/lib/liballoc/alloc.c LKCD1/lkcd/trunk/lkcdutils/lib/liballoc/alloc.c --- LKCD_TRUNK/lkcd/trunk/lkcdutils/lib/liballoc/alloc.c 2006-05-24 10:19:54.413436166 -0700 +++ LKCD1/lkcd/trunk/lkcdutils/lib/liballoc/alloc.c 2007-10-12 11:41:55.176191090 -0700 @@ -308,7 +308,7 @@ if ((blk = bucket[i].freeblks)) { while (blk) { cp = blk->b_chunkp; - if (cp->chunksz >= size) { + if (cp->blksz >= size) { break; } lastblk = blk; |