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);
 }

Attachment: msg40038/pgp00000.pgp
Description: PGP signature

Reply via email to