]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
scsi: hpsa: Fix potential memory leak in hpsa_big_passthru_ioctl()
authorThorsten Blum <thorsten.blum@linux.dev>
Fri, 19 Sep 2025 09:26:37 +0000 (11:26 +0200)
committerMartin K. Petersen <martin.petersen@oracle.com>
Thu, 25 Sep 2025 01:27:00 +0000 (21:27 -0400)
Replace kmalloc() followed by copy_from_user() with memdup_user() to fix
a memory leak that occurs when copy_from_user(buff[sg_used],,) fails and
the 'cleanup1:' path does not free the memory for 'buff[sg_used]'. Using
memdup_user() avoids this by freeing the memory internally.

Since memdup_user() already allocates memory, use kzalloc() in the else
branch instead of manually zeroing 'buff[sg_used]' using memset(0).

Cc: stable@vger.kernel.org
Fixes: edd163687ea5 ("[SCSI] hpsa: add driver for HP Smart Array controllers.")
Signed-off-by: Thorsten Blum <thorsten.blum@linux.dev>
Acked-by: Don Brace <don.brace@microchip.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/hpsa.c

index 8738ad75723543a40896710b3cb4e1cdc35d13a0..1f917e882ae45c59102d92ea741e18b80c0a804a 100644 (file)
@@ -6517,18 +6517,21 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h,
        while (left) {
                sz = (left > ioc->malloc_size) ? ioc->malloc_size : left;
                buff_size[sg_used] = sz;
-               buff[sg_used] = kmalloc(sz, GFP_KERNEL);
-               if (buff[sg_used] == NULL) {
-                       status = -ENOMEM;
-                       goto cleanup1;
-               }
+
                if (ioc->Request.Type.Direction & XFER_WRITE) {
-                       if (copy_from_user(buff[sg_used], data_ptr, sz)) {
-                               status = -EFAULT;
+                       buff[sg_used] = memdup_user(data_ptr, sz);
+                       if (IS_ERR(buff[sg_used])) {
+                               status = PTR_ERR(buff[sg_used]);
                                goto cleanup1;
                        }
-               } else
-                       memset(buff[sg_used], 0, sz);
+               } else {
+                       buff[sg_used] = kzalloc(sz, GFP_KERNEL);
+                       if (!buff[sg_used]) {
+                               status = -ENOMEM;
+                               goto cleanup1;
+                       }
+               }
+
                left -= sz;
                data_ptr += sz;
                sg_used++;