From be4dbe1b36cf748c36bd7aad910603f12693b769 Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Tue, 6 Jul 2010 16:47:28 -0400 Subject: [PATCH 6/8] scsi: address leak in scsi_setup_discard_cmnd error path BZ 610054 Posted for inclussion in linux-2.6-block's 'for-2.6.36': http://marc.info/?l=linux-scsi&m=127842482308698&w=2 This minimalist patch is less invassive than the fix proposed by Tomo. For RHEL6 it'd be best to avoid crafty SCSI prep error handling changes. Currently, a discard request's page will not get cleaned up in the scsi_setup_discard_cmnd error path. A scsi_setup_discard_cmnd return other than BLKPREP_OK will not cause a discard request to get completely cleaned up (scsi_prep_return will not set REQ_DONTPREP unless BLKPREP_OK was returned). This fix eliminates the leak while preserving the rule that: Unprep is only called if the request gets prepped (meaning a return BLKPREP_OK). Defer or kill assume there's no teardown to do, so any allocation must be reversed before returning them. Signed-off-by: Mike Snitzer --- drivers/scsi/sd.c | 8 +++++++- 1 files changed, 7 insertions(+), 1 deletions(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index c748bbd..a8abe65 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -466,13 +466,19 @@ static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) blk_add_request_payload(rq, page, len); ret = scsi_setup_blk_pc_cmnd(sdp, rq); rq->buffer = page_address(page); + if (ret != BLKPREP_OK) { + __free_page(page); + rq->buffer = NULL; + } return ret; } static void sd_unprep_fn(struct request_queue *q, struct request *rq) { - if (rq->cmd_flags & REQ_DISCARD) + if (rq->cmd_flags & REQ_DISCARD) { __free_page(virt_to_page(rq->buffer)); + rq->buffer = NULL; + } } /** -- 1.6.6.1