Date: Tue, 26 Aug 2003 13:47:16 -0700 (PDT) From: Hrishikesh Dandekar <hdandeka@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 36978 for review Message-ID: <200308262047.h7QKlG9e012791@repoman.freebsd.org>
index | next in thread | raw e-mail
http://perforce.freebsd.org/chv.cgi?CH=36978 Change 36978 by hdandeka@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) <<<help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200308262047.h7QKlG9e012791>
