summaryrefslogtreecommitdiffstats
path: root/sys/kern/sys_pipe.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/sys_pipe.c')
-rw-r--r--sys/kern/sys_pipe.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c
index e0cff3c..861a8b6 100644
--- a/sys/kern/sys_pipe.c
+++ b/sys/kern/sys_pipe.c
@@ -49,6 +49,8 @@
* amount of kernel virtual memory.
*/
+#include "opt_mac.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/fcntl.h>
@@ -57,6 +59,7 @@
#include <sys/filio.h>
#include <sys/kernel.h>
#include <sys/lock.h>
+#include <sys/mac.h>
#include <sys/mutex.h>
#include <sys/ttycom.h>
#include <sys/stat.h>
@@ -266,6 +269,16 @@ pipe(td, uap)
td->td_retval[1] = fd;
rpipe->pipe_peer = wpipe;
wpipe->pipe_peer = rpipe;
+#ifdef MAC
+ /*
+ * struct pipe represents a pipe endpoint. The MAC label is shared
+ * between the connected endpoints. As a result mac_init_pipe() and
+ * mac_create_pipe() should only be called on one of the endpoints
+ * after they have been connected.
+ */
+ mac_init_pipe(rpipe);
+ mac_create_pipe(td->td_ucred, rpipe);
+#endif
mtx_init(pmtx, "pipe mutex", NULL, MTX_DEF | MTX_RECURSE);
rpipe->pipe_mtxp = wpipe->pipe_mtxp = pmtx;
fdrop(rf, td);
@@ -454,6 +467,12 @@ pipe_read(fp, uio, cred, flags, td)
if (error)
goto unlocked_error;
+#ifdef MAC
+ error = mac_check_pipe_op(td->td_ucred, rpipe, MAC_OP_PIPE_READ);
+ if (error)
+ goto locked_error;
+#endif
+
while (uio->uio_resid) {
/*
* normal pipe buffer receive
@@ -559,6 +578,9 @@ pipe_read(fp, uio, cred, flags, td)
goto unlocked_error;
}
}
+#ifdef MAC
+locked_error:
+#endif
pipeunlock(rpipe);
/* XXX: should probably do this before getting any locks. */
@@ -861,6 +883,13 @@ pipe_write(fp, uio, cred, flags, td)
PIPE_UNLOCK(rpipe);
return (EPIPE);
}
+#ifdef MAC
+ error = mac_check_pipe_op(td->td_ucred, wpipe, MAC_OP_PIPE_WRITE);
+ if (error) {
+ PIPE_UNLOCK(rpipe);
+ return (error);
+ }
+#endif
++wpipe->pipe_busy;
/*
@@ -1132,6 +1161,14 @@ pipe_ioctl(fp, cmd, data, td)
struct thread *td;
{
struct pipe *mpipe = (struct pipe *)fp->f_data;
+#ifdef MAC
+ int error;
+
+ /* XXXMAC: Pipe should be locked for this check. */
+ error = mac_check_pipe_ioctl(td->td_ucred, mpipe, cmd, data);
+ if (error)
+ return (error);
+#endif
switch (cmd) {
@@ -1187,9 +1224,17 @@ pipe_poll(fp, events, cred, td)
struct pipe *rpipe = (struct pipe *)fp->f_data;
struct pipe *wpipe;
int revents = 0;
+#ifdef MAC
+ int error;
+#endif
wpipe = rpipe->pipe_peer;
PIPE_LOCK(rpipe);
+#ifdef MAC
+ error = mac_check_pipe_op(td->td_ucred, rpipe, MAC_OP_PIPE_POLL);
+ if (error)
+ goto locked_error;
+#endif
if (events & (POLLIN | POLLRDNORM))
if ((rpipe->pipe_state & PIPE_DIRECTW) ||
(rpipe->pipe_buffer.cnt > 0) ||
@@ -1218,6 +1263,9 @@ pipe_poll(fp, events, cred, td)
wpipe->pipe_state |= PIPE_SEL;
}
}
+#ifdef MAC
+locked_error:
+#endif
PIPE_UNLOCK(rpipe);
return (revents);
@@ -1234,7 +1282,14 @@ pipe_stat(fp, ub, td)
struct thread *td;
{
struct pipe *pipe = (struct pipe *)fp->f_data;
+#ifdef MAC
+ int error;
+ /* XXXMAC: Pipe should be locked for this check. */
+ error = mac_check_pipe_op(td->td_ucred, pipe, MAC_OP_PIPE_STAT);
+ if (error)
+ return (error);
+#endif
bzero(ub, sizeof(*ub));
ub->st_mode = S_IFIFO;
ub->st_blksize = pipe->pipe_buffer.size;
@@ -1330,6 +1385,11 @@ pipeclose(cpipe)
msleep(cpipe, PIPE_MTX(cpipe), PRIBIO, "pipecl", 0);
}
+#ifdef MAC
+ if (cpipe->pipe_label != NULL && cpipe->pipe_peer == NULL)
+ mac_destroy_pipe(cpipe);
+#endif
+
/*
* Disconnect from peer
*/
OpenPOWER on IntegriCloud