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/security/mac/mac_process.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-2003 Networks Associates Technology, Inc.
    5  * Copyright (c) 2005 Samy Al Bahra
    6  * All rights reserved.
    7  *
    8  * This software was developed by Robert Watson and Ilmar Habibulin for the
    9  * TrustedBSD Project.
   10  *
   11  * This software was developed for the FreeBSD Project in part by Network
   12  * Associates Laboratories, the Security Research Division of Network
   13  * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
   14  * as part of the DARPA CHATS research program.
   15  *
   16  * Redistribution and use in source and binary forms, with or without
   17  * modification, are permitted provided that the following conditions
   18  * are met:
   19  * 1. Redistributions of source code must retain the above copyright
   20  *    notice, this list of conditions and the following disclaimer.
   21  * 2. Redistributions in binary form must reproduce the above copyright
   22  *    notice, this list of conditions and the following disclaimer in the
   23  *    documentation and/or other materials provided with the distribution.
   24  *
   25  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   35  * SUCH DAMAGE.
   36  */
   37 
   38 #include <sys/cdefs.h>
   39 __FBSDID("$FreeBSD$");
   40 
   41 #include "opt_mac.h"
   42 
   43 #include <sys/param.h>
   44 #include <sys/condvar.h>
   45 #include <sys/imgact.h>
   46 #include <sys/kernel.h>
   47 #include <sys/lock.h>
   48 #include <sys/malloc.h>
   49 #include <sys/mutex.h>
   50 #include <sys/mac.h>
   51 #include <sys/proc.h>
   52 #include <sys/sbuf.h>
   53 #include <sys/systm.h>
   54 #include <sys/vnode.h>
   55 #include <sys/mount.h>
   56 #include <sys/file.h>
   57 #include <sys/namei.h>
   58 #include <sys/sysctl.h>
   59 
   60 #include <vm/vm.h>
   61 #include <vm/pmap.h>
   62 #include <vm/vm_map.h>
   63 #include <vm/vm_object.h>
   64 
   65 #include <security/mac/mac_framework.h>
   66 #include <security/mac/mac_internal.h>
   67 #include <security/mac/mac_policy.h>
   68 
   69 static int      mac_mmap_revocation = 1;
   70 SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW,
   71     &mac_mmap_revocation, 0, "Revoke mmap access to files on subject "
   72     "relabel");
   73 
   74 static int      mac_mmap_revocation_via_cow = 0;
   75 SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW,
   76     &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via "
   77     "copy-on-write semantics, or by removing all write access");
   78 
   79 static void     mac_cred_mmapped_drop_perms_recurse(struct thread *td,
   80                     struct ucred *cred, struct vm_map *map);
   81 
   82 struct label *
   83 mac_cred_label_alloc(void)
   84 {
   85         struct label *label;
   86 
   87         label = mac_labelzone_alloc(M_WAITOK);
   88         MAC_PERFORM(init_cred_label, label);
   89         return (label);
   90 }
   91 
   92 void
   93 mac_init_cred(struct ucred *cred)
   94 {
   95 
   96         cred->cr_label = mac_cred_label_alloc();
   97 }
   98 
   99 static struct label *
  100 mac_proc_label_alloc(void)
  101 {
  102         struct label *label;
  103 
  104         label = mac_labelzone_alloc(M_WAITOK);
  105         MAC_PERFORM(init_proc_label, label);
  106         return (label);
  107 }
  108 
  109 void
  110 mac_init_proc(struct proc *p)
  111 {
  112 
  113         p->p_label = mac_proc_label_alloc();
  114 }
  115 
  116 void
  117 mac_cred_label_free(struct label *label)
  118 {
  119 
  120         MAC_PERFORM(destroy_cred_label, label);
  121         mac_labelzone_free(label);
  122 }
  123 
  124 void
  125 mac_destroy_cred(struct ucred *cred)
  126 {
  127 
  128         mac_cred_label_free(cred->cr_label);
  129         cred->cr_label = NULL;
  130 }
  131 
  132 static void
  133 mac_proc_label_free(struct label *label)
  134 {
  135 
  136         MAC_PERFORM(destroy_proc_label, label);
  137         mac_labelzone_free(label);
  138 }
  139 
  140 void
  141 mac_destroy_proc(struct proc *p)
  142 {
  143 
  144         mac_proc_label_free(p->p_label);
  145         p->p_label = NULL;
  146 }
  147 
  148 int
  149 mac_externalize_cred_label(struct label *label, char *elements,
  150     char *outbuf, size_t outbuflen)
  151 {
  152         int error;
  153 
  154         MAC_EXTERNALIZE(cred, label, elements, outbuf, outbuflen);
  155 
  156         return (error);
  157 }
  158 
  159 int
  160 mac_internalize_cred_label(struct label *label, char *string)
  161 {
  162         int error;
  163 
  164         MAC_INTERNALIZE(cred, label, string);
  165 
  166         return (error);
  167 }
  168 
  169 /*
  170  * Initialize MAC label for the first kernel process, from which other kernel
  171  * processes and threads are spawned.
  172  */
  173 void
  174 mac_create_proc0(struct ucred *cred)
  175 {
  176 
  177         MAC_PERFORM(create_proc0, cred);
  178 }
  179 
  180 /*
  181  * Initialize MAC label for the first userland process, from which other
  182  * userland processes and threads are spawned.
  183  */
  184 void
  185 mac_create_proc1(struct ucred *cred)
  186 {
  187 
  188         MAC_PERFORM(create_proc1, cred);
  189 }
  190 
  191 void
  192 mac_thread_userret(struct thread *td)
  193 {
  194 
  195         MAC_PERFORM(thread_userret, td);
  196 }
  197 
  198 /*
  199  * When a new process is created, its label must be initialized.  Generally,
  200  * this involves inheritence from the parent process, modulo possible deltas.
  201  * This function allows that processing to take place.
  202  */
  203 void
  204 mac_copy_cred(struct ucred *src, struct ucred *dest)
  205 {
  206 
  207         MAC_PERFORM(copy_cred_label, src->cr_label, dest->cr_label);
  208 }
  209 
  210 int
  211 mac_execve_enter(struct image_params *imgp, struct mac *mac_p)
  212 {
  213         struct label *label;
  214         struct mac mac;
  215         char *buffer;
  216         int error;
  217 
  218         if (mac_p == NULL)
  219                 return (0);
  220 
  221         error = copyin(mac_p, &mac, sizeof(mac));
  222         if (error)
  223                 return (error);
  224 
  225         error = mac_check_structmac_consistent(&mac);
  226         if (error)
  227                 return (error);
  228 
  229         buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
  230         error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
  231         if (error) {
  232                 free(buffer, M_MACTEMP);
  233                 return (error);
  234         }
  235 
  236         label = mac_cred_label_alloc();
  237         error = mac_internalize_cred_label(label, buffer);
  238         free(buffer, M_MACTEMP);
  239         if (error) {
  240                 mac_cred_label_free(label);
  241                 return (error);
  242         }
  243         imgp->execlabel = label;
  244         return (0);
  245 }
  246 
  247 void
  248 mac_execve_exit(struct image_params *imgp)
  249 {
  250         if (imgp->execlabel != NULL) {
  251                 mac_cred_label_free(imgp->execlabel);
  252                 imgp->execlabel = NULL;
  253         }
  254 }
  255 
  256 /*
  257  * When relabeling a process, call out to the policies for the maximum
  258  * permission allowed for each object type we know about in its memory space,
  259  * and revoke access (in the least surprising ways we know) when necessary.
  260  * The process lock is not held here.
  261  */
  262 void
  263 mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred)
  264 {
  265 
  266         /* XXX freeze all other threads */
  267         mac_cred_mmapped_drop_perms_recurse(td, cred,
  268             &td->td_proc->p_vmspace->vm_map);
  269         /* XXX allow other threads to continue */
  270 }
  271 
  272 static __inline const char *
  273 prot2str(vm_prot_t prot)
  274 {
  275 
  276         switch (prot & VM_PROT_ALL) {
  277         case VM_PROT_READ:
  278                 return ("r--");
  279         case VM_PROT_READ | VM_PROT_WRITE:
  280                 return ("rw-");
  281         case VM_PROT_READ | VM_PROT_EXECUTE:
  282                 return ("r-x");
  283         case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
  284                 return ("rwx");
  285         case VM_PROT_WRITE:
  286                 return ("-w-");
  287         case VM_PROT_EXECUTE:
  288                 return ("--x");
  289         case VM_PROT_WRITE | VM_PROT_EXECUTE:
  290                 return ("-wx");
  291         default:
  292                 return ("---");
  293         }
  294 }
  295 
  296 static void
  297 mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred,
  298     struct vm_map *map)
  299 {
  300         struct vm_map_entry *vme;
  301         int vfslocked, result;
  302         vm_prot_t revokeperms;
  303         vm_object_t backing_object, object;
  304         vm_ooffset_t offset;
  305         struct vnode *vp;
  306         struct mount *mp;
  307 
  308         if (!mac_mmap_revocation)
  309                 return;
  310 
  311         vm_map_lock_read(map);
  312         for (vme = map->header.next; vme != &map->header; vme = vme->next) {
  313                 if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) {
  314                         mac_cred_mmapped_drop_perms_recurse(td, cred,
  315                             vme->object.sub_map);
  316                         continue;
  317                 }
  318                 /*
  319                  * Skip over entries that obviously are not shared.
  320                  */
  321                 if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) ||
  322                     !vme->max_protection)
  323                         continue;
  324                 /*
  325                  * Drill down to the deepest backing object.
  326                  */
  327                 offset = vme->offset;
  328                 object = vme->object.vm_object;
  329                 if (object == NULL)
  330                         continue;
  331                 VM_OBJECT_LOCK(object);
  332                 while ((backing_object = object->backing_object) != NULL) {
  333                         VM_OBJECT_LOCK(backing_object);
  334                         offset += object->backing_object_offset;
  335                         VM_OBJECT_UNLOCK(object);
  336                         object = backing_object;
  337                 }
  338                 VM_OBJECT_UNLOCK(object);
  339                 /*
  340                  * At the moment, vm_maps and objects aren't considered by
  341                  * the MAC system, so only things with backing by a normal
  342                  * object (read: vnodes) are checked.
  343                  */
  344                 if (object->type != OBJT_VNODE)
  345                         continue;
  346                 vp = (struct vnode *)object->handle;
  347                 vfslocked = VFS_LOCK_GIANT(vp->v_mount);
  348                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
  349                 result = vme->max_protection;
  350                 mac_check_vnode_mmap_downgrade(cred, vp, &result);
  351                 VOP_UNLOCK(vp, 0, td);
  352                 /*
  353                  * Find out what maximum protection we may be allowing now
  354                  * but a policy needs to get removed.
  355                  */
  356                 revokeperms = vme->max_protection & ~result;
  357                 if (!revokeperms) {
  358                         VFS_UNLOCK_GIANT(vfslocked);
  359                         continue;
  360                 }
  361                 printf("pid %ld: revoking %s perms from %#lx:%ld "
  362                     "(max %s/cur %s)\n", (long)td->td_proc->p_pid,
  363                     prot2str(revokeperms), (u_long)vme->start,
  364                     (long)(vme->end - vme->start),
  365                     prot2str(vme->max_protection), prot2str(vme->protection));
  366                 vm_map_lock_upgrade(map);
  367                 /*
  368                  * This is the really simple case: if a map has more
  369                  * max_protection than is allowed, but it's not being
  370                  * actually used (that is, the current protection is still
  371                  * allowed), we can just wipe it out and do nothing more.
  372                  */
  373                 if ((vme->protection & revokeperms) == 0) {
  374                         vme->max_protection -= revokeperms;
  375                 } else {
  376                         if (revokeperms & VM_PROT_WRITE) {
  377                                 /*
  378                                  * In the more complicated case, flush out all
  379                                  * pending changes to the object then turn it
  380                                  * copy-on-write.
  381                                  */
  382                                 vm_object_reference(object);
  383                                 (void) vn_start_write(vp, &mp, V_WAIT);
  384                                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
  385                                 VM_OBJECT_LOCK(object);
  386                                 vm_object_page_clean(object,
  387                                     OFF_TO_IDX(offset),
  388                                     OFF_TO_IDX(offset + vme->end - vme->start +
  389                                         PAGE_MASK),
  390                                     OBJPC_SYNC);
  391                                 VM_OBJECT_UNLOCK(object);
  392                                 VOP_UNLOCK(vp, 0, td);
  393                                 vn_finished_write(mp);
  394                                 vm_object_deallocate(object);
  395                                 /*
  396                                  * Why bother if there's no read permissions
  397                                  * anymore?  For the rest, we need to leave
  398                                  * the write permissions on for COW, or
  399                                  * remove them entirely if configured to.
  400                                  */
  401                                 if (!mac_mmap_revocation_via_cow) {
  402                                         vme->max_protection &= ~VM_PROT_WRITE;
  403                                         vme->protection &= ~VM_PROT_WRITE;
  404                                 } if ((revokeperms & VM_PROT_READ) == 0)
  405                                         vme->eflags |= MAP_ENTRY_COW |
  406                                             MAP_ENTRY_NEEDS_COPY;
  407                         }
  408                         if (revokeperms & VM_PROT_EXECUTE) {
  409                                 vme->max_protection &= ~VM_PROT_EXECUTE;
  410                                 vme->protection &= ~VM_PROT_EXECUTE;
  411                         }
  412                         if (revokeperms & VM_PROT_READ) {
  413                                 vme->max_protection = 0;
  414                                 vme->protection = 0;
  415                         }
  416                         pmap_protect(map->pmap, vme->start, vme->end,
  417                             vme->protection & ~revokeperms);
  418                         vm_map_simplify_entry(map, vme);
  419                 }
  420                 vm_map_lock_downgrade(map);
  421                 VFS_UNLOCK_GIANT(vfslocked);
  422         }
  423         vm_map_unlock_read(map);
  424 }
  425 
  426 /*
  427  * When the subject's label changes, it may require revocation of privilege
  428  * to mapped objects.  This can't be done on-the-fly later with a unified
  429  * buffer cache.
  430  */
  431 void
  432 mac_relabel_cred(struct ucred *cred, struct label *newlabel)
  433 {
  434 
  435         MAC_PERFORM(relabel_cred, cred, newlabel);
  436 }
  437 
  438 int
  439 mac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
  440 {
  441         int error;
  442 
  443         MAC_CHECK(check_cred_relabel, cred, newlabel);
  444 
  445         return (error);
  446 }
  447 
  448 int
  449 mac_check_cred_visible(struct ucred *cr1, struct ucred *cr2)
  450 {
  451         int error;
  452 
  453         MAC_CHECK(check_cred_visible, cr1, cr2);
  454 
  455         return (error);
  456 }
  457 
  458 int
  459 mac_check_proc_debug(struct ucred *cred, struct proc *p)
  460 {
  461         int error;
  462 
  463         PROC_LOCK_ASSERT(p, MA_OWNED);
  464 
  465         MAC_CHECK(check_proc_debug, cred, p);
  466 
  467         return (error);
  468 }
  469 
  470 int
  471 mac_check_proc_sched(struct ucred *cred, struct proc *p)
  472 {
  473         int error;
  474 
  475         PROC_LOCK_ASSERT(p, MA_OWNED);
  476 
  477         MAC_CHECK(check_proc_sched, cred, p);
  478 
  479         return (error);
  480 }
  481 
  482 int
  483 mac_check_proc_signal(struct ucred *cred, struct proc *p, int signum)
  484 {
  485         int error;
  486 
  487         PROC_LOCK_ASSERT(p, MA_OWNED);
  488 
  489         MAC_CHECK(check_proc_signal, cred, p, signum);
  490 
  491         return (error);
  492 }
  493 
  494 int
  495 mac_check_proc_setuid(struct proc *p, struct ucred *cred, uid_t uid)
  496 {
  497         int error;
  498 
  499         PROC_LOCK_ASSERT(p, MA_OWNED);
  500 
  501         MAC_CHECK(check_proc_setuid, cred, uid);
  502         return (error);
  503 }
  504 
  505 int
  506 mac_check_proc_seteuid(struct proc *p, struct ucred *cred, uid_t euid)
  507 {
  508         int error;
  509 
  510         PROC_LOCK_ASSERT(p, MA_OWNED);
  511 
  512         MAC_CHECK(check_proc_seteuid, cred, euid);
  513         return (error);
  514 }
  515 
  516 int
  517 mac_check_proc_setgid(struct proc *p, struct ucred *cred, gid_t gid)
  518 {
  519         int error;
  520 
  521         PROC_LOCK_ASSERT(p, MA_OWNED);
  522 
  523         MAC_CHECK(check_proc_setgid, cred, gid);
  524 
  525         return (error);
  526 }
  527 
  528 int
  529 mac_check_proc_setegid(struct proc *p, struct ucred *cred, gid_t egid)
  530 {
  531         int error;
  532 
  533         PROC_LOCK_ASSERT(p, MA_OWNED);
  534 
  535         MAC_CHECK(check_proc_setegid, cred, egid);
  536 
  537         return (error);
  538 }
  539 
  540 int
  541 mac_check_proc_setgroups(struct proc *p, struct ucred *cred, int ngroups,
  542     gid_t *gidset)
  543 {
  544         int error;
  545 
  546         PROC_LOCK_ASSERT(p, MA_OWNED);
  547 
  548         MAC_CHECK(check_proc_setgroups, cred, ngroups, gidset);
  549         return (error);
  550 }
  551 
  552 int
  553 mac_check_proc_setreuid(struct proc *p, struct ucred *cred, uid_t ruid,
  554     uid_t euid)
  555 {
  556         int error;
  557 
  558         PROC_LOCK_ASSERT(p, MA_OWNED);
  559 
  560         MAC_CHECK(check_proc_setreuid, cred, ruid, euid);
  561 
  562         return (error);
  563 }
  564 
  565 int
  566 mac_check_proc_setregid(struct proc *proc, struct ucred *cred, gid_t rgid,
  567     gid_t egid)
  568 {
  569         int error;
  570 
  571         PROC_LOCK_ASSERT(proc, MA_OWNED);
  572 
  573         MAC_CHECK(check_proc_setregid, cred, rgid, egid);
  574 
  575         return (error);
  576 }
  577 
  578 int
  579 mac_check_proc_setresuid(struct proc *p, struct ucred *cred, uid_t ruid,
  580     uid_t euid, uid_t suid)
  581 {
  582         int error;
  583 
  584         PROC_LOCK_ASSERT(p, MA_OWNED);
  585 
  586         MAC_CHECK(check_proc_setresuid, cred, ruid, euid, suid);
  587         return (error);
  588 }
  589 
  590 int
  591 mac_check_proc_setresgid(struct proc *p, struct ucred *cred, gid_t rgid,
  592     gid_t egid, gid_t sgid)
  593 {
  594         int error;
  595 
  596         PROC_LOCK_ASSERT(p, MA_OWNED);
  597 
  598         MAC_CHECK(check_proc_setresgid, cred, rgid, egid, sgid);
  599 
  600         return (error);
  601 }
  602 
  603 int
  604 mac_check_proc_wait(struct ucred *cred, struct proc *p)
  605 {
  606         int error;
  607 
  608         PROC_LOCK_ASSERT(p, MA_OWNED);
  609 
  610         MAC_CHECK(check_proc_wait, cred, p);
  611 
  612         return (error);
  613 }

Cache object: 2defc548cb26f9e7a161e8a091416ced


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