1/*- 2 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson 3 * Copyright (c) 2001 Ilmar S. Habibulin 4 * Copyright (c) 2001, 2002, 2003 Networks Associates Technology, Inc. 5 * All rights reserved. 6 * 7 * This software was developed by Robert Watson and Ilmar Habibulin for the 8 * TrustedBSD Project. 9 * 10 * This software was developed for the FreeBSD Project in part by Network 11 * Associates Laboratories, the Security Research Division of Network 12 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 13 * as part of the DARPA CHATS research program. 14 * 15 * Redistribution and use in source and binary forms, with or without 16 * modification, are permitted provided that the following conditions 17 * are met: 18 * 1. Redistributions of source code must retain the above copyright 19 * notice, this list of conditions and the following disclaimer. 20 * 2. Redistributions in binary form must reproduce the above copyright 21 * notice, this list of conditions and the following disclaimer in the 22 * documentation and/or other materials provided with the distribution. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37/*- 38 * Framework for extensible kernel access control. This file contains 39 * Kernel and userland interface to the framework, policy registration 40 * and composition. Per-object interfaces, controls, and labeling may be 41 * found in src/sys/mac/. Sample policies may be found in src/sys/mac*. 42 */ 43 44#include <sys/cdefs.h>
| 1/*- 2 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson 3 * Copyright (c) 2001 Ilmar S. Habibulin 4 * Copyright (c) 2001, 2002, 2003 Networks Associates Technology, Inc. 5 * All rights reserved. 6 * 7 * This software was developed by Robert Watson and Ilmar Habibulin for the 8 * TrustedBSD Project. 9 * 10 * This software was developed for the FreeBSD Project in part by Network 11 * Associates Laboratories, the Security Research Division of Network 12 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 13 * as part of the DARPA CHATS research program. 14 * 15 * Redistribution and use in source and binary forms, with or without 16 * modification, are permitted provided that the following conditions 17 * are met: 18 * 1. Redistributions of source code must retain the above copyright 19 * notice, this list of conditions and the following disclaimer. 20 * 2. Redistributions in binary form must reproduce the above copyright 21 * notice, this list of conditions and the following disclaimer in the 22 * documentation and/or other materials provided with the distribution. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37/*- 38 * Framework for extensible kernel access control. This file contains 39 * Kernel and userland interface to the framework, policy registration 40 * and composition. Per-object interfaces, controls, and labeling may be 41 * found in src/sys/mac/. Sample policies may be found in src/sys/mac*. 42 */ 43 44#include <sys/cdefs.h>
|
45__FBSDID("$FreeBSD: head/sys/security/mac/mac_framework.c 122454 2003-11-11 03:40:04Z rwatson $");
| 45__FBSDID("$FreeBSD: head/sys/security/mac/mac_framework.c 122524 2003-11-12 03:14:31Z rwatson $");
|
46 47#include "opt_mac.h" 48#include "opt_devfs.h" 49 50#include <sys/param.h> 51#include <sys/condvar.h> 52#include <sys/extattr.h> 53#include <sys/imgact.h> 54#include <sys/kernel.h> 55#include <sys/lock.h> 56#include <sys/malloc.h> 57#include <sys/mutex.h> 58#include <sys/mac.h> 59#include <sys/module.h> 60#include <sys/proc.h> 61#include <sys/sbuf.h> 62#include <sys/systm.h> 63#include <sys/sysproto.h> 64#include <sys/sysent.h> 65#include <sys/vnode.h> 66#include <sys/mount.h> 67#include <sys/file.h> 68#include <sys/namei.h> 69#include <sys/socket.h> 70#include <sys/pipe.h> 71#include <sys/socketvar.h> 72#include <sys/sysctl.h> 73 74#include <vm/vm.h> 75#include <vm/pmap.h> 76#include <vm/vm_map.h> 77#include <vm/vm_object.h> 78 79#include <sys/mac_policy.h> 80 81#include <fs/devfs/devfs.h> 82 83#include <net/bpfdesc.h> 84#include <net/if.h> 85#include <net/if_var.h> 86 87#include <netinet/in.h> 88#include <netinet/ip_var.h> 89 90#include <security/mac/mac_internal.h> 91 92#ifdef MAC 93 94/* 95 * Declare that the kernel provides MAC support, version 1. This permits 96 * modules to refuse to be loaded if the necessary support isn't present, 97 * even if it's pre-boot. 98 */ 99MODULE_VERSION(kernel_mac_support, 1); 100 101SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0, 102 "TrustedBSD MAC policy controls"); 103 104#if MAC_MAX_SLOTS > 32 105#error "MAC_MAX_SLOTS too large" 106#endif 107 108static unsigned int mac_max_slots = MAC_MAX_SLOTS; 109static unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1; 110SYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD, 111 &mac_max_slots, 0, ""); 112 113/* 114 * Has the kernel started generating labeled objects yet? All read/write 115 * access to this variable is serialized during the boot process. Following 116 * the end of serialization, we don't update this flag; no locking. 117 */ 118int mac_late = 0; 119 120/* 121 * Flag to indicate whether or not we should allocate label storage for 122 * new mbufs. Since most dynamic policies we currently work with don't 123 * rely on mbuf labeling, try to avoid paying the cost of mtag allocation 124 * unless specifically notified of interest. One result of this is 125 * that if a dynamically loaded policy requests mbuf labels, it must 126 * be able to deal with a NULL label being returned on any mbufs that 127 * were already in flight when the policy was loaded. Since the policy 128 * already has to deal with uninitialized labels, this probably won't 129 * be a problem. Note: currently no locking. Will this be a problem? 130 */ 131#ifndef MAC_ALWAYS_LABEL_MBUF 132int mac_labelmbufs = 0; 133#endif 134 135#ifdef MAC_DEBUG 136SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0, 137 "TrustedBSD MAC debug info"); 138SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0, 139 "TrustedBSD MAC object counters"); 140 141static unsigned int nmactemp; 142SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD, 143 &nmactemp, 0, "number of temporary labels in use"); 144#endif 145 146static int mac_policy_register(struct mac_policy_conf *mpc); 147static int mac_policy_unregister(struct mac_policy_conf *mpc); 148 149MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); 150 151/* 152 * mac_static_policy_list holds a list of policy modules that are not 153 * loaded while the system is "live", and cannot be unloaded. These 154 * policies can be invoked without holding the busy count. 155 * 156 * mac_policy_list stores the list of dynamic policies. A busy count is 157 * maintained for the list, stored in mac_policy_busy. The busy count 158 * is protected by mac_policy_mtx; the list may be modified only 159 * while the busy count is 0, requiring that the lock be held to 160 * prevent new references to the list from being acquired. For almost 161 * all operations, incrementing the busy count is sufficient to 162 * guarantee consistency, as the list cannot be modified while the 163 * busy count is elevated. For a few special operations involving a 164 * change to the list of active policies, the mtx itself must be held. 165 * A condition variable, mac_policy_cv, is used to signal potential 166 * exclusive consumers that they should try to acquire the lock if a 167 * first attempt at exclusive access fails. 168 */ 169static struct mtx mac_policy_mtx; 170static struct cv mac_policy_cv; 171static int mac_policy_count; 172struct mac_policy_list_head mac_policy_list; 173struct mac_policy_list_head mac_static_policy_list; 174 175/* 176 * We manually invoke WITNESS_WARN() to allow Witness to generate 177 * warnings even if we don't end up ever triggering the wait at 178 * run-time. The consumer of the exclusive interface must not hold 179 * any locks (other than potentially Giant) since we may sleep for 180 * long (potentially indefinite) periods of time waiting for the 181 * framework to become quiescent so that a policy list change may 182 * be made. 183 */ 184void 185mac_policy_grab_exclusive(void) 186{ 187 188 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 189 "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__); 190 mtx_lock(&mac_policy_mtx); 191 while (mac_policy_count != 0) 192 cv_wait(&mac_policy_cv, &mac_policy_mtx); 193} 194 195void 196mac_policy_assert_exclusive(void) 197{ 198 199 mtx_assert(&mac_policy_mtx, MA_OWNED); 200 KASSERT(mac_policy_count == 0, 201 ("mac_policy_assert_exclusive(): not exclusive")); 202} 203 204void 205mac_policy_release_exclusive(void) 206{ 207 208 KASSERT(mac_policy_count == 0, 209 ("mac_policy_release_exclusive(): not exclusive")); 210 mtx_unlock(&mac_policy_mtx); 211 cv_signal(&mac_policy_cv); 212} 213 214void 215mac_policy_list_busy(void) 216{ 217 218 mtx_lock(&mac_policy_mtx); 219 mac_policy_count++; 220 mtx_unlock(&mac_policy_mtx); 221} 222 223int 224mac_policy_list_conditional_busy(void) 225{ 226 int ret; 227 228 mtx_lock(&mac_policy_mtx); 229 if (!LIST_EMPTY(&mac_policy_list)) { 230 mac_policy_count++; 231 ret = 1; 232 } else 233 ret = 0; 234 mtx_unlock(&mac_policy_mtx); 235 return (ret); 236} 237 238void 239mac_policy_list_unbusy(void) 240{ 241 242 mtx_lock(&mac_policy_mtx); 243 mac_policy_count--; 244 KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK")); 245 if (mac_policy_count == 0) 246 cv_signal(&mac_policy_cv); 247 mtx_unlock(&mac_policy_mtx); 248} 249 250/* 251 * Initialize the MAC subsystem, including appropriate SMP locks. 252 */ 253static void 254mac_init(void) 255{ 256 257 LIST_INIT(&mac_static_policy_list); 258 LIST_INIT(&mac_policy_list);
| 46 47#include "opt_mac.h" 48#include "opt_devfs.h" 49 50#include <sys/param.h> 51#include <sys/condvar.h> 52#include <sys/extattr.h> 53#include <sys/imgact.h> 54#include <sys/kernel.h> 55#include <sys/lock.h> 56#include <sys/malloc.h> 57#include <sys/mutex.h> 58#include <sys/mac.h> 59#include <sys/module.h> 60#include <sys/proc.h> 61#include <sys/sbuf.h> 62#include <sys/systm.h> 63#include <sys/sysproto.h> 64#include <sys/sysent.h> 65#include <sys/vnode.h> 66#include <sys/mount.h> 67#include <sys/file.h> 68#include <sys/namei.h> 69#include <sys/socket.h> 70#include <sys/pipe.h> 71#include <sys/socketvar.h> 72#include <sys/sysctl.h> 73 74#include <vm/vm.h> 75#include <vm/pmap.h> 76#include <vm/vm_map.h> 77#include <vm/vm_object.h> 78 79#include <sys/mac_policy.h> 80 81#include <fs/devfs/devfs.h> 82 83#include <net/bpfdesc.h> 84#include <net/if.h> 85#include <net/if_var.h> 86 87#include <netinet/in.h> 88#include <netinet/ip_var.h> 89 90#include <security/mac/mac_internal.h> 91 92#ifdef MAC 93 94/* 95 * Declare that the kernel provides MAC support, version 1. This permits 96 * modules to refuse to be loaded if the necessary support isn't present, 97 * even if it's pre-boot. 98 */ 99MODULE_VERSION(kernel_mac_support, 1); 100 101SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0, 102 "TrustedBSD MAC policy controls"); 103 104#if MAC_MAX_SLOTS > 32 105#error "MAC_MAX_SLOTS too large" 106#endif 107 108static unsigned int mac_max_slots = MAC_MAX_SLOTS; 109static unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1; 110SYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD, 111 &mac_max_slots, 0, ""); 112 113/* 114 * Has the kernel started generating labeled objects yet? All read/write 115 * access to this variable is serialized during the boot process. Following 116 * the end of serialization, we don't update this flag; no locking. 117 */ 118int mac_late = 0; 119 120/* 121 * Flag to indicate whether or not we should allocate label storage for 122 * new mbufs. Since most dynamic policies we currently work with don't 123 * rely on mbuf labeling, try to avoid paying the cost of mtag allocation 124 * unless specifically notified of interest. One result of this is 125 * that if a dynamically loaded policy requests mbuf labels, it must 126 * be able to deal with a NULL label being returned on any mbufs that 127 * were already in flight when the policy was loaded. Since the policy 128 * already has to deal with uninitialized labels, this probably won't 129 * be a problem. Note: currently no locking. Will this be a problem? 130 */ 131#ifndef MAC_ALWAYS_LABEL_MBUF 132int mac_labelmbufs = 0; 133#endif 134 135#ifdef MAC_DEBUG 136SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0, 137 "TrustedBSD MAC debug info"); 138SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0, 139 "TrustedBSD MAC object counters"); 140 141static unsigned int nmactemp; 142SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD, 143 &nmactemp, 0, "number of temporary labels in use"); 144#endif 145 146static int mac_policy_register(struct mac_policy_conf *mpc); 147static int mac_policy_unregister(struct mac_policy_conf *mpc); 148 149MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); 150 151/* 152 * mac_static_policy_list holds a list of policy modules that are not 153 * loaded while the system is "live", and cannot be unloaded. These 154 * policies can be invoked without holding the busy count. 155 * 156 * mac_policy_list stores the list of dynamic policies. A busy count is 157 * maintained for the list, stored in mac_policy_busy. The busy count 158 * is protected by mac_policy_mtx; the list may be modified only 159 * while the busy count is 0, requiring that the lock be held to 160 * prevent new references to the list from being acquired. For almost 161 * all operations, incrementing the busy count is sufficient to 162 * guarantee consistency, as the list cannot be modified while the 163 * busy count is elevated. For a few special operations involving a 164 * change to the list of active policies, the mtx itself must be held. 165 * A condition variable, mac_policy_cv, is used to signal potential 166 * exclusive consumers that they should try to acquire the lock if a 167 * first attempt at exclusive access fails. 168 */ 169static struct mtx mac_policy_mtx; 170static struct cv mac_policy_cv; 171static int mac_policy_count; 172struct mac_policy_list_head mac_policy_list; 173struct mac_policy_list_head mac_static_policy_list; 174 175/* 176 * We manually invoke WITNESS_WARN() to allow Witness to generate 177 * warnings even if we don't end up ever triggering the wait at 178 * run-time. The consumer of the exclusive interface must not hold 179 * any locks (other than potentially Giant) since we may sleep for 180 * long (potentially indefinite) periods of time waiting for the 181 * framework to become quiescent so that a policy list change may 182 * be made. 183 */ 184void 185mac_policy_grab_exclusive(void) 186{ 187 188 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 189 "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__); 190 mtx_lock(&mac_policy_mtx); 191 while (mac_policy_count != 0) 192 cv_wait(&mac_policy_cv, &mac_policy_mtx); 193} 194 195void 196mac_policy_assert_exclusive(void) 197{ 198 199 mtx_assert(&mac_policy_mtx, MA_OWNED); 200 KASSERT(mac_policy_count == 0, 201 ("mac_policy_assert_exclusive(): not exclusive")); 202} 203 204void 205mac_policy_release_exclusive(void) 206{ 207 208 KASSERT(mac_policy_count == 0, 209 ("mac_policy_release_exclusive(): not exclusive")); 210 mtx_unlock(&mac_policy_mtx); 211 cv_signal(&mac_policy_cv); 212} 213 214void 215mac_policy_list_busy(void) 216{ 217 218 mtx_lock(&mac_policy_mtx); 219 mac_policy_count++; 220 mtx_unlock(&mac_policy_mtx); 221} 222 223int 224mac_policy_list_conditional_busy(void) 225{ 226 int ret; 227 228 mtx_lock(&mac_policy_mtx); 229 if (!LIST_EMPTY(&mac_policy_list)) { 230 mac_policy_count++; 231 ret = 1; 232 } else 233 ret = 0; 234 mtx_unlock(&mac_policy_mtx); 235 return (ret); 236} 237 238void 239mac_policy_list_unbusy(void) 240{ 241 242 mtx_lock(&mac_policy_mtx); 243 mac_policy_count--; 244 KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK")); 245 if (mac_policy_count == 0) 246 cv_signal(&mac_policy_cv); 247 mtx_unlock(&mac_policy_mtx); 248} 249 250/* 251 * Initialize the MAC subsystem, including appropriate SMP locks. 252 */ 253static void 254mac_init(void) 255{ 256 257 LIST_INIT(&mac_static_policy_list); 258 LIST_INIT(&mac_policy_list);
|
| 259 mac_labelzone_init();
|
259 260 mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF); 261 cv_init(&mac_policy_cv, "mac_policy_cv"); 262} 263 264/* 265 * For the purposes of modules that want to know if they were loaded 266 * "early", set the mac_late flag once we've processed modules either 267 * linked into the kernel, or loaded before the kernel startup. 268 */ 269static void 270mac_late_init(void) 271{ 272 273 mac_late = 1; 274} 275 276/* 277 * After the policy list has changed, walk the list to update any global 278 * flags. Currently, we support only one flag, and it's conditionally 279 * defined; as a result, the entire function is conditional. Eventually, 280 * the #else case might also iterate across the policies. 281 */ 282static void 283mac_policy_updateflags(void) 284{ 285#ifndef MAC_ALWAYS_LABEL_MBUF 286 struct mac_policy_conf *tmpc; 287 int labelmbufs; 288 289 mac_policy_assert_exclusive(); 290 291 labelmbufs = 0; 292 LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 293 if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 294 labelmbufs++; 295 } 296 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 297 if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 298 labelmbufs++; 299 } 300 mac_labelmbufs = (labelmbufs != 0); 301#endif 302} 303 304/* 305 * Allow MAC policy modules to register during boot, etc. 306 */ 307int 308mac_policy_modevent(module_t mod, int type, void *data) 309{ 310 struct mac_policy_conf *mpc; 311 int error; 312 313 error = 0; 314 mpc = (struct mac_policy_conf *) data; 315 316 switch (type) { 317 case MOD_LOAD: 318 if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 319 mac_late) { 320 printf("mac_policy_modevent: can't load %s policy " 321 "after booting\n", mpc->mpc_name); 322 error = EBUSY; 323 break; 324 } 325 error = mac_policy_register(mpc); 326 break; 327 case MOD_UNLOAD: 328 /* Don't unregister the module if it was never registered. */ 329 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 330 != 0) 331 error = mac_policy_unregister(mpc); 332 else 333 error = 0; 334 break; 335 default: 336 break; 337 } 338 339 return (error); 340} 341 342static int 343mac_policy_register(struct mac_policy_conf *mpc) 344{ 345 struct mac_policy_conf *tmpc; 346 int error, slot, static_entry; 347 348 error = 0; 349 350 /* 351 * We don't technically need exclusive access while !mac_late, 352 * but hold it for assertion consistency. 353 */ 354 mac_policy_grab_exclusive(); 355 356 /* 357 * If the module can potentially be unloaded, or we're loading 358 * late, we have to stick it in the non-static list and pay 359 * an extra performance overhead. Otherwise, we can pay a 360 * light locking cost and stick it in the static list. 361 */ 362 static_entry = (!mac_late && 363 !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK)); 364 365 if (static_entry) { 366 LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 367 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 368 error = EEXIST; 369 goto out; 370 } 371 } 372 } else { 373 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 374 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 375 error = EEXIST; 376 goto out; 377 } 378 } 379 } 380 if (mpc->mpc_field_off != NULL) { 381 slot = ffs(mac_slot_offsets_free); 382 if (slot == 0) { 383 error = ENOMEM; 384 goto out; 385 } 386 slot--; 387 mac_slot_offsets_free &= ~(1 << slot); 388 *mpc->mpc_field_off = slot; 389 } 390 mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 391 392 /* 393 * If we're loading a MAC module after the framework has 394 * initialized, it has to go into the dynamic list. If 395 * we're loading it before we've finished initializing, 396 * it can go into the static list with weaker locker 397 * requirements. 398 */ 399 if (static_entry) 400 LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list); 401 else 402 LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 403 404 /* Per-policy initialization. */ 405 if (mpc->mpc_ops->mpo_init != NULL) 406 (*(mpc->mpc_ops->mpo_init))(mpc); 407 mac_policy_updateflags(); 408 409 printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 410 mpc->mpc_name); 411 412out: 413 mac_policy_release_exclusive(); 414 return (error); 415} 416 417static int 418mac_policy_unregister(struct mac_policy_conf *mpc) 419{ 420 421 /* 422 * If we fail the load, we may get a request to unload. Check 423 * to see if we did the run-time registration, and if not, 424 * silently succeed. 425 */ 426 mac_policy_grab_exclusive(); 427 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 428 mac_policy_release_exclusive(); 429 return (0); 430 } 431#if 0 432 /* 433 * Don't allow unloading modules with private data. 434 */ 435 if (mpc->mpc_field_off != NULL) { 436 MAC_POLICY_LIST_UNLOCK(); 437 return (EBUSY); 438 } 439#endif 440 /* 441 * Only allow the unload to proceed if the module is unloadable 442 * by its own definition. 443 */ 444 if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 445 mac_policy_release_exclusive(); 446 return (EBUSY); 447 } 448 if (mpc->mpc_ops->mpo_destroy != NULL) 449 (*(mpc->mpc_ops->mpo_destroy))(mpc); 450 451 LIST_REMOVE(mpc, mpc_list); 452 mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 453 mac_policy_updateflags(); 454 455 mac_policy_release_exclusive(); 456 457 printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 458 mpc->mpc_name); 459 460 return (0); 461} 462 463/* 464 * Define an error value precedence, and given two arguments, selects the 465 * value with the higher precedence. 466 */ 467int 468mac_error_select(int error1, int error2) 469{ 470 471 /* Certain decision-making errors take top priority. */ 472 if (error1 == EDEADLK || error2 == EDEADLK) 473 return (EDEADLK); 474 475 /* Invalid arguments should be reported where possible. */ 476 if (error1 == EINVAL || error2 == EINVAL) 477 return (EINVAL); 478 479 /* Precedence goes to "visibility", with both process and file. */ 480 if (error1 == ESRCH || error2 == ESRCH) 481 return (ESRCH); 482 483 if (error1 == ENOENT || error2 == ENOENT) 484 return (ENOENT); 485 486 /* Precedence goes to DAC/MAC protections. */ 487 if (error1 == EACCES || error2 == EACCES) 488 return (EACCES); 489 490 /* Precedence goes to privilege. */ 491 if (error1 == EPERM || error2 == EPERM) 492 return (EPERM); 493 494 /* Precedence goes to error over success; otherwise, arbitrary. */ 495 if (error1 != 0) 496 return (error1); 497 return (error2); 498} 499 500void 501mac_init_label(struct label *label) 502{ 503 504 bzero(label, sizeof(*label)); 505 label->l_flags = MAC_FLAG_INITIALIZED; 506} 507 508void 509mac_destroy_label(struct label *label) 510{ 511 512 KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 513 ("destroying uninitialized label")); 514 515 bzero(label, sizeof(*label)); 516 /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 517} 518 519int 520mac_check_structmac_consistent(struct mac *mac) 521{ 522 523 if (mac->m_buflen < 0 || 524 mac->m_buflen > MAC_MAX_LABEL_BUF_LEN) 525 return (EINVAL); 526 527 return (0); 528} 529 530int 531__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 532{ 533 char *elements, *buffer; 534 struct mac mac; 535 struct proc *tproc; 536 struct ucred *tcred; 537 int error; 538 539 error = copyin(uap->mac_p, &mac, sizeof(mac)); 540 if (error) 541 return (error); 542 543 error = mac_check_structmac_consistent(&mac); 544 if (error) 545 return (error); 546 547 tproc = pfind(uap->pid); 548 if (tproc == NULL) 549 return (ESRCH); 550 551 tcred = NULL; /* Satisfy gcc. */ 552 error = p_cansee(td, tproc); 553 if (error == 0) 554 tcred = crhold(tproc->p_ucred); 555 PROC_UNLOCK(tproc); 556 if (error) 557 return (error); 558 559 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 560 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 561 if (error) { 562 free(elements, M_MACTEMP); 563 crfree(tcred); 564 return (error); 565 } 566 567 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
| 260 261 mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF); 262 cv_init(&mac_policy_cv, "mac_policy_cv"); 263} 264 265/* 266 * For the purposes of modules that want to know if they were loaded 267 * "early", set the mac_late flag once we've processed modules either 268 * linked into the kernel, or loaded before the kernel startup. 269 */ 270static void 271mac_late_init(void) 272{ 273 274 mac_late = 1; 275} 276 277/* 278 * After the policy list has changed, walk the list to update any global 279 * flags. Currently, we support only one flag, and it's conditionally 280 * defined; as a result, the entire function is conditional. Eventually, 281 * the #else case might also iterate across the policies. 282 */ 283static void 284mac_policy_updateflags(void) 285{ 286#ifndef MAC_ALWAYS_LABEL_MBUF 287 struct mac_policy_conf *tmpc; 288 int labelmbufs; 289 290 mac_policy_assert_exclusive(); 291 292 labelmbufs = 0; 293 LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 294 if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 295 labelmbufs++; 296 } 297 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 298 if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS) 299 labelmbufs++; 300 } 301 mac_labelmbufs = (labelmbufs != 0); 302#endif 303} 304 305/* 306 * Allow MAC policy modules to register during boot, etc. 307 */ 308int 309mac_policy_modevent(module_t mod, int type, void *data) 310{ 311 struct mac_policy_conf *mpc; 312 int error; 313 314 error = 0; 315 mpc = (struct mac_policy_conf *) data; 316 317 switch (type) { 318 case MOD_LOAD: 319 if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && 320 mac_late) { 321 printf("mac_policy_modevent: can't load %s policy " 322 "after booting\n", mpc->mpc_name); 323 error = EBUSY; 324 break; 325 } 326 error = mac_policy_register(mpc); 327 break; 328 case MOD_UNLOAD: 329 /* Don't unregister the module if it was never registered. */ 330 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) 331 != 0) 332 error = mac_policy_unregister(mpc); 333 else 334 error = 0; 335 break; 336 default: 337 break; 338 } 339 340 return (error); 341} 342 343static int 344mac_policy_register(struct mac_policy_conf *mpc) 345{ 346 struct mac_policy_conf *tmpc; 347 int error, slot, static_entry; 348 349 error = 0; 350 351 /* 352 * We don't technically need exclusive access while !mac_late, 353 * but hold it for assertion consistency. 354 */ 355 mac_policy_grab_exclusive(); 356 357 /* 358 * If the module can potentially be unloaded, or we're loading 359 * late, we have to stick it in the non-static list and pay 360 * an extra performance overhead. Otherwise, we can pay a 361 * light locking cost and stick it in the static list. 362 */ 363 static_entry = (!mac_late && 364 !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK)); 365 366 if (static_entry) { 367 LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) { 368 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 369 error = EEXIST; 370 goto out; 371 } 372 } 373 } else { 374 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) { 375 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) { 376 error = EEXIST; 377 goto out; 378 } 379 } 380 } 381 if (mpc->mpc_field_off != NULL) { 382 slot = ffs(mac_slot_offsets_free); 383 if (slot == 0) { 384 error = ENOMEM; 385 goto out; 386 } 387 slot--; 388 mac_slot_offsets_free &= ~(1 << slot); 389 *mpc->mpc_field_off = slot; 390 } 391 mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED; 392 393 /* 394 * If we're loading a MAC module after the framework has 395 * initialized, it has to go into the dynamic list. If 396 * we're loading it before we've finished initializing, 397 * it can go into the static list with weaker locker 398 * requirements. 399 */ 400 if (static_entry) 401 LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list); 402 else 403 LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list); 404 405 /* Per-policy initialization. */ 406 if (mpc->mpc_ops->mpo_init != NULL) 407 (*(mpc->mpc_ops->mpo_init))(mpc); 408 mac_policy_updateflags(); 409 410 printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, 411 mpc->mpc_name); 412 413out: 414 mac_policy_release_exclusive(); 415 return (error); 416} 417 418static int 419mac_policy_unregister(struct mac_policy_conf *mpc) 420{ 421 422 /* 423 * If we fail the load, we may get a request to unload. Check 424 * to see if we did the run-time registration, and if not, 425 * silently succeed. 426 */ 427 mac_policy_grab_exclusive(); 428 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) { 429 mac_policy_release_exclusive(); 430 return (0); 431 } 432#if 0 433 /* 434 * Don't allow unloading modules with private data. 435 */ 436 if (mpc->mpc_field_off != NULL) { 437 MAC_POLICY_LIST_UNLOCK(); 438 return (EBUSY); 439 } 440#endif 441 /* 442 * Only allow the unload to proceed if the module is unloadable 443 * by its own definition. 444 */ 445 if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) { 446 mac_policy_release_exclusive(); 447 return (EBUSY); 448 } 449 if (mpc->mpc_ops->mpo_destroy != NULL) 450 (*(mpc->mpc_ops->mpo_destroy))(mpc); 451 452 LIST_REMOVE(mpc, mpc_list); 453 mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED; 454 mac_policy_updateflags(); 455 456 mac_policy_release_exclusive(); 457 458 printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, 459 mpc->mpc_name); 460 461 return (0); 462} 463 464/* 465 * Define an error value precedence, and given two arguments, selects the 466 * value with the higher precedence. 467 */ 468int 469mac_error_select(int error1, int error2) 470{ 471 472 /* Certain decision-making errors take top priority. */ 473 if (error1 == EDEADLK || error2 == EDEADLK) 474 return (EDEADLK); 475 476 /* Invalid arguments should be reported where possible. */ 477 if (error1 == EINVAL || error2 == EINVAL) 478 return (EINVAL); 479 480 /* Precedence goes to "visibility", with both process and file. */ 481 if (error1 == ESRCH || error2 == ESRCH) 482 return (ESRCH); 483 484 if (error1 == ENOENT || error2 == ENOENT) 485 return (ENOENT); 486 487 /* Precedence goes to DAC/MAC protections. */ 488 if (error1 == EACCES || error2 == EACCES) 489 return (EACCES); 490 491 /* Precedence goes to privilege. */ 492 if (error1 == EPERM || error2 == EPERM) 493 return (EPERM); 494 495 /* Precedence goes to error over success; otherwise, arbitrary. */ 496 if (error1 != 0) 497 return (error1); 498 return (error2); 499} 500 501void 502mac_init_label(struct label *label) 503{ 504 505 bzero(label, sizeof(*label)); 506 label->l_flags = MAC_FLAG_INITIALIZED; 507} 508 509void 510mac_destroy_label(struct label *label) 511{ 512 513 KASSERT(label->l_flags & MAC_FLAG_INITIALIZED, 514 ("destroying uninitialized label")); 515 516 bzero(label, sizeof(*label)); 517 /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */ 518} 519 520int 521mac_check_structmac_consistent(struct mac *mac) 522{ 523 524 if (mac->m_buflen < 0 || 525 mac->m_buflen > MAC_MAX_LABEL_BUF_LEN) 526 return (EINVAL); 527 528 return (0); 529} 530 531int 532__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 533{ 534 char *elements, *buffer; 535 struct mac mac; 536 struct proc *tproc; 537 struct ucred *tcred; 538 int error; 539 540 error = copyin(uap->mac_p, &mac, sizeof(mac)); 541 if (error) 542 return (error); 543 544 error = mac_check_structmac_consistent(&mac); 545 if (error) 546 return (error); 547 548 tproc = pfind(uap->pid); 549 if (tproc == NULL) 550 return (ESRCH); 551 552 tcred = NULL; /* Satisfy gcc. */ 553 error = p_cansee(td, tproc); 554 if (error == 0) 555 tcred = crhold(tproc->p_ucred); 556 PROC_UNLOCK(tproc); 557 if (error) 558 return (error); 559 560 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 561 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 562 if (error) { 563 free(elements, M_MACTEMP); 564 crfree(tcred); 565 return (error); 566 } 567 568 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
|
568 error = mac_externalize_cred_label(&tcred->cr_label, elements,
| 569 error = mac_externalize_cred_label(tcred->cr_label, elements,
|
569 buffer, mac.m_buflen); 570 if (error == 0) 571 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 572 573 free(buffer, M_MACTEMP); 574 free(elements, M_MACTEMP); 575 crfree(tcred); 576 return (error); 577} 578 579/* 580 * MPSAFE 581 */ 582int 583__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 584{ 585 char *elements, *buffer; 586 struct mac mac; 587 int error; 588 589 error = copyin(uap->mac_p, &mac, sizeof(mac)); 590 if (error) 591 return (error); 592 593 error = mac_check_structmac_consistent(&mac); 594 if (error) 595 return (error); 596 597 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 598 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 599 if (error) { 600 free(elements, M_MACTEMP); 601 return (error); 602 } 603 604 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
| 570 buffer, mac.m_buflen); 571 if (error == 0) 572 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 573 574 free(buffer, M_MACTEMP); 575 free(elements, M_MACTEMP); 576 crfree(tcred); 577 return (error); 578} 579 580/* 581 * MPSAFE 582 */ 583int 584__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 585{ 586 char *elements, *buffer; 587 struct mac mac; 588 int error; 589 590 error = copyin(uap->mac_p, &mac, sizeof(mac)); 591 if (error) 592 return (error); 593 594 error = mac_check_structmac_consistent(&mac); 595 if (error) 596 return (error); 597 598 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 599 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 600 if (error) { 601 free(elements, M_MACTEMP); 602 return (error); 603 } 604 605 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
|
605 error = mac_externalize_cred_label(&td->td_ucred->cr_label,
| 606 error = mac_externalize_cred_label(td->td_ucred->cr_label,
|
606 elements, buffer, mac.m_buflen); 607 if (error == 0) 608 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 609 610 free(buffer, M_MACTEMP); 611 free(elements, M_MACTEMP); 612 return (error); 613} 614 615/* 616 * MPSAFE 617 */ 618int 619__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 620{ 621 struct ucred *newcred, *oldcred;
| 607 elements, buffer, mac.m_buflen); 608 if (error == 0) 609 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 610 611 free(buffer, M_MACTEMP); 612 free(elements, M_MACTEMP); 613 return (error); 614} 615 616/* 617 * MPSAFE 618 */ 619int 620__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 621{ 622 struct ucred *newcred, *oldcred;
|
622 struct label intlabel;
| 623 struct label *intlabel;
|
623 struct proc *p; 624 struct mac mac; 625 char *buffer; 626 int error; 627 628 error = copyin(uap->mac_p, &mac, sizeof(mac)); 629 if (error) 630 return (error); 631 632 error = mac_check_structmac_consistent(&mac); 633 if (error) 634 return (error); 635 636 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 637 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 638 if (error) { 639 free(buffer, M_MACTEMP); 640 return (error); 641 } 642
| 624 struct proc *p; 625 struct mac mac; 626 char *buffer; 627 int error; 628 629 error = copyin(uap->mac_p, &mac, sizeof(mac)); 630 if (error) 631 return (error); 632 633 error = mac_check_structmac_consistent(&mac); 634 if (error) 635 return (error); 636 637 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 638 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 639 if (error) { 640 free(buffer, M_MACTEMP); 641 return (error); 642 } 643
|
643 mac_init_cred_label(&intlabel); 644 error = mac_internalize_cred_label(&intlabel, buffer);
| 644 intlabel = mac_cred_label_alloc(); 645 error = mac_internalize_cred_label(intlabel, buffer);
|
645 free(buffer, M_MACTEMP);
| 646 free(buffer, M_MACTEMP);
|
646 if (error) { 647 mac_destroy_cred_label(&intlabel); 648 return (error); 649 }
| 647 if (error) 648 goto out;
|
650 651 newcred = crget(); 652 653 p = td->td_proc; 654 PROC_LOCK(p); 655 oldcred = p->p_ucred; 656
| 649 650 newcred = crget(); 651 652 p = td->td_proc; 653 PROC_LOCK(p); 654 oldcred = p->p_ucred; 655
|
657 error = mac_check_cred_relabel(oldcred, &intlabel);
| 656 error = mac_check_cred_relabel(oldcred, intlabel);
|
658 if (error) { 659 PROC_UNLOCK(p); 660 crfree(newcred); 661 goto out; 662 } 663 664 setsugid(p); 665 crcopy(newcred, oldcred);
| 657 if (error) { 658 PROC_UNLOCK(p); 659 crfree(newcred); 660 goto out; 661 } 662 663 setsugid(p); 664 crcopy(newcred, oldcred);
|
666 mac_relabel_cred(newcred, &intlabel);
| 665 mac_relabel_cred(newcred, intlabel);
|
667 p->p_ucred = newcred; 668 669 /* 670 * Grab additional reference for use while revoking mmaps, prior 671 * to releasing the proc lock and sharing the cred. 672 */ 673 crhold(newcred); 674 PROC_UNLOCK(p); 675 676 if (mac_enforce_vm) { 677 mtx_lock(&Giant); 678 mac_cred_mmapped_drop_perms(td, newcred); 679 mtx_unlock(&Giant); 680 } 681 682 crfree(newcred); /* Free revocation reference. */ 683 crfree(oldcred); 684 685out:
| 666 p->p_ucred = newcred; 667 668 /* 669 * Grab additional reference for use while revoking mmaps, prior 670 * to releasing the proc lock and sharing the cred. 671 */ 672 crhold(newcred); 673 PROC_UNLOCK(p); 674 675 if (mac_enforce_vm) { 676 mtx_lock(&Giant); 677 mac_cred_mmapped_drop_perms(td, newcred); 678 mtx_unlock(&Giant); 679 } 680 681 crfree(newcred); /* Free revocation reference. */ 682 crfree(oldcred); 683 684out:
|
686 mac_destroy_cred_label(&intlabel);
| 685 mac_cred_label_free(intlabel);
|
687 return (error); 688} 689 690/* 691 * MPSAFE 692 */ 693int 694__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 695{ 696 char *elements, *buffer;
| 686 return (error); 687} 688 689/* 690 * MPSAFE 691 */ 692int 693__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 694{ 695 char *elements, *buffer;
|
697 struct label intlabel;
| 696 struct label *intlabel;
|
698 struct file *fp; 699 struct mac mac; 700 struct vnode *vp; 701 struct pipe *pipe; 702 short label_type; 703 int error; 704 705 error = copyin(uap->mac_p, &mac, sizeof(mac)); 706 if (error) 707 return (error); 708 709 error = mac_check_structmac_consistent(&mac); 710 if (error) 711 return (error); 712 713 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 714 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 715 if (error) { 716 free(elements, M_MACTEMP); 717 return (error); 718 } 719 720 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 721 mtx_lock(&Giant); /* VFS */ 722 error = fget(td, uap->fd, &fp); 723 if (error) 724 goto out; 725 726 label_type = fp->f_type; 727 switch (fp->f_type) { 728 case DTYPE_FIFO: 729 case DTYPE_VNODE: 730 vp = fp->f_vnode; 731
| 697 struct file *fp; 698 struct mac mac; 699 struct vnode *vp; 700 struct pipe *pipe; 701 short label_type; 702 int error; 703 704 error = copyin(uap->mac_p, &mac, sizeof(mac)); 705 if (error) 706 return (error); 707 708 error = mac_check_structmac_consistent(&mac); 709 if (error) 710 return (error); 711 712 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 713 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 714 if (error) { 715 free(elements, M_MACTEMP); 716 return (error); 717 } 718 719 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 720 mtx_lock(&Giant); /* VFS */ 721 error = fget(td, uap->fd, &fp); 722 if (error) 723 goto out; 724 725 label_type = fp->f_type; 726 switch (fp->f_type) { 727 case DTYPE_FIFO: 728 case DTYPE_VNODE: 729 vp = fp->f_vnode; 730
|
732 mac_init_vnode_label(&intlabel);
| 731 intlabel = mac_vnode_label_alloc();
|
733 734 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
| 732 733 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
|
735 mac_copy_vnode_label(&vp->v_label, &intlabel);
| 734 mac_copy_vnode_label(vp->v_label, intlabel);
|
736 VOP_UNLOCK(vp, 0, td); 737 738 break; 739 case DTYPE_PIPE: 740 pipe = fp->f_data; 741
| 735 VOP_UNLOCK(vp, 0, td); 736 737 break; 738 case DTYPE_PIPE: 739 pipe = fp->f_data; 740
|
742 mac_init_pipe_label(&intlabel);
| 741 intlabel = mac_pipe_label_alloc();
|
743 744 PIPE_LOCK(pipe);
| 742 743 PIPE_LOCK(pipe);
|
745 mac_copy_pipe_label(pipe->pipe_label, &intlabel);
| 744 mac_copy_pipe_label(pipe->pipe_label, intlabel);
|
746 PIPE_UNLOCK(pipe); 747 break; 748 default: 749 error = EINVAL; 750 fdrop(fp, td); 751 goto out; 752 } 753 fdrop(fp, td); 754 755 switch (label_type) { 756 case DTYPE_FIFO: 757 case DTYPE_VNODE: 758 if (error == 0)
| 745 PIPE_UNLOCK(pipe); 746 break; 747 default: 748 error = EINVAL; 749 fdrop(fp, td); 750 goto out; 751 } 752 fdrop(fp, td); 753 754 switch (label_type) { 755 case DTYPE_FIFO: 756 case DTYPE_VNODE: 757 if (error == 0)
|
759 error = mac_externalize_vnode_label(&intlabel,
| 758 error = mac_externalize_vnode_label(intlabel,
|
760 elements, buffer, mac.m_buflen);
| 759 elements, buffer, mac.m_buflen);
|
761 mac_destroy_vnode_label(&intlabel);
| 760 mac_vnode_label_free(intlabel);
|
762 break; 763 case DTYPE_PIPE:
| 761 break; 762 case DTYPE_PIPE:
|
764 error = mac_externalize_pipe_label(&intlabel, elements,
| 763 error = mac_externalize_pipe_label(intlabel, elements,
|
765 buffer, mac.m_buflen);
| 764 buffer, mac.m_buflen);
|
766 mac_destroy_pipe_label(&intlabel);
| 765 mac_pipe_label_free(intlabel);
|
767 break; 768 default: 769 panic("__mac_get_fd: corrupted label_type"); 770 } 771 772 if (error == 0) 773 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 774 775out: 776 mtx_unlock(&Giant); /* VFS */ 777 free(buffer, M_MACTEMP); 778 free(elements, M_MACTEMP); 779 780 return (error); 781} 782 783/* 784 * MPSAFE 785 */ 786int 787__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 788{ 789 char *elements, *buffer; 790 struct nameidata nd;
| 766 break; 767 default: 768 panic("__mac_get_fd: corrupted label_type"); 769 } 770 771 if (error == 0) 772 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 773 774out: 775 mtx_unlock(&Giant); /* VFS */ 776 free(buffer, M_MACTEMP); 777 free(elements, M_MACTEMP); 778 779 return (error); 780} 781 782/* 783 * MPSAFE 784 */ 785int 786__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 787{ 788 char *elements, *buffer; 789 struct nameidata nd;
|
791 struct label intlabel;
| 790 struct label *intlabel;
|
792 struct mac mac; 793 int error; 794 795 error = copyin(uap->mac_p, &mac, sizeof(mac)); 796 if (error) 797 return (error); 798 799 error = mac_check_structmac_consistent(&mac); 800 if (error) 801 return (error); 802 803 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 804 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 805 if (error) { 806 free(elements, M_MACTEMP); 807 return (error); 808 } 809 810 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 811 mtx_lock(&Giant); /* VFS */ 812 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 813 td); 814 error = namei(&nd); 815 if (error) 816 goto out; 817
| 791 struct mac mac; 792 int error; 793 794 error = copyin(uap->mac_p, &mac, sizeof(mac)); 795 if (error) 796 return (error); 797 798 error = mac_check_structmac_consistent(&mac); 799 if (error) 800 return (error); 801 802 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 803 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 804 if (error) { 805 free(elements, M_MACTEMP); 806 return (error); 807 } 808 809 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 810 mtx_lock(&Giant); /* VFS */ 811 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 812 td); 813 error = namei(&nd); 814 if (error) 815 goto out; 816
|
818 mac_init_vnode_label(&intlabel); 819 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 820 error = mac_externalize_vnode_label(&intlabel, elements, buffer,
| 817 intlabel = mac_vnode_label_alloc(); 818 mac_copy_vnode_label(nd.ni_vp->v_label, intlabel); 819 error = mac_externalize_vnode_label(intlabel, elements, buffer,
|
821 mac.m_buflen); 822 823 NDFREE(&nd, 0);
| 820 mac.m_buflen); 821 822 NDFREE(&nd, 0);
|
824 mac_destroy_vnode_label(&intlabel);
| 823 mac_vnode_label_free(intlabel);
|
825 826 if (error == 0) 827 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 828 829out: 830 mtx_unlock(&Giant); /* VFS */ 831 832 free(buffer, M_MACTEMP); 833 free(elements, M_MACTEMP); 834 835 return (error); 836} 837 838/* 839 * MPSAFE 840 */ 841int 842__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 843{ 844 char *elements, *buffer; 845 struct nameidata nd;
| 824 825 if (error == 0) 826 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 827 828out: 829 mtx_unlock(&Giant); /* VFS */ 830 831 free(buffer, M_MACTEMP); 832 free(elements, M_MACTEMP); 833 834 return (error); 835} 836 837/* 838 * MPSAFE 839 */ 840int 841__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 842{ 843 char *elements, *buffer; 844 struct nameidata nd;
|
846 struct label intlabel;
| 845 struct label *intlabel;
|
847 struct mac mac; 848 int error; 849 850 error = copyin(uap->mac_p, &mac, sizeof(mac)); 851 if (error) 852 return (error); 853 854 error = mac_check_structmac_consistent(&mac); 855 if (error) 856 return (error); 857 858 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 859 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 860 if (error) { 861 free(elements, M_MACTEMP); 862 return (error); 863 } 864 865 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 866 mtx_lock(&Giant); /* VFS */ 867 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 868 td); 869 error = namei(&nd); 870 if (error) 871 goto out; 872
| 846 struct mac mac; 847 int error; 848 849 error = copyin(uap->mac_p, &mac, sizeof(mac)); 850 if (error) 851 return (error); 852 853 error = mac_check_structmac_consistent(&mac); 854 if (error) 855 return (error); 856 857 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 858 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); 859 if (error) { 860 free(elements, M_MACTEMP); 861 return (error); 862 } 863 864 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 865 mtx_lock(&Giant); /* VFS */ 866 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 867 td); 868 error = namei(&nd); 869 if (error) 870 goto out; 871
|
873 mac_init_vnode_label(&intlabel); 874 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); 875 error = mac_externalize_vnode_label(&intlabel, elements, buffer,
| 872 intlabel = mac_vnode_label_alloc(); 873 mac_copy_vnode_label(nd.ni_vp->v_label, intlabel); 874 error = mac_externalize_vnode_label(intlabel, elements, buffer,
|
876 mac.m_buflen); 877 NDFREE(&nd, 0);
| 875 mac.m_buflen); 876 NDFREE(&nd, 0);
|
878 mac_destroy_vnode_label(&intlabel);
| 877 mac_vnode_label_free(intlabel);
|
879 880 if (error == 0) 881 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 882 883out: 884 mtx_unlock(&Giant); /* VFS */ 885 886 free(buffer, M_MACTEMP); 887 free(elements, M_MACTEMP); 888 889 return (error); 890} 891 892/* 893 * MPSAFE 894 */ 895int 896__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 897{
| 878 879 if (error == 0) 880 error = copyout(buffer, mac.m_string, strlen(buffer)+1); 881 882out: 883 mtx_unlock(&Giant); /* VFS */ 884 885 free(buffer, M_MACTEMP); 886 free(elements, M_MACTEMP); 887 888 return (error); 889} 890 891/* 892 * MPSAFE 893 */ 894int 895__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 896{
|
898 struct label intlabel;
| 897 struct label *intlabel;
|
899 struct pipe *pipe; 900 struct file *fp; 901 struct mount *mp; 902 struct vnode *vp; 903 struct mac mac; 904 char *buffer; 905 int error; 906 907 error = copyin(uap->mac_p, &mac, sizeof(mac)); 908 if (error) 909 return (error); 910 911 error = mac_check_structmac_consistent(&mac); 912 if (error) 913 return (error); 914 915 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 916 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 917 if (error) { 918 free(buffer, M_MACTEMP); 919 return (error); 920 } 921 922 mtx_lock(&Giant); /* VFS */ 923 924 error = fget(td, uap->fd, &fp); 925 if (error) 926 goto out; 927 928 switch (fp->f_type) { 929 case DTYPE_FIFO: 930 case DTYPE_VNODE:
| 898 struct pipe *pipe; 899 struct file *fp; 900 struct mount *mp; 901 struct vnode *vp; 902 struct mac mac; 903 char *buffer; 904 int error; 905 906 error = copyin(uap->mac_p, &mac, sizeof(mac)); 907 if (error) 908 return (error); 909 910 error = mac_check_structmac_consistent(&mac); 911 if (error) 912 return (error); 913 914 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 915 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 916 if (error) { 917 free(buffer, M_MACTEMP); 918 return (error); 919 } 920 921 mtx_lock(&Giant); /* VFS */ 922 923 error = fget(td, uap->fd, &fp); 924 if (error) 925 goto out; 926 927 switch (fp->f_type) { 928 case DTYPE_FIFO: 929 case DTYPE_VNODE:
|
931 mac_init_vnode_label(&intlabel); 932 error = mac_internalize_vnode_label(&intlabel, buffer);
| 930 intlabel = mac_vnode_label_alloc(); 931 error = mac_internalize_vnode_label(intlabel, buffer);
|
933 if (error) {
| 932 if (error) {
|
934 mac_destroy_vnode_label(&intlabel);
| 933 mac_vnode_label_free(intlabel);
|
935 break; 936 } 937 938 vp = fp->f_vnode; 939 error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 940 if (error != 0) {
| 934 break; 935 } 936 937 vp = fp->f_vnode; 938 error = vn_start_write(vp, &mp, V_WAIT | PCATCH); 939 if (error != 0) {
|
941 mac_destroy_vnode_label(&intlabel);
| 940 mac_vnode_label_free(intlabel);
|
942 break; 943 } 944 945 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
| 941 break; 942 } 943 944 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
|
946 error = vn_setlabel(vp, &intlabel, td->td_ucred);
| 945 error = vn_setlabel(vp, intlabel, td->td_ucred);
|
947 VOP_UNLOCK(vp, 0, td); 948 vn_finished_write(mp); 949
| 946 VOP_UNLOCK(vp, 0, td); 947 vn_finished_write(mp); 948
|
950 mac_destroy_vnode_label(&intlabel);
| 949 mac_vnode_label_free(intlabel);
|
951 break; 952 953 case DTYPE_PIPE:
| 950 break; 951 952 case DTYPE_PIPE:
|
954 mac_init_pipe_label(&intlabel); 955 error = mac_internalize_pipe_label(&intlabel, buffer);
| 953 intlabel = mac_pipe_label_alloc(); 954 error = mac_internalize_pipe_label(intlabel, buffer);
|
956 if (error == 0) { 957 pipe = fp->f_data; 958 PIPE_LOCK(pipe); 959 error = mac_pipe_label_set(td->td_ucred, pipe,
| 955 if (error == 0) { 956 pipe = fp->f_data; 957 PIPE_LOCK(pipe); 958 error = mac_pipe_label_set(td->td_ucred, pipe,
|
960 &intlabel);
| 959 intlabel);
|
961 PIPE_UNLOCK(pipe); 962 } 963
| 960 PIPE_UNLOCK(pipe); 961 } 962
|
964 mac_destroy_pipe_label(&intlabel);
| 963 mac_pipe_label_free(intlabel);
|
965 break; 966 967 default: 968 error = EINVAL; 969 } 970 971 fdrop(fp, td); 972out: 973 mtx_unlock(&Giant); /* VFS */ 974 975 free(buffer, M_MACTEMP); 976 977 return (error); 978} 979 980/* 981 * MPSAFE 982 */ 983int 984__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 985{
| 964 break; 965 966 default: 967 error = EINVAL; 968 } 969 970 fdrop(fp, td); 971out: 972 mtx_unlock(&Giant); /* VFS */ 973 974 free(buffer, M_MACTEMP); 975 976 return (error); 977} 978 979/* 980 * MPSAFE 981 */ 982int 983__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 984{
|
986 struct label intlabel;
| 985 struct label *intlabel;
|
987 struct nameidata nd; 988 struct mount *mp; 989 struct mac mac; 990 char *buffer; 991 int error; 992 993 error = copyin(uap->mac_p, &mac, sizeof(mac)); 994 if (error) 995 return (error); 996 997 error = mac_check_structmac_consistent(&mac); 998 if (error) 999 return (error); 1000 1001 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1002 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1003 if (error) { 1004 free(buffer, M_MACTEMP); 1005 return (error); 1006 } 1007
| 986 struct nameidata nd; 987 struct mount *mp; 988 struct mac mac; 989 char *buffer; 990 int error; 991 992 error = copyin(uap->mac_p, &mac, sizeof(mac)); 993 if (error) 994 return (error); 995 996 error = mac_check_structmac_consistent(&mac); 997 if (error) 998 return (error); 999 1000 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1001 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1002 if (error) { 1003 free(buffer, M_MACTEMP); 1004 return (error); 1005 } 1006
|
1008 mac_init_vnode_label(&intlabel); 1009 error = mac_internalize_vnode_label(&intlabel, buffer);
| 1007 intlabel = mac_vnode_label_alloc(); 1008 error = mac_internalize_vnode_label(intlabel, buffer);
|
1010 free(buffer, M_MACTEMP);
| 1009 free(buffer, M_MACTEMP);
|
1011 if (error) { 1012 mac_destroy_vnode_label(&intlabel); 1013 return (error); 1014 }
| 1010 if (error) 1011 goto out;
|
1015 1016 mtx_lock(&Giant); /* VFS */ 1017 1018 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 1019 td); 1020 error = namei(&nd); 1021 if (error == 0) { 1022 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1023 if (error == 0)
| 1012 1013 mtx_lock(&Giant); /* VFS */ 1014 1015 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, 1016 td); 1017 error = namei(&nd); 1018 if (error == 0) { 1019 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1020 if (error == 0)
|
1024 error = vn_setlabel(nd.ni_vp, &intlabel,
| 1021 error = vn_setlabel(nd.ni_vp, intlabel,
|
1025 td->td_ucred); 1026 vn_finished_write(mp); 1027 } 1028 1029 NDFREE(&nd, 0); 1030 mtx_unlock(&Giant); /* VFS */
| 1022 td->td_ucred); 1023 vn_finished_write(mp); 1024 } 1025 1026 NDFREE(&nd, 0); 1027 mtx_unlock(&Giant); /* VFS */
|
1031 mac_destroy_vnode_label(&intlabel); 1032
| 1028out: 1029 mac_vnode_label_free(intlabel);
|
1033 return (error); 1034} 1035 1036/* 1037 * MPSAFE 1038 */ 1039int 1040__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1041{
| 1030 return (error); 1031} 1032 1033/* 1034 * MPSAFE 1035 */ 1036int 1037__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1038{
|
1042 struct label intlabel;
| 1039 struct label *intlabel;
|
1043 struct nameidata nd; 1044 struct mount *mp; 1045 struct mac mac; 1046 char *buffer; 1047 int error; 1048 1049 error = copyin(uap->mac_p, &mac, sizeof(mac)); 1050 if (error) 1051 return (error); 1052 1053 error = mac_check_structmac_consistent(&mac); 1054 if (error) 1055 return (error); 1056 1057 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1058 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1059 if (error) { 1060 free(buffer, M_MACTEMP); 1061 return (error); 1062 } 1063
| 1040 struct nameidata nd; 1041 struct mount *mp; 1042 struct mac mac; 1043 char *buffer; 1044 int error; 1045 1046 error = copyin(uap->mac_p, &mac, sizeof(mac)); 1047 if (error) 1048 return (error); 1049 1050 error = mac_check_structmac_consistent(&mac); 1051 if (error) 1052 return (error); 1053 1054 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); 1055 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); 1056 if (error) { 1057 free(buffer, M_MACTEMP); 1058 return (error); 1059 } 1060
|
1064 mac_init_vnode_label(&intlabel); 1065 error = mac_internalize_vnode_label(&intlabel, buffer);
| 1061 intlabel = mac_vnode_label_alloc(); 1062 error = mac_internalize_vnode_label(intlabel, buffer);
|
1066 free(buffer, M_MACTEMP);
| 1063 free(buffer, M_MACTEMP);
|
1067 if (error) { 1068 mac_destroy_vnode_label(&intlabel); 1069 return (error); 1070 }
| 1064 if (error) 1065 goto out;
|
1071 1072 mtx_lock(&Giant); /* VFS */ 1073 1074 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 1075 td); 1076 error = namei(&nd); 1077 if (error == 0) { 1078 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1079 if (error == 0)
| 1066 1067 mtx_lock(&Giant); /* VFS */ 1068 1069 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, 1070 td); 1071 error = namei(&nd); 1072 if (error == 0) { 1073 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 1074 if (error == 0)
|
1080 error = vn_setlabel(nd.ni_vp, &intlabel,
| 1075 error = vn_setlabel(nd.ni_vp, intlabel,
|
1081 td->td_ucred); 1082 vn_finished_write(mp); 1083 } 1084 1085 NDFREE(&nd, 0); 1086 mtx_unlock(&Giant); /* VFS */
| 1076 td->td_ucred); 1077 vn_finished_write(mp); 1078 } 1079 1080 NDFREE(&nd, 0); 1081 mtx_unlock(&Giant); /* VFS */
|
1087 mac_destroy_vnode_label(&intlabel); 1088
| 1082out: 1083 mac_vnode_label_free(intlabel);
|
1089 return (error); 1090} 1091 1092/* 1093 * MPSAFE 1094 */ 1095int 1096mac_syscall(struct thread *td, struct mac_syscall_args *uap) 1097{ 1098 struct mac_policy_conf *mpc; 1099 char target[MAC_MAX_POLICY_NAME]; 1100 int entrycount, error; 1101 1102 error = copyinstr(uap->policy, target, sizeof(target), NULL); 1103 if (error) 1104 return (error); 1105 1106 error = ENOSYS; 1107 LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { 1108 if (strcmp(mpc->mpc_name, target) == 0 && 1109 mpc->mpc_ops->mpo_syscall != NULL) { 1110 error = mpc->mpc_ops->mpo_syscall(td, 1111 uap->call, uap->arg); 1112 goto out; 1113 } 1114 } 1115 1116 if ((entrycount = mac_policy_list_conditional_busy()) != 0) { 1117 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 1118 if (strcmp(mpc->mpc_name, target) == 0 && 1119 mpc->mpc_ops->mpo_syscall != NULL) { 1120 error = mpc->mpc_ops->mpo_syscall(td, 1121 uap->call, uap->arg); 1122 break; 1123 } 1124 } 1125 mac_policy_list_unbusy(); 1126 } 1127out: 1128 return (error); 1129} 1130 1131SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 1132SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 1133 1134#else /* !MAC */ 1135 1136int 1137__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 1138{ 1139 1140 return (ENOSYS); 1141} 1142 1143int 1144__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 1145{ 1146 1147 return (ENOSYS); 1148} 1149 1150int 1151__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 1152{ 1153 1154 return (ENOSYS); 1155} 1156 1157int 1158__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 1159{ 1160 1161 return (ENOSYS); 1162} 1163 1164int 1165__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 1166{ 1167 1168 return (ENOSYS); 1169} 1170 1171int 1172__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 1173{ 1174 1175 return (ENOSYS); 1176} 1177 1178int 1179__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 1180{ 1181 1182 return (ENOSYS); 1183} 1184 1185int 1186__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 1187{ 1188 1189 return (ENOSYS); 1190} 1191 1192int 1193__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1194{ 1195 1196 return (ENOSYS); 1197} 1198 1199int 1200mac_syscall(struct thread *td, struct mac_syscall_args *uap) 1201{ 1202 1203 return (ENOSYS); 1204} 1205 1206#endif
| 1084 return (error); 1085} 1086 1087/* 1088 * MPSAFE 1089 */ 1090int 1091mac_syscall(struct thread *td, struct mac_syscall_args *uap) 1092{ 1093 struct mac_policy_conf *mpc; 1094 char target[MAC_MAX_POLICY_NAME]; 1095 int entrycount, error; 1096 1097 error = copyinstr(uap->policy, target, sizeof(target), NULL); 1098 if (error) 1099 return (error); 1100 1101 error = ENOSYS; 1102 LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { 1103 if (strcmp(mpc->mpc_name, target) == 0 && 1104 mpc->mpc_ops->mpo_syscall != NULL) { 1105 error = mpc->mpc_ops->mpo_syscall(td, 1106 uap->call, uap->arg); 1107 goto out; 1108 } 1109 } 1110 1111 if ((entrycount = mac_policy_list_conditional_busy()) != 0) { 1112 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { 1113 if (strcmp(mpc->mpc_name, target) == 0 && 1114 mpc->mpc_ops->mpo_syscall != NULL) { 1115 error = mpc->mpc_ops->mpo_syscall(td, 1116 uap->call, uap->arg); 1117 break; 1118 } 1119 } 1120 mac_policy_list_unbusy(); 1121 } 1122out: 1123 return (error); 1124} 1125 1126SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL); 1127SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL); 1128 1129#else /* !MAC */ 1130 1131int 1132__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) 1133{ 1134 1135 return (ENOSYS); 1136} 1137 1138int 1139__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) 1140{ 1141 1142 return (ENOSYS); 1143} 1144 1145int 1146__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) 1147{ 1148 1149 return (ENOSYS); 1150} 1151 1152int 1153__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) 1154{ 1155 1156 return (ENOSYS); 1157} 1158 1159int 1160__mac_get_file(struct thread *td, struct __mac_get_file_args *uap) 1161{ 1162 1163 return (ENOSYS); 1164} 1165 1166int 1167__mac_get_link(struct thread *td, struct __mac_get_link_args *uap) 1168{ 1169 1170 return (ENOSYS); 1171} 1172 1173int 1174__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) 1175{ 1176 1177 return (ENOSYS); 1178} 1179 1180int 1181__mac_set_file(struct thread *td, struct __mac_set_file_args *uap) 1182{ 1183 1184 return (ENOSYS); 1185} 1186 1187int 1188__mac_set_link(struct thread *td, struct __mac_set_link_args *uap) 1189{ 1190 1191 return (ENOSYS); 1192} 1193 1194int 1195mac_syscall(struct thread *td, struct mac_syscall_args *uap) 1196{ 1197 1198 return (ENOSYS); 1199} 1200 1201#endif
|