[PATCH] backends/rng: cap request size to avoid oversized allocation

Laurent Vivier posted 1 patch 1 week, 3 days ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20260715141300.2295392-1-lvivier@redhat.com
Maintainers: Laurent Vivier <lvivier@redhat.com>, Amit Shah <amit@kernel.org>
backends/rng.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
[PATCH] backends/rng: cap request size to avoid oversized allocation
Posted by Laurent Vivier 1 week, 3 days ago
rng_backend_request_entropy() uses the requested size to allocate
a buffer with g_malloc(). With virtio-rng, this size comes from
guest-supplied descriptor lengths. A malicious guest can set a very
large descriptor length, causing QEMU to attempt a multi-gigabyte
allocation and abort.

Cap the allocation to 64 KiB. The virtio-rng queue size is
hardcoded to 8 entries, the EGD backend protocol limits requests
to 255 bytes, the Linux kernel hwrng framework requests at most
SMP_CACHE_BYTES per call (64 bytes on x86_64), and the Windows
viorng driver uses a 4 KiB buffer. The worst legitimate case is
8 x 4 KiB = 32 KiB, so 64 KiB is well above any legitimate use.

Fixes: 14417039653d ("virtio-rng: use virtqueue_get_avail_bytes, fix migration")
Cc: qemu-stable@nongnu.org
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3983
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
---
 backends/rng.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/backends/rng.c b/backends/rng.c
index ab94dfea850a..d8904f89dc43 100644
--- a/backends/rng.c
+++ b/backends/rng.c
@@ -11,11 +11,14 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/units.h"
 #include "system/rng.h"
 #include "qapi/error.h"
 #include "qemu/module.h"
 #include "qom/object_interfaces.h"
 
+#define RNG_MAX_REQUEST_SIZE (64 * KiB)
+
 void rng_backend_request_entropy(RngBackend *s, size_t size,
                                  EntropyReceiveFunc *receive_entropy,
                                  void *opaque)
@@ -27,7 +30,7 @@ void rng_backend_request_entropy(RngBackend *s, size_t size,
         req = g_malloc(sizeof(*req));
 
         req->offset = 0;
-        req->size = size;
+        req->size = MIN(size, RNG_MAX_REQUEST_SIZE);
         req->receive_entropy = receive_entropy;
         req->opaque = opaque;
         req->data = g_malloc(req->size);
-- 
2.54.0
Re: [PATCH] backends/rng: cap request size to avoid oversized allocation
Posted by Thomas Huth 5 days, 9 hours ago
On 15/07/2026 16.13, Laurent Vivier wrote:
> rng_backend_request_entropy() uses the requested size to allocate
> a buffer with g_malloc(). With virtio-rng, this size comes from
> guest-supplied descriptor lengths. A malicious guest can set a very
> large descriptor length, causing QEMU to attempt a multi-gigabyte
> allocation and abort.
> 
> Cap the allocation to 64 KiB. The virtio-rng queue size is
> hardcoded to 8 entries, the EGD backend protocol limits requests
> to 255 bytes, the Linux kernel hwrng framework requests at most
> SMP_CACHE_BYTES per call (64 bytes on x86_64), and the Windows
> viorng driver uses a 4 KiB buffer. The worst legitimate case is
> 8 x 4 KiB = 32 KiB, so 64 KiB is well above any legitimate use.
> 
> Fixes: 14417039653d ("virtio-rng: use virtqueue_get_avail_bytes, fix migration")
> Cc: qemu-stable@nongnu.org
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3983
> Signed-off-by: Laurent Vivier <lvivier@redhat.com>
> ---
>   backends/rng.c | 5 ++++-
>   1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/backends/rng.c b/backends/rng.c
> index ab94dfea850a..d8904f89dc43 100644
> --- a/backends/rng.c
> +++ b/backends/rng.c
> @@ -11,11 +11,14 @@
>    */
>   
>   #include "qemu/osdep.h"
> +#include "qemu/units.h"
>   #include "system/rng.h"
>   #include "qapi/error.h"
>   #include "qemu/module.h"
>   #include "qom/object_interfaces.h"
>   
> +#define RNG_MAX_REQUEST_SIZE (64 * KiB)
> +
>   void rng_backend_request_entropy(RngBackend *s, size_t size,
>                                    EntropyReceiveFunc *receive_entropy,
>                                    void *opaque)
> @@ -27,7 +30,7 @@ void rng_backend_request_entropy(RngBackend *s, size_t size,
>           req = g_malloc(sizeof(*req));
>   
>           req->offset = 0;
> -        req->size = size;
> +        req->size = MIN(size, RNG_MAX_REQUEST_SIZE);
>           req->receive_entropy = receive_entropy;
>           req->opaque = opaque;
>           req->data = g_malloc(req->size);

Reviewed-by: Thomas Huth <thuth@redhat.com>