Re: [PATCH v4 4/5] scsi: mpi3mr: use number of bits to manage bitmap sizes

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

 



On Thu, Jan 26, 2023 at 11:35 PM Shin'ichiro Kawasaki
<shinichiro.kawasaki@xxxxxxx> wrote:
>
> To allocate bitmaps, the mpi3mr driver calculates sizes of bitmaps using
> byte as unit. However, bitmap helper functions assume that bitmaps are
> allocated using unsigned long as unit. This gap causes memory access
> beyond the bitmap sizes and results in "BUG: KASAN: slab-out-of-bounds".
> The BUG was observed at firmware download to eHBA-9600. Call trace
> indicated that the out-of-bounds access happened in find_first_zero_bit
> called from mpi3mr_send_event_ack for miroc->evtack_cmds_bitmap.
>
> To fix the BUG, do not use bytes to manage bitmap sizes. Instead, use
> number of bits, and call bitmap helper functions which take number of
> bits as arguments. For memory allocation, call bitmap_zalloc instead of
> kzalloc. For zero clear, call bitmap_clear instead of memset. For
> resize, call bitmap_zalloc and bitmap_copy instead of krealloc.
>
> Remove three fields for bitmap byte sizes in struct scmd_priv, which are
> no longer required. Replace the field dev_handle_bitmap_sz with
> dev_handle_bitmap_bits to keep number of bits of removepend_bitmap
> across resize.
>
>>Thanks for getting this changed, can you please change the kfree for the bitmaps to bitmap_free for consistency of the API.
> Fixes: c5758fc72b92 ("scsi: mpi3mr: Gracefully handle online FW update operation")
> Fixes: e844adb1fbdc ("scsi: mpi3mr: Implement SCSI error handler hooks")
> Fixes: c1af985d27da ("scsi: mpi3mr: Add Event acknowledgment logic")
> Fixes: 824a156633df ("scsi: mpi3mr: Base driver code")
> Reviewed-by: Damien Le Moal <damien.lemoal@xxxxxxxxxxxxxxxxxx>
> Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@xxxxxxx>
> ---
>  drivers/scsi/mpi3mr/mpi3mr.h    | 10 +----
>  drivers/scsi/mpi3mr/mpi3mr_fw.c | 68 ++++++++++++++-------------------
>  2 files changed, 30 insertions(+), 48 deletions(-)
>
> diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h
> index def4c5e15cd8..8a438f248a82 100644
> --- a/drivers/scsi/mpi3mr/mpi3mr.h
> +++ b/drivers/scsi/mpi3mr/mpi3mr.h
> @@ -955,19 +955,16 @@ struct scmd_priv {
>   * @chain_buf_count: Chain buffer count
>   * @chain_buf_pool: Chain buffer pool
>   * @chain_sgl_list: Chain SGL list
> - * @chain_bitmap_sz: Chain buffer allocator bitmap size
>   * @chain_bitmap: Chain buffer allocator bitmap
>   * @chain_buf_lock: Chain buffer list lock
>   * @bsg_cmds: Command tracker for BSG command
>   * @host_tm_cmds: Command tracker for task management commands
>   * @dev_rmhs_cmds: Command tracker for device removal commands
>   * @evtack_cmds: Command tracker for event ack commands
> - * @devrem_bitmap_sz: Device removal bitmap size
>   * @devrem_bitmap: Device removal bitmap
> - * @dev_handle_bitmap_sz: Device handle bitmap size
> + * @dev_handle_bitmap_bits: Number of bits in device handle bitmap
>   * @removepend_bitmap: Remove pending bitmap
>   * @delayed_rmhs_list: Delayed device removal list
> - * @evtack_cmds_bitmap_sz: Event Ack bitmap size
>   * @evtack_cmds_bitmap: Event Ack bitmap
>   * @delayed_evtack_cmds_list: Delayed event acknowledgment list
>   * @ts_update_counter: Timestamp update counter
> @@ -1128,7 +1125,6 @@ struct mpi3mr_ioc {
>         u32 chain_buf_count;
>         struct dma_pool *chain_buf_pool;
>         struct chain_element *chain_sgl_list;
> -       u16  chain_bitmap_sz;
>         void *chain_bitmap;
>         spinlock_t chain_buf_lock;
>
> @@ -1136,12 +1132,10 @@ struct mpi3mr_ioc {
>         struct mpi3mr_drv_cmd host_tm_cmds;
>         struct mpi3mr_drv_cmd dev_rmhs_cmds[MPI3MR_NUM_DEVRMCMD];
>         struct mpi3mr_drv_cmd evtack_cmds[MPI3MR_NUM_EVTACKCMD];
> -       u16 devrem_bitmap_sz;
>         void *devrem_bitmap;
> -       u16 dev_handle_bitmap_sz;
> +       u16 dev_handle_bitmap_bits;
>         void *removepend_bitmap;
>         struct list_head delayed_rmhs_list;
> -       u16 evtack_cmds_bitmap_sz;
>         void *evtack_cmds_bitmap;
>         struct list_head delayed_evtack_cmds_list;
>
> diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c
> index 286a44506578..d25cd0382e20 100644
> --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c
> +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c
> @@ -1128,7 +1128,6 @@ static int mpi3mr_issue_and_process_mur(struct mpi3mr_ioc *mrioc,
>  static int
>  mpi3mr_revalidate_factsdata(struct mpi3mr_ioc *mrioc)
>  {
> -       u16 dev_handle_bitmap_sz;
>         void *removepend_bitmap;
>
>         if (mrioc->facts.reply_sz > mrioc->reply_sz) {
> @@ -1160,25 +1159,24 @@ mpi3mr_revalidate_factsdata(struct mpi3mr_ioc *mrioc)
>                     "\tcontroller while sas transport support is enabled at the\n"
>                     "\tdriver, please reboot the system or reload the driver\n");
>
> -       dev_handle_bitmap_sz = mrioc->facts.max_devhandle / 8;
> -       if (mrioc->facts.max_devhandle % 8)
> -               dev_handle_bitmap_sz++;
> -       if (dev_handle_bitmap_sz > mrioc->dev_handle_bitmap_sz) {
> -               removepend_bitmap = krealloc(mrioc->removepend_bitmap,
> -                   dev_handle_bitmap_sz, GFP_KERNEL);
> +       if (mrioc->facts.max_devhandle > mrioc->dev_handle_bitmap_bits) {
>>Free the existing removepend_bitmap prior the alloc.
> +               removepend_bitmap = bitmap_zalloc(mrioc->facts.max_devhandle,
> +                                                 GFP_KERNEL);
>                 if (!removepend_bitmap) {
>                         ioc_err(mrioc,
> -                           "failed to increase removepend_bitmap sz from: %d to %d\n",
> -                           mrioc->dev_handle_bitmap_sz, dev_handle_bitmap_sz);
> +                               "failed to increase removepend_bitmap bits from %d to %d\n",
> +                               mrioc->dev_handle_bitmap_bits,
> +                               mrioc->facts.max_devhandle);
>                         return -EPERM;
>                 }
> -               memset(removepend_bitmap + mrioc->dev_handle_bitmap_sz, 0,
> -                   dev_handle_bitmap_sz - mrioc->dev_handle_bitmap_sz);
> +               bitmap_copy(removepend_bitmap, mrioc->removepend_bitmap,
> +                           mrioc->dev_handle_bitmap_bits);
>>This copy is not needed as the data in the removepend_bitmap is not valid after reset and the zalloc already cleared the memory.

>                 mrioc->removepend_bitmap = removepend_bitmap;
>                 ioc_info(mrioc,
> -                   "increased dev_handle_bitmap_sz from %d to %d\n",
> -                   mrioc->dev_handle_bitmap_sz, dev_handle_bitmap_sz);
> -               mrioc->dev_handle_bitmap_sz = dev_handle_bitmap_sz;
> +                        "increased bits of dev_handle_bitmap from %d to %d\n",
> +                        mrioc->dev_handle_bitmap_bits,
> +                        mrioc->facts.max_devhandle);
> +               mrioc->dev_handle_bitmap_bits = mrioc->facts.max_devhandle;
>         }
>
>         return 0;
> @@ -2957,27 +2955,18 @@ static int mpi3mr_alloc_reply_sense_bufs(struct mpi3mr_ioc *mrioc)
>         if (!mrioc->pel_abort_cmd.reply)
>                 goto out_failed;
>
> -       mrioc->dev_handle_bitmap_sz = mrioc->facts.max_devhandle / 8;
> -       if (mrioc->facts.max_devhandle % 8)
> -               mrioc->dev_handle_bitmap_sz++;
> -       mrioc->removepend_bitmap = kzalloc(mrioc->dev_handle_bitmap_sz,
> -           GFP_KERNEL);
> +       mrioc->dev_handle_bitmap_bits = mrioc->facts.max_devhandle;
> +       mrioc->removepend_bitmap = bitmap_zalloc(mrioc->dev_handle_bitmap_bits,
> +                                                GFP_KERNEL);
>         if (!mrioc->removepend_bitmap)
>                 goto out_failed;
>
> -       mrioc->devrem_bitmap_sz = MPI3MR_NUM_DEVRMCMD / 8;
> -       if (MPI3MR_NUM_DEVRMCMD % 8)
> -               mrioc->devrem_bitmap_sz++;
> -       mrioc->devrem_bitmap = kzalloc(mrioc->devrem_bitmap_sz,
> -           GFP_KERNEL);
> +       mrioc->devrem_bitmap = bitmap_zalloc(MPI3MR_NUM_DEVRMCMD, GFP_KERNEL);
>         if (!mrioc->devrem_bitmap)
>                 goto out_failed;
>
> -       mrioc->evtack_cmds_bitmap_sz = MPI3MR_NUM_EVTACKCMD / 8;
> -       if (MPI3MR_NUM_EVTACKCMD % 8)
> -               mrioc->evtack_cmds_bitmap_sz++;
> -       mrioc->evtack_cmds_bitmap = kzalloc(mrioc->evtack_cmds_bitmap_sz,
> -           GFP_KERNEL);
> +       mrioc->evtack_cmds_bitmap = bitmap_zalloc(MPI3MR_NUM_EVTACKCMD,
> +                                                 GFP_KERNEL);
>         if (!mrioc->evtack_cmds_bitmap)
>                 goto out_failed;
>
> @@ -3415,10 +3404,7 @@ static int mpi3mr_alloc_chain_bufs(struct mpi3mr_ioc *mrioc)
>                 if (!mrioc->chain_sgl_list[i].addr)
>                         goto out_failed;
>         }
> -       mrioc->chain_bitmap_sz = num_chains / 8;
> -       if (num_chains % 8)
> -               mrioc->chain_bitmap_sz++;
> -       mrioc->chain_bitmap = kzalloc(mrioc->chain_bitmap_sz, GFP_KERNEL);
> +       mrioc->chain_bitmap = bitmap_zalloc(num_chains, GFP_KERNEL);
>         if (!mrioc->chain_bitmap)
>                 goto out_failed;
>         return retval;
> @@ -4189,10 +4175,11 @@ void mpi3mr_memset_buffers(struct mpi3mr_ioc *mrioc)
>                 for (i = 0; i < MPI3MR_NUM_EVTACKCMD; i++)
>                         memset(mrioc->evtack_cmds[i].reply, 0,
>                             sizeof(*mrioc->evtack_cmds[i].reply));
> -               memset(mrioc->removepend_bitmap, 0, mrioc->dev_handle_bitmap_sz);
> -               memset(mrioc->devrem_bitmap, 0, mrioc->devrem_bitmap_sz);
> -               memset(mrioc->evtack_cmds_bitmap, 0,
> -                   mrioc->evtack_cmds_bitmap_sz);
> +               bitmap_clear(mrioc->removepend_bitmap, 0,
> +                            mrioc->dev_handle_bitmap_bits);
> +               bitmap_clear(mrioc->devrem_bitmap, 0, MPI3MR_NUM_DEVRMCMD);
> +               bitmap_clear(mrioc->evtack_cmds_bitmap, 0,
> +                            MPI3MR_NUM_EVTACKCMD);
>         }
>
>         for (i = 0; i < mrioc->num_queues; i++) {
> @@ -4886,9 +4873,10 @@ int mpi3mr_soft_reset_handler(struct mpi3mr_ioc *mrioc,
>
>         mpi3mr_flush_delayed_cmd_lists(mrioc);
>         mpi3mr_flush_drv_cmds(mrioc);
> -       memset(mrioc->devrem_bitmap, 0, mrioc->devrem_bitmap_sz);
> -       memset(mrioc->removepend_bitmap, 0, mrioc->dev_handle_bitmap_sz);
> -       memset(mrioc->evtack_cmds_bitmap, 0, mrioc->evtack_cmds_bitmap_sz);
> +       bitmap_clear(mrioc->devrem_bitmap, 0, MPI3MR_NUM_DEVRMCMD);
> +       bitmap_clear(mrioc->removepend_bitmap, 0,
> +                    mrioc->dev_handle_bitmap_bits);
> +       bitmap_clear(mrioc->evtack_cmds_bitmap, 0, MPI3MR_NUM_EVTACKCMD);
>         mpi3mr_flush_host_io(mrioc);
>         mpi3mr_cleanup_fwevt_list(mrioc);
>         mpi3mr_invalidate_devhandles(mrioc);
> --
> 2.38.1
>

-- 
This electronic communication and the information and any files transmitted 
with it, or attached to it, are confidential and are intended solely for 
the use of the individual or entity to whom it is addressed and may contain 
information that is confidential, legally privileged, protected by privacy 
laws, or otherwise restricted from disclosure to anyone else. If you are 
not the intended recipient or the person responsible for delivering the 
e-mail to the intended recipient, you are hereby notified that any use, 
copying, distributing, dissemination, forwarding, printing, or copying of 
this e-mail is strictly prohibited. If you received this e-mail in error, 
please return the e-mail to the sender, delete it from your computer, and 
destroy any printed copy of it.

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]

  Powered by Linux