Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 19 Feb 2003 19:45:52 +0100
From:      Pawel Jakub Dawidek <nick@garage.freebsd.pl>
To:        freebsd-hackers@freebsd.org
Subject:   Re: Ok, IPC jailed.
Message-ID:  <20030219184552.GC76998@garage.freebsd.pl>
In-Reply-To: <20030219184319.GB76998@garage.freebsd.pl>
References:  <20030219184319.GB76998@garage.freebsd.pl>

next in thread | previous in thread | raw e-mail | index | archive | help

--n2Pv11Ogg/Ox8ay5
Content-Type: multipart/mixed; boundary="oTHb8nViIGeoXxdp"
Content-Disposition: inline


--oTHb8nViIGeoXxdp
Content-Type: text/plain; charset=iso-8859-2
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On Wed, Feb 19, 2003 at 07:43:19PM +0100, Pawel Jakub Dawidek wrote:
+> Patches are attached.

Now!:)

--=20
Pawel Jakub Dawidek
UNIX Systems Administrator
http://garage.freebsd.pl
Am I Evil? Yes, I Am.

--oTHb8nViIGeoXxdp
Content-Type: text/plain; charset=iso-8859-2
Content-Disposition: attachment; filename="privipc.patch"
Content-Transfer-Encoding: quoted-printable

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$
  */
=20
 #include <sys/param.h>
@@ -34,6 +34,7 @@
 #include <sys/proc.h>
 #include <sys/sem.h>
 #include <sys/shm.h>
+#include <sys/jail.h>
=20
 #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 =3D=3D NULL)
+		sp =3D &mainsem;
+	else
+		sp =3D &p->p_prison->pr_sem;
=20
 	sg =3D stackgap_init();
=20
@@ -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] =3D seminfo.semmni;
+		p->p_retval[0] =3D 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 dill=
on Exp $
+ * $FreeBSD$
  */
=20
 #include "opt_compat.h"
 #include "opt_ktrace.h"
+#include "opt_sysvipc.h"
=20
 #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 !=3D 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);
 			}
=20
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 rwatso=
n Exp $
+ * $FreeBSD$
  *
  */
=20
+#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>
=20
@@ -39,10 +44,12 @@
     &jail_socket_unixiproute_only, 0,
     "Processes in jail are limited to creating UNIX/IPv4/route sockets onl=
y");
=20
-int	jail_sysvipc_allowed =3D 0;
+#if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
+int	jail_sysvipc_allowed =3D 1;
 SYSCTL_INT(_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW,
     &jail_sysvipc_allowed, 0,
     "Processes in jail can use System V IPC primitives");
+#endif
=20
 int
 jail(p, uap)
@@ -75,7 +82,32 @@
 	error =3D chroot(p, &ca);
 	if (error)
 		goto bail;
-
+#ifdef SYSVMSG
+	error =3D msginit(pr);
+	if (error !=3D 0)
+		goto bail;
+#endif
+#ifdef SYSVSEM
+	error =3D seminit(pr);
+	if (error !=3D 0) {
+#ifdef SYSVMSG
+		msgclear(pr);
+#endif
+		goto bail;
+	}
+#endif
+#ifdef SYSVSHM
+	error =3D shminit(pr);
+	if (error !=3D 0) {
+#ifdef SYSVMSG
+		msgclear(pr);
+#endif
+#ifdef SYSVSEM
+		semclear(pr);
+#endif
+		goto bail;
+	}
+#endif
 	pr->pr_ref++;
 	p->p_prison =3D pr;
 	p->p_flag |=3D 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$ */
=20
 /*
  * Implementation of SVID messages
  *
  * Author:  Daniel Boulet
+ * Jailed by: Pawel Jakub Dawidek <nick@garage.freebsd.pl>
  *
  * Copyright 1993 Daniel Boulet and RTMX Inc.
  *
@@ -34,8 +35,6 @@
=20
 static MALLOC_DEFINE(M_MSG, "msg", "SVID compatible message queues");
=20
-static void msginit __P((void *));
-
 #define MSG_DEBUG
 #undef MSG_DEBUG_OK
=20
@@ -47,15 +46,6 @@
 	(sy_call_t *)msgsnd, (sy_call_t *)msgrcv
 };
=20
-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 */
-};
-
=20
 #ifndef MSGSSZ
 #define MSGSSZ	8		/* Each segment must be 2^N long */
@@ -75,26 +65,6 @@
 #endif
=20
 /*
- * 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 =3D {
-                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.
  */
=20
-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? */
=20
-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;
=20
-static void
-msginit(dummy)
-	void *dummy;
+int
+msginit(struct prison *pr)
 {
 	register int i;
+	struct msgpriv *mp;
+	int error;
=20
-	msginfo.msgmax =3D msginfo.msgseg * msginfo.msgssz;
-	msgpool =3D malloc(msginfo.msgmax, M_MSG, M_WAITOK);
-	if (msgpool =3D=3D NULL)
-		panic("msgpool is NULL");
-	msgmaps =3D malloc(sizeof(struct msgmap) * msginfo.msgseg, M_MSG, M_WAITO=
K);
-	if (msgmaps =3D=3D NULL)
-		panic("msgmaps is NULL");
-	msghdrs =3D malloc(sizeof(struct msg) * msginfo.msgtql, M_MSG, M_WAITOK);
-	if (msghdrs =3D=3D NULL)
-		panic("msghdrs is NULL");
-	msqids =3D malloc(sizeof(struct msqid_ds) * msginfo.msgmni, M_MSG, M_WAIT=
OK);
-	if (msqids =3D=3D NULL)
-		panic("msqids is NULL");
+	if (pr =3D=3D NULL)
+		mp =3D &mainmsg;
+	else
+		mp =3D &pr->pr_msg;
+
+	mp->msginfo.msgmax =3D MSGMAX;
+	mp->msginfo.msgmni =3D MSGMNI;
+	mp->msginfo.msgmnb =3D MSGMNB;
+	mp->msginfo.msgtql =3D MSGTQL;
+	mp->msginfo.msgssz =3D MSGSSZ;
+	mp->msginfo.msgseg =3D MSGSEG;
+
+	mp->msginfo.msgmax =3D mp->msginfo.msgseg * mp->msginfo.msgssz;
+	mp->msgpool =3D malloc(mp->msginfo.msgmax, M_MSG, M_WAITOK);
+	if (mp->msgpool =3D=3D NULL) {
+		if (pr =3D=3D NULL)
+			panic("msgpool is NULL");
+		else
+			return (ENOMEM);
+	}
+	mp->msgmaps =3D malloc(sizeof(struct msgmap) * mp->msginfo.msgseg, M_MSG,
+	    M_WAITOK);
+	if (mp->msgmaps =3D=3D NULL) {
+		if (pr =3D=3D NULL)
+			panic("msgmaps is NULL");
+		else {
+			error =3D ENOMEM;
+			goto fail_msgmaps;
+		}
+	}
+	mp->msghdrs =3D malloc(sizeof(struct msg) * mp->msginfo.msgtql, M_MSG,
+	    M_WAITOK);
+	if (mp->msghdrs =3D=3D NULL) {
+		if (pr =3D=3D NULL)
+			panic("msghdrs is NULL");
+		else {
+			error =3D ENOMEM;
+			goto fail_msghdrs;
+		}
+	}
+	mp->msqids =3D malloc(sizeof(struct msqid_ds) * mp->msginfo.msgmni, M_MSG,
+	    M_WAITOK);
+	if (mp->msqids =3D=3D NULL) {
+		if (pr =3D=3D NULL)
+			panic("msqids is NULL");
+		else {
+			error =3D ENOMEM;
+			goto fail_msqids;
+		}
+	}
=20
 	/*
 	 * msginfo.msgssz should be a power of two for efficiency reasons.
@@ -149,49 +146,88 @@
 	 */
=20
 	i =3D 8;
-	while (i < 1024 && i !=3D msginfo.msgssz)
+	while (i < 1024 && i !=3D mp->msginfo.msgssz)
 		i <<=3D 1;
-    	if (i !=3D msginfo.msgssz) {
-		printf("msginfo.msgssz=3D%d (0x%x)\n", msginfo.msgssz,
-		    msginfo.msgssz);
-		panic("msginfo.msgssz not a small power of 2");
+    	if (i !=3D mp->msginfo.msgssz) {
+		printf("msginfo.msgssz=3D%d (0x%x)\n", mp->msginfo.msgssz,
+		    mp->msginfo.msgssz);
+		if (pr =3D=3D NULL)
+			panic("msginfo.msgssz not a small power of 2");
+		else {
+			error =3D EINVAL;
+			goto all;
+		}
 	}
=20
-	if (msginfo.msgseg > 32767) {
-		printf("msginfo.msgseg=3D%d\n", msginfo.msgseg);
-		panic("msginfo.msgseg > 32767");
+	if (mp->msginfo.msgseg > 32767) {
+		printf("msginfo.msgseg=3D%d\n", mp->msginfo.msgseg);
+		if (pr =3D=3D NULL)
+			panic("msginfo.msgseg > 32767");
+		else {
+			error =3D EINVAL;
+			goto all;
+		}
 	}
=20
-	if (msgmaps =3D=3D NULL)
-		panic("msgmaps is NULL");
+	if (mp->msgmaps =3D=3D NULL) {
+		if (pr =3D=3D NULL)
+			panic("msgmaps is NULL");
+		else {
+			error =3D EFAULT;
+			goto all;
+		}
+	}
=20
-	for (i =3D 0; i < msginfo.msgseg; i++) {
+	for (i =3D 0; i < mp->msginfo.msgseg; i++) {
 		if (i > 0)
-			msgmaps[i-1].next =3D i;
-		msgmaps[i].next =3D -1;	/* implies entry is available */
+			mp->msgmaps[i-1].next =3D i;
+		mp->msgmaps[i].next =3D -1;	/* implies entry is available */
 	}
-	free_msgmaps =3D 0;
-	nfree_msgmaps =3D msginfo.msgseg;
+	mp->free_msgmaps =3D 0;
+	mp->nfree_msgmaps =3D mp->msginfo.msgseg;
=20
-	if (msghdrs =3D=3D NULL)
-		panic("msghdrs is NULL");
+	if (mp->msghdrs =3D=3D NULL) {
+		if (pr =3D=3D NULL)
+			panic("msghdrs is NULL");
+		else {
+			error =3D EFAULT;
+			goto all;
+		}
+	}
=20
-	for (i =3D 0; i < msginfo.msgtql; i++) {
-		msghdrs[i].msg_type =3D 0;
+	for (i =3D 0; i < mp->msginfo.msgtql; i++) {
+		mp->msghdrs[i].msg_type =3D 0;
 		if (i > 0)
-			msghdrs[i-1].msg_next =3D &msghdrs[i];
-		msghdrs[i].msg_next =3D NULL;
+			mp->msghdrs[i-1].msg_next =3D &mp->msghdrs[i];
+		mp->msghdrs[i].msg_next =3D NULL;
     	}
-	free_msghdrs =3D &msghdrs[0];
+	mp->free_msghdrs =3D &mp->msghdrs[0];
=20
-	if (msqids =3D=3D NULL)
-		panic("msqids is NULL");
+	if (mp->msqids =3D=3D NULL) {
+		if (pr =3D=3D NULL)
+			panic("msqids is NULL");
+		else {
+			error =3D EFAULT;
+			goto all;
+		}
+	}
=20
-	for (i =3D 0; i < msginfo.msgmni; i++) {
-		msqids[i].msg_qbytes =3D 0;	/* implies entry is available */
-		msqids[i].msg_perm.seq =3D 0;	/* reset to a known value */
-		msqids[i].msg_perm.mode =3D 0;
+	for (i =3D 0; i < mp->msginfo.msgmni; i++) {
+		mp->msqids[i].msg_qbytes =3D 0;	/* implies entry is available */
+		mp->msqids[i].msg_perm.seq =3D 0;	/* reset to a known value */
+		mp->msqids[i].msg_perm.mode =3D 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)
=20
@@ -224,24 +260,34 @@
 msg_freehdr(msghdr)
 	struct msg *msghdr;
 {
+	struct msgpriv *mp;
+
+	KASSERT(curproc !=3D NULL, ("msg_freehdr: curproc is NULL"));
+	if (curproc->p_prison =3D=3D NULL)
+		mp =3D &mainmsg;
+	else
+		mp =3D &curproc->p_prison->pr_msg;
+
 	while (msghdr->msg_ts > 0) {
 		short next;
-		if (msghdr->msg_spot < 0 || msghdr->msg_spot >=3D msginfo.msgseg)
+		if (msghdr->msg_spot < 0 ||
+		    msghdr->msg_spot >=3D mp->msginfo.msgseg) {
 			panic("msghdr->msg_spot out of range");
-		next =3D msgmaps[msghdr->msg_spot].next;
-		msgmaps[msghdr->msg_spot].next =3D free_msgmaps;
-		free_msgmaps =3D msghdr->msg_spot;
-		nfree_msgmaps++;
+		}
+		next =3D mp->msgmaps[msghdr->msg_spot].next;
+		mp->msgmaps[msghdr->msg_spot].next =3D mp->free_msgmaps;
+		mp->free_msgmaps =3D msghdr->msg_spot;
+		mp->nfree_msgmaps++;
 		msghdr->msg_spot =3D next;
-		if (msghdr->msg_ts >=3D msginfo.msgssz)
-			msghdr->msg_ts -=3D msginfo.msgssz;
+		if (msghdr->msg_ts >=3D mp->msginfo.msgssz)
+			msghdr->msg_ts -=3D mp->msginfo.msgssz;
 		else
 			msghdr->msg_ts =3D 0;
 	}
 	if (msghdr->msg_spot !=3D -1)
 		panic("msghdr->msg_spot !=3D -1");
-	msghdr->msg_next =3D free_msghdrs;
-	free_msghdrs =3D msghdr;
+	msghdr->msg_next =3D mp->free_msghdrs;
+	mp->free_msghdrs =3D msghdr;
 }
=20
 #ifndef _SYS_SYSPROTO_H_
@@ -263,6 +309,7 @@
 	int rval, eval;
 	struct msqid_ds msqbuf;
 	register struct msqid_ds *msqptr;
+	struct msgpriv *mp;
=20
 #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 !=3D NULL)
 		return (ENOSYS);
=20
+	if (p->p_prison =3D=3D NULL)
+		mp =3D &mainmsg;
+	else
+		mp =3D &p->p_prison->pr_msg;
+
 	msqid =3D IPCID_TO_IX(msqid);
=20
-	if (msqid < 0 || msqid >=3D msginfo.msgmni) {
+	if (msqid < 0 || msqid >=3D mp->msginfo.msgmni) {
 #ifdef MSG_DEBUG_OK
 		printf("msqid (%d) out of range (0<=3Dmsqid<%d)\n", msqid,
-		    msginfo.msgmni);
+		    mp->msginfo.msgmni);
 #endif
 		return(EINVAL);
 	}
=20
-	msqptr =3D &msqids[msqid];
+	msqptr =3D &(mp->msqids[msqid]);
=20
 	if (msqptr->msg_qbytes =3D=3D 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 =3D msginfo.msgmnb;	/* silently restrict qbytes to sy=
stem limit */
+			/* silently restrict qbytes to system limit */
+			msqbuf.msg_qbytes =3D mp->msginfo.msgmnb;
 		}
 		if (msqbuf.msg_qbytes =3D=3D 0) {
 #ifdef MSG_DEBUG_OK
@@ -402,6 +455,7 @@
 	int msgflg =3D uap->msgflg;
 	struct ucred *cred =3D p->p_ucred;
 	register struct msqid_ds *msqptr =3D NULL;
+	struct msgpriv *mp;
=20
 #ifdef MSG_DEBUG_OK
 	printf("msgget(0x%x, 0%o)\n", key, msgflg);
@@ -410,14 +464,19 @@
 	if (!jail_sysvipc_allowed && p->p_prison !=3D NULL)
 		return (ENOSYS);
=20
+	if (p->p_prison =3D=3D NULL)
+		mp =3D &mainmsg;
+	else
+		mp =3D &p->p_prison->pr_msg;
+
 	if (key !=3D IPC_PRIVATE) {
-		for (msqid =3D 0; msqid < msginfo.msgmni; msqid++) {
-			msqptr =3D &msqids[msqid];
+		for (msqid =3D 0; msqid < mp->msginfo.msgmni; msqid++) {
+			msqptr =3D &(mp->msqids[msqid]);
 			if (msqptr->msg_qbytes !=3D 0 &&
 			    msqptr->msg_perm.key =3D=3D 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 =3D=3D IPC_PRIVATE || (msgflg & IPC_CREAT)) {
-		for (msqid =3D 0; msqid < msginfo.msgmni; msqid++) {
+		for (msqid =3D 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 =3D &msqids[msqid];
+			msqptr =3D &(mp->msqids[msqid]);
 			if (msqptr->msg_qbytes =3D=3D 0 &&
 			    (msqptr->msg_perm.mode & MSG_LOCKED) =3D=3D 0)
 				break;
 		}
-		if (msqid =3D=3D msginfo.msgmni) {
+		if (msqid =3D=3D mp->msginfo.msgmni) {
 #ifdef MSG_DEBUG_OK
 			printf("no more msqid_ds's available\n");
 #endif
@@ -475,7 +534,7 @@
 		msqptr->msg_last =3D NULL;
 		msqptr->msg_cbytes =3D 0;
 		msqptr->msg_qnum =3D 0;
-		msqptr->msg_qbytes =3D msginfo.msgmnb;
+		msqptr->msg_qbytes =3D mp->msginfo.msgmnb;
 		msqptr->msg_lspid =3D 0;
 		msqptr->msg_lrpid =3D 0;
 		msqptr->msg_stime =3D 0;
@@ -516,6 +575,7 @@
 	register struct msqid_ds *msqptr;
 	register struct msg *msghdr;
 	short next;
+	struct msgpriv *mp;
=20
 #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 !=3D NULL)
 		return (ENOSYS);
=20
+	if (p->p_prison =3D=3D NULL)
+		mp =3D &mainmsg;
+	else
+		mp =3D &p->p_prison->pr_msg;
+
 	msqid =3D IPCID_TO_IX(msqid);
=20
-	if (msqid < 0 || msqid >=3D msginfo.msgmni) {
+	if (msqid < 0 || msqid >=3D mp->msginfo.msgmni) {
 #ifdef MSG_DEBUG_OK
 		printf("msqid (%d) out of range (0<=3Dmsqid<%d)\n", msqid,
-		    msginfo.msgmni);
+		    mp->msginfo.msgmni);
 #endif
 		return(EINVAL);
 	}
=20
-	msqptr =3D &msqids[msqid];
+	msqptr =3D &(mp->msqids[msqid]);
 	if (msqptr->msg_qbytes =3D=3D 0) {
 #ifdef MSG_DEBUG_OK
 		printf("no such message queue id\n");
@@ -556,10 +621,10 @@
 		return(eval);
 	}
=20
-	segs_needed =3D (msgsz + msginfo.msgssz - 1) / msginfo.msgssz;
+	segs_needed =3D (msgsz + mp->msginfo.msgssz - 1) / mp->msginfo.msgssz;
 #ifdef MSG_DEBUG_OK
-	printf("msgsz=3D%d, msgssz=3D%d, segs_needed=3D%d\n", msgsz, msginfo.msgs=
sz,
-	    segs_needed);
+	printf("msgsz=3D%d, msgssz=3D%d, segs_needed=3D%d\n", msgsz,
+	    mp->msginfo.msgssz, segs_needed);
 #endif
 	for (;;) {
 		int need_more_resources =3D 0;
@@ -588,13 +653,13 @@
 #endif
 			need_more_resources =3D 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 =3D 1;
 		}
-		if (free_msghdrs =3D=3D NULL) {
+		if (mp->free_msghdrs =3D=3D NULL) {
 #ifdef MSG_DEBUG_OK
 			printf("no more msghdrs\n");
 #endif
@@ -668,11 +733,11 @@
=20
 	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 =3D=3D NULL)
+	if (mp->free_msghdrs =3D=3D NULL)
 		panic("no more msghdrs");
=20
 	/*
@@ -688,8 +753,8 @@
 	 * Allocate a message header
 	 */
=20
-	msghdr =3D free_msghdrs;
-	free_msghdrs =3D msghdr->msg_next;
+	msghdr =3D mp->free_msghdrs;
+	mp->free_msghdrs =3D msghdr->msg_next;
 	msghdr->msg_spot =3D -1;
 	msghdr->msg_ts =3D msgsz;
=20
@@ -698,21 +763,21 @@
 	 */
=20
 	while (segs_needed > 0) {
-		if (nfree_msgmaps <=3D 0)
+		if (mp->nfree_msgmaps <=3D 0)
 			panic("not enough msgmaps");
-		if (free_msgmaps =3D=3D -1)
+		if (mp->free_msgmaps =3D=3D -1)
 			panic("nil free_msgmaps");
-		next =3D free_msgmaps;
+		next =3D mp->free_msgmaps;
 		if (next <=3D -1)
 			panic("next too low #1");
-		if (next >=3D msginfo.msgseg)
+		if (next >=3D mp->msginfo.msgseg)
 			panic("next out of range #1");
 #ifdef MSG_DEBUG_OK
 		printf("allocating segment %d to message\n", next);
 #endif
-		free_msgmaps =3D msgmaps[next].next;
-		nfree_msgmaps--;
-		msgmaps[next].next =3D msghdr->msg_spot;
+		mp->free_msgmaps =3D mp->msgmaps[next].next;
+		mp->nfree_msgmaps--;
+		mp->msgmaps[next].next =3D msghdr->msg_spot;
 		msghdr->msg_spot =3D next;
 		segs_needed--;
 	}
@@ -754,16 +819,16 @@
 	next =3D msghdr->msg_spot;
 	while (msgsz > 0) {
 		size_t tlen;
-		if (msgsz > msginfo.msgssz)
-			tlen =3D msginfo.msgssz;
+		if (msgsz > mp->msginfo.msgssz)
+			tlen =3D mp->msginfo.msgssz;
 		else
 			tlen =3D msgsz;
 		if (next <=3D -1)
 			panic("next too low #2");
-		if (next >=3D msginfo.msgseg)
+		if (next >=3D mp->msginfo.msgseg)
 			panic("next out of range #2");
-		if ((eval =3D copyin(user_msgp, &msgpool[next * msginfo.msgssz],
-		    tlen)) !=3D 0) {
+		if ((eval =3D copyin(user_msgp,
+		    &mp->msgpool[next * mp->msginfo.msgssz], tlen)) !=3D 0) {
 #ifdef MSG_DEBUG_OK
 			printf("error %d copying in message segment\n", eval);
 #endif
@@ -774,7 +839,7 @@
 		}
 		msgsz -=3D tlen;
 		user_msgp =3D (char *)user_msgp + tlen;
-		next =3D msgmaps[next].next;
+		next =3D mp->msgmaps[next].next;
 	}
 	if (next !=3D -1)
 		panic("didn't use all the msg segments");
@@ -843,6 +908,7 @@
 	register struct msg *msghdr;
 	int eval;
 	short next;
+	struct msgpriv *mp;
=20
 #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 !=3D NULL)
 		return (ENOSYS);
=20
+	if (p->p_prison =3D=3D NULL)
+		mp =3D &mainmsg;
+	else
+		mp =3D &p->p_prison->pr_msg;
+
 	msqid =3D IPCID_TO_IX(msqid);
=20
-	if (msqid < 0 || msqid >=3D msginfo.msgmni) {
+	if (msqid < 0 || msqid >=3D mp->msginfo.msgmni) {
 #ifdef MSG_DEBUG_OK
 		printf("msqid (%d) out of range (0<=3Dmsqid<%d)\n", msqid,
-		    msginfo.msgmni);
+		    mp->msginfo.msgmni);
 #endif
 		return(EINVAL);
 	}
=20
-	msqptr =3D &msqids[msqid];
+	msqptr =3D &(mp->msqids[msqid]);
 	if (msqptr->msg_qbytes =3D=3D 0) {
 #ifdef MSG_DEBUG_OK
 		printf("no such message queue id\n");
@@ -1065,18 +1136,18 @@
 	 */
=20
 	next =3D msghdr->msg_spot;
-	for (len =3D 0; len < msgsz; len +=3D msginfo.msgssz) {
+	for (len =3D 0; len < msgsz; len +=3D mp->msginfo.msgssz) {
 		size_t tlen;
=20
-		if (msgsz - len > msginfo.msgssz)
-			tlen =3D msginfo.msgssz;
+		if (msgsz - len > mp->msginfo.msgssz)
+			tlen =3D mp->msginfo.msgssz;
 		else
 			tlen =3D msgsz - len;
 		if (next <=3D -1)
 			panic("next too low #3");
-		if (next >=3D msginfo.msgseg)
+		if (next >=3D mp->msginfo.msgseg)
 			panic("next out of range #3");
-		eval =3D copyout((caddr_t)&msgpool[next * msginfo.msgssz],
+		eval =3D copyout((caddr_t)&mp->msgpool[next * mp->msginfo.msgssz],
 		    user_msgp, tlen);
 		if (eval !=3D 0) {
 #ifdef MSG_DEBUG_OK
@@ -1088,7 +1159,7 @@
 			return(eval);
 		}
 		user_msgp =3D (char *)user_msgp + tlen;
-		next =3D msgmaps[next].next;
+		next =3D mp->msgmaps[next].next;
 	}
=20
 	/*
@@ -1101,24 +1172,155 @@
 	return(0);
 }
=20
-static int
-sysctl_msqids(SYSCTL_HANDLER_ARGS)
+void
+msgclear(struct prison *pr)
 {
+	struct msgpriv *mp;
=20
-	return (SYSCTL_OUT(req, msqids,
-	    sizeof(struct msqid_ds) * msginfo.msgmni));
+	if (pr =3D=3D NULL)
+		mp =3D &mainmsg;
+	else
+		mp =3D &pr->pr_msg;
+
+	free(mp->msgpool, M_MSG);
+	free(mp->msgmaps, M_MSG);
+	free(mp->msghdrs, M_MSG);
+	free(mp->msqids, M_MSG);
 }
=20
-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);
=20
 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 =3D=3D NULL)
+		mp =3D &mainmsg;
+	else
+		mp =3D &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 =3D=3D NULL)
+		mp =3D &mainmsg;
+	else
+		mp =3D &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 =3D=3D NULL)
+		mp =3D &mainmsg;
+	else
+		mp =3D &req->p->p_prison->pr_msg;
+
+	switch (type) {
+	case IPC_MSGMAX:
+		msginfo =3D &mp->msginfo.msgmax;
+		break;
+	case IPC_MSGMNI:
+		msginfo =3D &mp->msginfo.msgmni;
+		break;
+	case IPC_MSGMNB:
+		msginfo =3D &mp->msginfo.msgmnb;
+		break;
+	case IPC_MSGTQL:
+		msginfo =3D &mp->msginfo.msgtql;
+		break;
+	case IPC_MSGSSZ:
+		msginfo =3D &mp->msginfo.msgssz;
+		break;
+	case IPC_MSGSEG:
+		msginfo =3D &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 E=
xp $ */
+/* $FreeBSD$ */
=20
 /*
  * Implementation of SVID semaphores
  *
  * Author:  Daniel Boulet
+ * Jailed by: Pawel Jakub Dawidek <nick@garage.freebsd.pl>
  *
  * This software is provided ``AS IS'' without any warranties of any kind.
  */
@@ -23,8 +24,6 @@
=20
 static MALLOC_DEFINE(M_SEM, "sem", "SVID compatible semaphores");
=20
-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
 };
=20
-static int	semtot =3D 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 =3D 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 =3D {
-                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->seminf=
o.semusz))
=20
 #if 0
 RO seminfo.semmap	/* SEMMAP unused */
@@ -169,31 +102,79 @@
 RO seminfo.semaem	/* SEMAEM unused - user param */
 #endif
=20
-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 =3D=3D NULL)
+		sp =3D &mainsem;
+	else
+		sp =3D &pr->pr_sem;
+
+	sp->semtot =3D 0;
+
+	sp->seminfo.semmap =3D SEMMAP;
+	sp->seminfo.semmni =3D SEMMNI;
+	sp->seminfo.semmns =3D SEMMNS;
+	sp->seminfo.semmnu =3D SEMMNU;
+	sp->seminfo.semmsl =3D SEMMSL;
+	sp->seminfo.semopm =3D SEMOPM;
+	sp->seminfo.semume =3D SEMUME;
+	sp->seminfo.semusz =3D SEMUSZ;
+	sp->seminfo.semvmx =3D SEMVMX;
+	sp->seminfo.semaem =3D SEMAEM;
+
+	sp->sem =3D malloc(sizeof(struct sem) * sp->seminfo.semmns, M_SEM, M_WAIT=
OK);
+	if (sp->sem =3D=3D NULL) {
+		if (pr =3D=3D NULL)
+			panic("sem is NULL");
+		else
+			return (ENOMEM);
+	}
=20
-	sem =3D malloc(sizeof(struct sem) * seminfo.semmns, M_SEM, M_WAITOK);
-	if (sem =3D=3D NULL)
-		panic("sem is NULL");
-	sema =3D malloc(sizeof(struct semid_ds) * seminfo.semmni, M_SEM, M_WAITOK=
);
-	if (sema =3D=3D NULL)
-		panic("sema is NULL");
-	semu =3D malloc(seminfo.semmnu * seminfo.semusz, M_SEM, M_WAITOK);
-	if (semu =3D=3D NULL)
-		panic("semu is NULL");
-
-	for (i =3D 0; i < seminfo.semmni; i++) {
-		sema[i].sem_base =3D 0;
-		sema[i].sem_perm.mode =3D 0;
+	sp->sema =3D malloc(sizeof(struct semid_ds) * sp->seminfo.semmni, M_SEM, =
M_WAITOK);
+	if (sp->sema =3D=3D NULL) {
+		if (pr =3D=3D NULL)
+			panic("sema is NULL");
+		else {
+			error =3D ENOMEM;
+			goto fail_sema;
+		}
+	}
+
+	sp->semu =3D malloc(sp->seminfo.semmnu * sp->seminfo.semusz, M_SEM, M_WAI=
TOK);
+	if (sp->semu =3D=3D NULL) {
+		if (pr =3D=3D NULL)
+			panic("semu is NULL");
+		else {
+			error =3D ENOMEM;
+			goto fail_semu;
+		}
 	}
-	for (i =3D 0; i < seminfo.semmnu; i++) {
+
+	for (i =3D 0; i < sp->seminfo.semmni; i++) {
+		sp->sema[i].sem_base =3D 0;
+		sp->sema[i].sem_perm.mode =3D 0;
+	}
+	for (i =3D 0; i < sp->seminfo.semmnu; i++) {
 		register struct sem_undo *suptr =3D SEMU(i);
 		suptr->un_proc =3D NULL;
 	}
-	semu_list =3D NULL;
+	sp->semu_list =3D 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)
=20
@@ -234,6 +215,12 @@
 	register struct sem_undo *suptr;
 	register struct sem_undo **supptr;
 	int attempt;
+	struct sempriv *sp;
+
+	if (p->p_prison =3D=3D NULL)
+		sp =3D &mainsem;
+	else
+		sp =3D &p->p_prison->pr_sem;
=20
 	/*
 	 * Try twice to allocate something.
@@ -247,11 +234,11 @@
 		 * Fill it in and return it if we find one.
 		 */
=20
-		for (i =3D 0; i < seminfo.semmnu; i++) {
+		for (i =3D 0; i < sp->seminfo.semmnu; i++) {
 			suptr =3D SEMU(i);
 			if (suptr->un_proc =3D=3D NULL) {
-				suptr->un_next =3D semu_list;
-				semu_list =3D suptr;
+				suptr->un_next =3D sp->semu_list;
+				sp->semu_list =3D suptr;
 				suptr->un_cnt =3D 0;
 				suptr->un_proc =3D p;
 				return(suptr);
@@ -267,7 +254,7 @@
 			/* All the structures are in use - try to free some */
 			int did_something =3D 0;
=20
-			supptr =3D &semu_list;
+			supptr =3D &sp->semu_list;
 			while ((suptr =3D *supptr) !=3D NULL) {
 				if (suptr->un_cnt =3D=3D 0)  {
 					suptr->un_proc =3D NULL;
@@ -306,13 +293,19 @@
 	register struct sem_undo *suptr;
 	register struct undo *sunptr;
 	int i;
+	struct sempriv *sp;
+
+	if (p->p_prison =3D=3D NULL)
+		sp =3D &mainsem;
+	else
+		sp =3D &p->p_prison->pr_sem;
=20
 	/* Look for and remember the sem_undo if the caller doesn't provide
 	   it */
=20
 	suptr =3D *supptr;
 	if (suptr =3D=3D NULL) {
-		for (suptr =3D semu_list; suptr !=3D NULL;
+		for (suptr =3D sp->semu_list; suptr !=3D NULL;
 		    suptr =3D suptr->un_next) {
 			if (suptr->un_proc =3D=3D p) {
 				*supptr =3D suptr;
@@ -353,7 +346,7 @@
 	/* Didn't find the right entry - create it */
 	if (adjval =3D=3D 0)
 		return(0);
-	if (suptr->un_cnt !=3D seminfo.semume) {
+	if (suptr->un_cnt !=3D sp->seminfo.semume) {
 		sunptr =3D &suptr->un_ent[suptr->un_cnt];
 		suptr->un_cnt++;
 		sunptr->un_adjval =3D adjval;
@@ -368,8 +361,14 @@
 	int semid, semnum;
 {
 	register struct sem_undo *suptr;
+	struct sempriv *sp;
+
+	if (curproc->p_prison =3D=3D NULL)
+		sp =3D &mainsem;
+	else
+		sp =3D &curproc->p_prison->pr_sem;
=20
-	for (suptr =3D semu_list; suptr !=3D NULL; suptr =3D suptr->un_next) {
+	for (suptr =3D sp->semu_list; suptr !=3D NULL; suptr =3D suptr->un_next) {
 		register struct undo *sunptr =3D &suptr->un_ent[0];
 		register int i =3D 0;
=20
@@ -417,6 +416,7 @@
 	int i, rval, eval;
 	struct semid_ds sbuf;
 	register struct semid_ds *semaptr;
+	struct sempriv *sp;
=20
 #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 !=3D NULL)
 		return (ENOSYS);
=20
+	if (p->p_prison =3D=3D NULL)
+		sp =3D &mainsem;
+	else
+		sp =3D &p->p_prison->pr_sem;
+
 	semid =3D IPCID_TO_IX(semid);
-	if (semid < 0 || semid >=3D seminfo.semmni)
+	if (semid < 0 || semid >=3D sp->seminfo.semmni)
 		return(EINVAL);
=20
-	semaptr =3D &sema[semid];
+	semaptr =3D &sp->sema[semid];
 	if ((semaptr->sem_perm.mode & SEM_ALLOC) =3D=3D 0 ||
 	    semaptr->sem_perm.seq !=3D IPCID_TO_SEQ(uap->semid))
 		return(EINVAL);
@@ -443,13 +448,13 @@
 			return(eval);
 		semaptr->sem_perm.cuid =3D cred->cr_uid;
 		semaptr->sem_perm.uid =3D cred->cr_uid;
-		semtot -=3D semaptr->sem_nsems;
-		for (i =3D semaptr->sem_base - sem; i < semtot; i++)
-			sem[i] =3D sem[i + semaptr->sem_nsems];
-		for (i =3D 0; i < seminfo.semmni; i++) {
-			if ((sema[i].sem_perm.mode & SEM_ALLOC) &&
-			    sema[i].sem_base > semaptr->sem_base)
-				sema[i].sem_base -=3D semaptr->sem_nsems;
+		sp->semtot -=3D semaptr->sem_nsems;
+		for (i =3D semaptr->sem_base - sp->sem; i < sp->semtot; i++)
+			sp->sem[i] =3D sp->sem[i + semaptr->sem_nsems];
+		for (i =3D 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 -=3D semaptr->sem_nsems;
 		}
 		semaptr->sem_perm.mode =3D 0;
 		semundo_clear(semid, -1);
@@ -580,6 +585,7 @@
 	int nsems =3D uap->nsems;
 	int semflg =3D uap->semflg;
 	struct ucred *cred =3D p->p_ucred;
+	struct sempriv *sp;
=20
 #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 !=3D NULL)
 		return (ENOSYS);
=20
+	if (p->p_prison =3D=3D NULL)
+		sp =3D &mainsem;
+	else
+		sp =3D &p->p_prison->pr_sem;
+
 	if (key !=3D IPC_PRIVATE) {
-		for (semid =3D 0; semid < seminfo.semmni; semid++) {
-			if ((sema[semid].sem_perm.mode & SEM_ALLOC) &&
-			    sema[semid].sem_perm.key =3D=3D key)
+		for (semid =3D 0; semid < sp->seminfo.semmni; semid++) {
+			if ((sp->sema[semid].sem_perm.mode & SEM_ALLOC) &&
+			    sp->sema[semid].sem_perm.key =3D=3D key)
 				break;
 		}
-		if (semid < seminfo.semmni) {
+		if (semid < sp->seminfo.semmni) {
 #ifdef SEM_DEBUG
 			printf("found public key\n");
 #endif
-			if ((eval =3D ipcperm(p, &sema[semid].sem_perm,
+			if ((eval =3D 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 =3D=3D IPC_PRIVATE || (semflg & IPC_CREAT)) {
-		if (nsems <=3D 0 || nsems > seminfo.semmsl) {
+		if (nsems <=3D 0 || nsems > sp->seminfo.semmsl) {
 #ifdef SEM_DEBUG
 			printf("nsems out of range (0<%d<=3D%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 =3D 0; semid < seminfo.semmni; semid++) {
-			if ((sema[semid].sem_perm.mode & SEM_ALLOC) =3D=3D 0)
+		for (semid =3D 0; semid < sp->seminfo.semmni; semid++) {
+			if ((sp->sema[semid].sem_perm.mode & SEM_ALLOC) =3D=3D 0)
 				break;
 		}
-		if (semid =3D=3D seminfo.semmni) {
+		if (semid =3D=3D 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 =3D key;
-		sema[semid].sem_perm.cuid =3D cred->cr_uid;
-		sema[semid].sem_perm.uid =3D cred->cr_uid;
-		sema[semid].sem_perm.cgid =3D cred->cr_gid;
-		sema[semid].sem_perm.gid =3D cred->cr_gid;
-		sema[semid].sem_perm.mode =3D (semflg & 0777) | SEM_ALLOC;
-		sema[semid].sem_perm.seq =3D
-		    (sema[semid].sem_perm.seq + 1) & 0x7fff;
-		sema[semid].sem_nsems =3D nsems;
-		sema[semid].sem_otime =3D 0;
-		sema[semid].sem_ctime =3D time_second;
-		sema[semid].sem_base =3D &sem[semtot];
-		semtot +=3D nsems;
-		bzero(sema[semid].sem_base,
-		    sizeof(sema[semid].sem_base[0])*nsems);
+		sp->sema[semid].sem_perm.key =3D key;
+		sp->sema[semid].sem_perm.cuid =3D cred->cr_uid;
+		sp->sema[semid].sem_perm.uid =3D cred->cr_uid;
+		sp->sema[semid].sem_perm.cgid =3D cred->cr_gid;
+		sp->sema[semid].sem_perm.gid =3D cred->cr_gid;
+		sp->sema[semid].sem_perm.mode =3D (semflg & 0777) | SEM_ALLOC;
+		sp->sema[semid].sem_perm.seq =3D
+		    (sp->sema[semid].sem_perm.seq + 1) & 0x7fff;
+		sp->sema[semid].sem_nsems =3D nsems;
+		sp->sema[semid].sem_otime =3D 0;
+		sp->sema[semid].sem_ctime =3D time_second;
+		sp->sema[semid].sem_base =3D &sp->sem[sp->semtot];
+		sp->semtot +=3D nsems;
+		bzero(sp->sema[semid].sem_base,
+		    sizeof(sp->sema[semid].sem_base[0])*nsems);
 #ifdef SEM_DEBUG
-		printf("sembase =3D 0x%x, next =3D 0x%x\n", sema[semid].sem_base,
-		    &sem[semtot]);
+		printf("sembase =3D 0x%x, next =3D 0x%x\n", sp->sema[semid].sem_base,
+		    &sp->sem[sp->semtot]);
 #endif
 	} else {
 #ifdef SEM_DEBUG
@@ -675,7 +686,7 @@
 	}
=20
 found:
-	p->p_retval[0] =3D IXSEQ_TO_IPCID(semid, sema[semid].sem_perm);
+	p->p_retval[0] =3D IXSEQ_TO_IPCID(semid, sp->sema[semid].sem_perm);
 	return(0);
 }
=20
@@ -701,6 +712,7 @@
 	struct sem_undo *suptr =3D NULL;
 	int i, j, eval;
 	int do_wakeup, do_undos;
+	struct sempriv *sp;
=20
 #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 !=3D NULL)
 		return (ENOSYS);
=20
+	if (p->p_prison =3D=3D NULL)
+		sp =3D &mainsem;
+	else
+		sp =3D &p->p_prison->pr_sem;
+
 	semid =3D IPCID_TO_IX(semid);	/* Convert back to zero origin */
=20
-	if (semid < 0 || semid >=3D seminfo.semmni)
+	if (semid < 0 || semid >=3D sp->seminfo.semmni)
 		return(EINVAL);
=20
-	semaptr =3D &sema[semid];
+	semaptr =3D &sp->sema[semid];
 	if ((semaptr->sem_perm.mode & SEM_ALLOC) =3D=3D 0)
 		return(EINVAL);
 	if (semaptr->sem_perm.seq !=3D 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 =3D=3D NULL)
+		sp =3D &mainsem;
+	else
+		sp =3D &p->p_prison->pr_sem;
=20
 	did_something =3D 0;
=20
@@ -959,7 +982,7 @@
 	 * associated with this process.
 	 */
=20
-	for (supptr =3D &semu_list; (suptr =3D *supptr) !=3D NULL;
+	for (supptr =3D &sp->semu_list; (suptr =3D *supptr) !=3D NULL;
 	    supptr =3D &suptr->un_next) {
 		if (suptr->un_proc =3D=3D p)
 			break;
@@ -985,7 +1008,7 @@
 			int adjval =3D suptr->un_ent[ix].un_adjval;
 			struct semid_ds *semaptr;
=20
-			semaptr =3D &sema[semid];
+			semaptr =3D &sp->sema[semid];
 			if ((semaptr->sem_perm.mode & SEM_ALLOC) =3D=3D 0)
 				panic("semexit - semid not allocated");
 			if (semnum >=3D semaptr->sem_nsems)
@@ -1024,3 +1047,213 @@
 	suptr->un_proc =3D NULL;
 	*supptr =3D suptr->un_next;
 }
+
+void
+semclear(struct prison *pr)
+{
+	struct sempriv *sp;
+
+	if (pr =3D=3D NULL)
+		sp =3D &mainsem;
+	else
+		sp =3D &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 =3D=3D NULL)
+		sp =3D &mainsem;
+	else
+		sp =3D &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 =3D=3D NULL)
+		sp =3D &mainsem;
+	else
+		sp =3D &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 =3D=3D NULL)
+		sp =3D &mainsem;
+	else
+		sp =3D &req->p->p_prison->pr_sem;
+
+	switch (type) {
+	case IPC_SEMMAP:
+		seminfo =3D &sp->seminfo.semmap;
+		break;
+	case IPC_SEMMNI:
+		seminfo =3D &sp->seminfo.semmni;
+		break;
+	case IPC_SEMMNS:
+		seminfo =3D &sp->seminfo.semmns;
+		break;
+	case IPC_SEMMNU:
+		seminfo =3D &sp->seminfo.semmnu;
+		break;
+	case IPC_SEMMSL:
+		seminfo =3D &sp->seminfo.semmsl;
+		break;
+	case IPC_SEMOPM:
+		seminfo =3D &sp->seminfo.semopm;
+		break;
+	case IPC_SEMUME:
+		seminfo =3D &sp->seminfo.semume;
+		break;
+	case IPC_SEMUSZ:
+		seminfo =3D &sp->seminfo.semume;
+		break;
+	case IPC_SEMVMX:
+		seminfo =3D &sp->seminfo.semvmx;
+		break;
+	case IPC_SEMAEM:
+		seminfo =3D &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 E=
xp $ */
+/* $FreeBSD$ */
 /*	$NetBSD: sysv_shm.c,v 1.23 1994/07/04 23:25:12 glass Exp $	*/
=20
 /*
  * Copyright (c) 1994 Adam Glass and Charles Hannum.  All rights reserved.
+ * Jailed by: Pawel Jakub Dawidek <nick@garage.freebsd.pl>
  *
  * 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
=20
-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 *));
=20
 /*
  * Tuneable values
@@ -118,39 +115,24 @@
 #define	SHMALL	(SHMMAXPGS)
 #endif
=20
-struct	shminfo shminfo =3D {
-	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;
=20
 static int
 shm_find_segment_by_key(key)
 	key_t key;
 {
 	int i;
+	struct shmpriv *sp;
=20
-	for (i =3D 0; i < shmalloced; i++)
-		if ((shmsegs[i].shm_perm.mode & SHMSEG_ALLOCATED) &&
-		    shmsegs[i].shm_perm.key =3D=3D key)
+	if (curproc->p_prison =3D=3D NULL)
+		sp =3D &mainshm;
+	else
+		sp =3D &curproc->p_prison->pr_shm;
+
+	for (i =3D 0; i < sp->shmalloced; i++)
+		if ((sp->shmsegs[i].shm_perm.mode & SHMSEG_ALLOCATED) &&
+		    sp->shmsegs[i].shm_perm.key =3D=3D key)
 			return i;
 	return -1;
 }
@@ -161,11 +143,17 @@
 {
 	int segnum;
 	struct shmid_ds *shmseg;
+	struct shmpriv *sp;
+
+	if (curproc->p_prison =3D=3D NULL)
+		sp =3D &mainshm;
+	else
+		sp =3D &curproc->p_prison->pr_shm;
=20
 	segnum =3D IPCID_TO_IX(shmid);
-	if (segnum < 0 || segnum >=3D shmalloced)
+	if (segnum < 0 || segnum >=3D sp->shmalloced)
 		return NULL;
-	shmseg =3D &shmsegs[segnum];
+	shmseg =3D &sp->shmsegs[segnum];
 	if ((shmseg->shm_perm.mode & (SHMSEG_ALLOCATED | SHMSEG_REMOVED))
 	    !=3D SHMSEG_ALLOCATED ||
 	    shmseg->shm_perm.seq !=3D IPCID_TO_SEQ(shmid))
@@ -179,14 +167,20 @@
 {
 	struct shm_handle *shm_handle;
 	size_t size;
+	struct shmpriv *sp;
+
+	if (curproc->p_prison =3D=3D NULL)
+		sp =3D &mainshm;
+	else
+		sp =3D &curproc->p_prison->pr_shm;
=20
 	shm_handle =3D shmseg->shm_internal;
 	vm_object_deallocate(shm_handle->shm_object);
 	free((caddr_t)shm_handle, M_SHM);
 	shmseg->shm_internal =3D NULL;
 	size =3D round_page(shmseg->shm_segsz);
-	shm_committed -=3D btoc(size);
-	shm_nused--;
+	sp->shm_committed -=3D btoc(size);
+	sp->shm_nused--;
 	shmseg->shm_perm.mode =3D SHMSEG_FREE;
 }
=20
@@ -198,9 +192,15 @@
 	struct shmid_ds *shmseg;
 	int segnum, result;
 	size_t size;
+	struct shmpriv *sp;
+
+	if (p->p_prison =3D=3D NULL)
+		sp =3D &mainshm;
+	else
+		sp =3D &p->p_prison->pr_shm;
=20
 	segnum =3D IPCID_TO_IX(shmmap_s->shmid);
-	shmseg =3D &shmsegs[segnum];
+	shmseg =3D &sp->shmsegs[segnum];
 	size =3D round_page(shmseg->shm_segsz);
 	result =3D vm_map_remove(&p->p_vmspace->vm_map, shmmap_s->va, shmmap_s->v=
a + size);
 	if (result !=3D KERN_SUCCESS)
@@ -210,7 +210,7 @@
 	if ((--shmseg->shm_nattch <=3D 0) &&
 	    (shmseg->shm_perm.mode & SHMSEG_REMOVED)) {
 		shm_deallocate_segment(shmseg);
-		shm_last_free =3D segnum;
+		sp->shm_last_free =3D segnum;
 	}
 	return 0;
 }
@@ -228,18 +228,24 @@
 {
 	struct shmmap_state *shmmap_s;
 	int i;
+	struct shmpriv *sp;
=20
 	if (!jail_sysvipc_allowed && p->p_prison !=3D NULL)
 		return (ENOSYS);
=20
+	if (p->p_prison =3D=3D NULL)
+		sp =3D &mainshm;
+	else
+		sp =3D &p->p_prison->pr_shm;
+
 	shmmap_s =3D (struct shmmap_state *)p->p_vmspace->vm_shm;
  	if (shmmap_s =3D=3D NULL)
  	    return EINVAL;
-	for (i =3D 0; i < shminfo.shmseg; i++, shmmap_s++)
+	for (i =3D 0; i < sp->shminfo.shmseg; i++, shmmap_s++)
 		if (shmmap_s->shmid !=3D -1 &&
 		    shmmap_s->va =3D=3D (vm_offset_t)uap->shmaddr)
 			break;
-	if (i =3D=3D shminfo.shmseg)
+	if (i =3D=3D 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;
=20
 	if (!jail_sysvipc_allowed && p->p_prison !=3D NULL)
 		return (ENOSYS);
=20
+	if (p->p_prison =3D=3D NULL)
+		sp =3D &mainshm;
+	else
+		sp =3D &p->p_prison->pr_shm;
+
 	shmmap_s =3D (struct shmmap_state *)p->p_vmspace->vm_shm;
 	if (shmmap_s =3D=3D NULL) {
-		size =3D shminfo.shmseg * sizeof(struct shmmap_state);
+		size =3D sp->shminfo.shmseg * sizeof(struct shmmap_state);
 		shmmap_s =3D malloc(size, M_SHM, M_WAITOK);
-		for (i =3D 0; i < shminfo.shmseg; i++)
+		for (i =3D 0; i < sp->shminfo.shmseg; i++)
 			shmmap_s[i].shmid =3D -1;
 		p->p_vmspace->vm_shm =3D (caddr_t)shmmap_s;
 	}
@@ -284,12 +296,12 @@
 	    (uap->shmflg & SHM_RDONLY) ? IPC_R : IPC_R|IPC_W);
 	if (error)
 		return error;
-	for (i =3D 0; i < shminfo.shmseg; i++) {
+	for (i =3D 0; i < sp->shminfo.shmseg; i++) {
 		if (shmmap_s->shmid =3D=3D -1)
 			break;
 		shmmap_s++;
 	}
-	if (i >=3D shminfo.shmseg)
+	if (i >=3D sp->shminfo.shmseg)
 		return EMFILE;
 	size =3D 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;
=20
 	if (!jail_sysvipc_allowed && p->p_prison !=3D NULL)
 		return (ENOSYS);
=20
+	if (p->p_prison =3D=3D NULL)
+		sp =3D &mainshm;
+	else
+		sp =3D &p->p_prison->pr_shm;
+
 	shmseg =3D shm_find_segment_by_shmid(uap->shmid);
 	if (shmseg =3D=3D NULL)
 		return EINVAL;
@@ -448,7 +466,7 @@
 		shmseg->shm_perm.mode |=3D SHMSEG_REMOVED;
 		if (shmseg->shm_nattch <=3D 0) {
 			shm_deallocate_segment(shmseg);
-			shm_last_free =3D IPCID_TO_IX(uap->shmid);
+			sp->shm_last_free =3D 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 =3D=3D NULL)
+		sp =3D &mainshm;
+	else
+		sp =3D &p->p_prison->pr_shm;
=20
-	shmseg =3D &shmsegs[segnum];
+	shmseg =3D &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 =3D p->p_ucred;
 	struct shmid_ds *shmseg;
 	struct shm_handle *shm_handle;
+	struct shmpriv *sp;
+
+	if (p->p_prison =3D=3D NULL)
+		sp =3D &mainshm;
+	else
+		sp =3D &p->p_prison->pr_shm;
=20
-	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 >=3D shminfo.shmmni) /* any shmids left? */
+	if (sp->shm_nused >=3D sp->shminfo.shmmni) /* any shmids left? */
 		return ENOSPC;
 	size =3D 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 =3D 0; i < shmalloced; i++)
-			if (shmsegs[i].shm_perm.mode & SHMSEG_FREE)
+		for (i =3D 0; i < sp->shmalloced; i++)
+			if (sp->shmsegs[i].shm_perm.mode & SHMSEG_FREE)
 				break;
-		if (i =3D=3D shmalloced)
+		if (i =3D=3D sp->shmalloced)
 			return ENOSPC;
 		segnum =3D i;
 	} else  {
-		segnum =3D shm_last_free;
-		shm_last_free =3D -1;
+		segnum =3D sp->shm_last_free;
+		sp->shm_last_free =3D -1;
 	}
-	shmseg =3D &shmsegs[segnum];
+	shmseg =3D &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 =3D
 		    vm_pager_allocate(OBJT_PHYS, 0, size, VM_PROT_DEFAULT, 0);
 	} else {
@@ -569,8 +599,8 @@
 	shmseg->shm_lpid =3D shmseg->shm_nattch =3D 0;
 	shmseg->shm_atime =3D shmseg->shm_dtime =3D 0;
 	shmseg->shm_ctime =3D time_second;
-	shm_committed +=3D btoc(size);
-	shm_nused++;
+	sp->shm_committed +=3D 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;
=20
-	size =3D shminfo.shmseg * sizeof(struct shmmap_state);
+	if (p1->p_prison =3D=3D NULL)
+		sp =3D &mainshm;
+	else
+		sp =3D &p1->p_prison->pr_shm;
+
+	size =3D sp->shminfo.shmseg * sizeof(struct shmmap_state);
 	shmmap_s =3D malloc(size, M_SHM, M_WAITOK);
 	bcopy((caddr_t)p1->p_vmspace->vm_shm, (caddr_t)shmmap_s, size);
 	p2->p_vmspace->vm_shm =3D (caddr_t)shmmap_s;
-	for (i =3D 0; i < shminfo.shmseg; i++, shmmap_s++)
+	for (i =3D 0; i < sp->shminfo.shmseg; i++, shmmap_s++)
 		if (shmmap_s->shmid !=3D -1)
-			shmsegs[IPCID_TO_IX(shmmap_s->shmid)].shm_nattch++;
+			sp->shmsegs[IPCID_TO_IX(shmmap_s->shmid)].shm_nattch++;
 }
=20
 void
@@ -652,9 +688,15 @@
 {
 	struct shmmap_state *shmmap_s;
 	int i;
+	struct shmpriv *sp;
+
+	if (p->p_prison =3D=3D NULL)
+		sp =3D &mainshm;
+	else
+		sp =3D &p->p_prison->pr_shm;
=20
 	shmmap_s =3D (struct shmmap_state *)p->p_vmspace->vm_shm;
-	for (i =3D 0; i < shminfo.shmseg; i++, shmmap_s++)
+	for (i =3D 0; i < sp->shminfo.shmseg; i++, shmmap_s++)
 		if (shmmap_s->shmid !=3D -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 =3D=3D NULL)
+		sp =3D &mainshm;
+	else
+		sp =3D &curproc->p_prison->pr_shm;
=20
-	if (shmalloced >=3D shminfo.shmmni)
+	if (sp->shmalloced >=3D sp->shminfo.shmmni)
 		return;
=20
-	newsegs =3D malloc(shminfo.shmmni * sizeof(*newsegs), M_SHM, M_WAITOK);
+	newsegs =3D malloc(sp->shminfo.shmmni * sizeof(*newsegs), M_SHM,
+	    M_WAITOK);
 	if (newsegs =3D=3D NULL)
 		return;
-	for (i =3D 0; i < shmalloced; i++)
-		bcopy(&shmsegs[i], &newsegs[i], sizeof(newsegs[0]));
-	for (; i < shminfo.shmmni; i++) {
-		shmsegs[i].shm_perm.mode =3D SHMSEG_FREE;
-		shmsegs[i].shm_perm.seq =3D 0;
-	}
-	free(shmsegs, M_SHM);
-	shmsegs =3D newsegs;
-	shmalloced =3D shminfo.shmmni;
+	for (i =3D 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 =3D SHMSEG_FREE;
+		sp->shmsegs[i].shm_perm.seq =3D 0;
+	}
+	free(sp->shmsegs, M_SHM);
+	sp->shmsegs =3D newsegs;
+	sp->shmalloced =3D sp->shminfo.shmmni;
 }
=20
-static void
-shminit(dummy)
-	void *dummy;
+int
+shminit(struct prison *pr)
 {
+	struct shmpriv *sp;
 	int i;
=20
-	shminfo.shmmax =3D shminfo.shmall * PAGE_SIZE;
-	shmalloced =3D shminfo.shmmni;
-	shmsegs =3D malloc(shmalloced * sizeof(shmsegs[0]), M_SHM, M_WAITOK);
-	if (shmsegs =3D=3D NULL)
-		panic("cannot allocate initial memory for sysvshm");
-	for (i =3D 0; i < shmalloced; i++) {
-		shmsegs[i].shm_perm.mode =3D SHMSEG_FREE;
-		shmsegs[i].shm_perm.seq =3D 0;
-	}
-	shm_last_free =3D 0;
-	shm_nused =3D 0;
-	shm_committed =3D 0;
+	if (pr =3D=3D NULL)
+		sp =3D &mainshm;
+	else
+		sp =3D &pr->pr_shm;
+
+	sp->shminfo.shmmax =3D SHMMAX;
+	sp->shminfo.shmmin =3D SHMMIN;
+	sp->shminfo.shmmni =3D SHMMNI;
+	sp->shminfo.shmseg =3D SHMSEG;
+	sp->shminfo.shmall =3D SHMALL;
+
+	sp->shminfo.shmmax =3D sp->shminfo.shmall * PAGE_SIZE;
+	sp->shmalloced =3D sp->shminfo.shmmni;
+	sp->shmsegs =3D malloc(sp->shmalloced * sizeof(sp->shmsegs[0]), M_SHM,
+	    M_WAITOK);
+	if (sp->shmsegs =3D=3D NULL) {
+		if (pr =3D=3D NULL)
+			panic("cannot allocate initial memory for sysvshm");
+		else
+			return (ENOMEM);
+	}
+	for (i =3D 0; i < sp->shmalloced; i++) {
+		sp->shmsegs[i].shm_perm.mode =3D SHMSEG_FREE;
+		sp->shmsegs[i].shm_perm.seq =3D 0;
+	}
+	sp->shm_last_free =3D 0;
+	sp->shm_nused =3D 0;
+	sp->shm_committed =3D 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 =3D=3D NULL)
+		sp =3D &mainshm;
+	else
+		sp =3D &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 =3D=3D NULL)
+		sp =3D &mainshm;
+	else
+		sp =3D &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 =3D=3D NULL)
+		sp =3D &mainshm;
+	else
+		sp =3D &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 =3D=3D NULL)
+		sp =3D &mainshm;
+	else
+		sp =3D &req->p->p_prison->pr_shm;
+
+	switch (type) {
+	case IPC_SHMMAX:
+		shminfo =3D &sp->shminfo.shmmax;
+		break;
+	case IPC_SHMMIN:
+		shminfo =3D &sp->shminfo.shmmin;
+		break;
+	case IPC_SHMMNI:
+		shminfo =3D &sp->shminfo.shmmni;
+		break;
+	case IPC_SHMSEG:
+		shminfo =3D &sp->shminfo.shmseg;
+		break;
+	case IPC_SHMALL:
+		shminfo =3D &sp->shminfo.shmall;
+		break;
+	case IPC_SHM_USE_PHYS:
+		shminfo =3D &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.
  *=20
- * $FreeBSD: src/sys/svr4/svr4_misc.c,v 1.13.2.7 2003/01/14 21:33:58 dillo=
n Exp $
+ * $FreeBSD$
  */
=20
 /*
@@ -35,6 +35,8 @@
  * handled here.
  */
=20
+#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>
=20
@@ -726,21 +729,34 @@
 	case SVR4_CONFIG_DELAYTIMER_MAX:
 		*retval =3D 0;	/* No delaytimer support */
 		break;
+#ifdef SYSVMSG
 	case SVR4_CONFIG_MQ_OPEN_MAX:
-		*retval =3D msginfo.msgmni;
+		if (p->p_prison =3D=3D NULL)
+			*retval =3D mainmsg.msginfo.msgmni;
+		else
+			*retval =3D p->p_prison->pr_msg.msginfo.msgmni;
 		break;
+#endif
 	case SVR4_CONFIG_MQ_PRIO_MAX:
 		*retval =3D 0;	/* XXX: Don't know */
 		break;
 	case SVR4_CONFIG_RTSIG_MAX:
 		*retval =3D 0;
 		break;
+#ifdef SYSVSEM
 	case SVR4_CONFIG_SEM_NSEMS_MAX:
-		*retval =3D seminfo.semmni;
+		if (p->p_prison =3D=3D NULL)
+			*retval =3D mainsem.seminfo.semmni;
+		else
+			*retval =3D p->p_prison->pr_sem.seminfo.semmni;
 		break;
 	case SVR4_CONFIG_SEM_VALUE_MAX:
-		*retval =3D seminfo.semvmx;
+		if (p->p_prison =3D=3D NULL)
+			*retval =3D mainsem.seminfo.semvmx;
+		else
+			*retval =3D p->p_prison->pr_sem.seminfo.semvmx;
 		break;
+#endif
 	case SVR4_CONFIG_SIGQUEUE_MAX:
 		*retval =3D 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$
  *
  */
=20
@@ -26,6 +26,10 @@
=20
 #else /* _KERNEL */
=20
+#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
 };
=20
 /*
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 @@
=20
 #define MSG_NOERROR	010000		/* don't complain about too long msgs */
=20
-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 */
+};
=20
 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
=20
 #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 $	*/
=20
 /*
@@ -67,6 +67,27 @@
=20
 #ifdef _KERNEL
=20
+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 =3D 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;
=20
 /* internal "mode" bits */
 #define	SEM_ALLOC	01000	/* semaphore is allocated */
 #define	SEM_DEST	02000	/* semaphore will be destroyed on last detach */
=20
+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 $	*/
=20
 /*
@@ -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;
=20
-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;
=20
+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 */
=20
 #include <sys/cdefs.h>

--oTHb8nViIGeoXxdp
Content-Type: text/plain; charset=iso-8859-2
Content-Disposition: attachment; filename="ipcs.patch"
Content-Transfer-Encoding: quoted-printable

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$
=20
 PROG=3D	ipcs
-BINGRP=3D	kmem
-BINMODE=3D 2555
-DPADD+=3D	${LIBKVM}
-LDADD+=3D	-lkvm
+BINMODE=3D 555
=20
 .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 @@
=20
 #ifndef lint
 static const char rcsid[] =3D
-  "$FreeBSD: src/usr.bin/ipcs/ipcs.c,v 1.12.2.3 2001/07/30 10:16:41 dd Exp=
 $";
+  "$FreeBSD$";
 #endif /* not lint */
=20
 #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 @@
=20
 void	usage __P((void));
=20
-static struct nlist symbols[] =3D {
-	{"_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 =3D SHMINFO | MSGINFO | SEMINFO;
 	int     option =3D 0;
-	char   *core =3D NULL, *namelist =3D NULL;
+	size_t	size;
 	int     i;
=20
-	while ((i =3D getopt(argc, argv, "MmQqSsabC:cN:optT")) !=3D -1)
+	while ((i =3D getopt(argc, argv, "MmQqSsab:c:optT")) !=3D -1)
 		switch (i) {
 		case 'M':
 			display =3D SHMTOTAL;
@@ -167,15 +147,9 @@
 		case 'b':
 			option |=3D BIGGEST;
 			break;
-		case 'C':
-			core =3D optarg;
-			break;
 		case 'c':
 			option |=3D CREATOR;
 			break;
-		case 'N':
-			namelist =3D optarg;
-			break;
 		case 'o':
 			option |=3D OUTSTANDING;
 			break;
@@ -189,35 +163,14 @@
 			usage();
 		}
=20
-	/*
-	 * Discard setgid privileges if not the running kernel so that bad
-	 * guys can't print interesting stuff from kernel memory.
-	 */
-	if (namelist !=3D NULL || core !=3D NULL)
-		setgid(getgid());
-
-	if ((kd =3D kvm_open(namelist, core, NULL, O_RDONLY, "ipcs")) =3D=3D 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 =3D 0; symbols[i].n_name !=3D NULL; i++)
-			if (symbols[i].n_value =3D=3D 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))=
=3D=3D sizeof(msginfo)) {
-
+	if (display & (MSGINFO | MSGTOTAL)) {
+		size =3D sizeof(struct msginfo);
+		if (sysctlbyname("kern.ipc.msginfo", &msginfo, &size, NULL,
+		    NULL) !=3D 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;
=20
-			kvm_read(kd, symbols[X_MSQIDS].n_value, &msqids, sizeof(msqids));
-			xmsqids =3D malloc(sizeof(struct msqid_ds) * msginfo.msgmni);
-			kvm_read(kd, (u_long) msqids, xmsqids, sizeof(struct msqid_ds) * msginf=
o.msgmni);
+		if (display & MSGINFO) {
+			size =3D sizeof(struct msqid_ds) * msginfo.msgmni;
+			msqids =3D malloc(size);
+			if (msqids =3D=3D NULL) {
+				fprintf(stderr, "No memory.\n");
+				exit(1);
+			}
+			if (sysctlbyname("kern.ipc.msqids", msqids, &size, NULL,
+			    NULL) !=3D 0) {
+				fprintf(stderr, "SVID messages facility not "
+				    "configured in the system\n");
+				free(msqids);
+				goto shm;
+			}
=20
 			printf("Message Queues:\n");
 			printf("T     ID     KEY        MODE       OWNER    GROUP");
@@ -254,10 +216,10 @@
 				printf("   STIME    RTIME    CTIME");
 			printf("\n");
 			for (i =3D 0; i < msginfo.msgmni; i +=3D 1) {
-				if (xmsqids[i].msg_qbytes !=3D 0) {
+				if (msqids[i].msg_qbytes !=3D 0) {
 					char    stime_buf[100], rtime_buf[100],
 					        ctime_buf[100];
-					struct msqid_ds *msqptr =3D &xmsqids[i];
+					struct msqid_ds *msqptr =3D &msqids[i];
=20
 					cvt_time(msqptr->msg_stime, stime_buf);
 					cvt_time(msqptr->msg_rtime, rtime_buf);
@@ -265,7 +227,7 @@
=20
 					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));
=20
 					if (option & OUTSTANDING)
-						printf(" %6d %6d",
+						printf(" %6ld %6ld",
 						    msqptr->msg_cbytes,
 						    msqptr->msg_qnum);
=20
 					if (option & BIGGEST)
-						printf(" %6d",
+						printf(" %6ld",
 						    msqptr->msg_qbytes);
=20
 					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 =3D sizeof(struct shminfo);
+		if (sysctlbyname("kern.ipc.shminfo", &shminfo, &size, NULL,
+		    NULL) !=3D 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 =3D malloc(sizeof(struct shmid_ds) * shminfo.shmmni);
-			kvm_read(kd, (u_long) shmsegs, xshmids, sizeof(struct shmid_ds) *
-			    shminfo.shmmni);
+			size =3D sizeof(struct shmid_ds) * shminfo.shmmni;
+			shmsegs =3D malloc(size);
+			if (shmsegs =3D=3D NULL) {
+				fprintf(stderr, "No memory.\n");
+				exit(1);
+			}
+			if (sysctlbyname("kern.ipc.shmsegs", shmsegs, &size, NULL,
+			    NULL) !=3D 0) {
+				fprintf(stderr, "SVID shared memory facility "
+				    "not configured in the system\n");
+				free(shmsegs);
+				goto sem;
+			}
=20
 			printf("Shared Memory:\n");
 			printf("T     ID     KEY        MODE       OWNER    GROUP");
@@ -342,10 +314,10 @@
 				printf("   ATIME    DTIME    CTIME");
 			printf("\n");
 			for (i =3D 0; i < shminfo.shmmni; i +=3D 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 =3D &xshmids[i];
+					struct shmid_ds *shmptr =3D &shmsegs[i];
=20
 					cvt_time(shmptr->shm_atime, atime_buf);
 					cvt_time(shmptr->shm_dtime, dtime_buf);
@@ -353,7 +325,7 @@
=20
 					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 =3D sizeof(struct seminfo);
+		if (sysctlbyname("kern.ipc.seminfo", &seminfo, &size, NULL,
+		    NULL) !=3D 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 =3D malloc(sizeof(struct semid_ds) * seminfo.semmni);
-			kvm_read(kd, (u_long) sema, xsema, sizeof(struct semid_ds) * seminfo.se=
mmni);
+			size =3D sizeof(struct semid_ds) * seminfo.semmni;
+			sema =3D malloc(size);
+			if (sema =3D=3D NULL) {
+				fprintf(stderr, "No memory.\n");
+				exit(1);
+			}
+			if (sysctlbyname("kern.ipc.sema", sema, &size, NULL,
+			    NULL) !=3D 0) {
+				fprintf(stderr, "SVID semaphores facility not "
+				    "configured in the system\n");
+				free(sema);
+				exit(0);
+			}
=20
 			printf("Semaphores:\n");
 			printf("T     ID     KEY        MODE       OWNER    GROUP");
@@ -434,16 +418,16 @@
 				printf("   OTIME    CTIME");
 			printf("\n");
 			for (i =3D 0; i < seminfo.semmni; i +=3D 1) {
-				if ((xsema[i].sem_perm.mode & SEM_ALLOC) !=3D 0) {
+				if ((sema[i].sem_perm.mode & SEM_ALLOC) !=3D 0) {
 					char    ctime_buf[100], otime_buf[100];
-					struct semid_ds *semaptr =3D &xsema[i];
+					struct semid_ds *semaptr =3D &sema[i];
=20
 					cvt_time(semaptr->sem_otime, otime_buf);
 					cvt_time(semaptr->sem_ctime, ctime_buf);
=20
 					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 @@
=20
 			printf("\n");
 		}
-	} else
-		if (display & (SEMINFO | SEMTOTAL)) {
-			fprintf(stderr, "SVID semaphores facility not configured in the system\=
n");
-		}
-	kvm_close(kd);
+	}
=20
 	exit(0);
 }

--oTHb8nViIGeoXxdp--

--n2Pv11Ogg/Ox8ay5
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.7 (FreeBSD)

iQCVAwUBPlPQ4D/PhmMH/Mf1AQEkSQP7BX9SobuMHu1QI6qFKKy+HRVQ/px+LL8Q
YaT1RbFduK4c/bTNmbeU6aSWRGXds+dBnLzlo7w7aeUn6VL/9cFRdAVBAjjM81Nx
InVST2E0wv9DLIWfKMwKXzTzdB+Dy0h1tFGz3wZzggANLi4TkcRmy5+9W81UA0hp
UURiLBJsREw=
=0Bag
-----END PGP SIGNATURE-----

--n2Pv11Ogg/Ox8ay5--

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030219184552.GC76998>