--- //depot/projects/trustedbsd/mac/sys/kern/kern_mac.c 2003/06/07 22:05:57 +++ //depot/user/hdandeka/rishi_SystemVIPC/sys/kern/kern_mac.c 2003/06/13 16:12:32 @@ -68,6 +68,10 @@ #include #include #include +#include +#include +#include +#include #include #include @@ -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 SystemV ipc system 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"); @@ -833,6 +842,36 @@ 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); +} + +void +mac_init_ipc_msgqueue(struct msqid_kernel *msqkptr) +{ + mac_init_label(&msqkptr->label); + MAC_PERFORM(init_ipc_msgqueue_label, &msqkptr->label); +} + +void +mac_init_ipc_sema(struct semid_kernel *semakptr) +{ + + mac_init_label(&semakptr->label); + MAC_PERFORM(init_ipc_sema_label, &semakptr->label); +} + +void +mac_init_ipc_shm(struct shmid_kernel *shmsegptr) +{ + + mac_init_label(&shmsegptr->label); + MAC_PERFORM(init_ipc_shm_label, &shmsegptr->label); +} + int mac_init_ipq(struct ipq *ipq, int flag) { @@ -1080,6 +1119,38 @@ } void +mac_destroy_ipc_msgmsg(struct msg *msgptr) +{ + + MAC_PERFORM(destroy_ipc_msgmsg_label, &msgptr->label); + mac_destroy_label(&msgptr->label); +} + +void +mac_destroy_ipc_msgqueue(struct msqid_kernel *msqkptr) +{ + + MAC_PERFORM(destroy_ipc_msgqueue_label, &msqkptr->label); + mac_destroy_label(&msqkptr->label); +} + +void +mac_destroy_ipc_sema(struct semid_kernel *semakptr) +{ + + MAC_PERFORM(destroy_ipc_sema_label, &semakptr->label); + mac_destroy_label(&semakptr->label); +} + +void +mac_destroy_ipc_shm(struct shmid_kernel *shmsegptr) +{ + + MAC_PERFORM(destroy_ipc_shm_label, &shmsegptr->label); + mac_destroy_label(&shmsegptr->label); +} + +void mac_destroy_ipq(struct ipq *ipq) { @@ -2238,6 +2309,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) { @@ -2489,6 +2588,33 @@ &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) { @@ -2546,6 +2672,213 @@ } 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 2003/05/31 18:09:30 +++ //depot/user/hdandeka/rishi_SystemVIPC/sys/kern/sysv_ipc.c 2003/06/11 17:17:58 @@ -69,6 +69,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 2003/02/21 10:04:40 +++ //depot/user/hdandeka/rishi_SystemVIPC/sys/kern/sysv_msg.c 2003/06/20 08:44:14 @@ -20,6 +20,7 @@ */ #include "opt_sysvipc.h" +#include "opt_mac.h" #include #include @@ -34,6 +35,11 @@ #include #include #include +#ifdef MAC +#include +#include +#include +#endif static MALLOC_DEFINE(M_MSG, "msg", "SVID compatible message queues"); @@ -55,6 +61,8 @@ (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 */ @@ -63,6 +71,7 @@ u_short msg_ts; /* size of this message */ short msg_spot; /* location of start of msg in buffer */ }; +#endif #ifndef MSGSSZ @@ -128,8 +137,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() @@ -150,7 +161,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"); @@ -193,6 +204,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]; @@ -200,19 +214,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. @@ -220,19 +259,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); } @@ -324,6 +382,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_ @@ -347,76 +409,116 @@ 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))) + 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))) { + DPRINTF(("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; @@ -431,16 +533,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; } @@ -457,7 +559,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); } @@ -480,19 +586,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) { @@ -502,11 +617,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) )) { + DPRINTF(("MAC Framework: mac_check_ipc_msqget access denied\n")); + goto done2; + } +#endif goto found; } } @@ -520,9 +641,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) { @@ -531,24 +652,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; @@ -557,9 +681,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); } @@ -585,7 +712,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; @@ -594,6 +721,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); @@ -604,23 +740,31 @@ goto done2; } - msqptr = &msqids[msqid]; - if (msqptr->msg_qbytes == 0) { + msqkptr = &msqids[msqid]; + if (msqkptr->u.msg_qbytes == 0) { DPRINTF(("no such message queue id\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; } - if ((error = ipcperm(td, &msqptr->msg_perm, IPC_W))) { + if ((error = ipcperm(td, &msqkptr->u.msg_perm, IPC_W))) { DPRINTF(("requester doesn't have write access\n")); goto done2; } +#ifdef MAC + /* Make sure that the thread has access rights to the message queue */ + if ((error = mac_check_ipc_msqsnd(td->td_ucred, msqkptr))) { + DPRINTF(("MAC Framework: mac_check_ipc_msqsnd permission denied\n")); + 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)); @@ -632,17 +776,17 @@ * (inside this loop in case msg_qbytes changes while we sleep) */ - if (msgsz > msqptr->msg_qbytes) { - DPRINTF(("msgsz > msqptr->msg_qbytes\n")); + if (msgsz > msqkptr->u.msg_qbytes) { + DPRINTF(("msgsz > msqkptr->u.msg_qbytes\n")); error = EINVAL; goto done2; } - if (msqptr->msg_perm.mode & MSG_LOCKED) { + if (msqkptr->u.msg_perm.mode & MSG_LOCKED) { DPRINTF(("msqid is locked\n")); need_more_resources = 1; } - if (msgsz + msqptr->msg_cbytes > msqptr->msg_qbytes) { + if (msgsz + msqkptr->u.msg_cbytes > msqkptr->u.msg_qbytes) { DPRINTF(("msgsz + msg_cbytes > msg_qbytes\n")); need_more_resources = 1; } @@ -665,22 +809,22 @@ goto done2; } - if ((msqptr->msg_perm.mode & MSG_LOCKED) != 0) { + if ((msqkptr->u.msg_perm.mode & MSG_LOCKED) != 0) { DPRINTF(("we don't own the msqid_ds\n")); we_own_it = 0; } else { /* Force later arrivals to wait for our request */ DPRINTF(("we own the msqid_ds\n")); - msqptr->msg_perm.mode |= MSG_LOCKED; + msqkptr->u.msg_perm.mode |= MSG_LOCKED; we_own_it = 1; } DPRINTF(("goodnight\n")); - error = msleep(msqptr, &msq_mtx, (PZERO - 4) | PCATCH, + error = msleep(msqkptr, &msq_mtx, (PZERO - 4) | PCATCH, "msgwait", 0); DPRINTF(("good morning, error=%d\n", error)); if (we_own_it) - msqptr->msg_perm.mode &= ~MSG_LOCKED; + msqkptr->u.msg_perm.mode &= ~MSG_LOCKED; if (error != 0) { DPRINTF(("msgsnd: interrupted system call\n")); error = EINTR; @@ -691,7 +835,7 @@ * Make sure that the msq queue still exists */ - if (msqptr->msg_qbytes == 0) { + if (msqkptr->u.msg_qbytes == 0) { DPRINTF(("msqid deleted\n")); error = EIDRM; goto done2; @@ -708,11 +852,11 @@ * Make sure! */ - if (msqptr->msg_perm.mode & MSG_LOCKED) + if (msqkptr->u.msg_perm.mode & MSG_LOCKED) panic("msg_perm.mode & MSG_LOCKED"); if (segs_needed > nfree_msgmaps) panic("segs_needed > nfree_msgmaps"); - if (msgsz + msqptr->msg_cbytes > msqptr->msg_qbytes) + if (msgsz + msqkptr->u.msg_cbytes > msqkptr->u.msg_qbytes) panic("msgsz + msg_cbytes > msg_qbytes"); if (free_msghdrs == NULL) panic("no more msghdrs"); @@ -722,9 +866,9 @@ * message */ - if ((msqptr->msg_perm.mode & MSG_LOCKED) != 0) + if ((msqkptr->u.msg_perm.mode & MSG_LOCKED) != 0) panic("msqid_ds is already locked"); - msqptr->msg_perm.mode |= MSG_LOCKED; + msqkptr->u.msg_perm.mode |= MSG_LOCKED; /* * Allocate a message header @@ -734,6 +878,15 @@ free_msghdrs = msghdr->msg_next; msghdr->msg_spot = -1; msghdr->msg_ts = msgsz; +#ifdef MAC + mac_create_ipc_msgmsg(td->td_ucred,msghdr); + /* + * XXX: Should the mac_check_ipc_msgmsq check follow here immediately ? + * Or, should it be checked just before the msg is enqueued in the msgq + * (as it is done now) ? + */ + +#endif /* * Allocate space for the message @@ -767,8 +920,8 @@ mtx_lock(&msq_mtx); DPRINTF(("error %d copying the message type\n", error)); msg_freehdr(msghdr); - msqptr->msg_perm.mode &= ~MSG_LOCKED; - wakeup(msqptr); + msqkptr->u.msg_perm.mode &= ~MSG_LOCKED; + wakeup(msqkptr); goto done2; } mtx_lock(&msq_mtx); @@ -780,8 +933,8 @@ if (msghdr->msg_type < 1) { msg_freehdr(msghdr); - msqptr->msg_perm.mode &= ~MSG_LOCKED; - wakeup(msqptr); + msqkptr->u.msg_perm.mode &= ~MSG_LOCKED; + wakeup(msqkptr); DPRINTF(("mtype (%d) < 1\n", msghdr->msg_type)); error = EINVAL; goto done2; @@ -809,8 +962,8 @@ DPRINTF(("error %d copying in message segment\n", error)); msg_freehdr(msghdr); - msqptr->msg_perm.mode &= ~MSG_LOCKED; - wakeup(msqptr); + msqkptr->u.msg_perm.mode &= ~MSG_LOCKED; + wakeup(msqkptr); goto done2; } mtx_lock(&msq_mtx); @@ -825,15 +978,15 @@ * We've got the message. Unlock the msqid_ds. */ - msqptr->msg_perm.mode &= ~MSG_LOCKED; + msqkptr->u.msg_perm.mode &= ~MSG_LOCKED; /* * Make sure that the msqid_ds is still allocated. */ - if (msqptr->msg_qbytes == 0) { + if (msqkptr->u.msg_qbytes == 0) { msg_freehdr(msghdr); - wakeup(msqptr); + wakeup(msqkptr); error = EIDRM; goto done2; } @@ -842,24 +995,45 @@ * Put the message into the queue */ - if (msqptr->msg_first == NULL) { - msqptr->msg_first = msghdr; - msqptr->msg_last = msghdr; +#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_ipc_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. + */ + if((error= mac_check_ipc_msgmsq(td->td_ucred,msghdr,msqkptr))) { + DPRINTF(("MAC Framework: mac_check_ipc_msqmsq permission denied\n")); + msg_freehdr(msghdr); + wakeup(msqkptr); + goto done2; + } +#endif + + if (msqkptr->u.msg_first == NULL) { + msqkptr->u.msg_first = msghdr; + msqkptr->u.msg_last = msghdr; } else { - msqptr->msg_last->msg_next = msghdr; - msqptr->msg_last = msghdr; + msqkptr->u.msg_last->msg_next = msghdr; + msqkptr->u.msg_last = msghdr; } - msqptr->msg_last->msg_next = NULL; + msqkptr->u.msg_last->msg_next = NULL; - msqptr->msg_cbytes += msghdr->msg_ts; - msqptr->msg_qnum++; - msqptr->msg_lspid = td->td_proc->p_pid; - msqptr->msg_stime = time_second; + msqkptr->u.msg_cbytes += msghdr->msg_ts; + msqkptr->u.msg_qnum++; + msqkptr->u.msg_lspid = td->td_proc->p_pid; + msqkptr->u.msg_stime = time_second; - wakeup(msqptr); + wakeup(msqkptr); td->td_retval[0] = 0; 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); } @@ -887,7 +1061,7 @@ long msgtyp = uap->msgtyp; int msgflg = uap->msgflg; size_t len; - register struct msqid_ds *msqptr; + register struct msqid_kernel *msqkptr; register struct msg *msghdr; int error = 0; short next; @@ -898,36 +1072,54 @@ 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; } - msqptr = &msqids[msqid]; + msqkptr = &msqids[msqid]; mtx_lock(&msq_mtx); - if (msqptr->msg_qbytes == 0) { + if (msqkptr->u.msg_qbytes == 0) { DPRINTF(("no such message queue id\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; } - 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; } +#ifdef MAC + /* Make sure that the thread has access rights to the message queue */ + if ((error = mac_check_ipc_msqrcv(td->td_ucred, msqkptr))) { + DPRINTF(("MAC Framework: mac_check_ipc_msqrcv permission denied\n")); + goto done2; + } +#endif + msghdr = NULL; while (msghdr == NULL) { if (msgtyp == 0) { - msghdr = msqptr->msg_first; + msghdr = msqkptr->u.msg_first; if (msghdr != NULL) { if (msgsz < msghdr->msg_ts && (msgflg & MSG_NOERROR) == 0) { @@ -937,12 +1129,19 @@ error = E2BIG; goto done2; } - if (msqptr->msg_first == msqptr->msg_last) { - msqptr->msg_first = NULL; - msqptr->msg_last = NULL; +#ifdef MAC + /* Make sure that the thread has access rights to the message header */ + if ((error = mac_check_ipc_msgrcv(td->td_ucred, msghdr))) { + DPRINTF(("MAC Framework: mac_check_ipc_msgrcv permission denied\n")); + goto done2; + } +#endif + if (msqkptr->u.msg_first == msqkptr->u.msg_last) { + msqkptr->u.msg_first = NULL; + msqkptr->u.msg_last = NULL; } else { - msqptr->msg_first = msghdr->msg_next; - if (msqptr->msg_first == NULL) + msqkptr->u.msg_first = msghdr->msg_next; + if (msqkptr->u.msg_first == NULL) panic("msg_first/last screwed up #1"); } } @@ -951,7 +1150,7 @@ struct msg **prev; previous = NULL; - prev = &(msqptr->msg_first); + prev = &(msqkptr->u.msg_first); while ((msghdr = *prev) != NULL) { /* * Is this message's type an exact match or is @@ -976,21 +1175,28 @@ error = E2BIG; goto done2; } +#ifdef MAC + /* Make sure that the thread has access rights to the message header */ + if ((error = mac_check_ipc_msgrcv(td->td_ucred, msghdr))) { + DPRINTF(("MAC Framework: mac_check_ipc_msgrcv permission denied\n")); + goto done2; + } +#endif *prev = msghdr->msg_next; - if (msghdr == msqptr->msg_last) { + if (msghdr == msqkptr->u.msg_last) { if (previous == NULL) { if (prev != - &msqptr->msg_first) + &msqkptr->u.msg_first) panic("msg_first/last screwed up #2"); - msqptr->msg_first = + msqkptr->u.msg_first = NULL; - msqptr->msg_last = + msqkptr->u.msg_last = NULL; } else { if (prev == - &msqptr->msg_first) + &msqkptr->u.msg_first) panic("msg_first/last screwed up #3"); - msqptr->msg_last = + msqkptr->u.msg_last = previous; } } @@ -1027,7 +1233,7 @@ */ DPRINTF(("msgrcv: goodnight\n")); - error = msleep(msqptr, &msq_mtx, (PZERO - 4) | PCATCH, + error = msleep(msqkptr, &msq_mtx, (PZERO - 4) | PCATCH, "msgwait", 0); DPRINTF(("msgrcv: good morning (error=%d)\n", error)); @@ -1041,8 +1247,8 @@ * Make sure that the msq queue still exists */ - if (msqptr->msg_qbytes == 0 || - msqptr->msg_perm.seq != IPCID_TO_SEQ(uap->msqid)) { + if (msqkptr->u.msg_qbytes == 0 || + msqkptr->u.msg_perm.seq != IPCID_TO_SEQ(uap->msqid)) { DPRINTF(("msqid deleted\n")); error = EIDRM; goto done2; @@ -1055,10 +1261,10 @@ * First, do the bookkeeping (before we risk being interrupted). */ - msqptr->msg_cbytes -= msghdr->msg_ts; - msqptr->msg_qnum--; - msqptr->msg_lrpid = td->td_proc->p_pid; - msqptr->msg_rtime = time_second; + msqkptr->u.msg_cbytes -= msghdr->msg_ts; + msqkptr->u.msg_qnum--; + msqkptr->u.msg_lrpid = td->td_proc->p_pid; + msqkptr->u.msg_rtime = time_second; /* * Make msgsz the actual amount that we'll be returning. @@ -1082,7 +1288,7 @@ if (error != 0) { DPRINTF(("error (%d) copying out message type\n", error)); msg_freehdr(msghdr); - wakeup(msqptr); + wakeup(msqkptr); goto done2; } user_msgp = (char *)user_msgp + sizeof(msghdr->msg_type); @@ -1111,7 +1317,7 @@ DPRINTF(("error (%d) copying out message segment\n", error)); msg_freehdr(msghdr); - wakeup(msqptr); + wakeup(msqkptr); goto done2; } user_msgp = (char *)user_msgp + tlen; @@ -1123,10 +1329,14 @@ */ msg_freehdr(msghdr); - wakeup(msqptr); + wakeup(msqkptr); td->td_retval[0] = msgsz; done2: mtx_unlock(&msq_mtx); +done3: + mtx_lock(&refcnt_mtx); + refcount--; /* Indicate that thread no longer active in the code-path */ + mtx_unlock(&refcnt_mtx); return (error); } --- //depot/projects/trustedbsd/mac/sys/kern/sysv_sem.c 2003/03/24 20:14:00 +++ //depot/user/hdandeka/rishi_SystemVIPC/sys/kern/sysv_sem.c 2003/06/20 08:44:14 @@ -9,6 +9,7 @@ */ #include "opt_sysvipc.h" +#include "opt_mac.h" #include #include @@ -24,6 +25,10 @@ #include #include #include +#ifdef MAC +#include +#include +#endif static MALLOC_DEFINE(M_SEM, "sem", "SVID compatible semaphores"); @@ -38,7 +43,7 @@ static int semunload(void); static void semexit_myhook(void *arg, struct proc *p); static int sysctl_sema(SYSCTL_HANDLER_ARGS); -static int semvalid(int semid, struct semid_ds *semaptr); +static int semvalid(int semid, struct semid_kernel *semakptr); #ifndef _SYS_SYSPROTO_H_ struct __semctl_args; @@ -62,12 +67,14 @@ static struct mtx sem_mtx; /* semaphore global lock */ static int semtot = 0; -static struct semid_ds *sema; /* semaphore id pool */ +static struct semid_kernel *sema; /* semaphore id pool */ static struct mtx *sema_mtx; /* semaphore id pool mutexes*/ static struct sem *sem; /* semaphore pool */ SLIST_HEAD(, sem_undo) semu_list; /* list of active undo structures */ static int *semu; /* undo structure pool */ static eventhandler_tag semexit_tag; +static int refcount; /* to ensure consistency during and after semunload */ +static struct mtx refcnt_mtx; /* global mutex for refcount. */ #define SEMUNDO_MTX sem_mtx #define SEMUNDO_LOCK() mtx_lock(&SEMUNDO_MTX); @@ -188,15 +195,18 @@ TUNABLE_INT_FETCH("kern.ipc.semaem", &seminfo.semaem); sem = malloc(sizeof(struct sem) * seminfo.semmns, M_SEM, M_WAITOK); - sema = malloc(sizeof(struct semid_ds) * seminfo.semmni, M_SEM, + sema = malloc(sizeof(struct semid_kernel ) * seminfo.semmni, M_SEM, M_WAITOK); sema_mtx = malloc(sizeof(struct mtx) * seminfo.semmni, M_SEM, M_WAITOK | M_ZERO); semu = malloc(seminfo.semmnu * seminfo.semusz, M_SEM, M_WAITOK); for (i = 0; i < seminfo.semmni; i++) { - sema[i].sem_base = 0; - sema[i].sem_perm.mode = 0; + sema[i].u.sem_base = 0; + sema[i].u.sem_perm.mode = 0; +#ifdef MAC + mac_init_ipc_sema(&sema[i]); +#endif } for (i = 0; i < seminfo.semmni; i++) mtx_init(&sema_mtx[i], "semid", NULL, MTX_DEF); @@ -206,6 +216,16 @@ } SLIST_INIT(&semu_list); mtx_init(&sem_mtx, "sem", 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 semunload, 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, "semrefcnt", NULL, MTX_DEF); semexit_tag = EVENTHANDLER_REGISTER(process_exit, semexit_myhook, NULL, EVENTHANDLER_PRI_ANY); } @@ -215,16 +235,37 @@ { int i; - if (semtot != 0) + /* + * Make sure that the semunload maintains the consistency of the sem and + * sema 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) || (semtot != 0)) { + mtx_unlock(&refcnt_mtx); return (EBUSY); + } + refcount= -1; /* Mark the module as being unloaded */ + mtx_unlock(&refcnt_mtx); EVENTHANDLER_DEREGISTER(process_exit, semexit_tag); +#ifdef MAC + for (i = 0; i < seminfo.semmni; i++) + mac_destroy_ipc_sema(&sema[i]); +#endif free(sem, M_SEM); free(sema, M_SEM); free(semu, M_SEM); for (i = 0; i < seminfo.semmni; i++) mtx_destroy(&sema_mtx[i]); mtx_destroy(&sem_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); } @@ -467,13 +508,13 @@ } static int -semvalid(semid, semaptr) +semvalid(semid, semakptr) int semid; - struct semid_ds *semaptr; + struct semid_kernel *semakptr; { - return ((semaptr->sem_perm.mode & SEM_ALLOC) == 0 || - semaptr->sem_perm.seq != IPCID_TO_SEQ(semid) ? EINVAL : 0); + return ((semakptr->u.sem_perm.mode & SEM_ALLOC) == 0 || + semakptr->u.sem_perm.seq != IPCID_TO_SEQ(semid) ? EINVAL : 0); } /* @@ -505,7 +546,7 @@ struct ucred *cred = td->td_ucred; int i, rval, error; struct semid_ds sbuf; - struct semid_ds *semaptr; + struct semid_kernel *semakptr; struct mtx *sema_mtxp; u_short usval, count; @@ -514,37 +555,68 @@ 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); + array = NULL; switch(cmd) { case SEM_STAT: - if (semid < 0 || semid >= seminfo.semmni) - return (EINVAL); + if (semid < 0 || semid >= seminfo.semmni) { + error = EINVAL; + goto done3; + } if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0) - return (error); - semaptr = &sema[semid]; + goto done3; + semakptr = &sema[semid]; sema_mtxp = &sema_mtx[semid]; mtx_lock(sema_mtxp); - if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0 ) { + if ((semakptr->u.sem_perm.mode & SEM_ALLOC) == 0 ) { error = EINVAL; goto done2; } - if ((error = ipcperm(td, &semaptr->sem_perm, IPC_R))) + if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R))) goto done2; +#ifdef MAC + if(( error = mac_check_ipc_semctl(cred,semakptr,cmd) )) { + DPRINTF(("MAC Framework: mac_check_ipc_semctl access denied\n")); + goto done2; + } +#endif mtx_unlock(sema_mtxp); - error = copyout(semaptr, real_arg.buf, sizeof(struct semid_ds)); - rval = IXSEQ_TO_IPCID(semid,semaptr->sem_perm); + error = copyout(&semakptr->u, real_arg.buf, sizeof(struct semid_ds)); + rval = IXSEQ_TO_IPCID(semid,semakptr->u.sem_perm); if (error == 0) td->td_retval[0] = rval; - return (error); + goto done3; } semid = IPCID_TO_IX(semid); - if (semid < 0 || semid >= seminfo.semmni) - return (EINVAL); + if (semid < 0 || semid >= seminfo.semmni) { + error = EINVAL; + goto done3; + } - semaptr = &sema[semid]; + semakptr = &sema[semid]; sema_mtxp = &sema_mtx[semid]; +#ifdef MAC + mtx_lock(sema_mtxp); + /* + * The MAC framework lets the policies decide what type of access + * is permitted, based on the cmd. + */ + if(( error = mac_check_ipc_semctl(cred,semakptr,cmd) )) { + DPRINTF(("MAC Framework: mac_check_ipc_semctl access denied\n")); + goto done2; + } + mtx_unlock(sema_mtxp); +#endif error = 0; rval = 0; @@ -552,25 +624,29 @@ switch (cmd) { case IPC_RMID: mtx_lock(sema_mtxp); - if ((error = semvalid(uap->semid, semaptr)) != 0) + if ((error = semvalid(uap->semid, semakptr)) != 0) goto done2; - if ((error = ipcperm(td, &semaptr->sem_perm, IPC_M))) + if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_M))) goto done2; - semaptr->sem_perm.cuid = cred->cr_uid; - semaptr->sem_perm.uid = cred->cr_uid; - semtot -= semaptr->sem_nsems; - for (i = semaptr->sem_base - sem; i < semtot; i++) - sem[i] = sem[i + semaptr->sem_nsems]; + semakptr->u.sem_perm.cuid = cred->cr_uid; + semakptr->u.sem_perm.uid = cred->cr_uid; + semtot -= semakptr->u.sem_nsems; + for (i = semakptr->u.sem_base - sem; i < semtot; i++) + sem[i] = sem[i + semakptr->u.sem_nsems]; for (i = 0; i < seminfo.semmni; i++) { - if ((sema[i].sem_perm.mode & SEM_ALLOC) && - sema[i].sem_base > semaptr->sem_base) - sema[i].sem_base -= semaptr->sem_nsems; + if ((sema[i].u.sem_perm.mode & SEM_ALLOC) && + sema[i].u.sem_base > semakptr->u.sem_base) + sema[i].u.sem_base -= semakptr->u.sem_nsems; } - semaptr->sem_perm.mode = 0; + semakptr->u.sem_perm.mode = 0; +#ifdef MAC + /* XXX: Reset the MAC label */ + mac_cleanup_ipc_sema(semakptr); +#endif SEMUNDO_LOCK(); semundo_clear(semid, -1); SEMUNDO_UNLOCK(); - wakeup(semaptr); + wakeup(semakptr); break; case IPC_SET: @@ -579,82 +655,82 @@ if ((error = copyin(real_arg.buf, &sbuf, sizeof(sbuf))) != 0) goto done2; mtx_lock(sema_mtxp); - if ((error = semvalid(uap->semid, semaptr)) != 0) + if ((error = semvalid(uap->semid, semakptr)) != 0) goto done2; - if ((error = ipcperm(td, &semaptr->sem_perm, IPC_M))) + if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_M))) goto done2; - semaptr->sem_perm.uid = sbuf.sem_perm.uid; - semaptr->sem_perm.gid = sbuf.sem_perm.gid; - semaptr->sem_perm.mode = (semaptr->sem_perm.mode & ~0777) | + semakptr->u.sem_perm.uid = sbuf.sem_perm.uid; + semakptr->u.sem_perm.gid = sbuf.sem_perm.gid; + semakptr->u.sem_perm.mode = (semakptr->u.sem_perm.mode & ~0777) | (sbuf.sem_perm.mode & 0777); - semaptr->sem_ctime = time_second; + semakptr->u.sem_ctime = time_second; break; case IPC_STAT: if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0) goto done2; mtx_lock(sema_mtxp); - if ((error = semvalid(uap->semid, semaptr)) != 0) + if ((error = semvalid(uap->semid, semakptr)) != 0) goto done2; - if ((error = ipcperm(td, &semaptr->sem_perm, IPC_R))) + if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R))) goto done2; - sbuf = *semaptr; + sbuf = semakptr->u; mtx_unlock(sema_mtxp); - error = copyout(semaptr, real_arg.buf, + error = copyout(&semakptr->u, real_arg.buf, sizeof(struct semid_ds)); break; case GETNCNT: mtx_lock(sema_mtxp); - if ((error = semvalid(uap->semid, semaptr)) != 0) + if ((error = semvalid(uap->semid, semakptr)) != 0) goto done2; - if ((error = ipcperm(td, &semaptr->sem_perm, IPC_R))) + if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R))) goto done2; - if (semnum < 0 || semnum >= semaptr->sem_nsems) { + if (semnum < 0 || semnum >= semakptr->u.sem_nsems) { error = EINVAL; goto done2; } - rval = semaptr->sem_base[semnum].semncnt; + rval = semakptr->u.sem_base[semnum].semncnt; break; case GETPID: mtx_lock(sema_mtxp); - if ((error = semvalid(uap->semid, semaptr)) != 0) + if ((error = semvalid(uap->semid, semakptr)) != 0) goto done2; - if ((error = ipcperm(td, &semaptr->sem_perm, IPC_R))) + if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R))) goto done2; - if (semnum < 0 || semnum >= semaptr->sem_nsems) { + if (semnum < 0 || semnum >= semakptr->u.sem_nsems) { error = EINVAL; goto done2; } - rval = semaptr->sem_base[semnum].sempid; + rval = semakptr->u.sem_base[semnum].sempid; break; case GETVAL: mtx_lock(sema_mtxp); - if ((error = semvalid(uap->semid, semaptr)) != 0) + if ((error = semvalid(uap->semid, semakptr)) != 0) goto done2; - if ((error = ipcperm(td, &semaptr->sem_perm, IPC_R))) + if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R))) goto done2; - if (semnum < 0 || semnum >= semaptr->sem_nsems) { + if (semnum < 0 || semnum >= semakptr->u.sem_nsems) { error = EINVAL; goto done2; } - rval = semaptr->sem_base[semnum].semval; + rval = semakptr->u.sem_base[semnum].semval; break; case GETALL: if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0) goto done2; - array = malloc(sizeof(*array) * semaptr->sem_nsems, M_TEMP, + array = malloc(sizeof(*array) * semakptr->u.sem_nsems, M_TEMP, M_WAITOK); mtx_lock(sema_mtxp); - if ((error = semvalid(uap->semid, semaptr)) != 0) + if ((error = semvalid(uap->semid, semakptr)) != 0) goto done2; - if ((error = ipcperm(td, &semaptr->sem_perm, IPC_R))) + if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R))) goto done2; - for (i = 0; i < semaptr->sem_nsems; i++) - array[i] = semaptr->sem_base[i].semval; + for (i = 0; i < semakptr->u.sem_nsems; i++) + array[i] = semakptr->u.sem_base[i].semval; mtx_unlock(sema_mtxp); error = copyout(array, real_arg.array, i * sizeof(real_arg.array[0])); @@ -662,26 +738,26 @@ case GETZCNT: mtx_lock(sema_mtxp); - if ((error = semvalid(uap->semid, semaptr)) != 0) + if ((error = semvalid(uap->semid, semakptr)) != 0) goto done2; - if ((error = ipcperm(td, &semaptr->sem_perm, IPC_R))) + if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R))) goto done2; - if (semnum < 0 || semnum >= semaptr->sem_nsems) { + if (semnum < 0 || semnum >= semakptr->u.sem_nsems) { error = EINVAL; goto done2; } - rval = semaptr->sem_base[semnum].semzcnt; + rval = semakptr->u.sem_base[semnum].semzcnt; break; case SETVAL: if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0) goto done2; mtx_lock(sema_mtxp); - if ((error = semvalid(uap->semid, semaptr)) != 0) + if ((error = semvalid(uap->semid, semakptr)) != 0) goto done2; - if ((error = ipcperm(td, &semaptr->sem_perm, IPC_W))) + if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_W))) goto done2; - if (semnum < 0 || semnum >= semaptr->sem_nsems) { + if (semnum < 0 || semnum >= semakptr->u.sem_nsems) { error = EINVAL; goto done2; } @@ -689,19 +765,19 @@ error = ERANGE; goto done2; } - semaptr->sem_base[semnum].semval = real_arg.val; + semakptr->u.sem_base[semnum].semval = real_arg.val; SEMUNDO_LOCK(); semundo_clear(semid, semnum); SEMUNDO_UNLOCK(); - wakeup(semaptr); + wakeup(semakptr); break; case SETALL: mtx_lock(sema_mtxp); raced: - if ((error = semvalid(uap->semid, semaptr)) != 0) + if ((error = semvalid(uap->semid, semakptr)) != 0) goto done2; - count = semaptr->sem_nsems; + count = semakptr->u.sem_nsems; mtx_unlock(sema_mtxp); if ((error = copyin(arg, &real_arg, sizeof(real_arg))) != 0) goto done2; @@ -710,28 +786,28 @@ if (error) break; mtx_lock(sema_mtxp); - if ((error = semvalid(uap->semid, semaptr)) != 0) + if ((error = semvalid(uap->semid, semakptr)) != 0) goto done2; /* we could have raced? */ - if (count != semaptr->sem_nsems) { + if (count != semakptr->u.sem_nsems) { free(array, M_TEMP); array = NULL; goto raced; } - if ((error = ipcperm(td, &semaptr->sem_perm, IPC_W))) + if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_W))) goto done2; - for (i = 0; i < semaptr->sem_nsems; i++) { + for (i = 0; i < semakptr->u.sem_nsems; i++) { usval = array[i]; if (usval > seminfo.semvmx) { error = ERANGE; break; } - semaptr->sem_base[i].semval = usval; + semakptr->u.sem_base[i].semval = usval; } SEMUNDO_LOCK(); semundo_clear(semid, -1); SEMUNDO_UNLOCK(); - wakeup(semaptr); + wakeup(semakptr); break; default: @@ -746,6 +822,10 @@ mtx_unlock(sema_mtxp); if (array != NULL) free(array, M_TEMP); +done3: + mtx_lock(&refcnt_mtx); + refcount--; /* Indicate that thread no longer active in the code-path */ + mtx_unlock(&refcnt_mtx); return(error); } @@ -775,20 +855,29 @@ 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(&Giant); if (key != IPC_PRIVATE) { for (semid = 0; semid < seminfo.semmni; semid++) { - if ((sema[semid].sem_perm.mode & SEM_ALLOC) && - sema[semid].sem_perm.key == key) + if ((sema[semid].u.sem_perm.mode & SEM_ALLOC) && + sema[semid].u.sem_perm.key == key) break; } if (semid < seminfo.semmni) { DPRINTF(("found public key\n")); - if ((error = ipcperm(td, &sema[semid].sem_perm, + if ((error = ipcperm(td, &sema[semid].u.sem_perm, semflg & 0700))) { goto done2; } - if (nsems > 0 && sema[semid].sem_nsems < nsems) { + if (nsems > 0 && sema[semid].u.sem_nsems < nsems) { DPRINTF(("too small\n")); error = EINVAL; goto done2; @@ -798,11 +887,17 @@ error = EEXIST; goto done2; } +#ifdef MAC + if(( error = mac_check_ipc_semget(cred,&sema[semid]) )) { + DPRINTF(("MAC Framework: mac_check_ipc_semget access denied\n")); + goto done2; + } +#endif goto found; } } - DPRINTF(("need to allocate the semid_ds\n")); + DPRINTF(("need to allocate the semid_kernel \n")); if (key == IPC_PRIVATE || (semflg & IPC_CREAT)) { if (nsems <= 0 || nsems > seminfo.semmsl) { DPRINTF(("nsems out of range (0<%d<=%d)\n", nsems, @@ -818,31 +913,34 @@ goto done2; } for (semid = 0; semid < seminfo.semmni; semid++) { - if ((sema[semid].sem_perm.mode & SEM_ALLOC) == 0) + if ((sema[semid].u.sem_perm.mode & SEM_ALLOC) == 0) break; } if (semid == seminfo.semmni) { - DPRINTF(("no more semid_ds's available\n")); + DPRINTF(("no more semid_kernel 's available\n")); error = ENOSPC; goto done2; } DPRINTF(("semid %d is available\n", semid)); - sema[semid].sem_perm.key = key; - sema[semid].sem_perm.cuid = cred->cr_uid; - sema[semid].sem_perm.uid = cred->cr_uid; - sema[semid].sem_perm.cgid = cred->cr_gid; - sema[semid].sem_perm.gid = cred->cr_gid; - sema[semid].sem_perm.mode = (semflg & 0777) | SEM_ALLOC; - sema[semid].sem_perm.seq = - (sema[semid].sem_perm.seq + 1) & 0x7fff; - sema[semid].sem_nsems = nsems; - sema[semid].sem_otime = 0; - sema[semid].sem_ctime = time_second; - sema[semid].sem_base = &sem[semtot]; + sema[semid].u.sem_perm.key = key; + sema[semid].u.sem_perm.cuid = cred->cr_uid; + sema[semid].u.sem_perm.uid = cred->cr_uid; + sema[semid].u.sem_perm.cgid = cred->cr_gid; + sema[semid].u.sem_perm.gid = cred->cr_gid; + sema[semid].u.sem_perm.mode = (semflg & 0777) | SEM_ALLOC; + sema[semid].u.sem_perm.seq = + (sema[semid].u.sem_perm.seq + 1) & 0x7fff; + sema[semid].u.sem_nsems = nsems; + sema[semid].u.sem_otime = 0; + sema[semid].u.sem_ctime = time_second; + sema[semid].u.sem_base = &sem[semtot]; semtot += nsems; - bzero(sema[semid].sem_base, - sizeof(sema[semid].sem_base[0])*nsems); - DPRINTF(("sembase = 0x%x, next = 0x%x\n", sema[semid].sem_base, + bzero(sema[semid].u.sem_base, + sizeof(sema[semid].u.sem_base[0])*nsems); +#ifdef MAC + mac_create_ipc_sema(cred, &sema[semid]); +#endif + DPRINTF(("sembase = 0x%x, next = 0x%x\n", sema[semid].u.sem_base, &sem[semtot])); } else { DPRINTF(("didn't find it and wasn't asked to create it\n")); @@ -851,9 +949,12 @@ } found: - td->td_retval[0] = IXSEQ_TO_IPCID(semid, sema[semid].sem_perm); + td->td_retval[0] = IXSEQ_TO_IPCID(semid, sema[semid].u.sem_perm); done2: mtx_unlock(&Giant); + mtx_lock(&refcnt_mtx); + refcount--; /* Indicate that thread no longer active in the code-path */ + mtx_unlock(&refcnt_mtx); return (error); } @@ -876,7 +977,7 @@ int semid = uap->semid; size_t nsops = uap->nsops; struct sembuf *sops; - struct semid_ds *semaptr; + struct semid_kernel *semakptr; struct sembuf *sopptr = 0; struct sem *semptr = 0; struct sem_undo *suptr; @@ -890,33 +991,45 @@ 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); + semid = IPCID_TO_IX(semid); /* Convert back to zero origin */ - if (semid < 0 || semid >= seminfo.semmni) - return (EINVAL); + if (semid < 0 || semid >= seminfo.semmni) { + error = EINVAL; + goto done3; + } /* Allocate memory for sem_ops */ if (nsops > seminfo.semopm) { DPRINTF(("too many sops (max=%d, nsops=%d)\n", seminfo.semopm, nsops)); - return (E2BIG); + error = E2BIG; + goto done3; } sops = malloc(nsops * sizeof(sops[0]), M_SEM, M_WAITOK); if ((error = copyin(uap->sops, sops, nsops * sizeof(sops[0]))) != 0) { DPRINTF(("error = %d from copyin(%08x, %08x, %d)\n", error, uap->sops, sops, nsops * sizeof(sops[0]))); free(sops, M_SEM); - return (error); + goto done3; } - semaptr = &sema[semid]; + semakptr = &sema[semid]; sema_mtxp = &sema_mtx[semid]; mtx_lock(sema_mtxp); - if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0) { + if ((semakptr->u.sem_perm.mode & SEM_ALLOC) == 0) { error = EINVAL; goto done2; } - if (semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid)) { + if (semakptr->u.sem_perm.seq != IPCID_TO_SEQ(uap->semid)) { error = EINVAL; goto done2; } @@ -929,7 +1042,7 @@ do_undos = 0; for (i = 0; i < nsops; i++) { sopptr = &sops[i]; - if (sopptr->sem_num >= semaptr->sem_nsems) { + if (sopptr->sem_num >= semakptr->u.sem_nsems) { error = EFBIG; goto done2; } @@ -938,10 +1051,20 @@ j |= (sopptr->sem_op == 0) ? SEM_R : SEM_A; } - if ((error = ipcperm(td, &semaptr->sem_perm, j))) { + if ((error = ipcperm(td, &semakptr->u.sem_perm, j))) { DPRINTF(("error = %d from ipaccess\n", error)); goto done2; } +#ifdef MAC + /* + * The MAC hook checks whether the thread has read ( and possibly write) + * permissions to the semaphore array based on the sopptr->sem_op value. + */ + if ((error = mac_check_ipc_semop(td->td_ucred, semakptr, j))) { + DPRINTF(("MAC Framework: mac_check_ipc_semop access denied\n")); + goto done2; + } +#endif /* * Loop trying to satisfy the vector of requests. @@ -958,12 +1081,12 @@ for (i = 0; i < nsops; i++) { sopptr = &sops[i]; - semptr = &semaptr->sem_base[sopptr->sem_num]; + semptr = &semakptr->u.sem_base[sopptr->sem_num]; DPRINTF(( - "semop: semaptr=%x, sem_base=%x, " + "semop: semakptr=%x, sem_base=%x, " "semptr=%x, sem[%d]=%d : op=%d, flag=%s\n", - semaptr, semaptr->sem_base, semptr, + semakptr, semakptr->u.sem_base, semptr, sopptr->sem_num, semptr->semval, sopptr->sem_op, (sopptr->sem_flg & IPC_NOWAIT) ? "nowait" : "wait")); @@ -1005,7 +1128,7 @@ */ DPRINTF(("semop: rollback 0 through %d\n", i-1)); for (j = 0; j < i; j++) - semaptr->sem_base[sops[j].sem_num].semval -= + semakptr->u.sem_base[sops[j].sem_num].semval -= sops[j].sem_op; /* If we detected an error, return it */ @@ -1027,7 +1150,7 @@ semptr->semncnt++; DPRINTF(("semop: good night!\n")); - error = msleep(semaptr, sema_mtxp, (PZERO - 4) | PCATCH, + error = msleep(semakptr, sema_mtxp, (PZERO - 4) | PCATCH, "semwait", 0); DPRINTF(("semop: good morning (error=%d)!\n", error)); @@ -1040,8 +1163,8 @@ /* * Make sure that the semaphore still exists */ - if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0 || - semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid)) { + if ((semakptr->u.sem_perm.mode & SEM_ALLOC) == 0 || + semakptr->u.sem_perm.seq != IPCID_TO_SEQ(uap->semid)) { error = EIDRM; goto done2; } @@ -1102,7 +1225,7 @@ } for (j = 0; j < nsops; j++) - semaptr->sem_base[sops[j].sem_num].semval -= + semakptr->u.sem_base[sops[j].sem_num].semval -= sops[j].sem_op; DPRINTF(("error = %d from semundo_adjust\n", error)); @@ -1115,10 +1238,10 @@ /* We're definitely done - set the sempid's and time */ for (i = 0; i < nsops; i++) { sopptr = &sops[i]; - semptr = &semaptr->sem_base[sopptr->sem_num]; + semptr = &semakptr->u.sem_base[sopptr->sem_num]; semptr->sempid = td->td_proc->p_pid; } - semaptr->sem_otime = time_second; + semakptr->u.sem_otime = time_second; /* * Do a wakeup if any semaphore was up'd whilst something was @@ -1126,7 +1249,7 @@ */ if (do_wakeup) { DPRINTF(("semop: doing wakeup\n")); - wakeup(semaptr); + wakeup(semakptr); DPRINTF(("semop: back from wakeup\n")); } DPRINTF(("semop: done\n")); @@ -1134,6 +1257,10 @@ done2: mtx_unlock(sema_mtxp); free(sops, M_SEM); +done3: + mtx_lock(&refcnt_mtx); + refcount--; /* Indicate that thread no longer active in the code-path */ + mtx_unlock(&refcnt_mtx); return (error); } @@ -1176,16 +1303,16 @@ int semid = suptr->un_ent[ix].un_id; int semnum = suptr->un_ent[ix].un_num; int adjval = suptr->un_ent[ix].un_adjval; - struct semid_ds *semaptr; + struct semid_kernel *semakptr; struct mtx *sema_mtxp; - semaptr = &sema[semid]; + semakptr = &sema[semid]; sema_mtxp = &sema_mtx[semid]; mtx_lock(sema_mtxp); SEMUNDO_LOCK(); - if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0) + if ((semakptr->u.sem_perm.mode & SEM_ALLOC) == 0) panic("semexit - semid not allocated"); - if (semnum >= semaptr->sem_nsems) + if (semnum >= semakptr->u.sem_nsems) panic("semexit - semnum out of range"); DPRINTF(( @@ -1193,18 +1320,18 @@ suptr->un_proc, suptr->un_ent[ix].un_id, suptr->un_ent[ix].un_num, suptr->un_ent[ix].un_adjval, - semaptr->sem_base[semnum].semval)); + semakptr->u.sem_base[semnum].semval)); if (adjval < 0) { - if (semaptr->sem_base[semnum].semval < -adjval) - semaptr->sem_base[semnum].semval = 0; + if (semakptr->u.sem_base[semnum].semval < -adjval) + semakptr->u.sem_base[semnum].semval = 0; else - semaptr->sem_base[semnum].semval += + semakptr->u.sem_base[semnum].semval += adjval; } else - semaptr->sem_base[semnum].semval += adjval; + semakptr->u.sem_base[semnum].semval += adjval; - wakeup(semaptr); + wakeup(semakptr); DPRINTF(("semexit: back from wakeup\n")); mtx_unlock(sema_mtxp); SEMUNDO_UNLOCK(); --- //depot/projects/trustedbsd/mac/sys/kern/sysv_shm.c 2003/05/05 17:13:02 +++ //depot/user/hdandeka/rishi_SystemVIPC/sys/kern/sysv_shm.c 2003/06/20 08:44:14 @@ -33,6 +33,7 @@ #include "opt_compat.h" #include "opt_sysvipc.h" +#include "opt_mac.h" #include #include @@ -50,6 +51,10 @@ #include #include #include +#ifdef MAC +#include +#include +#endif #include #include @@ -82,7 +87,9 @@ #define SHMSEG_WANTED 0x1000 static int shm_last_free, shm_nused, shm_committed, shmalloced; -static struct shmid_ds *shmsegs; +static struct shmid_kernel *shmsegs; +static int refcount; /* to ensure consistency during and after shmunload */ +static struct mtx refcnt_mtx; /* global mutex for refcount. */ struct shm_handle { /* vm_offset_t kva; */ @@ -94,15 +101,16 @@ int shmid; }; -static void shm_deallocate_segment(struct shmid_ds *); +static void shm_deallocate_segment(struct shmid_kernel *); static int shm_find_segment_by_key(key_t); -static struct shmid_ds *shm_find_segment_by_shmid(int, int); -static struct shmid_ds *shm_find_segment_by_shmidx(int, int); +static struct shmid_kernel *shm_find_segment_by_shmid(int, int); +static struct shmid_kernel *shm_find_segment_by_shmidx(int, int); static int shm_delete_mapping(struct vmspace *vm, struct shmmap_state *); static void shmrealloc(void); static void shminit(void); static int sysvshm_modload(struct module *, int, void *); static int shmunload(void); +/* TODO: Look at the following functions w.r.t. the MAC framework */ static void shmexit_myhook(struct vmspace *vm); static void shmfork_myhook(struct proc *p1, struct proc *p2); static int sysctl_shmsegs(SYSCTL_HANDLER_ARGS); @@ -157,66 +165,70 @@ int i; for (i = 0; i < shmalloced; i++) - if ((shmsegs[i].shm_perm.mode & SHMSEG_ALLOCATED) && - shmsegs[i].shm_perm.key == key) + if ((shmsegs[i].u.shm_perm.mode & SHMSEG_ALLOCATED) && + shmsegs[i].u.shm_perm.key == key) return (i); return (-1); } -static struct shmid_ds * +static struct shmid_kernel * shm_find_segment_by_shmid(int shmid, int wantrem) { int segnum; - struct shmid_ds *shmseg; + struct shmid_kernel *shmseg; segnum = IPCID_TO_IX(shmid); if (segnum < 0 || segnum >= shmalloced) return (NULL); shmseg = &shmsegs[segnum]; - if (!((shmseg->shm_perm.mode & SHMSEG_ALLOCATED) || - (wantrem && !(shmseg->shm_perm.mode & SHMSEG_REMOVED))) || - shmseg->shm_perm.seq != IPCID_TO_SEQ(shmid)) + if (!((shmseg->u.shm_perm.mode & SHMSEG_ALLOCATED) || + (wantrem && !(shmseg->u.shm_perm.mode & SHMSEG_REMOVED))) || + shmseg->u.shm_perm.seq != IPCID_TO_SEQ(shmid)) return (NULL); return (shmseg); } -static struct shmid_ds * +static struct shmid_kernel * shm_find_segment_by_shmidx(int segnum, int wantrem) { - struct shmid_ds *shmseg; + struct shmid_kernel *shmseg; if (segnum < 0 || segnum >= shmalloced) return (NULL); shmseg = &shmsegs[segnum]; - if (!((shmseg->shm_perm.mode & SHMSEG_ALLOCATED) || - (wantrem && !(shmseg->shm_perm.mode & SHMSEG_REMOVED)))) + if (!((shmseg->u.shm_perm.mode & SHMSEG_ALLOCATED) || + (wantrem && !(shmseg->u.shm_perm.mode & SHMSEG_REMOVED)))) return (NULL); return (shmseg); } static void shm_deallocate_segment(shmseg) - struct shmid_ds *shmseg; + struct shmid_kernel *shmseg; { struct shm_handle *shm_handle; size_t size; GIANT_REQUIRED; - shm_handle = shmseg->shm_internal; + shm_handle = shmseg->u.shm_internal; vm_object_deallocate(shm_handle->shm_object); free(shm_handle, M_SHM); - shmseg->shm_internal = NULL; - size = round_page(shmseg->shm_segsz); + shmseg->u.shm_internal = NULL; + size = round_page(shmseg->u.shm_segsz); shm_committed -= btoc(size); shm_nused--; - shmseg->shm_perm.mode = SHMSEG_FREE; + shmseg->u.shm_perm.mode = SHMSEG_FREE; +#ifdef MAC + /* XXX: Reset the MAC label */ + mac_cleanup_ipc_shm(shmseg); +#endif } static int shm_delete_mapping(struct vmspace *vm, struct shmmap_state *shmmap_s) { - struct shmid_ds *shmseg; + struct shmid_kernel *shmseg; int segnum, result; size_t size; @@ -224,14 +236,14 @@ segnum = IPCID_TO_IX(shmmap_s->shmid); shmseg = &shmsegs[segnum]; - size = round_page(shmseg->shm_segsz); + size = round_page(shmseg->u.shm_segsz); result = vm_map_remove(&vm->vm_map, shmmap_s->va, shmmap_s->va + size); if (result != KERN_SUCCESS) return (EINVAL); shmmap_s->shmid = -1; - shmseg->shm_dtime = time_second; - if ((--shmseg->shm_nattch <= 0) && - (shmseg->shm_perm.mode & SHMSEG_REMOVED)) { + shmseg->u.shm_dtime = time_second; + if ((--shmseg->u.shm_nattch <= 0) && + (shmseg->u.shm_perm.mode & SHMSEG_REMOVED)) { shm_deallocate_segment(shmseg); shm_last_free = segnum; } @@ -259,6 +271,16 @@ 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(&Giant); shmmap_s = p->p_vmspace->vm_shm; if (shmmap_s == NULL) { @@ -275,9 +297,21 @@ error = EINVAL; goto done2; } +#ifdef MAC + /* XXX It might be useful to move this into the shm_delete_mapping function */ + struct shmid_kernel *shmsegptr; + shmsegptr = &shmsegs[IPCID_TO_IX(shmmap_s->shmid)]; + if(( error = mac_check_ipc_shmdt(td->td_ucred, shmsegptr) )) { + printf(("MAC Framework: mac_check_ipc_shmdt access denied\n")); + goto done2; + } +#endif error = shm_delete_mapping(p->p_vmspace, shmmap_s); done2: mtx_unlock(&Giant); + mtx_lock(&refcnt_mtx); + refcount--; /* Indicate that thread no longer active in the code-path */ + mtx_unlock(&refcnt_mtx); return (error); } @@ -302,7 +336,7 @@ { struct proc *p = td->td_proc; int i, flags; - struct shmid_ds *shmseg; + struct shmid_kernel *shmseg; struct shmmap_state *shmmap_s = NULL; struct shm_handle *shm_handle; vm_offset_t attach_va; @@ -313,6 +347,16 @@ 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(&Giant); shmmap_s = p->p_vmspace->vm_shm; if (shmmap_s == NULL) { @@ -327,10 +371,16 @@ error = EINVAL; goto done2; } - error = ipcperm(td, &shmseg->shm_perm, + error = ipcperm(td, &shmseg->u.shm_perm, (shmflg & SHM_RDONLY) ? IPC_R : IPC_R|IPC_W); if (error) goto done2; +#ifdef MAC + if(( error = mac_check_ipc_shmat(td->td_ucred, shmseg, shmflg) )) { + printf(("MAC Framework: mac_check_ipc_shmat access denied\n")); + goto done2; + } +#endif for (i = 0; i < shminfo.shmseg; i++) { if (shmmap_s->shmid == -1) break; @@ -340,7 +390,7 @@ error = EMFILE; goto done2; } - size = round_page(shmseg->shm_segsz); + size = round_page(shmseg->u.shm_segsz); #ifdef VM_PROT_READ_IS_EXEC prot = VM_PROT_READ | VM_PROT_EXECUTE; #else @@ -368,7 +418,7 @@ + maxtsiz + maxdsiz); } - shm_handle = shmseg->shm_internal; + shm_handle = shmseg->u.shm_internal; vm_object_reference(shm_handle->shm_object); rv = vm_map_find(&p->p_vmspace->vm_map, shm_handle->shm_object, 0, &attach_va, size, (flags & MAP_FIXED)?0:1, prot, prot, 0); @@ -381,12 +431,15 @@ shmmap_s->va = attach_va; shmmap_s->shmid = shmid; - shmseg->shm_lpid = p->p_pid; - shmseg->shm_atime = time_second; - shmseg->shm_nattch++; + shmseg->u.shm_lpid = p->p_pid; + shmseg->u.shm_atime = time_second; + shmseg->u.shm_nattch++; td->td_retval[0] = attach_va; done2: mtx_unlock(&Giant); + mtx_lock(&refcnt_mtx); + refcount--; /* Indicate that thread no longer active in the code-path */ + mtx_unlock(&refcnt_mtx); return (error); } @@ -426,11 +479,21 @@ { #ifdef COMPAT_43 int error = 0; - struct shmid_ds *shmseg; + struct shmid_kernel *shmseg; struct oshmid_ds outbuf; 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(&Giant); shmseg = shm_find_segment_by_shmid(uap->shmid, 0); if (shmseg == NULL) { @@ -439,18 +502,24 @@ } switch (uap->cmd) { case IPC_STAT: - error = ipcperm(td, &shmseg->shm_perm, IPC_R); + error = ipcperm(td, &shmseg->u.shm_perm, IPC_R); if (error) goto done2; - outbuf.shm_perm = shmseg->shm_perm; - outbuf.shm_segsz = shmseg->shm_segsz; - outbuf.shm_cpid = shmseg->shm_cpid; - outbuf.shm_lpid = shmseg->shm_lpid; - outbuf.shm_nattch = shmseg->shm_nattch; - outbuf.shm_atime = shmseg->shm_atime; - outbuf.shm_dtime = shmseg->shm_dtime; - outbuf.shm_ctime = shmseg->shm_ctime; - outbuf.shm_handle = shmseg->shm_internal; +#ifdef MAC + if(( error = mac_check_ipc_shmctl(td->td_ucred, shmseg, uap->cmd) )) { + printf(("MAC Framework: mac_check_ipc_shmctl access denied\n")); + goto done2; + } +#endif + outbuf.shm_perm = shmseg->u.shm_perm; + outbuf.shm_segsz = shmseg->u.shm_segsz; + outbuf.shm_cpid = shmseg->u.shm_cpid; + outbuf.shm_lpid = shmseg->u.shm_lpid; + outbuf.shm_nattch = shmseg->u.shm_nattch; + outbuf.shm_atime = shmseg->u.shm_atime; + outbuf.shm_dtime = shmseg->u.shm_dtime; + outbuf.shm_ctime = shmseg->u.shm_ctime; + outbuf.shm_handle = shmseg->u.shm_internal; error = copyout(&outbuf, uap->ubuf, sizeof(outbuf)); if (error) goto done2; @@ -462,6 +531,9 @@ } done2: mtx_unlock(&Giant); + mtx_lock(&refcnt_mtx); + refcount--; /* Indicate that thread no longer active in the code-path */ + mtx_unlock(&refcnt_mtx); return (error); #else return (EINVAL); @@ -489,11 +561,20 @@ int wantrem; { int error = 0; - struct shmid_ds *shmseg; + struct shmid_kernel *shmseg; 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(&Giant); switch (cmd) { case IPC_INFO: @@ -525,40 +606,46 @@ error = EINVAL; goto done2; } +#ifdef MAC + if(( error = mac_check_ipc_shmctl(td->td_ucred, shmseg, cmd) )) { + printf(("MAC Framework: mac_check_ipc_shmctl access denied\n")); + goto done2; + } +#endif switch (cmd) { case SHM_STAT: case IPC_STAT: - error = ipcperm(td, &shmseg->shm_perm, IPC_R); + error = ipcperm(td, &shmseg->u.shm_perm, IPC_R); if (error) goto done2; - memcpy(buf, shmseg, sizeof(struct shmid_ds)); + memcpy(buf, &shmseg->u, sizeof(struct shmid_ds)); if (bufsz) *bufsz = sizeof(struct shmid_ds); if (cmd == SHM_STAT) - td->td_retval[0] = IXSEQ_TO_IPCID(shmid, shmseg->shm_perm); + td->td_retval[0] = IXSEQ_TO_IPCID(shmid, shmseg->u.shm_perm); break; case IPC_SET: { struct shmid_ds *shmid; shmid = (struct shmid_ds *)buf; - error = ipcperm(td, &shmseg->shm_perm, IPC_M); + error = ipcperm(td, &shmseg->u.shm_perm, IPC_M); if (error) goto done2; - shmseg->shm_perm.uid = shmid->shm_perm.uid; - shmseg->shm_perm.gid = shmid->shm_perm.gid; - shmseg->shm_perm.mode = - (shmseg->shm_perm.mode & ~ACCESSPERMS) | + shmseg->u.shm_perm.uid = shmid->shm_perm.uid; + shmseg->u.shm_perm.gid = shmid->shm_perm.gid; + shmseg->u.shm_perm.mode = + (shmseg->u.shm_perm.mode & ~ACCESSPERMS) | (shmid->shm_perm.mode & ACCESSPERMS); - shmseg->shm_ctime = time_second; + shmseg->u.shm_ctime = time_second; break; } case IPC_RMID: - error = ipcperm(td, &shmseg->shm_perm, IPC_M); + error = ipcperm(td, &shmseg->u.shm_perm, IPC_M); if (error) goto done2; - shmseg->shm_perm.key = IPC_PRIVATE; - shmseg->shm_perm.mode |= SHMSEG_REMOVED; - if (shmseg->shm_nattch <= 0) { + shmseg->u.shm_perm.key = IPC_PRIVATE; + shmseg->u.shm_perm.mode |= SHMSEG_REMOVED; + if (shmseg->u.shm_nattch <= 0) { shm_deallocate_segment(shmseg); shm_last_free = IPCID_TO_IX(shmid); } @@ -573,6 +660,9 @@ } done2: mtx_unlock(&Giant); + mtx_lock(&refcnt_mtx); + refcount--; /* Indicate that thread no longer active in the code-path */ + mtx_unlock(&refcnt_mtx); return (error); } @@ -629,17 +719,17 @@ int mode; int segnum; { - struct shmid_ds *shmseg; + struct shmid_kernel *shmseg; int error; shmseg = &shmsegs[segnum]; - if (shmseg->shm_perm.mode & SHMSEG_REMOVED) { + if (shmseg->u.shm_perm.mode & SHMSEG_REMOVED) { /* * This segment is in the process of being allocated. Wait * until it's done, and look the key up again (in case the * allocation failed or it was freed). */ - shmseg->shm_perm.mode |= SHMSEG_WANTED; + shmseg->u.shm_perm.mode |= SHMSEG_WANTED; error = tsleep(shmseg, PLOCK | PCATCH, "shmget", 0); if (error) return (error); @@ -647,12 +737,17 @@ } if ((uap->shmflg & (IPC_CREAT | IPC_EXCL)) == (IPC_CREAT | IPC_EXCL)) return (EEXIST); - error = ipcperm(td, &shmseg->shm_perm, mode); + error = ipcperm(td, &shmseg->u.shm_perm, mode); +#ifdef MAC + if(( error = mac_check_ipc_shmget(td->td_ucred,shmseg,uap->shmflg) )) { + printf(("MAC Framework: mac_check_ipc_shmget access denied\n")); + } +#endif if (error) return (error); - if (uap->size && uap->size > shmseg->shm_segsz) + if (uap->size && uap->size > shmseg->u.shm_segsz) return (EINVAL); - td->td_retval[0] = IXSEQ_TO_IPCID(segnum, shmseg->shm_perm); + td->td_retval[0] = IXSEQ_TO_IPCID(segnum, shmseg->u.shm_perm); return (0); } @@ -664,7 +759,7 @@ { int i, segnum, shmid, size; struct ucred *cred = td->td_ucred; - struct shmid_ds *shmseg; + struct shmid_kernel *shmseg; struct shm_handle *shm_handle; GIANT_REQUIRED; @@ -679,7 +774,7 @@ if (shm_last_free < 0) { shmrealloc(); /* Maybe expand the shmsegs[] array. */ for (i = 0; i < shmalloced; i++) - if (shmsegs[i].shm_perm.mode & SHMSEG_FREE) + if (shmsegs[i].u.shm_perm.mode & SHMSEG_FREE) break; if (i == shmalloced) return (ENOSPC); @@ -693,12 +788,12 @@ * In case we sleep in malloc(), mark the segment present but deleted * so that noone else tries to create the same key. */ - shmseg->shm_perm.mode = SHMSEG_ALLOCATED | SHMSEG_REMOVED; - shmseg->shm_perm.key = uap->key; - shmseg->shm_perm.seq = (shmseg->shm_perm.seq + 1) & 0x7fff; + shmseg->u.shm_perm.mode = SHMSEG_ALLOCATED | SHMSEG_REMOVED; + shmseg->u.shm_perm.key = uap->key; + shmseg->u.shm_perm.seq = (shmseg->u.shm_perm.seq + 1) & 0x7fff; shm_handle = (struct shm_handle *) malloc(sizeof(struct shm_handle), M_SHM, M_WAITOK); - shmid = IXSEQ_TO_IPCID(segnum, shmseg->shm_perm); + shmid = IXSEQ_TO_IPCID(segnum, shmseg->u.shm_perm); /* * We make sure that we have allocated a pager before we need @@ -716,24 +811,27 @@ vm_object_set_flag(shm_handle->shm_object, OBJ_NOSPLIT); VM_OBJECT_UNLOCK(shm_handle->shm_object); - shmseg->shm_internal = shm_handle; - shmseg->shm_perm.cuid = shmseg->shm_perm.uid = cred->cr_uid; - shmseg->shm_perm.cgid = shmseg->shm_perm.gid = cred->cr_gid; - shmseg->shm_perm.mode = (shmseg->shm_perm.mode & SHMSEG_WANTED) | + shmseg->u.shm_internal = shm_handle; + shmseg->u.shm_perm.cuid = shmseg->u.shm_perm.uid = cred->cr_uid; + shmseg->u.shm_perm.cgid = shmseg->u.shm_perm.gid = cred->cr_gid; + shmseg->u.shm_perm.mode = (shmseg->u.shm_perm.mode & SHMSEG_WANTED) | (mode & ACCESSPERMS) | SHMSEG_ALLOCATED; - shmseg->shm_segsz = uap->size; - shmseg->shm_cpid = td->td_proc->p_pid; - shmseg->shm_lpid = shmseg->shm_nattch = 0; - shmseg->shm_atime = shmseg->shm_dtime = 0; - shmseg->shm_ctime = time_second; + shmseg->u.shm_segsz = uap->size; + shmseg->u.shm_cpid = td->td_proc->p_pid; + shmseg->u.shm_lpid = shmseg->u.shm_nattch = 0; + shmseg->u.shm_atime = shmseg->u.shm_dtime = 0; +#ifdef MAC + mac_create_ipc_shm(cred, shmseg); +#endif + shmseg->u.shm_ctime = time_second; shm_committed += btoc(size); shm_nused++; - if (shmseg->shm_perm.mode & SHMSEG_WANTED) { + if (shmseg->u.shm_perm.mode & SHMSEG_WANTED) { /* * Somebody else wanted this key while we were asleep. Wake * them up now. */ - shmseg->shm_perm.mode &= ~SHMSEG_WANTED; + shmseg->u.shm_perm.mode &= ~SHMSEG_WANTED; wakeup(shmseg); } td->td_retval[0] = shmid; @@ -753,6 +851,16 @@ 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(&Giant); mode = uap->shmflg & ACCESSPERMS; if (uap->key != IPC_PRIVATE) { @@ -772,6 +880,9 @@ error = shmget_allocate_segment(td, uap, mode); done2: mtx_unlock(&Giant); + mtx_lock(&refcnt_mtx); + refcount--; /* Indicate that thread no longer active in the code-path */ + mtx_unlock(&refcnt_mtx); return (error); } @@ -815,7 +926,7 @@ p2->p_vmspace->vm_shm = shmmap_s; for (i = 0; i < shminfo.shmseg; i++, shmmap_s++) if (shmmap_s->shmid != -1) - shmsegs[IPCID_TO_IX(shmmap_s->shmid)].shm_nattch++; + shmsegs[IPCID_TO_IX(shmmap_s->shmid)].u.shm_nattch++; } static void @@ -830,6 +941,7 @@ vm->vm_shm = NULL; for (i = 0, shm = base; i < shminfo.shmseg; i++, shm++) { if (shm->shmid != -1) + /* XXX: Should the MAC framework enforce check here as well */ shm_delete_mapping(vm, shm); } free(base, M_SHM); @@ -840,7 +952,7 @@ shmrealloc(void) { int i; - struct shmid_ds *newsegs; + struct shmid_kernel *newsegs; if (shmalloced >= shminfo.shmmni) return; @@ -851,8 +963,11 @@ for (i = 0; i < shmalloced; i++) bcopy(&shmsegs[i], &newsegs[i], sizeof(newsegs[0])); for (; i < shminfo.shmmni; i++) { - shmsegs[i].shm_perm.mode = SHMSEG_FREE; - shmsegs[i].shm_perm.seq = 0; + shmsegs[i].u.shm_perm.mode = SHMSEG_FREE; + shmsegs[i].u.shm_perm.seq = 0; +#ifdef MAC + mac_init_ipc_shm(&shmsegs[i]); +#endif } free(shmsegs, M_SHM); shmsegs = newsegs; @@ -880,23 +995,53 @@ if (shmsegs == NULL) panic("cannot allocate initial memory for sysvshm"); for (i = 0; i < shmalloced; i++) { - shmsegs[i].shm_perm.mode = SHMSEG_FREE; - shmsegs[i].shm_perm.seq = 0; + shmsegs[i].u.shm_perm.mode = SHMSEG_FREE; + shmsegs[i].u.shm_perm.seq = 0; +#ifdef MAC + mac_init_ipc_shm(&shmsegs[i]); +#endif } shm_last_free = 0; shm_nused = 0; shm_committed = 0; shmexit_hook = &shmexit_myhook; shmfork_hook = &shmfork_myhook; + 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 shmunload, 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, "shmrefcnt", NULL, MTX_DEF); } static int shmunload() { - if (shm_nused > 0) + /* + * Make sure that the shmunload maintains the consistency of the shmsegs + * data structure. 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) || (shm_nused > 0)) { + mtx_unlock(&refcnt_mtx); return (EBUSY); + } + refcount= -1; /* Mark the module as being unloaded */ + mtx_unlock(&refcnt_mtx); +#ifdef MAC + int i; + for (i = 0; i < shmalloced; i++) + mac_destroy_ipc_shm(&shmsegs[i]); +#endif free(shmsegs, M_SHM); shmexit_hook = NULL; shmfork_hook = NULL; @@ -907,6 +1052,7 @@ sysctl_shmsegs(SYSCTL_HANDLER_ARGS) { + /* TODO: Change from shmid_ds to shmid_kernel needs to be incorporated */ return (SYSCTL_OUT(req, shmsegs, shmalloced * sizeof(shmsegs[0]))); } --- //depot/projects/trustedbsd/mac/sys/modules/sysvipc/sysvmsg/Makefile 2001/11/17 06:10:00 +++ //depot/user/hdandeka/rishi_SystemVIPC/sys/modules/sysvipc/sysvmsg/Makefile 2003/05/23 16:38:07 @@ -3,6 +3,6 @@ .PATH: ${.CURDIR}/../../../kern KMOD= sysvmsg -SRCS= sysv_msg.c opt_sysvipc.h +SRCS= sysv_msg.c opt_sysvipc.h opt_mac.h .include --- //depot/projects/trustedbsd/mac/sys/modules/sysvipc/sysvsem/Makefile 2001/11/17 06:10:00 +++ //depot/user/hdandeka/rishi_SystemVIPC/sys/modules/sysvipc/sysvsem/Makefile 2003/05/30 18:42:59 @@ -3,6 +3,6 @@ .PATH: ${.CURDIR}/../../../kern KMOD= sysvsem -SRCS= sysv_sem.c opt_sysvipc.h +SRCS= sysv_sem.c opt_sysvipc.h opt_mac.h .include --- //depot/projects/trustedbsd/mac/sys/modules/sysvipc/sysvshm/Makefile 2001/11/17 06:10:00 +++ //depot/user/hdandeka/rishi_SystemVIPC/sys/modules/sysvipc/sysvshm/Makefile 2003/06/03 19:22:59 @@ -3,7 +3,7 @@ .PATH: ${.CURDIR}/../../../kern KMOD= sysvshm -OPTS= opt_sysvipc.h opt_compat.h +OPTS= opt_sysvipc.h opt_compat.h opt_mac.h SRCS= sysv_shm.c $(OPTS) .include --- //depot/projects/trustedbsd/mac/sys/security/mac_biba/mac_biba.c 2003/06/02 12:26:58 +++ //depot/user/hdandeka/rishi_SystemVIPC/sys/security/mac_biba/mac_biba.c 2003/06/13 16:12:32 @@ -60,6 +60,10 @@ #include #include #include +#include +#include +#include +#include #include @@ -1151,6 +1155,58 @@ } /* + * Labeling event operations: System V IPC objects. + */ + +static void +mac_biba_create_ipc_msgmsg(struct ucred *cred, struct msg *msgptr, + struct label *msglabel) +{ + struct mac_biba *source, *dest; + + source = SLOT(&cred->cr_label); + dest = SLOT(msglabel); + + mac_biba_copy_single(source, dest); +} + +static void +mac_biba_create_ipc_msgqueue(struct ucred *cred, struct msqid_kernel *msqkptr, + struct label *msqlabel) +{ + struct mac_biba *source, *dest; + + source = SLOT(&cred->cr_label); + dest = SLOT(msqlabel); + + mac_biba_copy_single(source, dest); +} + +static void +mac_biba_create_ipc_sema(struct ucred *cred, struct semid_kernel *semakptr, + struct label *semalabel) +{ + struct mac_biba *source, *dest; + + source = SLOT(&cred->cr_label); + dest = SLOT(semalabel); + + mac_biba_copy_single(source, dest); +} + +static void +mac_biba_create_ipc_shm(struct ucred *cred, struct shmid_kernel *shmsegptr, + struct label *shmlabel) +{ + struct mac_biba *source, *dest; + + source = SLOT(&cred->cr_label); + dest = SLOT(shmlabel); + + mac_biba_copy_single(source, dest); +} + +/* * Labeling event operations: network objects. */ static void @@ -1427,6 +1483,33 @@ } /* + * Label cleanup/flush operations + */ +static void +mac_biba_cleanup_ipc_msgmsg(struct label *msglabel) +{ + bzero(SLOT(msglabel), sizeof(struct mac_biba)); +} + +static void +mac_biba_cleanup_ipc_msgqueue(struct label *msqlabel) +{ + bzero(SLOT(msqlabel), sizeof(struct mac_biba)); +} + +static void +mac_biba_cleanup_ipc_sema(struct label *semalabel) +{ + bzero(SLOT(semalabel), sizeof(struct mac_biba)); +} + +static void +mac_biba_cleanup_ipc_shm(struct label *shmlabel) +{ + bzero(SLOT(shmlabel), sizeof(struct mac_biba)); +} + +/* * Access control checks. */ static int @@ -1588,7 +1671,294 @@ return (mac_biba_single_in_range(p, i) ? 0 : EACCES); } + +static int +mac_biba_check_ipc_msgrcv(struct ucred *cred, struct msg *msgptr) +{ + + struct mac_biba *subj, *obj; + + if (!mac_biba_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&msgptr->label); + + if (!mac_biba_dominate_single(obj, subj)) + return (EACCES); + + return (0); +} + +static int +mac_biba_check_ipc_msgrmid(struct ucred *cred, struct msg *msgptr) +{ + + struct mac_biba *subj, *obj; + + if (!mac_biba_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&msgptr->label); + + if (!mac_biba_dominate_single(subj, obj)) + return (EACCES); + + return (0); +} + +static int +mac_biba_check_ipc_msqget(struct ucred *cred, struct msqid_kernel *msqkptr) +{ + struct mac_biba *subj, *obj; + + if (!mac_biba_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&msqkptr->label); + + if (!mac_biba_dominate_single(obj, subj)) + return (EACCES); + + return (0); +} + + +static int +mac_biba_check_ipc_msqsnd(struct ucred *cred, struct msqid_kernel *msqkptr) +{ + struct mac_biba *subj, *obj; + + if (!mac_biba_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&msqkptr->label); + + if (!mac_biba_dominate_single(subj, obj)) + return (EACCES); + + return (0); +} + +static int +mac_biba_check_ipc_msqrcv(struct ucred *cred, struct msqid_kernel *msqkptr) +{ + struct mac_biba *subj, *obj; + + if (!mac_biba_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&msqkptr->label); + + if (!mac_biba_dominate_single(obj, subj)) + return (EACCES); + + return (0); +} + + +static int +mac_biba_check_ipc_msqctl(struct ucred *cred, struct msqid_kernel *msqkptr, + int cmd) +{ + struct mac_biba *subj, *obj; + + if (!mac_biba_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&msqkptr->label); + switch(cmd) { + case IPC_RMID: + case IPC_SET: + if (!mac_biba_dominate_single(subj, obj)) + return (EACCES); + break; + case IPC_STAT: + if (!mac_biba_dominate_single(obj, subj)) + return (EACCES); + break; + default: + return (EACCES); + } + return (0); +} + static int +mac_biba_check_ipc_semctl(struct ucred *cred, struct semid_kernel *semakptr, + int cmd) +{ + struct mac_biba *subj, *obj; + + if (!mac_biba_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&semakptr->label); + switch(cmd) { + case IPC_RMID: + case IPC_SET: + case SETVAL: + case SETALL: + if (!mac_biba_dominate_single(subj, obj)) + return (EACCES); + break; + case IPC_STAT: + case GETVAL: + case GETPID: + case GETNCNT: + case GETZCNT: + case GETALL: + if (!mac_biba_dominate_single(obj, subj)) + return (EACCES); + break; + default: + return (EACCES); + } + return (0); +} + + +static int +mac_biba_check_ipc_semget(struct ucred *cred, struct semid_kernel *semakptr) +{ + struct mac_biba *subj, *obj; + + if (!mac_biba_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&semakptr->label); + + if (!mac_biba_dominate_single(obj, subj)) + return (EACCES); + + return (0); +} + + +static int +mac_biba_check_ipc_semop(struct ucred *cred, struct semid_kernel *semakptr, + size_t accesstype) +{ + struct mac_biba *subj, *obj; + + if (!mac_biba_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&semakptr->label); + + if( accesstype & SEM_R ) + if (!mac_biba_dominate_single(obj, subj)) + return (EACCES); + + if( accesstype & SEM_A ) + if (!mac_biba_dominate_single(subj, obj)) + return (EACCES); + + return (0); + +} + +static int +mac_biba_check_ipc_shmat(struct ucred *cred, struct shmid_kernel *shmsegptr, + int shmflg) +{ + struct mac_biba *subj, *obj; + + if (!mac_biba_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&shmsegptr->label); + + if (!mac_biba_dominate_single(obj, subj)) + return (EACCES); + if ((shmflg & SHM_RDONLY) == 0) + if (!mac_biba_dominate_single(subj, obj)) + return (EACCES); + + return (0); +} + +static int +mac_biba_check_ipc_shmctl(struct ucred *cred, struct shmid_kernel *shmsegptr, + int cmd) +{ + struct mac_biba *subj, *obj; + + if (!mac_biba_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&shmsegptr->label); + switch(cmd) { + case IPC_RMID: + case IPC_SET: + if (!mac_biba_dominate_single(subj, obj)) + return (EACCES); + break; + case IPC_STAT: + case SHM_STAT: + if (!mac_biba_dominate_single(obj, subj)) + return (EACCES); + break; + default: + return (EACCES); + } + return (0); +} + +#if 0 + +/* + * TODO: Do we check the integrity of the implicit write access caused + * by the bookkeeping tasks associated with the shmdt call, which may + * modify/delete the shmseg meta-data and/or the shared segment itself? + */ + +static int +mac_biba_check_ipc_shmdt(struct ucred *cred, struct shmid_kernel *shmsegptr) +{ + struct mac_biba *subj, *obj; + + if (!mac_biba_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&shmsegptr->label); + + if (!mac_biba_dominate_single(subj, obj)) + return (EACCES); + + return (0); +} +#endif + +static int +mac_biba_check_ipc_shmget(struct ucred *cred, struct shmid_kernel *shmsegptr, + int shmflg) +{ + struct mac_biba *subj, *obj; + + if (!mac_biba_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&shmsegptr->label); + + if (!mac_biba_dominate_single(obj, subj)) + return (EACCES); + + return (0); +} + +static int mac_biba_check_kld_load(struct ucred *cred, struct vnode *vp, struct label *label) { @@ -2667,6 +3037,10 @@ .mpo_init_cred_label = mac_biba_init_label, .mpo_init_devfsdirent_label = mac_biba_init_label, .mpo_init_ifnet_label = mac_biba_init_label, + .mpo_init_ipc_msgmsg_label = mac_biba_init_label, + .mpo_init_ipc_msgqueue_label = mac_biba_init_label, + .mpo_init_ipc_sema_label = mac_biba_init_label, + .mpo_init_ipc_shm_label = mac_biba_init_label, .mpo_init_ipq_label = mac_biba_init_label_waitcheck, .mpo_init_mbuf_label = mac_biba_init_label_waitcheck, .mpo_init_mount_label = mac_biba_init_label, @@ -2679,6 +3053,10 @@ .mpo_destroy_cred_label = mac_biba_destroy_label, .mpo_destroy_devfsdirent_label = mac_biba_destroy_label, .mpo_destroy_ifnet_label = mac_biba_destroy_label, + .mpo_destroy_ipc_msgmsg_label = mac_biba_destroy_label, + .mpo_destroy_ipc_msgqueue_label = mac_biba_destroy_label, + .mpo_destroy_ipc_sema_label = mac_biba_destroy_label, + .mpo_destroy_ipc_shm_label = mac_biba_destroy_label, .mpo_destroy_ipq_label = mac_biba_destroy_label, .mpo_destroy_mbuf_label = mac_biba_destroy_label, .mpo_destroy_mount_label = mac_biba_destroy_label, @@ -2725,6 +3103,10 @@ .mpo_create_datagram_from_ipq = mac_biba_create_datagram_from_ipq, .mpo_create_fragment = mac_biba_create_fragment, .mpo_create_ifnet = mac_biba_create_ifnet, + .mpo_create_ipc_msgmsg = mac_biba_create_ipc_msgmsg, + .mpo_create_ipc_msgqueue = mac_biba_create_ipc_msgqueue, + .mpo_create_ipc_sema = mac_biba_create_ipc_sema, + .mpo_create_ipc_shm = mac_biba_create_ipc_shm, .mpo_create_ipq = mac_biba_create_ipq, .mpo_create_mbuf_from_mbuf = mac_biba_create_mbuf_from_mbuf, .mpo_create_mbuf_linklayer = mac_biba_create_mbuf_linklayer, @@ -2739,11 +3121,28 @@ .mpo_create_proc0 = mac_biba_create_proc0, .mpo_create_proc1 = mac_biba_create_proc1, .mpo_relabel_cred = mac_biba_relabel_cred, + .mpo_cleanup_ipc_msgmsg = mac_biba_cleanup_ipc_msgmsg, + .mpo_cleanup_ipc_msgqueue = mac_biba_cleanup_ipc_msgqueue, + .mpo_cleanup_ipc_sema = mac_biba_cleanup_ipc_sema, + .mpo_cleanup_ipc_shm = mac_biba_cleanup_ipc_shm, .mpo_check_bpfdesc_receive = mac_biba_check_bpfdesc_receive, .mpo_check_cred_relabel = mac_biba_check_cred_relabel, .mpo_check_cred_visible = mac_biba_check_cred_visible, .mpo_check_ifnet_relabel = mac_biba_check_ifnet_relabel, .mpo_check_ifnet_transmit = mac_biba_check_ifnet_transmit, + .mpo_check_ipc_msgrcv = mac_biba_check_ipc_msgrcv, + .mpo_check_ipc_msgrmid = mac_biba_check_ipc_msgrmid, + .mpo_check_ipc_msqget = mac_biba_check_ipc_msqget, + .mpo_check_ipc_msqsnd = mac_biba_check_ipc_msqsnd, + .mpo_check_ipc_msqrcv = mac_biba_check_ipc_msqrcv, + .mpo_check_ipc_msqctl = mac_biba_check_ipc_msqctl, + .mpo_check_ipc_semctl = mac_biba_check_ipc_semctl, + .mpo_check_ipc_semget = mac_biba_check_ipc_semget, + .mpo_check_ipc_semop = mac_biba_check_ipc_semop, + .mpo_check_ipc_shmat = mac_biba_check_ipc_shmat, + .mpo_check_ipc_shmctl = mac_biba_check_ipc_shmctl, +/* .mpo_check_ipc_shmdt = mac_biba_check_ipc_shmdt, */ + .mpo_check_ipc_shmget = mac_biba_check_ipc_shmget, .mpo_check_kld_load = mac_biba_check_kld_load, .mpo_check_kld_unload = mac_biba_check_kld_unload, .mpo_check_mount_stat = mac_biba_check_mount_stat, --- //depot/projects/trustedbsd/mac/sys/security/mac_lomac/mac_lomac.c 2003/06/02 12:26:58 +++ //depot/user/hdandeka/rishi_SystemVIPC/sys/security/mac_lomac/mac_lomac.c 2003/06/13 18:14:49 @@ -60,6 +60,10 @@ #include #include #include +#include +#include +#include +#include #include @@ -1223,6 +1227,59 @@ } /* + * Labeling event operations: System V IPC objects. + */ + +static void +mac_lomac_create_ipc_msgmsg(struct ucred *cred, struct msg *msgptr, + struct label *msglabel) +{ + struct mac_lomac *source, *dest; + + source = SLOT(&cred->cr_label); + dest = SLOT(msglabel); + + mac_lomac_copy_single(source, dest); +} + +static void +mac_lomac_create_ipc_msgqueue(struct ucred *cred, struct msqid_kernel *msqkptr, + struct label *msqlabel) +{ + struct mac_lomac *source, *dest; + + source = SLOT(&cred->cr_label); + dest = SLOT(msqlabel); + + mac_lomac_copy_single(source, dest); +} + +static void +mac_lomac_create_ipc_sema(struct ucred *cred, struct semid_kernel *semakptr, + struct label *semalabel) +{ + struct mac_lomac *source, *dest; + + source = SLOT(&cred->cr_label); + dest = SLOT(semalabel); + + mac_lomac_copy_single(source, dest); +} + +static void +mac_lomac_create_ipc_shm(struct ucred *cred, struct shmid_kernel *shmsegptr, + struct label *shmlabel) +{ + struct mac_lomac *source, *dest; + + source = SLOT(&cred->cr_label); + dest = SLOT(shmlabel); + + mac_lomac_copy_single(source, dest); +} + + +/* * Labeling event operations: network objects. */ static void @@ -1568,6 +1625,34 @@ } /* + * Label cleanup/flush operations + */ +static void +mac_lomac_cleanup_ipc_msgmsg(struct label *msglabel) +{ + bzero(SLOT(msglabel), sizeof(struct mac_lomac)); +} + +static void +mac_lomac_cleanup_ipc_msgqueue(struct label *msqlabel) +{ + bzero(SLOT(msqlabel), sizeof(struct mac_lomac)); +} + +static void +mac_lomac_cleanup_ipc_sema(struct label *semalabel) +{ + bzero(SLOT(semalabel), sizeof(struct mac_lomac)); +} + +static void +mac_lomac_cleanup_ipc_shm(struct label *shmlabel) +{ + bzero(SLOT(shmlabel), sizeof(struct mac_lomac)); +} + + +/* * Access control checks. */ static int @@ -1742,6 +1827,292 @@ } static int +mac_lomac_check_ipc_msgrcv(struct ucred *cred, struct msg *msgptr) +{ + + struct mac_lomac *subj, *obj; + + if (!mac_lomac_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&msgptr->label); + + if (!mac_lomac_dominate_single(obj, subj)) + return (maybe_demote(subj, obj, "msgrcv", "msg", NULL)); + + return (0); +} + +static int +mac_lomac_check_ipc_msgrmid(struct ucred *cred, struct msg *msgptr) +{ + + struct mac_lomac *subj, *obj; + + if (!mac_lomac_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&msgptr->label); + + if (!mac_lomac_dominate_single(subj, obj)) + return (EACCES); + + return (0); +} + +static int +mac_lomac_check_ipc_msqget(struct ucred *cred, struct msqid_kernel *msqkptr) +{ + struct mac_lomac *subj, *obj; + + if (!mac_lomac_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&msqkptr->label); + + if (!mac_lomac_dominate_single(obj, subj)) + return (maybe_demote(subj, obj, "msqget", "msg", NULL)); + + return (0); +} + + +static int +mac_lomac_check_ipc_msqsnd(struct ucred *cred, struct msqid_kernel *msqkptr) +{ + struct mac_lomac *subj, *obj; + + if (!mac_lomac_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&msqkptr->label); + + if (!mac_lomac_dominate_single(subj, obj)) + return (EACCES); + + return (0); +} + +static int +mac_lomac_check_ipc_msqrcv(struct ucred *cred, struct msqid_kernel *msqkptr) +{ + struct mac_lomac *subj, *obj; + + if (!mac_lomac_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&msqkptr->label); + + if (!mac_lomac_dominate_single(obj, subj)) + return (maybe_demote(subj, obj, "msqrcv", "msg", NULL)); + + return (0); +} + + +static int +mac_lomac_check_ipc_msqctl(struct ucred *cred, struct msqid_kernel *msqkptr, + int cmd) +{ + struct mac_lomac *subj, *obj; + + if (!mac_lomac_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&msqkptr->label); + switch(cmd) { + case IPC_RMID: + case IPC_SET: + if (!mac_lomac_dominate_single(subj, obj)) + return (EACCES); + break; + case IPC_STAT: + if (!mac_lomac_dominate_single(obj, subj)) + return (maybe_demote(subj, obj, "msqctl", "msg", NULL)); + break; + default: + return (EACCES); + } + return (0); +} + +static int +mac_lomac_check_ipc_semctl(struct ucred *cred, struct semid_kernel *semakptr, + int cmd) +{ + struct mac_lomac *subj, *obj; + + if (!mac_lomac_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&semakptr->label); + switch(cmd) { + case IPC_RMID: + case IPC_SET: + case SETVAL: + case SETALL: + if (!mac_lomac_dominate_single(subj, obj)) + return (EACCES); + break; + case IPC_STAT: + case GETVAL: + case GETPID: + case GETNCNT: + case GETZCNT: + case GETALL: + if (!mac_lomac_dominate_single(obj, subj)) + return (maybe_demote(subj, obj, "semctl", "sem", NULL)); + break; + default: + return (EACCES); + } + return (0); +} + + +static int +mac_lomac_check_ipc_semget(struct ucred *cred, struct semid_kernel *semakptr) +{ + struct mac_lomac *subj, *obj; + + if (!mac_lomac_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&semakptr->label); + + if (!mac_lomac_dominate_single(obj, subj)) + return (maybe_demote(subj, obj, "semget", "sem", NULL)); + + return (0); +} + + +static int +mac_lomac_check_ipc_semop(struct ucred *cred, struct semid_kernel *semakptr, + size_t accesstype) +{ + struct mac_lomac *subj, *obj; + + if (!mac_lomac_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&semakptr->label); + + if( accesstype & SEM_R ) + if (!mac_lomac_dominate_single(obj, subj)) + return (maybe_demote(subj, obj, "semop", "sem", NULL)); + + if( accesstype & SEM_A ) + if (!mac_lomac_dominate_single(subj, obj)) + return (EACCES); + + return (0); + +} + +static int +mac_lomac_check_ipc_shmat(struct ucred *cred, struct shmid_kernel *shmsegptr, + int shmflg) +{ + struct mac_lomac *subj, *obj; + + if (!mac_lomac_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&shmsegptr->label); + + if (!mac_lomac_dominate_single(obj, subj)) + return (maybe_demote(subj, obj, "shmat", "shm", NULL)); + if ((shmflg & SHM_RDONLY) == 0) + if (!mac_lomac_dominate_single(subj, obj)) + return (EACCES); + + return (0); +} + +static int +mac_lomac_check_ipc_shmctl(struct ucred *cred, struct shmid_kernel *shmsegptr, + int cmd) +{ + struct mac_lomac *subj, *obj; + + if (!mac_lomac_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&shmsegptr->label); + switch(cmd) { + case IPC_RMID: + case IPC_SET: + if (!mac_lomac_dominate_single(subj, obj)) + return (EACCES); + break; + case IPC_STAT: + case SHM_STAT: + if (!mac_lomac_dominate_single(obj, subj)) + return (maybe_demote(subj, obj, "shmctl", "shm", NULL)); + break; + default: + return (EACCES); + } + return (0); +} + +#if 0 + +/* + * TODO: Do we check the integrity of the implicit write access caused + * by the bookkeeping tasks associated with the shmdt call, which may + * modify/delete the shmseg meta-data and/or the shared segment itself? + */ + +static int +mac_lomac_check_ipc_shmdt(struct ucred *cred, struct shmid_kernel *shmsegptr) +{ + struct mac_lomac *subj, *obj; + + if (!mac_lomac_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&shmsegptr->label); + + if (!mac_lomac_dominate_single(subj, obj)) + return (EACCES); + + return (0); +} +#endif + +static int +mac_lomac_check_ipc_shmget(struct ucred *cred, struct shmid_kernel *shmsegptr, + int shmflg) +{ + struct mac_lomac *subj, *obj; + + if (!mac_lomac_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&shmsegptr->label); + + if (!mac_lomac_dominate_single(obj, subj)) + return (maybe_demote(subj, obj, "shmget", "shm", NULL)); + + return (0); +} + +static int mac_lomac_check_kld_load(struct ucred *cred, struct vnode *vp, struct label *label) { @@ -2606,6 +2977,10 @@ .mpo_init_cred_label = mac_lomac_init_label, .mpo_init_devfsdirent_label = mac_lomac_init_label, .mpo_init_ifnet_label = mac_lomac_init_label, + .mpo_init_ipc_msgmsg_label = mac_lomac_init_label, + .mpo_init_ipc_msgqueue_label = mac_lomac_init_label, + .mpo_init_ipc_sema_label = mac_lomac_init_label, + .mpo_init_ipc_shm_label = mac_lomac_init_label, .mpo_init_ipq_label = mac_lomac_init_label_waitcheck, .mpo_init_mbuf_label = mac_lomac_init_label_waitcheck, .mpo_init_mount_label = mac_lomac_init_label, @@ -2619,6 +2994,10 @@ .mpo_destroy_cred_label = mac_lomac_destroy_label, .mpo_destroy_devfsdirent_label = mac_lomac_destroy_label, .mpo_destroy_ifnet_label = mac_lomac_destroy_label, + .mpo_destroy_ipc_msgmsg_label = mac_lomac_destroy_label, + .mpo_destroy_ipc_msgqueue_label = mac_lomac_destroy_label, + .mpo_destroy_ipc_sema_label = mac_lomac_destroy_label, + .mpo_destroy_ipc_shm_label = mac_lomac_destroy_label, .mpo_destroy_ipq_label = mac_lomac_destroy_label, .mpo_destroy_mbuf_label = mac_lomac_destroy_label, .mpo_destroy_mount_label = mac_lomac_destroy_label, @@ -2667,6 +3046,10 @@ .mpo_create_datagram_from_ipq = mac_lomac_create_datagram_from_ipq, .mpo_create_fragment = mac_lomac_create_fragment, .mpo_create_ifnet = mac_lomac_create_ifnet, + .mpo_create_ipc_msgmsg = mac_lomac_create_ipc_msgmsg, + .mpo_create_ipc_msgqueue = mac_lomac_create_ipc_msgqueue, + .mpo_create_ipc_sema = mac_lomac_create_ipc_sema, + .mpo_create_ipc_shm = mac_lomac_create_ipc_shm, .mpo_create_ipq = mac_lomac_create_ipq, .mpo_create_mbuf_from_mbuf = mac_lomac_create_mbuf_from_mbuf, .mpo_create_mbuf_linklayer = mac_lomac_create_mbuf_linklayer, @@ -2684,11 +3067,29 @@ .mpo_create_proc0 = mac_lomac_create_proc0, .mpo_create_proc1 = mac_lomac_create_proc1, .mpo_relabel_cred = mac_lomac_relabel_cred, + .mpo_cleanup_ipc_msgmsg = mac_lomac_cleanup_ipc_msgmsg, + .mpo_cleanup_ipc_msgqueue = mac_lomac_cleanup_ipc_msgqueue, + .mpo_cleanup_ipc_sema = mac_lomac_cleanup_ipc_sema, + .mpo_cleanup_ipc_shm = mac_lomac_cleanup_ipc_shm, .mpo_check_bpfdesc_receive = mac_lomac_check_bpfdesc_receive, .mpo_check_cred_relabel = mac_lomac_check_cred_relabel, .mpo_check_cred_visible = mac_lomac_check_cred_visible, .mpo_check_ifnet_relabel = mac_lomac_check_ifnet_relabel, .mpo_check_ifnet_transmit = mac_lomac_check_ifnet_transmit, +/* .mpo_check_ipc_msgmsq = mac_lomac_check_ipc_msgmsq, */ + .mpo_check_ipc_msgrcv = mac_lomac_check_ipc_msgrcv, + .mpo_check_ipc_msgrmid = mac_lomac_check_ipc_msgrmid, + .mpo_check_ipc_msqget = mac_lomac_check_ipc_msqget, + .mpo_check_ipc_msqsnd = mac_lomac_check_ipc_msqsnd, + .mpo_check_ipc_msqrcv = mac_lomac_check_ipc_msqrcv, + .mpo_check_ipc_msqctl = mac_lomac_check_ipc_msqctl, + .mpo_check_ipc_semctl = mac_lomac_check_ipc_semctl, + .mpo_check_ipc_semget = mac_lomac_check_ipc_semget, + .mpo_check_ipc_semop = mac_lomac_check_ipc_semop, + .mpo_check_ipc_shmat = mac_lomac_check_ipc_shmat, + .mpo_check_ipc_shmctl = mac_lomac_check_ipc_shmctl, +/* .mpo_check_ipc_shmdt = mac_lomac_check_ipc_shmdt, */ + .mpo_check_ipc_shmget = mac_lomac_check_ipc_shmget, .mpo_check_kld_load = mac_lomac_check_kld_load, .mpo_check_kld_unload = mac_lomac_check_kld_unload, .mpo_check_pipe_ioctl = mac_lomac_check_pipe_ioctl, --- //depot/projects/trustedbsd/mac/sys/security/mac_mls/mac_mls.c 2003/06/02 12:26:58 +++ //depot/user/hdandeka/rishi_SystemVIPC/sys/security/mac_mls/mac_mls.c 2003/06/13 16:12:32 @@ -60,6 +60,10 @@ #include #include #include +#include +#include +#include +#include #include @@ -1117,6 +1121,58 @@ } /* + * Labeling event operations: System V IPC objects. + */ + +static void +mac_mls_create_ipc_msgmsg(struct ucred *cred, struct msg *msgptr, + struct label *msglabel) +{ + struct mac_mls *source, *dest; + + source = SLOT(&cred->cr_label); + dest = SLOT(msglabel); + + mac_mls_copy_single(source, dest); +} + +static void +mac_mls_create_ipc_msgqueue(struct ucred *cred, struct msqid_kernel *msqkptr, + struct label *msqlabel) +{ + struct mac_mls *source, *dest; + + source = SLOT(&cred->cr_label); + dest = SLOT(msqlabel); + + mac_mls_copy_single(source, dest); +} + +static void +mac_mls_create_ipc_sema(struct ucred *cred, struct semid_kernel *semakptr, + struct label *semalabel) +{ + struct mac_mls *source, *dest; + + source = SLOT(&cred->cr_label); + dest = SLOT(semalabel); + + mac_mls_copy_single(source, dest); +} + +static void +mac_mls_create_ipc_shm(struct ucred *cred, struct shmid_kernel *shmsegptr, + struct label *shmlabel) +{ + struct mac_mls *source, *dest; + + source = SLOT(&cred->cr_label); + dest = SLOT(shmlabel); + + mac_mls_copy_single(source, dest); +} + +/* * Labeling event operations: network objects. */ static void @@ -1362,6 +1418,38 @@ } /* + * Label cleanup/flush operations + */ + +static void +mac_mls_cleanup_ipc_msgmsg(struct label *msglabel) +{ + + bzero(SLOT(msglabel), sizeof(struct mac_mls)); +} + +static void +mac_mls_cleanup_ipc_msgqueue(struct label *msqlabel) +{ + + bzero(SLOT(msqlabel), sizeof(struct mac_mls)); +} + +static void +mac_mls_cleanup_ipc_sema(struct label *semalabel) +{ + + bzero(SLOT(semalabel), sizeof(struct mac_mls)); +} + +static void +mac_mls_cleanup_ipc_shm(struct label *shmlabel) +{ + + bzero(SLOT(shmlabel), sizeof(struct mac_mls)); +} + +/* * Access control checks. */ static int @@ -1517,6 +1605,292 @@ } static int +mac_mls_check_ipc_msgrcv(struct ucred *cred, struct msg *msgptr) +{ + + struct mac_mls *subj, *obj; + + if (!mac_mls_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&msgptr->label); + + if (!mac_mls_dominate_single(subj, obj)) + return (EACCES); + + return (0); +} + +static int +mac_mls_check_ipc_msgrmid(struct ucred *cred, struct msg *msgptr) +{ + + struct mac_mls *subj, *obj; + + if (!mac_mls_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&msgptr->label); + + if (!mac_mls_dominate_single(obj, subj)) + return (EACCES); + + return (0); +} + +static int +mac_mls_check_ipc_msqget(struct ucred *cred, struct msqid_kernel *msqkptr) +{ + struct mac_mls *subj, *obj; + + if (!mac_mls_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&msqkptr->label); + + if (!mac_mls_dominate_single(subj, obj)) + return (EACCES); + + return (0); +} + + +static int +mac_mls_check_ipc_msqsnd(struct ucred *cred, struct msqid_kernel *msqkptr) +{ + struct mac_mls *subj, *obj; + + if (!mac_mls_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&msqkptr->label); + + if (!mac_mls_dominate_single(obj, subj)) + return (EACCES); + + return (0); +} + +static int +mac_mls_check_ipc_msqrcv(struct ucred *cred, struct msqid_kernel *msqkptr) +{ + struct mac_mls *subj, *obj; + + if (!mac_mls_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&msqkptr->label); + + if (!mac_mls_dominate_single(subj, obj)) + return (EACCES); + + return (0); +} + + +static int +mac_mls_check_ipc_msqctl(struct ucred *cred, struct msqid_kernel *msqkptr, + int cmd) +{ + struct mac_mls *subj, *obj; + + if (!mac_mls_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&msqkptr->label); + switch(cmd) { + case IPC_RMID: + case IPC_SET: + if (!mac_mls_dominate_single(obj, subj)) + return (EACCES); + break; + case IPC_STAT: + if (!mac_mls_dominate_single(subj, obj)) + return (EACCES); + break; + default: + return (EACCES); + } + return (0); +} + +static int +mac_mls_check_ipc_semctl(struct ucred *cred, struct semid_kernel *semakptr, + int cmd) +{ + struct mac_mls *subj, *obj; + + if (!mac_mls_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&semakptr->label); + switch(cmd) { + case IPC_RMID: + case IPC_SET: + case SETVAL: + case SETALL: + if (!mac_mls_dominate_single(obj, subj)) + return (EACCES); + break; + case IPC_STAT: + case GETVAL: + case GETPID: + case GETNCNT: + case GETZCNT: + case GETALL: + if (!mac_mls_dominate_single(subj, obj)) + return (EACCES); + break; + default: + return (EACCES); + } + return (0); +} + + +static int +mac_mls_check_ipc_semget(struct ucred *cred, struct semid_kernel *semakptr) +{ + struct mac_mls *subj, *obj; + + if (!mac_mls_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&semakptr->label); + + if (!mac_mls_dominate_single(subj, obj)) + return (EACCES); + + return (0); +} + + +static int +mac_mls_check_ipc_semop(struct ucred *cred, struct semid_kernel *semakptr, + size_t accesstype) +{ + struct mac_mls *subj, *obj; + + if (!mac_mls_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&semakptr->label); + + if( accesstype & SEM_R ) + if (!mac_mls_dominate_single(subj, obj)) + return (EACCES); + + if( accesstype & SEM_A ) + if (!mac_mls_dominate_single(obj, subj)) + return (EACCES); + + return (0); + +} + +static int +mac_mls_check_ipc_shmat(struct ucred *cred, struct shmid_kernel *shmsegptr, + int shmflg) +{ + struct mac_mls *subj, *obj; + + if (!mac_mls_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&shmsegptr->label); + + if (!mac_mls_dominate_single(subj, obj)) + return (EACCES); + if ((shmflg & SHM_RDONLY) == 0) + if (!mac_mls_dominate_single(obj, subj)) + return (EACCES); + + return (0); +} + +static int +mac_mls_check_ipc_shmctl(struct ucred *cred, struct shmid_kernel *shmsegptr, + int cmd) +{ + struct mac_mls *subj, *obj; + + if (!mac_mls_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&shmsegptr->label); + switch(cmd) { + case IPC_RMID: + case IPC_SET: + if (!mac_mls_dominate_single(obj, subj)) + return (EACCES); + break; + case IPC_STAT: + case SHM_STAT: + if (!mac_mls_dominate_single(subj, obj)) + return (EACCES); + break; + default: + return (EACCES); + } + return (0); +} + +#if 0 + +/* + * TODO: Do we check the integrity of the implicit write access caused + * by the bookkeeping tasks associated with the shmdt call, which may + * modify/delete the shmseg meta-data and/or the shared segment itself? + */ + +static int +mac_mls_check_ipc_shmdt(struct ucred *cred, struct shmid_kernel *shmsegptr) +{ + struct mac_mls *subj, *obj; + + if (!mac_mls_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&shmsegptr->label); + + if (!mac_mls_dominate_single(obj, subj)) + return (EACCES); + + return (0); +} +#endif + +static int +mac_mls_check_ipc_shmget(struct ucred *cred, struct shmid_kernel *shmsegptr, + int shmflg) +{ + struct mac_mls *subj, *obj; + + if (!mac_mls_enabled) + return (0); + + subj = SLOT(&cred->cr_label); + obj = SLOT(&shmsegptr->label); + + if (!mac_mls_dominate_single(obj, subj)) + return (EACCES); + + return (0); +} + +static int mac_mls_check_mount_stat(struct ucred *cred, struct mount *mp, struct label *mntlabel) { @@ -2438,6 +2812,10 @@ .mpo_init_cred_label = mac_mls_init_label, .mpo_init_devfsdirent_label = mac_mls_init_label, .mpo_init_ifnet_label = mac_mls_init_label, + .mpo_init_ipc_msgmsg_label = mac_mls_init_label, + .mpo_init_ipc_msgqueue_label = mac_mls_init_label, + .mpo_init_ipc_sema_label = mac_mls_init_label, + .mpo_init_ipc_shm_label = mac_mls_init_label, .mpo_init_ipq_label = mac_mls_init_label_waitcheck, .mpo_init_mbuf_label = mac_mls_init_label_waitcheck, .mpo_init_mount_label = mac_mls_init_label, @@ -2450,6 +2828,10 @@ .mpo_destroy_cred_label = mac_mls_destroy_label, .mpo_destroy_devfsdirent_label = mac_mls_destroy_label, .mpo_destroy_ifnet_label = mac_mls_destroy_label, + .mpo_destroy_ipc_msgmsg_label = mac_mls_destroy_label, + .mpo_destroy_ipc_msgqueue_label = mac_mls_destroy_label, + .mpo_destroy_ipc_sema_label = mac_mls_destroy_label, + .mpo_destroy_ipc_shm_label = mac_mls_destroy_label, .mpo_destroy_ipq_label = mac_mls_destroy_label, .mpo_destroy_mbuf_label = mac_mls_destroy_label, .mpo_destroy_mount_label = mac_mls_destroy_label, @@ -2497,6 +2879,10 @@ .mpo_create_fragment = mac_mls_create_fragment, .mpo_create_ifnet = mac_mls_create_ifnet, .mpo_create_ipq = mac_mls_create_ipq, + .mpo_create_ipc_msgmsg = mac_mls_create_ipc_msgmsg, + .mpo_create_ipc_msgqueue = mac_mls_create_ipc_msgqueue, + .mpo_create_ipc_sema = mac_mls_create_ipc_sema, + .mpo_create_ipc_shm = mac_mls_create_ipc_shm, .mpo_create_mbuf_from_mbuf = mac_mls_create_mbuf_from_mbuf, .mpo_create_mbuf_linklayer = mac_mls_create_mbuf_linklayer, .mpo_create_mbuf_from_bpfdesc = mac_mls_create_mbuf_from_bpfdesc, @@ -2510,11 +2896,28 @@ .mpo_create_proc0 = mac_mls_create_proc0, .mpo_create_proc1 = mac_mls_create_proc1, .mpo_relabel_cred = mac_mls_relabel_cred, + .mpo_cleanup_ipc_msgmsg = mac_mls_cleanup_ipc_msgmsg, + .mpo_cleanup_ipc_msgqueue = mac_mls_cleanup_ipc_msgqueue, + .mpo_cleanup_ipc_sema = mac_mls_cleanup_ipc_sema, + .mpo_cleanup_ipc_shm = mac_mls_cleanup_ipc_shm, .mpo_check_bpfdesc_receive = mac_mls_check_bpfdesc_receive, .mpo_check_cred_relabel = mac_mls_check_cred_relabel, .mpo_check_cred_visible = mac_mls_check_cred_visible, .mpo_check_ifnet_relabel = mac_mls_check_ifnet_relabel, .mpo_check_ifnet_transmit = mac_mls_check_ifnet_transmit, + .mpo_check_ipc_msgrcv = mac_mls_check_ipc_msgrcv, + .mpo_check_ipc_msgrmid = mac_mls_check_ipc_msgrmid, + .mpo_check_ipc_msqget = mac_mls_check_ipc_msqget, + .mpo_check_ipc_msqsnd = mac_mls_check_ipc_msqsnd, + .mpo_check_ipc_msqrcv = mac_mls_check_ipc_msqrcv, + .mpo_check_ipc_msqctl = mac_mls_check_ipc_msqctl, + .mpo_check_ipc_semctl = mac_mls_check_ipc_semctl, + .mpo_check_ipc_semget = mac_mls_check_ipc_semget, + .mpo_check_ipc_semop = mac_mls_check_ipc_semop, + .mpo_check_ipc_shmat = mac_mls_check_ipc_shmat, + .mpo_check_ipc_shmctl = mac_mls_check_ipc_shmctl, +/* .mpo_check_ipc_shmdt = mac_mls_check_ipc_shmdt, */ + .mpo_check_ipc_shmget = mac_mls_check_ipc_shmget, .mpo_check_mount_stat = mac_mls_check_mount_stat, .mpo_check_pipe_ioctl = mac_mls_check_pipe_ioctl, .mpo_check_pipe_poll = mac_mls_check_pipe_poll, --- //depot/projects/trustedbsd/mac/sys/security/mac_none/mac_none.c 2003/06/02 12:26:58 +++ //depot/user/hdandeka/rishi_SystemVIPC/sys/security/mac_none/mac_none.c 2003/06/13 16:12:32 @@ -57,6 +57,10 @@ #include #include #include +#include +#include +#include +#include #include @@ -329,6 +333,34 @@ } +static void +mac_none_create_ipc_msgmsg(struct ucred *cred, struct msg *msgptr, + struct label *msglabel) +{ + +} + +static void +mac_none_create_ipc_msgqueue(struct ucred *cred, struct msqid_kernel *msqkptr, + struct label *msqlabel) +{ + +} + +static void +mac_none_create_ipc_sema(struct ucred *cred, struct semid_kernel *semakptr, + struct label *semalabel) +{ + +} + +static void +mac_none_create_ipc_shm(struct ucred *cred, struct shmid_kernel *shmsegptr, + struct label *shmalabel) +{ + +} + static void mac_none_create_ipq(struct mbuf *fragment, struct label *fragmentlabel, struct ipq *ipq, struct label *ipqlabel) @@ -466,6 +498,34 @@ } /* + * Label cleanup/flush operations + */ +static void +mac_none_cleanup_ipc_msgmsg(struct label *msglabel) +{ + +} + +static void +mac_none_cleanup_ipc_msgqueue(struct label *msqlabel) +{ + +} + +static void +mac_none_cleanup_ipc_sema(struct label *semalabel) +{ + +} + +static void +mac_none_cleanup_ipc_shm(struct label *shmlabel) +{ + +} + + +/* * Access control checks. */ static int @@ -507,6 +567,123 @@ } static int +mac_none_check_ipc_msgmsq(struct ucred *cred, struct msg *msgptr, + struct msqid_kernel *msqkptr) +{ + + return (0); +} + +static int +mac_none_check_ipc_msgrcv(struct ucred *cred, struct msg *msgptr) +{ + + return (0); +} + + +static int +mac_none_check_ipc_msgrmid(struct ucred *cred, struct msg *msgptr) +{ + + return (0); +} + + +static int +mac_none_check_ipc_msqget(struct ucred *cred, struct msqid_kernel *msqkptr) +{ + + return (0); +} + + +static int +mac_none_check_ipc_msqsnd(struct ucred *cred, struct msqid_kernel *msqkptr) +{ + + return (0); +} + + +static int +mac_none_check_ipc_msqrcv(struct ucred *cred, struct msqid_kernel *msqkptr) +{ + + return (0); +} + + +static int +mac_none_check_ipc_msqctl(struct ucred *cred, struct msqid_kernel *msqkptr, + int cmd) +{ + + return (0); +} + + +static int +mac_none_check_ipc_semctl(struct ucred *cred, struct semid_kernel *semakptr, + int cmd) +{ + + return (0); +} + + +static int +mac_none_check_ipc_semget(struct ucred *cred, struct semid_kernel *semakptr) +{ + + return (0); +} + + +static int +mac_none_check_ipc_semop(struct ucred *cred, struct semid_kernel *semakptr, + size_t accesstype) +{ + + return (0); +} + + +static int +mac_none_check_ipc_shmat(struct ucred *cred, struct shmid_kernel *shmsegptr, + int shmflg) +{ + + return (0); +} + + +static int +mac_none_check_ipc_shmctl(struct ucred *cred, struct shmid_kernel *shmsegptr, + int cmd) +{ + + return (0); +} + + +static int +mac_none_check_ipc_shmdt(struct ucred *cred, struct shmid_kernel *shmsegptr) +{ + + return (0); +} + + +static int +mac_none_check_ipc_shmget(struct ucred *cred, struct shmid_kernel *shmsegptr, + int shmflg) +{ + + return (0); +} + +static int mac_none_check_kenv_dump(struct ucred *cred) { @@ -988,6 +1165,10 @@ .mpo_init_cred_label = mac_none_init_label, .mpo_init_devfsdirent_label = mac_none_init_label, .mpo_init_ifnet_label = mac_none_init_label, + .mpo_init_ipc_msgmsg_label = mac_none_init_label, + .mpo_init_ipc_msgqueue_label = mac_none_init_label, + .mpo_init_ipc_sema_label = mac_none_init_label, + .mpo_init_ipc_shm_label = mac_none_init_label, .mpo_init_ipq_label = mac_none_init_label_waitcheck, .mpo_init_mbuf_label = mac_none_init_label_waitcheck, .mpo_init_mount_label = mac_none_init_label, @@ -1000,6 +1181,10 @@ .mpo_destroy_cred_label = mac_none_destroy_label, .mpo_destroy_devfsdirent_label = mac_none_destroy_label, .mpo_destroy_ifnet_label = mac_none_destroy_label, + .mpo_destroy_ipc_msgmsg_label = mac_none_destroy_label, + .mpo_destroy_ipc_msgqueue_label = mac_none_destroy_label, + .mpo_destroy_ipc_sema_label = mac_none_destroy_label, + .mpo_destroy_ipc_shm_label = mac_none_destroy_label, .mpo_destroy_ipq_label = mac_none_destroy_label, .mpo_destroy_mbuf_label = mac_none_destroy_label, .mpo_destroy_mount_label = mac_none_destroy_label, @@ -1025,6 +1210,10 @@ .mpo_create_devfs_device = mac_none_create_devfs_device, .mpo_create_devfs_directory = mac_none_create_devfs_directory, .mpo_create_devfs_symlink = mac_none_create_devfs_symlink, + .mpo_create_ipc_msgmsg = mac_none_create_ipc_msgmsg, + .mpo_create_ipc_msgqueue = mac_none_create_ipc_msgqueue, + .mpo_create_ipc_sema = mac_none_create_ipc_sema, + .mpo_create_ipc_shm = mac_none_create_ipc_shm, .mpo_create_vnode_extattr = mac_none_create_vnode_extattr, .mpo_create_mount = mac_none_create_mount, .mpo_create_root_mount = mac_none_create_root_mount, @@ -1063,11 +1252,29 @@ .mpo_create_proc1 = mac_none_create_proc1, .mpo_relabel_cred = mac_none_relabel_cred, .mpo_thread_userret = mac_none_thread_userret, + .mpo_cleanup_ipc_msgmsg = mac_none_cleanup_ipc_msgmsg, + .mpo_cleanup_ipc_msgqueue = mac_none_cleanup_ipc_msgqueue, + .mpo_cleanup_ipc_sema = mac_none_cleanup_ipc_sema, + .mpo_cleanup_ipc_shm = mac_none_cleanup_ipc_shm, .mpo_check_bpfdesc_receive = mac_none_check_bpfdesc_receive, .mpo_check_cred_relabel = mac_none_check_cred_relabel, .mpo_check_cred_visible = mac_none_check_cred_visible, .mpo_check_ifnet_relabel = mac_none_check_ifnet_relabel, .mpo_check_ifnet_transmit = mac_none_check_ifnet_transmit, + .mpo_check_ipc_msgmsq = mac_none_check_ipc_msgmsq, + .mpo_check_ipc_msgrcv = mac_none_check_ipc_msgrcv, + .mpo_check_ipc_msgrmid = mac_none_check_ipc_msgrmid, + .mpo_check_ipc_msqget = mac_none_check_ipc_msqget, + .mpo_check_ipc_msqsnd = mac_none_check_ipc_msqsnd, + .mpo_check_ipc_msqrcv = mac_none_check_ipc_msqrcv, + .mpo_check_ipc_msqctl = mac_none_check_ipc_msqctl, + .mpo_check_ipc_semctl = mac_none_check_ipc_semctl, + .mpo_check_ipc_semget = mac_none_check_ipc_semget, + .mpo_check_ipc_semop = mac_none_check_ipc_semop, + .mpo_check_ipc_shmat = mac_none_check_ipc_shmat, + .mpo_check_ipc_shmctl = mac_none_check_ipc_shmctl, + .mpo_check_ipc_shmdt = mac_none_check_ipc_shmdt, + .mpo_check_ipc_shmget = mac_none_check_ipc_shmget, .mpo_check_kenv_dump = mac_none_check_kenv_dump, .mpo_check_kenv_get = mac_none_check_kenv_get, .mpo_check_kenv_set = mac_none_check_kenv_set, --- //depot/projects/trustedbsd/mac/sys/security/mac_test/mac_test.c 2003/06/02 12:26:58 +++ //depot/user/hdandeka/rishi_SystemVIPC/sys/security/mac_test/mac_test.c 2003/06/13 16:12:32 @@ -57,6 +57,10 @@ #include #include #include +#include +#include +#include +#include #include @@ -85,6 +89,10 @@ #define MBUFMAGIC 0xbbefa5bb #define MOUNTMAGIC 0xc7c46e47 #define SOCKETMAGIC 0x9199c6cd +#define SYSVIPCMSQMAGIC 0xea672391 +#define SYSVIPCMSGMAGIC 0x8bbba61e +#define SYSVIPCSEMMAGIC 0x896e8a0b +#define SYSVIPCSHMMAGIC 0x76119ab0 #define PIPEMAGIC 0xdc6c9919 #define PROCMAGIC 0x3b4be98f #define CREDMAGIC 0x9a5a4987 @@ -107,6 +115,14 @@ SLOT(x) == 0, ("%s: Bad MOUNT label", __func__ )) #define ASSERT_SOCKET_LABEL(x) KASSERT(SLOT(x) == SOCKETMAGIC || \ SLOT(x) == 0, ("%s: Bad SOCKET label", __func__ )) +#define ASSERT_SYSVIPCMSQ_LABEL(x) KASSERT(SLOT(x) == SYSVIPCMSQMAGIC || \ + SLOT(x) == 0, ("%s: Bad SYSVIPCMSQ label", __func__ )) +#define ASSERT_SYSVIPCMSG_LABEL(x) KASSERT(SLOT(x) == SYSVIPCMSGMAGIC || \ + SLOT(x) == 0, ("%s: Bad SYSVIPCMSG label", __func__ )) +#define ASSERT_SYSVIPCSEM_LABEL(x) KASSERT(SLOT(x) == SYSVIPCSEMMAGIC || \ + SLOT(x) == 0, ("%s: Bad SYSVIPCSEM label", __func__ )) +#define ASSERT_SYSVIPCSHM_LABEL(x) KASSERT(SLOT(x) == SYSVIPCSHMMAGIC || \ + SLOT(x) == 0, ("%s: Bad SYSVIPCSHM label", __func__ )) #define ASSERT_PIPE_LABEL(x) KASSERT(SLOT(x) == PIPEMAGIC || \ SLOT(x) == 0, ("%s: Bad PIPE label", __func__ )) #define ASSERT_PROC_LABEL(x) KASSERT(SLOT(x) == PROCMAGIC || \ @@ -132,6 +148,18 @@ static int init_count_ifnet; SYSCTL_INT(_security_mac_test, OID_AUTO, init_count_ifnet, CTLFLAG_RD, &init_count_ifnet, 0, "ifnet init calls"); +static int init_count_ipc_msg; +SYSCTL_INT(_security_mac_test, OID_AUTO, init_count_ipc_msg, CTLFLAG_RD, + &init_count_ipc_msg, 0, "ipc_msg init calls"); +static int init_count_ipc_msq; +SYSCTL_INT(_security_mac_test, OID_AUTO, init_count_ipc_msq, CTLFLAG_RD, + &init_count_ipc_msq, 0, "ipc_msq init calls"); +static int init_count_ipc_sema; +SYSCTL_INT(_security_mac_test, OID_AUTO, init_count_ipc_sema, CTLFLAG_RD, + &init_count_ipc_sema, 0, "ipc_sema init calls"); +static int init_count_ipc_shm; +SYSCTL_INT(_security_mac_test, OID_AUTO, init_count_ipc_shm, CTLFLAG_RD, + &init_count_ipc_shm, 0, "ipc_shm init calls"); static int init_count_ipq; SYSCTL_INT(_security_mac_test, OID_AUTO, init_count_ipq, CTLFLAG_RD, &init_count_ipq, 0, "ipq init calls"); @@ -173,6 +201,18 @@ static int destroy_count_ifnet; SYSCTL_INT(_security_mac_test, OID_AUTO, destroy_count_ifnet, CTLFLAG_RD, &destroy_count_ifnet, 0, "ifnet destroy calls"); +static int destroy_count_ipc_msg; +SYSCTL_INT(_security_mac_test, OID_AUTO, destroy_count_ipc_msg, CTLFLAG_RD, + &destroy_count_ipc_msg, 0, "ipc_msg destroy calls"); +static int destroy_count_ipc_msq; +SYSCTL_INT(_security_mac_test, OID_AUTO, destroy_count_ipc_msq, CTLFLAG_RD, + &destroy_count_ipc_msq, 0, "ipc_msq destroy calls"); +static int destroy_count_ipc_sema; +SYSCTL_INT(_security_mac_test, OID_AUTO, destroy_count_ipc_sema, CTLFLAG_RD, + &destroy_count_ipc_sema, 0, "ipc_sema destroy calls"); +static int destroy_count_ipc_shm; +SYSCTL_INT(_security_mac_test, OID_AUTO, destroy_count_ipc_shm, CTLFLAG_RD, + &destroy_count_ipc_shm, 0, "ipc_shm destroy calls"); static int destroy_count_ipq; SYSCTL_INT(_security_mac_test, OID_AUTO, destroy_count_ipq, CTLFLAG_RD, &destroy_count_ipq, 0, "ipq destroy calls"); @@ -267,6 +307,34 @@ atomic_add_int(&init_count_ifnet, 1); } +static void +mac_test_init_ipc_msgmsg_label(struct label *label) +{ + SLOT(label) = SYSVIPCMSGMAGIC; + atomic_add_int(&init_count_ipc_msg, 1); +} + +static void +mac_test_init_ipc_msgqueue_label(struct label *label) +{ + SLOT(label) = SYSVIPCMSQMAGIC; + atomic_add_int(&init_count_ipc_msq, 1); +} + +static void +mac_test_init_ipc_sema_label(struct label *label) +{ + SLOT(label) = SYSVIPCSEMMAGIC; + atomic_add_int(&init_count_ipc_sema, 1); +} + +static void +mac_test_init_ipc_shm_label(struct label *label) +{ + SLOT(label) = SYSVIPCSHMMAGIC; + atomic_add_int(&init_count_ipc_shm, 1); +} + static int mac_test_init_ipq_label(struct label *label, int flag) { @@ -420,6 +488,62 @@ } static void +mac_test_destroy_ipc_msgmsg_label(struct label *label) +{ + + if (SLOT(label) == SYSVIPCMSGMAGIC || SLOT(label) == 0) { + atomic_add_int(&destroy_count_ipc_msg, 1); + SLOT(label) = EXMAGIC; + } else if (SLOT(label) == EXMAGIC) { + Debugger("mac_test_destroy_ipc_msgmsg_label: dup destroy"); + } else { + Debugger("mac_test_destroy_ipc_msgmsg_label: corrupted label"); + } +} + +static void +mac_test_destroy_ipc_msgqueue_label(struct label *label) +{ + + if (SLOT(label) == SYSVIPCMSQMAGIC || SLOT(label) == 0) { + atomic_add_int(&destroy_count_ipc_msq, 1); + SLOT(label) = EXMAGIC; + } else if (SLOT(label) == EXMAGIC) { + Debugger("mac_test_destroy_ipc_msgqueue_label: dup destroy"); + } else { + Debugger("mac_test_destroy_ipc_msgqueue_label: corrupted label"); + } +} + +static void +mac_test_destroy_ipc_sema_label(struct label *label) +{ + + if (SLOT(label) == SYSVIPCSEMMAGIC || SLOT(label) == 0) { + atomic_add_int(&destroy_count_ipc_sema, 1); + SLOT(label) = EXMAGIC; + } else if (SLOT(label) == EXMAGIC) { + Debugger("mac_test_destroy_ipc_sema_label: dup destroy"); + } else { + Debugger("mac_test_destroy_ipc_sema_label: corrupted label"); + } +} + +static void +mac_test_destroy_ipc_shm_label(struct label *label) +{ + + if (SLOT(label) == SYSVIPCSHMMAGIC || SLOT(label) == 0) { + atomic_add_int(&destroy_count_ipc_shm, 1); + SLOT(label) = EXMAGIC; + } else if (SLOT(label) == EXMAGIC) { + Debugger("mac_test_destroy_ipc_shm_label: dup destroy"); + } else { + Debugger("mac_test_destroy_ipc_shm_label: corrupted label"); + } +} + +static void mac_test_destroy_ipq_label