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
39511b67b7SGarrett Wollman #include "opt_sysvipc.h"
40511b67b7SGarrett Wollman
413d903220SDoug Rabson #include <sys/param.h>
42cf9fa8e7SPoul-Henning Kamp #include <sys/systm.h>
4378525ce3SAlfred Perlstein #include <sys/sem.h>
4478525ce3SAlfred Perlstein #include <sys/shm.h>
4581090119SPeter Wemm #include <sys/ipc.h>
46b12c55abSRobert Watson #include <sys/priv.h>
471c308b81SPoul-Henning Kamp #include <sys/proc.h>
48b7f5d5b5SBruce Evans #include <sys/ucred.h>
4981090119SPeter Wemm
505408c6dbSMateusz Guzik #ifndef SYSVSHM
5178525ce3SAlfred Perlstein void (*shmfork_hook)(struct proc *, struct proc *) = NULL;
523db161e0SMatthew Dillon void (*shmexit_hook)(struct vmspace *) = NULL;
53*b7202958SKonstantin Belousov void (*shmobjinfo_hook)(struct vm_object *, key_t *key,
54*b7202958SKonstantin Belousov unsigned short *seq) = NULL;
5578525ce3SAlfred Perlstein
5678525ce3SAlfred Perlstein /* called from kern_fork.c */
5778525ce3SAlfred Perlstein void
shmfork(struct proc * p1,struct proc * p2)58836e4b37SKonstantin Belousov shmfork(struct proc *p1, struct proc *p2)
5978525ce3SAlfred Perlstein {
6078525ce3SAlfred Perlstein if (shmfork_hook != NULL)
6178525ce3SAlfred Perlstein shmfork_hook(p1, p2);
6278525ce3SAlfred Perlstein }
6378525ce3SAlfred Perlstein
6478525ce3SAlfred Perlstein /* called from kern_exit.c */
6578525ce3SAlfred Perlstein void
shmexit(struct vmspace * vm)663db161e0SMatthew Dillon shmexit(struct vmspace *vm)
6778525ce3SAlfred Perlstein {
6878525ce3SAlfred Perlstein if (shmexit_hook != NULL)
693db161e0SMatthew Dillon shmexit_hook(vm);
7078525ce3SAlfred Perlstein }
71*b7202958SKonstantin Belousov
72*b7202958SKonstantin Belousov void
shmobjinfo(struct vm_object * obj,key_t * key,unsigned short * seq)73*b7202958SKonstantin Belousov shmobjinfo(struct vm_object *obj, key_t *key, unsigned short *seq)
74*b7202958SKonstantin Belousov {
75*b7202958SKonstantin Belousov *key = 0; /* For non-present sysvshm.ko */
76*b7202958SKonstantin Belousov *seq = 0;
77*b7202958SKonstantin Belousov if (shmobjinfo_hook != NULL)
78*b7202958SKonstantin Belousov shmobjinfo_hook(obj, key, seq);
79*b7202958SKonstantin Belousov }
805408c6dbSMateusz Guzik #endif
813d903220SDoug Rabson
823d903220SDoug Rabson /*
83857a6005SRobert Watson * Check for IPC permission.
84857a6005SRobert Watson *
85857a6005SRobert Watson * Note: The MAC Framework does not require any modifications to the
86857a6005SRobert Watson * ipcperm() function, as access control checks are performed throughout the
87857a6005SRobert Watson * implementation of each primitive. Those entry point calls complement the
88b12c55abSRobert Watson * ipcperm() discertionary checks. Unlike file system discretionary access
89b12c55abSRobert Watson * control, the original create of an object is given the same rights as the
90b12c55abSRobert Watson * current owner.
913d903220SDoug Rabson */
923d903220SDoug Rabson int
ipcperm(struct thread * td,struct ipc_perm * perm,int acc_mode)93b12c55abSRobert Watson ipcperm(struct thread *td, struct ipc_perm *perm, int acc_mode)
943d903220SDoug Rabson {
95a854ed98SJohn Baldwin struct ucred *cred = td->td_ucred;
96b12c55abSRobert Watson int error, obj_mode, dac_granted, priv_granted;
973d903220SDoug Rabson
98b12c55abSRobert Watson dac_granted = 0;
99b12c55abSRobert Watson if (cred->cr_uid == perm->cuid || cred->cr_uid == perm->uid) {
100b12c55abSRobert Watson obj_mode = perm->mode;
101b12c55abSRobert Watson dac_granted |= IPC_M;
102b12c55abSRobert Watson } else if (groupmember(perm->gid, cred) ||
103b12c55abSRobert Watson groupmember(perm->cgid, cred)) {
104b12c55abSRobert Watson obj_mode = perm->mode;
105b12c55abSRobert Watson obj_mode <<= 3;
106ef2e1ca5SRobert Watson } else {
107b12c55abSRobert Watson obj_mode = perm->mode;
108b12c55abSRobert Watson obj_mode <<= 6;
109acd3428bSRobert Watson }
110acd3428bSRobert Watson
111b12c55abSRobert Watson /*
112b12c55abSRobert Watson * While the System V IPC permission model allows IPC_M to be
113b12c55abSRobert Watson * granted, as part of the mode, our implementation requires
114b12c55abSRobert Watson * privilege to adminster the object if not the owner or creator.
115b12c55abSRobert Watson */
116b12c55abSRobert Watson #if 0
117b12c55abSRobert Watson if (obj_mode & IPC_M)
118b12c55abSRobert Watson dac_granted |= IPC_M;
119b12c55abSRobert Watson #endif
120b12c55abSRobert Watson if (obj_mode & IPC_R)
121b12c55abSRobert Watson dac_granted |= IPC_R;
122b12c55abSRobert Watson if (obj_mode & IPC_W)
123b12c55abSRobert Watson dac_granted |= IPC_W;
124b12c55abSRobert Watson
125b12c55abSRobert Watson /*
126b12c55abSRobert Watson * Simple case: all required rights are granted by DAC.
127b12c55abSRobert Watson */
128b12c55abSRobert Watson if ((dac_granted & acc_mode) == acc_mode)
1299ac57410SRobert Watson return (0);
130b12c55abSRobert Watson
131b12c55abSRobert Watson /*
132b12c55abSRobert Watson * Privilege is required to satisfy the request.
133b12c55abSRobert Watson */
134b12c55abSRobert Watson priv_granted = 0;
135b12c55abSRobert Watson if ((acc_mode & IPC_M) && !(dac_granted & IPC_M)) {
13632f9753cSRobert Watson error = priv_check(td, PRIV_IPC_ADMIN);
137b12c55abSRobert Watson if (error == 0)
138b12c55abSRobert Watson priv_granted |= IPC_M;
139b12c55abSRobert Watson }
140b12c55abSRobert Watson
141b12c55abSRobert Watson if ((acc_mode & IPC_R) && !(dac_granted & IPC_R)) {
14232f9753cSRobert Watson error = priv_check(td, PRIV_IPC_READ);
143b12c55abSRobert Watson if (error == 0)
144b12c55abSRobert Watson priv_granted |= IPC_R;
145b12c55abSRobert Watson }
146b12c55abSRobert Watson
147b12c55abSRobert Watson if ((acc_mode & IPC_W) && !(dac_granted & IPC_W)) {
14832f9753cSRobert Watson error = priv_check(td, PRIV_IPC_WRITE);
149b12c55abSRobert Watson if (error == 0)
150b12c55abSRobert Watson priv_granted |= IPC_W;
151b12c55abSRobert Watson }
152b12c55abSRobert Watson
153b12c55abSRobert Watson if (((dac_granted | priv_granted) & acc_mode) == acc_mode)
154b12c55abSRobert Watson return (0);
155b12c55abSRobert Watson else
156b12c55abSRobert Watson return (EACCES);
1579ac57410SRobert Watson }
158b648d480SJohn Baldwin
159b648d480SJohn Baldwin #if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
160b648d480SJohn Baldwin defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
161b648d480SJohn Baldwin void
ipcperm_old2new(struct ipc_perm_old * old,struct ipc_perm * new)162b648d480SJohn Baldwin ipcperm_old2new(struct ipc_perm_old *old, struct ipc_perm *new)
163b648d480SJohn Baldwin {
164b648d480SJohn Baldwin
165b648d480SJohn Baldwin new->cuid = old->cuid;
166b648d480SJohn Baldwin new->cgid = old->cgid;
167b648d480SJohn Baldwin new->uid = old->uid;
168b648d480SJohn Baldwin new->gid = old->gid;
169b648d480SJohn Baldwin new->mode = old->mode;
170b648d480SJohn Baldwin new->seq = old->seq;
171b648d480SJohn Baldwin new->key = old->key;
172b648d480SJohn Baldwin }
173b648d480SJohn Baldwin
174b648d480SJohn Baldwin void
ipcperm_new2old(struct ipc_perm * new,struct ipc_perm_old * old)175b648d480SJohn Baldwin ipcperm_new2old(struct ipc_perm *new, struct ipc_perm_old *old)
176b648d480SJohn Baldwin {
177b648d480SJohn Baldwin
178b648d480SJohn Baldwin /* XXX: How to handle ID's > USHORT_MAX? */
179b648d480SJohn Baldwin old->cuid = new->cuid;
180b648d480SJohn Baldwin old->cgid = new->cgid;
181b648d480SJohn Baldwin old->uid = new->uid;
182b648d480SJohn Baldwin old->gid = new->gid;
183b648d480SJohn Baldwin old->mode = new->mode;
184b648d480SJohn Baldwin old->seq = new->seq;
185b648d480SJohn Baldwin old->key = new->key;
186b648d480SJohn Baldwin }
187b648d480SJohn Baldwin #endif
1884cfc39cfSKonstantin Belousov
1894cfc39cfSKonstantin Belousov #ifdef COMPAT_FREEBSD32
1904cfc39cfSKonstantin Belousov #include <sys/mount.h>
1914cfc39cfSKonstantin Belousov #include <sys/socket.h>
1924cfc39cfSKonstantin Belousov #include <compat/freebsd32/freebsd32.h>
1934cfc39cfSKonstantin Belousov #include <compat/freebsd32/freebsd32_ipc.h>
1944cfc39cfSKonstantin Belousov #include <compat/freebsd32/freebsd32_proto.h>
1954cfc39cfSKonstantin Belousov #include <compat/freebsd32/freebsd32_signal.h>
1964cfc39cfSKonstantin Belousov #include <compat/freebsd32/freebsd32_syscall.h>
1974cfc39cfSKonstantin Belousov #include <compat/freebsd32/freebsd32_util.h>
1984cfc39cfSKonstantin Belousov
1994cfc39cfSKonstantin Belousov #if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
2004cfc39cfSKonstantin Belousov defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
2014cfc39cfSKonstantin Belousov void
freebsd32_ipcperm_old_in(struct ipc_perm_old32 * ip32,struct ipc_perm * ip)2023b0cd7e5SBrooks Davis freebsd32_ipcperm_old_in(struct ipc_perm_old32 *ip32, struct ipc_perm *ip)
2034cfc39cfSKonstantin Belousov {
2044cfc39cfSKonstantin Belousov
2054cfc39cfSKonstantin Belousov CP(*ip32, *ip, cuid);
2064cfc39cfSKonstantin Belousov CP(*ip32, *ip, cgid);
2074cfc39cfSKonstantin Belousov CP(*ip32, *ip, uid);
2084cfc39cfSKonstantin Belousov CP(*ip32, *ip, gid);
2094cfc39cfSKonstantin Belousov CP(*ip32, *ip, mode);
2104cfc39cfSKonstantin Belousov CP(*ip32, *ip, seq);
2114cfc39cfSKonstantin Belousov CP(*ip32, *ip, key);
2124cfc39cfSKonstantin Belousov }
2134cfc39cfSKonstantin Belousov
2144cfc39cfSKonstantin Belousov void
freebsd32_ipcperm_old_out(struct ipc_perm * ip,struct ipc_perm_old32 * ip32)2153b0cd7e5SBrooks Davis freebsd32_ipcperm_old_out(struct ipc_perm *ip, struct ipc_perm_old32 *ip32)
2164cfc39cfSKonstantin Belousov {
2174cfc39cfSKonstantin Belousov
2184cfc39cfSKonstantin Belousov CP(*ip, *ip32, cuid);
2194cfc39cfSKonstantin Belousov CP(*ip, *ip32, cgid);
2204cfc39cfSKonstantin Belousov CP(*ip, *ip32, uid);
2214cfc39cfSKonstantin Belousov CP(*ip, *ip32, gid);
2224cfc39cfSKonstantin Belousov CP(*ip, *ip32, mode);
2234cfc39cfSKonstantin Belousov CP(*ip, *ip32, seq);
2244cfc39cfSKonstantin Belousov CP(*ip, *ip32, key);
2254cfc39cfSKonstantin Belousov }
2264cfc39cfSKonstantin Belousov #endif
2274cfc39cfSKonstantin Belousov
2284cfc39cfSKonstantin Belousov void
freebsd32_ipcperm_in(struct ipc_perm32 * ip32,struct ipc_perm * ip)2294cfc39cfSKonstantin Belousov freebsd32_ipcperm_in(struct ipc_perm32 *ip32, struct ipc_perm *ip)
2304cfc39cfSKonstantin Belousov {
2314cfc39cfSKonstantin Belousov
2324cfc39cfSKonstantin Belousov CP(*ip32, *ip, cuid);
2334cfc39cfSKonstantin Belousov CP(*ip32, *ip, cgid);
2344cfc39cfSKonstantin Belousov CP(*ip32, *ip, uid);
2354cfc39cfSKonstantin Belousov CP(*ip32, *ip, gid);
2364cfc39cfSKonstantin Belousov CP(*ip32, *ip, mode);
2374cfc39cfSKonstantin Belousov CP(*ip32, *ip, seq);
2384cfc39cfSKonstantin Belousov CP(*ip32, *ip, key);
2394cfc39cfSKonstantin Belousov }
2404cfc39cfSKonstantin Belousov
2414cfc39cfSKonstantin Belousov void
freebsd32_ipcperm_out(struct ipc_perm * ip,struct ipc_perm32 * ip32)2424cfc39cfSKonstantin Belousov freebsd32_ipcperm_out(struct ipc_perm *ip, struct ipc_perm32 *ip32)
2434cfc39cfSKonstantin Belousov {
2444cfc39cfSKonstantin Belousov
2454cfc39cfSKonstantin Belousov CP(*ip, *ip32, cuid);
2464cfc39cfSKonstantin Belousov CP(*ip, *ip32, cgid);
2474cfc39cfSKonstantin Belousov CP(*ip, *ip32, uid);
2484cfc39cfSKonstantin Belousov CP(*ip, *ip32, gid);
2494cfc39cfSKonstantin Belousov CP(*ip, *ip32, mode);
2504cfc39cfSKonstantin Belousov CP(*ip, *ip32, seq);
2514cfc39cfSKonstantin Belousov CP(*ip, *ip32, key);
2524cfc39cfSKonstantin Belousov }
2534cfc39cfSKonstantin Belousov #endif
254