On Fri, 2023-11-10 at 16:54 +0100, Benjamin Beichler wrote:
> At the moment, we haven't patched the random device that fetches random 
> bytes from the host (do you already have a patch for this?),
> so complete repeatability isn't guaranteed at the moment. However, that 
> could be a logical next step.

Right, we have the attached kernel patches internally. This simply
disables some of the random sources and replaces os_getrandom with
returning static random from the UML_RANDOM environment variable.

I doubt that it makes sense to upstream these patches, but may we can
include them as patch files in USFSTL or so.

The second piece is using a mount namespace to ensure that the linux
command line is identical between runs and that the location of all
files that are accessed directly from the host through hostfs never
changes.

The last piece was setting GLIBC_TUNABLES=-AVX512CD in the environment
just in case the CPU feature set is slightly different. That would
cause ld.so to search for a different set of optimized library versions
(affecting syscalls and with that randomness).

Benjamin
From 0b51202872111f1a5f7a59435ff741ef0272d30f Mon Sep 17 00:00:00 2001
From: Benjamin Berg <benjamin.b...@intel.com>
Date: Thu, 16 Mar 2023 13:19:37 +0200
Subject: [PATCH 1/3] um: Use fixed random seed if UML_RANDOM is set

This helps with reproducable test runs.

Signed-off-by: Benjamin Berg <benjamin.b...@intel.com>
---
 arch/um/os-Linux/util.c | 36 ++++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index fc0f2a9dee5a..1e7b19272dfa 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -99,6 +99,42 @@ static inline void __attribute__ ((noreturn)) uml_abort(void)
 
 ssize_t os_getrandom(void *buf, size_t len, unsigned int flags)
 {
+	static char random_pattern[128];
+	static ssize_t random_pattern_len = -1;
+
+	/* This happens when called by setup_arch */
+	if (random_pattern_len == -1) {
+		const char *env;
+
+		env = getenv("UML_RANDOM");
+		if (env) {
+			random_pattern_len =
+				strlen(env) > sizeof(random_pattern) ?
+				sizeof(random_pattern) : strlen(env);
+			memcpy(random_pattern, env, random_pattern_len);
+		} else {
+			random_pattern_len = 0;
+		}
+	}
+
+	if (random_pattern_len > 0) {
+		size_t tail = len;
+		/*
+		 * If the returned length is too short, then the kernel might
+		 * loop trying to generate random from the passing of time.
+		 * Which seems to possibly infinite loop in time-travel mode.
+		 * So just repeat the given pattern.
+		 */
+		while (tail > random_pattern_len) {
+			memcpy(buf, random_pattern, random_pattern_len);
+			tail -= random_pattern_len;
+			buf += random_pattern_len;
+		}
+		memcpy(buf, random_pattern, tail);
+
+		return len;
+	}
+
 	return getrandom(buf, len, flags);
 }
 
-- 
2.41.0

From b8aa74aed9fa008b908682bfa085461635e876e0 Mon Sep 17 00:00:00 2001
From: Benjamin Berg <benjamin.b...@intel.com>
Date: Thu, 16 Mar 2023 13:21:19 +0200
Subject: [PATCH 2/3] random: disable interrupt random source

Interrupts in our UML environment are signals, which can be delivered at
somewhat random times depending on host scheduling. Disable these as a
source to make the random reproducible between runs.

Signed-off-by: Benjamin Berg <benjamin.b...@intel.com>
---
 drivers/char/random.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/char/random.c b/drivers/char/random.c
index 253f2ddb8913..db2c5a296c05 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1093,6 +1093,9 @@ void add_interrupt_randomness(int irq)
 	struct pt_regs *regs = get_irq_regs();
 	unsigned int new_count;
 
+	/* UML seems to not always get the signals entirely at the same time */
+	return;
+
 	fast_mix(fast_pool->pool, entropy,
 		 (regs ? instruction_pointer(regs) : _RET_IP_) ^ swab(irq));
 	new_count = ++fast_pool->count;
-- 
2.41.0

From c62e671073cfe990fd2200c81defae98b1e9258b Mon Sep 17 00:00:00 2001
From: Benjamin Berg <benjamin.b...@intel.com>
Date: Wed, 22 Mar 2023 17:56:37 +0100
Subject: [PATCH 3/3] random: do not include utsname in early random

The uts name includes information about the compile time and such and
changes. Exclude it, so that different kernel compilations will see
the same random numbers.

Signed-off-by: Benjamin Berg <benjamin.b...@intel.com>
---
 drivers/char/random.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/char/random.c b/drivers/char/random.c
index db2c5a296c05..dd4aa42a4404 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -865,7 +865,7 @@ void __init random_init_early(const char *command_line)
 		++i;
 	}
 
-	_mix_pool_bytes(init_utsname(), sizeof(*(init_utsname())));
+	/* _mix_pool_bytes(init_utsname(), sizeof(*(init_utsname()))); */
 	_mix_pool_bytes(command_line, strlen(command_line));
 
 	/* Reseed if already seeded by earlier phases. */
-- 
2.41.0

_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

Reply via email to