diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c --- a/sys/kern/sys_pipe.c +++ b/sys/kern/sys_pipe.c @@ -115,6 +115,7 @@ #include #include #include +#include #include @@ -202,6 +203,7 @@ #define MAXPIPESIZE (2*PIPE_SIZE/3) static long amountpipekva; +static int killpipekvathiefs; static int pipefragretry; static int pipeallocfail; static int piperesizefail; @@ -212,6 +214,8 @@ &maxpipekva, 0, "Pipe KVA limit"); SYSCTL_LONG(_kern_ipc, OID_AUTO, pipekva, CTLFLAG_RD, &amountpipekva, 0, "Pipe KVA usage"); +SYSCTL_INT(_kern_ipc, OID_AUTO, killpipekvathiefs, CTLFLAG_RW, + &killpipekvathiefs, 0, "Kill process(es) stealing Pipe KVA"); SYSCTL_INT(_kern_ipc, OID_AUTO, pipefragretry, CTLFLAG_RD, &pipefragretry, 0, "Pipe allocation retries due to fragmentation"); SYSCTL_INT(_kern_ipc, OID_AUTO, pipeallocfail, CTLFLAG_RD, @@ -550,6 +554,23 @@ return (error); } +static void +pipekva_enomem(void) +{ + static int curfail = 0; + static struct timeval lastfail; + + pipeallocfail++; + if (!ppsratecheck(&lastfail, &curfail, 1)) + return; + printf("pid %d (%s), jid %d, uid %d: kern.ipc.maxpipekva exceeded\n", + curproc->p_pid, curproc->p_comm, curproc->p_ucred->cr_prison->pr_id, + curproc->p_ucred->cr_uid); + if (killpipekvathiefs == 0) + return; + killproc(curproc, "Suspected pipekva thief"); +} + /* * Allocate kva for pipe circular buffer, the space is pageable * This routine will 'realloc' the size of a pipe safely, if it fails @@ -561,8 +582,6 @@ { caddr_t buffer; int error, cnt, firstseg; - static int curfail = 0; - static struct timeval lastfail; KASSERT(!mtx_owned(PIPE_MTX(cpipe)), ("pipespace: pipe mutex locked")); KASSERT(!(cpipe->pipe_state & PIPE_DIRECTW), @@ -585,9 +604,7 @@ goto retry; } if (cpipe->pipe_buffer.buffer == NULL) { - pipeallocfail++; - if (ppsratecheck(&lastfail, &curfail, 1)) - printf("kern.ipc.maxpipekva exceeded; see tuning(7)\n"); + pipekva_enomem(); } else { piperesizefail++; }