Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

target: Avoid integer overflow in se_dev_align_max_sectors()

The expression (max_sectors * block_size) might overflow a u32
(indeed, since iblock sets max_hw_sectors to UINT_MAX, it is
guaranteed to overflow and end up with a much-too-small result in many
common cases). Fix this by doing an equivalent calculation that
doesn't require multiplication.

While we're touching this code, avoid splitting a printk format across
two lines and use pr_info(...) instead of printk(KERN_INFO ...).

Signed-off-by: Roland Dreier <roland@purestorage.com>
Cc: stable@vger.kernel.org
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>

authored by

Roland Dreier and committed by
Nicholas Bellinger
3e03989b 0d0f9dfb

+9 -9
+9 -9
drivers/target/target_core_device.c
··· 850 850 851 851 static u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size) 852 852 { 853 - u32 tmp, aligned_max_sectors; 853 + u32 aligned_max_sectors; 854 + u32 alignment; 854 855 /* 855 856 * Limit max_sectors to a PAGE_SIZE aligned value for modern 856 857 * transport_allocate_data_tasks() operation. 857 858 */ 858 - tmp = rounddown((max_sectors * block_size), PAGE_SIZE); 859 - aligned_max_sectors = (tmp / block_size); 860 - if (max_sectors != aligned_max_sectors) { 861 - printk(KERN_INFO "Rounding down aligned max_sectors from %u" 862 - " to %u\n", max_sectors, aligned_max_sectors); 863 - return aligned_max_sectors; 864 - } 859 + alignment = max(1ul, PAGE_SIZE / block_size); 860 + aligned_max_sectors = rounddown(max_sectors, alignment); 865 861 866 - return max_sectors; 862 + if (max_sectors != aligned_max_sectors) 863 + pr_info("Rounding down aligned max_sectors from %u to %u\n", 864 + max_sectors, aligned_max_sectors); 865 + 866 + return aligned_max_sectors; 867 867 } 868 868 869 869 void se_dev_set_default_attribs(