summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1999-12-06 11:13:50 +0000
committerpeter <peter@FreeBSD.org>1999-12-06 11:13:50 +0000
commit83c2cea457cac2b346ef3a30ddfdaaa5a9115e2d (patch)
tree80c61d89f27097e8ea1db95aac311f47fcaaa9fb /sys/kern
parentc9bb2498127a16c9c6ec0a3beb4fe38e1dac553d (diff)
downloadFreeBSD-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')
-rw-r--r--sys/kern/kern_fork.c39
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) {
OpenPOWER on IntegriCloud