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 <hugh@xxxxxxxxxxx> --- 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; - : send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html