commit 55966ebc12eb233ad93cf1ff580a82945247ff74
parent 9dfe7c4c5de9c88f0c2c77bf3230f5b5804238eb
Author: Jared Tobin <jared@jtobin.io>
Date: Mon, 19 Oct 2026 14:06:08 +0400
qemu: getrandom keeps the kernel's flags and length
The patch answered a guest's getrandom from the seeded generator
alone, ignoring its flags and always returning the length asked for:
a call the kernel refuses (an invalid flag, EINVAL) succeeded, which
could change the path a harness takes. The host now answers the call
as before, checking its flags and choosing its length and errors, and
only the bytes it returned are drawn from the seeded generator.
Diffstat:
2 files changed, 17 insertions(+), 13 deletions(-)
diff --git a/README.md b/README.md
@@ -129,7 +129,8 @@ runs. `record` turns address-space randomisation off for itself and
QEMU, refusing to run where it cannot, and seeds the guest's
entropy, so runs lay memory out alike and a hash table seeded from
the system's randomness is laid out alike too. The pinned QEMU
-answers the guest's `getrandom` from that seeded generator
+fills the guest's `getrandom` from that seeded generator, the host
+still checking its flags and choosing its length
(`nix/qemu-getrandom.patch`); a guest reading `/dev/urandom` still
reads the host's. `--control DUMP` names a run repeating the first run's
secret: whatever differs between the two (a clock read, a
diff --git a/nix/qemu-getrandom.patch b/nix/qemu-getrandom.patch
@@ -1,22 +1,25 @@
QEMU's user mode answers a guest's getrandom from the host, which
-seed does not reach: two runs of one program draw different entropy,
-and every instruction computing on it differs between them. Draw it
-from the guest generator instead, which -seed makes deterministic and
-which, unseeded, draws from the host as before.
+and every instruction computing on it differs between them. The host
+still answers the call, so its flags are checked and its length and
+errors chosen as the kernel would; the bytes it returned are then
+drawn from the guest generator, which -seed makes deterministic and
+which, unseeded, draws from the host.
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
-@@ -10898,7 +10898,12 @@
- if (!p) {
+@@ -10899,6 +10899,14 @@
return -TARGET_EFAULT;
}
-- ret = get_errno(getrandom(p, arg2, arg3));
-+ /*
-+ * The guest's entropy, from the generator -seed makes
-+ * deterministic; unseeded, it draws from the host as before.
-+ */
-+ qemu_guest_getrandom_nofail(p, arg2);
-+ ret = arg2;
+ ret = get_errno(getrandom(p, arg2, arg3));
++ if (ret > 0) {
++ /*
++ * The host checked the flags and chose the length; the
++ * bytes come from the guest generator, which -seed makes
++ * deterministic.
++ */
++ qemu_guest_getrandom_nofail(p, ret);
++ }
unlock_user(p, arg1, ret);
return ret;
#endif