Commit 44f2bfe9 authored by Damien Le Moal's avatar Damien Le Moal Committed by Martin K. Petersen
Browse files

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: default avatarJohn Garry <john.garry@huawei.com>
Signed-off-by: default avatarDamien Le Moal <damien.lemoal@opensource.wdc.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent c3752f44
Loading
Loading
Loading
Loading
+13 −18
Original line number Diff line number Diff line
@@ -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)
+8 −0
Original line number Diff line number Diff line
@@ -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;