The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/kern_mac.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1999-2002 Robert N. M. Watson
    3  * Copyright (c) 2001 Ilmar S. Habibulin
    4  * Copyright (c) 2001-2004 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  * found in src/sys/security/mac/.  Sample policies may be found in
   41  * src/sys/security/mac_*.
   42  */
   43 
   44 #include <sys/cdefs.h>
   45 __FBSDID("$FreeBSD: src/sys/kern/kern_mac.c,v 1.113.2.2 2005/05/05 18:36:03 trhodes Exp $");
   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  */
   99 MODULE_VERSION(kernel_mac_support, 1);
  100 
  101 SYSCTL_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 
  108 static unsigned int mac_max_slots = MAC_MAX_SLOTS;
  109 static unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1;
  110 SYSCTL_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  */
  118 int     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
  132 int     mac_labelmbufs = 0;
  133 #endif
  134 
  135 #ifdef MAC_DEBUG
  136 SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0,
  137     "TrustedBSD MAC debug info");
  138 SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0,
  139     "TrustedBSD MAC object counters");
  140 
  141 static unsigned int nmactemp;
  142 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD,
  143     &nmactemp, 0, "number of temporary labels in use");
  144 #endif
  145 
  146 static int      mac_policy_register(struct mac_policy_conf *mpc);
  147 static int      mac_policy_unregister(struct mac_policy_conf *mpc);
  148 
  149 MALLOC_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  */
  169 #ifndef MAC_STATIC
  170 static struct mtx mac_policy_mtx;
  171 static struct cv mac_policy_cv;
  172 static int mac_policy_count;
  173 #endif
  174 struct mac_policy_list_head mac_policy_list;
  175 struct mac_policy_list_head mac_static_policy_list;
  176 
  177 /*
  178  * We manually invoke WITNESS_WARN() to allow Witness to generate
  179  * warnings even if we don't end up ever triggering the wait at
  180  * run-time.  The consumer of the exclusive interface must not hold
  181  * any locks (other than potentially Giant) since we may sleep for
  182  * long (potentially indefinite) periods of time waiting for the
  183  * framework to become quiescent so that a policy list change may
  184  * be made.
  185  */
  186 void
  187 mac_policy_grab_exclusive(void)
  188 {
  189 
  190 #ifndef MAC_STATIC
  191         if (!mac_late)
  192                 return;
  193 
  194         WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
  195             "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__);
  196         mtx_lock(&mac_policy_mtx);
  197         while (mac_policy_count != 0)
  198                 cv_wait(&mac_policy_cv, &mac_policy_mtx);
  199 #endif
  200 }
  201 
  202 void
  203 mac_policy_assert_exclusive(void)
  204 {
  205 
  206 #ifndef MAC_STATIC
  207         if (!mac_late)
  208                 return;
  209 
  210         mtx_assert(&mac_policy_mtx, MA_OWNED);
  211         KASSERT(mac_policy_count == 0,
  212             ("mac_policy_assert_exclusive(): not exclusive"));
  213 #endif
  214 }
  215 
  216 void
  217 mac_policy_release_exclusive(void)
  218 {
  219 
  220 #ifndef MAC_STATIC
  221         if (!mac_late)
  222                 return;
  223 
  224         KASSERT(mac_policy_count == 0,
  225             ("mac_policy_release_exclusive(): not exclusive"));
  226         mtx_unlock(&mac_policy_mtx);
  227         cv_signal(&mac_policy_cv);
  228 #endif
  229 }
  230 
  231 void
  232 mac_policy_list_busy(void)
  233 {
  234 
  235 #ifndef MAC_STATIC
  236         if (!mac_late)
  237                 return;
  238 
  239         mtx_lock(&mac_policy_mtx);
  240         mac_policy_count++;
  241         mtx_unlock(&mac_policy_mtx);
  242 #endif
  243 }
  244 
  245 int
  246 mac_policy_list_conditional_busy(void)
  247 {
  248 #ifndef MAC_STATIC
  249         int ret;
  250 
  251         if (!mac_late)
  252                 return (1);
  253 
  254         mtx_lock(&mac_policy_mtx);
  255         if (!LIST_EMPTY(&mac_policy_list)) {
  256                 mac_policy_count++;
  257                 ret = 1;
  258         } else
  259                 ret = 0;
  260         mtx_unlock(&mac_policy_mtx);
  261         return (ret);
  262 #else
  263         if (!mac_late)
  264                 return (1);
  265 
  266         return (1);
  267 #endif
  268 }
  269 
  270 void
  271 mac_policy_list_unbusy(void)
  272 {
  273 
  274 #ifndef MAC_STATIC
  275         if (!mac_late)
  276                 return;
  277 
  278         mtx_lock(&mac_policy_mtx);
  279         mac_policy_count--;
  280         KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK"));
  281         if (mac_policy_count == 0)
  282                 cv_signal(&mac_policy_cv);
  283         mtx_unlock(&mac_policy_mtx);
  284 #endif
  285 }
  286 
  287 /*
  288  * Initialize the MAC subsystem, including appropriate SMP locks.
  289  */
  290 static void
  291 mac_init(void)
  292 {
  293 
  294         LIST_INIT(&mac_static_policy_list);
  295         LIST_INIT(&mac_policy_list);
  296         mac_labelzone_init();
  297 
  298 #ifndef MAC_STATIC
  299         mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF);
  300         cv_init(&mac_policy_cv, "mac_policy_cv");
  301 #endif
  302 }
  303 
  304 /*
  305  * For the purposes of modules that want to know if they were loaded
  306  * "early", set the mac_late flag once we've processed modules either
  307  * linked into the kernel, or loaded before the kernel startup.
  308  */
  309 static void
  310 mac_late_init(void)
  311 {
  312 
  313         mac_late = 1;
  314 }
  315 
  316 /*
  317  * After the policy list has changed, walk the list to update any global
  318  * flags.  Currently, we support only one flag, and it's conditionally
  319  * defined; as a result, the entire function is conditional.  Eventually,
  320  * the #else case might also iterate across the policies.
  321  */
  322 static void
  323 mac_policy_updateflags(void)
  324 {
  325 #ifndef MAC_ALWAYS_LABEL_MBUF
  326         struct mac_policy_conf *tmpc;
  327         int labelmbufs;
  328 
  329         mac_policy_assert_exclusive();
  330 
  331         labelmbufs = 0;
  332         LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) {
  333                 if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
  334                         labelmbufs++;
  335         }
  336         LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
  337                 if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
  338                         labelmbufs++;
  339         }
  340         mac_labelmbufs = (labelmbufs != 0);
  341 #endif
  342 }
  343 
  344 /*
  345  * Allow MAC policy modules to register during boot, etc.
  346  */
  347 int
  348 mac_policy_modevent(module_t mod, int type, void *data)
  349 {
  350         struct mac_policy_conf *mpc;
  351         int error;
  352 
  353         error = 0;
  354         mpc = (struct mac_policy_conf *) data;
  355 
  356 #ifdef MAC_STATIC
  357         if (mac_late) {
  358                 printf("mac_policy_modevent: MAC_STATIC and late\n");
  359                 return (EBUSY);
  360         }
  361 #endif
  362 
  363         switch (type) {
  364         case MOD_LOAD:
  365                 if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE &&
  366                     mac_late) {
  367                         printf("mac_policy_modevent: can't load %s policy "
  368                             "after booting\n", mpc->mpc_name);
  369                         error = EBUSY;
  370                         break;
  371                 }
  372                 error = mac_policy_register(mpc);
  373                 break;
  374         case MOD_UNLOAD:
  375                 /* Don't unregister the module if it was never registered. */
  376                 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED)
  377                     != 0)
  378                         error = mac_policy_unregister(mpc);
  379                 else
  380                         error = 0;
  381                 break;
  382         default:
  383                 error = EOPNOTSUPP;
  384                 break;
  385         }
  386 
  387         return (error);
  388 }
  389 
  390 static int
  391 mac_policy_register(struct mac_policy_conf *mpc)
  392 {
  393         struct mac_policy_conf *tmpc;
  394         int error, slot, static_entry;
  395 
  396         error = 0;
  397 
  398         /*
  399          * We don't technically need exclusive access while !mac_late,
  400          * but hold it for assertion consistency.
  401          */
  402         mac_policy_grab_exclusive();
  403 
  404         /*
  405          * If the module can potentially be unloaded, or we're loading
  406          * late, we have to stick it in the non-static list and pay
  407          * an extra performance overhead.  Otherwise, we can pay a
  408          * light locking cost and stick it in the static list.
  409          */
  410         static_entry = (!mac_late &&
  411             !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK));
  412 
  413         if (static_entry) {
  414                 LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) {
  415                         if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
  416                                 error = EEXIST;
  417                                 goto out;
  418                         }
  419                 }
  420         } else {
  421                 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
  422                         if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
  423                                 error = EEXIST;
  424                                 goto out;
  425                         }
  426                 }
  427         }
  428         if (mpc->mpc_field_off != NULL) {
  429                 slot = ffs(mac_slot_offsets_free);
  430                 if (slot == 0) {
  431                         error = ENOMEM;
  432                         goto out;
  433                 }
  434                 slot--;
  435                 mac_slot_offsets_free &= ~(1 << slot);
  436                 *mpc->mpc_field_off = slot;
  437         }
  438         mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED;
  439 
  440         /*
  441          * If we're loading a MAC module after the framework has
  442          * initialized, it has to go into the dynamic list.  If
  443          * we're loading it before we've finished initializing,
  444          * it can go into the static list with weaker locker
  445          * requirements.
  446          */
  447         if (static_entry)
  448                 LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list);
  449         else
  450                 LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list);
  451 
  452         /* Per-policy initialization. */
  453         if (mpc->mpc_ops->mpo_init != NULL)
  454                 (*(mpc->mpc_ops->mpo_init))(mpc);
  455         mac_policy_updateflags();
  456 
  457         printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
  458             mpc->mpc_name);
  459 
  460 out:
  461         mac_policy_release_exclusive();
  462         return (error);
  463 }
  464 
  465 static int
  466 mac_policy_unregister(struct mac_policy_conf *mpc)
  467 {
  468 
  469         /*
  470          * If we fail the load, we may get a request to unload.  Check
  471          * to see if we did the run-time registration, and if not,
  472          * silently succeed.
  473          */
  474         mac_policy_grab_exclusive();
  475         if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) {
  476                 mac_policy_release_exclusive();
  477                 return (0);
  478         }
  479 #if 0
  480         /*
  481          * Don't allow unloading modules with private data.
  482          */
  483         if (mpc->mpc_field_off != NULL) {
  484                 MAC_POLICY_LIST_UNLOCK();
  485                 return (EBUSY);
  486         }
  487 #endif
  488         /*
  489          * Only allow the unload to proceed if the module is unloadable
  490          * by its own definition.
  491          */
  492         if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) {
  493                 mac_policy_release_exclusive();
  494                 return (EBUSY);
  495         }
  496         if (mpc->mpc_ops->mpo_destroy != NULL)
  497                 (*(mpc->mpc_ops->mpo_destroy))(mpc);
  498 
  499         LIST_REMOVE(mpc, mpc_list);
  500         mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
  501         mac_policy_updateflags();
  502 
  503         mac_policy_release_exclusive();
  504 
  505         printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
  506             mpc->mpc_name);
  507 
  508         return (0);
  509 }
  510 
  511 /*
  512  * Define an error value precedence, and given two arguments, selects the
  513  * value with the higher precedence.
  514  */
  515 int
  516 mac_error_select(int error1, int error2)
  517 {
  518 
  519         /* Certain decision-making errors take top priority. */
  520         if (error1 == EDEADLK || error2 == EDEADLK)
  521                 return (EDEADLK);
  522 
  523         /* Invalid arguments should be reported where possible. */
  524         if (error1 == EINVAL || error2 == EINVAL)
  525                 return (EINVAL);
  526 
  527         /* Precedence goes to "visibility", with both process and file. */
  528         if (error1 == ESRCH || error2 == ESRCH)
  529                 return (ESRCH);
  530 
  531         if (error1 == ENOENT || error2 == ENOENT)
  532                 return (ENOENT);
  533 
  534         /* Precedence goes to DAC/MAC protections. */
  535         if (error1 == EACCES || error2 == EACCES)
  536                 return (EACCES);
  537 
  538         /* Precedence goes to privilege. */
  539         if (error1 == EPERM || error2 == EPERM)
  540                 return (EPERM);
  541 
  542         /* Precedence goes to error over success; otherwise, arbitrary. */
  543         if (error1 != 0)
  544                 return (error1);
  545         return (error2);
  546 }
  547 
  548 void
  549 mac_init_label(struct label *label)
  550 {
  551 
  552         bzero(label, sizeof(*label));
  553         label->l_flags = MAC_FLAG_INITIALIZED;
  554 }
  555 
  556 void
  557 mac_destroy_label(struct label *label)
  558 {
  559 
  560         KASSERT(label->l_flags & MAC_FLAG_INITIALIZED,
  561             ("destroying uninitialized label"));
  562 
  563         bzero(label, sizeof(*label));
  564         /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */
  565 }
  566 
  567 int
  568 mac_check_structmac_consistent(struct mac *mac)
  569 {
  570 
  571         if (mac->m_buflen < 0 ||
  572             mac->m_buflen > MAC_MAX_LABEL_BUF_LEN)
  573                 return (EINVAL);
  574 
  575         return (0);
  576 }
  577 
  578 /*
  579  * MPSAFE
  580  */
  581 int
  582 __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
  583 {
  584         char *elements, *buffer;
  585         struct mac mac;
  586         struct proc *tproc;
  587         struct ucred *tcred;
  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         tproc = pfind(uap->pid);
  599         if (tproc == NULL)
  600                 return (ESRCH);
  601 
  602         tcred = NULL;                           /* Satisfy gcc. */
  603         error = p_cansee(td, tproc);
  604         if (error == 0)
  605                 tcred = crhold(tproc->p_ucred);
  606         PROC_UNLOCK(tproc);
  607         if (error)
  608                 return (error);
  609 
  610         elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
  611         error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
  612         if (error) {
  613                 free(elements, M_MACTEMP);
  614                 crfree(tcred);
  615                 return (error);
  616         }
  617 
  618         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
  619         error = mac_externalize_cred_label(tcred->cr_label, elements,
  620             buffer, mac.m_buflen);
  621         if (error == 0)
  622                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
  623 
  624         free(buffer, M_MACTEMP);
  625         free(elements, M_MACTEMP);
  626         crfree(tcred);
  627         return (error);
  628 }
  629 
  630 /*
  631  * MPSAFE
  632  */
  633 int
  634 __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
  635 {
  636         char *elements, *buffer;
  637         struct mac mac;
  638         int error;
  639 
  640         error = copyin(uap->mac_p, &mac, sizeof(mac));
  641         if (error)
  642                 return (error);
  643 
  644         error = mac_check_structmac_consistent(&mac);
  645         if (error)
  646                 return (error);
  647 
  648         elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
  649         error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
  650         if (error) {
  651                 free(elements, M_MACTEMP);
  652                 return (error);
  653         }
  654 
  655         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
  656         error = mac_externalize_cred_label(td->td_ucred->cr_label,
  657             elements, buffer, mac.m_buflen);
  658         if (error == 0)
  659                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
  660 
  661         free(buffer, M_MACTEMP);
  662         free(elements, M_MACTEMP);
  663         return (error);
  664 }
  665 
  666 /*
  667  * MPSAFE
  668  */
  669 int
  670 __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
  671 {
  672         struct ucred *newcred, *oldcred;
  673         struct label *intlabel;
  674         struct proc *p;
  675         struct mac mac;
  676         char *buffer;
  677         int error;
  678 
  679         error = copyin(uap->mac_p, &mac, sizeof(mac));
  680         if (error)
  681                 return (error);
  682 
  683         error = mac_check_structmac_consistent(&mac);
  684         if (error)
  685                 return (error);
  686 
  687         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
  688         error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
  689         if (error) {
  690                 free(buffer, M_MACTEMP);
  691                 return (error);
  692         }
  693 
  694         intlabel = mac_cred_label_alloc();
  695         error = mac_internalize_cred_label(intlabel, buffer);
  696         free(buffer, M_MACTEMP);
  697         if (error)
  698                 goto out;
  699 
  700         newcred = crget();
  701 
  702         p = td->td_proc;
  703         PROC_LOCK(p);
  704         oldcred = p->p_ucred;
  705 
  706         error = mac_check_cred_relabel(oldcred, intlabel);
  707         if (error) {
  708                 PROC_UNLOCK(p);
  709                 crfree(newcred);
  710                 goto out;
  711         }
  712 
  713         setsugid(p);
  714         crcopy(newcred, oldcred);
  715         mac_relabel_cred(newcred, intlabel);
  716         p->p_ucred = newcred;
  717 
  718         /*
  719          * Grab additional reference for use while revoking mmaps, prior
  720          * to releasing the proc lock and sharing the cred.
  721          */
  722         crhold(newcred);
  723         PROC_UNLOCK(p);
  724 
  725         if (mac_enforce_vm) {
  726                 mtx_lock(&Giant);
  727                 mac_cred_mmapped_drop_perms(td, newcred);
  728                 mtx_unlock(&Giant);
  729         }
  730 
  731         crfree(newcred);        /* Free revocation reference. */
  732         crfree(oldcred);
  733 
  734 out:
  735         mac_cred_label_free(intlabel);
  736         return (error);
  737 }
  738 
  739 /*
  740  * MPSAFE
  741  */
  742 int
  743 __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
  744 {
  745         char *elements, *buffer;
  746         struct label *intlabel;
  747         struct file *fp;
  748         struct mac mac;
  749         struct vnode *vp;
  750         struct pipe *pipe;
  751         struct socket *so;
  752         short label_type;
  753         int error;
  754 
  755         error = copyin(uap->mac_p, &mac, sizeof(mac));
  756         if (error)
  757                 return (error);
  758 
  759         error = mac_check_structmac_consistent(&mac);
  760         if (error)
  761                 return (error);
  762 
  763         elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
  764         error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
  765         if (error) {
  766                 free(elements, M_MACTEMP);
  767                 return (error);
  768         }
  769 
  770         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
  771         error = fget(td, uap->fd, &fp);
  772         if (error)
  773                 goto out;
  774 
  775         label_type = fp->f_type;
  776         switch (fp->f_type) {
  777         case DTYPE_FIFO:
  778         case DTYPE_VNODE:
  779                 vp = fp->f_vnode;
  780                 intlabel = mac_vnode_label_alloc();
  781                 mtx_lock(&Giant);                               /* VFS */
  782                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
  783                 mac_copy_vnode_label(vp->v_label, intlabel);
  784                 VOP_UNLOCK(vp, 0, td);
  785                 mtx_unlock(&Giant);                             /* VFS */
  786                 error = mac_externalize_vnode_label(intlabel, elements,
  787                     buffer, mac.m_buflen);
  788                 mac_vnode_label_free(intlabel);
  789                 break;
  790 
  791         case DTYPE_PIPE:
  792                 pipe = fp->f_data;
  793                 intlabel = mac_pipe_label_alloc();
  794                 PIPE_LOCK(pipe);
  795                 mac_copy_pipe_label(pipe->pipe_pair->pp_label, intlabel);
  796                 PIPE_UNLOCK(pipe);
  797                 error = mac_externalize_pipe_label(intlabel, elements,
  798                     buffer, mac.m_buflen);
  799                 mac_pipe_label_free(intlabel);
  800                 break;
  801 
  802         case DTYPE_SOCKET:
  803                 so = fp->f_data;
  804                 intlabel = mac_socket_label_alloc(M_WAITOK);
  805                 mtx_lock(&Giant);                               /* Sockets */
  806                 /* XXX: Socket lock here. */
  807                 mac_copy_socket_label(so->so_label, intlabel);
  808                 /* XXX: Socket unlock here. */
  809                 mtx_unlock(&Giant);                             /* Sockets */
  810                 error = mac_externalize_socket_label(intlabel, elements,
  811                     buffer, mac.m_buflen);
  812                 mac_socket_label_free(intlabel);
  813                 break;
  814 
  815         default:
  816                 error = EINVAL;
  817         }
  818         fdrop(fp, td);
  819         if (error == 0)
  820                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
  821 
  822 out:
  823         free(buffer, M_MACTEMP);
  824         free(elements, M_MACTEMP);
  825         return (error);
  826 }
  827 
  828 /*
  829  * MPSAFE
  830  */
  831 int
  832 __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
  833 {
  834         char *elements, *buffer;
  835         struct nameidata nd;
  836         struct label *intlabel;
  837         struct mac mac;
  838         int error;
  839 
  840         error = copyin(uap->mac_p, &mac, sizeof(mac));
  841         if (error)
  842                 return (error);
  843 
  844         error = mac_check_structmac_consistent(&mac);
  845         if (error)
  846                 return (error);
  847 
  848         elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
  849         error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
  850         if (error) {
  851                 free(elements, M_MACTEMP);
  852                 return (error);
  853         }
  854 
  855         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
  856         mtx_lock(&Giant);                               /* VFS */
  857         NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
  858             td);
  859         error = namei(&nd);
  860         if (error)
  861                 goto out;
  862 
  863         intlabel = mac_vnode_label_alloc();
  864         mac_copy_vnode_label(nd.ni_vp->v_label, intlabel);
  865         error = mac_externalize_vnode_label(intlabel, elements, buffer,
  866             mac.m_buflen);
  867 
  868         NDFREE(&nd, 0);
  869         mac_vnode_label_free(intlabel);
  870 
  871         if (error == 0)
  872                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
  873 
  874 out:
  875         mtx_unlock(&Giant);                             /* VFS */
  876 
  877         free(buffer, M_MACTEMP);
  878         free(elements, M_MACTEMP);
  879 
  880         return (error);
  881 }
  882 
  883 /*
  884  * MPSAFE
  885  */
  886 int
  887 __mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
  888 {
  889         char *elements, *buffer;
  890         struct nameidata nd;
  891         struct label *intlabel;
  892         struct mac mac;
  893         int error;
  894 
  895         error = copyin(uap->mac_p, &mac, sizeof(mac));
  896         if (error)
  897                 return (error);
  898 
  899         error = mac_check_structmac_consistent(&mac);
  900         if (error)
  901                 return (error);
  902 
  903         elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
  904         error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
  905         if (error) {
  906                 free(elements, M_MACTEMP);
  907                 return (error);
  908         }
  909 
  910         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
  911         mtx_lock(&Giant);                               /* VFS */
  912         NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
  913             td);
  914         error = namei(&nd);
  915         if (error)
  916                 goto out;
  917 
  918         intlabel = mac_vnode_label_alloc();
  919         mac_copy_vnode_label(nd.ni_vp->v_label, intlabel);
  920         error = mac_externalize_vnode_label(intlabel, elements, buffer,
  921             mac.m_buflen);
  922         NDFREE(&nd, 0);
  923         mac_vnode_label_free(intlabel);
  924 
  925         if (error == 0)
  926                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
  927 
  928 out:
  929         mtx_unlock(&Giant);                             /* VFS */
  930 
  931         free(buffer, M_MACTEMP);
  932         free(elements, M_MACTEMP);
  933 
  934         return (error);
  935 }
  936 
  937 /*
  938  * MPSAFE
  939  */
  940 int
  941 __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
  942 {
  943         struct label *intlabel;
  944         struct pipe *pipe;
  945         struct socket *so;
  946         struct file *fp;
  947         struct mount *mp;
  948         struct vnode *vp;
  949         struct mac mac;
  950         char *buffer;
  951         int error;
  952 
  953         error = copyin(uap->mac_p, &mac, sizeof(mac));
  954         if (error)
  955                 return (error);
  956 
  957         error = mac_check_structmac_consistent(&mac);
  958         if (error)
  959                 return (error);
  960 
  961         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
  962         error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
  963         if (error) {
  964                 free(buffer, M_MACTEMP);
  965                 return (error);
  966         }
  967 
  968         error = fget(td, uap->fd, &fp);
  969         if (error)
  970                 goto out;
  971 
  972         switch (fp->f_type) {
  973         case DTYPE_FIFO:
  974         case DTYPE_VNODE:
  975                 intlabel = mac_vnode_label_alloc();
  976                 error = mac_internalize_vnode_label(intlabel, buffer);
  977                 if (error) {
  978                         mac_vnode_label_free(intlabel);
  979                         break;
  980                 }
  981                 vp = fp->f_vnode;
  982                 mtx_lock(&Giant);                               /* VFS */
  983                 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
  984                 if (error != 0) {
  985                         mtx_unlock(&Giant);                     /* VFS */
  986                         mac_vnode_label_free(intlabel);
  987                         break;
  988                 }
  989                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
  990                 error = vn_setlabel(vp, intlabel, td->td_ucred);
  991                 VOP_UNLOCK(vp, 0, td);
  992                 vn_finished_write(mp);
  993                 mtx_unlock(&Giant);                             /* VFS */
  994                 mac_vnode_label_free(intlabel);
  995                 break;
  996 
  997         case DTYPE_PIPE:
  998                 intlabel = mac_pipe_label_alloc();
  999                 error = mac_internalize_pipe_label(intlabel, buffer);
 1000                 if (error == 0) {
 1001                         pipe = fp->f_data;
 1002                         PIPE_LOCK(pipe);
 1003                         error = mac_pipe_label_set(td->td_ucred,
 1004                             pipe->pipe_pair, intlabel);
 1005                         PIPE_UNLOCK(pipe);
 1006                 }
 1007                 mac_pipe_label_free(intlabel);
 1008                 break;
 1009 
 1010         case DTYPE_SOCKET:
 1011                 intlabel = mac_socket_label_alloc(M_WAITOK);
 1012                 error = mac_internalize_socket_label(intlabel, buffer);
 1013                 if (error == 0) {
 1014                         so = fp->f_data;
 1015                         mtx_lock(&Giant);                       /* Sockets */
 1016                         /* XXX: Socket lock here. */
 1017                         error = mac_socket_label_set(td->td_ucred, so,
 1018                             intlabel);
 1019                         /* XXX: Socket unlock here. */
 1020                         mtx_unlock(&Giant);                     /* Sockets */
 1021                 }
 1022                 mac_socket_label_free(intlabel);
 1023                 break;
 1024 
 1025         default:
 1026                 error = EINVAL;
 1027         }
 1028         fdrop(fp, td);
 1029 out:
 1030         free(buffer, M_MACTEMP);
 1031         return (error);
 1032 }
 1033 
 1034 /*
 1035  * MPSAFE
 1036  */
 1037 int
 1038 __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
 1039 {
 1040         struct label *intlabel;
 1041         struct nameidata nd;
 1042         struct mount *mp;
 1043         struct mac mac;
 1044         char *buffer;
 1045         int error;
 1046 
 1047         error = copyin(uap->mac_p, &mac, sizeof(mac));
 1048         if (error)
 1049                 return (error);
 1050 
 1051         error = mac_check_structmac_consistent(&mac);
 1052         if (error)
 1053                 return (error);
 1054 
 1055         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
 1056         error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
 1057         if (error) {
 1058                 free(buffer, M_MACTEMP);
 1059                 return (error);
 1060         }
 1061 
 1062         intlabel = mac_vnode_label_alloc();
 1063         error = mac_internalize_vnode_label(intlabel, buffer);
 1064         free(buffer, M_MACTEMP);
 1065         if (error)
 1066                 goto out;
 1067 
 1068         mtx_lock(&Giant);                               /* VFS */
 1069 
 1070         NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
 1071             td);
 1072         error = namei(&nd);
 1073         if (error == 0) {
 1074                 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
 1075                 if (error == 0)
 1076                         error = vn_setlabel(nd.ni_vp, intlabel,
 1077                             td->td_ucred);
 1078                 vn_finished_write(mp);
 1079         }
 1080 
 1081         NDFREE(&nd, 0);
 1082         mtx_unlock(&Giant);                             /* VFS */
 1083 out:
 1084         mac_vnode_label_free(intlabel);
 1085         return (error);
 1086 }
 1087 
 1088 /*
 1089  * MPSAFE
 1090  */
 1091 int
 1092 __mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
 1093 {
 1094         struct label *intlabel;
 1095         struct nameidata nd;
 1096         struct mount *mp;
 1097         struct mac mac;
 1098         char *buffer;
 1099         int error;
 1100 
 1101         error = copyin(uap->mac_p, &mac, sizeof(mac));
 1102         if (error)
 1103                 return (error);
 1104 
 1105         error = mac_check_structmac_consistent(&mac);
 1106         if (error)
 1107                 return (error);
 1108 
 1109         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
 1110         error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
 1111         if (error) {
 1112                 free(buffer, M_MACTEMP);
 1113                 return (error);
 1114         }
 1115 
 1116         intlabel = mac_vnode_label_alloc();
 1117         error = mac_internalize_vnode_label(intlabel, buffer);
 1118         free(buffer, M_MACTEMP);
 1119         if (error)
 1120                 goto out;
 1121 
 1122         mtx_lock(&Giant);                               /* VFS */
 1123 
 1124         NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
 1125             td);
 1126         error = namei(&nd);
 1127         if (error == 0) {
 1128                 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
 1129                 if (error == 0)
 1130                         error = vn_setlabel(nd.ni_vp, intlabel,
 1131                             td->td_ucred);
 1132                 vn_finished_write(mp);
 1133         }
 1134 
 1135         NDFREE(&nd, 0);
 1136         mtx_unlock(&Giant);                             /* VFS */
 1137 out:
 1138         mac_vnode_label_free(intlabel);
 1139         return (error);
 1140 }
 1141 
 1142 /*
 1143  * MPSAFE
 1144  */
 1145 int
 1146 mac_syscall(struct thread *td, struct mac_syscall_args *uap)
 1147 {
 1148         struct mac_policy_conf *mpc;
 1149         char target[MAC_MAX_POLICY_NAME];
 1150         int entrycount, error;
 1151 
 1152         error = copyinstr(uap->policy, target, sizeof(target), NULL);
 1153         if (error)
 1154                 return (error);
 1155 
 1156         error = ENOSYS;
 1157         LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {
 1158                 if (strcmp(mpc->mpc_name, target) == 0 &&
 1159                     mpc->mpc_ops->mpo_syscall != NULL) {
 1160                         error = mpc->mpc_ops->mpo_syscall(td,
 1161                             uap->call, uap->arg);
 1162                         goto out;
 1163                 }
 1164         }
 1165 
 1166         if ((entrycount = mac_policy_list_conditional_busy()) != 0) {
 1167                 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
 1168                         if (strcmp(mpc->mpc_name, target) == 0 &&
 1169                             mpc->mpc_ops->mpo_syscall != NULL) {
 1170                                 error = mpc->mpc_ops->mpo_syscall(td,
 1171                                     uap->call, uap->arg);
 1172                                 break;
 1173                         }
 1174                 }
 1175                 mac_policy_list_unbusy();
 1176         }
 1177 out:
 1178         return (error);
 1179 }
 1180 
 1181 SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
 1182 SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
 1183 
 1184 #else /* !MAC */
 1185 
 1186 int
 1187 __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
 1188 {
 1189 
 1190         return (ENOSYS);
 1191 }
 1192 
 1193 int
 1194 __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
 1195 {
 1196 
 1197         return (ENOSYS);
 1198 }
 1199 
 1200 int
 1201 __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
 1202 {
 1203 
 1204         return (ENOSYS);
 1205 }
 1206 
 1207 int
 1208 __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
 1209 {
 1210 
 1211         return (ENOSYS);
 1212 }
 1213 
 1214 int
 1215 __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
 1216 {
 1217 
 1218         return (ENOSYS);
 1219 }
 1220 
 1221 int
 1222 __mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
 1223 {
 1224 
 1225         return (ENOSYS);
 1226 }
 1227 
 1228 int
 1229 __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
 1230 {
 1231 
 1232         return (ENOSYS);
 1233 }
 1234 
 1235 int
 1236 __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
 1237 {
 1238 
 1239         return (ENOSYS);
 1240 }
 1241 
 1242 int
 1243 __mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
 1244 {
 1245 
 1246         return (ENOSYS);
 1247 }
 1248 
 1249 int
 1250 mac_syscall(struct thread *td, struct mac_syscall_args *uap)
 1251 {
 1252 
 1253         return (ENOSYS);
 1254 }
 1255 
 1256 #endif /* !MAC */

Cache object: 3d905331dfb77d0d08b00decad7d50e3


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.