Is fork() hook ever possible?

Andrey Chernov ache at
Mon Nov 14 21:29:29 UTC 2011

On Mon, Nov 14, 2011 at 03:58:55PM -0500, David Schultz wrote:
> On Mon, Nov 14, 2011, Andrey Chernov wrote:
> > 1) We should use 
> > 	mib[0] = CTL_KERN;
> > 	mib[1] = KERN_ARND;
> > 
> > 	len = sizeof(rnd);
> > 	sysctl(mib, 2, rnd, &len, NULL, 0);
> > here instead of /dev/random, like OpenBSD did. It helps jails, and 
> > re-stearing not happens too often in anycase. Obviously it minimizes 
> > OpenBSD diffs too.
> Yes, that was in my list of suggested follow-on work, but I don't
> have time for it right now.

I can add this to your patch, we have the same semantics here as OpenBSD, 
so there will be no surprizes.

> > 2) I already explain this moment before. There is no bug here but 
> > intentional hack using time and pid entropy for stearing when read is 
> > fail: time/pid are at the beginning of the struct, successful read happens 
> > at the beginning of the struct too and beginning of the struct is passed 
> > as the key too. Key is always fixed KEYSIZE bytes.
> > 
> > In your new patch you pass unneded stack garbadge at the beginning of the 
> > struct (often 0-s) in case good entropy is successfully readed into 
> > rdat.rnd, moreover, you pass more then KEYSIZE bytes - sizeof(rdat).
> No, the "unneeded stack garbage" was passed in before.  The
> difference is that previously you were calling arc4_addrandom()
> with a 148-byte struct rdat and a length parameter of 128 bytes.
> The result was that the last 20 bytes of the key obtained from
> /dev/random were unused.

Lets go:

#define KEYSIZE         128
if (_read(fd, &rdat, KEYSIZE) == KEYSIZE)
arc4_addrandom((u_char *)&rdat, KEYSIZE);

All 128 bytes read to &rdat pointer are used. Where you found unused 20 
bytes? _read() call here is aligned not to rnd[] member, but to the 
beginnig of the structure. rnd[] member used just as space filler, key 
start is not there.

> It's actually worrisome that you've got the predictable part of
> the key (pid and timestamp) first.  

Only if _read() fails (for jails f.e.). Alternative solution will be to 
return error, but this branch us out of OpenBSD semantics too far, 
programs will not expect it, ignoring errno, which makes security problem 
even worse. Right solution will be using KERN_ARND.

BTW, this way isn't my invention, it was in the OpenBSD code before they 
start using KERN_ARND (when it was imported to FreeBSD) in much less 
secure way than now. It still present in NetBSD:
They use non-random timeval part even if they read good entropy.

> The known-key attacks on RC4
> that were used to break WEP rely on exactly this type of key.
> Specifically, because of the way the key scheduling algorithm
> works, the first few bytes of the state are strongly correlated
> with the first few bytes of the key.

This is well-known.

> > 3) (optional) I think we can lover initial permutations from our 1024 to 
> > at least OpenBSD's 256 here:
> > 	for (i = 0; i < 1024; i++)
> > 		(void)arc4_getbyte();
> > In my initial commit attemps I post several references to publicly 
> > available mathematical researches calculating estimated initial 
> > permutation count, some paper allows even 128. They can be found in the 
> > commit log.
> The revision history shows that you changed that parameter from
> 256 to 1024 to 512 to 768 to 1024 again.  I'm not inclined to
> change it yet again unless an actual cryptographer weighs in and
> proscribes an appropriate level of paranoia.

As I say, this my suggestion is optional.


More information about the freebsd-current mailing list