2014-04-28 20:18:49

by Florian Weimer

[permalink] [raw]
Subject: [PATCH] random: Add "initialized" variable to proc

Before this change, you had to check kernel log messages to see if the
non-blocking pool had been properly initialized. With this change, you
can consult the file /proc/sys/kernel/random/intialized instead.

Signed-off-by: Florian Weimer <[email protected]>
---
drivers/char/random.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)

diff --git a/drivers/char/random.c b/drivers/char/random.c
index 6b75713..81d83e2 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1592,6 +1592,19 @@ static int proc_do_entropy(ctl_table *table, int write,
return proc_dointvec(&fake_table, write, buffer, lenp, ppos);
}

+/*
+ * Return whether the urandom pool has been initialized.
+ */
+static int proc_do_initialized(ctl_table *table, int write,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ ctl_table fake_table;
+ char ch = '0' + nonblocking_pool.initialized;
+ fake_table.data = &ch;
+ fake_table.maxlen = 1;
+ return proc_dostring(&fake_table, write, buffer, lenp, ppos);
+}
+
static int sysctl_poolsize = INPUT_POOL_WORDS * 32;
extern struct ctl_table random_table[];
struct ctl_table random_table[] = {
@@ -1610,6 +1623,12 @@ struct ctl_table random_table[] = {
.data = &input_pool.entropy_count,
},
{
+ .procname = "initialized",
+ .maxlen = 1,
+ .mode = 0444,
+ .proc_handler = proc_do_initialized,
+ },
+ {
.procname = "read_wakeup_threshold",
.data = &random_read_wakeup_bits,
.maxlen = sizeof(int),
--
1.9.0


2014-04-28 21:41:17

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH] random: Add "initialized" variable to proc

On Mon, Apr 28, 2014 at 09:52:11PM +0200, Florian Weimer wrote:
> Before this change, you had to check kernel log messages to see if the
> non-blocking pool had been properly initialized. With this change, you
> can consult the file /proc/sys/kernel/random/intialized instead.
>
> Signed-off-by: Florian Weimer <[email protected]>

The main reason why I hadn't added a facility like this was because
the main goal was to make knowledge of when the /dev/urandom entropy
pool had been fully initialized could be made clear. In fact, at
least on my laptop, this happened at 2.5 seconds after boot, which is
after the hard drives had been probed, and before all of the various
laptop devices have been fully probed.

My goal was to see if we could make it be more or less guaranteed that
by the time userspace daemons started coming up, in practice
/dev/urandom would be initialized, so we wouldn't have to change
userspace. And for the most part, this isn't a problem.

Now there may be systems where the device probe can happen much more
quickly. in which case it does make sense for really paranoid crypto
libraries to check if the urandom pool has been fully initialized.
But in that case, instead of (or perhaps in addition to) providing a
file which a library daemon could poll on, to provide an ioctl
interface which allows userspace to block until /dev/urandom has been
initialized.

- Ted

2014-04-29 17:51:14

by Florian Weimer

[permalink] [raw]
Subject: Re: [PATCH] random: Add "initialized" variable to proc

On 04/28/2014 11:41 PM, Theodore Ts'o wrote:
> On Mon, Apr 28, 2014 at 09:52:11PM +0200, Florian Weimer wrote:
>> Before this change, you had to check kernel log messages to see if the
>> non-blocking pool had been properly initialized. With this change, you
>> can consult the file /proc/sys/kernel/random/intialized instead.
>>
>> Signed-off-by: Florian Weimer <[email protected]>
>
> The main reason why I hadn't added a facility like this was because
> the main goal was to make knowledge of when the /dev/urandom entropy
> pool had been fully initialized could be made clear. In fact, at
> least on my laptop, this happened at 2.5 seconds after boot, which is
> after the hard drives had been probed, and before all of the various
> laptop devices have been fully probed.

I've got a (physical) machine where it happens after ten seconds, or
much longer if there is no activity.

I've seen cases where on the first boot of virtual machines, the SSH key
was generated before the printk with the initialization message. It's
not a problem if you install the OS first and then generate the keys,
but for booting from pre-provisioned images, it could be. (I have no
evidence that this hurts the quality of the generated key material, this
is just based on what's reported by the kernel.)

> My goal was to see if we could make it be more or less guaranteed that
> by the time userspace daemons started coming up, in practice
> /dev/urandom would be initialized, so we wouldn't have to change
> userspace. And for the most part, this isn't a problem.

I'm not sure if I want to bet an increasingly crucial part of the boot
design on the continuing availability of the current entropy levels
(which could go down as the result of environmental changes or a
reassessment of the entropy that actually comes into the system).

> Now there may be systems where the device probe can happen much more
> quickly. in which case it does make sense for really paranoid crypto
> libraries to check if the urandom pool has been fully initialized.
> But in that case, instead of (or perhaps in addition to) providing a
> file which a library daemon could poll on, to provide an ioctl
> interface which allows userspace to block until /dev/urandom has been
> initialized.

Or a new /dev/?random device that blocks until initialized, but behaves
just like /dev/urandom after that. The question is how useful it would
be because of the deadlock scenario.

--
Florian Weimer / Red Hat Product Security Team

2014-04-29 18:26:14

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH] random: Add "initialized" variable to proc

On Tue, Apr 29, 2014 at 07:51:08PM +0200, Florian Weimer wrote:
>
> I've got a (physical) machine where it happens after ten seconds, or much
> longer if there is no activity.
>
> I've seen cases where on the first boot of virtual machines, the SSH key was
> generated before the printk with the initialization message. It's not a
> problem if you install the OS first and then generate the keys, but for
> booting from pre-provisioned images, it could be. (I have no evidence that
> this hurts the quality of the generated key material, this is just based on
> what's reported by the kernel.)

Yes, fair enough, just because it works for me for my laptops doesn't
mean that there aren't systems for which it was a problem. :-)

I will say that for virtual machines, we *really* need virtio-rng.
And I wonder if the right answer is that initially we have some other
process listening on the ssh port, which can generate the ssh host
keys when someone actually first connects to the ssh port (since at
that point, networking will have come up and we'll get some entropy
just from the networking interupts if nothing else), and then exec the
real ssh daemon to handle the incoming connection, as well as execing
a the real ssh daemon to take over listening on the ssh port.

> I'm not sure if I want to bet an increasingly crucial part of the boot
> design on the continuing availability of the current entropy levels (which
> could go down as the result of environmental changes or a reassessment of
> the entropy that actually comes into the system).

It doesn't matter of entropy levels go down; what's important is that
at least at one point, the entropy estimate goes above the threshold
level. Once that happens, someone can only break the RNG if (a) we
were wrong about the entropy estimate --- and we've made the entropy
estimator extremely conservative for that reason; the academic papers
which have studied /dev/random have not found fault with the
estimator, or (b) someone has broken the underlying crypto algorithm.

> Or a new /dev/?random device that blocks until initialized, but behaves just
> like /dev/urandom after that. The question is how useful it would be
> because of the deadlock scenario.

It's like any other technology; it depends on how you use it. If you
don't block the whole boot, but just those services which depend on
the entropy generation (for example, ssh), and there's enough services
up so that the machine has activity so that eventually the initialized
flag is set, it won't be a deadlock. Maybe it will take five minutes
before the machine is answering ssh queries, and that could be a
support nightmare, sure. At some level, it's up to use to generate a
system that can generate enough entropy in a reasonable time, which is
why I added the printk in the first place -- to assist in that effort.

So if you're not going to block on the urandom generator being
"initialized" (where the definition, like the entropy estimator, is
somewhat arbitrary), how were you thinking the information from
/proc/sys/kernel/random/intialized would be used?

- Ted

2014-04-30 20:52:39

by Andy Lutomirski

[permalink] [raw]
Subject: Re: [PATCH] random: Add "initialized" variable to proc

On 04/29/2014 11:26 AM, Theodore Ts'o wrote:
> On Tue, Apr 29, 2014 at 07:51:08PM +0200, Florian Weimer wrote:
>>
>> I've got a (physical) machine where it happens after ten seconds, or much
>> longer if there is no activity.
>>
>> I've seen cases where on the first boot of virtual machines, the SSH key was
>> generated before the printk with the initialization message. It's not a
>> problem if you install the OS first and then generate the keys, but for
>> booting from pre-provisioned images, it could be. (I have no evidence that
>> this hurts the quality of the generated key material, this is just based on
>> what's reported by the kernel.)
>
> Yes, fair enough, just because it works for me for my laptops doesn't
> mean that there aren't systems for which it was a problem. :-)
>
> I will say that for virtual machines, we *really* need virtio-rng.

I only sort of agree. I think that for VMs, we really need a good way
to provide an initial seed and ongoing entropy, and virtio-rng isn't it.

IMO virtio-rng is, alas, terminally fscked up. It has four issues, all
show-stopping. Fixing them may be impossible without changing the
interface.

1. It simply doesn't work on my system. In particular, it never returns
entropy. It just blocks forever.

2. The hwrng code sucks and the guest will never boot if there's a
non-working virtio-rng device around. See #1. I *may* get around to
writing a patch for this before the next merge window.

3. There should be a way to provide some entropy-free cryptographically
secure data, too. Regardless of the speed of the hosts's /dev/random,
the guest should start with at least 256 bits of cryptographically
secure seed material IMO.

4. virtio-pci and its asynchronous interface are too complicated to
achieve #3, even if a future virtio-rng enhancement could provide
urandom-like data. This thing is paravirt hardware; it should be able
to provide a seed *really* early.

--Andy

2014-05-01 02:06:39

by Theodore Ts'o

[permalink] [raw]
Subject: Re: [PATCH] random: Add "initialized" variable to proc

On Wed, Apr 30, 2014 at 01:52:35PM -0700, Andy Lutomirski wrote:
>
> 1. It simply doesn't work on my system. In particular, it never returns
> entropy. It just blocks forever.

Why? Is this a bug in qemu? The host OS? The guest OS? It is qemu
trying to use /dev/random instead of /dev/urandom? Any thing else?

> 3. There should be a way to provide some entropy-free cryptographically
> secure data, too. Regardless of the speed of the hosts's /dev/random,
> the guest should start with at least 256 bits of cryptographically
> secure seed material IMO.

Well, the simplest way to do this is to pass it in via the command
line, and then have the the kernel make sure it gets obscured so it's
not exposed via /proc/cmdline.

Otherwise we would have to define an extension where we pass 32 bytes
or so after the boot command line. But the downside of doing that is
we would have to modify every single architecture to define where
those 32 bytes could be found.

Aside from passing it on the command line as being a bit grotty, the
other big problem this is that some architectures only have 256 bytes
of command line, and if we use a base 64 encoding, 256 bits will take
43 characters. Not a problem on x86, and it seems rather unlikely
that people would want to virtualize a m68k or avr32 CPU. It just
feels really unclean.

I've cc'ed Peter Anvin for his opinion about extending Linux boot
parameter protocol. I agree it would be a lot simpler and easier to
enable things like Kernel ASLR with real randomness on guest OS's if
we didn't have to erect the whole virtio-pci infrastructure during
early boot. :-)

-Ted