(address . bug-guix@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).
;;; Carry some entropy across reboots. Adapted from examples in random(4).
;;; We assume Linux >= 2.6, where the poolsize is always 4096 bits (according to
;;; random(4). Otherwise, the example in random(4) reads the 'poolsize' file and
;;; creates a seed of equal size.
;;; This should be run during system shutdown. It saves some random state as a
;;; seed for /dev/urandom, to be used on the next boot.
(define (urandom-shutdown seed)
(touch seed)
(chmod seed #o600)
(write-seed seed))
;;; This should be run at boot, before starting anything that needs random
;;; numbers (sshd, TLS server, etc).
(define (urandom-boot seed)
(and (if (file-exists? seed)
(zero? (system (string-append "cat " seed " > /dev/urandom")))
(touch seed))
(chmod seed #o600)
(write-seed seed)))
;;; On Debian, '/var/lib/urandom/random-seed'.
;;; random(4) suggests '/var/run/random-seed'.
(define seed "/tmp/random-seed")
(define (write-seed seed)
(zero? (system* "dd" "if=/dev/urandom" (string-append "of=" seed)
"count=1" "bs=512"))) ;; If Linux is not >= 2.6, then 'bs'
;; must be calculated as shown in
;; random(4).
(define (touch file)
(close-port (open-file file "a0b")))
Toggle diff (77 lines)
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)
$ ./pre-inst-env guix system vm --no-grafts ~/work/guix/doc/os-config-bare-bones.texi
Backtrace:
In ice-9/boot-9.scm:
1724: 19 [%start-stack load-stack ...]
1729: 18 [#<procedure 1503ea0 ()>]
In unknown file:
?: 17 [primitive-load "/home/leo/work/guix/scripts/guix"]
In guix/ui.scm:
1197: 16 [run-guix-command system "vm" ...]
In ice-9/boot-9.scm:
157: 15 [catch srfi-34 #<procedure 3fa0880 at guix/ui.scm:421:2 ()> ...]
157: 14 [catch system-error ...]
In guix/scripts/system.scm:
882: 13 [#<procedure 3ed9210 at guix/scripts/system.scm:874:2 ()>]
788: 12 [process-action vm # #]
In guix/store.scm:
1163: 11 [run-with-store # ...]
In guix/scripts/system.scm:
800: 10 [#<procedure 46827e0 at guix/scripts/system.scm:792:8 (state)> #]
564: 9 [perform-action vm # # ...]
In gnu/system/vm.scm:
496: 8 [system-qemu-image/shared-store-script # # # ...]
In gnu/system.scm:
601: 7 [operating-system-derivation # # #f]
In gnu/services.scm:
573: 6 [loop #]
In srfi/srfi-1.scm:
578: 5 [map #<procedure loop (sink)> (# # #)]
In gnu/services.scm:
573: 4 [loop #<<service> type: # parameters: #>]
In srfi/srfi-1.scm:
578: 3 [map #<procedure loop (sink)> (# # #)]
In gnu/services.scm:
573: 2 [loop #<<service> type: # parameters: ()>]
In srfi/srfi-1.scm:
578: 1 [map #<procedure 50635e0 at gnu/services.scm:562:4 (service)> (# # # # ...)]
In ice-9/eval.scm:
416: 0 [urandom-seed-shepherd-service ()]
ice-9/eval.scm:416:20: In procedure urandom-seed-shepherd-service:
ice-9/eval.scm:416:20: Wrong number of arguments to #<procedure urandom-seed-shepherd-service ()>