Skip to content

Commit 52c5e62

Browse files
Christoph Hellwigaxboe
authored andcommitted
block: bio_check_eod() needs to consider partitions
bio_check_eod() should check partition size not the whole disk if bio->bi_partno is non-zero. Do this by moving the call to bio_check_eod() into blk_partition_remap(). Based on an earlier patch from Jiufei Xue. Fixes: 74d4699 ("block: replace bi_bdev with a gendisk pointer and partitions index") Reported-by: Jiufei Xue <[email protected]> Signed-off-by: Christoph Hellwig <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent 233bde2 commit 52c5e62

File tree

1 file changed

+40
-53
lines changed

1 file changed

+40
-53
lines changed

block/blk-core.c

Lines changed: 40 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -2122,15 +2122,15 @@ static blk_qc_t blk_queue_bio(struct request_queue *q, struct bio *bio)
21222122
return BLK_QC_T_NONE;
21232123
}
21242124

2125-
static void handle_bad_sector(struct bio *bio)
2125+
static void handle_bad_sector(struct bio *bio, sector_t maxsector)
21262126
{
21272127
char b[BDEVNAME_SIZE];
21282128

21292129
printk(KERN_INFO "attempt to access beyond end of device\n");
21302130
printk(KERN_INFO "%s: rw=%d, want=%Lu, limit=%Lu\n",
21312131
bio_devname(bio, b), bio->bi_opf,
21322132
(unsigned long long)bio_end_sector(bio),
2133-
(long long)get_capacity(bio->bi_disk));
2133+
(long long)maxsector);
21342134
}
21352135

21362136
#ifdef CONFIG_FAIL_MAKE_REQUEST
@@ -2191,68 +2191,59 @@ static noinline int should_fail_bio(struct bio *bio)
21912191
}
21922192
ALLOW_ERROR_INJECTION(should_fail_bio, ERRNO);
21932193

2194+
/*
2195+
* Check whether this bio extends beyond the end of the device or partition.
2196+
* This may well happen - the kernel calls bread() without checking the size of
2197+
* the device, e.g., when mounting a file system.
2198+
*/
2199+
static inline int bio_check_eod(struct bio *bio, sector_t maxsector)
2200+
{
2201+
unsigned int nr_sectors = bio_sectors(bio);
2202+
2203+
if (nr_sectors && maxsector &&
2204+
(nr_sectors > maxsector ||
2205+
bio->bi_iter.bi_sector > maxsector - nr_sectors)) {
2206+
handle_bad_sector(bio, maxsector);
2207+
return -EIO;
2208+
}
2209+
return 0;
2210+
}
2211+
21942212
/*
21952213
* Remap block n of partition p to block n+start(p) of the disk.
21962214
*/
21972215
static inline int blk_partition_remap(struct bio *bio)
21982216
{
21992217
struct hd_struct *p;
2200-
int ret = 0;
2218+
int ret = -EIO;
22012219

22022220
rcu_read_lock();
22032221
p = __disk_get_part(bio->bi_disk, bio->bi_partno);
2204-
if (unlikely(!p || should_fail_request(p, bio->bi_iter.bi_size) ||
2205-
bio_check_ro(bio, p))) {
2206-
ret = -EIO;
2222+
if (unlikely(!p))
2223+
goto out;
2224+
if (unlikely(should_fail_request(p, bio->bi_iter.bi_size)))
2225+
goto out;
2226+
if (unlikely(bio_check_ro(bio, p)))
22072227
goto out;
2208-
}
22092228

22102229
/*
22112230
* Zone reset does not include bi_size so bio_sectors() is always 0.
22122231
* Include a test for the reset op code and perform the remap if needed.
22132232
*/
2214-
if (!bio_sectors(bio) && bio_op(bio) != REQ_OP_ZONE_RESET)
2215-
goto out;
2216-
2217-
bio->bi_iter.bi_sector += p->start_sect;
2218-
bio->bi_partno = 0;
2219-
trace_block_bio_remap(bio->bi_disk->queue, bio, part_devt(p),
2220-
bio->bi_iter.bi_sector - p->start_sect);
2221-
2233+
if (bio_sectors(bio) || bio_op(bio) == REQ_OP_ZONE_RESET) {
2234+
if (bio_check_eod(bio, part_nr_sects_read(p)))
2235+
goto out;
2236+
bio->bi_iter.bi_sector += p->start_sect;
2237+
bio->bi_partno = 0;
2238+
trace_block_bio_remap(bio->bi_disk->queue, bio, part_devt(p),
2239+
bio->bi_iter.bi_sector - p->start_sect);
2240+
}
2241+
ret = 0;
22222242
out:
22232243
rcu_read_unlock();
22242244
return ret;
22252245
}
22262246

2227-
/*
2228-
* Check whether this bio extends beyond the end of the device.
2229-
*/
2230-
static inline int bio_check_eod(struct bio *bio, unsigned int nr_sectors)
2231-
{
2232-
sector_t maxsector;
2233-
2234-
if (!nr_sectors)
2235-
return 0;
2236-
2237-
/* Test device or partition size, when known. */
2238-
maxsector = get_capacity(bio->bi_disk);
2239-
if (maxsector) {
2240-
sector_t sector = bio->bi_iter.bi_sector;
2241-
2242-
if (maxsector < nr_sectors || maxsector - nr_sectors < sector) {
2243-
/*
2244-
* This may well happen - the kernel calls bread()
2245-
* without checking the size of the device, e.g., when
2246-
* mounting a device.
2247-
*/
2248-
handle_bad_sector(bio);
2249-
return 1;
2250-
}
2251-
}
2252-
2253-
return 0;
2254-
}
2255-
22562247
static noinline_for_stack bool
22572248
generic_make_request_checks(struct bio *bio)
22582249
{
@@ -2263,9 +2254,6 @@ generic_make_request_checks(struct bio *bio)
22632254

22642255
might_sleep();
22652256

2266-
if (bio_check_eod(bio, nr_sectors))
2267-
goto end_io;
2268-
22692257
q = bio->bi_disk->queue;
22702258
if (unlikely(!q)) {
22712259
printk(KERN_ERR
@@ -2285,17 +2273,16 @@ generic_make_request_checks(struct bio *bio)
22852273
if (should_fail_bio(bio))
22862274
goto end_io;
22872275

2288-
if (!bio->bi_partno) {
2289-
if (unlikely(bio_check_ro(bio, &bio->bi_disk->part0)))
2276+
if (bio->bi_partno) {
2277+
if (unlikely(blk_partition_remap(bio)))
22902278
goto end_io;
22912279
} else {
2292-
if (blk_partition_remap(bio))
2280+
if (unlikely(bio_check_ro(bio, &bio->bi_disk->part0)))
2281+
goto end_io;
2282+
if (unlikely(bio_check_eod(bio, get_capacity(bio->bi_disk))))
22932283
goto end_io;
22942284
}
22952285

2296-
if (bio_check_eod(bio, nr_sectors))
2297-
goto end_io;
2298-
22992286
/*
23002287
* Filter flush bio's early so that make_request based
23012288
* drivers without flush support don't have to worry

0 commit comments

Comments
 (0)