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. 35*0879ca72SPedro F. Giffuni * 36*0879ca72SPedro 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 42b648d480SJohn Baldwin #include "opt_compat.h" 43511b67b7SGarrett Wollman #include "opt_sysvipc.h" 44511b67b7SGarrett Wollman 453d903220SDoug Rabson #include <sys/param.h> 46cf9fa8e7SPoul-Henning Kamp #include <sys/systm.h> 4778525ce3SAlfred Perlstein #include <sys/sem.h> 4878525ce3SAlfred Perlstein #include <sys/shm.h> 4981090119SPeter Wemm #include <sys/ipc.h> 50b12c55abSRobert Watson #include <sys/priv.h> 511c308b81SPoul-Henning Kamp #include <sys/proc.h> 52b7f5d5b5SBruce Evans #include <sys/ucred.h> 5381090119SPeter Wemm 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 } 773d903220SDoug Rabson 783d903220SDoug Rabson /* 79857a6005SRobert Watson * Check for IPC permission. 80857a6005SRobert Watson * 81857a6005SRobert Watson * Note: The MAC Framework does not require any modifications to the 82857a6005SRobert Watson * ipcperm() function, as access control checks are performed throughout the 83857a6005SRobert Watson * implementation of each primitive. Those entry point calls complement the 84b12c55abSRobert Watson * ipcperm() discertionary checks. Unlike file system discretionary access 85b12c55abSRobert Watson * control, the original create of an object is given the same rights as the 86b12c55abSRobert Watson * current owner. 873d903220SDoug Rabson */ 883d903220SDoug Rabson int 89b12c55abSRobert Watson ipcperm(struct thread *td, struct ipc_perm *perm, int acc_mode) 903d903220SDoug Rabson { 91a854ed98SJohn Baldwin struct ucred *cred = td->td_ucred; 92b12c55abSRobert Watson int error, obj_mode, dac_granted, priv_granted; 933d903220SDoug Rabson 94b12c55abSRobert Watson dac_granted = 0; 95b12c55abSRobert Watson if (cred->cr_uid == perm->cuid || cred->cr_uid == perm->uid) { 96b12c55abSRobert Watson obj_mode = perm->mode; 97b12c55abSRobert Watson dac_granted |= IPC_M; 98b12c55abSRobert Watson } else if (groupmember(perm->gid, cred) || 99b12c55abSRobert Watson groupmember(perm->cgid, cred)) { 100b12c55abSRobert Watson obj_mode = perm->mode; 101b12c55abSRobert Watson obj_mode <<= 3; 102ef2e1ca5SRobert Watson } else { 103b12c55abSRobert Watson obj_mode = perm->mode; 104b12c55abSRobert Watson obj_mode <<= 6; 105acd3428bSRobert Watson } 106acd3428bSRobert Watson 107b12c55abSRobert Watson /* 108b12c55abSRobert Watson * While the System V IPC permission model allows IPC_M to be 109b12c55abSRobert Watson * granted, as part of the mode, our implementation requires 110b12c55abSRobert Watson * privilege to adminster the object if not the owner or creator. 111b12c55abSRobert Watson */ 112b12c55abSRobert Watson #if 0 113b12c55abSRobert Watson if (obj_mode & IPC_M) 114b12c55abSRobert Watson dac_granted |= IPC_M; 115b12c55abSRobert Watson #endif 116b12c55abSRobert Watson if (obj_mode & IPC_R) 117b12c55abSRobert Watson dac_granted |= IPC_R; 118b12c55abSRobert Watson if (obj_mode & IPC_W) 119b12c55abSRobert Watson dac_granted |= IPC_W; 120b12c55abSRobert Watson 121b12c55abSRobert Watson /* 122b12c55abSRobert Watson * Simple case: all required rights are granted by DAC. 123b12c55abSRobert Watson */ 124b12c55abSRobert Watson if ((dac_granted & acc_mode) == acc_mode) 1259ac57410SRobert Watson return (0); 126b12c55abSRobert Watson 127b12c55abSRobert Watson /* 128b12c55abSRobert Watson * Privilege is required to satisfy the request. 129b12c55abSRobert Watson */ 130b12c55abSRobert Watson priv_granted = 0; 131b12c55abSRobert Watson if ((acc_mode & IPC_M) && !(dac_granted & IPC_M)) { 13232f9753cSRobert Watson error = priv_check(td, PRIV_IPC_ADMIN); 133b12c55abSRobert Watson if (error == 0) 134b12c55abSRobert Watson priv_granted |= IPC_M; 135b12c55abSRobert Watson } 136b12c55abSRobert Watson 137b12c55abSRobert Watson if ((acc_mode & IPC_R) && !(dac_granted & IPC_R)) { 13832f9753cSRobert Watson error = priv_check(td, PRIV_IPC_READ); 139b12c55abSRobert Watson if (error == 0) 140b12c55abSRobert Watson priv_granted |= IPC_R; 141b12c55abSRobert Watson } 142b12c55abSRobert Watson 143b12c55abSRobert Watson if ((acc_mode & IPC_W) && !(dac_granted & IPC_W)) { 14432f9753cSRobert Watson error = priv_check(td, PRIV_IPC_WRITE); 145b12c55abSRobert Watson if (error == 0) 146b12c55abSRobert Watson priv_granted |= IPC_W; 147b12c55abSRobert Watson } 148b12c55abSRobert Watson 149b12c55abSRobert Watson if (((dac_granted | priv_granted) & acc_mode) == acc_mode) 150b12c55abSRobert Watson return (0); 151b12c55abSRobert Watson else 152b12c55abSRobert Watson return (EACCES); 1539ac57410SRobert Watson } 154b648d480SJohn Baldwin 155b648d480SJohn Baldwin #if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ 156b648d480SJohn Baldwin defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) 157b648d480SJohn Baldwin void 158b648d480SJohn Baldwin ipcperm_old2new(struct ipc_perm_old *old, struct ipc_perm *new) 159b648d480SJohn Baldwin { 160b648d480SJohn Baldwin 161b648d480SJohn Baldwin new->cuid = old->cuid; 162b648d480SJohn Baldwin new->cgid = old->cgid; 163b648d480SJohn Baldwin new->uid = old->uid; 164b648d480SJohn Baldwin new->gid = old->gid; 165b648d480SJohn Baldwin new->mode = old->mode; 166b648d480SJohn Baldwin new->seq = old->seq; 167b648d480SJohn Baldwin new->key = old->key; 168b648d480SJohn Baldwin } 169b648d480SJohn Baldwin 170b648d480SJohn Baldwin void 171b648d480SJohn Baldwin ipcperm_new2old(struct ipc_perm *new, struct ipc_perm_old *old) 172b648d480SJohn Baldwin { 173b648d480SJohn Baldwin 174b648d480SJohn Baldwin /* XXX: How to handle ID's > USHORT_MAX? */ 175b648d480SJohn Baldwin old->cuid = new->cuid; 176b648d480SJohn Baldwin old->cgid = new->cgid; 177b648d480SJohn Baldwin old->uid = new->uid; 178b648d480SJohn Baldwin old->gid = new->gid; 179b648d480SJohn Baldwin old->mode = new->mode; 180b648d480SJohn Baldwin old->seq = new->seq; 181b648d480SJohn Baldwin old->key = new->key; 182b648d480SJohn Baldwin } 183b648d480SJohn Baldwin #endif 1844cfc39cfSKonstantin Belousov 1854cfc39cfSKonstantin Belousov #ifdef COMPAT_FREEBSD32 1864cfc39cfSKonstantin Belousov #include <sys/mount.h> 1874cfc39cfSKonstantin Belousov #include <sys/socket.h> 1884cfc39cfSKonstantin Belousov #include <compat/freebsd32/freebsd32.h> 1894cfc39cfSKonstantin Belousov #include <compat/freebsd32/freebsd32_ipc.h> 1904cfc39cfSKonstantin Belousov #include <compat/freebsd32/freebsd32_proto.h> 1914cfc39cfSKonstantin Belousov #include <compat/freebsd32/freebsd32_signal.h> 1924cfc39cfSKonstantin Belousov #include <compat/freebsd32/freebsd32_syscall.h> 1934cfc39cfSKonstantin Belousov #include <compat/freebsd32/freebsd32_util.h> 1944cfc39cfSKonstantin Belousov 1954cfc39cfSKonstantin Belousov #if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ 1964cfc39cfSKonstantin Belousov defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) 1974cfc39cfSKonstantin Belousov void 1984cfc39cfSKonstantin Belousov freebsd32_ipcperm_old_in(struct ipc_perm32_old *ip32, struct ipc_perm *ip) 1994cfc39cfSKonstantin Belousov { 2004cfc39cfSKonstantin Belousov 2014cfc39cfSKonstantin Belousov CP(*ip32, *ip, cuid); 2024cfc39cfSKonstantin Belousov CP(*ip32, *ip, cgid); 2034cfc39cfSKonstantin Belousov CP(*ip32, *ip, uid); 2044cfc39cfSKonstantin Belousov CP(*ip32, *ip, gid); 2054cfc39cfSKonstantin Belousov CP(*ip32, *ip, mode); 2064cfc39cfSKonstantin Belousov CP(*ip32, *ip, seq); 2074cfc39cfSKonstantin Belousov CP(*ip32, *ip, key); 2084cfc39cfSKonstantin Belousov } 2094cfc39cfSKonstantin Belousov 2104cfc39cfSKonstantin Belousov void 2114cfc39cfSKonstantin Belousov freebsd32_ipcperm_old_out(struct ipc_perm *ip, struct ipc_perm32_old *ip32) 2124cfc39cfSKonstantin Belousov { 2134cfc39cfSKonstantin Belousov 2144cfc39cfSKonstantin Belousov CP(*ip, *ip32, cuid); 2154cfc39cfSKonstantin Belousov CP(*ip, *ip32, cgid); 2164cfc39cfSKonstantin Belousov CP(*ip, *ip32, uid); 2174cfc39cfSKonstantin Belousov CP(*ip, *ip32, gid); 2184cfc39cfSKonstantin Belousov CP(*ip, *ip32, mode); 2194cfc39cfSKonstantin Belousov CP(*ip, *ip32, seq); 2204cfc39cfSKonstantin Belousov CP(*ip, *ip32, key); 2214cfc39cfSKonstantin Belousov } 2224cfc39cfSKonstantin Belousov #endif 2234cfc39cfSKonstantin Belousov 2244cfc39cfSKonstantin Belousov void 2254cfc39cfSKonstantin Belousov freebsd32_ipcperm_in(struct ipc_perm32 *ip32, struct ipc_perm *ip) 2264cfc39cfSKonstantin Belousov { 2274cfc39cfSKonstantin Belousov 2284cfc39cfSKonstantin Belousov CP(*ip32, *ip, cuid); 2294cfc39cfSKonstantin Belousov CP(*ip32, *ip, cgid); 2304cfc39cfSKonstantin Belousov CP(*ip32, *ip, uid); 2314cfc39cfSKonstantin Belousov CP(*ip32, *ip, gid); 2324cfc39cfSKonstantin Belousov CP(*ip32, *ip, mode); 2334cfc39cfSKonstantin Belousov CP(*ip32, *ip, seq); 2344cfc39cfSKonstantin Belousov CP(*ip32, *ip, key); 2354cfc39cfSKonstantin Belousov } 2364cfc39cfSKonstantin Belousov 2374cfc39cfSKonstantin Belousov void 2384cfc39cfSKonstantin Belousov freebsd32_ipcperm_out(struct ipc_perm *ip, struct ipc_perm32 *ip32) 2394cfc39cfSKonstantin Belousov { 2404cfc39cfSKonstantin Belousov 2414cfc39cfSKonstantin Belousov CP(*ip, *ip32, cuid); 2424cfc39cfSKonstantin Belousov CP(*ip, *ip32, cgid); 2434cfc39cfSKonstantin Belousov CP(*ip, *ip32, uid); 2444cfc39cfSKonstantin Belousov CP(*ip, *ip32, gid); 2454cfc39cfSKonstantin Belousov CP(*ip, *ip32, mode); 2464cfc39cfSKonstantin Belousov CP(*ip, *ip32, seq); 2474cfc39cfSKonstantin Belousov CP(*ip, *ip32, key); 2484cfc39cfSKonstantin Belousov } 2494cfc39cfSKonstantin Belousov #endif 250