* [PATCH] zram: unsafe zram_get_element call in zram_read_page()
@ 2023-11-06 19:54 Vasily Averin
2023-11-07 7:39 ` Sergey Senozhatsky
0 siblings, 1 reply; 5+ messages in thread
From: Vasily Averin @ 2023-11-06 19:54 UTC (permalink / raw)
To: Sergey Senozhatsky, Minchan Kim; +Cc: linux-kernel, linux-block, zhouxianrong
Taken lock is required to access the content of zram entry.
Fixes: 8e19d540d107 ("zram: extend zero pages to same element pages")
Signed-off-by: Vasily Averin <vasily.averin@linux.dev>
---
drivers/block/zram/zram_drv.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index d77d3664ca08..9ac3d4e51d26 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -1362,14 +1362,14 @@ static int zram_read_page(struct zram *zram, struct page *page, u32 index,
ret = zram_read_from_zspool(zram, page, index);
zram_slot_unlock(zram, index);
} else {
+ unsigned long entry = zram_get_element(zram, index);
/*
* The slot should be unlocked before reading from the backing
* device.
*/
zram_slot_unlock(zram, index);
- ret = read_from_bdev(zram, page, zram_get_element(zram, index),
- parent);
+ ret = read_from_bdev(zram, page, entry, parent);
}
/* Should NEVER happen. Return bio error if it does. */
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH] zram: unsafe zram_get_element call in zram_read_page() 2023-11-06 19:54 [PATCH] zram: unsafe zram_get_element call in zram_read_page() Vasily Averin @ 2023-11-07 7:39 ` Sergey Senozhatsky 2023-11-07 10:40 ` Sergey Senozhatsky 0 siblings, 1 reply; 5+ messages in thread From: Sergey Senozhatsky @ 2023-11-07 7:39 UTC (permalink / raw) To: Minchan Kim Cc: Sergey Senozhatsky, linux-kernel, linux-block, zhouxianrong, Vasily Averin On (23/11/06 22:54), Vasily Averin wrote: > @@ -1362,14 +1362,14 @@ static int zram_read_page(struct zram *zram, struct page *page, u32 index, > ret = zram_read_from_zspool(zram, page, index); > zram_slot_unlock(zram, index); > } else { > + unsigned long entry = zram_get_element(zram, index); > /* > * The slot should be unlocked before reading from the backing > * device. > */ > zram_slot_unlock(zram, index); > > - ret = read_from_bdev(zram, page, zram_get_element(zram, index), > - parent); > + ret = read_from_bdev(zram, page, entry, parent); Hmmm, We may want to do more here. Basically, we probably need to re-confirm after read_from_bdev() that the entry at index still has ZRAM_WB set and, if so, that it points to the same blk_idx. IOW, check that it has not been free-ed and re-used under us. Minchan, what do you think? Is that scenario possible? ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] zram: unsafe zram_get_element call in zram_read_page() 2023-11-07 7:39 ` Sergey Senozhatsky @ 2023-11-07 10:40 ` Sergey Senozhatsky 2023-11-07 18:19 ` Vasily Averin 0 siblings, 1 reply; 5+ messages in thread From: Sergey Senozhatsky @ 2023-11-07 10:40 UTC (permalink / raw) To: Minchan Kim; +Cc: linux-kernel, linux-block, Vasily Averin, Sergey Senozhatsky On (23/11/07 16:39), Sergey Senozhatsky wrote: > On (23/11/06 22:54), Vasily Averin wrote: > > @@ -1362,14 +1362,14 @@ static int zram_read_page(struct zram *zram, struct page *page, u32 index, > > ret = zram_read_from_zspool(zram, page, index); > > zram_slot_unlock(zram, index); > > } else { > > + unsigned long entry = zram_get_element(zram, index); > > /* > > * The slot should be unlocked before reading from the backing > > * device. > > */ > > zram_slot_unlock(zram, index); > > > > - ret = read_from_bdev(zram, page, zram_get_element(zram, index), > > - parent); > > + ret = read_from_bdev(zram, page, entry, parent); > > Hmmm, > We may want to do more here. Basically, we probably need to re-confirm > after read_from_bdev() that the entry at index still has ZRAM_WB set > and, if so, that it points to the same blk_idx. IOW, check that it has > not been free-ed and re-used under us. > > Minchan, what do you think? Is that scenario possible? Basically --- diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index f5e3756fc21a..2d69f6efcee3 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -1364,14 +1364,21 @@ static int zram_read_page(struct zram *zram, struct page *page, u32 index, ret = zram_read_from_zspool(zram, page, index); zram_slot_unlock(zram, index); } else { + unsigned long idx = zram_get_element(zram, index); /* * The slot should be unlocked before reading from the backing * device. */ zram_slot_unlock(zram, index); - ret = read_from_bdev(zram, page, zram_get_element(zram, index), - parent); + ret = read_from_bdev(zram, page, idx, parent); + if (ret == 0) { + zram_slot_lock(zram, index); + if (!zram_test_flag(zram, index, ZRAM_WB) || + idx != zram_get_element(zram, index)) + ret = -EINVAL; + zram_slot_unlock(zram, index); + } } /* Should NEVER happen. Return bio error if it does. */ ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] zram: unsafe zram_get_element call in zram_read_page() 2023-11-07 10:40 ` Sergey Senozhatsky @ 2023-11-07 18:19 ` Vasily Averin 2023-11-08 1:42 ` Sergey Senozhatsky 0 siblings, 1 reply; 5+ messages in thread From: Vasily Averin @ 2023-11-07 18:19 UTC (permalink / raw) To: Sergey Senozhatsky, Minchan Kim; +Cc: linux-kernel, linux-block On 11/7/23 13:40, Sergey Senozhatsky wrote: > On (23/11/07 16:39), Sergey Senozhatsky wrote: >> Hmmm, >> We may want to do more here. Basically, we probably need to re-confirm >> after read_from_bdev() that the entry at index still has ZRAM_WB set >> and, if so, that it points to the same blk_idx. IOW, check that it has >> not been free-ed and re-used under us. > --- a/drivers/block/zram/zram_drv.c > +++ b/drivers/block/zram/zram_drv.c > @@ -1364,14 +1364,21 @@ static int zram_read_page(struct zram *zram, struct page *page, u32 index, > ret = zram_read_from_zspool(zram, page, index); > zram_slot_unlock(zram, index); > } else { > + unsigned long idx = zram_get_element(zram, index); > /* > * The slot should be unlocked before reading from the backing > * device. > */ > zram_slot_unlock(zram, index); > > - ret = read_from_bdev(zram, page, zram_get_element(zram, index), > - parent); > + ret = read_from_bdev(zram, page, idx, parent); > + if (ret == 0) { > + zram_slot_lock(zram, index); > + if (!zram_test_flag(zram, index, ZRAM_WB) || > + idx != zram_get_element(zram, index)) > + ret = -EINVAL; > + zram_slot_unlock(zram, index); > + } Why overwritten page can not be pushed to WB to the same blk_idx? However I'm agree that this is VERY unlikely case, and this check is better than nothing. ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] zram: unsafe zram_get_element call in zram_read_page() 2023-11-07 18:19 ` Vasily Averin @ 2023-11-08 1:42 ` Sergey Senozhatsky 0 siblings, 0 replies; 5+ messages in thread From: Sergey Senozhatsky @ 2023-11-08 1:42 UTC (permalink / raw) To: Vasily Averin; +Cc: Sergey Senozhatsky, Minchan Kim, linux-kernel, linux-block On (23/11/07 21:19), Vasily Averin wrote: > On 11/7/23 13:40, Sergey Senozhatsky wrote: > > On (23/11/07 16:39), Sergey Senozhatsky wrote: > >> Hmmm, > >> We may want to do more here. Basically, we probably need to re-confirm > >> after read_from_bdev() that the entry at index still has ZRAM_WB set > >> and, if so, that it points to the same blk_idx. IOW, check that it has > >> not been free-ed and re-used under us. > > --- a/drivers/block/zram/zram_drv.c > > +++ b/drivers/block/zram/zram_drv.c > > @@ -1364,14 +1364,21 @@ static int zram_read_page(struct zram *zram, struct page *page, u32 index, > > ret = zram_read_from_zspool(zram, page, index); > > zram_slot_unlock(zram, index); > > } else { > > + unsigned long idx = zram_get_element(zram, index); > > /* > > * The slot should be unlocked before reading from the backing > > * device. > > */ > > zram_slot_unlock(zram, index); > > > > - ret = read_from_bdev(zram, page, zram_get_element(zram, index), > > - parent); > > + ret = read_from_bdev(zram, page, idx, parent); > > + if (ret == 0) { > > + zram_slot_lock(zram, index); > > + if (!zram_test_flag(zram, index, ZRAM_WB) || > > + idx != zram_get_element(zram, index)) > > + ret = -EINVAL; > > + zram_slot_unlock(zram, index); > > + } > > Why overwritten page can not be pushed to WB to the same blk_idx? Yeah, so I thought about it too but didn't want to go too deep into it. We probably can only address it if we synchronize free_page (?), read_page() and writeback(), so that we never have concurrent bitmap modifications when one of the operations is in progress. ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2023-11-08 1:42 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2023-11-06 19:54 [PATCH] zram: unsafe zram_get_element call in zram_read_page() Vasily Averin 2023-11-07 7:39 ` Sergey Senozhatsky 2023-11-07 10:40 ` Sergey Senozhatsky 2023-11-07 18:19 ` Vasily Averin 2023-11-08 1:42 ` Sergey Senozhatsky
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox