diff options
| author | Ming Lei <ming.lei@canonical.com> | 2016-03-29 20:46:31 -0400 |
|---|---|---|
| committer | Jens Axboe <axboe@fb.com> | 2016-03-29 21:18:14 -0400 |
| commit | b30a337ca27c4f40439e4bfb290cba5f88d73bb7 (patch) | |
| tree | 07da263067ec36686177990a48000beb0ceb2eae | |
| parent | 1993b176a8224e371e0732ffada7ab9eb3b0912b (diff) | |
block: partition: initialize percpuref before sending out KOBJ_ADD
The initialization of partition's percpu_ref should have been done before
sending out KOBJ_ADD uevent, which may cause userspace to read partition
table. So the uninitialized percpu_ref may be accessed in data path.
This patch fixes this issue reported by Naveen.
Reported-by: Naveen Kaje <nkaje@codeaurora.org>
Tested-by: Naveen Kaje <nkaje@codeaurora.org>
Fixes: 6c71013ecb7e2(block: partition: convert percpu ref)
Cc: <stable@vger.kernel.org> # v4.3+
Signed-off-by: Ming Lei <ming.lei@canonical.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
| -rw-r--r-- | block/partition-generic.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/block/partition-generic.c b/block/partition-generic.c index 5d8701941054..84c53f04777a 100644 --- a/block/partition-generic.c +++ b/block/partition-generic.c | |||
| @@ -361,15 +361,20 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno, | |||
| 361 | goto out_del; | 361 | goto out_del; |
| 362 | } | 362 | } |
| 363 | 363 | ||
| 364 | err = hd_ref_init(p); | ||
| 365 | if (err) { | ||
| 366 | if (flags & ADDPART_FLAG_WHOLEDISK) | ||
| 367 | goto out_remove_file; | ||
| 368 | goto out_del; | ||
| 369 | } | ||
| 370 | |||
| 364 | /* everything is up and running, commence */ | 371 | /* everything is up and running, commence */ |
| 365 | rcu_assign_pointer(ptbl->part[partno], p); | 372 | rcu_assign_pointer(ptbl->part[partno], p); |
| 366 | 373 | ||
| 367 | /* suppress uevent if the disk suppresses it */ | 374 | /* suppress uevent if the disk suppresses it */ |
| 368 | if (!dev_get_uevent_suppress(ddev)) | 375 | if (!dev_get_uevent_suppress(ddev)) |
| 369 | kobject_uevent(&pdev->kobj, KOBJ_ADD); | 376 | kobject_uevent(&pdev->kobj, KOBJ_ADD); |
| 370 | 377 | return p; | |
| 371 | if (!hd_ref_init(p)) | ||
| 372 | return p; | ||
| 373 | 378 | ||
| 374 | out_free_info: | 379 | out_free_info: |
| 375 | free_part_info(p); | 380 | free_part_info(p); |
| @@ -378,6 +383,8 @@ out_free_stats: | |||
| 378 | out_free: | 383 | out_free: |
| 379 | kfree(p); | 384 | kfree(p); |
| 380 | return ERR_PTR(err); | 385 | return ERR_PTR(err); |
| 386 | out_remove_file: | ||
| 387 | device_remove_file(pdev, &dev_attr_whole_disk); | ||
| 381 | out_del: | 388 | out_del: |
| 382 | kobject_put(p->holder_dir); | 389 | kobject_put(p->holder_dir); |
| 383 | device_del(pdev); | 390 | device_del(pdev); |
