Patch "scsi: aacraid: Rearrange order of struct aac_srb_unit" has been added to the 4.19-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    scsi: aacraid: Rearrange order of struct aac_srb_unit

to the 4.19-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     scsi-aacraid-rearrange-order-of-struct-aac_srb_unit.patch
and it can be found in the queue-4.19 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit f574198762b98bbcf7a1a6745e0469a5eee5fb0a
Author: Kees Cook <kees@xxxxxxxxxx>
Date:   Thu Jul 11 14:57:37 2024 -0700

    scsi: aacraid: Rearrange order of struct aac_srb_unit
    
    [ Upstream commit 6e5860b0ad4934baee8c7a202c02033b2631bb44 ]
    
    struct aac_srb_unit contains struct aac_srb, which contains struct sgmap,
    which ends in a (currently) "fake" (1-element) flexible array.  Converting
    this to a flexible array is needed so that runtime bounds checking won't
    think the array is fixed size (i.e. under CONFIG_FORTIFY_SOURCE=y and/or
    CONFIG_UBSAN_BOUNDS=y), as other parts of aacraid use struct sgmap as a
    flexible array.
    
    It is not legal to have a flexible array in the middle of a structure, so
    it either needs to be split up or rearranged so that it is at the end of
    the structure. Luckily, struct aac_srb_unit, which is exclusively
    consumed/updated by aac_send_safw_bmic_cmd(), does not depend on member
    ordering.
    
    The values set in the on-stack struct aac_srb_unit instance "srbu" by the
    only two callers, aac_issue_safw_bmic_identify() and
    aac_get_safw_ciss_luns(), do not contain anything in srbu.srb.sgmap.sg, and
    they both implicitly initialize srbu.srb.sgmap.count to 0 during
    memset(). For example:
    
            memset(&srbu, 0, sizeof(struct aac_srb_unit));
    
            srbcmd = &srbu.srb;
            srbcmd->flags   = cpu_to_le32(SRB_DataIn);
            srbcmd->cdb[0]  = CISS_REPORT_PHYSICAL_LUNS;
            srbcmd->cdb[1]  = 2; /* extended reporting */
            srbcmd->cdb[8]  = (u8)(datasize >> 8);
            srbcmd->cdb[9]  = (u8)(datasize);
    
            rcode = aac_send_safw_bmic_cmd(dev, &srbu, phys_luns, datasize);
    
    During aac_send_safw_bmic_cmd(), a separate srb is mapped into DMA, and has
    srbu.srb copied into it:
    
            srb = fib_data(fibptr);
            memcpy(srb, &srbu->srb, sizeof(struct aac_srb));
    
    Only then is srb.sgmap.count written and srb->sg populated:
    
            srb->count              = cpu_to_le32(xfer_len);
    
            sg64 = (struct sgmap64 *)&srb->sg;
            sg64->count             = cpu_to_le32(1);
            sg64->sg[0].addr[1]     = cpu_to_le32(upper_32_bits(addr));
            sg64->sg[0].addr[0]     = cpu_to_le32(lower_32_bits(addr));
            sg64->sg[0].count       = cpu_to_le32(xfer_len);
    
    But this is happening in the DMA memory, not in srbu.srb. An attempt to
    copy the changes back to srbu does happen:
    
            /*
             * Copy the updated data for other dumping or other usage if
             * needed
             */
            memcpy(&srbu->srb, srb, sizeof(struct aac_srb));
    
    But this was never correct: the sg64 (3 u32s) overlap of srb.sg (2 u32s)
    always meant that srbu.srb would have held truncated information and any
    attempt to walk srbu.srb.sg.sg based on the value of srbu.srb.sg.count
    would result in attempting to parse past the end of srbu.srb.sg.sg[0] into
    srbu.srb_reply.
    
    After getting a reply from hardware, the reply is copied into
    srbu.srb_reply:
    
            srb_reply = (struct aac_srb_reply *)fib_data(fibptr);
            memcpy(&srbu->srb_reply, srb_reply, sizeof(struct aac_srb_reply));
    
    This has always been fixed-size, so there's no issue here. It is worth
    noting that the two callers _never check_ srbu contents -- neither
    srbu.srb nor srbu.srb_reply is examined. (They depend on the mapped
    xfer_buf instead.)
    
    Therefore, the ordering of members in struct aac_srb_unit does not matter,
    and the flexible array member can moved to the end.
    
    (Additionally, the two memcpy()s that update srbu could be entirely
    removed as they are never consumed, but I left that as-is.)
    
    Signed-off-by: Kees Cook <kees@xxxxxxxxxx>
    Link: https://lore.kernel.org/r/20240711215739.208776-1-kees@xxxxxxxxxx
    Signed-off-by: Martin K. Petersen <martin.petersen@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 074760f210145..135e3f39c895c 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -2037,8 +2037,8 @@ struct aac_srb_reply
 };
 
 struct aac_srb_unit {
-	struct aac_srb		srb;
 	struct aac_srb_reply	srb_reply;
+	struct aac_srb		srb;
 };
 
 /*




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux