[PATCH] osst: don't doublefree pages from scatterlist

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On some architectures, mapping the scatterlist may coalesce entries:
if that coalesced list is then used for freeing the pages afterwards,
there's a danger that pages may be doubly freed (and others leaked).

Fix OnStream SCSI Tape's normalize_buffer by freeing from a second list
beyond the I/O scatterlist, saving page pointers with their lengths.

Signed-off-by: Hugh Dickins <[email protected]>
---
Warning: untested!

 drivers/scsi/osst.c |   13 ++++++++++---
 1 files changed, 10 insertions(+), 3 deletions(-)

--- 2.6.16-rc2/drivers/scsi/osst.c	2006-01-03 03:21:10.000000000 +0000
+++ linux/drivers/scsi/osst.c	2006-02-03 09:59:37.000000000 +0000
@@ -5152,7 +5152,8 @@ static struct osst_buffer * new_tape_buf
 	else
 		priority = GFP_KERNEL;
 
-	i = sizeof(struct osst_buffer) + (osst_max_sg_segs - 1) * sizeof(struct scatterlist);
+	i = sizeof(struct osst_buffer) +
+		(2 * osst_max_sg_segs - 1) * sizeof(struct scatterlist);
 	tb = (struct osst_buffer *)kmalloc(i, priority);
 	if (!tb) {
 		printk(KERN_NOTICE "osst :I: Can't allocate new tape buffer.\n");
@@ -5227,6 +5228,8 @@ static int enlarge_buffer(struct osst_bu
 #if DEBUG
 			STbuffer->buffer_size = got;
 #endif
+			memcpy(STbuffer->sg + STbuffer->sg_segs, STbuffer->sg,
+				STbuffer->sg_segs * sizeof(STbuffer->sg[0]));
 			normalize_buffer(STbuffer);
 			return 0;
 		}
@@ -5235,6 +5238,9 @@ static int enlarge_buffer(struct osst_bu
 		STbuffer->buffer_size = got;
 		STbuffer->sg_segs = ++segs;
 	}
+	/* Save uncoalesced scatterlist of pages to be freed */
+	memcpy(STbuffer->sg + STbuffer->sg_segs, STbuffer->sg,
+		STbuffer->sg_segs * sizeof(STbuffer->sg[0]));
 #if DEBUG
 	if (debugging) {
 		printk(OSST_DEB_MSG
@@ -5254,9 +5260,10 @@ static int enlarge_buffer(struct osst_bu
 /* Release the segments */
 static void normalize_buffer(struct osst_buffer *STbuffer)
 {
-  int i, order, b_size;
+	int i, order, b_size;
 
-	for (i=0; i < STbuffer->sg_segs; i++) {
+	/* Scatterlist entries may have been coalesced: free saved pagelist */
+	for (i = STbuffer->sg_segs; i < 2*STbuffer->sg_segs; i++) {
 
 		for (b_size = PAGE_SIZE, order = 0;
 		     b_size < STbuffer->sg[i].length;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux