• Martin Wilck's avatar
    scsi: target: pscsi: Avoid OOM in pscsi_map_sg() · 077ce028
    Martin Wilck authored
    pscsi_map_sg() uses the variable nr_pages as a hint for bio_kmalloc() how
    many vector elements to allocate. If nr_pages is < BIO_MAX_PAGES, it will
    be reset to 0 after successful allocation of the bio.
    
    If bio_add_pc_page() fails later for whatever reason, pscsi_map_sg() tries
    to allocate another bio, passing nr_vecs = 0. This causes bio_add_pc_page()
    to fail immediately in the next call. pci_map_sg() continues to allocate
    zero-length bios until memory is exhausted and the kernel crashes with
    OOM. This can be easily observed by exporting a SATA DVD drive via pscsi.
    The target crashes as soon as the client tries to access the DVD LUN. In
    the case I analyzed, bio_add_pc_page() would fail because the DVD device's
    max_sectors_kb (128) was exceeded.
    
    Avoid this by simply not resetting nr_pages to 0 after allocating the
    bio. This way, the client receives an I/O error when it tries to send
    requests exceeding the devices max_sectors_kb, and eventually gets it
    right. The client must still limit max_sectors_kb e.g. by an udev rule if
    (like in my case) the driver doesn't report valid block limits, otherwise
    it encounters I/O errors.
    
    Link: https://lore.kernel.org/r/20210323212431.15306-1-mwilck@suse.comReviewed-by: default avatarChristoph Hellwig <hch@lst.de>
    Reviewed-by: default avatarLee Duncan <lduncan@suse.com>
    Signed-off-by: default avatarMartin Wilck <mwilck@suse.com>
    Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
    077ce028
target_core_pscsi.c 27.4 KB