Re: [PATCH] bdi: fix use-after-free for bdi device

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




__blkg_prfill_rwstat() tries to get the device name by
'bdi->dev', while the 'dev' has been freed by bdi_unregister().
Then, blkg_dev_name() will return an invalid name pointer,
resulting in crash on string(). The race as following:

CPU1                          CPU2
blkg_print_stat_bytes
                               __scsi_remove_device
                               del_gendisk
                                 bdi_unregister

                                 put_device(bdi->dev)
                                   kfree(bdi->dev)
__blkg_prfill_rwstat
   blkg_dev_name
     //use the freed bdi->dev
     dev_name(blkg->q->backing_dev_info->dev)
                                 bdi->dev = NULL


There is another simple way to fix the problem.

Since blkg_dev_name() have been coverd by rcu_read_lock/unlock(),
we can wait all rcu reader to finish before free 'bdi->dev' to avoid use-after-free.

But I am not sure if this solution will introduce new problems.


diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 62f05f605fb5..6f322473ca4d 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -1007,15 +1007,19 @@ static void bdi_remove_from_list(struct backing_dev_info *bdi)

 void bdi_unregister(struct backing_dev_info *bdi)
 {
+       struct device *dev = bdi->dev;
        /* make sure nobody finds us on the bdi_list anymore */
        bdi_remove_from_list(bdi);
        wb_shutdown(&bdi->wb);
        cgwb_bdi_unregister(bdi);

-       if (bdi->dev) {
+       if (dev) {
                bdi_debug_unregister(bdi);
-               device_unregister(bdi->dev);
                bdi->dev = NULL;
+               device_del(dev);
+               /* wait all rcu reader of bdi->dev before free dev */
+               synchronize_rcu();
+               put_device(dev);
        }

        if (bdi->owner) {



[Index of Archives]     [Linux RAID]     [Linux SCSI]     [Linux ATA RAID]     [IDE]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Device Mapper]

  Powered by Linux