Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

scsi: libsas: Introduce struct smp_rg_resp

When compiling with gcc 12, several warnings are thrown by gcc when
compiling drivers/scsi/libsas/sas_expander.c, e.g.:

In function ‘sas_get_ex_change_count’,
inlined from ‘sas_find_bcast_dev’ at
drivers/scsi/libsas/sas_expander.c:1816:8:
drivers/scsi/libsas/sas_expander.c:1781:20: warning: array subscript
‘struct smp_resp[0]’ is partly outside array bounds of ‘unsigned
char[32]’ [-Warray-bounds]
1781 | if (rg_resp->result != SMP_RESP_FUNC_ACC) {
| ~~~~~~~^~~~~~~~

This is due to the use of the struct smp_resp to aggregate all possible
response types using a union but allocating a response buffer with a size
exactly equal to the size of the response type needed. This leads to access
to fields of struct smp_resp from an allocated memory area that is smaller
than the size of struct smp_resp.

Fix this by defining struct smp_rg_resp for sas report general responses.

Link: https://lore.kernel.org/r/20220609022456.409087-3-damien.lemoal@opensource.wdc.com
Reviewed-by: John Garry <john.garry@huawei.com>
Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Damien Le Moal and committed by
Martin K. Petersen
44f2bfe9 c3752f44

+21 -18
+13 -18
drivers/scsi/libsas/sas_expander.c
··· 429 429 430 430 #define MAX_EXPANDER_PHYS 128 431 431 432 - static void ex_assign_report_general(struct domain_device *dev, 433 - struct smp_resp *resp) 434 - { 435 - struct report_general_resp *rg = &resp->rg; 436 - 437 - dev->ex_dev.ex_change_count = be16_to_cpu(rg->change_count); 438 - dev->ex_dev.max_route_indexes = be16_to_cpu(rg->route_indexes); 439 - dev->ex_dev.num_phys = min(rg->num_phys, (u8)MAX_EXPANDER_PHYS); 440 - dev->ex_dev.t2t_supp = rg->t2t_supp; 441 - dev->ex_dev.conf_route_table = rg->conf_route_table; 442 - dev->ex_dev.configuring = rg->configuring; 443 - memcpy(dev->ex_dev.enclosure_logical_id, rg->enclosure_logical_id, 8); 444 - } 445 - 446 432 #define RG_REQ_SIZE 8 447 - #define RG_RESP_SIZE 32 433 + #define RG_RESP_SIZE sizeof(struct smp_rg_resp) 448 434 449 435 static int sas_ex_general(struct domain_device *dev) 450 436 { 451 437 u8 *rg_req; 452 - struct smp_resp *rg_resp; 438 + struct smp_rg_resp *rg_resp; 439 + struct report_general_resp *rg; 453 440 int res; 454 441 int i; 455 442 ··· 467 480 goto out; 468 481 } 469 482 470 - ex_assign_report_general(dev, rg_resp); 483 + rg = &rg_resp->rg; 484 + dev->ex_dev.ex_change_count = be16_to_cpu(rg->change_count); 485 + dev->ex_dev.max_route_indexes = be16_to_cpu(rg->route_indexes); 486 + dev->ex_dev.num_phys = min(rg->num_phys, (u8)MAX_EXPANDER_PHYS); 487 + dev->ex_dev.t2t_supp = rg->t2t_supp; 488 + dev->ex_dev.conf_route_table = rg->conf_route_table; 489 + dev->ex_dev.configuring = rg->configuring; 490 + memcpy(dev->ex_dev.enclosure_logical_id, 491 + rg->enclosure_logical_id, 8); 471 492 472 493 if (dev->ex_dev.configuring) { 473 494 pr_debug("RG: ex %016llx self-configuring...\n", ··· 1751 1756 { 1752 1757 int res; 1753 1758 u8 *rg_req; 1754 - struct smp_resp *rg_resp; 1759 + struct smp_rg_resp *rg_resp; 1755 1760 1756 1761 rg_req = alloc_smp_req(RG_REQ_SIZE); 1757 1762 if (!rg_req)
+8
include/scsi/sas.h
··· 696 696 #error "Bitfield order not defined!" 697 697 #endif 698 698 699 + struct smp_rg_resp { 700 + u8 frame_type; 701 + u8 function; 702 + u8 result; 703 + u8 reserved; 704 + struct report_general_resp rg; 705 + } __attribute__ ((packed)); 706 + 699 707 struct smp_disc_resp { 700 708 u8 frame_type; 701 709 u8 function;