PERFORCE change 36978 for review
Hrishikesh Dandekar
hdandeka at FreeBSD.org
Tue Aug 26 20:47:16 GMT 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) <<<
To Unsubscribe: send mail to majordomo at trustedbsd.org
with "unsubscribe trustedbsd-cvs" in the body of the message
More information about the trustedbsd-cvs
mailing list