Okay, I finally have some code that works! (attached)
I tested it by using `inotifywait -m /dev/urandom` [0] to see that
/dev/urandom was indeed being open and closed for writing when running
`herd {start, stop} urandom-seed`. If you can suggest a way to see
exactly what is being written to /dev/urandom, I would like to verify it
more fully.
If you test it, don't be surprised that the random-seed is empty the
first time you start the service. It is `touch`-ed at boot but filled
during shutdown.
The big caveat is that the only way I could make it work was to use the
old service API. I just couldn't figure out how to use the extensible
service API for a service that takes to arguments.
If this is a problem, then your help is wanted!
I also had to change the location of %random-seed-file from
/var/run/random-seed to /var/lib/random-seed, because /var/run is
cleared upon reboot. This is specified in the FHS standard [1]. Debian
puts it at /var/lib/urandom/random-seed.
[0] From the inotify-tools package
[1]
http://www.pathname.com/fhs/pub/fhs-2.3.html#VARRUNRUNTIMEVARIABLEDATA
>From 8d41d37e2d0f8a0edf7ab9d659d1a2c9315965c1 Mon Sep 17 00:00:00 2001
From: Leo Famulari <[email protected]>
Date: Sun, 8 May 2016 03:08:46 -0400
Subject: [PATCH] services: Add urandom-seed-service.
* gnu/services/base.scm (urandom-seed-service): New procedure.
(%random-seed-file, urandom-seed-service-type): New variables.
(%urandom-seed-shepherd-service): New procedure.
* doc/guix.texi (Base Services): Document it.
---
doc/guix.texi | 10 ++++++++++
gnu/services/base.scm | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 61 insertions(+), 1 deletion(-)
diff --git a/doc/guix.texi b/doc/guix.texi
index bb75425..34a51a8 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -7355,6 +7355,16 @@ Return a service that runs the Guix build daemon according to
Run @var{udev}, which populates the @file{/dev} directory dynamically.
@end deffn
+@deffn {Scheme Procedure} urandom-seed-service @var{#f}
+Save some entropy in @var{%random-seed-file} to seed @file{/dev/urandom}
+when rebooting.
+@end deffn
+
+@deftp {Data Type} %random-seed-file
+This is where some random bytes are saved by @var{urandom-seed-service}
+to seed @file{/dev/urandom} when rebooting.
+@end deftp
+
@deffn {Scheme Procedure} console-keymap-service @var{files} ...
@cindex keyboard layout
Return a service to load console keymaps from @var{files} using
diff --git a/gnu/services/base.scm b/gnu/services/base.scm
index 96bf8da..329a989 100644
--- a/gnu/services/base.scm
+++ b/gnu/services/base.scm
@@ -3,6 +3,7 @@
;;; Copyright © 2015, 2016 Alex Kost <[email protected]>
;;; Copyright © 2015 Mark H Weaver <[email protected]>
;;; Copyright © 2015 Sou Bunnbu <[email protected]>
+;;; Copyright © 2016 Leo Famulari <[email protected]>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -93,6 +94,8 @@
gpm-service-type
gpm-service
+ urandom-seed-service
+
%base-services))
;;; Commentary:
@@ -422,6 +425,53 @@ stopped before 'kill' is called."
;;;
+;;; Preserve entropy to seed /dev/urandom on boot.
+;;;
+
+(define %random-seed-file
+ "/var/lib/random-seed")
+
+(define %urandom-seed-shepherd-service
+ (shepherd-service
+ (documentation "Preserve entropy across reboots for /dev/urandom.")
+ (provision '(urandom-seed))
+ (requirement '(user-processes))
+ (start #~(lambda _
+ ;; "Activation"
+ (mkdir-p (dirname #$%random-seed-file))
+ (close-port (open-file #$%random-seed-file "a0b"))
+ (chmod #$%random-seed-file #o600)
+ ;; On boot, write random seed into /dev/urandom
+ (when (file-exists? #$%random-seed-file)
+ (call-with-input-file #$%random-seed-file
+ (lambda (seed)
+ (call-with-output-file "/dev/urandom"
+ (lambda (urandom)
+ (dump-port seed urandom))))))
+ #t))
+ (stop #~(lambda _
+ ;; During shutdown, write from /dev/urandom into random seed
+ (let ((buf (make-bytevector 512)))
+ (call-with-input-file "/dev/urandom"
+ (lambda (urandom)
+ (get-bytevector-n! urandom buf 0 512)
+ (call-with-output-file #$%random-seed-file
+ (lambda (seed)
+ (put-bytevector seed buf)))
+ #t)))))
+ (modules `((rnrs bytevectors)
+ (rnrs io ports)
+ ,@%default-modules))))
+
+(define urandom-seed-service-type
+ (shepherd-service-type 'urandom-seed
+ (const %urandom-seed-shepherd-service)))
+
+(define (urandom-seed-service)
+ (service urandom-seed-service-type #f))
+
+
+;;;
;;; System-wide environment variables.
;;;
@@ -1200,7 +1250,6 @@ 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-record-type* <gpm-configuration>
gpm-configuration make-gpm-configuration gpm-configuration?
(gpm gpm-configuration-gpm) ;package
@@ -1283,6 +1332,7 @@ This is the GNU operating system, welcome!\n\n")))
(syslog-service)
(guix-service)
(nscd-service)
+ (urandom-seed-service)
;; The LVM2 rules are needed as soon as LVM2 or the device-mapper is
;; used, so enable them by default. The FUSE and ALSA rules are
--
2.8.3