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>