Subject: bug#23605: closed (Re: bug#23605: /dev/urandom not seeded across reboots)

From: [email-masked] (GNU bug Tracking System)
Date: Sun, 29 May 2016 00:05:02 +0000

Your bug report

#23605: /dev/urandom not seeded across reboots

which was filed against the guix package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
23605: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=23605
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Re: bug#23605: /dev/urandom not seeded across reboots
From: Leo Famulari <[email-masked]>
To: [email-masked]
Date: Sat, 28 May 2016 20:04:31 -0400
List-Id: <debbugs-submit.debbugs.gnu.org>

On Sat, May 28, 2016 at 08:00:58PM -0400, Leo Famulari wrote:
> On Sat, May 28, 2016 at 10:53:08PM +0200, Ludovic Courtès wrote:
> > 
> > OK with these changes.
> 
> Done as a535e12226!

Subject: /dev/urandom not seeded across reboots
From: Leo Famulari <[email-masked]>
To: [email-masked]
Date: Mon, 23 May 2016 13:58:32 -0400
List-Id: <debbugs-submit.debbugs.gnu.org>

I realized that we don't seem to be saving any of the entropy in the
kernel's random pool [0] across reboots.

This means that for some period after boot, /dev/urandom may not be safe
to use. From random(4):

---
If  a seed file is saved across reboots as recommended below (all major
Linux distributions have done this since 2000 at least),
[/dev/urandom's] output is cryptographically  secure against  attackers
without  local  root access as soon as it is reloaded in the boot
sequence, and perfectly adequate for network encryption session  keys.
---

I interpret that text to mean that, without use of a seed file,
urandom's output is *not* adequate for network encryption session keys
(SSH, TLS, etc) until enough entropy has been gathered. I don't know how
long that takes.

I've attached my not-yet-working attempt at a urandom-seed-service. I
tried to get it working on my own but I need the assistance of some more
experienced Guix hackers :)

I've also attached a stand-alone Guile script to illustrate what the
effect of the service should be. This script does seem to work. I'm sure
the use of shell tools could be replaced by Guile.

After applying my patch and attempting `guix system vm ...`, I get the
attached backtrace.

Does anyone have advice about the service? Am I wrong that we need to
seed /dev/urandom to make it work properly?

[0] See the man page for random(4).
diff --git a/gnu/services/base.scm b/gnu/services/base.scm
index 96bf8da..4a85ed0 100644
--- a/gnu/services/base.scm
+++ b/gnu/services/base.scm
@@ -32,7 +32,7 @@
   #:use-module ((gnu packages linux)
                 #:select (eudev kbd e2fsprogs lvm2 fuse alsa-utils crda gpm))
   #:use-module ((gnu packages base)
-                #:select (canonical-package glibc))
+                #:select (canonical-package glibc coreutils)) ; coreutils for `dd`, `cat`.
   #:use-module (gnu packages package-management)
   #:use-module (gnu packages lsh)
   #:use-module (gnu packages lsof)
@@ -93,6 +93,8 @@
             gpm-service-type
             gpm-service
 
+            urandom-seed-service
+
             %base-services))
 
 ;;; Commentary:
@@ -1200,6 +1202,47 @@ extra rules from the packages listed in @var{rules}."
   "Return a service that uses @var{device} as a swap device."
   (service swap-service-type device))
 
+(define %urandom-seed-activation
+  ;; Activation gexp for the urandom seed
+  #~(begin
+      (use-modules (guix build utils))
+
+      (mkdir-p "/var/run")
+      (close-port (open-file "/var/run/urandom-seed" "a0b"))
+      (chmod "/var/run/urandom-seed" #o600)))
+
+(define (urandom-seed-shepherd-service)
+  "Return a shepherd service for the /dev/urandom seed."
+  (list (shepherd-service
+         (documentation "Preserve entropy across reboots for /dev/urandom.")
+         (provision '(urandom-seed))
+         (requirement '(user-processes)) ; whatever provides file-system /var
+         (start #~(lambda _
+                    (exec-command
+                      (zero?
+                        (system (string-append "cat "
+                                               "/var/run/urandom-seed"
+                                               " > /dev/urandom"))))))
+         (stop #~(lambda _
+                   (exec-command
+                     (zero?
+                       (system* "dd" "if=/dev/urandom"
+                                (string-append "of=" "/var/run/urandom-seed")
+                                "count=1" "bs=512"))))))))
+
+(define urandom-seed-service-type
+  (service-type (name 'urandom-seed)
+                (extensions
+                 (list (service-extension shepherd-root-service-type
+                                          urandom-seed-shepherd-service)
+                       (service-extension activation-service-type
+                                          (const %urandom-seed-activation))
+                       ;; Add urandom-seed to the system profile
+                       ;; Where is profile-service-type defined?
+                       (service-extension profile-service-type list)))))
+
+(define (urandom-seed-service)
+  (service urandom-seed-service-type '()))
 
 (define-record-type* <gpm-configuration>
   gpm-configuration make-gpm-configuration gpm-configuration?
@@ -1281,6 +1324,7 @@ This is the GNU operating system, welcome!\n\n")))
           (static-networking-service "lo" "127.0.0.1"
                                      #:provision '(loopback))
           (syslog-service)
+          (urandom-seed-service)
           (guix-service)
           (nscd-service)