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

Cache object: b06e15d96f8541a2b4343d512e9b8a78


[ 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.