1 1.43 christos /* $NetBSD: sysv_ipc.c,v 1.43 2024/10/09 16:27:28 christos Exp $ */ 2 1.7 cgd 3 1.13 mycroft /*- 4 1.20 ad * Copyright (c) 1998, 2007 The NetBSD Foundation, Inc. 5 1.13 mycroft * All rights reserved. 6 1.13 mycroft * 7 1.13 mycroft * This code is derived from software contributed to The NetBSD Foundation 8 1.13 mycroft * by Charles M. Hannum. 9 1.1 cgd * 10 1.1 cgd * Redistribution and use in source and binary forms, with or without 11 1.1 cgd * modification, are permitted provided that the following conditions 12 1.1 cgd * are met: 13 1.1 cgd * 1. Redistributions of source code must retain the above copyright 14 1.1 cgd * notice, this list of conditions and the following disclaimer. 15 1.6 hpeyerl * 2. Redistributions in binary form must reproduce the above copyright 16 1.6 hpeyerl * notice, this list of conditions and the following disclaimer in the 17 1.6 hpeyerl * documentation and/or other materials provided with the distribution. 18 1.1 cgd * 19 1.13 mycroft * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.13 mycroft * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.13 mycroft * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.13 mycroft * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.13 mycroft * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.13 mycroft * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.13 mycroft * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.13 mycroft * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.13 mycroft * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.13 mycroft * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.13 mycroft * POSSIBILITY OF SUCH DAMAGE. 30 1.1 cgd */ 31 1.15 lukem 32 1.15 lukem #include <sys/cdefs.h> 33 1.43 christos __KERNEL_RCSID(0, "$NetBSD: sysv_ipc.c,v 1.43 2024/10/09 16:27:28 christos Exp $"); 34 1.18 christos 35 1.28 pgoyette #ifdef _KERNEL_OPT 36 1.18 christos #include "opt_sysv.h" 37 1.38 pgoyette #include "opt_sysvparam.h" 38 1.31 pgoyette #include "opt_compat_netbsd.h" 39 1.28 pgoyette #endif 40 1.28 pgoyette 41 1.28 pgoyette #include <sys/syscall.h> 42 1.28 pgoyette #include <sys/syscallargs.h> 43 1.28 pgoyette #include <sys/syscallvar.h> 44 1.2 mycroft #include <sys/param.h> 45 1.2 mycroft #include <sys/kernel.h> 46 1.2 mycroft #include <sys/proc.h> 47 1.2 mycroft #include <sys/ipc.h> 48 1.18 christos #ifdef SYSVMSG 49 1.18 christos #include <sys/msg.h> 50 1.18 christos #endif 51 1.18 christos #ifdef SYSVSEM 52 1.18 christos #include <sys/sem.h> 53 1.18 christos #endif 54 1.18 christos #ifdef SYSVSHM 55 1.18 christos #include <sys/shm.h> 56 1.18 christos #endif 57 1.4 hpeyerl #include <sys/systm.h> 58 1.23 rmind #include <sys/kmem.h> 59 1.28 pgoyette #include <sys/module.h> 60 1.10 mycroft #include <sys/mount.h> 61 1.10 mycroft #include <sys/vnode.h> 62 1.12 mycroft #include <sys/stat.h> 63 1.18 christos #include <sys/sysctl.h> 64 1.17 elad #include <sys/kauth.h> 65 1.35 pgoyette #include <sys/compat_stub.h> 66 1.35 pgoyette 67 1.35 pgoyette #include <compat/common/compat_sysv_mod.h> /* for sysctl routine vector */ 68 1.1 cgd 69 1.28 pgoyette /* 70 1.28 pgoyette * Values in support of System V compatible shared memory. XXX 71 1.28 pgoyette * (originally located in sys/conf/param.c) 72 1.28 pgoyette */ 73 1.28 pgoyette #ifdef SYSVSHM 74 1.28 pgoyette #if !defined(SHMMAX) && defined(SHMMAXPGS) 75 1.28 pgoyette #define SHMMAX SHMMAXPGS /* shminit() performs a `*= PAGE_SIZE' */ 76 1.28 pgoyette #elif !defined(SHMMAX) 77 1.28 pgoyette #define SHMMAX 0 78 1.28 pgoyette #endif 79 1.28 pgoyette #ifndef SHMMIN 80 1.28 pgoyette #define SHMMIN 1 81 1.28 pgoyette #endif 82 1.28 pgoyette #ifndef SHMMNI 83 1.28 pgoyette #define SHMMNI 128 /* <64k, see IPCID_TO_IX in ipc.h */ 84 1.28 pgoyette #endif 85 1.28 pgoyette #ifndef SHMSEG 86 1.28 pgoyette #define SHMSEG 128 87 1.28 pgoyette #endif 88 1.28 pgoyette 89 1.28 pgoyette struct shminfo shminfo = { 90 1.28 pgoyette SHMMAX, 91 1.28 pgoyette SHMMIN, 92 1.28 pgoyette SHMMNI, 93 1.28 pgoyette SHMSEG, 94 1.28 pgoyette 0 95 1.28 pgoyette }; 96 1.28 pgoyette #endif 97 1.28 pgoyette 98 1.28 pgoyette /* 99 1.28 pgoyette * Values in support of System V compatible semaphores. 100 1.28 pgoyette */ 101 1.28 pgoyette #ifdef SYSVSEM 102 1.28 pgoyette struct seminfo seminfo = { 103 1.28 pgoyette SEMMAP, /* # of entries in semaphore map */ 104 1.28 pgoyette SEMMNI, /* # of semaphore identifiers */ 105 1.28 pgoyette SEMMNS, /* # of semaphores in system */ 106 1.28 pgoyette SEMMNU, /* # of undo structures in system */ 107 1.28 pgoyette SEMMSL, /* max # of semaphores per id */ 108 1.28 pgoyette SEMOPM, /* max # of operations per semop call */ 109 1.28 pgoyette SEMUME, /* max # of undo entries per process */ 110 1.28 pgoyette SEMUSZ, /* size in bytes of undo structure */ 111 1.28 pgoyette SEMVMX, /* semaphore maximum value */ 112 1.28 pgoyette SEMAEM /* adjust on exit max value */ 113 1.28 pgoyette }; 114 1.22 christos #endif 115 1.22 christos 116 1.28 pgoyette /* 117 1.28 pgoyette * Values in support of System V compatible messages. 118 1.28 pgoyette */ 119 1.28 pgoyette #ifdef SYSVMSG 120 1.28 pgoyette struct msginfo msginfo = { 121 1.28 pgoyette MSGMAX, /* max chars in a message */ 122 1.28 pgoyette MSGMNI, /* # of message queue identifiers */ 123 1.28 pgoyette MSGMNB, /* max chars in a queue */ 124 1.28 pgoyette MSGTQL, /* max messages in system */ 125 1.28 pgoyette MSGSSZ, /* size of a message segment */ 126 1.28 pgoyette /* (must be small power of 2 greater than 4) */ 127 1.28 pgoyette MSGSEG /* number of message segments */ 128 1.28 pgoyette }; 129 1.28 pgoyette #endif 130 1.28 pgoyette 131 1.28 pgoyette MODULE(MODULE_CLASS_EXEC, sysv_ipc, NULL); 132 1.28 pgoyette 133 1.28 pgoyette SYSCTL_SETUP_PROTO(sysctl_ipc_setup); 134 1.28 pgoyette 135 1.28 pgoyette static const struct syscall_package sysvipc_syscalls[] = { 136 1.31 pgoyette #if defined(SYSVSHM) 137 1.28 pgoyette { SYS___shmctl50, 0, (sy_call_t *)sys___shmctl50 }, 138 1.28 pgoyette { SYS_shmat, 0, (sy_call_t *)sys_shmat }, 139 1.28 pgoyette { SYS_shmdt, 0, (sy_call_t *)sys_shmdt }, 140 1.28 pgoyette { SYS_shmget, 0, (sy_call_t *)sys_shmget }, 141 1.31 pgoyette #endif /* SYSVSHM */ 142 1.31 pgoyette 143 1.31 pgoyette #if defined(SYSVSEM) 144 1.28 pgoyette { SYS_____semctl50, 0, (sy_call_t *)sys_____semctl50 }, 145 1.28 pgoyette { SYS_semget, 0, (sy_call_t *)sys_semget }, 146 1.28 pgoyette { SYS_semop, 0, (sy_call_t *)sys_semop }, 147 1.28 pgoyette { SYS_semconfig, 0, (sy_call_t *)sys_semconfig }, 148 1.43 christos { SYS_semtimedop, 0, (sy_call_t *)sys_semtimedop }, 149 1.31 pgoyette #endif /* SYSVSEM */ 150 1.31 pgoyette 151 1.31 pgoyette #if defined(SYSVMSG) 152 1.28 pgoyette { SYS___msgctl50, 0, (sy_call_t *)sys___msgctl50 }, 153 1.28 pgoyette { SYS_msgget, 0, (sy_call_t *)sys_msgget }, 154 1.28 pgoyette { SYS_msgsnd, 0, (sy_call_t *)sys_msgsnd }, 155 1.28 pgoyette { SYS_msgrcv, 0, (sy_call_t *)sys_msgrcv }, 156 1.31 pgoyette #endif /* SYSVMSG */ 157 1.28 pgoyette { 0, 0, NULL } 158 1.28 pgoyette }; 159 1.28 pgoyette 160 1.28 pgoyette static int 161 1.28 pgoyette sysv_ipc_modcmd(modcmd_t cmd, void *arg) 162 1.28 pgoyette { 163 1.28 pgoyette int error = 0; 164 1.28 pgoyette 165 1.28 pgoyette switch (cmd) { 166 1.28 pgoyette case MODULE_CMD_INIT: 167 1.30 pgoyette /* Set up the kauth listener */ 168 1.30 pgoyette sysvipcinit(); 169 1.28 pgoyette 170 1.30 pgoyette /* Link the system calls */ 171 1.30 pgoyette error = syscall_establish(NULL, sysvipc_syscalls); 172 1.34 christos if (error) { 173 1.30 pgoyette sysvipcfini(); 174 1.34 christos return error; 175 1.34 christos } 176 1.30 pgoyette 177 1.30 pgoyette /* 178 1.30 pgoyette * Initialize each sub-component, including their 179 1.30 pgoyette * sysctl data 180 1.30 pgoyette */ 181 1.28 pgoyette #ifdef SYSVSHM 182 1.40 pgoyette error = shminit(); 183 1.39 pgoyette if (error != 0) 184 1.39 pgoyette return error; 185 1.28 pgoyette #endif 186 1.28 pgoyette #ifdef SYSVSEM 187 1.40 pgoyette error = seminit(); 188 1.39 pgoyette if (error != 0) { 189 1.39 pgoyette #ifdef SYSVSHM 190 1.39 pgoyette shmfini(); 191 1.39 pgoyette #endif 192 1.39 pgoyette return error; 193 1.39 pgoyette } 194 1.28 pgoyette #endif 195 1.28 pgoyette #ifdef SYSVMSG 196 1.40 pgoyette error = msginit(); 197 1.39 pgoyette if (error != 0) { 198 1.39 pgoyette #ifdef SYSVSEM 199 1.39 pgoyette semfini(); 200 1.39 pgoyette #endif 201 1.39 pgoyette #ifdef SYSVSHM 202 1.39 pgoyette shmfini(); 203 1.39 pgoyette #endif 204 1.39 pgoyette return error; 205 1.39 pgoyette } 206 1.28 pgoyette #endif 207 1.28 pgoyette break; 208 1.28 pgoyette case MODULE_CMD_FINI: 209 1.28 pgoyette /* 210 1.28 pgoyette * Make sure no subcomponents are active. Each one 211 1.28 pgoyette * tells us if it is busy, and if it was _not_ busy, 212 1.28 pgoyette * we assume it has already done its own clean-up. 213 1.28 pgoyette * So we might need to re-init any components that 214 1.28 pgoyette * are successfully fini'd if we find one that is 215 1.28 pgoyette * still busy. 216 1.28 pgoyette */ 217 1.28 pgoyette #ifdef SYSVSHM 218 1.28 pgoyette if (shmfini()) { 219 1.28 pgoyette return EBUSY; 220 1.28 pgoyette } 221 1.28 pgoyette #endif 222 1.28 pgoyette #ifdef SYSVSEM 223 1.28 pgoyette if (semfini()) { 224 1.28 pgoyette #ifdef SYSVSHM 225 1.40 pgoyette shminit(); 226 1.28 pgoyette #endif 227 1.28 pgoyette return EBUSY; 228 1.28 pgoyette } 229 1.28 pgoyette #endif 230 1.28 pgoyette #ifdef SYSVMSG 231 1.28 pgoyette if (msgfini()) { 232 1.28 pgoyette #ifdef SYSVSEM 233 1.40 pgoyette seminit(); 234 1.28 pgoyette #endif 235 1.28 pgoyette #ifdef SYSVSHM 236 1.40 pgoyette shminit(); 237 1.28 pgoyette #endif 238 1.28 pgoyette return EBUSY; 239 1.28 pgoyette } 240 1.26 pgoyette #endif 241 1.28 pgoyette /* Unlink the system calls. */ 242 1.28 pgoyette error = syscall_disestablish(NULL, sysvipc_syscalls); 243 1.28 pgoyette if (error) 244 1.28 pgoyette return error; 245 1.28 pgoyette 246 1.28 pgoyette /* Remove the kauth listener */ 247 1.28 pgoyette sysvipcfini(); 248 1.28 pgoyette break; 249 1.28 pgoyette default: 250 1.28 pgoyette return ENOTTY; 251 1.28 pgoyette } 252 1.28 pgoyette return error; 253 1.28 pgoyette } 254 1.28 pgoyette 255 1.24 elad static kauth_listener_t sysvipc_listener = NULL; 256 1.1 cgd 257 1.24 elad static int 258 1.24 elad sysvipc_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie, 259 1.24 elad void *arg0, void *arg1, void *arg2, void *arg3) 260 1.1 cgd { 261 1.12 mycroft mode_t mask; 262 1.24 elad struct ipc_perm *perm; 263 1.24 elad int mode; 264 1.24 elad enum kauth_system_req req; 265 1.24 elad 266 1.41 joerg req = (enum kauth_system_req)(uintptr_t)arg0; 267 1.24 elad 268 1.24 elad if (!(action == KAUTH_SYSTEM_SYSVIPC && 269 1.24 elad req == KAUTH_REQ_SYSTEM_SYSVIPC_BYPASS)) 270 1.24 elad return KAUTH_RESULT_DEFER; 271 1.12 mycroft 272 1.24 elad perm = arg1; 273 1.24 elad mode = (int)(uintptr_t)arg2; 274 1.1 cgd 275 1.9 mycroft if (mode == IPC_M) { 276 1.17 elad if (kauth_cred_geteuid(cred) == perm->uid || 277 1.17 elad kauth_cred_geteuid(cred) == perm->cuid) 278 1.24 elad return (KAUTH_RESULT_ALLOW); 279 1.24 elad return (KAUTH_RESULT_DEFER); /* EPERM */ 280 1.1 cgd } 281 1.4 hpeyerl 282 1.12 mycroft mask = 0; 283 1.12 mycroft 284 1.17 elad if (kauth_cred_geteuid(cred) == perm->uid || 285 1.17 elad kauth_cred_geteuid(cred) == perm->cuid) { 286 1.12 mycroft if (mode & IPC_R) 287 1.12 mycroft mask |= S_IRUSR; 288 1.12 mycroft if (mode & IPC_W) 289 1.12 mycroft mask |= S_IWUSR; 290 1.24 elad return ((perm->mode & mask) == mask ? KAUTH_RESULT_ALLOW : KAUTH_RESULT_DEFER /* EACCES */); 291 1.12 mycroft } 292 1.12 mycroft 293 1.42 christos if (kauth_cred_groupmember(cred, perm->gid) == 0 || 294 1.42 christos kauth_cred_groupmember(cred, perm->cgid) == 0) { 295 1.12 mycroft if (mode & IPC_R) 296 1.12 mycroft mask |= S_IRGRP; 297 1.12 mycroft if (mode & IPC_W) 298 1.12 mycroft mask |= S_IWGRP; 299 1.24 elad return ((perm->mode & mask) == mask ? KAUTH_RESULT_ALLOW : KAUTH_RESULT_DEFER /* EACCES */); 300 1.12 mycroft } 301 1.12 mycroft 302 1.12 mycroft if (mode & IPC_R) 303 1.12 mycroft mask |= S_IROTH; 304 1.12 mycroft if (mode & IPC_W) 305 1.12 mycroft mask |= S_IWOTH; 306 1.24 elad return ((perm->mode & mask) == mask ? KAUTH_RESULT_ALLOW : KAUTH_RESULT_DEFER /* EACCES */); 307 1.24 elad } 308 1.24 elad 309 1.24 elad /* 310 1.24 elad * Check for ipc permission 311 1.24 elad */ 312 1.24 elad 313 1.24 elad int 314 1.24 elad ipcperm(kauth_cred_t cred, struct ipc_perm *perm, int mode) 315 1.24 elad { 316 1.24 elad int error; 317 1.24 elad 318 1.24 elad error = kauth_authorize_system(cred, KAUTH_SYSTEM_SYSVIPC, 319 1.24 elad KAUTH_REQ_SYSTEM_SYSVIPC_BYPASS, perm, KAUTH_ARG(mode), NULL); 320 1.24 elad if (error == 0) 321 1.24 elad return (0); 322 1.24 elad 323 1.24 elad /* Adjust EPERM and EACCES errors until there's a better way to do this. */ 324 1.24 elad if (mode != IPC_M) 325 1.24 elad error = EACCES; 326 1.24 elad 327 1.24 elad return error; 328 1.24 elad } 329 1.24 elad 330 1.24 elad void 331 1.27 pgoyette sysvipcfini(void) 332 1.27 pgoyette { 333 1.27 pgoyette 334 1.27 pgoyette KASSERT(sysvipc_listener != NULL); 335 1.27 pgoyette kauth_unlisten_scope(sysvipc_listener); 336 1.32 pgoyette sysvipc_listener = NULL; 337 1.27 pgoyette } 338 1.27 pgoyette 339 1.27 pgoyette void 340 1.24 elad sysvipcinit(void) 341 1.24 elad { 342 1.24 elad 343 1.30 pgoyette KASSERT(sysvipc_listener == NULL); 344 1.24 elad 345 1.24 elad sysvipc_listener = kauth_listen_scope(KAUTH_SCOPE_SYSTEM, 346 1.24 elad sysvipc_listener_cb, NULL); 347 1.1 cgd } 348 1.18 christos 349 1.18 christos static int 350 1.35 pgoyette stub_sysvipc50_sysctl(SYSCTLFN_ARGS) 351 1.35 pgoyette { 352 1.35 pgoyette return EPASSTHROUGH; 353 1.35 pgoyette } 354 1.35 pgoyette 355 1.35 pgoyette static int 356 1.18 christos sysctl_kern_sysvipc(SYSCTLFN_ARGS) 357 1.18 christos { 358 1.18 christos void *where = oldp; 359 1.23 rmind size_t sz, *sizep = oldlenp; 360 1.18 christos #ifdef SYSVMSG 361 1.18 christos struct msg_sysctl_info *msgsi = NULL; 362 1.18 christos #endif 363 1.18 christos #ifdef SYSVSEM 364 1.18 christos struct sem_sysctl_info *semsi = NULL; 365 1.18 christos #endif 366 1.18 christos #ifdef SYSVSHM 367 1.18 christos struct shm_sysctl_info *shmsi = NULL; 368 1.18 christos #endif 369 1.18 christos size_t infosize, dssize, tsize, buflen; 370 1.18 christos void *bf = NULL; 371 1.18 christos char *start; 372 1.18 christos int32_t nds; 373 1.18 christos int i, error, ret; 374 1.18 christos 375 1.26 pgoyette /* 376 1.31 pgoyette * If present, call the compat sysctl() code. If it handles the request 377 1.31 pgoyette * completely (either success or error), return. Otherwise fallthrough 378 1.31 pgoyette * to the non-compat sysctl code. 379 1.26 pgoyette */ 380 1.31 pgoyette 381 1.37 pgoyette MODULE_HOOK_CALL(sysvipc_sysctl_50_hook, (SYSCTLFN_CALL(rnode)), 382 1.35 pgoyette stub_sysvipc50_sysctl(SYSCTLFN_CALL(rnode)), error); 383 1.31 pgoyette if (error != EPASSTHROUGH) 384 1.31 pgoyette return error; 385 1.26 pgoyette 386 1.18 christos if (namelen != 1) 387 1.18 christos return EINVAL; 388 1.18 christos 389 1.18 christos start = where; 390 1.18 christos buflen = *sizep; 391 1.18 christos 392 1.18 christos switch (*name) { 393 1.18 christos case KERN_SYSVIPC_MSG_INFO: 394 1.18 christos #ifdef SYSVMSG 395 1.18 christos infosize = sizeof(msgsi->msginfo); 396 1.18 christos nds = msginfo.msgmni; 397 1.18 christos dssize = sizeof(msgsi->msgids[0]); 398 1.18 christos break; 399 1.18 christos #else 400 1.18 christos return EINVAL; 401 1.18 christos #endif 402 1.18 christos case KERN_SYSVIPC_SEM_INFO: 403 1.18 christos #ifdef SYSVSEM 404 1.18 christos infosize = sizeof(semsi->seminfo); 405 1.18 christos nds = seminfo.semmni; 406 1.18 christos dssize = sizeof(semsi->semids[0]); 407 1.18 christos break; 408 1.18 christos #else 409 1.18 christos return EINVAL; 410 1.18 christos #endif 411 1.18 christos case KERN_SYSVIPC_SHM_INFO: 412 1.18 christos #ifdef SYSVSHM 413 1.18 christos infosize = sizeof(shmsi->shminfo); 414 1.18 christos nds = shminfo.shmmni; 415 1.18 christos dssize = sizeof(shmsi->shmids[0]); 416 1.18 christos break; 417 1.18 christos #else 418 1.18 christos return EINVAL; 419 1.18 christos #endif 420 1.18 christos default: 421 1.18 christos return EINVAL; 422 1.18 christos } 423 1.18 christos /* 424 1.18 christos * Round infosize to 64 bit boundary if requesting more than just 425 1.18 christos * the info structure or getting the total data size. 426 1.18 christos */ 427 1.18 christos if (where == NULL || *sizep > infosize) 428 1.18 christos infosize = roundup(infosize, sizeof(quad_t)); 429 1.18 christos tsize = infosize + nds * dssize; 430 1.18 christos 431 1.18 christos /* Return just the total size required. */ 432 1.18 christos if (where == NULL) { 433 1.18 christos *sizep = tsize; 434 1.18 christos return 0; 435 1.18 christos } 436 1.18 christos 437 1.18 christos /* Not enough room for even the info struct. */ 438 1.18 christos if (buflen < infosize) { 439 1.18 christos *sizep = 0; 440 1.18 christos return ENOMEM; 441 1.18 christos } 442 1.33 riastrad sz = uimin(tsize, buflen); 443 1.23 rmind bf = kmem_zalloc(sz, KM_SLEEP); 444 1.18 christos 445 1.18 christos switch (*name) { 446 1.18 christos #ifdef SYSVMSG 447 1.18 christos case KERN_SYSVIPC_MSG_INFO: 448 1.18 christos msgsi = (struct msg_sysctl_info *)bf; 449 1.18 christos msgsi->msginfo = msginfo; 450 1.18 christos break; 451 1.18 christos #endif 452 1.18 christos #ifdef SYSVSEM 453 1.18 christos case KERN_SYSVIPC_SEM_INFO: 454 1.18 christos semsi = (struct sem_sysctl_info *)bf; 455 1.18 christos semsi->seminfo = seminfo; 456 1.18 christos break; 457 1.18 christos #endif 458 1.18 christos #ifdef SYSVSHM 459 1.18 christos case KERN_SYSVIPC_SHM_INFO: 460 1.18 christos shmsi = (struct shm_sysctl_info *)bf; 461 1.18 christos shmsi->shminfo = shminfo; 462 1.18 christos break; 463 1.18 christos #endif 464 1.18 christos } 465 1.18 christos buflen -= infosize; 466 1.18 christos 467 1.18 christos ret = 0; 468 1.18 christos if (buflen > 0) { 469 1.18 christos /* Fill in the IPC data structures. */ 470 1.18 christos for (i = 0; i < nds; i++) { 471 1.18 christos if (buflen < dssize) { 472 1.18 christos ret = ENOMEM; 473 1.18 christos break; 474 1.18 christos } 475 1.18 christos switch (*name) { 476 1.18 christos #ifdef SYSVMSG 477 1.18 christos case KERN_SYSVIPC_MSG_INFO: 478 1.20 ad mutex_enter(&msgmutex); 479 1.22 christos SYSCTL_FILL_MSG(msqs[i].msq_u, msgsi->msgids[i]); 480 1.20 ad mutex_exit(&msgmutex); 481 1.18 christos break; 482 1.18 christos #endif 483 1.18 christos #ifdef SYSVSEM 484 1.18 christos case KERN_SYSVIPC_SEM_INFO: 485 1.22 christos SYSCTL_FILL_SEM(sema[i], semsi->semids[i]); 486 1.18 christos break; 487 1.18 christos #endif 488 1.18 christos #ifdef SYSVSHM 489 1.18 christos case KERN_SYSVIPC_SHM_INFO: 490 1.22 christos SYSCTL_FILL_SHM(shmsegs[i], shmsi->shmids[i]); 491 1.18 christos break; 492 1.18 christos #endif 493 1.18 christos } 494 1.18 christos buflen -= dssize; 495 1.18 christos } 496 1.18 christos } 497 1.18 christos *sizep -= buflen; 498 1.18 christos error = copyout(bf, start, *sizep); 499 1.18 christos /* If copyout succeeded, use return code set earlier. */ 500 1.18 christos if (error == 0) 501 1.18 christos error = ret; 502 1.18 christos if (bf) 503 1.23 rmind kmem_free(bf, sz); 504 1.18 christos return error; 505 1.18 christos } 506 1.18 christos 507 1.18 christos SYSCTL_SETUP(sysctl_ipc_setup, "sysctl kern.ipc subtree setup") 508 1.18 christos { 509 1.18 christos 510 1.18 christos sysctl_createv(clog, 0, NULL, NULL, 511 1.18 christos CTLFLAG_PERMANENT, 512 1.18 christos CTLTYPE_NODE, "ipc", 513 1.18 christos SYSCTL_DESCR("SysV IPC options"), 514 1.18 christos NULL, 0, NULL, 0, 515 1.18 christos CTL_KERN, KERN_SYSVIPC, CTL_EOL); 516 1.18 christos 517 1.18 christos sysctl_createv(clog, 0, NULL, NULL, 518 1.18 christos CTLFLAG_PERMANENT, 519 1.18 christos CTLTYPE_STRUCT, "sysvipc_info", 520 1.18 christos SYSCTL_DESCR("System V style IPC information"), 521 1.18 christos sysctl_kern_sysvipc, 0, NULL, 0, 522 1.18 christos CTL_KERN, KERN_SYSVIPC, KERN_SYSVIPC_INFO, CTL_EOL); 523 1.18 christos } 524