Page MenuHomeFreeBSD

D46472.diff
No OneTemporary

D46472.diff

diff --git a/sys/fs/fifofs/fifo_vnops.c b/sys/fs/fifofs/fifo_vnops.c
--- a/sys/fs/fifofs/fifo_vnops.c
+++ b/sys/fs/fifofs/fifo_vnops.c
@@ -140,9 +140,7 @@
if (fp == NULL || (ap->a_mode & FEXEC) != 0)
return (EINVAL);
if ((fip = vp->v_fifoinfo) == NULL) {
- error = pipe_named_ctor(&fpipe, td);
- if (error != 0)
- return (error);
+ pipe_named_ctor(&fpipe, td);
fip = malloc(sizeof(*fip), M_VNODE, M_WAITOK | M_ZERO);
fip->fi_pipe = fpipe;
fpipe->pipe_wgen = 0;
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
@@ -114,6 +114,7 @@
#include <sys/uio.h>
#include <sys/user.h>
#include <sys/event.h>
+#include <sys/jail.h>
#include <security/mac/mac_framework.h>
@@ -223,8 +224,8 @@
static void pipeinit(void *dummy __unused);
static void pipeclose(struct pipe *cpipe);
static void pipe_free_kmem(struct pipe *cpipe);
-static int pipe_create(struct pipe *pipe, bool backing);
-static int pipe_paircreate(struct thread *td, struct pipepair **p_pp);
+static void pipe_create(struct pipe *pipe, bool backing);
+static void pipe_paircreate(struct thread *td, struct pipepair **p_pp);
static __inline int pipelock(struct pipe *cpipe, bool catch);
static __inline void pipeunlock(struct pipe *cpipe);
static void pipe_timestamp(struct timespec *tsp);
@@ -356,12 +357,11 @@
mtx_destroy(&pp->pp_mtx);
}
-static int
+static void
pipe_paircreate(struct thread *td, struct pipepair **p_pp)
{
struct pipepair *pp;
struct pipe *rpipe, *wpipe;
- int error;
*p_pp = pp = uma_zalloc(pipe_zone, M_WAITOK);
#ifdef MAC
@@ -383,50 +383,21 @@
* Only the forward direction pipe is backed by big buffer by
* default.
*/
- error = pipe_create(rpipe, true);
- if (error != 0)
- goto fail;
- error = pipe_create(wpipe, false);
- if (error != 0) {
- /*
- * This cleanup leaves the pipe inode number for rpipe
- * still allocated, but never used. We do not free
- * inode numbers for opened pipes, which is required
- * for correctness because numbers must be unique.
- * But also it avoids any memory use by the unr
- * allocator, so stashing away the transient inode
- * number is reasonable.
- */
- pipe_free_kmem(rpipe);
- goto fail;
- }
+ pipe_create(rpipe, true);
+ pipe_create(wpipe, false);
rpipe->pipe_state |= PIPE_DIRECTOK;
wpipe->pipe_state |= PIPE_DIRECTOK;
- return (0);
-
-fail:
- knlist_destroy(&rpipe->pipe_sel.si_note);
- knlist_destroy(&wpipe->pipe_sel.si_note);
-#ifdef MAC
- mac_pipe_destroy(pp);
-#endif
- uma_zfree(pipe_zone, pp);
- return (error);
}
-int
+void
pipe_named_ctor(struct pipe **ppipe, struct thread *td)
{
struct pipepair *pp;
- int error;
- error = pipe_paircreate(td, &pp);
- if (error != 0)
- return (error);
+ pipe_paircreate(td, &pp);
pp->pp_rpipe.pipe_type |= PIPE_TYPE_NAMED;
*ppipe = &pp->pp_rpipe;
- return (0);
}
void
@@ -470,9 +441,7 @@
struct pipepair *pp;
int fd, fflags, error;
- error = pipe_paircreate(td, &pp);
- if (error != 0)
- return (error);
+ pipe_paircreate(td, &pp);
rpipe = &pp->pp_rpipe;
wpipe = &pp->pp_wpipe;
error = falloc_caps(td, &rf, &fd, flags, fcaps1);
@@ -549,6 +518,20 @@
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);
+}
+
/*
* Allocate kva for pipe circular buffer, the space is pageable
* This routine will 'realloc' the size of a pipe safely, if it fails
@@ -560,8 +543,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),
@@ -584,9 +565,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++;
}
@@ -694,16 +673,21 @@
* Initialize and allocate VM and memory for pipe. The structure
* will start out zero'd from the ctor, so we just manage the kmem.
*/
-static int
+static void
pipe_create(struct pipe *pipe, bool large_backing)
{
- int error;
- error = pipespace_new(pipe, !large_backing || amountpipekva >
+ /*
+ * Note that pipespace_new() can fail if pipe map is exhausted
+ * (as a result of too many pipes created), but we ignore the
+ * error here as it is not fatal and could be provoked by
+ * unprivileged users. The pipe will be unused in absolute majority
+ * of cases anyways, so it is not a big deal. If the condition
+ * persists, the write() will re-try allocation and report it then.
+ */
+ (void)pipespace_new(pipe, !large_backing || amountpipekva >
maxpipekva / 2 ? SMALL_PIPE_SIZE : PIPE_SIZE);
- if (error == 0)
- pipe->pipe_ino = alloc_unr64(&pipeino_unr);
- return (error);
+ pipe->pipe_ino = alloc_unr64(&pipeino_unr);
}
/* ARGSUSED */
@@ -1159,7 +1143,17 @@
pipespace(wpipe, desiredsize);
PIPE_LOCK(wpipe);
}
- MPASS(wpipe->pipe_buffer.size != 0);
+ if (wpipe->pipe_buffer.size == 0) {
+ /*
+ * This can only happen for reverse direction use of pipes
+ * in a complete OOM situation.
+ */
+ error = ENOMEM;
+ --wpipe->pipe_busy;
+ pipeunlock(wpipe);
+ PIPE_UNLOCK(wpipe);
+ return (error);
+ }
orig_resid = uio->uio_resid;
diff --git a/sys/sys/pipe.h b/sys/sys/pipe.h
--- a/sys/sys/pipe.h
+++ b/sys/sys/pipe.h
@@ -145,7 +145,7 @@
#ifdef _KERNEL
void pipe_dtor(struct pipe *dpipe);
-int pipe_named_ctor(struct pipe **ppipe, struct thread *td);
+void pipe_named_ctor(struct pipe **ppipe, struct thread *td);
void pipeselwakeup(struct pipe *cpipe);
#endif
#endif /* !_SYS_PIPE_H_ */

File Metadata

Mime Type
text/plain
Expires
Tue, Apr 29, 4:20 AM (3 h, 31 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17836993
Default Alt Text
D46472.diff (5 KB)

Event Timeline