diff options
author | peter <peter@FreeBSD.org> | 1999-12-06 11:13:50 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1999-12-06 11:13:50 +0000 |
commit | 83c2cea457cac2b346ef3a30ddfdaaa5a9115e2d (patch) | |
tree | 80c61d89f27097e8ea1db95aac311f47fcaaa9fb /sys/kern/kern_fork.c | |
parent | c9bb2498127a16c9c6ec0a3beb4fe38e1dac553d (diff) | |
download | FreeBSD-src-83c2cea457cac2b346ef3a30ddfdaaa5a9115e2d.zip FreeBSD-src-83c2cea457cac2b346ef3a30ddfdaaa5a9115e2d.tar.gz |
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.
Diffstat (limited to 'sys/kern/kern_fork.c')
-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 2468ad7..fc69d28 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) { |