/ duct-tape / xnu / security / mac_internal.h
mac_internal.h
  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/locks.h>
 83  #include <sys/kernel.h>
 84  #include <sys/lock.h>
 85  #include <sys/malloc.h>
 86  #include <sys/sbuf.h>
 87  #include <sys/proc.h>
 88  #include <sys/systm.h>
 89  #include <sys/socket.h>
 90  #include <sys/socketvar.h>
 91  #include <sys/vnode.h>
 92  
 93  /*
 94   * MAC Framework sysctl namespace.
 95   */
 96  
 97  SYSCTL_DECL(_security);
 98  SYSCTL_DECL(_security_mac);
 99  
100  extern int mac_late;
101  
102  struct mac_policy_list_element {
103  	struct mac_policy_conf *mpc;
104  };
105  
106  struct mac_policy_list {
107  	u_int                           numloaded;
108  	u_int                           max;
109  	u_int                           maxindex;
110  	u_int                           staticmax;
111  	u_int                           chunks;
112  	u_int                           freehint;
113  	struct mac_policy_list_element  *entries;
114  };
115  
116  typedef struct mac_policy_list mac_policy_list_t;
117  
118  
119  /*
120   * Policy that has registered with the framework for a specific
121   * label namespace name.
122   */
123  struct mac_label_listener {
124  	mac_policy_handle_t             mll_handle;
125  	LIST_ENTRY(mac_label_listener)  mll_list;
126  };
127  
128  LIST_HEAD(mac_label_listeners_t, mac_label_listener);
129  
130  /*
131   * Type of list used to manage label namespace names.
132   */
133  struct mac_label_element {
134  	char                            mle_name[MAC_MAX_LABEL_ELEMENT_NAME];
135  	struct mac_label_listeners_t    mle_listeners;
136  	LIST_ENTRY(mac_label_element)   mle_list;
137  };
138  
139  LIST_HEAD(mac_label_element_list_t, mac_label_element);
140  
141  /*
142   * MAC Framework global variables.
143   */
144  
145  extern struct mac_label_element_list_t mac_label_element_list;
146  extern struct mac_label_element_list_t mac_static_label_element_list;
147  
148  extern struct mac_policy_list mac_policy_list;
149  
150  /*
151   * global flags to control whether a MACF subsystem is configured
152   * at all in the system.
153   */
154  extern unsigned int mac_device_enforce;
155  extern unsigned int mac_pipe_enforce;
156  extern unsigned int mac_posixsem_enforce;
157  extern unsigned int mac_posixshm_enforce;
158  extern unsigned int mac_proc_enforce;
159  extern unsigned int mac_socket_enforce;
160  extern unsigned int mac_system_enforce;
161  extern unsigned int mac_sysvmsg_enforce;
162  extern unsigned int mac_sysvsem_enforce;
163  extern unsigned int mac_sysvshm_enforce;
164  extern unsigned int mac_vm_enforce;
165  extern unsigned int mac_vnode_enforce;
166  
167  extern unsigned int mac_label_vnodes;
168  extern unsigned int mac_vnode_label_count;
169  
170  static bool mac_proc_check_enforce(proc_t p);
171  
172  static __inline__ bool
173  mac_proc_check_enforce(proc_t p)
174  {
175  #if CONFIG_MACF
176  	// Don't apply policies to the kernel itself.
177  	return p != kernproc;
178  #else
179  #pragma unused(p)
180  	return false;
181  #endif // CONFIG_MACF
182  }
183  
184  static bool mac_cred_check_enforce(kauth_cred_t cred);
185  
186  static __inline__ bool
187  mac_cred_check_enforce(kauth_cred_t cred)
188  {
189  #if CONFIG_MACF
190  	return cred != proc_ucred(kernproc);
191  #else
192  #pragma unused(p)
193  	return false;
194  #endif // CONFIG_MACF
195  }
196  
197  /*
198   * MAC Framework infrastructure functions.
199   */
200  
201  int mac_error_select(int error1, int error2);
202  
203  void  mac_policy_list_busy(void);
204  int   mac_policy_list_conditional_busy(void);
205  void  mac_policy_list_unbusy(void);
206  
207  void           mac_labelzone_init(void);
208  struct label  *mac_labelzone_alloc(int flags);
209  void           mac_labelzone_free(struct label *label);
210  
211  void  mac_label_init(struct label *label);
212  void  mac_label_destroy(struct label *label);
213  #if KERNEL
214  int   mac_check_structmac_consistent(struct user_mac *mac);
215  #else
216  int   mac_check_structmac_consistent(struct mac *mac);
217  #endif
218  
219  int mac_cred_label_externalize(struct label *, char *e, char *out, size_t olen, int flags);
220  int mac_vnode_label_externalize(struct label *, char *e, char *out, size_t olen, int flags);
221  
222  int mac_cred_label_internalize(struct label *label, char *string);
223  int mac_vnode_label_internalize(struct label *label, char *string);
224  
225  /*
226   * MAC_CHECK performs the designated check by walking the policy
227   * module list and checking with each as to how it feels about the
228   * request.  Note that it returns its value via 'error' in the scope
229   * of the caller.
230   */
231  #define MAC_CHECK(check, args...) do {                                  \
232  	struct mac_policy_conf *mpc;                                    \
233  	u_int i;                                                        \
234                                                                          \
235  	error = 0;                                                      \
236  	for (i = 0; i < mac_policy_list.staticmax; i++) {               \
237  	        mpc = mac_policy_list.entries[i].mpc;                   \
238  	        if (mpc == NULL)                                        \
239  	                continue;                                       \
240                                                                          \
241  	        if (mpc->mpc_ops->mpo_ ## check != NULL)                \
242  	                error = mac_error_select(                       \
243  	                    mpc->mpc_ops->mpo_ ## check (args),         \
244  	                    error);                                     \
245  	}                                                               \
246  	if (mac_policy_list_conditional_busy() != 0) {                  \
247  	        for (; i <= mac_policy_list.maxindex; i++) {            \
248  	                mpc = mac_policy_list.entries[i].mpc;           \
249  	                if (mpc == NULL)                                \
250  	                        continue;                               \
251                                                                          \
252  	                if (mpc->mpc_ops->mpo_ ## check != NULL)        \
253  	                        error = mac_error_select(               \
254  	                            mpc->mpc_ops->mpo_ ## check (args), \
255  	                            error);                             \
256  	        }                                                       \
257  	        mac_policy_list_unbusy();                               \
258  	}                                                               \
259  } while (0)
260  
261  /*
262   * MAC_GRANT performs the designated check by walking the policy
263   * module list and checking with each as to how it feels about the
264   * request.  Unlike MAC_CHECK, it grants if any policies return '0',
265   * and otherwise returns EPERM.  Note that it returns its value via
266   * 'error' in the scope of the caller.
267   */
268  #define MAC_GRANT(check, args...) do {                                  \
269  	struct mac_policy_conf *mpc;                                    \
270  	u_int i;                                                        \
271                                                                          \
272  	error = EPERM;                                                  \
273  	for (i = 0; i < mac_policy_list.staticmax; i++) {               \
274  	        mpc = mac_policy_list.entries[i].mpc;                   \
275  	        if (mpc == NULL)                                        \
276  	                continue;                                       \
277                                                                          \
278  	        if (mpc->mpc_ops->mpo_ ## check != NULL) {              \
279  	                if (mpc->mpc_ops->mpo_ ## check (args) == 0)    \
280  	                        error = 0;                              \
281  	        }                                                       \
282  	}                                                               \
283  	if (mac_policy_list_conditional_busy() != 0) {                  \
284  	        for (; i <= mac_policy_list.maxindex; i++) {            \
285  	                mpc = mac_policy_list.entries[i].mpc;           \
286  	                if (mpc == NULL)                                \
287  	                        continue;                               \
288                                                                          \
289  	                if (mpc->mpc_ops->mpo_ ## check != NULL) {      \
290  	                        if (mpc->mpc_ops->mpo_ ## check (args)  \
291  	                            == 0)                               \
292  	                                error = 0;                      \
293  	                }                                               \
294  	        }                                                       \
295  	        mac_policy_list_unbusy();                               \
296  	}                                                               \
297  } while (0)
298  
299  /*
300   * MAC_BOOLEAN performs the designated boolean composition by walking
301   * the module list, invoking each instance of the operation, and
302   * combining the results using the passed C operator.  Note that it
303   * returns its value via 'result' in the scope of the caller, which
304   * should be initialized by the caller in a meaningful way to get
305   * a meaningful result.
306   */
307  #define MAC_BOOLEAN(operation, composition, args...) do {               \
308  	struct mac_policy_conf *mpc;                                    \
309  	u_int i;                                                        \
310                                                                          \
311  	for (i = 0; i < mac_policy_list.staticmax; i++) {               \
312  	        mpc = mac_policy_list.entries[i].mpc;                   \
313  	        if (mpc == NULL)                                        \
314  	                continue;                                       \
315                                                                          \
316  	        if (mpc->mpc_ops->mpo_ ## operation != NULL)            \
317  	                result = result composition                     \
318  	                    mpc->mpc_ops->mpo_ ## operation             \
319  	                    (args);                                     \
320  	}                                                               \
321  	if (mac_policy_list_conditional_busy() != 0) {                  \
322  	        for (; i <= mac_policy_list.maxindex; i++) {            \
323  	                mpc = mac_policy_list.entries[i].mpc;           \
324  	                if (mpc == NULL)                                \
325  	                        continue;                               \
326                                                                          \
327  	                if (mpc->mpc_ops->mpo_ ## operation != NULL)    \
328  	                        result = result composition             \
329  	                            mpc->mpc_ops->mpo_ ## operation     \
330  	                            (args);                             \
331  	        }                                                       \
332  	        mac_policy_list_unbusy();                               \
333  	}                                                               \
334  } while (0)
335  
336  #define MAC_INTERNALIZE(obj, label, instring)                           \
337  	mac_internalize(offsetof(struct mac_policy_ops, mpo_ ## obj ## _label_internalize), label, instring)
338  
339  #define MAC_EXTERNALIZE(obj, label, elementlist, outbuf, outbuflen)     \
340  	mac_externalize(offsetof(struct mac_policy_ops, mpo_ ## obj ## _label_externalize), label, elementlist, outbuf, outbuflen)
341  
342  #define MAC_EXTERNALIZE_AUDIT(obj, label, outbuf, outbuflen)    \
343  	mac_externalize(offsetof(struct mac_policy_ops, mpo_ ## obj ## _label_externalize_audit), label, "*", outbuf, outbuflen)
344  
345  /*
346   * MAC_PERFORM performs the designated operation by walking the policy
347   * module list and invoking that operation for each policy.
348   */
349  #define MAC_PERFORM(operation, args...) do {                            \
350  	struct mac_policy_conf *mpc;                                    \
351  	u_int i;                                                        \
352                                                                          \
353  	for (i = 0; i < mac_policy_list.staticmax; i++) {               \
354  	        mpc = mac_policy_list.entries[i].mpc;                   \
355  	        if (mpc == NULL)                                        \
356  	                continue;                                       \
357                                                                          \
358  	        if (mpc->mpc_ops->mpo_ ## operation != NULL)            \
359  	                mpc->mpc_ops->mpo_ ## operation (args);         \
360  	}                                                               \
361  	if (mac_policy_list_conditional_busy() != 0) {                  \
362  	        for (; i <= mac_policy_list.maxindex; i++) {            \
363  	                mpc = mac_policy_list.entries[i].mpc;           \
364  	                if (mpc == NULL)                                \
365  	                        continue;                               \
366                                                                          \
367  	                if (mpc->mpc_ops->mpo_ ## operation != NULL)    \
368  	                        mpc->mpc_ops->mpo_ ## operation (args); \
369  	        }                                                       \
370  	        mac_policy_list_unbusy();                               \
371  	}                                                               \
372  } while (0)
373  
374  struct __mac_get_pid_args;
375  struct __mac_get_proc_args;
376  struct __mac_set_proc_args;
377  struct __mac_get_lcid_args;
378  struct __mac_get_fd_args;
379  struct __mac_get_file_args;
380  struct __mac_get_link_args;
381  struct __mac_set_fd_args;
382  struct __mac_set_file_args;
383  struct __mac_syscall_args;
384  
385  void mac_policy_addto_labellist(const mac_policy_handle_t, int);
386  void mac_policy_removefrom_labellist(const mac_policy_handle_t);
387  
388  int mac_externalize(size_t mpo_externalize_off, struct label *label,
389      const char *elementlist, char *outbuf, size_t outbuflen);
390  int mac_internalize(size_t mpo_internalize_off, struct label *label,
391      char *elementlist);
392  #endif  /* !_SECURITY_MAC_INTERNAL_H_ */