diff options
author | Stephen M. Cameron <scameron@beardog.cce.hp.com> | 2013-09-23 14:33:51 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-12-16 13:57:53 -0500 |
commit | e2d4a1f6b497e39d68775378960ad27be4f86250 (patch) | |
tree | ff624082307842cb4089d193b4a4e725fa699cca | |
parent | a4af4606dbe959a09b2fc61da7052d5ba9b292f9 (diff) |
[SCSI] hpsa: fix memory leak in CCISS_BIG_PASSTHRU ioctl
We were leaking a command buffer if a DMA mapping error was
encountered in the CCISS_BIG_PASSTHRU ioctl.
Signed-off-by: Stephen M. Cameron <scameron@beardog.cce.hp.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r-- | drivers/scsi/hpsa.c | 11 |
1 files changed, 5 insertions, 6 deletions
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index bb3ee8fd2a3d..f12f55669cb3 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c | |||
@@ -3170,7 +3170,7 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp) | |||
3170 | hpsa_pci_unmap(h->pdev, c, i, | 3170 | hpsa_pci_unmap(h->pdev, c, i, |
3171 | PCI_DMA_BIDIRECTIONAL); | 3171 | PCI_DMA_BIDIRECTIONAL); |
3172 | status = -ENOMEM; | 3172 | status = -ENOMEM; |
3173 | goto cleanup1; | 3173 | goto cleanup0; |
3174 | } | 3174 | } |
3175 | c->SG[i].Addr.lower = temp64.val32.lower; | 3175 | c->SG[i].Addr.lower = temp64.val32.lower; |
3176 | c->SG[i].Addr.upper = temp64.val32.upper; | 3176 | c->SG[i].Addr.upper = temp64.val32.upper; |
@@ -3186,24 +3186,23 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp) | |||
3186 | /* Copy the error information out */ | 3186 | /* Copy the error information out */ |
3187 | memcpy(&ioc->error_info, c->err_info, sizeof(ioc->error_info)); | 3187 | memcpy(&ioc->error_info, c->err_info, sizeof(ioc->error_info)); |
3188 | if (copy_to_user(argp, ioc, sizeof(*ioc))) { | 3188 | if (copy_to_user(argp, ioc, sizeof(*ioc))) { |
3189 | cmd_special_free(h, c); | ||
3190 | status = -EFAULT; | 3189 | status = -EFAULT; |
3191 | goto cleanup1; | 3190 | goto cleanup0; |
3192 | } | 3191 | } |
3193 | if (ioc->Request.Type.Direction == XFER_READ && ioc->buf_size > 0) { | 3192 | if (ioc->Request.Type.Direction == XFER_READ && ioc->buf_size > 0) { |
3194 | /* Copy the data out of the buffer we created */ | 3193 | /* Copy the data out of the buffer we created */ |
3195 | BYTE __user *ptr = ioc->buf; | 3194 | BYTE __user *ptr = ioc->buf; |
3196 | for (i = 0; i < sg_used; i++) { | 3195 | for (i = 0; i < sg_used; i++) { |
3197 | if (copy_to_user(ptr, buff[i], buff_size[i])) { | 3196 | if (copy_to_user(ptr, buff[i], buff_size[i])) { |
3198 | cmd_special_free(h, c); | ||
3199 | status = -EFAULT; | 3197 | status = -EFAULT; |
3200 | goto cleanup1; | 3198 | goto cleanup0; |
3201 | } | 3199 | } |
3202 | ptr += buff_size[i]; | 3200 | ptr += buff_size[i]; |
3203 | } | 3201 | } |
3204 | } | 3202 | } |
3205 | cmd_special_free(h, c); | ||
3206 | status = 0; | 3203 | status = 0; |
3204 | cleanup0: | ||
3205 | cmd_special_free(h, c); | ||
3207 | cleanup1: | 3206 | cleanup1: |
3208 | if (buff) { | 3207 | if (buff) { |
3209 | for (i = 0; i < sg_used; i++) | 3208 | for (i = 0; i < sg_used; i++) |