lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Wed, 24 Mar 2021 19:46:35 -0500
From:   "Gustavo A. R. Silva" <gustavo@...eddedor.com>
To:     "Martin K. Petersen" <martin.petersen@...cle.com>,
        "Gustavo A. R. Silva" <gustavoars@...nel.org>
Cc:     Adaptec OEM Raid Solutions <aacraid@...rosemi.com>,
        "James E.J. Bottomley" <jejb@...ux.ibm.com>,
        linux-scsi@...r.kernel.org, linux-kernel@...r.kernel.org,
        linux-hardening@...r.kernel.org
Subject: Re: [PATCH][next] scsi: aacraid: Replace one-element array with
 flexible-array member

Hi Martin,

On 3/24/21 20:18, Martin K. Petersen wrote:
> 
> Hi Gustavo!
> 
> Your changes and the original code do not appear to be functionally
> equivalent.
> 
>> @@ -1235,8 +1235,8 @@ static int aac_read_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u3
>>  		if (ret < 0)
>>  			return ret;
>>  		command = ContainerRawIo2;
>> -		fibsize = sizeof(struct aac_raw_io2) +
>> -			((le32_to_cpu(readcmd2->sgeCnt)-1) * sizeof(struct sge_ieee1212));
>> +		fibsize = struct_size(readcmd2, sge,
>> +				     le32_to_cpu(readcmd2->sgeCnt));
> 
> The old code allocated sgeCnt-1 elements (whether that was a mistake or
> not I do not know) whereas the new code would send a larger fib to the
> ASIC. I don't have any aacraid adapters and I am hesitant to merging
> changes that have not been validated on real hardware.

Precisely this sort of confusion is one of the things we want to avoid
by using flexible-array members instead of one-element arrays.

fibsize is actually the same for both the old and the new code. The
difference is that in the original code, the one-element array _sge_
at the bottom of struct aac_raw_io2, contributes to the size of the
structure, as it occupies at least as much space as a single object
of its type. On the other hand, flexible-array members don't contribute
to the size of the enclosing structure. See below...

Old code:

$ pahole -C aac_raw_io2 drivers/scsi/aacraid/aachba.o
struct aac_raw_io2 {
	__le32                     blockLow;             /*     0     4 */
	__le32                     blockHigh;            /*     4     4 */
	__le32                     byteCount;            /*     8     4 */
	__le16                     cid;                  /*    12     2 */
	__le16                     flags;                /*    14     2 */
	__le32                     sgeFirstSize;         /*    16     4 */
	__le32                     sgeNominalSize;       /*    20     4 */
	u8                         sgeCnt;               /*    24     1 */
	u8                         bpTotal;              /*    25     1 */
	u8                         bpComplete;           /*    26     1 */
	u8                         sgeFirstIndex;        /*    27     1 */
	u8                         unused[4];            /*    28     4 */
	struct sge_ieee1212        sge[1];               /*    32    16 */

	/* size: 48, cachelines: 1, members: 13 */
	/* last cacheline: 48 bytes */
};

New code:

$ pahole -C aac_raw_io2 drivers/scsi/aacraid/aachba.o
struct aac_raw_io2 {
	__le32                     blockLow;             /*     0     4 */
	__le32                     blockHigh;            /*     4     4 */
	__le32                     byteCount;            /*     8     4 */
	__le16                     cid;                  /*    12     2 */
	__le16                     flags;                /*    14     2 */
	__le32                     sgeFirstSize;         /*    16     4 */
	__le32                     sgeNominalSize;       /*    20     4 */
	u8                         sgeCnt;               /*    24     1 */
	u8                         bpTotal;              /*    25     1 */
	u8                         bpComplete;           /*    26     1 */
	u8                         sgeFirstIndex;        /*    27     1 */
	u8                         unused[4];            /*    28     4 */
	struct sge_ieee1212        sge[];                /*    32     0 */

	/* size: 32, cachelines: 1, members: 13 */
	/* last cacheline: 32 bytes */
};

So, the old code allocates sgeCnt-1 elements because sizeof(struct aac_raw_io2) is
already counting one element of the _sge_ array.

Please, let me know if this is clear now.

Thanks!
--
Gustavo

Powered by blists - more mailing lists