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