From: Andre Przywara <andre.przywara@arm.com>
To: Will Deacon <will@kernel.org>,
Julien Thierry <julien.thierry.kdev@gmail.com>
Cc: kvm@vger.kernel.org, Alexandru Elisei <alexandru.elisei@arm.com>,
Sami Mujawar <sami.mujawar@arm.com>
Subject: [RFC PATCH kvmtool 2/2] virtio/rng: return at least one byte of entropy
Date: Thu, 13 Apr 2023 17:57:57 +0100 [thread overview]
Message-ID: <20230413165757.1728800-3-andre.przywara@arm.com> (raw)
In-Reply-To: <20230413165757.1728800-1-andre.przywara@arm.com>
In contrast to the original v0.9 virtio spec (which was rather vague),
the virtio 1.0+ spec demands that a RNG request returns at least one
byte:
"The device MUST place one or more random bytes into the buffer, but it
MAY use less than the entire buffer length."
Our current implementation does not prevent returning zero bytes, which
upsets an assert in EDK II. Since we open the fd with O_NONBLOCK, a
return with not the whole buffer filled seems possible.
Take care of that special case, by switching the /dev/urandom file
descriptor into blocking mode when a 0-return happens, than wait for one
byte to arrive. We then switch back to non-blocking mode, and try to
read even more (in case multiple bytes became available at once).
This makes sure we return at least one byte of entropy and become spec
compliant.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reported-by: Sami Mujawar <sami.mujawar@arm.com>
---
virtio/rng.c | 31 +++++++++++++++++++++++++++++--
1 file changed, 29 insertions(+), 2 deletions(-)
diff --git a/virtio/rng.c b/virtio/rng.c
index eab8f3ac0..0a0b31a16 100644
--- a/virtio/rng.c
+++ b/virtio/rng.c
@@ -66,8 +66,35 @@ static bool virtio_rng_do_io_request(struct kvm *kvm, struct rng_dev *rdev, stru
head = virt_queue__get_iov(queue, iov, &out, &in, kvm);
len = readv(rdev->fd, iov, in);
- if (len < 0 && errno == EAGAIN)
- len = 0;
+ if (len < 0 && errno == EAGAIN) {
+ /*
+ * The virtio 1.0 spec demands at least one byte of entropy.
+ * Switch the /dev/urandom file descriptor to blocking mode,
+ * then wait for one byte to arrive. Switch it back to
+ * non-blocking mode, and try to read even more, if available.
+ */
+ int flags = fcntl(rdev->fd, F_GETFL);
+
+ if (flags < 0)
+ return false;
+
+ fcntl(rdev->fd, F_SETFL, flags & ~O_NONBLOCK);
+ len = read(rdev->fd, iov[0].iov_base, 1);
+ if (len < 1)
+ return false;
+ fcntl(rdev->fd, F_SETFL, flags);
+ iov[0].iov_base++;
+ iov[0].iov_len--;
+ len = readv(rdev->fd, iov, in);
+ if (len < 0) {
+ if (errno == EAGAIN) /* no more bytes yet */
+ len = 1;
+ else
+ return false; /* some error */
+ } else {
+ len++; /* the one byte already read */
+ }
+ }
virt_queue__set_used_elem(queue, head, len);
--
2.25.1
next prev parent reply other threads:[~2023-04-13 16:58 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-04-13 16:57 [PATCH kvmtool 0/2] Fix virtio/rng handling in low entropy situations Andre Przywara
2023-04-13 16:57 ` [PATCH kvmtool 1/2] virtio/rng: switch to using /dev/urandom Andre Przywara
2023-04-19 13:53 ` Jean-Philippe Brucker
2023-04-13 16:57 ` Andre Przywara [this message]
2023-04-19 13:58 ` [PATCH kvmtool 0/2] Fix virtio/rng handling in low entropy situations Jean-Philippe Brucker
2023-04-19 15:10 ` Jean-Philippe Brucker
2023-04-19 15:31 ` Andre Przywara
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230413165757.1728800-3-andre.przywara@arm.com \
--to=andre.przywara@arm.com \
--cc=alexandru.elisei@arm.com \
--cc=julien.thierry.kdev@gmail.com \
--cc=kvm@vger.kernel.org \
--cc=sami.mujawar@arm.com \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox