Messages in this thread Patch in this message | | | Date | Wed, 5 Jun 2013 18:20:35 -0700 | From | Tejun Heo <> | Subject | [PATCH] block: don't call kobj_map() with 0 @range |
| |
When fully dynamic devt allocation is used, gendisk->minors is zero. In such cases, add_disk() calls blk_register_region() with 0 @range expecting it to do nothing; however, blk_register_region() is a thin wrapper around kobj_map(), which doesn't expect 0 @range input and goes through an underflow while calculating the number of mapping entries to allocate. Fortunately, it has limit check built-in and this doesn't lead to anything disastrous - it just wastes 255 * sizeof(struct probe) bytes.
When gendisk->minors is zero, the kobj_map isn't used at all and both blk_[un]register_region() are expected to be noops. Add conditionals to blk_[un]register_region() so that nothing happens when @range is zero.
Signed-off-by: Tejun Heo <tj@kernel.org> Reported-by: PaX Team <pageexec@freemail.hu> Cc: stable@vger.kernel.org --- block/genhd.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/block/genhd.c b/block/genhd.c index 20625ee..3a4a1ed 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -467,21 +467,24 @@ static char *bdevt_str(dev_t devt, char *buf) /* * Register device numbers dev..(dev+range-1) - * range must be nonzero + * Noop if @range is zero. * The hash chain is sorted on range, so that subranges can override. */ void blk_register_region(dev_t devt, unsigned long range, struct module *module, struct kobject *(*probe)(dev_t, int *, void *), int (*lock)(dev_t, void *), void *data) { - kobj_map(bdev_map, devt, range, module, probe, lock, data); + if (range) + kobj_map(bdev_map, devt, range, module, probe, lock, data); } EXPORT_SYMBOL(blk_register_region); +/* undo blk_register_region(), noop if @range is zero */ void blk_unregister_region(dev_t devt, unsigned long range) { - kobj_unmap(bdev_map, devt, range); + if (range) + kobj_unmap(bdev_map, devt, range); } EXPORT_SYMBOL(blk_unregister_region);
| |