zram: fix invalid memory access
authorMinchan Kim <minchan@kernel.org>
Mon, 12 Aug 2013 06:13:55 +0000 (15:13 +0900)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 12 Aug 2013 22:24:59 +0000 (15:24 -0700)
[1] tried to fix invalid memory access on zram->disk but it didn't
fix properly because get_disk failed during module exit path.

Actually, we don't need to reset zram->disk's capacity to zero
in module exit path so that this patch introduces new argument
"reset_capacity" on zram_reset_divice and it only reset it when
reset_store is called.

[1] 6030ea9b,  zram: avoid invalid memory access in zram_exit()

Cc: Nitin Gupta <ngupta@vflare.org>
Cc: Jiang Liu <jiang.liu@huawei.com>
Cc: stable@vger.kernel.org
Signed-off-by: Minchan Kim <minchan@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/zram/zram_drv.c

index 44949d2..2a85b95 100644 (file)
@@ -523,7 +523,7 @@ static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index,
        return ret;
 }
 
-static void zram_reset_device(struct zram *zram)
+static void zram_reset_device(struct zram *zram, bool reset_capacity)
 {
        size_t index;
        struct zram_meta *meta;
@@ -552,7 +552,8 @@ static void zram_reset_device(struct zram *zram)
        memset(&zram->stats, 0, sizeof(zram->stats));
 
        zram->disksize = 0;
-       set_capacity(zram->disk, 0);
+       if (reset_capacity)
+               set_capacity(zram->disk, 0);
        up_write(&zram->init_lock);
 }
 
@@ -636,7 +637,7 @@ static ssize_t reset_store(struct device *dev,
        if (bdev)
                fsync_bdev(bdev);
 
-       zram_reset_device(zram);
+       zram_reset_device(zram, true);
        return len;
 }
 
@@ -903,10 +904,12 @@ static void __exit zram_exit(void)
        for (i = 0; i < num_devices; i++) {
                zram = &zram_devices[i];
 
-               get_disk(zram->disk);
                destroy_device(zram);
-               zram_reset_device(zram);
-               put_disk(zram->disk);
+               /*
+                * Shouldn't access zram->disk after destroy_device
+                * because destroy_device already released zram->disk.
+                */
+               zram_reset_device(zram, false);
        }
 
        unregister_blkdev(zram_major, "zram");