19454b2d8SWarner Losh /*- 28a36da99SPedro F. Giffuni * SPDX-License-Identifier: BSD-4-Clause 38a36da99SPedro F. Giffuni * 43d903220SDoug Rabson * Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca> 5b12c55abSRobert Watson * Copyright (c) 2006 nCircle Network Security, Inc. 63d903220SDoug Rabson * All rights reserved. 73d903220SDoug Rabson * 8b12c55abSRobert Watson * This software was developed by Robert N. M. Watson for the TrustedBSD 9b12c55abSRobert Watson * Project under contract to nCircle Network Security, Inc. 10b12c55abSRobert Watson * 113d903220SDoug Rabson * Redistribution and use in source and binary forms, with or without 123d903220SDoug Rabson * modification, are permitted provided that the following conditions 133d903220SDoug Rabson * are met: 143d903220SDoug Rabson * 1. Redistributions of source code must retain the above copyright 153d903220SDoug Rabson * notice, this list of conditions and the following disclaimer. 163d903220SDoug Rabson * 2. Redistributions in binary form must reproduce the above copyright 173d903220SDoug Rabson * notice, this list of conditions and the following disclaimer in the 183d903220SDoug Rabson * documentation and/or other materials provided with the distribution. 193d903220SDoug Rabson * 3. All advertising materials mentioning features or use of this software 203d903220SDoug Rabson * must display the following acknowledgement: 213d903220SDoug Rabson * This product includes software developed by Herb Peyerl. 223d903220SDoug Rabson * 4. The name of Herb Peyerl may not be used to endorse or promote products 233d903220SDoug Rabson * derived from this software without specific prior written permission. 243d903220SDoug Rabson * 253d903220SDoug Rabson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 263d903220SDoug Rabson * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 273d903220SDoug Rabson * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 283d903220SDoug Rabson * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 293d903220SDoug Rabson * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 303d903220SDoug Rabson * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 313d903220SDoug Rabson * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 323d903220SDoug Rabson * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 333d903220SDoug Rabson * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 343d903220SDoug Rabson * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 350879ca72SPedro F. Giffuni * 360879ca72SPedro F. Giffuni * $NetBSD: sysv_ipc.c,v 1.9 1995/06/02 19:04:22 mycroft Exp $ 373d903220SDoug Rabson */ 383d903220SDoug Rabson 39677b542eSDavid E. O'Brien #include <sys/cdefs.h> 40677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 41677b542eSDavid E. O'Brien 42511b67b7SGarrett Wollman #include "opt_sysvipc.h" 43511b67b7SGarrett Wollman 443d903220SDoug Rabson #include <sys/param.h> 45cf9fa8e7SPoul-Henning Kamp #include <sys/systm.h> 4678525ce3SAlfred Perlstein #include <sys/sem.h> 4778525ce3SAlfred Perlstein #include <sys/shm.h> 4881090119SPeter Wemm #include <sys/ipc.h> 49b12c55abSRobert Watson #include <sys/priv.h> 501c308b81SPoul-Henning Kamp #include <sys/proc.h> 51b7f5d5b5SBruce Evans #include <sys/ucred.h> 5281090119SPeter Wemm 53*5408c6dbSMateusz Guzik #ifndef SYSVSHM 5478525ce3SAlfred Perlstein void (*shmfork_hook)(struct proc *, struct proc *) = NULL; 553db161e0SMatthew Dillon void (*shmexit_hook)(struct vmspace *) = NULL; 5678525ce3SAlfred Perlstein 5778525ce3SAlfred Perlstein /* called from kern_fork.c */ 5878525ce3SAlfred Perlstein void 5978525ce3SAlfred Perlstein shmfork(p1, p2) 6078525ce3SAlfred Perlstein struct proc *p1, *p2; 6178525ce3SAlfred Perlstein { 6278525ce3SAlfred Perlstein 6378525ce3SAlfred Perlstein if (shmfork_hook != NULL) 6478525ce3SAlfred Perlstein shmfork_hook(p1, p2); 6578525ce3SAlfred Perlstein return; 6678525ce3SAlfred Perlstein } 6778525ce3SAlfred Perlstein 6878525ce3SAlfred Perlstein /* called from kern_exit.c */ 6978525ce3SAlfred Perlstein void 703db161e0SMatthew Dillon shmexit(struct vmspace *vm) 7178525ce3SAlfred Perlstein { 7278525ce3SAlfred Perlstein 7378525ce3SAlfred Perlstein if (shmexit_hook != NULL) 743db161e0SMatthew Dillon shmexit_hook(vm); 7578525ce3SAlfred Perlstein return; 7678525ce3SAlfred Perlstein } 77*5408c6dbSMateusz Guzik #endif 783d903220SDoug Rabson 793d903220SDoug Rabson /* 80857a6005SRobert Watson * Check for IPC permission. 81857a6005SRobert Watson * 82857a6005SRobert Watson * Note: The MAC Framework does not require any modifications to the 83857a6005SRobert Watson * ipcperm() function, as access control checks are performed throughout the 84857a6005SRobert Watson * implementation of each primitive. Those entry point calls complement the 85b12c55abSRobert Watson * ipcperm() discertionary checks. Unlike file system discretionary access 86b12c55abSRobert Watson * control, the original create of an object is given the same rights as the 87b12c55abSRobert Watson * current owner. 883d903220SDoug Rabson */ 893d903220SDoug Rabson int 90b12c55abSRobert Watson ipcperm(struct thread *td, struct ipc_perm *perm, int acc_mode) 913d903220SDoug Rabson { 92a854ed98SJohn Baldwin struct ucred *cred = td->td_ucred; 93b12c55abSRobert Watson int error, obj_mode, dac_granted, priv_granted; 943d903220SDoug Rabson 95b12c55abSRobert Watson dac_granted = 0; 96b12c55abSRobert Watson if (cred->cr_uid == perm->cuid || cred->cr_uid == perm->uid) { 97b12c55abSRobert Watson obj_mode = perm->mode; 98b12c55abSRobert Watson dac_granted |= IPC_M; 99b12c55abSRobert Watson } else if (groupmember(perm->gid, cred) || 100b12c55abSRobert Watson groupmember(perm->cgid, cred)) { 101b12c55abSRobert Watson obj_mode = perm->mode; 102b12c55abSRobert Watson obj_mode <<= 3; 103ef2e1ca5SRobert Watson } else { 104b12c55abSRobert Watson obj_mode = perm->mode; 105b12c55abSRobert Watson obj_mode <<= 6; 106acd3428bSRobert Watson } 107acd3428bSRobert Watson 108b12c55abSRobert Watson /* 109b12c55abSRobert Watson * While the System V IPC permission model allows IPC_M to be 110b12c55abSRobert Watson * granted, as part of the mode, our implementation requires 111b12c55abSRobert Watson * privilege to adminster the object if not the owner or creator. 112b12c55abSRobert Watson */ 113b12c55abSRobert Watson #if 0 114b12c55abSRobert Watson if (obj_mode & IPC_M) 115b12c55abSRobert Watson dac_granted |= IPC_M; 116b12c55abSRobert Watson #endif 117b12c55abSRobert Watson if (obj_mode & IPC_R) 118b12c55abSRobert Watson dac_granted |= IPC_R; 119b12c55abSRobert Watson if (obj_mode & IPC_W) 120b12c55abSRobert Watson dac_granted |= IPC_W; 121b12c55abSRobert Watson 122b12c55abSRobert Watson /* 123b12c55abSRobert Watson * Simple case: all required rights are granted by DAC. 124b12c55abSRobert Watson */ 125b12c55abSRobert Watson if ((dac_granted & acc_mode) == acc_mode) 1269ac57410SRobert Watson return (0); 127b12c55abSRobert Watson 128b12c55abSRobert Watson /* 129b12c55abSRobert Watson * Privilege is required to satisfy the request. 130b12c55abSRobert Watson */ 131b12c55abSRobert Watson priv_granted = 0; 132b12c55abSRobert Watson if ((acc_mode & IPC_M) && !(dac_granted & IPC_M)) { 13332f9753cSRobert Watson error = priv_check(td, PRIV_IPC_ADMIN); 134b12c55abSRobert Watson if (error == 0) 135b12c55abSRobert Watson priv_granted |= IPC_M; 136b12c55abSRobert Watson } 137b12c55abSRobert Watson 138b12c55abSRobert Watson if ((acc_mode & IPC_R) && !(dac_granted & IPC_R)) { 13932f9753cSRobert Watson error = priv_check(td, PRIV_IPC_READ); 140b12c55abSRobert Watson if (error == 0) 141b12c55abSRobert Watson priv_granted |= IPC_R; 142b12c55abSRobert Watson } 143b12c55abSRobert Watson 144b12c55abSRobert Watson if ((acc_mode & IPC_W) && !(dac_granted & IPC_W)) { 14532f9753cSRobert Watson error = priv_check(td, PRIV_IPC_WRITE); 146b12c55abSRobert Watson if (error == 0) 147b12c55abSRobert Watson priv_granted |= IPC_W; 148b12c55abSRobert Watson } 149b12c55abSRobert Watson 150b12c55abSRobert Watson if (((dac_granted | priv_granted) & acc_mode) == acc_mode) 151b12c55abSRobert Watson return (0); 152b12c55abSRobert Watson else 153b12c55abSRobert Watson return (EACCES); 1549ac57410SRobert Watson } 155b648d480SJohn Baldwin 156b648d480SJohn Baldwin #if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ 157b648d480SJohn Baldwin defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) 158b648d480SJohn Baldwin void 159b648d480SJohn Baldwin ipcperm_old2new(struct ipc_perm_old *old, struct ipc_perm *new) 160b648d480SJohn Baldwin { 161b648d480SJohn Baldwin 162b648d480SJohn Baldwin new->cuid = old->cuid; 163b648d480SJohn Baldwin new->cgid = old->cgid; 164b648d480SJohn Baldwin new->uid = old->uid; 165b648d480SJohn Baldwin new->gid = old->gid; 166b648d480SJohn Baldwin new->mode = old->mode; 167b648d480SJohn Baldwin new->seq = old->seq; 168b648d480SJohn Baldwin new->key = old->key; 169b648d480SJohn Baldwin } 170b648d480SJohn Baldwin 171b648d480SJohn Baldwin void 172b648d480SJohn Baldwin ipcperm_new2old(struct ipc_perm *new, struct ipc_perm_old *old) 173b648d480SJohn Baldwin { 174b648d480SJohn Baldwin 175b648d480SJohn Baldwin /* XXX: How to handle ID's > USHORT_MAX? */ 176b648d480SJohn Baldwin old->cuid = new->cuid; 177b648d480SJohn Baldwin old->cgid = new->cgid; 178b648d480SJohn Baldwin old->uid = new->uid; 179b648d480SJohn Baldwin old->gid = new->gid; 180b648d480SJohn Baldwin old->mode = new->mode; 181b648d480SJohn Baldwin old->seq = new->seq; 182b648d480SJohn Baldwin old->key = new->key; 183b648d480SJohn Baldwin } 184b648d480SJohn Baldwin #endif 1854cfc39cfSKonstantin Belousov 1864cfc39cfSKonstantin Belousov #ifdef COMPAT_FREEBSD32 1874cfc39cfSKonstantin Belousov #include <sys/mount.h> 1884cfc39cfSKonstantin Belousov #include <sys/socket.h> 1894cfc39cfSKonstantin Belousov #include <compat/freebsd32/freebsd32.h> 1904cfc39cfSKonstantin Belousov #include <compat/freebsd32/freebsd32_ipc.h> 1914cfc39cfSKonstantin Belousov #include <compat/freebsd32/freebsd32_proto.h> 1924cfc39cfSKonstantin Belousov #include <compat/freebsd32/freebsd32_signal.h> 1934cfc39cfSKonstantin Belousov #include <compat/freebsd32/freebsd32_syscall.h> 1944cfc39cfSKonstantin Belousov #include <compat/freebsd32/freebsd32_util.h> 1954cfc39cfSKonstantin Belousov 1964cfc39cfSKonstantin Belousov #if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ 1974cfc39cfSKonstantin Belousov defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) 1984cfc39cfSKonstantin Belousov void 1994cfc39cfSKonstantin Belousov freebsd32_ipcperm_old_in(struct ipc_perm32_old *ip32, struct ipc_perm *ip) 2004cfc39cfSKonstantin Belousov { 2014cfc39cfSKonstantin Belousov 2024cfc39cfSKonstantin Belousov CP(*ip32, *ip, cuid); 2034cfc39cfSKonstantin Belousov CP(*ip32, *ip, cgid); 2044cfc39cfSKonstantin Belousov CP(*ip32, *ip, uid); 2054cfc39cfSKonstantin Belousov CP(*ip32, *ip, gid); 2064cfc39cfSKonstantin Belousov CP(*ip32, *ip, mode); 2074cfc39cfSKonstantin Belousov CP(*ip32, *ip, seq); 2084cfc39cfSKonstantin Belousov CP(*ip32, *ip, key); 2094cfc39cfSKonstantin Belousov } 2104cfc39cfSKonstantin Belousov 2114cfc39cfSKonstantin Belousov void 2124cfc39cfSKonstantin Belousov freebsd32_ipcperm_old_out(struct ipc_perm *ip, struct ipc_perm32_old *ip32) 2134cfc39cfSKonstantin Belousov { 2144cfc39cfSKonstantin Belousov 2154cfc39cfSKonstantin Belousov CP(*ip, *ip32, cuid); 2164cfc39cfSKonstantin Belousov CP(*ip, *ip32, cgid); 2174cfc39cfSKonstantin Belousov CP(*ip, *ip32, uid); 2184cfc39cfSKonstantin Belousov CP(*ip, *ip32, gid); 2194cfc39cfSKonstantin Belousov CP(*ip, *ip32, mode); 2204cfc39cfSKonstantin Belousov CP(*ip, *ip32, seq); 2214cfc39cfSKonstantin Belousov CP(*ip, *ip32, key); 2224cfc39cfSKonstantin Belousov } 2234cfc39cfSKonstantin Belousov #endif 2244cfc39cfSKonstantin Belousov 2254cfc39cfSKonstantin Belousov void 2264cfc39cfSKonstantin Belousov freebsd32_ipcperm_in(struct ipc_perm32 *ip32, struct ipc_perm *ip) 2274cfc39cfSKonstantin Belousov { 2284cfc39cfSKonstantin Belousov 2294cfc39cfSKonstantin Belousov CP(*ip32, *ip, cuid); 2304cfc39cfSKonstantin Belousov CP(*ip32, *ip, cgid); 2314cfc39cfSKonstantin Belousov CP(*ip32, *ip, uid); 2324cfc39cfSKonstantin Belousov CP(*ip32, *ip, gid); 2334cfc39cfSKonstantin Belousov CP(*ip32, *ip, mode); 2344cfc39cfSKonstantin Belousov CP(*ip32, *ip, seq); 2354cfc39cfSKonstantin Belousov CP(*ip32, *ip, key); 2364cfc39cfSKonstantin Belousov } 2374cfc39cfSKonstantin Belousov 2384cfc39cfSKonstantin Belousov void 2394cfc39cfSKonstantin Belousov freebsd32_ipcperm_out(struct ipc_perm *ip, struct ipc_perm32 *ip32) 2404cfc39cfSKonstantin Belousov { 2414cfc39cfSKonstantin Belousov 2424cfc39cfSKonstantin Belousov CP(*ip, *ip32, cuid); 2434cfc39cfSKonstantin Belousov CP(*ip, *ip32, cgid); 2444cfc39cfSKonstantin Belousov CP(*ip, *ip32, uid); 2454cfc39cfSKonstantin Belousov CP(*ip, *ip32, gid); 2464cfc39cfSKonstantin Belousov CP(*ip, *ip32, mode); 2474cfc39cfSKonstantin Belousov CP(*ip, *ip32, seq); 2484cfc39cfSKonstantin Belousov CP(*ip, *ip32, key); 2494cfc39cfSKonstantin Belousov } 2504cfc39cfSKonstantin Belousov #endif 251