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

Cache object: 80be6e71ffdc3821d90ca4b08c5d22df


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