Skip to content

Commit fb428a2

Browse files
kawasakimartinkpetersen
authored andcommitted
scsi: mpi3mr: Fix issues in mpi3mr_get_all_tgt_info()
The function mpi3mr_get_all_tgt_info() has four issues: 1) It calculates valid entry length in alltgt_info assuming the header part of the struct mpi3mr_device_map_info would equal to sizeof(u32). The correct size is sizeof(u64). 2) When it calculates the valid entry length kern_entrylen, it excludes one entry by subtracting 1 from num_devices. 3) It copies num_device by calling memcpy(). Substitution is enough. 4) It does not specify the calculated length to sg_copy_from_buffer(). Instead, it specifies the payload length which is larger than the alltgt_info size. It causes "BUG: KASAN: slab-out-of-bounds". Fix the issues by using the correct header size, removing the subtraction from num_devices, replacing the memcpy() with substitution and specifying the correct length to sg_copy_from_buffer(). Link: https://lore.kernel.org/r/20230214005019.1897251-2-shinichiro.kawasaki@wdc.com Cc: stable@vger.kernel.org Fixes: f5e6d5a ("scsi: mpi3mr: Add support for driver commands") Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com> Acked-by: Sathya Prakash Veerichetty <sathya.prakash@broadcom.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent ae7d45f commit fb428a2

1 file changed

Lines changed: 8 additions & 7 deletions

File tree

drivers/scsi/mpi3mr/mpi3mr_app.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -312,22 +312,22 @@ static long mpi3mr_get_all_tgt_info(struct mpi3mr_ioc *mrioc,
312312
num_devices++;
313313
spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
314314

315-
if ((job->request_payload.payload_len == sizeof(u32)) ||
315+
if ((job->request_payload.payload_len <= sizeof(u64)) ||
316316
list_empty(&mrioc->tgtdev_list)) {
317317
sg_copy_from_buffer(job->request_payload.sg_list,
318318
job->request_payload.sg_cnt,
319319
&num_devices, sizeof(num_devices));
320320
return 0;
321321
}
322322

323-
kern_entrylen = (num_devices - 1) * sizeof(*devmap_info);
324-
size = sizeof(*alltgt_info) + kern_entrylen;
323+
kern_entrylen = num_devices * sizeof(*devmap_info);
324+
size = sizeof(u64) + kern_entrylen;
325325
alltgt_info = kzalloc(size, GFP_KERNEL);
326326
if (!alltgt_info)
327327
return -ENOMEM;
328328

329329
devmap_info = alltgt_info->dmi;
330-
memset((u8 *)devmap_info, 0xFF, (kern_entrylen + sizeof(*devmap_info)));
330+
memset((u8 *)devmap_info, 0xFF, kern_entrylen);
331331
spin_lock_irqsave(&mrioc->tgtdev_lock, flags);
332332
list_for_each_entry(tgtdev, &mrioc->tgtdev_list, list) {
333333
if (i < num_devices) {
@@ -344,9 +344,10 @@ static long mpi3mr_get_all_tgt_info(struct mpi3mr_ioc *mrioc,
344344
num_devices = i;
345345
spin_unlock_irqrestore(&mrioc->tgtdev_lock, flags);
346346

347-
memcpy(&alltgt_info->num_devices, &num_devices, sizeof(num_devices));
347+
alltgt_info->num_devices = num_devices;
348348

349-
usr_entrylen = (job->request_payload.payload_len - sizeof(u32)) / sizeof(*devmap_info);
349+
usr_entrylen = (job->request_payload.payload_len - sizeof(u64)) /
350+
sizeof(*devmap_info);
350351
usr_entrylen *= sizeof(*devmap_info);
351352
min_entrylen = min(usr_entrylen, kern_entrylen);
352353
if (min_entrylen && (!memcpy(&alltgt_info->dmi, devmap_info, min_entrylen))) {
@@ -358,7 +359,7 @@ static long mpi3mr_get_all_tgt_info(struct mpi3mr_ioc *mrioc,
358359

359360
sg_copy_from_buffer(job->request_payload.sg_list,
360361
job->request_payload.sg_cnt,
361-
alltgt_info, job->request_payload.payload_len);
362+
alltgt_info, (min_entrylen + sizeof(u64)));
362363
rval = 0;
363364
out:
364365
kfree(alltgt_info);

0 commit comments

Comments
 (0)