On Wed, Feb 19, 2003 at 07:43:19PM +0100, Pawel Jakub Dawidek wrote: +> Patches are attached.
Now!:) -- Pawel Jakub Dawidek UNIX Systems Administrator http://garage.freebsd.pl Am I Evil? Yes, I Am.
diff -ru /sys/compat/linux/linux_ipc.c sys/compat/linux/linux_ipc.c --- /sys/compat/linux/linux_ipc.c Wed Feb 19 19:29:13 2003 +++ sys/compat/linux/linux_ipc.c Wed Feb 19 18:02:21 2003 @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD: src/sys/compat/linux/linux_ipc.c,v 1.17.2.3 2001/11/05 19:08:22 marcel Exp $ + * $FreeBSD$ */ #include <sys/param.h> @@ -34,6 +34,7 @@ #include <sys/proc.h> #include <sys/sem.h> #include <sys/shm.h> +#include <sys/jail.h> #include <machine/../linux/linux.h> #include <machine/../linux/linux_proto.h> @@ -222,6 +223,12 @@ int error; union semun *unptr; caddr_t sg; + struct sempriv *sp; + + if (p->p_prison == NULL) + sp = &mainsem; + else + sp = &p->p_prison->pr_sem; sg = stackgap_init(); @@ -278,7 +285,7 @@ sizeof(linux_seminfo) ); if (error) return error; - bcopy(&seminfo, &linux_seminfo, sizeof(linux_seminfo) ); + bcopy(&sp->seminfo, &linux_seminfo, sizeof(linux_seminfo) ); /* XXX BSD equivalent? #define used_semids 10 #define used_sems 10 @@ -289,7 +296,7 @@ sizeof(linux_seminfo) ); if (error) return error; - p->p_retval[0] = seminfo.semmni; + p->p_retval[0] = sp->seminfo.semmni; return 0; /* No need for __semctl call */ case LINUX_GETALL: /* FALLTHROUGH */ diff -ru /sys/kern/kern_exit.c sys/kern/kern_exit.c --- /sys/kern/kern_exit.c Wed Feb 19 19:29:13 2003 +++ sys/kern/kern_exit.c Wed Feb 19 18:38:38 2003 @@ -36,11 +36,12 @@ * SUCH DAMAGE. * * @(#)kern_exit.c 8.7 (Berkeley) 2/12/94 - * $FreeBSD: src/sys/kern/kern_exit.c,v 1.92.2.11 2003/01/13 22:51:16 dillon Exp $ + * $FreeBSD$ */ #include "opt_compat.h" #include "opt_ktrace.h" +#include "opt_sysvipc.h" #include <sys/param.h> #include <sys/systm.h> @@ -57,6 +58,7 @@ #include <sys/ptrace.h> #include <sys/acct.h> /* for acct_process() function prototype */ #include <sys/filedesc.h> +#include <sys/msg.h> #include <sys/shm.h> #include <sys/sem.h> #include <sys/aio.h> @@ -510,6 +512,15 @@ if (p->p_prison && !--p->p_prison->pr_ref) { if (p->p_prison->pr_linux != NULL) FREE(p->p_prison->pr_linux, M_PRISON); +#ifdef SYSVMSG + msgclear(p->p_prison); +#endif +#ifdef SYSVSEM + semclear(p->p_prison); +#endif +#ifdef SYSVSHM + shmclear(p->p_prison); +#endif FREE(p->p_prison, M_PRISON); } diff -ru /sys/kern/kern_jail.c sys/kern/kern_jail.c --- /sys/kern/kern_jail.c Wed Feb 19 19:29:13 2003 +++ sys/kern/kern_jail.c Wed Feb 19 19:29:09 2003 @@ -6,10 +6,12 @@ * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp * ---------------------------------------------------------------------------- * - * $FreeBSD: src/sys/kern/kern_jail.c,v 1.6.2.3 2001/08/17 01:00:26 rwatson Exp $ + * $FreeBSD$ * */ +#include "opt_sysvipc.h" + #include <sys/param.h> #include <sys/types.h> #include <sys/kernel.h> @@ -21,6 +23,9 @@ #include <sys/jail.h> #include <sys/socket.h> #include <sys/sysctl.h> +#include <sys/msg.h> +#include <sys/sem.h> +#include <sys/shm.h> #include <net/if.h> #include <netinet/in.h> @@ -39,10 +44,12 @@ &jail_socket_unixiproute_only, 0, "Processes in jail are limited to creating UNIX/IPv4/route sockets only"); -int jail_sysvipc_allowed = 0; +#if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) +int jail_sysvipc_allowed = 1; SYSCTL_INT(_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW, &jail_sysvipc_allowed, 0, "Processes in jail can use System V IPC primitives"); +#endif int jail(p, uap) @@ -75,7 +82,32 @@ error = chroot(p, &ca); if (error) goto bail; - +#ifdef SYSVMSG + error = msginit(pr); + if (error != 0) + goto bail; +#endif +#ifdef SYSVSEM + error = seminit(pr); + if (error != 0) { +#ifdef SYSVMSG + msgclear(pr); +#endif + goto bail; + } +#endif +#ifdef SYSVSHM + error = shminit(pr); + if (error != 0) { +#ifdef SYSVMSG + msgclear(pr); +#endif +#ifdef SYSVSEM + semclear(pr); +#endif + goto bail; + } +#endif pr->pr_ref++; p->p_prison = pr; p->p_flag |= P_JAILED; diff -ru /sys/kern/sysv_msg.c sys/kern/sysv_msg.c --- /sys/kern/sysv_msg.c Wed Feb 19 19:29:13 2003 +++ sys/kern/sysv_msg.c Wed Feb 19 18:27:23 2003 @@ -1,9 +1,10 @@ -/* $FreeBSD: src/sys/kern/sysv_msg.c,v 1.23.2.5 2002/12/31 08:54:53 maxim Exp $ */ +/* $FreeBSD$ */ /* * Implementation of SVID messages * * Author: Daniel Boulet + * Jailed by: Pawel Jakub Dawidek <[EMAIL PROTECTED]> * * Copyright 1993 Daniel Boulet and RTMX Inc. * @@ -34,8 +35,6 @@ static MALLOC_DEFINE(M_MSG, "msg", "SVID compatible message queues"); -static void msginit __P((void *)); - #define MSG_DEBUG #undef MSG_DEBUG_OK @@ -47,15 +46,6 @@ (sy_call_t *)msgsnd, (sy_call_t *)msgrcv }; -struct msg { - struct msg *msg_next; /* next msg in the chain */ - long msg_type; /* type of this message */ - /* >0 -> type of this message */ - /* 0 -> free header */ - u_short msg_ts; /* size of this message */ - short msg_spot; /* location of start of msg in buffer */ -}; - #ifndef MSGSSZ #define MSGSSZ 8 /* Each segment must be 2^N long */ @@ -75,26 +65,6 @@ #endif /* - * Based on the configuration parameters described in an SVR2 (yes, two) - * config(1m) man page. - * - * Each message is broken up and stored in segments that are msgssz bytes - * long. For efficiency reasons, this should be a power of two. Also, - * it doesn't make sense if it is less than 8 or greater than about 256. - * Consequently, msginit in kern/sysv_msg.c checks that msgssz is a power of - * two between 8 and 1024 inclusive (and panic's if it isn't). - */ -struct msginfo msginfo = { - MSGMAX, /* max chars in a message */ - MSGMNI, /* # of message queue identifiers */ - MSGMNB, /* max chars in a queue */ - MSGTQL, /* max messages in system */ - MSGSSZ, /* size of a message segment */ - /* (must be small power of 2 greater than 4) */ - MSGSEG /* number of message segments */ -}; - -/* * macros to convert between msqid_ds's and msqid's. * (specific to this implementation) */ @@ -106,41 +76,68 @@ * The rest of this file is specific to this particular implementation. */ -struct msgmap { - short next; /* next segment in buffer */ - /* -1 -> available */ - /* 0..(MSGSEG-1) -> index of next segment */ -}; - #define MSG_LOCKED 01000 /* Is this msqid_ds locked? */ -static int nfree_msgmaps; /* # of free map entries */ -static short free_msgmaps; /* head of linked list of free map entries */ -static struct msg *free_msghdrs;/* list of free msg headers */ -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 */ +/* Global struct for main system, all jails have its own. */ +struct msgpriv mainmsg; -static void -msginit(dummy) - void *dummy; +int +msginit(struct prison *pr) { register int i; + struct msgpriv *mp; + int error; - msginfo.msgmax = msginfo.msgseg * msginfo.msgssz; - msgpool = malloc(msginfo.msgmax, M_MSG, M_WAITOK); - if (msgpool == NULL) - panic("msgpool is NULL"); - msgmaps = malloc(sizeof(struct msgmap) * msginfo.msgseg, M_MSG, M_WAITOK); - if (msgmaps == NULL) - panic("msgmaps is NULL"); - 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); - if (msqids == NULL) - panic("msqids is NULL"); + if (pr == NULL) + mp = &mainmsg; + else + mp = &pr->pr_msg; + + mp->msginfo.msgmax = MSGMAX; + mp->msginfo.msgmni = MSGMNI; + mp->msginfo.msgmnb = MSGMNB; + mp->msginfo.msgtql = MSGTQL; + mp->msginfo.msgssz = MSGSSZ; + mp->msginfo.msgseg = MSGSEG; + + mp->msginfo.msgmax = mp->msginfo.msgseg * mp->msginfo.msgssz; + mp->msgpool = malloc(mp->msginfo.msgmax, M_MSG, M_WAITOK); + if (mp->msgpool == NULL) { + if (pr == NULL) + panic("msgpool is NULL"); + else + return (ENOMEM); + } + mp->msgmaps = malloc(sizeof(struct msgmap) * mp->msginfo.msgseg, M_MSG, + M_WAITOK); + if (mp->msgmaps == NULL) { + if (pr == NULL) + panic("msgmaps is NULL"); + else { + error = ENOMEM; + goto fail_msgmaps; + } + } + mp->msghdrs = malloc(sizeof(struct msg) * mp->msginfo.msgtql, M_MSG, + M_WAITOK); + if (mp->msghdrs == NULL) { + if (pr == NULL) + panic("msghdrs is NULL"); + else { + error = ENOMEM; + goto fail_msghdrs; + } + } + mp->msqids = malloc(sizeof(struct msqid_ds) * mp->msginfo.msgmni, M_MSG, + M_WAITOK); + if (mp->msqids == NULL) { + if (pr == NULL) + panic("msqids is NULL"); + else { + error = ENOMEM; + goto fail_msqids; + } + } /* * msginfo.msgssz should be a power of two for efficiency reasons. @@ -149,49 +146,88 @@ */ i = 8; - while (i < 1024 && i != msginfo.msgssz) + while (i < 1024 && i != mp->msginfo.msgssz) i <<= 1; - if (i != msginfo.msgssz) { - printf("msginfo.msgssz=%d (0x%x)\n", msginfo.msgssz, - msginfo.msgssz); - panic("msginfo.msgssz not a small power of 2"); + if (i != mp->msginfo.msgssz) { + printf("msginfo.msgssz=%d (0x%x)\n", mp->msginfo.msgssz, + mp->msginfo.msgssz); + if (pr == NULL) + panic("msginfo.msgssz not a small power of 2"); + else { + error = EINVAL; + goto all; + } } - if (msginfo.msgseg > 32767) { - printf("msginfo.msgseg=%d\n", msginfo.msgseg); - panic("msginfo.msgseg > 32767"); + if (mp->msginfo.msgseg > 32767) { + printf("msginfo.msgseg=%d\n", mp->msginfo.msgseg); + if (pr == NULL) + panic("msginfo.msgseg > 32767"); + else { + error = EINVAL; + goto all; + } } - if (msgmaps == NULL) - panic("msgmaps is NULL"); + if (mp->msgmaps == NULL) { + if (pr == NULL) + panic("msgmaps is NULL"); + else { + error = EFAULT; + goto all; + } + } - for (i = 0; i < msginfo.msgseg; i++) { + for (i = 0; i < mp->msginfo.msgseg; i++) { if (i > 0) - msgmaps[i-1].next = i; - msgmaps[i].next = -1; /* implies entry is available */ + mp->msgmaps[i-1].next = i; + mp->msgmaps[i].next = -1; /* implies entry is available */ } - free_msgmaps = 0; - nfree_msgmaps = msginfo.msgseg; + mp->free_msgmaps = 0; + mp->nfree_msgmaps = mp->msginfo.msgseg; - if (msghdrs == NULL) - panic("msghdrs is NULL"); + if (mp->msghdrs == NULL) { + if (pr == NULL) + panic("msghdrs is NULL"); + else { + error = EFAULT; + goto all; + } + } - for (i = 0; i < msginfo.msgtql; i++) { - msghdrs[i].msg_type = 0; + for (i = 0; i < mp->msginfo.msgtql; i++) { + mp->msghdrs[i].msg_type = 0; if (i > 0) - msghdrs[i-1].msg_next = &msghdrs[i]; - msghdrs[i].msg_next = NULL; + mp->msghdrs[i-1].msg_next = &mp->msghdrs[i]; + mp->msghdrs[i].msg_next = NULL; } - free_msghdrs = &msghdrs[0]; + mp->free_msghdrs = &mp->msghdrs[0]; - if (msqids == NULL) - panic("msqids is NULL"); + if (mp->msqids == NULL) { + if (pr == NULL) + panic("msqids is NULL"); + else { + error = EFAULT; + goto all; + } + } - 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; + for (i = 0; i < mp->msginfo.msgmni; i++) { + mp->msqids[i].msg_qbytes = 0; /* implies entry is available */ + mp->msqids[i].msg_perm.seq = 0; /* reset to a known value */ + mp->msqids[i].msg_perm.mode = 0; } + + return (0); +all: +fail_msqids: + free(mp->msghdrs, M_MSG); +fail_msghdrs: + free(mp->msgmaps, M_MSG); +fail_msgmaps: + free(mp->msgpool, M_MSG); + + return (error); } SYSINIT(sysv_msg, SI_SUB_SYSV_MSG, SI_ORDER_FIRST, msginit, NULL) @@ -224,24 +260,34 @@ msg_freehdr(msghdr) struct msg *msghdr; { + struct msgpriv *mp; + + KASSERT(curproc != NULL, ("msg_freehdr: curproc is NULL")); + if (curproc->p_prison == NULL) + mp = &mainmsg; + else + mp = &curproc->p_prison->pr_msg; + while (msghdr->msg_ts > 0) { short next; - if (msghdr->msg_spot < 0 || msghdr->msg_spot >= msginfo.msgseg) + if (msghdr->msg_spot < 0 || + msghdr->msg_spot >= mp->msginfo.msgseg) { panic("msghdr->msg_spot out of range"); - next = msgmaps[msghdr->msg_spot].next; - msgmaps[msghdr->msg_spot].next = free_msgmaps; - free_msgmaps = msghdr->msg_spot; - nfree_msgmaps++; + } + next = mp->msgmaps[msghdr->msg_spot].next; + mp->msgmaps[msghdr->msg_spot].next = mp->free_msgmaps; + mp->free_msgmaps = msghdr->msg_spot; + mp->nfree_msgmaps++; msghdr->msg_spot = next; - if (msghdr->msg_ts >= msginfo.msgssz) - msghdr->msg_ts -= msginfo.msgssz; + if (msghdr->msg_ts >= mp->msginfo.msgssz) + msghdr->msg_ts -= mp->msginfo.msgssz; else msghdr->msg_ts = 0; } if (msghdr->msg_spot != -1) panic("msghdr->msg_spot != -1"); - msghdr->msg_next = free_msghdrs; - free_msghdrs = msghdr; + msghdr->msg_next = mp->free_msghdrs; + mp->free_msghdrs = msghdr; } #ifndef _SYS_SYSPROTO_H_ @@ -263,6 +309,7 @@ int rval, eval; struct msqid_ds msqbuf; register struct msqid_ds *msqptr; + struct msgpriv *mp; #ifdef MSG_DEBUG_OK printf("call to msgctl(%d, %d, 0x%x)\n", msqid, cmd, user_msqptr); @@ -271,17 +318,22 @@ if (!jail_sysvipc_allowed && p->p_prison != NULL) return (ENOSYS); + if (p->p_prison == NULL) + mp = &mainmsg; + else + mp = &p->p_prison->pr_msg; + msqid = IPCID_TO_IX(msqid); - if (msqid < 0 || msqid >= msginfo.msgmni) { + if (msqid < 0 || msqid >= mp->msginfo.msgmni) { #ifdef MSG_DEBUG_OK printf("msqid (%d) out of range (0<=msqid<%d)\n", msqid, - msginfo.msgmni); + mp->msginfo.msgmni); #endif return(EINVAL); } - msqptr = &msqids[msqid]; + msqptr = &(mp->msqids[msqid]); if (msqptr->msg_qbytes == 0) { #ifdef MSG_DEBUG_OK @@ -341,12 +393,13 @@ if (eval) return(eval); } - if (msqbuf.msg_qbytes > msginfo.msgmnb) { + if (msqbuf.msg_qbytes > mp->msginfo.msgmnb) { #ifdef MSG_DEBUG_OK printf("can't increase msg_qbytes beyond %d (truncating)\n", - msginfo.msgmnb); + mp->msginfo.msgmnb); #endif - msqbuf.msg_qbytes = msginfo.msgmnb; /* silently restrict qbytes to system limit */ + /* silently restrict qbytes to system limit */ + msqbuf.msg_qbytes = mp->msginfo.msgmnb; } if (msqbuf.msg_qbytes == 0) { #ifdef MSG_DEBUG_OK @@ -402,6 +455,7 @@ int msgflg = uap->msgflg; struct ucred *cred = p->p_ucred; register struct msqid_ds *msqptr = NULL; + struct msgpriv *mp; #ifdef MSG_DEBUG_OK printf("msgget(0x%x, 0%o)\n", key, msgflg); @@ -410,14 +464,19 @@ if (!jail_sysvipc_allowed && p->p_prison != NULL) return (ENOSYS); + if (p->p_prison == NULL) + mp = &mainmsg; + else + mp = &p->p_prison->pr_msg; + if (key != IPC_PRIVATE) { - for (msqid = 0; msqid < msginfo.msgmni; msqid++) { - msqptr = &msqids[msqid]; + for (msqid = 0; msqid < mp->msginfo.msgmni; msqid++) { + msqptr = &(mp->msqids[msqid]); if (msqptr->msg_qbytes != 0 && msqptr->msg_perm.key == key) break; } - if (msqid < msginfo.msgmni) { + if (msqid < mp->msginfo.msgmni) { #ifdef MSG_DEBUG_OK printf("found public key\n"); #endif @@ -442,19 +501,19 @@ printf("need to allocate the msqid_ds\n"); #endif if (key == IPC_PRIVATE || (msgflg & IPC_CREAT)) { - for (msqid = 0; msqid < msginfo.msgmni; msqid++) { + for (msqid = 0; msqid < mp->msginfo.msgmni; msqid++) { /* * Look for an unallocated and unlocked msqid_ds. * msqid_ds's can be locked by msgsnd or msgrcv while * they are copying the message in/out. We can't * re-use the entry until they release it. */ - msqptr = &msqids[msqid]; + msqptr = &(mp->msqids[msqid]); if (msqptr->msg_qbytes == 0 && (msqptr->msg_perm.mode & MSG_LOCKED) == 0) break; } - if (msqid == msginfo.msgmni) { + if (msqid == mp->msginfo.msgmni) { #ifdef MSG_DEBUG_OK printf("no more msqid_ds's available\n"); #endif @@ -475,7 +534,7 @@ msqptr->msg_last = NULL; msqptr->msg_cbytes = 0; msqptr->msg_qnum = 0; - msqptr->msg_qbytes = msginfo.msgmnb; + msqptr->msg_qbytes = mp->msginfo.msgmnb; msqptr->msg_lspid = 0; msqptr->msg_lrpid = 0; msqptr->msg_stime = 0; @@ -516,6 +575,7 @@ register struct msqid_ds *msqptr; register struct msg *msghdr; short next; + struct msgpriv *mp; #ifdef MSG_DEBUG_OK printf("call to msgsnd(%d, 0x%x, %d, %d)\n", msqid, user_msgp, msgsz, @@ -525,17 +585,22 @@ if (!jail_sysvipc_allowed && p->p_prison != NULL) return (ENOSYS); + if (p->p_prison == NULL) + mp = &mainmsg; + else + mp = &p->p_prison->pr_msg; + msqid = IPCID_TO_IX(msqid); - if (msqid < 0 || msqid >= msginfo.msgmni) { + if (msqid < 0 || msqid >= mp->msginfo.msgmni) { #ifdef MSG_DEBUG_OK printf("msqid (%d) out of range (0<=msqid<%d)\n", msqid, - msginfo.msgmni); + mp->msginfo.msgmni); #endif return(EINVAL); } - msqptr = &msqids[msqid]; + msqptr = &(mp->msqids[msqid]); if (msqptr->msg_qbytes == 0) { #ifdef MSG_DEBUG_OK printf("no such message queue id\n"); @@ -556,10 +621,10 @@ return(eval); } - segs_needed = (msgsz + msginfo.msgssz - 1) / msginfo.msgssz; + segs_needed = (msgsz + mp->msginfo.msgssz - 1) / mp->msginfo.msgssz; #ifdef MSG_DEBUG_OK - printf("msgsz=%d, msgssz=%d, segs_needed=%d\n", msgsz, msginfo.msgssz, - segs_needed); + printf("msgsz=%d, msgssz=%d, segs_needed=%d\n", msgsz, + mp->msginfo.msgssz, segs_needed); #endif for (;;) { int need_more_resources = 0; @@ -588,13 +653,13 @@ #endif need_more_resources = 1; } - if (segs_needed > nfree_msgmaps) { + if (segs_needed > mp->nfree_msgmaps) { #ifdef MSG_DEBUG_OK printf("segs_needed > nfree_msgmaps\n"); #endif need_more_resources = 1; } - if (free_msghdrs == NULL) { + if (mp->free_msghdrs == NULL) { #ifdef MSG_DEBUG_OK printf("no more msghdrs\n"); #endif @@ -668,11 +733,11 @@ if (msqptr->msg_perm.mode & MSG_LOCKED) panic("msg_perm.mode & MSG_LOCKED"); - if (segs_needed > nfree_msgmaps) + if (segs_needed > mp->nfree_msgmaps) panic("segs_needed > nfree_msgmaps"); if (msgsz + msqptr->msg_cbytes > msqptr->msg_qbytes) panic("msgsz + msg_cbytes > msg_qbytes"); - if (free_msghdrs == NULL) + if (mp->free_msghdrs == NULL) panic("no more msghdrs"); /* @@ -688,8 +753,8 @@ * Allocate a message header */ - msghdr = free_msghdrs; - free_msghdrs = msghdr->msg_next; + msghdr = mp->free_msghdrs; + mp->free_msghdrs = msghdr->msg_next; msghdr->msg_spot = -1; msghdr->msg_ts = msgsz; @@ -698,21 +763,21 @@ */ while (segs_needed > 0) { - if (nfree_msgmaps <= 0) + if (mp->nfree_msgmaps <= 0) panic("not enough msgmaps"); - if (free_msgmaps == -1) + if (mp->free_msgmaps == -1) panic("nil free_msgmaps"); - next = free_msgmaps; + next = mp->free_msgmaps; if (next <= -1) panic("next too low #1"); - if (next >= msginfo.msgseg) + if (next >= mp->msginfo.msgseg) panic("next out of range #1"); #ifdef MSG_DEBUG_OK printf("allocating segment %d to message\n", next); #endif - free_msgmaps = msgmaps[next].next; - nfree_msgmaps--; - msgmaps[next].next = msghdr->msg_spot; + mp->free_msgmaps = mp->msgmaps[next].next; + mp->nfree_msgmaps--; + mp->msgmaps[next].next = msghdr->msg_spot; msghdr->msg_spot = next; segs_needed--; } @@ -754,16 +819,16 @@ next = msghdr->msg_spot; while (msgsz > 0) { size_t tlen; - if (msgsz > msginfo.msgssz) - tlen = msginfo.msgssz; + if (msgsz > mp->msginfo.msgssz) + tlen = mp->msginfo.msgssz; else tlen = msgsz; if (next <= -1) panic("next too low #2"); - if (next >= msginfo.msgseg) + if (next >= mp->msginfo.msgseg) panic("next out of range #2"); - if ((eval = copyin(user_msgp, &msgpool[next * msginfo.msgssz], - tlen)) != 0) { + if ((eval = copyin(user_msgp, + &mp->msgpool[next * mp->msginfo.msgssz], tlen)) != 0) { #ifdef MSG_DEBUG_OK printf("error %d copying in message segment\n", eval); #endif @@ -774,7 +839,7 @@ } msgsz -= tlen; user_msgp = (char *)user_msgp + tlen; - next = msgmaps[next].next; + next = mp->msgmaps[next].next; } if (next != -1) panic("didn't use all the msg segments"); @@ -843,6 +908,7 @@ register struct msg *msghdr; int eval; short next; + struct msgpriv *mp; #ifdef MSG_DEBUG_OK printf("call to msgrcv(%d, 0x%x, %d, %ld, %d)\n", msqid, user_msgp, @@ -852,17 +918,22 @@ if (!jail_sysvipc_allowed && p->p_prison != NULL) return (ENOSYS); + if (p->p_prison == NULL) + mp = &mainmsg; + else + mp = &p->p_prison->pr_msg; + msqid = IPCID_TO_IX(msqid); - if (msqid < 0 || msqid >= msginfo.msgmni) { + if (msqid < 0 || msqid >= mp->msginfo.msgmni) { #ifdef MSG_DEBUG_OK printf("msqid (%d) out of range (0<=msqid<%d)\n", msqid, - msginfo.msgmni); + mp->msginfo.msgmni); #endif return(EINVAL); } - msqptr = &msqids[msqid]; + msqptr = &(mp->msqids[msqid]); if (msqptr->msg_qbytes == 0) { #ifdef MSG_DEBUG_OK printf("no such message queue id\n"); @@ -1065,18 +1136,18 @@ */ next = msghdr->msg_spot; - for (len = 0; len < msgsz; len += msginfo.msgssz) { + for (len = 0; len < msgsz; len += mp->msginfo.msgssz) { size_t tlen; - if (msgsz - len > msginfo.msgssz) - tlen = msginfo.msgssz; + if (msgsz - len > mp->msginfo.msgssz) + tlen = mp->msginfo.msgssz; else tlen = msgsz - len; if (next <= -1) panic("next too low #3"); - if (next >= msginfo.msgseg) + if (next >= mp->msginfo.msgseg) panic("next out of range #3"); - eval = copyout((caddr_t)&msgpool[next * msginfo.msgssz], + eval = copyout((caddr_t)&mp->msgpool[next * mp->msginfo.msgssz], user_msgp, tlen); if (eval != 0) { #ifdef MSG_DEBUG_OK @@ -1088,7 +1159,7 @@ return(eval); } user_msgp = (char *)user_msgp + tlen; - next = msgmaps[next].next; + next = mp->msgmaps[next].next; } /* @@ -1101,24 +1172,155 @@ return(0); } -static int -sysctl_msqids(SYSCTL_HANDLER_ARGS) +void +msgclear(struct prison *pr) { + struct msgpriv *mp; - return (SYSCTL_OUT(req, msqids, - sizeof(struct msqid_ds) * msginfo.msgmni)); + if (pr == NULL) + mp = &mainmsg; + else + mp = &pr->pr_msg; + + free(mp->msgpool, M_MSG); + free(mp->msgmaps, M_MSG); + free(mp->msghdrs, M_MSG); + free(mp->msqids, M_MSG); } -TUNABLE_INT("kern.ipc.msgseg", &msginfo.msgseg); -TUNABLE_INT("kern.ipc.msgssz", &msginfo.msgssz); -TUNABLE_INT("kern.ipc.msgmni", &msginfo.msgmni); +/* XXX: Should it stay? */ +TUNABLE_INT("kern.ipc.msgseg", &mainmsg.msginfo.msgseg); +TUNABLE_INT("kern.ipc.msgssz", &mainmsg.msginfo.msgssz); +TUNABLE_INT("kern.ipc.msgmni", &mainmsg.msginfo.msgmni); SYSCTL_DECL(_kern_ipc); -SYSCTL_INT(_kern_ipc, OID_AUTO, msgmax, CTLFLAG_RD, &msginfo.msgmax, 0, ""); -SYSCTL_INT(_kern_ipc, OID_AUTO, msgmni, CTLFLAG_RD, &msginfo.msgmni, 0, ""); -SYSCTL_INT(_kern_ipc, OID_AUTO, msgmnb, CTLFLAG_RD, &msginfo.msgmnb, 0, ""); -SYSCTL_INT(_kern_ipc, OID_AUTO, msgtql, CTLFLAG_RD, &msginfo.msgtql, 0, ""); -SYSCTL_INT(_kern_ipc, OID_AUTO, msgssz, CTLFLAG_RD, &msginfo.msgssz, 0, ""); -SYSCTL_INT(_kern_ipc, OID_AUTO, msgseg, CTLFLAG_RD, &msginfo.msgseg, 0, ""); + +static int +sysctl_msqids(SYSCTL_HANDLER_ARGS) +{ + struct msgpriv *mp; + + if (req->p->p_prison == NULL) + mp = &mainmsg; + else + mp = &req->p->p_prison->pr_msg; + + return (SYSCTL_OUT(req, mp->msqids, + sizeof(struct msqid_ds) * mp->msginfo.msgmni)); +} SYSCTL_PROC(_kern_ipc, OID_AUTO, msqids, CTLFLAG_RD, NULL, 0, sysctl_msqids, "", "Message queue IDs"); + +static int +sysctl_msginfo(SYSCTL_HANDLER_ARGS) +{ + struct msgpriv *mp; + + if (req->p->p_prison == NULL) + mp = &mainmsg; + else + mp = &req->p->p_prison->pr_msg; + + return (sysctl_handle_opaque(oidp, &mp->msginfo, sizeof(struct msginfo), + req)); +} +SYSCTL_PROC(_kern_ipc, OID_AUTO, msginfo, CTLTYPE_STRUCT | CTLFLAG_RD, 0, 0, + sysctl_msginfo, "S,msginfo",""); + +#define IPC_MSGMAX 0 +#define IPC_MSGMNI 1 +#define IPC_MSGMNB 2 +#define IPC_MSGTQL 3 +#define IPC_MSGSSZ 4 +#define IPC_MSGSEG 5 + +static int +sysctl_msginfo_val(struct sysctl_oid *oidp, struct sysctl_req *req, u_int type) +{ + int *msginfo; + struct msgpriv *mp; + + if (req->p->p_prison == NULL) + mp = &mainmsg; + else + mp = &req->p->p_prison->pr_msg; + + switch (type) { + case IPC_MSGMAX: + msginfo = &mp->msginfo.msgmax; + break; + case IPC_MSGMNI: + msginfo = &mp->msginfo.msgmni; + break; + case IPC_MSGMNB: + msginfo = &mp->msginfo.msgmnb; + break; + case IPC_MSGTQL: + msginfo = &mp->msginfo.msgtql; + break; + case IPC_MSGSSZ: + msginfo = &mp->msginfo.msgssz; + break; + case IPC_MSGSEG: + msginfo = &mp->msginfo.msgseg; + break; + default: + panic("unknown msg type"); + } + + return (sysctl_handle_int(oidp, msginfo, 0, req)); +} + +static int +sysctl_msginfo_msgmax(SYSCTL_HANDLER_ARGS) +{ + + return (sysctl_msginfo_val(oidp, req, IPC_MSGMAX)); +} +SYSCTL_PROC(_kern_ipc, OID_AUTO, msgmax, CTLTYPE_INT|CTLFLAG_RD, 0, 0, + sysctl_msginfo_msgmax, "IU", ""); + +static int +sysctl_msginfo_msgmni(SYSCTL_HANDLER_ARGS) +{ + + return (sysctl_msginfo_val(oidp, req, IPC_MSGMNI)); +} +SYSCTL_PROC(_kern_ipc, OID_AUTO, msgmni, CTLTYPE_INT|CTLFLAG_RD, 0, 0, + sysctl_msginfo_msgmni, "IU", ""); + +static int +sysctl_msginfo_msgmnb(SYSCTL_HANDLER_ARGS) +{ + + return (sysctl_msginfo_val(oidp, req, IPC_MSGMNB)); +} +SYSCTL_PROC(_kern_ipc, OID_AUTO, msgmnb, CTLTYPE_INT|CTLFLAG_RD, 0, 0, + sysctl_msginfo_msgmnb, "IU", ""); + +static int +sysctl_msginfo_msgtql(SYSCTL_HANDLER_ARGS) +{ + + return (sysctl_msginfo_val(oidp, req, IPC_MSGTQL)); +} +SYSCTL_PROC(_kern_ipc, OID_AUTO, msgtql, CTLTYPE_INT|CTLFLAG_RD, 0, 0, + sysctl_msginfo_msgtql, "IU", ""); + +static int +sysctl_msginfo_msgssz(SYSCTL_HANDLER_ARGS) +{ + + return (sysctl_msginfo_val(oidp, req, IPC_MSGSSZ)); +} +SYSCTL_PROC(_kern_ipc, OID_AUTO, msgssz, CTLTYPE_INT|CTLFLAG_RD, 0, 0, + sysctl_msginfo_msgssz, "IU", ""); + +static int +sysctl_msginfo_msgseg(SYSCTL_HANDLER_ARGS) +{ + + return (sysctl_msginfo_val(oidp, req, IPC_MSGSEG)); +} +SYSCTL_PROC(_kern_ipc, OID_AUTO, msgseg, CTLTYPE_INT|CTLFLAG_RD, 0, 0, + sysctl_msginfo_msgseg, "IU", ""); diff -ru /sys/kern/sysv_sem.c sys/kern/sysv_sem.c --- /sys/kern/sysv_sem.c Wed Feb 19 19:29:13 2003 +++ sys/kern/sysv_sem.c Wed Feb 19 18:27:06 2003 @@ -1,9 +1,10 @@ -/* $FreeBSD: src/sys/kern/sysv_sem.c,v 1.24.2.8 2002/10/22 20:45:03 fjoe Exp $ */ +/* $FreeBSD$ */ /* * Implementation of SVID semaphores * * Author: Daniel Boulet + * Jailed by: Pawel Jakub Dawidek <[EMAIL PROTECTED]> * * This software is provided ``AS IS'' without any warranties of any kind. */ @@ -23,8 +24,6 @@ static MALLOC_DEFINE(M_SEM, "sem", "SVID compatible semaphores"); -static void seminit __P((void *)); - #ifndef _SYS_SYSPROTO_H_ struct __semctl_args; int __semctl __P((struct proc *p, struct __semctl_args *uap)); @@ -45,33 +44,6 @@ (sy_call_t *)semop }; -static int semtot = 0; -static struct semid_ds *sema; /* semaphore id pool */ -static struct sem *sem; /* semaphore pool */ -static struct sem_undo *semu_list; /* list of active undo structures */ -static int *semu; /* undo structure pool */ - -struct sem { - u_short semval; /* semaphore value */ - pid_t sempid; /* pid of last operation */ - u_short semncnt; /* # awaiting semval > cval */ - u_short semzcnt; /* # awaiting semval = 0 */ -}; - -/* - * Undo structure (one per process) - */ -struct sem_undo { - struct sem_undo *un_next; /* ptr to next active undo structure */ - struct proc *un_proc; /* owner of this structure */ - short un_cnt; /* # of active entries */ - struct undo { - short un_adjval; /* adjust on exit values */ - short un_num; /* semaphore # */ - int un_id; /* semid */ - } un_ent[1]; /* undo entries */ -}; - /* * Configuration parameters */ @@ -115,46 +87,7 @@ /* * Macro to find a particular sem_undo vector */ -#define SEMU(ix) ((struct sem_undo *)(((intptr_t)semu)+ix * seminfo.semusz)) - -/* - * semaphore info struct - */ -struct seminfo seminfo = { - SEMMAP, /* # of entries in semaphore map */ - SEMMNI, /* # of semaphore identifiers */ - SEMMNS, /* # of semaphores in system */ - SEMMNU, /* # of undo structures in system */ - SEMMSL, /* max # of semaphores per id */ - SEMOPM, /* max # of operations per semop call */ - SEMUME, /* max # of undo entries per process */ - SEMUSZ, /* size in bytes of undo structure */ - SEMVMX, /* semaphore maximum value */ - SEMAEM /* adjust on exit max value */ -}; - -TUNABLE_INT("kern.ipc.semmap", &seminfo.semmap); -TUNABLE_INT("kern.ipc.semmni", &seminfo.semmni); -TUNABLE_INT("kern.ipc.semmns", &seminfo.semmns); -TUNABLE_INT("kern.ipc.semmnu", &seminfo.semmnu); -TUNABLE_INT("kern.ipc.semmsl", &seminfo.semmsl); -TUNABLE_INT("kern.ipc.semopm", &seminfo.semopm); -TUNABLE_INT("kern.ipc.semume", &seminfo.semume); -TUNABLE_INT("kern.ipc.semusz", &seminfo.semusz); -TUNABLE_INT("kern.ipc.semvmx", &seminfo.semvmx); -TUNABLE_INT("kern.ipc.semaem", &seminfo.semaem); - -SYSCTL_DECL(_kern_ipc); -SYSCTL_INT(_kern_ipc, OID_AUTO, semmap, CTLFLAG_RW, &seminfo.semmap, 0, ""); -SYSCTL_INT(_kern_ipc, OID_AUTO, semmni, CTLFLAG_RD, &seminfo.semmni, 0, ""); -SYSCTL_INT(_kern_ipc, OID_AUTO, semmns, CTLFLAG_RD, &seminfo.semmns, 0, ""); -SYSCTL_INT(_kern_ipc, OID_AUTO, semmnu, CTLFLAG_RD, &seminfo.semmnu, 0, ""); -SYSCTL_INT(_kern_ipc, OID_AUTO, semmsl, CTLFLAG_RW, &seminfo.semmsl, 0, ""); -SYSCTL_INT(_kern_ipc, OID_AUTO, semopm, CTLFLAG_RD, &seminfo.semopm, 0, ""); -SYSCTL_INT(_kern_ipc, OID_AUTO, semume, CTLFLAG_RD, &seminfo.semume, 0, ""); -SYSCTL_INT(_kern_ipc, OID_AUTO, semusz, CTLFLAG_RD, &seminfo.semusz, 0, ""); -SYSCTL_INT(_kern_ipc, OID_AUTO, semvmx, CTLFLAG_RW, &seminfo.semvmx, 0, ""); -SYSCTL_INT(_kern_ipc, OID_AUTO, semaem, CTLFLAG_RW, &seminfo.semaem, 0, ""); +#define SEMU(ix) ((struct sem_undo *)(((intptr_t)sp->semu)+ix * +sp->seminfo.semusz)) #if 0 RO seminfo.semmap /* SEMMAP unused */ @@ -169,31 +102,79 @@ RO seminfo.semaem /* SEMAEM unused - user param */ #endif -static void -seminit(dummy) - void *dummy; +/* Global struct for main system, all jails have its own. */ +struct sempriv mainsem; + +int +seminit(struct prison *pr) { register int i; + struct sempriv *sp; + int error; + + if (pr == NULL) + sp = &mainsem; + else + sp = &pr->pr_sem; + + sp->semtot = 0; + + sp->seminfo.semmap = SEMMAP; + sp->seminfo.semmni = SEMMNI; + sp->seminfo.semmns = SEMMNS; + sp->seminfo.semmnu = SEMMNU; + sp->seminfo.semmsl = SEMMSL; + sp->seminfo.semopm = SEMOPM; + sp->seminfo.semume = SEMUME; + sp->seminfo.semusz = SEMUSZ; + sp->seminfo.semvmx = SEMVMX; + sp->seminfo.semaem = SEMAEM; + + sp->sem = malloc(sizeof(struct sem) * sp->seminfo.semmns, M_SEM, M_WAITOK); + if (sp->sem == NULL) { + if (pr == NULL) + panic("sem is NULL"); + else + return (ENOMEM); + } - sem = malloc(sizeof(struct sem) * seminfo.semmns, M_SEM, M_WAITOK); - if (sem == NULL) - panic("sem is NULL"); - sema = malloc(sizeof(struct semid_ds) * seminfo.semmni, M_SEM, M_WAITOK); - if (sema == NULL) - panic("sema is NULL"); - semu = malloc(seminfo.semmnu * seminfo.semusz, M_SEM, M_WAITOK); - if (semu == NULL) - panic("semu is NULL"); - - for (i = 0; i < seminfo.semmni; i++) { - sema[i].sem_base = 0; - sema[i].sem_perm.mode = 0; + sp->sema = malloc(sizeof(struct semid_ds) * sp->seminfo.semmni, M_SEM, +M_WAITOK); + if (sp->sema == NULL) { + if (pr == NULL) + panic("sema is NULL"); + else { + error = ENOMEM; + goto fail_sema; + } + } + + sp->semu = malloc(sp->seminfo.semmnu * sp->seminfo.semusz, M_SEM, M_WAITOK); + if (sp->semu == NULL) { + if (pr == NULL) + panic("semu is NULL"); + else { + error = ENOMEM; + goto fail_semu; + } } - for (i = 0; i < seminfo.semmnu; i++) { + + for (i = 0; i < sp->seminfo.semmni; i++) { + sp->sema[i].sem_base = 0; + sp->sema[i].sem_perm.mode = 0; + } + for (i = 0; i < sp->seminfo.semmnu; i++) { register struct sem_undo *suptr = SEMU(i); suptr->un_proc = NULL; } - semu_list = NULL; + sp->semu_list = NULL; + + return (0); +fail_sema: + free(sp->sem, M_SEM); +fail_semu: + free(sp->sema, M_SEM); + + return (error); } SYSINIT(sysv_sem, SI_SUB_SYSV_SEM, SI_ORDER_FIRST, seminit, NULL) @@ -234,6 +215,12 @@ register struct sem_undo *suptr; register struct sem_undo **supptr; int attempt; + struct sempriv *sp; + + if (p->p_prison == NULL) + sp = &mainsem; + else + sp = &p->p_prison->pr_sem; /* * Try twice to allocate something. @@ -247,11 +234,11 @@ * Fill it in and return it if we find one. */ - for (i = 0; i < seminfo.semmnu; i++) { + for (i = 0; i < sp->seminfo.semmnu; i++) { suptr = SEMU(i); if (suptr->un_proc == NULL) { - suptr->un_next = semu_list; - semu_list = suptr; + suptr->un_next = sp->semu_list; + sp->semu_list = suptr; suptr->un_cnt = 0; suptr->un_proc = p; return(suptr); @@ -267,7 +254,7 @@ /* All the structures are in use - try to free some */ int did_something = 0; - supptr = &semu_list; + supptr = &sp->semu_list; while ((suptr = *supptr) != NULL) { if (suptr->un_cnt == 0) { suptr->un_proc = NULL; @@ -306,13 +293,19 @@ register struct sem_undo *suptr; register struct undo *sunptr; int i; + struct sempriv *sp; + + if (p->p_prison == NULL) + sp = &mainsem; + else + sp = &p->p_prison->pr_sem; /* Look for and remember the sem_undo if the caller doesn't provide it */ suptr = *supptr; if (suptr == NULL) { - for (suptr = semu_list; suptr != NULL; + for (suptr = sp->semu_list; suptr != NULL; suptr = suptr->un_next) { if (suptr->un_proc == p) { *supptr = suptr; @@ -353,7 +346,7 @@ /* Didn't find the right entry - create it */ if (adjval == 0) return(0); - if (suptr->un_cnt != seminfo.semume) { + if (suptr->un_cnt != sp->seminfo.semume) { sunptr = &suptr->un_ent[suptr->un_cnt]; suptr->un_cnt++; sunptr->un_adjval = adjval; @@ -368,8 +361,14 @@ int semid, semnum; { register struct sem_undo *suptr; + struct sempriv *sp; + + if (curproc->p_prison == NULL) + sp = &mainsem; + else + sp = &curproc->p_prison->pr_sem; - for (suptr = semu_list; suptr != NULL; suptr = suptr->un_next) { + for (suptr = sp->semu_list; suptr != NULL; suptr = suptr->un_next) { register struct undo *sunptr = &suptr->un_ent[0]; register int i = 0; @@ -417,6 +416,7 @@ int i, rval, eval; struct semid_ds sbuf; register struct semid_ds *semaptr; + struct sempriv *sp; #ifdef SEM_DEBUG printf("call to semctl(%d, %d, %d, 0x%x)\n", semid, semnum, cmd, arg); @@ -425,11 +425,16 @@ if (!jail_sysvipc_allowed && p->p_prison != NULL) return (ENOSYS); + if (p->p_prison == NULL) + sp = &mainsem; + else + sp = &p->p_prison->pr_sem; + semid = IPCID_TO_IX(semid); - if (semid < 0 || semid >= seminfo.semmni) + if (semid < 0 || semid >= sp->seminfo.semmni) return(EINVAL); - semaptr = &sema[semid]; + semaptr = &sp->sema[semid]; if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0 || semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid)) return(EINVAL); @@ -443,13 +448,13 @@ return(eval); 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]; - 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; + sp->semtot -= semaptr->sem_nsems; + for (i = semaptr->sem_base - sp->sem; i < sp->semtot; i++) + sp->sem[i] = sp->sem[i + semaptr->sem_nsems]; + for (i = 0; i < sp->seminfo.semmni; i++) { + if ((sp->sema[i].sem_perm.mode & SEM_ALLOC) && + sp->sema[i].sem_base > semaptr->sem_base) + sp->sema[i].sem_base -= semaptr->sem_nsems; } semaptr->sem_perm.mode = 0; semundo_clear(semid, -1); @@ -580,6 +585,7 @@ int nsems = uap->nsems; int semflg = uap->semflg; struct ucred *cred = p->p_ucred; + struct sempriv *sp; #ifdef SEM_DEBUG printf("semget(0x%x, %d, 0%o)\n", key, nsems, semflg); @@ -588,20 +594,25 @@ if (!jail_sysvipc_allowed && p->p_prison != NULL) return (ENOSYS); + if (p->p_prison == NULL) + sp = &mainsem; + else + sp = &p->p_prison->pr_sem; + 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) + for (semid = 0; semid < sp->seminfo.semmni; semid++) { + if ((sp->sema[semid].sem_perm.mode & SEM_ALLOC) && + sp->sema[semid].sem_perm.key == key) break; } - if (semid < seminfo.semmni) { + if (semid < sp->seminfo.semmni) { #ifdef SEM_DEBUG printf("found public key\n"); #endif - if ((eval = ipcperm(p, &sema[semid].sem_perm, + if ((eval = ipcperm(p, &sp->sema[semid].sem_perm, semflg & 0700))) return(eval); - if (nsems > 0 && sema[semid].sem_nsems < nsems) { + if (nsems > 0 && sp->sema[semid].sem_nsems < nsems) { #ifdef SEM_DEBUG printf("too small\n"); #endif @@ -621,25 +632,25 @@ printf("need to allocate the semid_ds\n"); #endif if (key == IPC_PRIVATE || (semflg & IPC_CREAT)) { - if (nsems <= 0 || nsems > seminfo.semmsl) { + if (nsems <= 0 || nsems > sp->seminfo.semmsl) { #ifdef SEM_DEBUG printf("nsems out of range (0<%d<=%d)\n", nsems, - seminfo.semmsl); + sp->seminfo.semmsl); #endif return(EINVAL); } - if (nsems > seminfo.semmns - semtot) { + if (nsems > sp->seminfo.semmns - sp->semtot) { #ifdef SEM_DEBUG printf("not enough semaphores left (need %d, got %d)\n", - nsems, seminfo.semmns - semtot); + nsems, sp->seminfo.semmns - sp->semtot); #endif return(ENOSPC); } - for (semid = 0; semid < seminfo.semmni; semid++) { - if ((sema[semid].sem_perm.mode & SEM_ALLOC) == 0) + for (semid = 0; semid < sp->seminfo.semmni; semid++) { + if ((sp->sema[semid].sem_perm.mode & SEM_ALLOC) == 0) break; } - if (semid == seminfo.semmni) { + if (semid == sp->seminfo.semmni) { #ifdef SEM_DEBUG printf("no more semid_ds's available\n"); #endif @@ -648,24 +659,24 @@ #ifdef SEM_DEBUG printf("semid %d is available\n", semid); #endif - 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]; - semtot += nsems; - bzero(sema[semid].sem_base, - sizeof(sema[semid].sem_base[0])*nsems); + sp->sema[semid].sem_perm.key = key; + sp->sema[semid].sem_perm.cuid = cred->cr_uid; + sp->sema[semid].sem_perm.uid = cred->cr_uid; + sp->sema[semid].sem_perm.cgid = cred->cr_gid; + sp->sema[semid].sem_perm.gid = cred->cr_gid; + sp->sema[semid].sem_perm.mode = (semflg & 0777) | SEM_ALLOC; + sp->sema[semid].sem_perm.seq = + (sp->sema[semid].sem_perm.seq + 1) & 0x7fff; + sp->sema[semid].sem_nsems = nsems; + sp->sema[semid].sem_otime = 0; + sp->sema[semid].sem_ctime = time_second; + sp->sema[semid].sem_base = &sp->sem[sp->semtot]; + sp->semtot += nsems; + bzero(sp->sema[semid].sem_base, + sizeof(sp->sema[semid].sem_base[0])*nsems); #ifdef SEM_DEBUG - printf("sembase = 0x%x, next = 0x%x\n", sema[semid].sem_base, - &sem[semtot]); + printf("sembase = 0x%x, next = 0x%x\n", sp->sema[semid].sem_base, + &sp->sem[sp->semtot]); #endif } else { #ifdef SEM_DEBUG @@ -675,7 +686,7 @@ } found: - p->p_retval[0] = IXSEQ_TO_IPCID(semid, sema[semid].sem_perm); + p->p_retval[0] = IXSEQ_TO_IPCID(semid, sp->sema[semid].sem_perm); return(0); } @@ -701,6 +712,7 @@ struct sem_undo *suptr = NULL; int i, j, eval; int do_wakeup, do_undos; + struct sempriv *sp; #ifdef SEM_DEBUG printf("call to semop(%d, 0x%x, %u)\n", semid, sops, nsops); @@ -709,12 +721,17 @@ if (!jail_sysvipc_allowed && p->p_prison != NULL) return (ENOSYS); + if (p->p_prison == NULL) + sp = &mainsem; + else + sp = &p->p_prison->pr_sem; + semid = IPCID_TO_IX(semid); /* Convert back to zero origin */ - if (semid < 0 || semid >= seminfo.semmni) + if (semid < 0 || semid >= sp->seminfo.semmni) return(EINVAL); - semaptr = &sema[semid]; + semaptr = &sp->sema[semid]; if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0) return(EINVAL); if (semaptr->sem_perm.seq != IPCID_TO_SEQ(uap->semid)) @@ -951,6 +968,12 @@ register struct sem_undo *suptr; register struct sem_undo **supptr; int did_something; + struct sempriv *sp; + + if (p->p_prison == NULL) + sp = &mainsem; + else + sp = &p->p_prison->pr_sem; did_something = 0; @@ -959,7 +982,7 @@ * associated with this process. */ - for (supptr = &semu_list; (suptr = *supptr) != NULL; + for (supptr = &sp->semu_list; (suptr = *supptr) != NULL; supptr = &suptr->un_next) { if (suptr->un_proc == p) break; @@ -985,7 +1008,7 @@ int adjval = suptr->un_ent[ix].un_adjval; struct semid_ds *semaptr; - semaptr = &sema[semid]; + semaptr = &sp->sema[semid]; if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0) panic("semexit - semid not allocated"); if (semnum >= semaptr->sem_nsems) @@ -1024,3 +1047,213 @@ suptr->un_proc = NULL; *supptr = suptr->un_next; } + +void +semclear(struct prison *pr) +{ + struct sempriv *sp; + + if (pr == NULL) + sp = &mainsem; + else + sp = &pr->pr_sem; + + free(sp->sem, M_SEM); + free(sp->sema, M_SEM); + free(sp->semu, M_SEM); +} + +TUNABLE_INT("kern.ipc.semmap", &mainsem.seminfo.semmap); +TUNABLE_INT("kern.ipc.semmni", &mainsem.seminfo.semmni); +TUNABLE_INT("kern.ipc.semmns", &mainsem.seminfo.semmns); +TUNABLE_INT("kern.ipc.semmnu", &mainsem.seminfo.semmnu); +TUNABLE_INT("kern.ipc.semmsl", &mainsem.seminfo.semmsl); +TUNABLE_INT("kern.ipc.semopm", &mainsem.seminfo.semopm); +TUNABLE_INT("kern.ipc.semume", &mainsem.seminfo.semume); +TUNABLE_INT("kern.ipc.semusz", &mainsem.seminfo.semusz); +TUNABLE_INT("kern.ipc.semvmx", &mainsem.seminfo.semvmx); +TUNABLE_INT("kern.ipc.semaem", &mainsem.seminfo.semaem); + +SYSCTL_DECL(_kern_ipc); + +static int +sysctl_sema(SYSCTL_HANDLER_ARGS) +{ + struct sempriv *sp; + + if (req->p->p_prison == NULL) + sp = &mainsem; + else + sp = &req->p->p_prison->pr_sem; + + return (SYSCTL_OUT(req, sp->sema, + sizeof(struct semid_ds) * sp->seminfo.semmni)); +} +SYSCTL_PROC(_kern_ipc, OID_AUTO, sema, CTLFLAG_RD, + NULL, 0, sysctl_sema, "", "Semaphores IDs"); + +static int +sysctl_seminfo(SYSCTL_HANDLER_ARGS) +{ + struct sempriv *sp; + + if (req->p->p_prison == NULL) + sp = &mainsem; + else + sp = &req->p->p_prison->pr_sem; + + return (sysctl_handle_opaque(oidp, &sp->seminfo, sizeof(struct seminfo), + req)); +} +SYSCTL_PROC(_kern_ipc, OID_AUTO, seminfo, CTLTYPE_STRUCT | CTLFLAG_RD, 0, 0, + sysctl_seminfo, "S,seminfo",""); + +#define IPC_SEMMAP 0 +#define IPC_SEMMNI 1 +#define IPC_SEMMNS 2 +#define IPC_SEMMNU 3 +#define IPC_SEMMSL 4 +#define IPC_SEMOPM 5 +#define IPC_SEMUME 6 +#define IPC_SEMUSZ 7 +#define IPC_SEMVMX 8 +#define IPC_SEMAEM 9 + +static int +sysctl_seminfo_val(struct sysctl_oid *oidp, struct sysctl_req *req, u_int type) +{ + int *seminfo; + struct sempriv *sp; + + if (req->p->p_prison == NULL) + sp = &mainsem; + else + sp = &req->p->p_prison->pr_sem; + + switch (type) { + case IPC_SEMMAP: + seminfo = &sp->seminfo.semmap; + break; + case IPC_SEMMNI: + seminfo = &sp->seminfo.semmni; + break; + case IPC_SEMMNS: + seminfo = &sp->seminfo.semmns; + break; + case IPC_SEMMNU: + seminfo = &sp->seminfo.semmnu; + break; + case IPC_SEMMSL: + seminfo = &sp->seminfo.semmsl; + break; + case IPC_SEMOPM: + seminfo = &sp->seminfo.semopm; + break; + case IPC_SEMUME: + seminfo = &sp->seminfo.semume; + break; + case IPC_SEMUSZ: + seminfo = &sp->seminfo.semume; + break; + case IPC_SEMVMX: + seminfo = &sp->seminfo.semvmx; + break; + case IPC_SEMAEM: + seminfo = &sp->seminfo.semaem; + break; + default: + panic("unknown sem type"); + } + + return (sysctl_handle_int(oidp, seminfo, 0, req)); +} + +static int +sysctl_seminfo_semmap(SYSCTL_HANDLER_ARGS) +{ + + return (sysctl_seminfo_val(oidp, req, IPC_SEMMAP)); +} +SYSCTL_PROC(_kern_ipc, OID_AUTO, semmap, CTLTYPE_INT | CTLFLAG_RD, 0, 0, + sysctl_seminfo_semmap, "IU", ""); + +static int +sysctl_seminfo_semmni(SYSCTL_HANDLER_ARGS) +{ + + return (sysctl_seminfo_val(oidp, req, IPC_SEMMNI)); +} +SYSCTL_PROC(_kern_ipc, OID_AUTO, semmni, CTLTYPE_INT | CTLFLAG_RD, 0, 0, + sysctl_seminfo_semmni, "IU", ""); + +static int +sysctl_seminfo_semmns(SYSCTL_HANDLER_ARGS) +{ + + return (sysctl_seminfo_val(oidp, req, IPC_SEMMNS)); +} +SYSCTL_PROC(_kern_ipc, OID_AUTO, semmns, CTLTYPE_INT | CTLFLAG_RD, 0, 0, + sysctl_seminfo_semmns, "IU", ""); + +static int +sysctl_seminfo_semmnu(SYSCTL_HANDLER_ARGS) +{ + + return (sysctl_seminfo_val(oidp, req, IPC_SEMMNU)); +} +SYSCTL_PROC(_kern_ipc, OID_AUTO, semmnu, CTLTYPE_INT | CTLFLAG_RD, 0, 0, + sysctl_seminfo_semmnu, "IU", ""); + +static int +sysctl_seminfo_semmsl(SYSCTL_HANDLER_ARGS) +{ + + return (sysctl_seminfo_val(oidp, req, IPC_SEMMSL)); +} +SYSCTL_PROC(_kern_ipc, OID_AUTO, semmsl, CTLTYPE_INT | CTLFLAG_RD, 0, 0, + sysctl_seminfo_semmsl, "IU", ""); + +static int +sysctl_seminfo_semopm(SYSCTL_HANDLER_ARGS) +{ + + return (sysctl_seminfo_val(oidp, req, IPC_SEMOPM)); +} +SYSCTL_PROC(_kern_ipc, OID_AUTO, semopm, CTLTYPE_INT | CTLFLAG_RD, 0, 0, + sysctl_seminfo_semopm, "IU", ""); + +static int +sysctl_seminfo_semume(SYSCTL_HANDLER_ARGS) +{ + + return (sysctl_seminfo_val(oidp, req, IPC_SEMUME)); +} +SYSCTL_PROC(_kern_ipc, OID_AUTO, semume, CTLTYPE_INT | CTLFLAG_RD, 0, 0, + sysctl_seminfo_semume, "IU", ""); + +static int +sysctl_seminfo_semusz(SYSCTL_HANDLER_ARGS) +{ + + return (sysctl_seminfo_val(oidp, req, IPC_SEMUSZ)); +} +SYSCTL_PROC(_kern_ipc, OID_AUTO, semusz, CTLTYPE_INT | CTLFLAG_RD, 0, 0, + sysctl_seminfo_semusz, "IU", ""); + +static int +sysctl_seminfo_semvmx(SYSCTL_HANDLER_ARGS) +{ + + return (sysctl_seminfo_val(oidp, req, IPC_SEMVMX)); +} +SYSCTL_PROC(_kern_ipc, OID_AUTO, semvmx, CTLTYPE_INT | CTLFLAG_RD, 0, 0, + sysctl_seminfo_semvmx, "IU", ""); + +static int +sysctl_seminfo_semaem(SYSCTL_HANDLER_ARGS) +{ + + return (sysctl_seminfo_val(oidp, req, IPC_SEMAEM)); +} +SYSCTL_PROC(_kern_ipc, OID_AUTO, semaem, CTLTYPE_INT | CTLFLAG_RD, 0, 0, + sysctl_seminfo_semaem, "IU", ""); diff -ru /sys/kern/sysv_shm.c sys/kern/sysv_shm.c --- /sys/kern/sysv_shm.c Wed Feb 19 19:29:13 2003 +++ sys/kern/sysv_shm.c Wed Feb 19 18:27:12 2003 @@ -1,8 +1,9 @@ -/* $FreeBSD: src/sys/kern/sysv_shm.c,v 1.45.2.6 2002/10/22 20:45:03 fjoe Exp $ */ +/* $FreeBSD$ */ /* $NetBSD: sysv_shm.c,v 1.23 1994/07/04 23:25:12 glass Exp $ */ /* * Copyright (c) 1994 Adam Glass and Charles Hannum. All rights reserved. + * Jailed by: Pawel Jakub Dawidek <[EMAIL PROTECTED]> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -76,9 +77,6 @@ #define SHMSEG_ALLOCATED 0x0800 #define SHMSEG_WANTED 0x1000 -static int shm_last_free, shm_nused, shm_committed, shmalloced; -static struct shmid_ds *shmsegs; - struct shm_handle { /* vm_offset_t kva; */ vm_object_t shm_object; @@ -94,7 +92,6 @@ static struct shmid_ds *shm_find_segment_by_shmid __P((int)); static int shm_delete_mapping __P((struct proc *, struct shmmap_state *)); static void shmrealloc __P((void)); -static void shminit __P((void *)); /* * Tuneable values @@ -118,39 +115,24 @@ #define SHMALL (SHMMAXPGS) #endif -struct shminfo shminfo = { - SHMMAX, - SHMMIN, - SHMMNI, - SHMSEG, - SHMALL -}; - -static int shm_use_phys; - -TUNABLE_INT("kern.ipc.shmmin", &shminfo.shmmin); -TUNABLE_INT("kern.ipc.shmmni", &shminfo.shmmni); -TUNABLE_INT("kern.ipc.shmseg", &shminfo.shmseg); -TUNABLE_INT("kern.ipc.shmmaxpgs", &shminfo.shmall); -TUNABLE_INT("kern.ipc.shm_use_phys", &shm_use_phys); - -SYSCTL_DECL(_kern_ipc); -SYSCTL_INT(_kern_ipc, OID_AUTO, shmmax, CTLFLAG_RW, &shminfo.shmmax, 0, ""); -SYSCTL_INT(_kern_ipc, OID_AUTO, shmmin, CTLFLAG_RW, &shminfo.shmmin, 0, ""); -SYSCTL_INT(_kern_ipc, OID_AUTO, shmmni, CTLFLAG_RD, &shminfo.shmmni, 0, ""); -SYSCTL_INT(_kern_ipc, OID_AUTO, shmseg, CTLFLAG_RW, &shminfo.shmseg, 0, ""); -SYSCTL_INT(_kern_ipc, OID_AUTO, shmall, CTLFLAG_RW, &shminfo.shmall, 0, ""); -SYSCTL_INT(_kern_ipc, OID_AUTO, shm_use_phys, CTLFLAG_RW, &shm_use_phys, 0, ""); +/* Global struct for main system, all jails have its own. */ +struct shmpriv mainshm; static int shm_find_segment_by_key(key) key_t key; { int i; + struct shmpriv *sp; - for (i = 0; i < shmalloced; i++) - if ((shmsegs[i].shm_perm.mode & SHMSEG_ALLOCATED) && - shmsegs[i].shm_perm.key == key) + if (curproc->p_prison == NULL) + sp = &mainshm; + else + sp = &curproc->p_prison->pr_shm; + + for (i = 0; i < sp->shmalloced; i++) + if ((sp->shmsegs[i].shm_perm.mode & SHMSEG_ALLOCATED) && + sp->shmsegs[i].shm_perm.key == key) return i; return -1; } @@ -161,11 +143,17 @@ { int segnum; struct shmid_ds *shmseg; + struct shmpriv *sp; + + if (curproc->p_prison == NULL) + sp = &mainshm; + else + sp = &curproc->p_prison->pr_shm; segnum = IPCID_TO_IX(shmid); - if (segnum < 0 || segnum >= shmalloced) + if (segnum < 0 || segnum >= sp->shmalloced) return NULL; - shmseg = &shmsegs[segnum]; + shmseg = &sp->shmsegs[segnum]; if ((shmseg->shm_perm.mode & (SHMSEG_ALLOCATED | SHMSEG_REMOVED)) != SHMSEG_ALLOCATED || shmseg->shm_perm.seq != IPCID_TO_SEQ(shmid)) @@ -179,14 +167,20 @@ { struct shm_handle *shm_handle; size_t size; + struct shmpriv *sp; + + if (curproc->p_prison == NULL) + sp = &mainshm; + else + sp = &curproc->p_prison->pr_shm; shm_handle = shmseg->shm_internal; vm_object_deallocate(shm_handle->shm_object); free((caddr_t)shm_handle, M_SHM); shmseg->shm_internal = NULL; size = round_page(shmseg->shm_segsz); - shm_committed -= btoc(size); - shm_nused--; + sp->shm_committed -= btoc(size); + sp->shm_nused--; shmseg->shm_perm.mode = SHMSEG_FREE; } @@ -198,9 +192,15 @@ struct shmid_ds *shmseg; int segnum, result; size_t size; + struct shmpriv *sp; + + if (p->p_prison == NULL) + sp = &mainshm; + else + sp = &p->p_prison->pr_shm; segnum = IPCID_TO_IX(shmmap_s->shmid); - shmseg = &shmsegs[segnum]; + shmseg = &sp->shmsegs[segnum]; size = round_page(shmseg->shm_segsz); result = vm_map_remove(&p->p_vmspace->vm_map, shmmap_s->va, shmmap_s->va + size); if (result != KERN_SUCCESS) @@ -210,7 +210,7 @@ if ((--shmseg->shm_nattch <= 0) && (shmseg->shm_perm.mode & SHMSEG_REMOVED)) { shm_deallocate_segment(shmseg); - shm_last_free = segnum; + sp->shm_last_free = segnum; } return 0; } @@ -228,18 +228,24 @@ { struct shmmap_state *shmmap_s; int i; + struct shmpriv *sp; if (!jail_sysvipc_allowed && p->p_prison != NULL) return (ENOSYS); + if (p->p_prison == NULL) + sp = &mainshm; + else + sp = &p->p_prison->pr_shm; + shmmap_s = (struct shmmap_state *)p->p_vmspace->vm_shm; if (shmmap_s == NULL) return EINVAL; - for (i = 0; i < shminfo.shmseg; i++, shmmap_s++) + for (i = 0; i < sp->shminfo.shmseg; i++, shmmap_s++) if (shmmap_s->shmid != -1 && shmmap_s->va == (vm_offset_t)uap->shmaddr) break; - if (i == shminfo.shmseg) + if (i == sp->shminfo.shmseg) return EINVAL; return shm_delete_mapping(p, shmmap_s); } @@ -265,15 +271,21 @@ vm_prot_t prot; vm_size_t size; int rv; + struct shmpriv *sp; if (!jail_sysvipc_allowed && p->p_prison != NULL) return (ENOSYS); + if (p->p_prison == NULL) + sp = &mainshm; + else + sp = &p->p_prison->pr_shm; + shmmap_s = (struct shmmap_state *)p->p_vmspace->vm_shm; if (shmmap_s == NULL) { - size = shminfo.shmseg * sizeof(struct shmmap_state); + size = sp->shminfo.shmseg * sizeof(struct shmmap_state); shmmap_s = malloc(size, M_SHM, M_WAITOK); - for (i = 0; i < shminfo.shmseg; i++) + for (i = 0; i < sp->shminfo.shmseg; i++) shmmap_s[i].shmid = -1; p->p_vmspace->vm_shm = (caddr_t)shmmap_s; } @@ -284,12 +296,12 @@ (uap->shmflg & SHM_RDONLY) ? IPC_R : IPC_R|IPC_W); if (error) return error; - for (i = 0; i < shminfo.shmseg; i++) { + for (i = 0; i < sp->shminfo.shmseg; i++) { if (shmmap_s->shmid == -1) break; shmmap_s++; } - if (i >= shminfo.shmseg) + if (i >= sp->shminfo.shmseg) return EMFILE; size = round_page(shmseg->shm_segsz); #ifdef VM_PROT_READ_IS_EXEC @@ -410,10 +422,16 @@ int error; struct shmid_ds inbuf; struct shmid_ds *shmseg; + struct shmpriv *sp; if (!jail_sysvipc_allowed && p->p_prison != NULL) return (ENOSYS); + if (p->p_prison == NULL) + sp = &mainshm; + else + sp = &p->p_prison->pr_shm; + shmseg = shm_find_segment_by_shmid(uap->shmid); if (shmseg == NULL) return EINVAL; @@ -448,7 +466,7 @@ shmseg->shm_perm.mode |= SHMSEG_REMOVED; if (shmseg->shm_nattch <= 0) { shm_deallocate_segment(shmseg); - shm_last_free = IPCID_TO_IX(uap->shmid); + sp->shm_last_free = IPCID_TO_IX(uap->shmid); } break; #if 0 @@ -478,8 +496,14 @@ { struct shmid_ds *shmseg; int error; + struct shmpriv *sp; + + if (p->p_prison == NULL) + sp = &mainshm; + else + sp = &p->p_prison->pr_shm; - shmseg = &shmsegs[segnum]; + shmseg = &sp->shmsegs[segnum]; if (shmseg->shm_perm.mode & SHMSEG_REMOVED) { /* * This segment is in the process of being allocated. Wait @@ -513,27 +537,33 @@ struct ucred *cred = p->p_ucred; struct shmid_ds *shmseg; struct shm_handle *shm_handle; + struct shmpriv *sp; + + if (p->p_prison == NULL) + sp = &mainshm; + else + sp = &p->p_prison->pr_shm; - if (uap->size < shminfo.shmmin || uap->size > shminfo.shmmax) + if (uap->size < sp->shminfo.shmmin || uap->size > sp->shminfo.shmmax) return EINVAL; - if (shm_nused >= shminfo.shmmni) /* any shmids left? */ + if (sp->shm_nused >= sp->shminfo.shmmni) /* any shmids left? */ return ENOSPC; size = round_page(uap->size); - if (shm_committed + btoc(size) > shminfo.shmall) + if (sp->shm_committed + btoc(size) > sp->shminfo.shmall) return ENOMEM; - if (shm_last_free < 0) { + if (sp->shm_last_free < 0) { shmrealloc(); /* maybe expand the shmsegs[] array */ - for (i = 0; i < shmalloced; i++) - if (shmsegs[i].shm_perm.mode & SHMSEG_FREE) + for (i = 0; i < sp->shmalloced; i++) + if (sp->shmsegs[i].shm_perm.mode & SHMSEG_FREE) break; - if (i == shmalloced) + if (i == sp->shmalloced) return ENOSPC; segnum = i; } else { - segnum = shm_last_free; - shm_last_free = -1; + segnum = sp->shm_last_free; + sp->shm_last_free = -1; } - shmseg = &shmsegs[segnum]; + shmseg = &sp->shmsegs[segnum]; /* * In case we sleep in malloc(), mark the segment present but deleted * so that noone else tries to create the same key. @@ -549,7 +579,7 @@ * We make sure that we have allocated a pager before we need * to. */ - if (shm_use_phys) { + if (sp->shm_use_phys) { shm_handle->shm_object = vm_pager_allocate(OBJT_PHYS, 0, size, VM_PROT_DEFAULT, 0); } else { @@ -569,8 +599,8 @@ shmseg->shm_lpid = shmseg->shm_nattch = 0; shmseg->shm_atime = shmseg->shm_dtime = 0; shmseg->shm_ctime = time_second; - shm_committed += btoc(size); - shm_nused++; + sp->shm_committed += btoc(size); + sp->shm_nused++; if (shmseg->shm_perm.mode & SHMSEG_WANTED) { /* * Somebody else wanted this key while we were asleep. Wake @@ -636,14 +666,20 @@ struct shmmap_state *shmmap_s; size_t size; int i; + struct shmpriv *sp; - size = shminfo.shmseg * sizeof(struct shmmap_state); + if (p1->p_prison == NULL) + sp = &mainshm; + else + sp = &p1->p_prison->pr_shm; + + size = sp->shminfo.shmseg * sizeof(struct shmmap_state); shmmap_s = malloc(size, M_SHM, M_WAITOK); bcopy((caddr_t)p1->p_vmspace->vm_shm, (caddr_t)shmmap_s, size); p2->p_vmspace->vm_shm = (caddr_t)shmmap_s; - for (i = 0; i < shminfo.shmseg; i++, shmmap_s++) + for (i = 0; i < sp->shminfo.shmseg; i++, shmmap_s++) if (shmmap_s->shmid != -1) - shmsegs[IPCID_TO_IX(shmmap_s->shmid)].shm_nattch++; + sp->shmsegs[IPCID_TO_IX(shmmap_s->shmid)].shm_nattch++; } void @@ -652,9 +688,15 @@ { struct shmmap_state *shmmap_s; int i; + struct shmpriv *sp; + + if (p->p_prison == NULL) + sp = &mainshm; + else + sp = &p->p_prison->pr_shm; shmmap_s = (struct shmmap_state *)p->p_vmspace->vm_shm; - for (i = 0; i < shminfo.shmseg; i++, shmmap_s++) + for (i = 0; i < sp->shminfo.shmseg; i++, shmmap_s++) if (shmmap_s->shmid != -1) shm_delete_mapping(p, shmmap_s); free((caddr_t)p->p_vmspace->vm_shm, M_SHM); @@ -666,41 +708,217 @@ { int i; struct shmid_ds *newsegs; + struct shmpriv *sp; + + if (curproc->p_prison == NULL) + sp = &mainshm; + else + sp = &curproc->p_prison->pr_shm; - if (shmalloced >= shminfo.shmmni) + if (sp->shmalloced >= sp->shminfo.shmmni) return; - newsegs = malloc(shminfo.shmmni * sizeof(*newsegs), M_SHM, M_WAITOK); + newsegs = malloc(sp->shminfo.shmmni * sizeof(*newsegs), M_SHM, + M_WAITOK); if (newsegs == NULL) return; - 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; - } - free(shmsegs, M_SHM); - shmsegs = newsegs; - shmalloced = shminfo.shmmni; + for (i = 0; i < sp->shmalloced; i++) + bcopy(&sp->shmsegs[i], &newsegs[i], sizeof(newsegs[0])); + for (; i < sp->shminfo.shmmni; i++) { + sp->shmsegs[i].shm_perm.mode = SHMSEG_FREE; + sp->shmsegs[i].shm_perm.seq = 0; + } + free(sp->shmsegs, M_SHM); + sp->shmsegs = newsegs; + sp->shmalloced = sp->shminfo.shmmni; } -static void -shminit(dummy) - void *dummy; +int +shminit(struct prison *pr) { + struct shmpriv *sp; int i; - shminfo.shmmax = shminfo.shmall * PAGE_SIZE; - shmalloced = shminfo.shmmni; - shmsegs = malloc(shmalloced * sizeof(shmsegs[0]), M_SHM, M_WAITOK); - 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; - } - shm_last_free = 0; - shm_nused = 0; - shm_committed = 0; + if (pr == NULL) + sp = &mainshm; + else + sp = &pr->pr_shm; + + sp->shminfo.shmmax = SHMMAX; + sp->shminfo.shmmin = SHMMIN; + sp->shminfo.shmmni = SHMMNI; + sp->shminfo.shmseg = SHMSEG; + sp->shminfo.shmall = SHMALL; + + sp->shminfo.shmmax = sp->shminfo.shmall * PAGE_SIZE; + sp->shmalloced = sp->shminfo.shmmni; + sp->shmsegs = malloc(sp->shmalloced * sizeof(sp->shmsegs[0]), M_SHM, + M_WAITOK); + if (sp->shmsegs == NULL) { + if (pr == NULL) + panic("cannot allocate initial memory for sysvshm"); + else + return (ENOMEM); + } + for (i = 0; i < sp->shmalloced; i++) { + sp->shmsegs[i].shm_perm.mode = SHMSEG_FREE; + sp->shmsegs[i].shm_perm.seq = 0; + } + sp->shm_last_free = 0; + sp->shm_nused = 0; + sp->shm_committed = 0; + + return (0); } SYSINIT(sysv_shm, SI_SUB_SYSV_SHM, SI_ORDER_FIRST, shminit, NULL); + +void +shmclear(struct prison *pr) +{ + struct shmpriv *sp; + + if (pr == NULL) + sp = &mainshm; + else + sp = &pr->pr_shm; + + free(sp->shmsegs, M_SHM); +} + +TUNABLE_INT("kern.ipc.shmmin", &mainshm.shminfo.shmmin); +TUNABLE_INT("kern.ipc.shmmni", &mainshm.shminfo.shmmni); +TUNABLE_INT("kern.ipc.shmseg", &mainshm.shminfo.shmseg); +TUNABLE_INT("kern.ipc.shmmaxpgs", &mainshm.shminfo.shmall); +TUNABLE_INT("kern.ipc.shm_use_phys", &mainshm.shm_use_phys); + +SYSCTL_DECL(_kern_ipc); + +static int +sysctl_shmsegs(SYSCTL_HANDLER_ARGS) +{ + struct shmpriv *sp; + + if (req->p->p_prison == NULL) + sp = &mainshm; + else + sp = &req->p->p_prison->pr_shm; + + return (SYSCTL_OUT(req, sp->shmsegs, + sizeof(struct shmid_ds) * sp->shminfo.shmmni)); +} +SYSCTL_PROC(_kern_ipc, OID_AUTO, shmsegs, CTLFLAG_RD, + NULL, 0, sysctl_shmsegs, "", "Shared memory IDs"); + +static int +sysctl_shminfo(SYSCTL_HANDLER_ARGS) +{ + struct shmpriv *sp; + + if (req->p->p_prison == NULL) + sp = &mainshm; + else + sp = &req->p->p_prison->pr_shm; + + return (sysctl_handle_opaque(oidp, &sp->shminfo, sizeof(struct shminfo), + req)); +} +SYSCTL_PROC(_kern_ipc, OID_AUTO, shminfo, CTLTYPE_STRUCT | CTLFLAG_RD, 0, 0, + sysctl_shminfo, "S,shminfo",""); + +#define IPC_SHMMAX 0 +#define IPC_SHMMIN 1 +#define IPC_SHMMNI 2 +#define IPC_SHMSEG 3 +#define IPC_SHMALL 4 +#define IPC_SHM_USE_PHYS 5 + +static int +sysctl_shminfo_val(struct sysctl_oid *oidp, struct sysctl_req *req, u_int type) +{ + int *shminfo; + struct shmpriv *sp; + + if (req->p->p_prison == NULL) + sp = &mainshm; + else + sp = &req->p->p_prison->pr_shm; + + switch (type) { + case IPC_SHMMAX: + shminfo = &sp->shminfo.shmmax; + break; + case IPC_SHMMIN: + shminfo = &sp->shminfo.shmmin; + break; + case IPC_SHMMNI: + shminfo = &sp->shminfo.shmmni; + break; + case IPC_SHMSEG: + shminfo = &sp->shminfo.shmseg; + break; + case IPC_SHMALL: + shminfo = &sp->shminfo.shmall; + break; + case IPC_SHM_USE_PHYS: + shminfo = &sp->shm_use_phys; + break; + default: + panic("unknown shm type"); + } + + return (sysctl_handle_int(oidp, shminfo, 0, req)); +} + +static int +sysctl_shminfo_shmmax(SYSCTL_HANDLER_ARGS) +{ + + return (sysctl_shminfo_val(oidp, req, IPC_SHMMAX)); +} +SYSCTL_PROC(_kern_ipc, OID_AUTO, shmmax, CTLTYPE_INT | CTLFLAG_RW, 0, 0, + sysctl_shminfo_shmmax, "IU", ""); + +static int +sysctl_shminfo_shmmin(SYSCTL_HANDLER_ARGS) +{ + + return (sysctl_shminfo_val(oidp, req, IPC_SHMMIN)); +} +SYSCTL_PROC(_kern_ipc, OID_AUTO, shmmin, CTLTYPE_INT | CTLFLAG_RW, 0, 0, + sysctl_shminfo_shmmin, "IU", ""); + +static int +sysctl_shminfo_shmmni(SYSCTL_HANDLER_ARGS) +{ + + return (sysctl_shminfo_val(oidp, req, IPC_SHMMNI)); +} +SYSCTL_PROC(_kern_ipc, OID_AUTO, shmmni, CTLTYPE_INT | CTLFLAG_RD, 0, 0, + sysctl_shminfo_shmmni, "IU", ""); + +static int +sysctl_shminfo_shmseg(SYSCTL_HANDLER_ARGS) +{ + + return (sysctl_shminfo_val(oidp, req, IPC_SHMSEG)); +} +SYSCTL_PROC(_kern_ipc, OID_AUTO, shmseg, CTLTYPE_INT | CTLFLAG_RW, 0, 0, + sysctl_shminfo_shmseg, "IU", ""); + +static int +sysctl_shminfo_shmall(SYSCTL_HANDLER_ARGS) +{ + + return (sysctl_shminfo_val(oidp, req, IPC_SHMALL)); +} +SYSCTL_PROC(_kern_ipc, OID_AUTO, shmall, CTLTYPE_INT | CTLFLAG_RW, 0, 0, + sysctl_shminfo_shmall, "IU", ""); + +static int +sysctl_shminfo_shm_use_phys(SYSCTL_HANDLER_ARGS) +{ + + return (sysctl_shminfo_val(oidp, req, IPC_SHM_USE_PHYS)); +} +SYSCTL_PROC(_kern_ipc, OID_AUTO, shm_use_phys, CTLTYPE_INT | CTLFLAG_RW, 0, 0, + sysctl_shminfo_shm_use_phys, "IU", ""); diff -ru /sys/svr4/svr4_misc.c sys/svr4/svr4_misc.c --- /sys/svr4/svr4_misc.c Wed Feb 19 19:29:13 2003 +++ sys/svr4/svr4_misc.c Wed Feb 19 18:39:19 2003 @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD: src/sys/svr4/svr4_misc.c,v 1.13.2.7 2003/01/14 21:33:58 dillon Exp $ + * $FreeBSD$ */ /* @@ -35,6 +35,8 @@ * handled here. */ +#include "opt_sysvipc.h" + #include <sys/param.h> #include <sys/systm.h> #include <sys/namei.h> @@ -58,6 +60,7 @@ #include <sys/fcntl.h> #include <sys/sem.h> #include <sys/msg.h> +#include <sys/jail.h> #include <sys/ptrace.h> #include <vm/vm_zone.h> @@ -726,21 +729,34 @@ case SVR4_CONFIG_DELAYTIMER_MAX: *retval = 0; /* No delaytimer support */ break; +#ifdef SYSVMSG case SVR4_CONFIG_MQ_OPEN_MAX: - *retval = msginfo.msgmni; + if (p->p_prison == NULL) + *retval = mainmsg.msginfo.msgmni; + else + *retval = p->p_prison->pr_msg.msginfo.msgmni; break; +#endif case SVR4_CONFIG_MQ_PRIO_MAX: *retval = 0; /* XXX: Don't know */ break; case SVR4_CONFIG_RTSIG_MAX: *retval = 0; break; +#ifdef SYSVSEM case SVR4_CONFIG_SEM_NSEMS_MAX: - *retval = seminfo.semmni; + if (p->p_prison == NULL) + *retval = mainsem.seminfo.semmni; + else + *retval = p->p_prison->pr_sem.seminfo.semmni; break; case SVR4_CONFIG_SEM_VALUE_MAX: - *retval = seminfo.semvmx; + if (p->p_prison == NULL) + *retval = mainsem.seminfo.semvmx; + else + *retval = p->p_prison->pr_sem.seminfo.semvmx; break; +#endif case SVR4_CONFIG_SIGQUEUE_MAX: *retval = 0; /* XXX: Don't know */ break; diff -ru /sys/sys/jail.h sys/sys/jail.h --- /sys/sys/jail.h Wed Feb 19 19:29:13 2003 +++ sys/sys/jail.h Wed Feb 19 18:24:53 2003 @@ -6,7 +6,7 @@ * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp * ---------------------------------------------------------------------------- * - * $FreeBSD: src/sys/sys/jail.h,v 1.8.2.2 2000/11/01 17:58:06 rwatson Exp $ + * $FreeBSD$ * */ @@ -26,6 +26,10 @@ #else /* _KERNEL */ +#include <sys/msg.h> +#include <sys/sem.h> +#include <sys/shm.h> + #ifdef MALLOC_DECLARE MALLOC_DECLARE(M_PRISON); #endif @@ -41,6 +45,15 @@ char pr_host[MAXHOSTNAMELEN]; u_int32_t pr_ip; void *pr_linux; +#ifdef SYSVMSG + struct msgpriv pr_msg; +#endif +#ifdef SYSVSEM + struct sempriv pr_sem; +#endif +#ifdef SYSVSHM + struct shmpriv pr_shm; +#endif }; /* diff -ru /sys/sys/msg.h sys/sys/msg.h --- /sys/sys/msg.h Wed Feb 19 19:29:13 2003 +++ sys/sys/msg.h Wed Feb 19 14:15:43 2003 @@ -32,7 +32,14 @@ #define MSG_NOERROR 010000 /* don't complain about too long msgs */ -struct msg; +struct msg { + struct msg *msg_next; /* next msg in the chain */ + long msg_type; /* type of this message */ + /* >0 -> type of this message */ + /* 0 -> free header */ + u_short msg_ts; /* size of this message */ + short msg_spot; /* location of start of msg in buffer */ +}; struct msqid_ds { struct ipc_perm msg_perm; /* msg queue permission bits */ @@ -87,7 +94,29 @@ msgssz, /* size of a message segment (see notes above) */ msgseg; /* number of message segments */ }; -extern struct msginfo msginfo; + +struct msgmap { + short next; /* next segment in buffer */ + /* -1 -> available */ + /* 0..(MSGSEG-1) -> index of next segment */ +}; + +struct msgpriv { + struct msginfo msginfo; + int nfree_msgmaps; /* # of free map entries */ + short free_msgmaps; /* head of linked list of + free map entries */ + struct msg *free_msghdrs; /* list of free msg headers */ + char *msgpool; /* MSGMAX byte long msg buffer pool */ + struct msgmap *msgmaps; /* MSGSEG msgmap structures */ + struct msg *msghdrs; /* MSGTQL msg headers */ + struct msqid_ds *msqids; /* MSGMNI msqid_ds struct's */ +}; +extern struct msgpriv mainmsg; + +struct prison; +int msginit(struct prison *pr); +void msgclear(struct prison *pr); #endif #ifndef _KERNEL diff -ru /sys/sys/sem.h sys/sys/sem.h --- /sys/sys/sem.h Wed Feb 19 19:29:13 2003 +++ sys/sys/sem.h Wed Feb 19 15:30:11 2003 @@ -1,4 +1,4 @@ -/* $FreeBSD: src/sys/sys/sem.h,v 1.20.2.2 2000/08/04 22:31:10 peter Exp $ */ +/* $FreeBSD$ */ /* $NetBSD: sem.h,v 1.5 1994/06/29 06:45:15 cgd Exp $ */ /* @@ -67,6 +67,27 @@ #ifdef _KERNEL +struct sem { + u_short semval; /* semaphore value */ + pid_t sempid; /* pid of last operation */ + u_short semncnt; /* # awaiting semval > cval */ + u_short semzcnt; /* # awaiting semval = 0 */ +}; + +/* + * Undo structure (one per process) + */ +struct sem_undo { + struct sem_undo *un_next; /* ptr to next active undo structure */ + struct proc *un_proc; /* owner of this structure */ + short un_cnt; /* # of active entries */ + struct undo { + short un_adjval; /* adjust on exit values */ + short un_num; /* semaphore # */ + int un_id; /* semid */ + } un_ent[1]; /* undo entries */ +}; + /* * semaphore info struct */ @@ -82,12 +103,24 @@ semvmx, /* semaphore maximum value */ semaem; /* adjust on exit max value */ }; -extern struct seminfo seminfo; /* internal "mode" bits */ #define SEM_ALLOC 01000 /* semaphore is allocated */ #define SEM_DEST 02000 /* semaphore will be destroyed on last detach */ +struct sempriv { + struct seminfo seminfo; + int semtot; + struct semid_ds *sema; /* semaphore id pool */ + struct sem *sem; /* semaphore pool */ + struct sem_undo *semu_list; /* list of active undo structures */ + int *semu; /* undo structure pool */ +}; +extern struct sempriv mainsem; + +struct prison; +int seminit(struct prison *pr); +void semclear(struct prison *pr); /* * Process sem_undo vectors at proc exit. */ diff -ru /sys/sys/shm.h sys/sys/shm.h --- /sys/sys/shm.h Wed Feb 19 19:29:13 2003 +++ sys/sys/shm.h Wed Feb 19 15:42:22 2003 @@ -1,4 +1,4 @@ -/* $FreeBSD: src/sys/sys/shm.h,v 1.14 1999/12/29 04:24:46 peter Exp $ */ +/* $FreeBSD$ */ /* $NetBSD: shm.h,v 1.15 1994/06/29 06:45:17 cgd Exp $ */ /* @@ -76,13 +76,24 @@ shmseg, /* max shared memory segments per process */ shmall; /* max amount of shared memory (pages) */ }; -extern struct shminfo shminfo; -extern struct shmid_ds *shmsegs; -struct proc; +struct shmpriv { + struct shminfo shminfo; + struct shmid_ds *shmsegs; + int shm_last_free; + int shm_nused; + int shm_committed; + int shmalloced; + int shm_use_phys; +}; +extern struct shmpriv mainshm; +struct proc; void shmexit __P((struct proc *)); void shmfork __P((struct proc *, struct proc *)); +struct prison; +int shminit(struct prison *pr); +void shmclear(struct prison *pr); #else /* !_KERNEL */ #include <sys/cdefs.h>
diff -ru /usr/src/usr.bin/ipcs/Makefile usr.bin/ipcs/Makefile --- /usr/src/usr.bin/ipcs/Makefile Wed Feb 19 19:29:14 2003 +++ usr.bin/ipcs/Makefile Wed Feb 19 18:58:06 2003 @@ -1,9 +1,6 @@ -# $FreeBSD: src/usr.bin/ipcs/Makefile,v 1.5 1999/08/28 01:02:15 peter Exp $ +# $FreeBSD$ PROG= ipcs -BINGRP= kmem -BINMODE= 2555 -DPADD+= ${LIBKVM} -LDADD+= -lkvm +BINMODE= 555 .include <bsd.prog.mk> diff -ru /usr/src/usr.bin/ipcs/ipcs.c usr.bin/ipcs/ipcs.c --- /usr/src/usr.bin/ipcs/ipcs.c Wed Feb 19 19:29:14 2003 +++ usr.bin/ipcs/ipcs.c Wed Feb 19 18:57:07 2003 @@ -27,12 +27,11 @@ #ifndef lint static const char rcsid[] = - "$FreeBSD: src/usr.bin/ipcs/ipcs.c,v 1.12.2.3 2001/07/30 10:16:41 dd Exp $"; + "$FreeBSD$"; #endif /* not lint */ #include <err.h> #include <fcntl.h> -#include <kvm.h> #include <nlist.h> #include <paths.h> #include <stdio.h> @@ -44,6 +43,7 @@ #include <sys/param.h> #include <sys/time.h> #include <sys/proc.h> +#include <sys/sysctl.h> #define _KERNEL #include <sys/ipc.h> #include <sys/sem.h> @@ -59,26 +59,6 @@ void usage __P((void)); -static struct nlist symbols[] = { - {"_sema"}, -#define X_SEMA 0 - {"_seminfo"}, -#define X_SEMINFO 1 - {"_semu"}, -#define X_SEMU 2 - {"_msginfo"}, -#define X_MSGINFO 3 - {"_msqids"}, -#define X_MSQIDS 4 - {"_shminfo"}, -#define X_SHMINFO 5 - {"_shmsegs"}, -#define X_SHMSEGS 6 - {NULL} -}; - -static kvm_t *kd; - char * fmt_perm(mode) u_short mode; @@ -135,10 +115,10 @@ { int display = SHMINFO | MSGINFO | SEMINFO; int option = 0; - char *core = NULL, *namelist = NULL; + size_t size; int i; - while ((i = getopt(argc, argv, "MmQqSsabC:cN:optT")) != -1) + while ((i = getopt(argc, argv, "MmQqSsab:c:optT")) != -1) switch (i) { case 'M': display = SHMTOTAL; @@ -167,15 +147,9 @@ case 'b': option |= BIGGEST; break; - case 'C': - core = optarg; - break; case 'c': option |= CREATOR; break; - case 'N': - namelist = optarg; - break; case 'o': option |= OUTSTANDING; break; @@ -189,35 +163,14 @@ usage(); } - /* - * Discard setgid privileges if not the running kernel so that bad - * guys can't print interesting stuff from kernel memory. - */ - if (namelist != NULL || core != NULL) - setgid(getgid()); - - if ((kd = kvm_open(namelist, core, NULL, O_RDONLY, "ipcs")) == NULL) - exit(1); - - switch (kvm_nlist(kd, symbols)) { - case 0: - break; - case -1: - errx(1, "unable to read kernel symbol table"); - default: -#ifdef notdef /* they'll be told more civilly later */ - warnx("nlist failed"); - for (i = 0; symbols[i].n_name != NULL; i++) - if (symbols[i].n_value == 0) - warnx("symbol %s not found", - symbols[i].n_name); - break; -#endif - } - - if ((display & (MSGINFO | MSGTOTAL)) && - kvm_read(kd, symbols[X_MSGINFO].n_value, &msginfo, sizeof(msginfo))== sizeof(msginfo)) { - + if (display & (MSGINFO | MSGTOTAL)) { + size = sizeof(struct msginfo); + if (sysctlbyname("kern.ipc.msginfo", &msginfo, &size, NULL, + NULL) != 0) { + fprintf(stderr, "SVID messages facility not configured " + "in the system\n"); + goto shm; + } if (display & MSGTOTAL) { printf("msginfo:\n"); printf("\tmsgmax: %6d\t(max characters in a message)\n", @@ -233,12 +186,21 @@ printf("\tmsgseg: %6d\t(# of message segments in system)\n\n", msginfo.msgseg); } - if (display & MSGINFO) { - struct msqid_ds *xmsqids; - kvm_read(kd, symbols[X_MSQIDS].n_value, &msqids, sizeof(msqids)); - xmsqids = malloc(sizeof(struct msqid_ds) * msginfo.msgmni); - kvm_read(kd, (u_long) msqids, xmsqids, sizeof(struct msqid_ds) * msginfo.msgmni); + if (display & MSGINFO) { + size = sizeof(struct msqid_ds) * msginfo.msgmni; + msqids = malloc(size); + if (msqids == NULL) { + fprintf(stderr, "No memory.\n"); + exit(1); + } + if (sysctlbyname("kern.ipc.msqids", msqids, &size, NULL, + NULL) != 0) { + fprintf(stderr, "SVID messages facility not " + "configured in the system\n"); + free(msqids); + goto shm; + } printf("Message Queues:\n"); printf("T ID KEY MODE OWNER GROUP"); @@ -254,10 +216,10 @@ printf(" STIME RTIME CTIME"); printf("\n"); for (i = 0; i < msginfo.msgmni; i += 1) { - if (xmsqids[i].msg_qbytes != 0) { + if (msqids[i].msg_qbytes != 0) { char stime_buf[100], rtime_buf[100], ctime_buf[100]; - struct msqid_ds *msqptr = &xmsqids[i]; + struct msqid_ds *msqptr = &msqids[i]; cvt_time(msqptr->msg_stime, stime_buf); cvt_time(msqptr->msg_rtime, rtime_buf); @@ -265,7 +227,7 @@ printf("q %6d %10d %s %8s %8s", IXSEQ_TO_IPCID(i, msqptr->msg_perm), - msqptr->msg_perm.key, + (int)msqptr->msg_perm.key, fmt_perm(msqptr->msg_perm.mode), user_from_uid(msqptr->msg_perm.uid, 0), group_from_gid(msqptr->msg_perm.gid, 0)); @@ -276,12 +238,12 @@ group_from_gid(msqptr->msg_perm.cgid, 0)); if (option & OUTSTANDING) - printf(" %6d %6d", + printf(" %6ld %6ld", msqptr->msg_cbytes, msqptr->msg_qnum); if (option & BIGGEST) - printf(" %6d", + printf(" %6ld", msqptr->msg_qbytes); if (option & PID) @@ -300,13 +262,16 @@ } printf("\n"); } - } else - if (display & (MSGINFO | MSGTOTAL)) { - fprintf(stderr, - "SVID messages facility not configured in the system\n"); + } +shm: + if (display & (SHMINFO | SHMTOTAL)) { + size = sizeof(struct shminfo); + if (sysctlbyname("kern.ipc.shminfo", &shminfo, &size, NULL, + NULL) != 0) { + fprintf(stderr, "SVID shared memory facility not " + "configured in the system\n"); + goto sem; } - if ((display & (SHMINFO | SHMTOTAL)) && - kvm_read(kd, symbols[X_SHMINFO].n_value, &shminfo, sizeof(shminfo))) { if (display & SHMTOTAL) { printf("shminfo:\n"); printf("\tshmmax: %7d\t(max shared memory segment size)\n", @@ -321,12 +286,19 @@ shminfo.shmall); } if (display & SHMINFO) { - struct shmid_ds *xshmids; - - kvm_read(kd, symbols[X_SHMSEGS].n_value, &shmsegs, sizeof(shmsegs)); - xshmids = malloc(sizeof(struct shmid_ds) * shminfo.shmmni); - kvm_read(kd, (u_long) shmsegs, xshmids, sizeof(struct shmid_ds) * - shminfo.shmmni); + size = sizeof(struct shmid_ds) * shminfo.shmmni; + shmsegs = malloc(size); + if (shmsegs == NULL) { + fprintf(stderr, "No memory.\n"); + exit(1); + } + if (sysctlbyname("kern.ipc.shmsegs", shmsegs, &size, NULL, + NULL) != 0) { + fprintf(stderr, "SVID shared memory facility " + "not configured in the system\n"); + free(shmsegs); + goto sem; + } printf("Shared Memory:\n"); printf("T ID KEY MODE OWNER GROUP"); @@ -342,10 +314,10 @@ printf(" ATIME DTIME CTIME"); printf("\n"); for (i = 0; i < shminfo.shmmni; i += 1) { - if (xshmids[i].shm_perm.mode & 0x0800) { + if (shmsegs[i].shm_perm.mode & 0x0800) { char atime_buf[100], dtime_buf[100], ctime_buf[100]; - struct shmid_ds *shmptr = &xshmids[i]; + struct shmid_ds *shmptr = &shmsegs[i]; cvt_time(shmptr->shm_atime, atime_buf); cvt_time(shmptr->shm_dtime, dtime_buf); @@ -353,7 +325,7 @@ printf("m %6d %10d %s %8s %8s", IXSEQ_TO_IPCID(i, shmptr->shm_perm), - shmptr->shm_perm.key, + (int)shmptr->shm_perm.key, fmt_perm(shmptr->shm_perm.mode), user_from_uid(shmptr->shm_perm.uid, 0), group_from_gid(shmptr->shm_perm.gid, 0)); @@ -387,15 +359,16 @@ } printf("\n"); } - } else - if (display & (SHMINFO | SHMTOTAL)) { - fprintf(stderr, - "SVID shared memory facility not configured in the system\n"); + } +sem: + if (display & (SEMINFO | SEMTOTAL)) { + size = sizeof(struct seminfo); + if (sysctlbyname("kern.ipc.seminfo", &seminfo, &size, NULL, + NULL) != 0) { + fprintf(stderr, "SVID semaphores facility not " + "configured in the system\n"); + exit(0); } - if ((display & (SEMINFO | SEMTOTAL)) && - kvm_read(kd, symbols[X_SEMINFO].n_value, &seminfo, sizeof(seminfo))) { - struct semid_ds *xsema; - if (display & SEMTOTAL) { printf("seminfo:\n"); printf("\tsemmap: %6d\t(# of entries in semaphore map)\n", @@ -419,10 +392,21 @@ printf("\tsemaem: %6d\t(adjust on exit max value)\n\n", seminfo.semaem); } + if (display & SEMINFO) { - kvm_read(kd, symbols[X_SEMA].n_value, &sema, sizeof(sema)); - xsema = malloc(sizeof(struct semid_ds) * seminfo.semmni); - kvm_read(kd, (u_long) sema, xsema, sizeof(struct semid_ds) * seminfo.semmni); + size = sizeof(struct semid_ds) * seminfo.semmni; + sema = malloc(size); + if (sema == NULL) { + fprintf(stderr, "No memory.\n"); + exit(1); + } + if (sysctlbyname("kern.ipc.sema", sema, &size, NULL, + NULL) != 0) { + fprintf(stderr, "SVID semaphores facility not " + "configured in the system\n"); + free(sema); + exit(0); + } printf("Semaphores:\n"); printf("T ID KEY MODE OWNER GROUP"); @@ -434,16 +418,16 @@ printf(" OTIME CTIME"); printf("\n"); for (i = 0; i < seminfo.semmni; i += 1) { - if ((xsema[i].sem_perm.mode & SEM_ALLOC) != 0) { + if ((sema[i].sem_perm.mode & SEM_ALLOC) != 0) { char ctime_buf[100], otime_buf[100]; - struct semid_ds *semaptr = &xsema[i]; + struct semid_ds *semaptr = &sema[i]; cvt_time(semaptr->sem_otime, otime_buf); cvt_time(semaptr->sem_ctime, ctime_buf); printf("s %6d %10d %s %8s %8s", IXSEQ_TO_IPCID(i, semaptr->sem_perm), - semaptr->sem_perm.key, + (int)semaptr->sem_perm.key, fmt_perm(semaptr->sem_perm.mode), user_from_uid(semaptr->sem_perm.uid, 0), group_from_gid(semaptr->sem_perm.gid, 0)); @@ -468,11 +452,7 @@ printf("\n"); } - } else - if (display & (SEMINFO | SEMTOTAL)) { - fprintf(stderr, "SVID semaphores facility not configured in the system\n"); - } - kvm_close(kd); + } exit(0); }
msg40038/pgp00000.pgp
Description: PGP signature