Re: Random device in 1.3.30

Theodore Ts'o (tytso@mit.edu)
Fri, 13 Oct 1995 14:05:39 -0400


Date: Tue, 10 Oct 95 15:57:31 MDT
From: colin@nyx10.cs.du.edu (Colin Plumb)

If a daemon needs some random data and can't wait, that's what /dev/urandom
is for. "Gimme the best thing you've got."
But if a demon needs *random* data, damn it, I think a way to wait for it
is highly desirable. Indeed, I thought that's what /dev/random did in
the first place - it seemed so obvious.

Well, I've been talking to someone who's implementing /dev/random for a
large workstation manufacturer, that's doing this in user-mode with a
named pipe for /dev/random. The proposed compromise that we came up
with was that if there was zero bytes of entropy available, the read
would block; otherwise, it would return what data was available. This
is naturally how named pipe works, and it's also how some character
devices work. I think this should make most people happy, or at least
not violently unhappy.....

> I've been meaning to do this ---- however, note that /dev/random had
> better be protected mode 644; you don't want anybody being able to write
> into /dev/random, since an attacker who wished to put malicious data
> into the entropy pool might be able to do something interesting.

There are lots of ways to ensure that that is impossible. No good
random number pool implementation (including the one you have now
and the one I sent you) is *hurt* by adding any data uncorrelated with
the existing contents, however the added data is correlated with itself.
It can be useless, but no worse than that.

True, but if the contents of the random pool leaks out somehow, someone
can then arrange the random pool to their hearts content. Given that
you don't add any value by letting J. Random to write to /dev/random
(since the ioctl which updates the entropy counter has to be root-only),
the more paranoid will probably want to leave /dev/random be mode 644.
A daemon which is collecting noise from the hardware will have to be
running as root anyway.

You also have to think about the timing issues carefully. For example,
let's say the random pool is empty. If you do the
ioctl(ADD_RANDOM_BITS, 512), then write() the data, if someone read()s
/dev/random between those two calls, the read might succeed even though
there's no entropy there. On the other hand, if the pool is full and
you write() some data, it doesn't actually improve thhe pool's entropy,
no matter what it is. If someone else *then* reads, they'll knock the
pool down to not-full status. The ioctl() restores the pool to full
even though it shouldn't.

Good point. What I'll probably have to do is to let the ioctl store the
number of bits to add, plus the current pid, in kernel static state.
Then when a write occurs to /dev/random, we check to make sure that the
current pid matches stored pid, and if so, add the stored random bits
into the entropy count at that point. This way, we can guarantee that
the write() and the update of the entropy counter is atomic.

- Ted