diff options
author | Peter Wemm <peter@FreeBSD.org> | 1999-12-06 11:13:50 +0000 |
---|---|---|
committer | Peter Wemm <peter@FreeBSD.org> | 1999-12-06 11:13:50 +0000 |
commit | bb6a234e476d66ea69667f5793fd3df96a1d6d1d (patch) | |
tree | 6e713d36500f7b0717286b8f248ed16665d16f77 /sys | |
parent | 547f2153bbba0369262a769498639b7a766da3c7 (diff) | |
download | src-bb6a234e476d66ea69667f5793fd3df96a1d6d1d.tar.gz src-bb6a234e476d66ea69667f5793fd3df96a1d6d1d.zip |
Put on my asbestos underwear and commit the patch that I posted to -arch
some time ago that changes kern.randompid from a boolean to a randomness
range for the next pid assigment. Too high causes a lot of extra work
to scan for free pids, and too low merely wastes randomness entropy. It's
still possible to select a completely random range by using PID_MAX (100k)
or -1 as a shortcut to mean "the whole range".
Also, don't waste randomness when doing a wraparound.
Notes
Notes:
svn path=/head/; revision=54203
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/kern_fork.c | 39 |
1 files changed, 36 insertions, 3 deletions
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 2468ad7f65f1..fc69d282ec2e 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -142,8 +142,37 @@ rfork(p, uap) int nprocs = 1; /* process 0 */ static int nextpid = 0; +/* + * Random component to nextpid generation. We mix in a random factor to make + * it a little harder to predict. We sanity check the modulus value to avoid + * doing it in critical paths. Don't let it be too small or we pointlessly + * waste randomness entropy, and don't let it be impossibly large. Using a + * modulus that is too big causes a LOT more process table scans and slows + * down fork processing as the pidchecked caching is defeated. + */ static int randompid = 0; -SYSCTL_INT(_kern, OID_AUTO, randompid, CTLFLAG_RW, &randompid, 0, ""); + +static int +sysctl_kern_randompid SYSCTL_HANDLER_ARGS +{ + int error, pid; + + pid = randompid; + error = sysctl_handle_int(oidp, &pid, 0, req); + if (error || !req->newptr) + return (error); + if (pid < 0 || pid > PID_MAX - 100) /* out of range */ + pid = PID_MAX - 100; + else if (pid < 2) /* NOP */ + pid = 0; + else if (pid < 100) /* Make it reasonable */ + pid = 100; + randompid = pid; + return (error); +} + +SYSCTL_PROC(_kern, OID_AUTO, randompid, CTLTYPE_INT|CTLFLAG_RW, + 0, 0, sysctl_kern_randompid, "I", "Random PID modulus"); int fork1(p1, flags, procp) @@ -250,14 +279,18 @@ fork1(p1, flags, procp) * ready to use (from nextpid+1 through pidchecked-1). */ nextpid++; + if (randompid) + nextpid += arc4random() % randompid; retry: /* * If the process ID prototype has wrapped around, * restart somewhat above 0, as the low-numbered procs * tend to include daemons that don't exit. */ - if (nextpid >= PID_MAX || randompid) { - nextpid = (randompid) ? arc4random() % PID_MAX : 100; + if (nextpid >= PID_MAX) { + nextpid = nextpid % PID_MAX; + if (nextpid < 100) + nextpid += 100; pidchecked = 0; } if (nextpid >= pidchecked) { |