bug-guix
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#37501: [core-updates] Entropy starvation during boot


From: Ludovic Courtès
Subject: bug#37501: [core-updates] Entropy starvation during boot
Date: Thu, 03 Oct 2019 00:29:59 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/26.3 (gnu/linux)

Hi again,

Marius Bakke <address@hidden> skribis:

> After reconfiguring on the 'core-updates' branch, systems using the
> OpenSSH service will occasionally (not always!) hang forever during
> boot, waiting for entropy.  Moving the mouse or mashing the keyboard
> allows the boot to proceed.
>
> I don't think this is limited to OpenSSH, but anything that calls
> getrandom() during startup.
>
> There is some information about this problem and various workarounds
> here, including links to recent LKML discussions:
>
> https://daniel-lange.com/archives/152-hello-buster.html

I read some of these, and our ‘urandom-seed-service-type’ has the same
bug as <https://github.com/systemd/systemd/issues/4271>.  Namely, we
write the previous seed to /dev/urandom but we don’t credit the
entropy.

The attached patch fixes that, and I think it should fix the problem you
reported.  Could people give it a try?

I’m interested in seeing the value of
/proc/sys/kernel/random/entropy_avail with and without this patch right
after boot (don’t try it in ‘guix system vm’ because there’s no seed
there.)

I wasn’t sure how much to add to the entropy count, but I think it’s
safe to account for all the bits of the seed since we know that it comes
from /dev/urandom.

Thoughts?

Ludo’.

diff --git a/gnu/services/base.scm b/gnu/services/base.scm
index 25716ef152..3fe5cb3329 100644
--- a/gnu/services/base.scm
+++ b/gnu/services/base.scm
@@ -573,7 +573,13 @@ file systems, as well as corresponding @file{/etc/fstab} 
entries.")))
                         (lambda (seed)
                           (call-with-output-file "/dev/urandom"
                             (lambda (urandom)
-                              (dump-port seed urandom))))))
+                              (dump-port seed urandom)
+
+                              ;; Writing SEED to URANDOM isn't enough: we must
+                              ;; also tell the kernel to account for these
+                              ;; extra bits of entropy.
+                              (let ((bits (* 8 (stat:size (stat seed)))))
+                                (add-to-entropy-count urandom bits)))))))
 
                     ;; Try writing from /dev/hwrng into /dev/urandom.
                     ;; It seems that the file /dev/hwrng always exists, even
diff --git a/guix/build/syscalls.scm b/guix/build/syscalls.scm
index f2fdb4d9d1..bbf2531c79 100644
--- a/guix/build/syscalls.scm
+++ b/guix/build/syscalls.scm
@@ -68,6 +68,7 @@
             statfs
             free-disk-space
             device-in-use?
+            add-to-entropy-count
 
             processes
             mkdtemp!
@@ -706,6 +707,33 @@ backend device."
              (list (strerror err))
              (list err))))))
 
+
+;;;
+;;; Random.
+;;;
+
+;; From <uapi/linux/random.h>.
+(define RNDADDTOENTCNT #x40045201)
+
+(define (add-to-entropy-count port-or-fd n)
+  "Add N to the kernel's entropy count (the value that can be read from
+/proc/sys/kernel/random/entropy_avail).  PORT-OR-FD must correspond to
+/dev/urandom or /dev/random.  Raise to 'system-error with EPERM when the
+caller lacks root privileges."
+  (let ((fd  (if (port? port-or-fd)
+                 (fileno port-or-fd)
+                 port-or-fd))
+        (box (make-bytevector (sizeof int))))
+    (bytevector-sint-set! box 0 n (native-endianness)
+                          (sizeof int))
+    (let-values (((ret err)
+                  (%ioctl fd RNDADDTOENTCNT
+                          (bytevector->pointer box))))
+      (unless (zero? err)
+        (throw 'system-error "add-to-entropy-count" "~A"
+               (list (strerror err))
+               (list err))))))
+
 
 ;;;
 ;;; Containers.
diff --git a/tests/syscalls.scm b/tests/syscalls.scm
index eeb223b950..1b3121e503 100644
--- a/tests/syscalls.scm
+++ b/tests/syscalls.scm
@@ -567,6 +567,19 @@
   (let ((result (call-with-input-file "/var/run/utmpx" read-utmpx)))
     (or (utmpx? result) (eof-object? result))))
 
+(when (zero? (getuid))
+  (test-skip 1))
+(test-equal "add-to-entropy-count"
+  EPERM
+  (call-with-output-file "/dev/urandom"
+    (lambda (port)
+      (catch 'system-error
+        (lambda ()
+          (add-to-entropy-count port 77)
+          #f)
+        (lambda args
+          (system-error-errno args))))))
+
 (test-end)
 
 (false-if-exception (delete-file temp-file))

reply via email to

[Prev in Thread] Current Thread [Next in Thread]