PERFORCE change 36978 for review

Hrishikesh Dandekar hdandeka at FreeBSD.org
Tue Aug 26 13:47:19 PDT 2003


http://perforce.freebsd.org/chv.cgi?CH=36978

Change 36978 by hdandeka at hdandeka_yash on 2003/08/26 13:47:12

	Integrate the System V IPC changes from the rishi_SystemVIPC
	branch to the parent mac branch. The changes include:
	- Kernel wrappers around the original structures for the SystemV
	  IPC primitives ( msg, msqs, sem, shm) to include the MAC label.
	- Changes to portions of the kernel code to reflect the use of 
	  these kernel wrappers. The ipcs utility was also modified for the
	  same reason.
	- New hooks inside the MAC framework to potentially enforce policies
	  on various actions on the primitives.
	- Changes to a number of mac policies to support the SystemV IPC MAC
	  framework hooks.

Affected files ...

.. //depot/projects/trustedbsd/mac/sys/kern/kern_mac.c#404 integrate
.. //depot/projects/trustedbsd/mac/sys/kern/sysv_ipc.c#8 integrate
.. //depot/projects/trustedbsd/mac/sys/kern/sysv_msg.c#11 integrate
.. //depot/projects/trustedbsd/mac/sys/kern/sysv_sem.c#13 integrate
.. //depot/projects/trustedbsd/mac/sys/kern/sysv_shm.c#12 integrate
.. //depot/projects/trustedbsd/mac/sys/modules/sysvipc/sysvmsg/Makefile#2 integrate
.. //depot/projects/trustedbsd/mac/sys/modules/sysvipc/sysvsem/Makefile#2 integrate
.. //depot/projects/trustedbsd/mac/sys/modules/sysvipc/sysvshm/Makefile#2 integrate
.. //depot/projects/trustedbsd/mac/sys/security/mac_biba/mac_biba.c#220 integrate
.. //depot/projects/trustedbsd/mac/sys/security/mac_biba/mac_biba.h#14 integrate
.. //depot/projects/trustedbsd/mac/sys/security/mac_lomac/mac_lomac.c#67 integrate
.. //depot/projects/trustedbsd/mac/sys/security/mac_mls/mac_mls.c#178 integrate
.. //depot/projects/trustedbsd/mac/sys/security/mac_stub/mac_stub.c#6 edit
.. //depot/projects/trustedbsd/mac/sys/sys/mac.h#242 integrate
.. //depot/projects/trustedbsd/mac/sys/sys/mac_policy.h#195 integrate
.. //depot/projects/trustedbsd/mac/sys/sys/msg.h#6 integrate
.. //depot/projects/trustedbsd/mac/sys/sys/msg_msg.h#1 branch
.. //depot/projects/trustedbsd/mac/sys/sys/sem.h#5 integrate
.. //depot/projects/trustedbsd/mac/sys/sys/shm.h#5 integrate
.. //depot/projects/trustedbsd/mac/usr.bin/ipcs/ipcs.c#6 integrate

Differences ...

==== //depot/projects/trustedbsd/mac/sys/kern/kern_mac.c#404 (text+ko) ====

@@ -68,6 +68,10 @@
 #include <sys/pipe.h>
 #include <sys/socketvar.h>
 #include <sys/sysctl.h>
+#include <sys/msg.h>
+#include <sys/msg_msg.h>
+#include <sys/sem.h>
+#include <sys/shm.h>
 
 #include <vm/vm.h>
 #include <vm/pmap.h>
@@ -171,6 +175,11 @@
     &mac_enforce_system, 0, "Enforce MAC policy on system operations");
 TUNABLE_INT("security.mac.enforce_system", &mac_enforce_system);
 
+static int	mac_enforce_sysv = 1;
+SYSCTL_INT(_security_mac, OID_AUTO, enforce_sysv, CTLFLAG_RW,
+    &mac_enforce_sysv, 0, "Enforce MAC policy on System V IPC objects");
+TUNABLE_INT("security.mac.enforce_sysv", &mac_enforce_sysv);
+
 static int	mac_enforce_vm = 1;
 SYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW,
     &mac_enforce_vm, 0, "Enforce MAC policy on vm operations");
@@ -180,6 +189,7 @@
 SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW,
     &mac_mmap_revocation, 0, "Revoke mmap access to files on subject "
     "relabel");
+
 static int	mac_mmap_revocation_via_cow = 1;
 SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW,
     &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via "
@@ -201,7 +211,11 @@
 
 static unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs,
     nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents,
-    nmacipqs, nmacpipes, nmacprocs;
+    nmacipqs, nmacpipes, nmacprocs, nmacipcmsgs, nmacipcmsqs, 
+    nmacipcsemas, nmacipcshms;
+
+#define	MAC_DEBUG_COUNTER_INC(x)	atomic_add_int(x, 1);
+#define	MAC_DEBUG_COUNTER_DEC(x)	atomic_subtract_int(x, 1);
 
 #define	MAC_DEBUG_COUNTER_INC(x)	atomic_add_int(x, 1);
 #define	MAC_DEBUG_COUNTER_DEC(x)	atomic_subtract_int(x, 1);
@@ -230,6 +244,14 @@
     &nmacvnodes, 0, "number of vnodes in use");
 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD,
     &nmacdevfsdirents, 0, "number of devfs dirents inuse");
+SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipc_msgs, CTLFLAG_RD,
+    &nmacipcmsgs, 0, "number of sysv ipc messages inuse");
+SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipc_msqs, CTLFLAG_RD,
+    &nmacipcmsqs, 0, "number of sysv ipc message queue identifiers inuse");
+SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipc_semas, CTLFLAG_RD,
+    &nmacipcsemas, 0, "number of sysv ipc semaphore identifiers inuse");
+SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipc_shms, CTLFLAG_RD,
+    &nmacipcshms, 0, "number of sysv ipc shm identifiers inuse");
 #else
 #define	MAC_DEBUG_COUNTER_INC(x)
 #define	MAC_DEBUG_COUNTER_DEC(x)
@@ -823,6 +845,42 @@
 	mac_init_ifnet_label(&ifp->if_label);
 }
 
+void 
+mac_init_ipc_msgmsg(struct msg *msgptr)
+{
+
+	mac_init_label(&msgptr->label);
+	MAC_PERFORM(init_ipc_msgmsg_label, &msgptr->label);
+	MAC_DEBUG_COUNTER_INC(&nmacipcmsgs);
+}
+
+void 
+mac_init_ipc_msgqueue(struct msqid_kernel *msqkptr)
+{
+
+	mac_init_label(&msqkptr->label);
+	MAC_PERFORM(init_ipc_msgqueue_label, &msqkptr->label);
+	MAC_DEBUG_COUNTER_INC(&nmacipcmsqs);
+}
+
+void  
+mac_init_ipc_sema(struct semid_kernel *semakptr)
+{
+
+	mac_init_label(&semakptr->label);
+	MAC_PERFORM(init_ipc_sema_label, &semakptr->label);
+	MAC_DEBUG_COUNTER_INC(&nmacipcsemas);
+}
+
+void 
+mac_init_ipc_shm(struct shmid_kernel *shmsegptr)
+{
+
+	mac_init_label(&shmsegptr->label);
+	MAC_PERFORM(init_ipc_shm_label, &shmsegptr->label);
+	MAC_DEBUG_COUNTER_INC(&nmacipcshms);
+}
+
 int
 mac_init_ipq(struct ipq *ipq, int flag)
 {
@@ -1045,6 +1103,42 @@
 }
 
 void
+mac_destroy_ipc_msgmsg(struct msg *msgptr)
+{
+
+	MAC_PERFORM(destroy_ipc_msgmsg_label, &msgptr->label);
+	mac_destroy_label(&msgptr->label);
+	MAC_DEBUG_COUNTER_DEC(&nmacipcmsgs);
+}
+
+void
+mac_destroy_ipc_msgqueue(struct msqid_kernel *msqkptr)
+{
+
+	MAC_PERFORM(destroy_ipc_msgqueue_label, &msqkptr->label);
+	mac_destroy_label(&msqkptr->label);
+	MAC_DEBUG_COUNTER_DEC(&nmacipcmsqs);
+}
+
+void
+mac_destroy_ipc_sema(struct semid_kernel *semakptr)
+{
+
+	MAC_PERFORM(destroy_ipc_sema_label, &semakptr->label);
+	mac_destroy_label(&semakptr->label);
+	MAC_DEBUG_COUNTER_DEC(&nmacipcsemas);
+}
+
+void
+mac_destroy_ipc_shm(struct shmid_kernel *shmsegptr)
+{
+
+	MAC_PERFORM(destroy_ipc_shm_label, &shmsegptr->label);
+	mac_destroy_label(&shmsegptr->label);
+	MAC_DEBUG_COUNTER_DEC(&nmacipcshms);
+}
+
+void
 mac_destroy_ipq(struct ipq *ipq)
 {
 
@@ -2221,6 +2315,34 @@
 	MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label);
 }
 
+void 
+mac_create_ipc_msgmsg(struct ucred *cred, struct msg *msgptr)
+{
+				
+	MAC_PERFORM(create_ipc_msgmsg, cred, msgptr, &msgptr->label);
+}
+
+void 
+mac_create_ipc_msgqueue(struct ucred *cred, struct msqid_kernel *msqkptr)
+{
+				
+	MAC_PERFORM(create_ipc_msgqueue, cred, msqkptr, &msqkptr->label);
+}
+
+void 
+mac_create_ipc_sema(struct ucred *cred, struct semid_kernel *semakptr)
+{
+
+	MAC_PERFORM(create_ipc_sema, cred, semakptr, &semakptr->label);
+}
+
+void 
+mac_create_ipc_shm(struct ucred *cred, struct shmid_kernel *shmsegptr)
+{
+
+	MAC_PERFORM(create_ipc_shm, cred, shmsegptr, &shmsegptr->label);
+}
+
 void
 mac_create_socket(struct ucred *cred, struct socket *socket)
 {
@@ -2472,6 +2594,34 @@
 	    &mp->mnt_fslabel);
 }
 
+void
+mac_cleanup_ipc_msgmsg(struct msg *msgptr)
+{
+
+	MAC_PERFORM(cleanup_ipc_msgmsg, &msgptr->label);
+}
+
+void 
+mac_cleanup_ipc_msgqueue(struct msqid_kernel *msqkptr)
+{
+				
+	MAC_PERFORM(cleanup_ipc_msgqueue, &msqkptr->label);
+}
+
+void 
+mac_cleanup_ipc_sema(struct semid_kernel *semakptr)
+{
+
+	MAC_PERFORM(cleanup_ipc_sema, &semakptr->label);
+}
+
+void 
+mac_cleanup_ipc_shm(struct shmid_kernel *shmsegptr)
+{
+
+	MAC_PERFORM(cleanup_ipc_shm, &shmsegptr->label);
+}
+
 int
 mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet)
 {
@@ -2529,6 +2679,209 @@
 }
 
 int
+mac_check_ipc_msgmsq(struct ucred *cred, struct msg *msgptr, 
+	struct msqid_kernel *msqkptr)
+{
+	int error;
+
+	if (!mac_enforce_sysv)
+		return (0);
+
+	//XXX: Should we also pass &msqkptr->label ??
+	MAC_CHECK(check_ipc_msgmsq, cred,  msgptr, msqkptr);
+
+	return(error);
+}
+
+int
+mac_check_ipc_msgrcv(struct ucred *cred, struct msg *msgptr)
+{
+	int error;
+
+	if (!mac_enforce_sysv)
+		return (0);
+
+	//XXX: Should we also pass &msqkptr->label ??
+	MAC_CHECK(check_ipc_msgrcv, cred, msgptr);
+
+	return(error);
+}
+
+int
+mac_check_ipc_msgrmid(struct ucred *cred, struct msg *msgptr)
+{
+	int error;
+
+	if (!mac_enforce_sysv)
+		return (0);
+
+	//XXX: Should we also pass &msqkptr->label ??
+	MAC_CHECK(check_ipc_msgrmid, cred,  msgptr);
+
+	return(error);
+}
+
+int
+mac_check_ipc_msqget(struct ucred *cred, struct msqid_kernel *msqkptr)
+{
+	int error;
+
+	if (!mac_enforce_sysv)
+		return (0);
+
+	//XXX: Should we also pass &msqkptr->label ??
+	MAC_CHECK(check_ipc_msqget, cred, msqkptr);
+
+	return(error);
+}
+
+int
+mac_check_ipc_msqsnd(struct ucred *cred, struct msqid_kernel *msqkptr)
+{
+	int error;
+
+	if (!mac_enforce_sysv)
+		return (0);
+
+	//XXX: Should we also pass &msqkptr->label ??
+	MAC_CHECK(check_ipc_msqsnd, cred, msqkptr);
+
+	return(error);
+}
+
+int
+mac_check_ipc_msqrcv(struct ucred *cred, struct msqid_kernel *msqkptr)
+{
+	int error;
+
+	if (!mac_enforce_sysv)
+		return (0);
+
+	//XXX: Should we also pass &msqkptr->label ??
+	MAC_CHECK(check_ipc_msqrcv, cred, msqkptr);
+
+	return(error);
+}
+
+int
+mac_check_ipc_msqctl(struct ucred *cred, struct msqid_kernel *msqkptr,
+    int cmd)
+{
+	int error;
+
+	if (!mac_enforce_sysv)
+		return (0);
+
+	//XXX: Should we also pass &msqkptr->label ??
+	MAC_CHECK(check_ipc_msqctl, cred, msqkptr, cmd);
+
+	return(error);
+}
+
+int
+mac_check_ipc_semctl(struct ucred *cred, struct semid_kernel *semakptr,
+    int cmd)
+{
+	int error;
+
+	if (!mac_enforce_sysv)
+		return (0);
+
+	//XXX: Should we also pass &semakptr->label ??
+	MAC_CHECK(check_ipc_semctl, cred, semakptr, cmd);
+
+	return(error);
+}
+
+int
+mac_check_ipc_semget(struct ucred *cred, struct semid_kernel *semakptr)
+{
+	int error;
+
+	if (!mac_enforce_sysv)
+		return (0);
+
+	//XXX: Should we also pass &semakptr->label ??
+	MAC_CHECK(check_ipc_semget, cred, semakptr);
+
+	return(error);
+}
+
+int
+mac_check_ipc_semop(struct ucred *cred, struct semid_kernel *semakptr,
+    size_t accesstype)
+{
+	int error;
+
+	if (!mac_enforce_sysv)
+		return (0);
+
+	//XXX: Should we also pass &semakptr->label ??
+	MAC_CHECK(check_ipc_semop, cred, semakptr, accesstype);
+
+	return(error);
+}
+
+int 
+mac_check_ipc_shmat(struct ucred *cred, struct shmid_kernel *shmsegptr,
+    int shmflg)
+{
+	int error;
+
+	if (!mac_enforce_sysv)
+		return (0);
+
+	//XXX: Should we also pass &shmsegptr->label ??
+	MAC_CHECK(check_ipc_shmat, cred, shmsegptr, shmflg);
+
+	return(error);
+}
+
+int
+mac_check_ipc_shmctl(struct ucred *cred, struct shmid_kernel *shmsegptr,
+    int cmd)
+{
+	int error;
+
+	if (!mac_enforce_sysv)
+		return (0);
+
+	//XXX: Should we also pass &shmsegptr->label ??
+	MAC_CHECK(check_ipc_shmctl, cred, shmsegptr, cmd);
+
+	return(error);
+}
+
+int 
+mac_check_ipc_shmdt(struct ucred *cred, struct shmid_kernel *shmsegptr)
+{
+	int error;
+
+	if (!mac_enforce_sysv)
+		return (0);
+
+	//XXX: Should we also pass &shmsegptr->label ??
+	MAC_CHECK(check_ipc_shmdt, cred, shmsegptr);
+
+	return(error);
+}
+
+int 
+mac_check_ipc_shmget(struct ucred *cred, struct shmid_kernel *shmsegptr,
+    int shmflg)
+{
+	int error;
+
+	if (!mac_enforce_sysv)
+		return (0);
+
+	//XXX: Should we also pass &shmsegptr->label ??
+	MAC_CHECK(check_ipc_shmget, cred, shmsegptr, shmflg);
+
+	return(error);
+}
+
+int
 mac_check_kenv_dump(struct ucred *cred)
 {
 	int error;

==== //depot/projects/trustedbsd/mac/sys/kern/sysv_ipc.c#8 (text+ko) ====

@@ -70,6 +70,13 @@
  * Check for ipc permission
  */
 
+
+/*
+ * Note: The MAC Framework doesnt add any hook to the ipcperm function as 
+ * fine-grained hooks are inserted throughout the ipc primitives. These hooks
+ * compliment the ipcperm check. 
+ */
+
 int
 ipcperm(td, perm, mode)
 	struct thread *td;

==== //depot/projects/trustedbsd/mac/sys/kern/sysv_msg.c#11 (text+ko) ====

@@ -21,6 +21,7 @@
 __FBSDID("$FreeBSD: src/sys/kern/sysv_msg.c,v 1.49 2003/06/11 00:56:57 obrien Exp $");
 
 #include "opt_sysvipc.h"
+#include "opt_mac.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -35,6 +36,11 @@
 #include <sys/sysctl.h>
 #include <sys/malloc.h>
 #include <sys/jail.h>
+#ifdef MAC
+#include <sys/msg_msg.h>
+#include <sys/_label.h>
+#include <sys/mac.h>
+#endif
 
 static MALLOC_DEFINE(M_MSG, "msg", "SVID compatible message queues");
 
@@ -47,6 +53,11 @@
 #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);
 
@@ -56,14 +67,17 @@
 	(sy_call_t *)msgsnd, (sy_call_t *)msgrcv
 };
 
+#ifndef MAC
+/* For the MAC framework, struct moved to the header file sys/msg_msg.h */
 struct msg {
 	struct	msg *msg_next;	/* next msg in the chain */
 	long	msg_type;	/* type of this message */
     				/* >0 -> type of this message */
     				/* 0 -> free header */
-	u_short	msg_ts;		/* size of this message */
+	unsigned short	msg_ts;		/* size of this message */
 	short	msg_spot;	/* location of start of msg in buffer */
 };
+#endif
 
 
 #ifndef MSGSSZ
@@ -129,8 +143,10 @@
 static char *msgpool;		/* MSGMAX byte long msg buffer pool */
 static struct msgmap *msgmaps;	/* MSGSEG msgmap structures */
 static struct msg *msghdrs;	/* MSGTQL msg headers */
-static struct msqid_ds *msqids;	/* MSGMNI msqid_ds struct's */
+static struct msqid_kernel *msqids;	/* MSGMNI msqid_kernel struct's */
 static struct mtx msq_mtx;	/* global mutex for message queues. */
+static int refcount; /* to ensure consistency during and after msgunload */
+static struct mtx refcnt_mtx;	/* global mutex for refcount. */
 
 static void
 msginit()
@@ -151,7 +167,7 @@
 	msghdrs = malloc(sizeof(struct msg) * msginfo.msgtql, M_MSG, M_WAITOK);
 	if (msghdrs == NULL)
 		panic("msghdrs is NULL");
-	msqids = malloc(sizeof(struct msqid_ds) * msginfo.msgmni, M_MSG, M_WAITOK);
+	msqids = malloc(sizeof(struct msqid_kernel) * msginfo.msgmni, M_MSG, M_WAITOK);
 	if (msqids == NULL)
 		panic("msqids is NULL");
 
@@ -194,6 +210,9 @@
 		if (i > 0)
 			msghdrs[i-1].msg_next = &msghdrs[i];
 		msghdrs[i].msg_next = NULL;
+#ifdef MAC
+		mac_init_ipc_msgmsg(&msghdrs[i]);
+#endif
     	}
 	free_msghdrs = &msghdrs[0];
 
@@ -201,19 +220,44 @@
 		panic("msqids is NULL");
 
 	for (i = 0; i < msginfo.msgmni; i++) {
-		msqids[i].msg_qbytes = 0;	/* implies entry is available */
-		msqids[i].msg_perm.seq = 0;	/* reset to a known value */
-		msqids[i].msg_perm.mode = 0;
+		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_ipc_msgqueue(&msqids[i]);
+#endif
 	}
 	mtx_init(&msq_mtx, "msq", NULL, MTX_DEF);
+	refcount = 0;
+	/* 
+	 * It is not permissible to pass the same mutex to mtx_init() multiple 
+	 * times without intervening calls to mtx_destroy().
+	 * Since we cannot destroy the refcnt_mtx during msgunload, we check if the 
+	 * mtx_init has ever been called. If so, we dont need to do mtx_init as the 
+	 * mutex is already initialized.
+	 */
+	if ( mtx_initialized(&refcnt_mtx) == 0 )
+		mtx_init(&refcnt_mtx, "msgrefcnt", NULL, MTX_DEF);
 }
 
 static int
 msgunload()
 {
-	struct msqid_ds *msqptr;
+	struct msqid_kernel *msqkptr;
 	int msqid;
 
+	/* 
+	 * Make sure that the msgunload maintains the consistency of the msqids
+	 * and msghdrs data structures. This assures that the unload doesn't take
+	 * place if any thread is in any of the code-paths (tinkering with the
+	 * data structures), and also that no thread can enter the code-paths once
+	 * the module is unloaded. 
+	 */
+	mtx_lock(&refcnt_mtx);
+	if (refcount > 0) {
+		mtx_unlock(&refcnt_mtx);
+		return (EBUSY);
+	}
 	for (msqid = 0; msqid < msginfo.msgmni; msqid++) {
 		/*
 		 * Look for an unallocated and unlocked msqid_ds.
@@ -221,19 +265,38 @@
 		 * they are copying the message in/out.  We can't
 		 * re-use the entry until they release it.
 		 */
-		msqptr = &msqids[msqid];
-		if (msqptr->msg_qbytes != 0 ||
-		    (msqptr->msg_perm.mode & MSG_LOCKED) != 0)
+		msqkptr = &msqids[msqid];
+		if (msqkptr->u.msg_qbytes != 0 ||
+		    (msqkptr->u.msg_perm.mode & MSG_LOCKED) != 0)
 			break;
 	}
-	if (msqid != msginfo.msgmni)
+	if (msqid != msginfo.msgmni) {
+		mtx_unlock(&refcnt_mtx);
 		return (EBUSY);
+	}
 
+	refcount= -1; /* Mark the module as being unloaded */
+	mtx_unlock(&refcnt_mtx);
+
+#ifdef MAC
+	int i;
+	/* Clean up the MAC label associated with the msg objects. */
+	for (i = 0; i < msginfo.msgtql; i++) 
+		mac_destroy_ipc_msgmsg(&msghdrs[i]);
+	/* Clean up the MAC label associated with the msq objects. */
+	for (msqid = 0; msqid < msginfo.msgmni; msqid++) 
+		mac_destroy_ipc_msgqueue(&msqids[msqid]);
+#endif 
 	free(msgpool, M_MSG);
 	free(msgmaps, M_MSG);
 	free(msghdrs, M_MSG);
 	free(msqids, M_MSG);
 	mtx_destroy(&msq_mtx);
+	/* 
+	 * NOTE: We cannot destroy the refcnt_mtx as it is possible that some thread
+	 * might (attempt to) hold the mutex.
+	 */
+/* 	mtx_destroy(&refcnt_mtx); */
 	return (0);
 }
 
@@ -325,6 +388,10 @@
 		panic("msghdr->msg_spot != -1");
 	msghdr->msg_next = free_msghdrs;
 	free_msghdrs = msghdr;
+#ifdef MAC
+	/* XXX: Reset the MAC label */
+	mac_cleanup_ipc_msgmsg(msghdr);
+#endif
 }
 
 #ifndef _SYS_SYSPROTO_H_
@@ -348,76 +415,120 @@
 	struct msqid_ds *user_msqptr = uap->buf;
 	int rval, error;
 	struct msqid_ds msqbuf;
-	register struct msqid_ds *msqptr;
+	register struct msqid_kernel *msqkptr;
 
 	DPRINTF(("call to msgctl(%d, %d, 0x%x)\n", msqid, cmd, user_msqptr));
 	if (!jail_sysvipc_allowed && jailed(td->td_ucred))
 		return (ENOSYS);
 
+	/* Prevent thread from going any further if module is (being) unloaded */
+	mtx_lock(&refcnt_mtx);
+	if (refcount < 0 ) {
+		mtx_unlock(&refcnt_mtx);
+		return (ENOSYS);
+	}
+	refcount++; /* Indicate that thread is active in the code-path */
+	mtx_unlock(&refcnt_mtx);
+
 	msqid = IPCID_TO_IX(msqid);
 
 	if (msqid < 0 || msqid >= msginfo.msgmni) {
 		DPRINTF(("msqid (%d) out of range (0<=msqid<%d)\n", msqid,
 		    msginfo.msgmni));
-		return (EINVAL);
+		error = EINVAL;
+		goto done3;
 	}
 	if (cmd == IPC_SET &&
-	    (error = copyin(user_msqptr, &msqbuf, sizeof(msqbuf))) != 0)
-		return (error);
+	    (error = copyin(user_msqptr, &msqbuf, sizeof(msqbuf))) != 0) 
+		goto done3;
 
-	msqptr = &msqids[msqid];
+	msqkptr = &msqids[msqid];
 
 	mtx_lock(&msq_mtx);
-	if (msqptr->msg_qbytes == 0) {
+	if (msqkptr->u.msg_qbytes == 0) {
 		DPRINTF(("no such msqid\n"));
 		error = EINVAL;
 		goto done2;
 	}
-	if (msqptr->msg_perm.seq != IPCID_TO_SEQ(uap->msqid)) {
+	if (msqkptr->u.msg_perm.seq != IPCID_TO_SEQ(uap->msqid)) {
 		DPRINTF(("wrong sequence number\n"));
 		error = EINVAL;
 		goto done2;
 	}
+#ifdef MAC
+	if ((error = mac_check_ipc_msqctl(td->td_ucred,msqkptr,cmd)))
+	{
+		MPRINTF(("MAC Framework: mac_check_ipc_msqctl permission denied!\n"));
+		goto done2;
+	}
+#endif
 
 	error = 0;
 	rval = 0;
 
+
 	switch (cmd) {
 
 	case IPC_RMID:
 	{
 		struct msg *msghdr;
-		if ((error = ipcperm(td, &msqptr->msg_perm, IPC_M)))
+		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.
+	 */
+		msghdr = msqkptr->u.msg_first;
+		while (msghdr != NULL) {
+		    if((error = mac_check_ipc_msgrmid(td->td_ucred,msghdr))) {
+			MPRINTF("MAC Framework: mac_check_ipc_msgrmid permission denied\n");
+			/* XXX wakeup(msqkptr); ??? */
 			goto done2;
+		    }
+		    msghdr = msghdr->msg_next;
+		}
+#endif
+
 		/* Free the message headers */
-		msghdr = msqptr->msg_first;
+		msghdr = msqkptr->u.msg_first;
 		while (msghdr != NULL) {
 			struct msg *msghdr_tmp;
 
 			/* Free the segments of each message */
-			msqptr->msg_cbytes -= msghdr->msg_ts;
-			msqptr->msg_qnum--;
+			msqkptr->u.msg_cbytes -= msghdr->msg_ts;
+			msqkptr->u.msg_qnum--;
 			msghdr_tmp = msghdr;
 			msghdr = msghdr->msg_next;
 			msg_freehdr(msghdr_tmp);
 		}
 
-		if (msqptr->msg_cbytes != 0)
+		if (msqkptr->u.msg_cbytes != 0)
 			panic("msg_cbytes is screwed up");
-		if (msqptr->msg_qnum != 0)
+		if (msqkptr->u.msg_qnum != 0)
 			panic("msg_qnum is screwed up");
 
-		msqptr->msg_qbytes = 0;	/* Mark it as free */
+		msqkptr->u.msg_qbytes = 0;	/* Mark it as free */
+
+#ifdef MAC
+		/* XXX: Reset the MAC label */
+		mac_cleanup_ipc_msgqueue(msqkptr);
+#endif
 
-		wakeup(msqptr);
+		wakeup(msqkptr);
 	}
 
 		break;
 
 	case IPC_SET:
-		if ((error = ipcperm(td, &msqptr->msg_perm, IPC_M)))
+		if ((error = ipcperm(td, &msqkptr->u.msg_perm, IPC_M)))
 			goto done2;
-		if (msqbuf.msg_qbytes > msqptr->msg_qbytes) {
+		if (msqbuf.msg_qbytes > msqkptr->u.msg_qbytes) {
 			error = suser(td);
 			if (error)
 				goto done2;
@@ -432,16 +543,16 @@
 			error = EINVAL;		/* non-standard errno! */
 			goto done2;
 		}
-		msqptr->msg_perm.uid = msqbuf.msg_perm.uid;	/* change the owner */
-		msqptr->msg_perm.gid = msqbuf.msg_perm.gid;	/* change the owner */
-		msqptr->msg_perm.mode = (msqptr->msg_perm.mode & ~0777) |
+		msqkptr->u.msg_perm.uid = msqbuf.msg_perm.uid;	/* change the owner */
+		msqkptr->u.msg_perm.gid = msqbuf.msg_perm.gid;	/* change the owner */
+		msqkptr->u.msg_perm.mode = (msqkptr->u.msg_perm.mode & ~0777) |
 		    (msqbuf.msg_perm.mode & 0777);
-		msqptr->msg_qbytes = msqbuf.msg_qbytes;
-		msqptr->msg_ctime = time_second;
+		msqkptr->u.msg_qbytes = msqbuf.msg_qbytes;
+		msqkptr->u.msg_ctime = time_second;
 		break;
 
 	case IPC_STAT:
-		if ((error = ipcperm(td, &msqptr->msg_perm, IPC_R))) {
+		if ((error = ipcperm(td, &msqkptr->u.msg_perm, IPC_R))) {
 			DPRINTF(("requester doesn't have read access\n"));
 			goto done2;
 		}
@@ -458,7 +569,11 @@
 done2:
 	mtx_unlock(&msq_mtx);
 	if (cmd == IPC_STAT && error == 0)
-		error = copyout(msqptr, user_msqptr, sizeof(struct msqid_ds));
+		error = copyout(&(msqkptr->u), user_msqptr, sizeof(struct msqid_ds));
+done3:
+	mtx_lock(&refcnt_mtx);
+	refcount--; /* Indicate that thread no longer active in the code-path */
+	mtx_unlock(&refcnt_mtx);
 	return(error);
 }
 
@@ -481,19 +596,28 @@
 	int key = uap->key;
 	int msgflg = uap->msgflg;
 	struct ucred *cred = td->td_ucred;
-	register struct msqid_ds *msqptr = NULL;
+	register struct msqid_kernel *msqkptr = NULL;
 
 	DPRINTF(("msgget(0x%x, 0%o)\n", key, msgflg));
 
 	if (!jail_sysvipc_allowed && jailed(td->td_ucred))
 		return (ENOSYS);
 
+	/* Prevent thread from going any further if module is (being) unloaded */
+	mtx_lock(&refcnt_mtx);
+	if (refcount < 0 ) {
+		mtx_unlock(&refcnt_mtx);
+		return (ENOSYS);
+	}
+	refcount++;	/* Indicate that thread is active in the code-path */
+	mtx_unlock(&refcnt_mtx);
+
 	mtx_lock(&msq_mtx);
 	if (key != IPC_PRIVATE) {
 		for (msqid = 0; msqid < msginfo.msgmni; msqid++) {
-			msqptr = &msqids[msqid];
-			if (msqptr->msg_qbytes != 0 &&
-			    msqptr->msg_perm.key == key)
+			msqkptr = &msqids[msqid];
+			if (msqkptr->u.msg_qbytes != 0 &&
+			    msqkptr->u.msg_perm.key == key)
 				break;
 		}
 		if (msqid < msginfo.msgmni) {
@@ -503,11 +627,17 @@
 				error = EEXIST;
 				goto done2;
 			}
-			if ((error = ipcperm(td, &msqptr->msg_perm, msgflg & 0700 ))) {
+			if ((error = ipcperm(td, &msqkptr->u.msg_perm, msgflg & 0700 ))) {
 				DPRINTF(("requester doesn't have 0%o access\n",
 				    msgflg & 0700));
 				goto done2;
 			}
+#ifdef MAC
+			if(( error = mac_check_ipc_msqget(cred, msqkptr) )) {
+				MPRINTF("MAC Framework:  mac_check_ipc_msqget access denied\n");
+				goto done2;
+			}
+#endif
 			goto found;
 		}
 	}
@@ -521,9 +651,9 @@
 			 * they are copying the message in/out.  We can't
 			 * re-use the entry until they release it.
 			 */
-			msqptr = &msqids[msqid];
-			if (msqptr->msg_qbytes == 0 &&
-			    (msqptr->msg_perm.mode & MSG_LOCKED) == 0)
+			msqkptr = &msqids[msqid];
+			if (msqkptr->u.msg_qbytes == 0 &&
+			    (msqkptr->u.msg_perm.mode & MSG_LOCKED) == 0)
 				break;
 		}
 		if (msqid == msginfo.msgmni) {
@@ -532,24 +662,27 @@
 			goto done2;
 		}
 		DPRINTF(("msqid %d is available\n", msqid));
-		msqptr->msg_perm.key = key;
-		msqptr->msg_perm.cuid = cred->cr_uid;
-		msqptr->msg_perm.uid = cred->cr_uid;
-		msqptr->msg_perm.cgid = cred->cr_gid;
-		msqptr->msg_perm.gid = cred->cr_gid;
-		msqptr->msg_perm.mode = (msgflg & 0777);
+		msqkptr->u.msg_perm.key = key;
+		msqkptr->u.msg_perm.cuid = cred->cr_uid;
+		msqkptr->u.msg_perm.uid = cred->cr_uid;
+		msqkptr->u.msg_perm.cgid = cred->cr_gid;
+		msqkptr->u.msg_perm.gid = cred->cr_gid;
+		msqkptr->u.msg_perm.mode = (msgflg & 0777);
 		/* Make sure that the returned msqid is unique */
-		msqptr->msg_perm.seq = (msqptr->msg_perm.seq + 1) & 0x7fff;
-		msqptr->msg_first = NULL;
-		msqptr->msg_last = NULL;
-		msqptr->msg_cbytes = 0;
-		msqptr->msg_qnum = 0;
-		msqptr->msg_qbytes = msginfo.msgmnb;
-		msqptr->msg_lspid = 0;
-		msqptr->msg_lrpid = 0;
-		msqptr->msg_stime = 0;
-		msqptr->msg_rtime = 0;
-		msqptr->msg_ctime = time_second;
+		msqkptr->u.msg_perm.seq = (msqkptr->u.msg_perm.seq + 1) & 0x7fff;
+		msqkptr->u.msg_first = NULL;
+		msqkptr->u.msg_last = NULL;
+		msqkptr->u.msg_cbytes = 0;
+		msqkptr->u.msg_qnum = 0;
+		msqkptr->u.msg_qbytes = msginfo.msgmnb;
+		msqkptr->u.msg_lspid = 0;
+		msqkptr->u.msg_lrpid = 0;
+		msqkptr->u.msg_stime = 0;
+		msqkptr->u.msg_rtime = 0;
+		msqkptr->u.msg_ctime = time_second;
+#ifdef MAC
+		mac_create_ipc_msgqueue(cred, msqkptr);
+#endif
 	} else {
 		DPRINTF(("didn't find it and wasn't asked to create it\n"));
 		error = ENOENT;
@@ -558,9 +691,12 @@
 
 found:
 	/* Construct the unique msqid */
-	td->td_retval[0] = IXSEQ_TO_IPCID(msqid, msqptr->msg_perm);
+	td->td_retval[0] = IXSEQ_TO_IPCID(msqid, msqkptr->u.msg_perm);
 done2:
 	mtx_unlock(&msq_mtx);
+	mtx_lock(&refcnt_mtx);
+	refcount--; /* Indicate that thread no longer active in the code-path */
+	mtx_unlock(&refcnt_mtx);
 	return (error);
 }
 
@@ -586,7 +722,7 @@
 	size_t msgsz = uap->msgsz;
 	int msgflg = uap->msgflg;
 	int segs_needed, error = 0;
-	register struct msqid_ds *msqptr;
+	register struct msqid_kernel *msqkptr;
 	register struct msg *msghdr;
 	short next;
 
@@ -595,6 +731,15 @@
 	if (!jail_sysvipc_allowed && jailed(td->td_ucred))
 		return (ENOSYS);
 
+	/* Prevent thread from going any further if module is (being) unloaded */
+	mtx_lock(&refcnt_mtx);
+	if (refcount < 0 ) {
+		mtx_unlock(&refcnt_mtx);
+		return (ENOSYS);
+	}
+	refcount++;	/* Indicate that thread is active in the code-path */
+	mtx_unlock(&refcnt_mtx);
+
 	mtx_lock(&msq_mtx);
 	msqid = IPCID_TO_IX(msqid);
 
@@ -605,23 +750,31 @@
 		goto done2;
 	}
 
-	msqptr = &msqids[msqid];
-	if (msqptr->msg_qbytes == 0) {

>>> TRUNCATED FOR MAIL (1000 lines) <<<


More information about the p4-projects mailing list