| From 467d9b5f95bc298e67263602ed0f653715a7888d Mon Sep 17 00:00:00 2001 |
| From: Mikulas Patocka <mpatocka@redhat.com> |
| Date: Wed, 15 Jan 2020 08:35:25 -0500 |
| Subject: [PATCH] block: fix an integer overflow in logical block size |
| |
| commit ad6bf88a6c19a39fb3b0045d78ea880325dfcf15 upstream. |
| |
| Logical block size has type unsigned short. That means that it can be at |
| most 32768. However, there are architectures that can run with 64k pages |
| (for example arm64) and on these architectures, it may be possible to |
| create block devices with 64k block size. |
| |
| For exmaple (run this on an architecture with 64k pages): |
| |
| Mount will fail with this error because it tries to read the superblock using 2-sector |
| access: |
| device-mapper: writecache: I/O is not aligned, sector 2, size 1024, block size 65536 |
| EXT4-fs (dm-0): unable to read superblock |
| |
| This patch changes the logical block size from unsigned short to unsigned |
| int to avoid the overflow. |
| |
| Cc: stable@vger.kernel.org |
| Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com> |
| Reviewed-by: Ming Lei <ming.lei@redhat.com> |
| Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> |
| Signed-off-by: Jens Axboe <axboe@kernel.dk> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/block/blk-settings.c b/block/blk-settings.c |
| index 2ae348c101a0..db7d01fd921b 100644 |
| --- a/block/blk-settings.c |
| +++ b/block/blk-settings.c |
| @@ -327,7 +327,7 @@ EXPORT_SYMBOL(blk_queue_max_segment_size); |
| * storage device can address. The default of 512 covers most |
| * hardware. |
| **/ |
| -void blk_queue_logical_block_size(struct request_queue *q, unsigned short size) |
| +void blk_queue_logical_block_size(struct request_queue *q, unsigned int size) |
| { |
| q->limits.logical_block_size = size; |
| |
| diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c |
| index 3c50c4e4da8f..963d3774c93e 100644 |
| --- a/drivers/md/dm-snap-persistent.c |
| +++ b/drivers/md/dm-snap-persistent.c |
| @@ -17,7 +17,7 @@ |
| #include <linux/dm-bufio.h> |
| |
| #define DM_MSG_PREFIX "persistent snapshot" |
| -#define DM_CHUNK_SIZE_DEFAULT_SECTORS 32 /* 16KB */ |
| +#define DM_CHUNK_SIZE_DEFAULT_SECTORS 32U /* 16KB */ |
| |
| #define DM_PREFETCH_CHUNKS 12 |
| |
| diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c |
| index 8f4046d5789d..40432cbd54d1 100644 |
| --- a/drivers/md/raid0.c |
| +++ b/drivers/md/raid0.c |
| @@ -87,7 +87,7 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf) |
| char b[BDEVNAME_SIZE]; |
| char b2[BDEVNAME_SIZE]; |
| struct r0conf *conf = kzalloc(sizeof(*conf), GFP_KERNEL); |
| - unsigned short blksize = 512; |
| + unsigned blksize = 512; |
| |
| *private_conf = ERR_PTR(-ENOMEM); |
| if (!conf) |
| diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h |
| index 4c6754e53672..5d9fe980125c 100644 |
| --- a/include/linux/blkdev.h |
| +++ b/include/linux/blkdev.h |
| @@ -324,6 +324,7 @@ struct queue_limits { |
| unsigned int max_sectors; |
| unsigned int max_segment_size; |
| unsigned int physical_block_size; |
| + unsigned int logical_block_size; |
| unsigned int alignment_offset; |
| unsigned int io_min; |
| unsigned int io_opt; |
| @@ -334,7 +335,6 @@ struct queue_limits { |
| unsigned int discard_granularity; |
| unsigned int discard_alignment; |
| |
| - unsigned short logical_block_size; |
| unsigned short max_segments; |
| unsigned short max_integrity_segments; |
| unsigned short max_discard_segments; |
| @@ -1077,7 +1077,7 @@ extern void blk_queue_max_write_same_sectors(struct request_queue *q, |
| unsigned int max_write_same_sectors); |
| extern void blk_queue_max_write_zeroes_sectors(struct request_queue *q, |
| unsigned int max_write_same_sectors); |
| -extern void blk_queue_logical_block_size(struct request_queue *, unsigned short); |
| +extern void blk_queue_logical_block_size(struct request_queue *, unsigned int); |
| extern void blk_queue_physical_block_size(struct request_queue *, unsigned int); |
| extern void blk_queue_alignment_offset(struct request_queue *q, |
| unsigned int alignment); |
| @@ -1287,7 +1287,7 @@ static inline unsigned int queue_max_segment_size(struct request_queue *q) |
| return q->limits.max_segment_size; |
| } |
| |
| -static inline unsigned short queue_logical_block_size(struct request_queue *q) |
| +static inline unsigned queue_logical_block_size(struct request_queue *q) |
| { |
| int retval = 512; |
| |
| @@ -1297,7 +1297,7 @@ static inline unsigned short queue_logical_block_size(struct request_queue *q) |
| return retval; |
| } |
| |
| -static inline unsigned short bdev_logical_block_size(struct block_device *bdev) |
| +static inline unsigned int bdev_logical_block_size(struct block_device *bdev) |
| { |
| return queue_logical_block_size(bdev_get_queue(bdev)); |
| } |
| -- |
| 2.7.4 |
| |