1 /* $NetBSD: sysv_ipc.c,v 1.22 2009/01/19 19:39:41 christos Exp $ */
4 * Copyright (c) 1998, 2007 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: sysv_ipc.c,v 1.22 2009/01/19 19:39:41 christos Exp $");
36 #include "opt_compat_netbsd.h"
37 #include <sys/param.h>
38 #include <sys/kernel.h>
50 #include <sys/systm.h>
52 #include <sys/mount.h>
53 #include <sys/vnode.h>
55 #include <sys/sysctl.h>
56 #include <sys/kauth.h>
59 #include <compat/sys/ipc.h>
63 * Check for ipc permission
67 ipcperm(kauth_cred_t cred
, struct ipc_perm
*perm
, int mode
)
72 if (kauth_authorize_generic(cred
, KAUTH_GENERIC_ISSUSER
, NULL
) == 0)
76 if (kauth_cred_geteuid(cred
) == perm
->uid
||
77 kauth_cred_geteuid(cred
) == perm
->cuid
)
84 if (kauth_cred_geteuid(cred
) == perm
->uid
||
85 kauth_cred_geteuid(cred
) == perm
->cuid
) {
90 return ((perm
->mode
& mask
) == mask
? 0 : EACCES
);
93 if (kauth_cred_getegid(cred
) == perm
->gid
||
94 (kauth_cred_ismember_gid(cred
, perm
->gid
, &ismember
) == 0 && ismember
) ||
95 kauth_cred_getegid(cred
) == perm
->cgid
||
96 (kauth_cred_ismember_gid(cred
, perm
->cgid
, &ismember
) == 0 && ismember
)) {
101 return ((perm
->mode
& mask
) == mask
? 0 : EACCES
);
108 return ((perm
->mode
& mask
) == mask
? 0 : EACCES
);
112 sysctl_kern_sysvipc(SYSCTLFN_ARGS
)
115 size_t sz
, *sizep
= oldlenp
;
117 struct msg_sysctl_info
*msgsi
= NULL
;
120 struct sem_sysctl_info
*semsi
= NULL
;
123 struct shm_sysctl_info
*shmsi
= NULL
;
125 size_t infosize
, dssize
, tsize
, buflen
;
132 switch ((error
= sysctl_kern_sysvipc50(SYSCTLFN_CALL(rnode
)))) {
148 case KERN_SYSVIPC_MSG_INFO
:
150 infosize
= sizeof(msgsi
->msginfo
);
151 nds
= msginfo
.msgmni
;
152 dssize
= sizeof(msgsi
->msgids
[0]);
157 case KERN_SYSVIPC_SEM_INFO
:
159 infosize
= sizeof(semsi
->seminfo
);
160 nds
= seminfo
.semmni
;
161 dssize
= sizeof(semsi
->semids
[0]);
166 case KERN_SYSVIPC_SHM_INFO
:
168 infosize
= sizeof(shmsi
->shminfo
);
169 nds
= shminfo
.shmmni
;
170 dssize
= sizeof(shmsi
->shmids
[0]);
179 * Round infosize to 64 bit boundary if requesting more than just
180 * the info structure or getting the total data size.
182 if (where
== NULL
|| *sizep
> infosize
)
183 infosize
= roundup(infosize
, sizeof(quad_t
));
184 tsize
= infosize
+ nds
* dssize
;
186 /* Return just the total size required. */
192 /* Not enough room for even the info struct. */
193 if (buflen
< infosize
) {
197 sz
= min(tsize
, buflen
);
198 bf
= kmem_zalloc(sz
, KM_SLEEP
);
202 case KERN_SYSVIPC_MSG_INFO
:
203 msgsi
= (struct msg_sysctl_info
*)bf
;
204 msgsi
->msginfo
= msginfo
;
208 case KERN_SYSVIPC_SEM_INFO
:
209 semsi
= (struct sem_sysctl_info
*)bf
;
210 semsi
->seminfo
= seminfo
;
214 case KERN_SYSVIPC_SHM_INFO
:
215 shmsi
= (struct shm_sysctl_info
*)bf
;
216 shmsi
->shminfo
= shminfo
;
224 /* Fill in the IPC data structures. */
225 for (i
= 0; i
< nds
; i
++) {
226 if (buflen
< dssize
) {
232 case KERN_SYSVIPC_MSG_INFO
:
233 mutex_enter(&msgmutex
);
234 SYSCTL_FILL_MSG(msqs
[i
].msq_u
, msgsi
->msgids
[i
]);
235 mutex_exit(&msgmutex
);
239 case KERN_SYSVIPC_SEM_INFO
:
240 SYSCTL_FILL_SEM(sema
[i
], semsi
->semids
[i
]);
244 case KERN_SYSVIPC_SHM_INFO
:
245 SYSCTL_FILL_SHM(shmsegs
[i
], shmsi
->shmids
[i
]);
253 error
= copyout(bf
, start
, *sizep
);
254 /* If copyout succeeded, use return code set earlier. */
262 SYSCTL_SETUP(sysctl_ipc_setup
, "sysctl kern.ipc subtree setup")
264 sysctl_createv(clog
, 0, NULL
, NULL
,
266 CTLTYPE_NODE
, "kern", NULL
,
270 sysctl_createv(clog
, 0, NULL
, NULL
,
273 SYSCTL_DESCR("SysV IPC options"),
275 CTL_KERN
, KERN_SYSVIPC
, CTL_EOL
);
277 sysctl_createv(clog
, 0, NULL
, NULL
,
279 CTLTYPE_STRUCT
, "sysvipc_info",
280 SYSCTL_DESCR("System V style IPC information"),
281 sysctl_kern_sysvipc
, 0, NULL
, 0,
282 CTL_KERN
, KERN_SYSVIPC
, KERN_SYSVIPC_INFO
, CTL_EOL
);