OSDN Git Service

scsi: libsas: Introduce struct smp_rg_resp
authorDamien Le Moal <damien.lemoal@opensource.wdc.com>
Thu, 9 Jun 2022 02:24:55 +0000 (11:24 +0900)
committerMartin K. Petersen <martin.petersen@oracle.com>
Fri, 10 Jun 2022 17:08:06 +0000 (13:08 -0400)
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>
drivers/scsi/libsas/sas_expander.c
include/scsi/sas.h

index fb998a8..78a3898 100644 (file)
@@ -429,27 +429,14 @@ static int sas_expander_discover(struct domain_device *dev)
 
 #define MAX_EXPANDER_PHYS 128
 
-static void ex_assign_report_general(struct domain_device *dev,
-                                           struct smp_resp *resp)
-{
-       struct report_general_resp *rg = &resp->rg;
-
-       dev->ex_dev.ex_change_count = be16_to_cpu(rg->change_count);
-       dev->ex_dev.max_route_indexes = be16_to_cpu(rg->route_indexes);
-       dev->ex_dev.num_phys = min(rg->num_phys, (u8)MAX_EXPANDER_PHYS);
-       dev->ex_dev.t2t_supp = rg->t2t_supp;
-       dev->ex_dev.conf_route_table = rg->conf_route_table;
-       dev->ex_dev.configuring = rg->configuring;
-       memcpy(dev->ex_dev.enclosure_logical_id, rg->enclosure_logical_id, 8);
-}
-
 #define RG_REQ_SIZE   8
-#define RG_RESP_SIZE 32
+#define RG_RESP_SIZE  sizeof(struct smp_rg_resp)
 
 static int sas_ex_general(struct domain_device *dev)
 {
        u8 *rg_req;
-       struct smp_resp *rg_resp;
+       struct smp_rg_resp *rg_resp;
+       struct report_general_resp *rg;
        int res;
        int i;
 
@@ -480,7 +467,15 @@ static int sas_ex_general(struct domain_device *dev)
                        goto out;
                }
 
-               ex_assign_report_general(dev, rg_resp);
+               rg = &rg_resp->rg;
+               dev->ex_dev.ex_change_count = be16_to_cpu(rg->change_count);
+               dev->ex_dev.max_route_indexes = be16_to_cpu(rg->route_indexes);
+               dev->ex_dev.num_phys = min(rg->num_phys, (u8)MAX_EXPANDER_PHYS);
+               dev->ex_dev.t2t_supp = rg->t2t_supp;
+               dev->ex_dev.conf_route_table = rg->conf_route_table;
+               dev->ex_dev.configuring = rg->configuring;
+               memcpy(dev->ex_dev.enclosure_logical_id,
+                      rg->enclosure_logical_id, 8);
 
                if (dev->ex_dev.configuring) {
                        pr_debug("RG: ex %016llx self-configuring...\n",
@@ -1756,7 +1751,7 @@ static int sas_get_ex_change_count(struct domain_device *dev, int *ecc)
 {
        int res;
        u8  *rg_req;
-       struct smp_resp  *rg_resp;
+       struct smp_rg_resp  *rg_resp;
 
        rg_req = alloc_smp_req(RG_REQ_SIZE);
        if (!rg_req)
index b3ee9bd..a8f9743 100644 (file)
@@ -696,6 +696,14 @@ struct report_phy_sata_resp {
 #error "Bitfield order not defined!"
 #endif
 
+struct smp_rg_resp {
+       u8    frame_type;
+       u8    function;
+       u8    result;
+       u8    reserved;
+       struct report_general_resp rg;
+} __attribute__ ((packed));
+
 struct smp_disc_resp {
        u8    frame_type;
        u8    function;