Messages in this thread Patch in this message | | | Date | Fri, 3 Feb 2006 19:56:55 +0000 (GMT) | From | Hugh Dickins <> | Subject | [PATCH] osst: don't doublefree pages from scatterlist |
| |
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@veritas.com> --- 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 majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |