vi->data_avail is decremented on each read, so it holds the remaining
bytes rather than the total length. Subtracting vi->data_idx from it
again in commit e3046eeada29 ("hwrng: virtio: clamp device-reported
used.len at copy_data()") undercounts the bytes left after a partial
read. This can leave vi->data_avail nonzero without queuing a new
request, causing virtio_read() to hang on have_data.

Clamp vi->data_avail to sizeof(vi->data) - vi->data_idx instead.

Fixes: e3046eeada29 ("hwrng: virtio: clamp device-reported used.len at 
copy_data()")
Tested-by: Wei Liu <[email protected]>
Cc: [email protected]
Signed-off-by: Xiang Lei <[email protected]>
---
 drivers/char/hw_random/virtio-rng.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/char/hw_random/virtio-rng.c 
b/drivers/char/hw_random/virtio-rng.c
index f9982217247d..a3392f7e2d8c 100644
--- a/drivers/char/hw_random/virtio-rng.c
+++ b/drivers/char/hw_random/virtio-rng.c
@@ -70,7 +70,7 @@ static void request_entropy(struct virtrng_info *vi)
 static unsigned int copy_data(struct virtrng_info *vi, void *buf,
                              unsigned int size)
 {
-       unsigned int idx, avail;
+       unsigned int idx;
 
        /*
         * vi->data_avail was set from the device-reported used.len and
@@ -81,13 +81,13 @@ static unsigned int copy_data(struct virtrng_info *vi, void 
*buf,
         * steered into adjacent slab memory, including under
         * speculation.
         */
-       avail = min(vi->data_avail, sizeof(vi->data));
-       if (vi->data_idx >= avail) {
+       if (vi->data_idx >= sizeof(vi->data)) {
                vi->data_avail = 0;
                request_entropy(vi);
                return 0;
        }
-       size = min(size, avail - vi->data_idx);
+       vi->data_avail = min(vi->data_avail, sizeof(vi->data) - vi->data_idx);
+       size = min(size, vi->data_avail);
        idx = array_index_nospec(vi->data_idx, sizeof(vi->data));
        memcpy(buf, vi->data + idx, size);
        vi->data_idx += size;
-- 
2.53.0


Reply via email to