urandom-seed-service should run earlier in the boot process

  • Done
  • quality assurance status badge
Details
2 participants
  • Leo Famulari
  • Ludovic Courtès
Owner
unassigned
Submitted by
Leo Famulari
Severity
normal
L
L
Leo Famulari wrote on 19 Dec 2017 20:13
(address . bug-guix@gnu.org)
20171219191348.GA19177@jasmine.lan
The urandom-seed-service preserves some of the Linux cryptographic
random number generator's (CRNG) pool across reboots so that freshly
booted systems have access to unpredictable psuedorandom numbers. It
also tries to take advantage of whatever is backing /dev/hwrng.

However, the urandom-seed-service may not be started before certain
applications that assume a good source of randomness.

In some cases, the applications require some random data before any
services are started, during activation. For example, our OpenSSH
service generates its host keys during activation. And even if it
generated host keys during the start of the OpenSSH service, that
service does not depend on urandom-seed-service. [0]

In systemd, there is an abstract sysinit "target" that basically serves
as a checkpoint. All the lower-level system initialization is required
before the sysinit.target is met, and the rest of the services depend on
sysinit. The random seeding is part of sysinit. I've reproduced a graph
of this in [1].

In practice, I'm not sure if it matters. I'd appreciate if GuixSD users
could check /var/log/messages for warnings like this one and report
them:

random: application: uninitialized urandom read (16 bytes read)

And I'd also appreciate any feedback or ideas for improvement in this
area.

[0] See the attached service graph of a bare-bones system with OpenSSH.

local-fs-pre.target
|
v
(various mounts and (various swap (various cryptsetup
fsck services...) devices...) devices...) (various low-level (various low-level
| | | services: udevd, API VFS mounts:
v v v tmpfiles, random mqueue, configfs,
local-fs.target swap.target cryptsetup.target seed, sysctl, ...) debugfs, ...)
| | | | |
\__________________|_________________ | ___________________|____________________/
\|/
v
sysinit.target
|
____________________________________/|\________________________________________
/ | | | \
| | | | |
v v | v v
(various (various | (various rescue.service
timers...) paths...) | sockets...) |
| | | | v
v v | v rescue.target
timers.target paths.target | sockets.target
| | | |
v \_________________ | ___________________/
\|/
v
basic.target
|
____________________________________/| emergency.service
/ | | |
| | | v
v v v emergency.target
display- (various system (various system
manager.service services services)
| required for |
| graphical UIs) v
| | multi-user.target
| | |
\_________________ | _________________/
\|/
v
graphical.target
-----BEGIN PGP SIGNATURE-----

iQIzBAABCAAdFiEEsFFZSPHn08G5gDigJkb6MLrKfwgFAlo5ZOkACgkQJkb6MLrK
fwj1ZxAAspjMPR2YabJVapuCz5rPmsSFHzXA9S4QlveffqRtSlHJwfrFxrZfezLY
wtbbB640BCEP3UWpHx3pi8F8Kjzv7k1Q/cf5M5nZLevj2ZQRwcI0M7eIVZddUCZm
wqZGssC0CIDHYcZv1iC8FE3nW1txsuqpYfUPkdYbcvfOqHywdMpBuMahzX412rG6
B7V44/athWu1werWqgETADb+zCPxggb7OyZBbaBpc6NbOO4I19HvSFAK0Hzp/vV8
PcnnKeOtUqAWf8+uvfkOXiK22Z1d7ZCDGsrVhEx/93Z/Z/RM/LpI360Vis/WpU+0
U7hyvXcpHhcB3+OinOxHDaxwd/fwoWwgQ1rwbb4YfR2lzv10mLWo4/3uq6eH0jmU
7ZQ3c1PygZ/QuJ574lgVnstD787uSvl/kOeununqOJWHRNDpF7H68SGqio3VIbJw
ipLvPb/VHfC9gHEqBUOmSi4xJC919uo65pbG+b8wMA9Jwc8WvIdav03Yc/zdV5xJ
EVf/42eOYUQuXUesri4McPRyiCx3vbrq5bgcdi0R3J3GQw/h9zh/Z1RDHYYfjtpy
C86zXZvBQimSBEGJLDO7C5SEuhXcpEDM5Uo0uh+sucRy7NBiy7jmf5O0b2qO/ATj
zlSg1HDg8/JprcIeRlcV1Ah9umCP1umAFzhVqb/jcRprLXKscEg=
=ZgHn
-----END PGP SIGNATURE-----


L
L
Leo Famulari wrote on 19 Dec 2017 20:24
Service graph
(address . 29773@debbugs.gnu.org)
20171219192452.GA20161@jasmine.lan
I forgot to attach the GuixSD service graph used an example in my last
message.

Here it is!
Attachment: service-graph.svg
-----BEGIN PGP SIGNATURE-----

iQIzBAABCAAdFiEEsFFZSPHn08G5gDigJkb6MLrKfwgFAlo5Z4QACgkQJkb6MLrK
fwgLiw//VIZZq8bRaWB4lZE6nZbeNauFHI+9zlQtry8KX+7I4j13wlG5dD/HBjiW
YwFyDL4236DGLzS8ZOOKLvAFR4q6ozK8BFQGLzDP7qqhX6SfxqS62mpd3NiLni5Y
/1eOx1rmAuMp4xNdVxbVMATyPoxCTrpS0+4y2IJyBP4uuy7pZu7l5yy0KbP7k7Od
FUEzIaaoiA8g2mJ3vHNsQgd2zC3W5+NQt59NQK5vLaW17AtMaP3VHOsM+2cHN3RU
1UhFxs5+Hk4pTsLEO9Xr1MQrzYWF1erKSGLnKU/OJ88lYZTntQ5JUhgd/F+sBim9
aw35loHD7nAKWrKzGwMvSsI0E2mlzMVxdtmSFhPRhD5G2tmbAAByuGnZYBOcpg/E
LUrcGNGtqrVRc9Z0Ckzi+fkRMiNyzC6uxclk3Vul3rJ7IxrmExEhwZ/A5hRuE6+E
Y5N6cJkgm37Sbc7Yv39uMVC9PjwOLxjj2QLJ1io2jY8IO/q+UxDByywgbZcpjsbY
qGqzsZZ3VI2NFNL2yf8Dw3PvuLS2jTt4NBd7V50Xk9cdz5Bw5t295GnLbp0SM+MP
T8pLsJrb8grOqEo8LA/20JLtp9qWLSFsn654q8ff1PvGI3FNuf/TsouXhq0AhHFp
SEnqPD3AxLLUEFdmKBVjAre4pmz7VZfCCVwxK8QnAuSbfZrwFYw=
=RoAm
-----END PGP SIGNATURE-----


L
L
Ludovic Courtès wrote on 20 Dec 2017 11:19
Re: bug#29773: urandom-seed-service should run earlier in the boot process
(name . Leo Famulari)(address . leo@famulari.name)(address . 29773@debbugs.gnu.org)
87tvwlzop3.fsf@gnu.org
Hello,

Leo Famulari <leo@famulari.name> skribis:

Toggle quote (12 lines)
> In some cases, the applications require some random data before any
> services are started, during activation. For example, our OpenSSH
> service generates its host keys during activation. And even if it
> generated host keys during the start of the OpenSSH service, that
> service does not depend on urandom-seed-service. [0]
>
> In systemd, there is an abstract sysinit "target" that basically serves
> as a checkpoint. All the lower-level system initialization is required
> before the sysinit.target is met, and the rest of the services depend on
> sysinit. The random seeding is part of sysinit. I've reproduced a graph
> of this in [1].

There’s a ‘user-processes’ service that serves a similar purpose.

With the attached patches ‘urandom-seed’ becomes a dependency of
‘user-processes’, meaning that daemons & co. start after
‘urandom-seed’.

WDYT?

Toggle quote (6 lines)
> In practice, I'm not sure if it matters. I'd appreciate if GuixSD users
> could check /var/log/messages for warnings like this one and report
> them:
>
> random: application: uninitialized urandom read (16 bytes read)

I don’t have any of these. I guess this is most likely to happen when
running ‘ssh-keygen’ on startup, which isn’t the case on my machine.

Ludo’.
From 5895acdbc345572434d9efae5cf5cdd11e4c1a07 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@gnu.org>
Date: Wed, 20 Dec 2017 11:09:03 +0100
Subject: [PATCH 2/3] services: urandom-seed: Become a dependency of
'user-processes'.

This ensures that 'urandom-seed' is started before programs that rely on
sources of randomness.

Reported by Leo Famulari <leo@famulari.name>.

* gnu/services/base.scm (urandom-seed-shepherd-service): Change
'requirement' to (file-systems).
(urandom-seed-service-type): Extend USER-PROCESSES-SERVICE-TYPE.
---
gnu/services/base.scm | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)

Toggle diff (30 lines)
diff --git a/gnu/services/base.scm b/gnu/services/base.scm
index 481439d4f..cc59ec573 100644
--- a/gnu/services/base.scm
+++ b/gnu/services/base.scm
@@ -529,7 +529,7 @@ in KNOWN-MOUNT-POINTS when it is stopped."
(list (shepherd-service
(documentation "Preserve entropy across reboots for /dev/urandom.")
(provision '(urandom-seed))
- (requirement '(user-processes))
+ (requirement '(file-systems))
(start #~(lambda _
;; On boot, write random seed into /dev/urandom.
(when (file-exists? #$%random-seed-file)
@@ -590,7 +590,13 @@ in KNOWN-MOUNT-POINTS when it is stopped."
(service-type (name 'urandom-seed)
(extensions
(list (service-extension shepherd-root-service-type
- urandom-seed-shepherd-service)))
+ urandom-seed-shepherd-service)
+
+ ;; Have 'user-processes' depend on 'urandom-seed'.
+ ;; This ensures that user processes and daemons don't
+ ;; start until we have seeded the PRNG.
+ (service-extension user-processes-service-type
+ (const '(urandom-seed)))))
(description
"Seed the @file{/dev/urandom} pseudo-random number
generator (RNG) with the value recorded when the system was last shut
--
2.15.1
L
L
Ludovic Courtès wrote on 20 Dec 2017 14:10
control message for bug #29773
(address . control@debbugs.gnu.org)
87mv2dy289.fsf@gnu.org
tags 29773 security
L
L
Leo Famulari wrote on 21 Dec 2017 00:07
Re: bug#29773: urandom-seed-service should run earlier in the boot process
(name . Ludovic Courtès)(address . ludo@gnu.org)(address . 29773@debbugs.gnu.org)
20171220230751.GA18857@jasmine.lan
On Wed, Dec 20, 2017 at 11:19:36AM +0100, Ludovic Courtès wrote:
Toggle quote (8 lines)
> There’s a ‘user-processes’ service that serves a similar purpose.
>
> With the attached patches ‘urandom-seed’ becomes a dependency of
> ‘user-processes’, meaning that daemons & co. start after
> ‘urandom-seed’.
>
> WDYT?

In general, I think it's a good approach.

Currently, the urandom-seed-service seems to non-deterministically but
typically start after the udev-service, so that /dev/hwrng is always set
up by udev before the urandom-seed-service tries to use it.

With these patches, that's not the case. This breaks the hwrng seeding
feature added in 9a56cf2b5b (services: urandom-seed: Try using a HWRNG
to seed the Linux CRNG at boot).

I'll try rearranging the service dependency graph.

Toggle quote (10 lines)
> > Leo Famulari <leo@famulari.name> skribis:
> > In practice, I'm not sure if it matters. I'd appreciate if GuixSD users
> > could check /var/log/messages for warnings like this one and report
> > them:
> >
> > random: application: uninitialized urandom read (16 bytes read)
>
> I don’t have any of these. I guess this is most likely to happen when
> running ‘ssh-keygen’ on startup, which isn’t the case on my machine.

Watching a fresh system boot repeatedly, I noticed that the host keys
always seem to be generated immediately after Linux reports "random:
crng init done".

To me, this suggests that OpenSSH is using the getrandom() syscall. If
so, any GuixSD host keys created with glibc >= 2.25 and OpenSSH >= 7.2
should be unpredictable. But I'm not sure if that's what's happening or
not.

Toggle quote (8 lines)
> +(define (user-processes-shepherd-service requirements)
> + "Return the 'user-processes' Shepherd service with dependencies on
> +REQUIREMENTS (a list of service names).
> +
> +This is a synchronization point used to make sure user processes and daemons
> +get started only after crucial initial services have been started---file
> +system mounts, etc. This is similar to 'target' in systemd."

To clarify, user-processes may be similar to the sysinit target in
systemd. Systemd targets are sort of like run-levels, and there are
several of them, such as the multi-user target, the graphical target,
etc.
-----BEGIN PGP SIGNATURE-----

iQIzBAABCAAdFiEEsFFZSPHn08G5gDigJkb6MLrKfwgFAlo67UQACgkQJkb6MLrK
fwh6axAAtP5RZChiH5oEVlfYg6boD9GmalkodpLFys4RF6HxB4JyTmZmHyvVmh56
HtqkoXCypXqHB9ZzZwi4Atc/i7/VidCqoYLNRJmNaUEbqlPpkGVMZWYp/i9qUcxG
o6CnYWWIexSlgWREjCXpu5nD/YEABeqWhltDwz2aMU3iIMDFIRx/ci3aVdwdoBeW
pgJ65Giq5gdndlYj1Iz8NTSDO+VBSktxCl2IccbH92Gx9BSuZ0/JtmT+hQKOzpF4
GYB1+XDvNXZfcXnigHK0hyMumJf9FLGqLyB9i1DoQUjpqODMHOyVfr3zrCU8y0Yy
AkA9nybw3ET0/XLjuG7WJfk1rPcfleyqvd06Hlu1RJcwPomfsTLxiK/WZj7JZYx0
z79XQk7MfFHHNywgoGi8hPDzf9KFyfGi0wPU/U0LWL6PEMBlBb08SW697Rrso+y7
NT+tDTc4qXAttcZAtOirqI/blUzXCYnyWzk+G1XhlEYAGSTiOwJ2R5MGnoxT9YNJ
djhAB9zRVtgp4aAnj4me4GUI1A6NfWTAY+C9BGKhzdLdsfsbp17fcGF68fdXrQ3t
bREQEyJAIAPFxc7EyiACg37/p1pKJE3CWo9qSeoRgiLMFDUf+o2ZHVPX/h7SYFSl
VfIJTzNp2yAyNbWOQ5bm/ftiBPxyZabHnDah3vwHwm9XGwGY4O8=
=ShZV
-----END PGP SIGNATURE-----


L
L
Ludovic Courtès wrote on 21 Dec 2017 10:10
(name . Leo Famulari)(address . leo@famulari.name)(address . 29773@debbugs.gnu.org)
87ind0a1kq.fsf@gnu.org
Leo Famulari <leo@famulari.name> skribis:

Toggle quote (21 lines)
> On Wed, Dec 20, 2017 at 11:19:36AM +0100, Ludovic Courtès wrote:
>> There’s a ‘user-processes’ service that serves a similar purpose.
>>
>> With the attached patches ‘urandom-seed’ becomes a dependency of
>> ‘user-processes’, meaning that daemons & co. start after
>> ‘urandom-seed’.
>>
>> WDYT?
>
> In general, I think it's a good approach.
>
> Currently, the urandom-seed-service seems to non-deterministically but
> typically start after the udev-service, so that /dev/hwrng is always set
> up by udev before the urandom-seed-service tries to use it.
>
> With these patches, that's not the case. This breaks the hwrng seeding
> feature added in 9a56cf2b5b (services: urandom-seed: Try using a HWRNG
> to seed the Linux CRNG at boot).
>
> I'll try rearranging the service dependency graph.

The attached patch does the trick, AFAICS:
Toggle diff (16 lines)
diff --git a/gnu/services/base.scm b/gnu/services/base.scm
index acc5c33f5..7fc8f6aa7 100644
--- a/gnu/services/base.scm
+++ b/gnu/services/base.scm
@@ -529,7 +529,10 @@ in KNOWN-MOUNT-POINTS when it is stopped."
(list (shepherd-service
(documentation "Preserve entropy across reboots for /dev/urandom.")
(provision '(urandom-seed))
- (requirement '(file-systems))
+
+ ;; Depend on udev so that /dev/hwrng is available.
+ (requirement '(file-systems udev))
+
(start #~(lambda _
;; On boot, write random seed into /dev/urandom.
(when (file-exists? #$%random-seed-file)
Toggle quote (9 lines)
> Watching a fresh system boot repeatedly, I noticed that the host keys
> always seem to be generated immediately after Linux reports "random:
> crng init done".
>
> To me, this suggests that OpenSSH is using the getrandom() syscall. If
> so, any GuixSD host keys created with glibc >= 2.25 and OpenSSH >= 7.2
> should be unpredictable. But I'm not sure if that's what's happening or
> not.

Nice.

The problem though is that ‘ssh-keygen -A’ runs from the activation
snippet, which itself runs before shepherd is started.

To work around that, we should either introduce a separate ‘ssh-keygen’
service that ‘ssh-daemon’ would depend on, or invoke ‘ssh-keygen’ from
the ‘start’ method of the ‘ssh-daemon’ service.

Toggle quote (13 lines)
>> +(define (user-processes-shepherd-service requirements)
>> + "Return the 'user-processes' Shepherd service with dependencies on
>> +REQUIREMENTS (a list of service names).
>> +
>> +This is a synchronization point used to make sure user processes and daemons
>> +get started only after crucial initial services have been started---file
>> +system mounts, etc. This is similar to 'target' in systemd."
>
> To clarify, user-processes may be similar to the sysinit target in
> systemd. Systemd targets are sort of like run-levels, and there are
> several of them, such as the multi-user target, the graphical target,
> etc.

Indeed, I’ve fixed it locally.

If that’s OK I’ll push these patches later today.

Thank you,
Ludo’.
L
L
Leo Famulari wrote on 21 Dec 2017 20:09
(name . Ludovic Courtès)(address . ludo@gnu.org)(address . 29773@debbugs.gnu.org)
20171221190914.GA11808@jasmine.lan
On Thu, Dec 21, 2017 at 10:10:29AM +0100, Ludovic Courtès wrote:
Toggle quote (21 lines)
>
> The attached patch does the trick, AFAICS:
>

> diff --git a/gnu/services/base.scm b/gnu/services/base.scm
> index acc5c33f5..7fc8f6aa7 100644
> --- a/gnu/services/base.scm
> +++ b/gnu/services/base.scm
> @@ -529,7 +529,10 @@ in KNOWN-MOUNT-POINTS when it is stopped."
> (list (shepherd-service
> (documentation "Preserve entropy across reboots for /dev/urandom.")
> (provision '(urandom-seed))
> - (requirement '(file-systems))
> +
> + ;; Depend on udev so that /dev/hwrng is available.
> + (requirement '(file-systems udev))
> +
> (start #~(lambda _
> ;; On boot, write random seed into /dev/urandom.
> (when (file-exists? #$%random-seed-file)

Yes, it seems to work for me.

I'm unsure if the stop action of urandom-seed-service is being executed
on shutdown.

I added some print statements and sleep delays to the stop action but
the system halts faster than I expected and I don't see any writes to
/var/lib/random-seed.
-----BEGIN PGP SIGNATURE-----

iQIzBAABCAAdFiEEsFFZSPHn08G5gDigJkb6MLrKfwgFAlo8BtoACgkQJkb6MLrK
fwhPRw//U4c/2yV4Rap5uD2ixSjjrdxXOO2P4WhH2u6kN1QiolUpYvdtHkgrY4+y
1zKoNqQ3XUIfetclO0ji0cXLTmh1sBfbxl/t5msvMZb66cc1qjdfl9PO8NQbqILF
RhtSaihad31A9hDmKlv9MYw2PSzvz4Z7fuTPOpm/2bOfq4CRKHA/P88hRKBhRy9U
2H8/gX9HxU5p1WIU+L7Y/iXUDMjV7RSygRvWyb11q0ioK8o8dZ+mV5OBHauAKvmU
IKe7Enygn0d6R3yIpyP0cE7b/iKzzVTpgOXP4JerxEkTdPk1f8KUwRBJMjYaTInt
fufLzhrGc+rSMmB7BYU7lJ/fhjOuWeY1Aq/Bx12IAo144OPEH7h+Edk72bksFrmK
Xu6YNCU3lZTcypoZDZVVI5TDrWgJpU1Cx/JQmuJFv3ESx0HppeQ7KdNCLYaKQ8uF
bHscHSeQKylgZoqdIO2iFr9WH1FEIEtTCI9G8g4LtofXekw7veVqFA/3Hi4Yn5F/
RpMMzU8hP+8Hy6EZHj92Wm2ZvIPweIknpJeaj0Hs9DavisgW4GuCIvidYAqZyfMQ
I/Us10AypMG7O7zNTT4tKWhY7n5KxYDJ7PRIKt+B8SXEJgyv2Q21j6oE+vj1buH7
nnn8qGal4UqiNNdvXnIgPxLMFfSnPBe17c4aiVqK9NIkVG/Z9Os=
=LrI4
-----END PGP SIGNATURE-----


L
L
Ludovic Courtès wrote on 22 Dec 2017 10:06
(name . Leo Famulari)(address . leo@famulari.name)(address . 29773-done@debbugs.gnu.org)
87po779lnd.fsf@gnu.org
Hello,

Leo Famulari <leo@famulari.name> skribis:

Toggle quote (24 lines)
> On Thu, Dec 21, 2017 at 10:10:29AM +0100, Ludovic Courtès wrote:
>>
>> The attached patch does the trick, AFAICS:
>>
>
>> diff --git a/gnu/services/base.scm b/gnu/services/base.scm
>> index acc5c33f5..7fc8f6aa7 100644
>> --- a/gnu/services/base.scm
>> +++ b/gnu/services/base.scm
>> @@ -529,7 +529,10 @@ in KNOWN-MOUNT-POINTS when it is stopped."
>> (list (shepherd-service
>> (documentation "Preserve entropy across reboots for /dev/urandom.")
>> (provision '(urandom-seed))
>> - (requirement '(file-systems))
>> +
>> + ;; Depend on udev so that /dev/hwrng is available.
>> + (requirement '(file-systems udev))
>> +
>> (start #~(lambda _
>> ;; On boot, write random seed into /dev/urandom.
>> (when (file-exists? #$%random-seed-file)
>
> Yes, it seems to work for me.

Great, I’ve pushed the whole series.

Toggle quote (7 lines)
> I'm unsure if the stop action of urandom-seed-service is being executed
> on shutdown.
>
> I added some print statements and sleep delays to the stop action but
> the system halts faster than I expected and I don't see any writes to
> /var/lib/random-seed.

/var/lib/random-seed is definitely being updated on shutdown on my
system, as can be seen from its mtime.

Thanks,
Ludo’.
Closed
?