Skip to content
  • Benjamin Block's avatar
    bsg-lib: fix use-after-free under memory-pressure · eab40cf3
    Benjamin Block authored
    When under memory-pressure it is possible that the mempool which backs
    the 'struct request_queue' will make use of up to BLKDEV_MIN_RQ count
    emergency buffers - in case it can't get a regular allocation. These
    buffers are preallocated and once they are also used, they are
    re-supplied with old finished requests from the same request_queue (see
    mempool_free()).
    
    The bug is, when re-supplying the emergency pool, the old requests are
    not again ran through the callback mempool_t->alloc(), and thus also not
    through the callback bsg_init_rq(). Thus we skip initialization, and
    while the sense-buffer still should be good, scsi_request->cmd might
    have become to be an invalid pointer in the meantime. When the request
    is initialized in bsg.c, and the user's CDB is larger than BLK_MAX_CDB,
    bsg will replace it with a custom allocated buffer, which is freed when
    the user's command is finished, thus it dangles afterwards. When next a
    command is sent by the user that has a smaller/similar CDB as
    BLK_MAX_CDB, bsg will assume that scsi_request->cmd is backed by
    scsi_request->__cmd, will not make a custom allocation, and write into
    undefined memory.
    
    Fix this by splitting bsg_init_rq() into two functions:
     - bsg_init_rq() is changed to only do the allocation of the
       sense-buffer, which is used to back the bsg job's reply buffer. This
       pointer should never change during the lifetime of a scsi_request, so
       it doesn't need re-initialization.
     - bsg_initialize_rq() is a new function that makes use of
       'struct request_queue's initialize_rq_fn callback (which was
       introduced in v4.12). This is always called before the request is
       given out via blk_get_request(). This function does the remaining
       initialization that was previously done in bsg_init_rq(), and will
       also do it when the request is taken from the emergency-pool of the
       backing mempool.
    
    Fixes: 50b4d485
    
     ("bsg-lib: fix kernel panic resulting from missing allocation of reply-buffer")
    Cc: <stable@vger.kernel.org> # 4.11+
    Reviewed-by: default avatarHannes Reinecke <hare@suse.com>
    Reviewed-by: default avatarJohannes Thumshirn <jthumshirn@suse.de>
    Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
    Signed-off-by: default avatarBenjamin Block <bblock@linux.vnet.ibm.com>
    Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
    eab40cf3