diff mbox series

[RFC] rng-random: allow to use getrandom()

Message ID 20190509132234.22103-1-lvivier@redhat.com
State New
Headers show
Series [RFC] rng-random: allow to use getrandom() | expand

Commit Message

Laurent Vivier May 9, 2019, 1:22 p.m. UTC
Add a parameter to select the rng-random backend mode,
from a file or from qemu_guest_getrandom():

  -object rng-random,id=rng0,mode=file or
  -object rng-random,id=rng0,mode=getrandom

by default mode is file

This patch applies on top of
"[PATCH v4 00/24] Add qemu_getrandom and ARMv8.5-RNG etc"
Based-on: <20190506173353.32206-1-richard.henderson@linaro.org>
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
---
 backends/rng-random.c | 76 ++++++++++++++++++++++++++++++++++++-------
 qapi/ui.json          | 11 +++++++
 2 files changed, 76 insertions(+), 11 deletions(-)

Comments

Daniel P. Berrangé May 9, 2019, 1:29 p.m. UTC | #1
On Thu, May 09, 2019 at 03:22:34PM +0200, Laurent Vivier wrote:
> Add a parameter to select the rng-random backend mode,
> from a file or from qemu_guest_getrandom():
> 
>   -object rng-random,id=rng0,mode=file or
>   -object rng-random,id=rng0,mode=getrandom
> 
> by default mode is file

I don't really see any benefit in overloading the existing rng-random
object with a completely different impl. There are already two distinct
backends, so we should just add a third "rng-builtin" which uses the
QEMU built-in APIs for collecting rand data.

This makes it trivial to detect support for this feature by simply
looking for existance of the new object class.

Regards,
Daniel
diff mbox series

Patch

diff --git a/backends/rng-random.c b/backends/rng-random.c
index e2a49b0571d7..e95c71545ef9 100644
--- a/backends/rng-random.c
+++ b/backends/rng-random.c
@@ -14,13 +14,16 @@ 
 #include "sysemu/rng-random.h"
 #include "sysemu/rng.h"
 #include "qapi/error.h"
+#include "qapi/qapi-types-ui.h"
 #include "qapi/qmp/qerror.h"
 #include "qemu/main-loop.h"
+#include "qemu/guest-random.h"
 
 struct RngRandom
 {
     RngBackend parent;
 
+    RngRandomMode mode;
     int fd;
     char *filename;
 };
@@ -59,10 +62,27 @@  static void rng_random_request_entropy(RngBackend *b, RngRequest *req)
 {
     RngRandom *s = RNG_RANDOM(b);
 
-    if (QSIMPLEQ_EMPTY(&s->parent.requests)) {
-        /* If there are no pending requests yet, we need to
-         * install our fd handler. */
-        qemu_set_fd_handler(s->fd, entropy_available, NULL, s);
+    switch (s->mode) {
+    case RNG_RANDOM_MODE_FILE:
+        if (QSIMPLEQ_EMPTY(&s->parent.requests)) {
+            /* If there are no pending requests yet, we need to
+             * install our fd handler. */
+            qemu_set_fd_handler(s->fd, entropy_available, NULL, s);
+        }
+        break;
+    case RNG_RANDOM_MODE_GETRANDOM:
+        while (!QSIMPLEQ_EMPTY(&s->parent.requests)) {
+            RngRequest *req = QSIMPLEQ_FIRST(&s->parent.requests);
+
+            qemu_guest_getrandom_nofail(req->data, req->size);
+
+            req->receive_entropy(req->opaque, req->data, req->size);
+
+            rng_backend_finalize_request(&s->parent, req);
+        }
+        break;
+    default:
+        break;
     }
 }
 
@@ -70,17 +90,40 @@  static void rng_random_opened(RngBackend *b, Error **errp)
 {
     RngRandom *s = RNG_RANDOM(b);
 
-    if (s->filename == NULL) {
-        error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
-                   "filename", "a valid filename");
-    } else {
-        s->fd = qemu_open(s->filename, O_RDONLY | O_NONBLOCK);
-        if (s->fd == -1) {
-            error_setg_file_open(errp, errno, s->filename);
+    switch (s->mode) {
+    case RNG_RANDOM_MODE_FILE:
+        if (s->filename == NULL) {
+            error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
+                       "filename", "a valid filename");
+        } else {
+            s->fd = qemu_open(s->filename, O_RDONLY | O_NONBLOCK);
+            if (s->fd == -1) {
+                error_setg_file_open(errp, errno, s->filename);
+            }
         }
+        break;
+    case RNG_RANDOM_MODE_GETRANDOM:
+        break;
+    default:
+        break;
     }
 }
 
+static int rng_random_get_mode(Object *obj, Error **errp)
+{
+    RngRandom *s = RNG_RANDOM(obj);
+
+    return s->mode;
+}
+
+static void rng_random_set_mode(Object *obj, int value,
+                                       Error **errp)
+{
+    RngRandom *s = RNG_RANDOM(obj);
+
+    s->mode = value;
+}
+
 static char *rng_random_get_filename(Object *obj, Error **errp)
 {
     RngRandom *s = RNG_RANDOM(obj);
@@ -94,6 +137,11 @@  static void rng_random_set_filename(Object *obj, const char *filename,
     RngBackend *b = RNG_BACKEND(obj);
     RngRandom *s = RNG_RANDOM(obj);
 
+    if (s->mode != RNG_RANDOM_MODE_FILE) {
+        error_setg(errp, QERR_INVALID_PARAMETER, "filename");
+        return;
+    }
+
     if (b->opened) {
         error_setg(errp, QERR_PERMISSION_DENIED);
         return;
@@ -107,11 +155,17 @@  static void rng_random_init(Object *obj)
 {
     RngRandom *s = RNG_RANDOM(obj);
 
+    object_property_add_enum(obj, "mode", "RngRandomMode",
+                            &RngRandomMode_lookup,
+                            rng_random_get_mode,
+                            rng_random_set_mode,
+                            NULL);
     object_property_add_str(obj, "filename",
                             rng_random_get_filename,
                             rng_random_set_filename,
                             NULL);
 
+    s->mode = RNG_RANDOM_MODE_FILE;
     s->filename = g_strdup("/dev/random");
     s->fd = -1;
 }
diff --git a/qapi/ui.json b/qapi/ui.json
index 59e412139adc..25b33d79e9af 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -1170,3 +1170,14 @@ 
 ##
 { 'command': 'query-display-options',
   'returns': 'DisplayOptions' }
+
+##
+# @RngRandomMode:
+#
+# Value to select random number generation mode in rng-random backend
+#
+# Since: 4.1
+#
+##
+{ 'enum': 'RngRandomMode',
+  'data': [ 'file', 'getrandom' ] }