summaryrefslogtreecommitdiffstats
path: root/sys/kern/sysv_msg.c
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2005-01-22 18:51:43 +0000
committerrwatson <rwatson@FreeBSD.org>2005-01-22 18:51:43 +0000
commita9307575e8a271668fbfd1b33c2d7cf5e33afd89 (patch)
tree1e5dd97f974a22651ef06363bece93a3bbf397dc /sys/kern/sysv_msg.c
parent5b8f6c761db73a5914be3df080718e78dc2ba824 (diff)
downloadFreeBSD-src-a9307575e8a271668fbfd1b33c2d7cf5e33afd89.zip
FreeBSD-src-a9307575e8a271668fbfd1b33c2d7cf5e33afd89.tar.gz
Invoke label initialization, creation, cleanup, and tear-down MAC
Framework entry points for System V IPC message queues. Submitted by: Dandekar Hrishikesh <rishi_dandekar at sbcglobal dot net> Obtained from: TrustedBSD Project Sponsored by: DARPA, SPAWAR, McAfee Research
Diffstat (limited to 'sys/kern/sysv_msg.c')
-rw-r--r--sys/kern/sysv_msg.c162
1 files changed, 162 insertions, 0 deletions
diff --git a/sys/kern/sysv_msg.c b/sys/kern/sysv_msg.c
index 32386b4..90bb5d6 100644
--- a/sys/kern/sysv_msg.c
+++ b/sys/kern/sysv_msg.c
@@ -16,11 +16,42 @@
*
* This software is provided ``AS IS'' without any warranties of any kind.
*/
+/*-
+ * Copyright (c) 2003-2005 McAfee, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project in part by McAfee
+ * Research, the Security Research Division of McAfee, Inc under DARPA/SPAWAR
+ * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS research
+ * program.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_sysvipc.h"
+#include "opt_mac.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -28,6 +59,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/lock.h>
+#include <sys/mac.h>
#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/msg.h>
@@ -48,6 +80,11 @@ static int sysvmsg_modload(struct module *, int, void *);
#else
#define DPRINTF(a)
#endif
+#ifdef MAC_DEBUG
+#define MPRINTF(a) printf a
+#else
+#define MPRINTF(a)
+#endif
static void msg_freehdr(struct msg *msghdr);
@@ -188,6 +225,9 @@ msginit()
if (i > 0)
msghdrs[i-1].msg_next = &msghdrs[i];
msghdrs[i].msg_next = NULL;
+#ifdef MAC
+ mac_init_sysv_msgmsg(&msghdrs[i]);
+#endif
}
free_msghdrs = &msghdrs[0];
@@ -198,6 +238,9 @@ msginit()
msqids[i].u.msg_qbytes = 0; /* implies entry is available */
msqids[i].u.msg_perm.seq = 0; /* reset to a known value */
msqids[i].u.msg_perm.mode = 0;
+#ifdef MAC
+ mac_init_sysv_msgqueue(&msqids[i]);
+#endif
}
mtx_init(&msq_mtx, "msq", NULL, MTX_DEF);
}
@@ -207,6 +250,9 @@ msgunload()
{
struct msqid_kernel *msqkptr;
int msqid;
+#ifdef MAC
+ int i;
+#endif
for (msqid = 0; msqid < msginfo.msgmni; msqid++) {
/*
@@ -223,6 +269,12 @@ msgunload()
if (msqid != msginfo.msgmni)
return (EBUSY);
+#ifdef MAC
+ for (i = 0; i < msginfo.msgtql; i++)
+ mac_destroy_sysv_msgmsg(&msghdrs[i]);
+ for (msqid = 0; msqid < msginfo.msgmni; msqid++)
+ mac_destroy_sysv_msgqueue(&msqids[msqid]);
+#endif
free(msgpool, M_MSG);
free(msgmaps, M_MSG);
free(msghdrs, M_MSG);
@@ -320,6 +372,9 @@ msg_freehdr(msghdr)
panic("msghdr->msg_spot != -1");
msghdr->msg_next = free_msghdrs;
free_msghdrs = msghdr;
+#ifdef MAC
+ mac_cleanup_sysv_msgmsg(msghdr);
+#endif
}
#ifndef _SYS_SYSPROTO_H_
@@ -373,6 +428,13 @@ msgctl(td, uap)
error = EINVAL;
goto done2;
}
+#ifdef MAC
+ error = mac_check_sysv_msqctl(td->td_ucred, msqkptr, cmd);
+ if (error != 0) {
+ MPRINTF(("mac_check_sysv_msqctl returned %d\n", error));
+ goto done2;
+ }
+#endif
error = 0;
rval = 0;
@@ -385,6 +447,27 @@ msgctl(td, uap)
if ((error = ipcperm(td, &msqkptr->u.msg_perm, IPC_M)))
goto done2;
+#ifdef MAC
+ /*
+ * Check that the thread has MAC access permissions to
+ * individual msghdrs. Note: We need to do this in a
+ * separate loop because the actual loop alters the
+ * msq/msghdr info as it progresses, and there is no going
+ * back if half the way through we discover that the
+ * thread cannot free a certain msghdr. The msq will get
+ * into an inconsistent state.
+ */
+ for (msghdr = msqkptr->u.msg_first; msghdr != NULL;
+ msghdr = msghdr->msg_next) {
+ error = mac_check_sysv_msgrmid(td->td_ucred, msghdr);
+ if (error != 0) {
+ MPRINTF(("mac_check_sysv_msgrmid returned %d\n",
+ error));
+ goto done2;
+ }
+ }
+#endif
+
/* Free the message headers */
msghdr = msqkptr->u.msg_first;
while (msghdr != NULL) {
@@ -405,6 +488,10 @@ msgctl(td, uap)
msqkptr->u.msg_qbytes = 0; /* Mark it as free */
+#ifdef MAC
+ mac_cleanup_sysv_msgqueue(msqkptr);
+#endif
+
wakeup(msqkptr);
}
@@ -505,6 +592,14 @@ msgget(td, uap)
msgflg & 0700));
goto done2;
}
+#ifdef MAC
+ error = mac_check_sysv_msqget(cred, msqkptr);
+ if (error != 0) {
+ MPRINTF(("mac_check_sysv_msqget returned %d\n",
+ error));
+ goto done2;
+ }
+#endif
goto found;
}
}
@@ -547,6 +642,9 @@ msgget(td, uap)
msqkptr->u.msg_stime = 0;
msqkptr->u.msg_rtime = 0;
msqkptr->u.msg_ctime = time_second;
+#ifdef MAC
+ mac_create_sysv_msgqueue(cred, msqkptr);
+#endif
} else {
DPRINTF(("didn't find it and wasn't asked to create it\n"));
error = ENOENT;
@@ -619,6 +717,14 @@ msgsnd(td, uap)
goto done2;
}
+#ifdef MAC
+ error = mac_check_sysv_msqsnd(td->td_ucred, msqkptr);
+ if (error != 0) {
+ MPRINTF(("mac_check_sysv_msqsnd returned %d\n", error));
+ goto done2;
+ }
+#endif
+
segs_needed = (msgsz + msginfo.msgssz - 1) / msginfo.msgssz;
DPRINTF(("msgsz=%d, msgssz=%d, segs_needed=%d\n", msgsz, msginfo.msgssz,
segs_needed));
@@ -732,6 +838,14 @@ msgsnd(td, uap)
free_msghdrs = msghdr->msg_next;
msghdr->msg_spot = -1;
msghdr->msg_ts = msgsz;
+#ifdef MAC
+ /*
+ * XXXMAC: Should the mac_check_sysv_msgmsq check follow here
+ * immediately? Or, should it be checked just before the msg is
+ * enqueued in the msgq (as it is done now)?
+ */
+ mac_create_sysv_msgmsg(td->td_ucred, msqkptr, msghdr);
+#endif
/*
* Allocate space for the message
@@ -836,6 +950,27 @@ msgsnd(td, uap)
goto done2;
}
+#ifdef MAC
+ /*
+ * Note: Since the task/thread allocates the msghdr and usually
+ * primes it with its own MAC label, for a majority of policies, it
+ * won't be necessary to check whether the msghdr has access
+ * permissions to the msgq. The mac_check_sysv_msqsnd check would
+ * suffice in that case. However, this hook may be required where
+ * individual policies derive a non-identical label for the msghdr
+ * from the current thread label and may want to check the msghdr
+ * enqueue permissions, along with read/write permissions to the
+ * msgq.
+ */
+ error = mac_check_sysv_msgmsq(td->td_ucred, msghdr, msqkptr);
+ if (error != 0) {
+ MPRINTF(("mac_check_sysv_msqmsq returned %d\n", error));
+ msg_freehdr(msghdr);
+ wakeup(msqkptr);
+ goto done2;
+ }
+#endif
+
/*
* Put the message into the queue
*/
@@ -921,6 +1056,14 @@ msgrcv(td, uap)
goto done2;
}
+#ifdef MAC
+ error = mac_check_sysv_msqrcv(td->td_ucred, msqkptr);
+ if (error != 0) {
+ MPRINTF(("mac_check_sysv_msqrcv returned %d\n", error));
+ goto done2;
+ }
+#endif
+
msghdr = NULL;
while (msghdr == NULL) {
if (msgtyp == 0) {
@@ -934,6 +1077,15 @@ msgrcv(td, uap)
error = E2BIG;
goto done2;
}
+#ifdef MAC
+ error = mac_check_sysv_msgrcv(td->td_ucred,
+ msghdr);
+ if (error != 0) {
+ MPRINTF(("mac_check_sysv_msgrcv "
+ "returned %d\n", error));
+ goto done2;
+ }
+#endif
if (msqkptr->u.msg_first == msqkptr->u.msg_last) {
msqkptr->u.msg_first = NULL;
msqkptr->u.msg_last = NULL;
@@ -973,6 +1125,16 @@ msgrcv(td, uap)
error = E2BIG;
goto done2;
}
+#ifdef MAC
+ error = mac_check_sysv_msgrcv(
+ td->td_ucred, msghdr);
+ if (error != 0) {
+ MPRINTF(("mac_check_sysv_"
+ "msgrcv returned %d\n",
+ error));
+ goto done2;
+ }
+#endif
*prev = msghdr->msg_next;
if (msghdr == msqkptr->u.msg_last) {
if (previous == NULL) {
OpenPOWER on IntegriCloud