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_ */