xref: /freebsd/sys/kern/sysv_ipc.c (revision b12c55ab925bb6d4af4dfa59c338f01fc01d8925)
13d903220SDoug Rabson /*	$NetBSD: sysv_ipc.c,v 1.7 1994/06/29 06:33:11 cgd Exp $	*/
29454b2d8SWarner Losh /*-
33d903220SDoug Rabson  * Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca>
4b12c55abSRobert Watson  * Copyright (c) 2006 nCircle Network Security, Inc.
53d903220SDoug Rabson  * All rights reserved.
63d903220SDoug Rabson  *
7b12c55abSRobert Watson  * This software was developed by Robert N. M. Watson for the TrustedBSD
8b12c55abSRobert Watson  * Project under contract to nCircle Network Security, Inc.
9b12c55abSRobert Watson  *
103d903220SDoug Rabson  * Redistribution and use in source and binary forms, with or without
113d903220SDoug Rabson  * modification, are permitted provided that the following conditions
123d903220SDoug Rabson  * are met:
133d903220SDoug Rabson  * 1. Redistributions of source code must retain the above copyright
143d903220SDoug Rabson  *    notice, this list of conditions and the following disclaimer.
153d903220SDoug Rabson  * 2. Redistributions in binary form must reproduce the above copyright
163d903220SDoug Rabson  *    notice, this list of conditions and the following disclaimer in the
173d903220SDoug Rabson  *    documentation and/or other materials provided with the distribution.
183d903220SDoug Rabson  * 3. All advertising materials mentioning features or use of this software
193d903220SDoug Rabson  *    must display the following acknowledgement:
203d903220SDoug Rabson  *      This product includes software developed by Herb Peyerl.
213d903220SDoug Rabson  * 4. The name of Herb Peyerl may not be used to endorse or promote products
223d903220SDoug Rabson  *    derived from this software without specific prior written permission.
233d903220SDoug Rabson  *
243d903220SDoug Rabson  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
253d903220SDoug Rabson  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
263d903220SDoug Rabson  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
273d903220SDoug Rabson  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
283d903220SDoug Rabson  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
293d903220SDoug Rabson  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
303d903220SDoug Rabson  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
313d903220SDoug Rabson  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
323d903220SDoug Rabson  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
333d903220SDoug Rabson  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
343d903220SDoug Rabson  */
353d903220SDoug Rabson 
36677b542eSDavid E. O'Brien #include <sys/cdefs.h>
37677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$");
38677b542eSDavid E. O'Brien 
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 
5078525ce3SAlfred Perlstein void (*shmfork_hook)(struct proc *, struct proc *) = NULL;
513db161e0SMatthew Dillon void (*shmexit_hook)(struct vmspace *) = NULL;
5278525ce3SAlfred Perlstein 
5378525ce3SAlfred Perlstein /* called from kern_fork.c */
5478525ce3SAlfred Perlstein void
5578525ce3SAlfred Perlstein shmfork(p1, p2)
5678525ce3SAlfred Perlstein 	struct proc *p1, *p2;
5778525ce3SAlfred Perlstein {
5878525ce3SAlfred Perlstein 
5978525ce3SAlfred Perlstein 	if (shmfork_hook != NULL)
6078525ce3SAlfred Perlstein 		shmfork_hook(p1, p2);
6178525ce3SAlfred Perlstein 	return;
6278525ce3SAlfred Perlstein }
6378525ce3SAlfred Perlstein 
6478525ce3SAlfred Perlstein /* called from kern_exit.c */
6578525ce3SAlfred Perlstein void
663db161e0SMatthew Dillon shmexit(struct vmspace *vm)
6778525ce3SAlfred Perlstein {
6878525ce3SAlfred Perlstein 
6978525ce3SAlfred Perlstein 	if (shmexit_hook != NULL)
703db161e0SMatthew Dillon 		shmexit_hook(vm);
7178525ce3SAlfred Perlstein 	return;
7278525ce3SAlfred Perlstein }
733d903220SDoug Rabson 
743d903220SDoug Rabson /*
75857a6005SRobert Watson  * Check for IPC permission.
76857a6005SRobert Watson  *
77857a6005SRobert Watson  * Note: The MAC Framework does not require any modifications to the
78857a6005SRobert Watson  * ipcperm() function, as access control checks are performed throughout the
79857a6005SRobert Watson  * implementation of each primitive.  Those entry point calls complement the
80b12c55abSRobert Watson  * ipcperm() discertionary checks.  Unlike file system discretionary access
81b12c55abSRobert Watson  * control, the original create of an object is given the same rights as the
82b12c55abSRobert Watson  * current owner.
833d903220SDoug Rabson  */
843d903220SDoug Rabson int
85b12c55abSRobert Watson ipcperm(struct thread *td, struct ipc_perm *perm, int acc_mode)
863d903220SDoug Rabson {
87a854ed98SJohn Baldwin 	struct ucred *cred = td->td_ucred;
88b12c55abSRobert Watson 	int error, obj_mode, dac_granted, priv_granted;
893d903220SDoug Rabson 
90b12c55abSRobert Watson 	dac_granted = 0;
91b12c55abSRobert Watson 	if (cred->cr_uid == perm->cuid || cred->cr_uid == perm->uid) {
92b12c55abSRobert Watson 		obj_mode = perm->mode;
93b12c55abSRobert Watson 		dac_granted |= IPC_M;
94b12c55abSRobert Watson 	} else if (groupmember(perm->gid, cred) ||
95b12c55abSRobert Watson 	    groupmember(perm->cgid, cred)) {
96b12c55abSRobert Watson 		obj_mode = perm->mode;
97b12c55abSRobert Watson 		obj_mode <<= 3;
98ef2e1ca5SRobert Watson 	} else {
99b12c55abSRobert Watson 		obj_mode = perm->mode;
100b12c55abSRobert Watson 		obj_mode <<= 6;
101acd3428bSRobert Watson 	}
102acd3428bSRobert Watson 
103b12c55abSRobert Watson 	/*
104b12c55abSRobert Watson 	 * While the System V IPC permission model allows IPC_M to be
105b12c55abSRobert Watson 	 * granted, as part of the mode, our implementation requires
106b12c55abSRobert Watson 	 * privilege to adminster the object if not the owner or creator.
107b12c55abSRobert Watson 	 */
108b12c55abSRobert Watson #if 0
109b12c55abSRobert Watson 	if (obj_mode & IPC_M)
110b12c55abSRobert Watson 		dac_granted |= IPC_M;
111b12c55abSRobert Watson #endif
112b12c55abSRobert Watson 	if (obj_mode & IPC_R)
113b12c55abSRobert Watson 		dac_granted |= IPC_R;
114b12c55abSRobert Watson 	if (obj_mode & IPC_W)
115b12c55abSRobert Watson 		dac_granted |= IPC_W;
116b12c55abSRobert Watson 
117b12c55abSRobert Watson 	/*
118b12c55abSRobert Watson 	 * Simple case: all required rights are granted by DAC.
119b12c55abSRobert Watson 	 */
120b12c55abSRobert Watson 	if ((dac_granted & acc_mode) == acc_mode)
1219ac57410SRobert Watson 		return (0);
122b12c55abSRobert Watson 
123b12c55abSRobert Watson 	/*
124b12c55abSRobert Watson 	 * Privilege is required to satisfy the request.
125b12c55abSRobert Watson 	 */
126b12c55abSRobert Watson 	priv_granted = 0;
127b12c55abSRobert Watson 	if ((acc_mode & IPC_M) && !(dac_granted & IPC_M)) {
128b12c55abSRobert Watson 		error = priv_check(td, PRIV_IPC_ADMIN);
129b12c55abSRobert Watson 		if (error == 0)
130b12c55abSRobert Watson 			priv_granted |= IPC_M;
131b12c55abSRobert Watson 	}
132b12c55abSRobert Watson 
133b12c55abSRobert Watson 	if ((acc_mode & IPC_R) && !(dac_granted & IPC_R)) {
134b12c55abSRobert Watson 		error = priv_check(td, PRIV_IPC_READ);
135b12c55abSRobert Watson 		if (error == 0)
136b12c55abSRobert Watson 			priv_granted |= IPC_R;
137b12c55abSRobert Watson 	}
138b12c55abSRobert Watson 
139b12c55abSRobert Watson 	if ((acc_mode & IPC_W) && !(dac_granted & IPC_W)) {
140b12c55abSRobert Watson 		error = priv_check(td, PRIV_IPC_WRITE);
141b12c55abSRobert Watson 		if (error == 0)
142b12c55abSRobert Watson 			priv_granted |= IPC_W;
143b12c55abSRobert Watson 	}
144b12c55abSRobert Watson 
145b12c55abSRobert Watson 	if (((dac_granted | priv_granted) & acc_mode) == acc_mode)
146b12c55abSRobert Watson 		return (0);
147b12c55abSRobert Watson 	else
148b12c55abSRobert Watson 		return (EACCES);
1499ac57410SRobert Watson }
150