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.1/sys/kern/kern_mac.c 158179 2006-04-30 16:44:43Z cvs2svn $");
   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                 mac_cred_mmapped_drop_perms(td, newcred);
  728         }
  729 
  730         crfree(newcred);        /* Free revocation reference. */
  731         crfree(oldcred);
  732 
  733 out:
  734         mac_cred_label_free(intlabel);
  735         return (error);
  736 }
  737 
  738 /*
  739  * MPSAFE
  740  */
  741 int
  742 __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
  743 {
  744         char *elements, *buffer;
  745         struct label *intlabel;
  746         struct file *fp;
  747         struct mac mac;
  748         struct vnode *vp;
  749         struct pipe *pipe;
  750         struct socket *so;
  751         short label_type;
  752         int vfslocked, error;
  753 
  754         error = copyin(uap->mac_p, &mac, sizeof(mac));
  755         if (error)
  756                 return (error);
  757 
  758         error = mac_check_structmac_consistent(&mac);
  759         if (error)
  760                 return (error);
  761 
  762         elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
  763         error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
  764         if (error) {
  765                 free(elements, M_MACTEMP);
  766                 return (error);
  767         }
  768 
  769         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
  770         error = fget(td, uap->fd, &fp);
  771         if (error)
  772                 goto out;
  773 
  774         label_type = fp->f_type;
  775         switch (fp->f_type) {
  776         case DTYPE_FIFO:
  777         case DTYPE_VNODE:
  778                 vp = fp->f_vnode;
  779                 intlabel = mac_vnode_label_alloc();
  780                 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
  781                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
  782                 mac_copy_vnode_label(vp->v_label, intlabel);
  783                 VOP_UNLOCK(vp, 0, td);
  784                 VFS_UNLOCK_GIANT(vfslocked);
  785                 error = mac_externalize_vnode_label(intlabel, elements,
  786                     buffer, mac.m_buflen);
  787                 mac_vnode_label_free(intlabel);
  788                 break;
  789 
  790         case DTYPE_PIPE:
  791                 pipe = fp->f_data;
  792                 intlabel = mac_pipe_label_alloc();
  793                 PIPE_LOCK(pipe);
  794                 mac_copy_pipe_label(pipe->pipe_pair->pp_label, intlabel);
  795                 PIPE_UNLOCK(pipe);
  796                 error = mac_externalize_pipe_label(intlabel, elements,
  797                     buffer, mac.m_buflen);
  798                 mac_pipe_label_free(intlabel);
  799                 break;
  800 
  801         case DTYPE_SOCKET:
  802                 so = fp->f_data;
  803                 intlabel = mac_socket_label_alloc(M_WAITOK);
  804                 NET_LOCK_GIANT();
  805                 SOCK_LOCK(so);
  806                 mac_copy_socket_label(so->so_label, intlabel);
  807                 SOCK_UNLOCK(so);
  808                 NET_UNLOCK_GIANT();
  809                 error = mac_externalize_socket_label(intlabel, elements,
  810                     buffer, mac.m_buflen);
  811                 mac_socket_label_free(intlabel);
  812                 break;
  813 
  814         default:
  815                 error = EINVAL;
  816         }
  817         fdrop(fp, td);
  818         if (error == 0)
  819                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
  820 
  821 out:
  822         free(buffer, M_MACTEMP);
  823         free(elements, M_MACTEMP);
  824         return (error);
  825 }
  826 
  827 /*
  828  * MPSAFE
  829  */
  830 int
  831 __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
  832 {
  833         char *elements, *buffer;
  834         struct nameidata nd;
  835         struct label *intlabel;
  836         struct mac mac;
  837         int vfslocked, error;
  838 
  839         error = copyin(uap->mac_p, &mac, sizeof(mac));
  840         if (error)
  841                 return (error);
  842 
  843         error = mac_check_structmac_consistent(&mac);
  844         if (error)
  845                 return (error);
  846 
  847         elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
  848         error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
  849         if (error) {
  850                 free(elements, M_MACTEMP);
  851                 return (error);
  852         }
  853 
  854         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
  855         NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | FOLLOW, UIO_USERSPACE,
  856             uap->path_p, td);
  857         error = namei(&nd);
  858         if (error)
  859                 goto out;
  860 
  861         intlabel = mac_vnode_label_alloc();
  862         vfslocked = NDHASGIANT(&nd);
  863         mac_copy_vnode_label(nd.ni_vp->v_label, intlabel);
  864         error = mac_externalize_vnode_label(intlabel, elements, buffer,
  865             mac.m_buflen);
  866 
  867         NDFREE(&nd, 0);
  868         VFS_UNLOCK_GIANT(vfslocked);
  869         mac_vnode_label_free(intlabel);
  870         if (error == 0)
  871                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
  872 
  873 out:
  874         free(buffer, M_MACTEMP);
  875         free(elements, M_MACTEMP);
  876 
  877         return (error);
  878 }
  879 
  880 /*
  881  * MPSAFE
  882  */
  883 int
  884 __mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
  885 {
  886         char *elements, *buffer;
  887         struct nameidata nd;
  888         struct label *intlabel;
  889         struct mac mac;
  890         int vfslocked, error;
  891 
  892         error = copyin(uap->mac_p, &mac, sizeof(mac));
  893         if (error)
  894                 return (error);
  895 
  896         error = mac_check_structmac_consistent(&mac);
  897         if (error)
  898                 return (error);
  899 
  900         elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
  901         error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
  902         if (error) {
  903                 free(elements, M_MACTEMP);
  904                 return (error);
  905         }
  906 
  907         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
  908         NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | NOFOLLOW, UIO_USERSPACE,
  909             uap->path_p, td);
  910         error = namei(&nd);
  911         if (error)
  912                 goto out;
  913 
  914         intlabel = mac_vnode_label_alloc();
  915         vfslocked = NDHASGIANT(&nd);
  916         mac_copy_vnode_label(nd.ni_vp->v_label, intlabel);
  917         error = mac_externalize_vnode_label(intlabel, elements, buffer,
  918             mac.m_buflen);
  919         NDFREE(&nd, 0);
  920         VFS_UNLOCK_GIANT(vfslocked);
  921         mac_vnode_label_free(intlabel);
  922 
  923         if (error == 0)
  924                 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
  925 
  926 out:
  927         free(buffer, M_MACTEMP);
  928         free(elements, M_MACTEMP);
  929 
  930         return (error);
  931 }
  932 
  933 /*
  934  * MPSAFE
  935  */
  936 int
  937 __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
  938 {
  939         struct label *intlabel;
  940         struct pipe *pipe;
  941         struct socket *so;
  942         struct file *fp;
  943         struct mount *mp;
  944         struct vnode *vp;
  945         struct mac mac;
  946         char *buffer;
  947         int error, vfslocked;
  948 
  949         error = copyin(uap->mac_p, &mac, sizeof(mac));
  950         if (error)
  951                 return (error);
  952 
  953         error = mac_check_structmac_consistent(&mac);
  954         if (error)
  955                 return (error);
  956 
  957         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
  958         error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
  959         if (error) {
  960                 free(buffer, M_MACTEMP);
  961                 return (error);
  962         }
  963 
  964         error = fget(td, uap->fd, &fp);
  965         if (error)
  966                 goto out;
  967 
  968         switch (fp->f_type) {
  969         case DTYPE_FIFO:
  970         case DTYPE_VNODE:
  971                 intlabel = mac_vnode_label_alloc();
  972                 error = mac_internalize_vnode_label(intlabel, buffer);
  973                 if (error) {
  974                         mac_vnode_label_free(intlabel);
  975                         break;
  976                 }
  977                 vp = fp->f_vnode;
  978                 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
  979                 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
  980                 if (error != 0) {
  981                         VFS_UNLOCK_GIANT(vfslocked);
  982                         mac_vnode_label_free(intlabel);
  983                         break;
  984                 }
  985                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
  986                 error = vn_setlabel(vp, intlabel, td->td_ucred);
  987                 VOP_UNLOCK(vp, 0, td);
  988                 vn_finished_write(mp);
  989                 VFS_UNLOCK_GIANT(vfslocked);
  990                 mac_vnode_label_free(intlabel);
  991                 break;
  992 
  993         case DTYPE_PIPE:
  994                 intlabel = mac_pipe_label_alloc();
  995                 error = mac_internalize_pipe_label(intlabel, buffer);
  996                 if (error == 0) {
  997                         pipe = fp->f_data;
  998                         PIPE_LOCK(pipe);
  999                         error = mac_pipe_label_set(td->td_ucred,
 1000                             pipe->pipe_pair, intlabel);
 1001                         PIPE_UNLOCK(pipe);
 1002                 }
 1003                 mac_pipe_label_free(intlabel);
 1004                 break;
 1005 
 1006         case DTYPE_SOCKET:
 1007                 intlabel = mac_socket_label_alloc(M_WAITOK);
 1008                 error = mac_internalize_socket_label(intlabel, buffer);
 1009                 if (error == 0) {
 1010                         so = fp->f_data;
 1011                         NET_LOCK_GIANT();
 1012                         error = mac_socket_label_set(td->td_ucred, so,
 1013                             intlabel);
 1014                         NET_UNLOCK_GIANT();
 1015                 }
 1016                 mac_socket_label_free(intlabel);
 1017                 break;
 1018 
 1019         default:
 1020                 error = EINVAL;
 1021         }
 1022         fdrop(fp, td);
 1023 out:
 1024         free(buffer, M_MACTEMP);
 1025         return (error);
 1026 }
 1027 
 1028 /*
 1029  * MPSAFE
 1030  */
 1031 int
 1032 __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
 1033 {
 1034         struct label *intlabel;
 1035         struct nameidata nd;
 1036         struct mount *mp;
 1037         struct mac mac;
 1038         char *buffer;
 1039         int vfslocked, error;
 1040 
 1041         error = copyin(uap->mac_p, &mac, sizeof(mac));
 1042         if (error)
 1043                 return (error);
 1044 
 1045         error = mac_check_structmac_consistent(&mac);
 1046         if (error)
 1047                 return (error);
 1048 
 1049         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
 1050         error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
 1051         if (error) {
 1052                 free(buffer, M_MACTEMP);
 1053                 return (error);
 1054         }
 1055 
 1056         intlabel = mac_vnode_label_alloc();
 1057         error = mac_internalize_vnode_label(intlabel, buffer);
 1058         free(buffer, M_MACTEMP);
 1059         if (error)
 1060                 goto out;
 1061 
 1062         NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | FOLLOW, UIO_USERSPACE,
 1063             uap->path_p, td);
 1064         error = namei(&nd);
 1065         vfslocked = NDHASGIANT(&nd);
 1066         if (error == 0) {
 1067                 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
 1068                 if (error == 0) {
 1069                         error = vn_setlabel(nd.ni_vp, intlabel,
 1070                             td->td_ucred);
 1071                         vn_finished_write(mp);
 1072                 }
 1073         }
 1074 
 1075         NDFREE(&nd, 0);
 1076         VFS_UNLOCK_GIANT(vfslocked);
 1077 out:
 1078         mac_vnode_label_free(intlabel);
 1079         return (error);
 1080 }
 1081 
 1082 /*
 1083  * MPSAFE
 1084  */
 1085 int
 1086 __mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
 1087 {
 1088         struct label *intlabel;
 1089         struct nameidata nd;
 1090         struct mount *mp;
 1091         struct mac mac;
 1092         char *buffer;
 1093         int vfslocked, error;
 1094 
 1095         error = copyin(uap->mac_p, &mac, sizeof(mac));
 1096         if (error)
 1097                 return (error);
 1098 
 1099         error = mac_check_structmac_consistent(&mac);
 1100         if (error)
 1101                 return (error);
 1102 
 1103         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
 1104         error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
 1105         if (error) {
 1106                 free(buffer, M_MACTEMP);
 1107                 return (error);
 1108         }
 1109 
 1110         intlabel = mac_vnode_label_alloc();
 1111         error = mac_internalize_vnode_label(intlabel, buffer);
 1112         free(buffer, M_MACTEMP);
 1113         if (error)
 1114                 goto out;
 1115 
 1116         NDINIT(&nd, LOOKUP, MPSAFE | LOCKLEAF | NOFOLLOW, UIO_USERSPACE,
 1117             uap->path_p, td);
 1118         error = namei(&nd);
 1119         vfslocked = NDHASGIANT(&nd);
 1120         if (error == 0) {
 1121                 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
 1122                 if (error == 0) {
 1123                         error = vn_setlabel(nd.ni_vp, intlabel,
 1124                             td->td_ucred);
 1125                         vn_finished_write(mp);
 1126                 }
 1127         }
 1128 
 1129         NDFREE(&nd, 0);
 1130         VFS_UNLOCK_GIANT(vfslocked);
 1131 out:
 1132         mac_vnode_label_free(intlabel);
 1133         return (error);
 1134 }
 1135 
 1136 /*
 1137  * MPSAFE
 1138  */
 1139 int
 1140 mac_syscall(struct thread *td, struct mac_syscall_args *uap)
 1141 {
 1142         struct mac_policy_conf *mpc;
 1143         char target[MAC_MAX_POLICY_NAME];
 1144         int entrycount, error;
 1145 
 1146         error = copyinstr(uap->policy, target, sizeof(target), NULL);
 1147         if (error)
 1148                 return (error);
 1149 
 1150         error = ENOSYS;
 1151         LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {
 1152                 if (strcmp(mpc->mpc_name, target) == 0 &&
 1153                     mpc->mpc_ops->mpo_syscall != NULL) {
 1154                         error = mpc->mpc_ops->mpo_syscall(td,
 1155                             uap->call, uap->arg);
 1156                         goto out;
 1157                 }
 1158         }
 1159 
 1160         if ((entrycount = mac_policy_list_conditional_busy()) != 0) {
 1161                 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
 1162                         if (strcmp(mpc->mpc_name, target) == 0 &&
 1163                             mpc->mpc_ops->mpo_syscall != NULL) {
 1164                                 error = mpc->mpc_ops->mpo_syscall(td,
 1165                                     uap->call, uap->arg);
 1166                                 break;
 1167                         }
 1168                 }
 1169                 mac_policy_list_unbusy();
 1170         }
 1171 out:
 1172         return (error);
 1173 }
 1174 
 1175 SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
 1176 SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
 1177 
 1178 #else /* !MAC */
 1179 
 1180 int
 1181 __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
 1182 {
 1183 
 1184         return (ENOSYS);
 1185 }
 1186 
 1187 int
 1188 __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
 1189 {
 1190 
 1191         return (ENOSYS);
 1192 }
 1193 
 1194 int
 1195 __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
 1196 {
 1197 
 1198         return (ENOSYS);
 1199 }
 1200 
 1201 int
 1202 __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
 1203 {
 1204 
 1205         return (ENOSYS);
 1206 }
 1207 
 1208 int
 1209 __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
 1210 {
 1211 
 1212         return (ENOSYS);
 1213 }
 1214 
 1215 int
 1216 __mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
 1217 {
 1218 
 1219         return (ENOSYS);
 1220 }
 1221 
 1222 int
 1223 __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
 1224 {
 1225 
 1226         return (ENOSYS);
 1227 }
 1228 
 1229 int
 1230 __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
 1231 {
 1232 
 1233         return (ENOSYS);
 1234 }
 1235 
 1236 int
 1237 __mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
 1238 {
 1239 
 1240         return (ENOSYS);
 1241 }
 1242 
 1243 int
 1244 mac_syscall(struct thread *td, struct mac_syscall_args *uap)
 1245 {
 1246 
 1247         return (ENOSYS);
 1248 }
 1249 
 1250 #endif /* !MAC */

Cache object: bd1cb4638c59ef3e9f99dc7cfeb062e9


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