1/*
2 * Copyright (c) 2007 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29/*-
30 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
31 * Copyright (c) 2001 Ilmar S. Habibulin
32 * Copyright (c) 2001, 2002, 2003, 2004 Networks Associates Technology, Inc.
33 * Copyright (c) 2005 SPARTA, Inc.
34 * All rights reserved.
35 *
36 * This software was developed by Robert Watson and Ilmar Habibulin for the
37 * TrustedBSD Project.
38 *
39 * This software was developed for the FreeBSD Project in part by Network
40 * Associates Laboratories, the Security Research Division of Network
41 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
42 * as part of the DARPA CHATS research program.
43 *
44 * Redistribution and use in source and binary forms, with or without
45 * modification, are permitted provided that the following conditions
46 * are met:
47 * 1. Redistributions of source code must retain the above copyright
48 *    notice, this list of conditions and the following disclaimer.
49 * 2. Redistributions in binary form must reproduce the above copyright
50 *    notice, this list of conditions and the following disclaimer in the
51 *    documentation and/or other materials provided with the distribution.
52 *
53 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 * SUCH DAMAGE.
64 *
65 */
66
67#ifndef _SECURITY_MAC_INTERNAL_H_
68#define _SECURITY_MAC_INTERNAL_H_
69
70#ifndef PRIVATE
71#warning "MAC policy is not KPI, see Technical Q&A QA1574, this header will be removed in next version"
72#endif
73
74#include <string.h>
75#include <sys/param.h>
76#include <sys/queue.h>
77#include <security/mac.h>
78#include <security/mac_framework.h>
79#include <security/mac_policy.h>
80#include <security/mac_data.h>
81#include <sys/sysctl.h>
82#include <kern/wait_queue.h>
83#include <kern/locks.h>
84#include <sys/kernel.h>
85#include <sys/lock.h>
86#include <sys/malloc.h>
87#include <sys/sbuf.h>
88#include <sys/proc.h>
89#include <sys/systm.h>
90#include <sys/socket.h>
91#include <sys/socketvar.h>
92#include <sys/vnode.h>
93
94/*
95 * MAC Framework sysctl namespace.
96 */
97
98SYSCTL_DECL(_security);
99SYSCTL_DECL(_security_mac);
100
101extern int mac_late;
102
103struct mac_policy_list_element {
104        struct mac_policy_conf *mpc;
105};
106
107struct mac_policy_list {
108	u_int				numloaded;
109	u_int 				max;
110	u_int				maxindex;
111	u_int				staticmax;
112	u_int				chunks;
113	u_int				freehint;
114	struct mac_policy_list_element	*entries;
115};
116
117typedef struct mac_policy_list mac_policy_list_t;
118
119
120/*
121 * Policy that has registered with the framework for a specific
122 * label namespace name.
123 */
124struct mac_label_listener {
125	mac_policy_handle_t		mll_handle;
126	LIST_ENTRY(mac_label_listener)	mll_list;
127};
128
129LIST_HEAD(mac_label_listeners_t, mac_label_listener);
130
131/*
132 * Type of list used to manage label namespace names.
133 */
134struct mac_label_element {
135	char				mle_name[MAC_MAX_LABEL_ELEMENT_NAME];
136	struct mac_label_listeners_t	mle_listeners;
137	LIST_ENTRY(mac_label_element)	mle_list;
138};
139
140LIST_HEAD(mac_label_element_list_t, mac_label_element);
141
142/*
143 * MAC Framework global variables.
144 */
145
146extern struct mac_label_element_list_t mac_label_element_list;
147extern struct mac_label_element_list_t mac_static_label_element_list;
148
149extern struct mac_policy_list mac_policy_list;
150
151/*
152 * global flags to control whether a MACF subsystem is configured
153 * at all in the system.
154 */
155extern unsigned int mac_device_enforce;
156extern unsigned int mac_pipe_enforce;
157extern unsigned int mac_posixsem_enforce;
158extern unsigned int mac_posixshm_enforce;
159extern unsigned int mac_proc_enforce;
160extern unsigned int mac_socket_enforce;
161extern unsigned int mac_system_enforce;
162extern unsigned int mac_sysvmsg_enforce;
163extern unsigned int mac_sysvsem_enforce;
164extern unsigned int mac_sysvshm_enforce;
165extern unsigned int mac_vm_enforce;
166extern unsigned int mac_vnode_enforce;
167
168#if CONFIG_MACF_NET
169extern unsigned int mac_label_mbufs;
170#endif
171
172extern unsigned int mac_label_vnodes;
173
174static int mac_proc_check_enforce(proc_t p, int enforce_flags);
175
176static __inline__ int mac_proc_check_enforce(proc_t p, int enforce_flags)
177{
178#if CONFIG_MACF
179	return ((p->p_mac_enforce & enforce_flags) != 0);
180#else
181#pragma unused(p,enforce_flags)
182	return 0;
183#endif
184}
185
186static int mac_context_check_enforce(vfs_context_t ctx, int enforce_flags);
187static void mac_context_set_enforce(vfs_context_t ctx, int enforce_flags);
188
189static __inline__ int mac_context_check_enforce(vfs_context_t ctx, int enforce_flags)
190{
191	proc_t proc = vfs_context_proc(ctx);
192
193	if (proc == NULL)
194		return 0;
195
196	return (mac_proc_check_enforce(proc, enforce_flags));
197}
198
199static __inline__ void mac_context_set_enforce(vfs_context_t ctx, int enforce_flags)
200{
201#if CONFIG_MACF
202	proc_t proc = vfs_context_proc(ctx);
203
204	if (proc == NULL)
205		return;
206
207	mac_proc_set_enforce(proc, enforce_flags);
208#else
209#pragma unused(ctx,enforce_flags)
210#endif
211}
212
213
214/*
215 * MAC Framework infrastructure functions.
216 */
217
218int mac_error_select(int error1, int error2);
219
220void  mac_policy_list_busy(void);
221int   mac_policy_list_conditional_busy(void);
222void  mac_policy_list_unbusy(void);
223
224void           mac_labelzone_init(void);
225struct label  *mac_labelzone_alloc(int flags);
226void           mac_labelzone_free(struct label *label);
227
228void  mac_label_init(struct label *label);
229void  mac_label_destroy(struct label *label);
230#if KERNEL
231int   mac_check_structmac_consistent(struct user_mac *mac);
232#else
233int   mac_check_structmac_consistent(struct mac *mac);
234#endif
235
236int mac_cred_label_externalize(struct label *, char *e, char *out, size_t olen, int flags);
237int mac_lctx_label_externalize(struct label *, char *e, char *out, size_t olen);
238#if CONFIG_MACF_SOCKET
239int mac_socket_label_externalize(struct label *, char *e, char *out, size_t olen);
240#endif /* CONFIG_MACF_SOCKET */
241int mac_vnode_label_externalize(struct label *, char *e, char *out, size_t olen, int flags);
242int mac_pipe_label_externalize(struct label *label, char *elements,
243 char *outbuf, size_t outbuflen);
244
245int mac_cred_label_internalize(struct label *label, char *string);
246int mac_lctx_label_internalize(struct label *label, char *string);
247#if CONFIG_MACF_SOCKET
248int mac_socket_label_internalize(struct label *label, char *string);
249#endif /* CONFIG_MACF_SOCKET */
250int mac_vnode_label_internalize(struct label *label, char *string);
251int mac_pipe_label_internalize(struct label *label, char *string);
252
253#if CONFIG_MACF_SOCKET
254/* internal socket label manipulation functions */
255struct  label *mac_socket_label_alloc(int flags);
256void    mac_socket_label_free(struct label *l);
257int     mac_socket_label_update(struct ucred *cred, struct socket *so, struct label *l);
258#endif /* MAC_SOCKET */
259
260#if CONFIG_MACF_NET
261struct label *mac_mbuf_to_label(struct mbuf *m);
262#else
263#define mac_mbuf_to_label(m) (NULL)
264#endif
265
266/*
267 * MAC_CHECK performs the designated check by walking the policy
268 * module list and checking with each as to how it feels about the
269 * request.  Note that it returns its value via 'error' in the scope
270 * of the caller.
271 */
272#define	MAC_CHECK(check, args...) do {					\
273	struct mac_policy_conf *mpc;					\
274	u_int i;                                               		\
275									\
276	error = 0;							\
277	for (i = 0; i < mac_policy_list.staticmax; i++) {		\
278		mpc = mac_policy_list.entries[i].mpc;              	\
279		if (mpc == NULL)                                	\
280			continue;                               	\
281									\
282		if (mpc->mpc_ops->mpo_ ## check != NULL)		\
283			error = mac_error_select(      			\
284			    mpc->mpc_ops->mpo_ ## check (args),		\
285			    error);					\
286	}								\
287	if (mac_policy_list_conditional_busy() != 0) {			\
288		for (; i <= mac_policy_list.maxindex; i++) {		\
289			mpc = mac_policy_list.entries[i].mpc;		\
290			if (mpc == NULL)                                \
291				continue;                               \
292                                                                        \
293			if (mpc->mpc_ops->mpo_ ## check != NULL)	\
294				error = mac_error_select(      		\
295				    mpc->mpc_ops->mpo_ ## check (args),	\
296				    error);				\
297		}							\
298		mac_policy_list_unbusy();				\
299	}								\
300} while (0)
301
302/*
303 * MAC_GRANT performs the designated check by walking the policy
304 * module list and checking with each as to how it feels about the
305 * request.  Unlike MAC_CHECK, it grants if any policies return '0',
306 * and otherwise returns EPERM.  Note that it returns its value via
307 * 'error' in the scope of the caller.
308 */
309#define MAC_GRANT(check, args...) do {					\
310	struct mac_policy_conf *mpc;					\
311	u_int i;							\
312									\
313	error = EPERM;							\
314	for (i = 0; i < mac_policy_list.staticmax; i++) {		\
315		mpc = mac_policy_list.entries[i].mpc;			\
316		if (mpc == NULL)					\
317			continue;					\
318									\
319		if (mpc->mpc_ops->mpo_ ## check != NULL) {		\
320			if (mpc->mpc_ops->mpo_ ## check (args) == 0)	\
321				error = 0;				\
322		}							\
323	}								\
324	if (mac_policy_list_conditional_busy() != 0) {			\
325		for (; i <= mac_policy_list.maxindex; i++) {		\
326			mpc = mac_policy_list.entries[i].mpc;		\
327			if (mpc == NULL)				\
328				continue;				\
329									\
330			if (mpc->mpc_ops->mpo_ ## check != NULL) {	\
331				if (mpc->mpc_ops->mpo_ ## check (args)	\
332				    == 0)				\
333					error = 0;			\
334			}						\
335		}							\
336		mac_policy_list_unbusy();				\
337	}								\
338} while (0)
339
340/*
341 * MAC_BOOLEAN performs the designated boolean composition by walking
342 * the module list, invoking each instance of the operation, and
343 * combining the results using the passed C operator.  Note that it
344 * returns its value via 'result' in the scope of the caller, which
345 * should be initialized by the caller in a meaningful way to get
346 * a meaningful result.
347 */
348#define	MAC_BOOLEAN(operation, composition, args...) do {		\
349	struct mac_policy_conf *mpc;					\
350	u_int i;							\
351									\
352	for (i = 0; i < mac_policy_list.staticmax; i++) {		\
353		mpc = mac_policy_list.entries[i].mpc;			\
354		if (mpc == NULL)                                	\
355			continue;                               	\
356									\
357		if (mpc->mpc_ops->mpo_ ## operation != NULL)		\
358			result = result composition			\
359			    mpc->mpc_ops->mpo_ ## operation		\
360			    (args);					\
361	}								\
362	if (mac_policy_list_conditional_busy() != 0) {			\
363		for (; i <= mac_policy_list.maxindex; i++) {		\
364			mpc = mac_policy_list.entries[i].mpc;		\
365			if (mpc == NULL)                                \
366				continue;                               \
367                                                                        \
368			if (mpc->mpc_ops->mpo_ ## operation != NULL)	\
369				result = result composition		\
370				    mpc->mpc_ops->mpo_ ## operation	\
371				    (args);				\
372		}							\
373		mac_policy_list_unbusy();				\
374	}								\
375} while (0)
376
377#define	MAC_INTERNALIZE(obj, label, instring)				\
378	mac_internalize(offsetof(struct mac_policy_ops, mpo_ ## obj ## _label_internalize), label, instring)
379
380#define MAC_EXTERNALIZE(obj, label, elementlist, outbuf, outbuflen)	\
381	mac_externalize(offsetof(struct mac_policy_ops, mpo_ ## obj ## _label_externalize), label, elementlist, outbuf, outbuflen)
382
383#define MAC_EXTERNALIZE_AUDIT(obj, label, outbuf, outbuflen)	\
384	mac_externalize(offsetof(struct mac_policy_ops, mpo_ ## obj ## _label_externalize_audit), label, "*", outbuf, outbuflen)
385
386/*
387 * MAC_PERFORM performs the designated operation by walking the policy
388 * module list and invoking that operation for each policy.
389 */
390#define	MAC_PERFORM(operation, args...) do {				\
391	struct mac_policy_conf *mpc;					\
392	u_int i;							\
393									\
394	for (i = 0; i < mac_policy_list.staticmax; i++) {		\
395		mpc = mac_policy_list.entries[i].mpc;			\
396		if (mpc == NULL)					\
397			continue;					\
398									\
399		if (mpc->mpc_ops->mpo_ ## operation != NULL)		\
400			mpc->mpc_ops->mpo_ ## operation (args);		\
401	}								\
402	if (mac_policy_list_conditional_busy() != 0) {			\
403		for (; i <= mac_policy_list.maxindex; i++) {		\
404			mpc = mac_policy_list.entries[i].mpc;		\
405			if (mpc == NULL)				\
406				continue;				\
407									\
408			if (mpc->mpc_ops->mpo_ ## operation != NULL)	\
409				mpc->mpc_ops->mpo_ ## operation (args);	\
410		}							\
411		mac_policy_list_unbusy();				\
412	}								\
413} while (0)
414
415struct __mac_get_pid_args;
416struct __mac_get_proc_args;
417struct __mac_set_proc_args;
418struct __mac_get_lcid_args;
419struct __mac_get_lctx_args;
420struct __mac_set_lctx_args;
421struct __mac_get_fd_args;
422struct __mac_get_file_args;
423struct __mac_get_link_args;
424struct __mac_set_fd_args;
425struct __mac_set_file_args;
426struct __mac_syscall_args;
427
428void mac_policy_addto_labellist(const mac_policy_handle_t, int);
429void mac_policy_removefrom_labellist(const mac_policy_handle_t);
430
431int mac_externalize(size_t mpo_externalize_off, struct label *label,
432    const char *elementlist, char *outbuf, size_t outbuflen);
433int mac_internalize(size_t mpo_internalize_off, struct label *label,
434    char *elementlist);
435#endif	/* !_SECURITY_MAC_INTERNAL_H_ */
436