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/sys_capability.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) 2008-2011 Robert N. M. Watson
    3  * Copyright (c) 2010-2011 Jonathan Anderson
    4  * Copyright (c) 2012 FreeBSD Foundation
    5  * All rights reserved.
    6  *
    7  * This software was developed at the University of Cambridge Computer
    8  * Laboratory with support from a grant from Google, Inc.
    9  *
   10  * Portions of this software were developed by Pawel Jakub Dawidek under
   11  * sponsorship from the FreeBSD Foundation.
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  * 1. Redistributions of source code must retain the above copyright
   17  *    notice, this list of conditions and the following disclaimer.
   18  * 2. Redistributions in binary form must reproduce the above copyright
   19  *    notice, this list of conditions and the following disclaimer in the
   20  *    documentation and/or other materials provided with the distribution.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  */
   34 
   35 /*
   36  * FreeBSD kernel capability facility.
   37  *
   38  * Two kernel features are implemented here: capability mode, a sandboxed mode
   39  * of execution for processes, and capabilities, a refinement on file
   40  * descriptors that allows fine-grained control over operations on the file
   41  * descriptor.  Collectively, these allow processes to run in the style of a
   42  * historic "capability system" in which they can use only resources
   43  * explicitly delegated to them.  This model is enforced by restricting access
   44  * to global namespaces in capability mode.
   45  *
   46  * Capabilities wrap other file descriptor types, binding them to a constant
   47  * rights mask set when the capability is created.  New capabilities may be
   48  * derived from existing capabilities, but only if they have the same or a
   49  * strict subset of the rights on the original capability.
   50  *
   51  * System calls permitted in capability mode are defined in capabilities.conf;
   52  * calls must be carefully audited for safety to ensure that they don't allow
   53  * escape from a sandbox.  Some calls permit only a subset of operations in
   54  * capability mode -- for example, shm_open(2) is limited to creating
   55  * anonymous, rather than named, POSIX shared memory objects.
   56  */
   57 
   58 #include <sys/cdefs.h>
   59 __FBSDID("$FreeBSD: releng/10.0/sys/kern/sys_capability.c 255229 2013-09-05 03:36:57Z sbruno $");
   60 
   61 #include "opt_capsicum.h"
   62 #include "opt_ktrace.h"
   63 
   64 #include <sys/param.h>
   65 #include <sys/capability.h>
   66 #include <sys/file.h>
   67 #include <sys/filedesc.h>
   68 #include <sys/kernel.h>
   69 #include <sys/limits.h>
   70 #include <sys/lock.h>
   71 #include <sys/mutex.h>
   72 #include <sys/proc.h>
   73 #include <sys/syscallsubr.h>
   74 #include <sys/sysproto.h>
   75 #include <sys/sysctl.h>
   76 #include <sys/systm.h>
   77 #include <sys/ucred.h>
   78 #include <sys/uio.h>
   79 #include <sys/ktrace.h>
   80 
   81 #include <security/audit/audit.h>
   82 
   83 #include <vm/uma.h>
   84 #include <vm/vm.h>
   85 
   86 #ifdef CAPABILITY_MODE
   87 
   88 FEATURE(security_capability_mode, "Capsicum Capability Mode");
   89 
   90 /*
   91  * System call to enter capability mode for the process.
   92  */
   93 int
   94 sys_cap_enter(struct thread *td, struct cap_enter_args *uap)
   95 {
   96         struct ucred *newcred, *oldcred;
   97         struct proc *p;
   98 
   99         if (IN_CAPABILITY_MODE(td))
  100                 return (0);
  101 
  102         newcred = crget();
  103         p = td->td_proc;
  104         PROC_LOCK(p);
  105         oldcred = p->p_ucred;
  106         crcopy(newcred, oldcred);
  107         newcred->cr_flags |= CRED_FLAG_CAPMODE;
  108         p->p_ucred = newcred;
  109         PROC_UNLOCK(p);
  110         crfree(oldcred);
  111         return (0);
  112 }
  113 
  114 /*
  115  * System call to query whether the process is in capability mode.
  116  */
  117 int
  118 sys_cap_getmode(struct thread *td, struct cap_getmode_args *uap)
  119 {
  120         u_int i;
  121 
  122         i = IN_CAPABILITY_MODE(td) ? 1 : 0;
  123         return (copyout(&i, uap->modep, sizeof(i)));
  124 }
  125 
  126 #else /* !CAPABILITY_MODE */
  127 
  128 int
  129 sys_cap_enter(struct thread *td, struct cap_enter_args *uap)
  130 {
  131 
  132         return (ENOSYS);
  133 }
  134 
  135 int
  136 sys_cap_getmode(struct thread *td, struct cap_getmode_args *uap)
  137 {
  138 
  139         return (ENOSYS);
  140 }
  141 
  142 #endif /* CAPABILITY_MODE */
  143 
  144 #ifdef CAPABILITIES
  145 
  146 FEATURE(security_capabilities, "Capsicum Capabilities");
  147 
  148 MALLOC_DECLARE(M_FILECAPS);
  149 
  150 static inline int
  151 _cap_check(const cap_rights_t *havep, const cap_rights_t *needp,
  152     enum ktr_cap_fail_type type)
  153 {
  154         int i;
  155 
  156         for (i = 0; i < nitems(havep->cr_rights); i++) {
  157                 if (!cap_rights_contains(havep, needp)) {
  158 #ifdef KTRACE
  159                         if (KTRPOINT(curthread, KTR_CAPFAIL))
  160                                 ktrcapfail(type, needp, havep);
  161 #endif
  162                         return (ENOTCAPABLE);
  163                 }
  164         }
  165         return (0);
  166 }
  167 
  168 /*
  169  * Test whether a capability grants the requested rights.
  170  */
  171 int
  172 cap_check(const cap_rights_t *havep, const cap_rights_t *needp)
  173 {
  174 
  175         return (_cap_check(havep, needp, CAPFAIL_NOTCAPABLE));
  176 }
  177 
  178 /*
  179  * Convert capability rights into VM access flags.
  180  */
  181 u_char
  182 cap_rights_to_vmprot(cap_rights_t *havep)
  183 {
  184         u_char maxprot;
  185 
  186         maxprot = VM_PROT_NONE;
  187         if (cap_rights_is_set(havep, CAP_MMAP_R))
  188                 maxprot |= VM_PROT_READ;
  189         if (cap_rights_is_set(havep, CAP_MMAP_W))
  190                 maxprot |= VM_PROT_WRITE;
  191         if (cap_rights_is_set(havep, CAP_MMAP_X))
  192                 maxprot |= VM_PROT_EXECUTE;
  193 
  194         return (maxprot);
  195 }
  196 
  197 /*
  198  * Extract rights from a capability for monitoring purposes -- not for use in
  199  * any other way, as we want to keep all capability permission evaluation in
  200  * this one file.
  201  */
  202 cap_rights_t *
  203 cap_rights(struct filedesc *fdp, int fd)
  204 {
  205 
  206         return (&fdp->fd_ofiles[fd].fde_rights);
  207 }
  208 
  209 /*
  210  * System call to limit rights of the given capability.
  211  */
  212 int
  213 sys_cap_rights_limit(struct thread *td, struct cap_rights_limit_args *uap)
  214 {
  215         struct filedesc *fdp;
  216         cap_rights_t rights;
  217         int error, fd, version;
  218 
  219         cap_rights_init(&rights);
  220 
  221         error = copyin(uap->rightsp, &rights, sizeof(rights.cr_rights[0]));
  222         if (error != 0)
  223                 return (error);
  224         version = CAPVER(&rights);
  225         if (version != CAP_RIGHTS_VERSION_00)
  226                 return (EINVAL);
  227 
  228         error = copyin(uap->rightsp, &rights,
  229             sizeof(rights.cr_rights[0]) * CAPARSIZE(&rights));
  230         if (error != 0)
  231                 return (error);
  232         /* Check for race. */
  233         if (CAPVER(&rights) != version)
  234                 return (EINVAL);
  235 
  236         if (!cap_rights_is_valid(&rights))
  237                 return (EINVAL);
  238 
  239         if (version != CAP_RIGHTS_VERSION) {
  240                 rights.cr_rights[0] &= ~(0x3ULL << 62);
  241                 rights.cr_rights[0] |= ((uint64_t)CAP_RIGHTS_VERSION << 62);
  242         }
  243 #ifdef KTRACE
  244         if (KTRPOINT(td, KTR_STRUCT))
  245                 ktrcaprights(&rights);
  246 #endif
  247 
  248         fd = uap->fd;
  249 
  250         AUDIT_ARG_FD(fd);
  251         AUDIT_ARG_RIGHTS(&rights);
  252 
  253         fdp = td->td_proc->p_fd;
  254         FILEDESC_XLOCK(fdp);
  255         if (fget_locked(fdp, fd) == NULL) {
  256                 FILEDESC_XUNLOCK(fdp);
  257                 return (EBADF);
  258         }
  259         error = _cap_check(cap_rights(fdp, fd), &rights, CAPFAIL_INCREASE);
  260         if (error == 0) {
  261                 fdp->fd_ofiles[fd].fde_rights = rights;
  262                 if (!cap_rights_is_set(&rights, CAP_IOCTL)) {
  263                         free(fdp->fd_ofiles[fd].fde_ioctls, M_FILECAPS);
  264                         fdp->fd_ofiles[fd].fde_ioctls = NULL;
  265                         fdp->fd_ofiles[fd].fde_nioctls = 0;
  266                 }
  267                 if (!cap_rights_is_set(&rights, CAP_FCNTL))
  268                         fdp->fd_ofiles[fd].fde_fcntls = 0;
  269         }
  270         FILEDESC_XUNLOCK(fdp);
  271         return (error);
  272 }
  273 
  274 /*
  275  * System call to query the rights mask associated with a capability.
  276  */
  277 int
  278 sys___cap_rights_get(struct thread *td, struct __cap_rights_get_args *uap)
  279 {
  280         struct filedesc *fdp;
  281         cap_rights_t rights;
  282         int error, fd, i, n;
  283 
  284         if (uap->version != CAP_RIGHTS_VERSION_00)
  285                 return (EINVAL);
  286 
  287         fd = uap->fd;
  288 
  289         AUDIT_ARG_FD(fd);
  290 
  291         fdp = td->td_proc->p_fd;
  292         FILEDESC_SLOCK(fdp);
  293         if (fget_locked(fdp, fd) == NULL) {
  294                 FILEDESC_SUNLOCK(fdp);
  295                 return (EBADF);
  296         }
  297         rights = *cap_rights(fdp, fd);
  298         FILEDESC_SUNLOCK(fdp);
  299         n = uap->version + 2;
  300         if (uap->version != CAPVER(&rights)) {
  301                 /*
  302                  * For older versions we need to check if the descriptor
  303                  * doesn't contain rights not understood by the caller.
  304                  * If it does, we have to return an error.
  305                  */
  306                 for (i = n; i < CAPARSIZE(&rights); i++) {
  307                         if ((rights.cr_rights[i] & ~(0x7FULL << 57)) != 0)
  308                                 return (EINVAL);
  309                 }
  310         }
  311         error = copyout(&rights, uap->rightsp, sizeof(rights.cr_rights[0]) * n);
  312 #ifdef KTRACE
  313         if (error == 0 && KTRPOINT(td, KTR_STRUCT))
  314                 ktrcaprights(&rights);
  315 #endif
  316         return (error);
  317 }
  318 
  319 /*
  320  * Test whether a capability grants the given ioctl command.
  321  * If descriptor doesn't have CAP_IOCTL, then ioctls list is empty and
  322  * ENOTCAPABLE will be returned.
  323  */
  324 int
  325 cap_ioctl_check(struct filedesc *fdp, int fd, u_long cmd)
  326 {
  327         u_long *cmds;
  328         ssize_t ncmds;
  329         long i;
  330 
  331         FILEDESC_LOCK_ASSERT(fdp);
  332         KASSERT(fd >= 0 && fd < fdp->fd_nfiles,
  333             ("%s: invalid fd=%d", __func__, fd));
  334 
  335         ncmds = fdp->fd_ofiles[fd].fde_nioctls;
  336         if (ncmds == -1)
  337                 return (0);
  338 
  339         cmds = fdp->fd_ofiles[fd].fde_ioctls;
  340         for (i = 0; i < ncmds; i++) {
  341                 if (cmds[i] == cmd)
  342                         return (0);
  343         }
  344 
  345         return (ENOTCAPABLE);
  346 }
  347 
  348 /*
  349  * Check if the current ioctls list can be replaced by the new one.
  350  */
  351 static int
  352 cap_ioctl_limit_check(struct filedesc *fdp, int fd, const u_long *cmds,
  353     size_t ncmds)
  354 {
  355         u_long *ocmds;
  356         ssize_t oncmds;
  357         u_long i;
  358         long j;
  359 
  360         oncmds = fdp->fd_ofiles[fd].fde_nioctls;
  361         if (oncmds == -1)
  362                 return (0);
  363         if (oncmds < (ssize_t)ncmds)
  364                 return (ENOTCAPABLE);
  365 
  366         ocmds = fdp->fd_ofiles[fd].fde_ioctls;
  367         for (i = 0; i < ncmds; i++) {
  368                 for (j = 0; j < oncmds; j++) {
  369                         if (cmds[i] == ocmds[j])
  370                                 break;
  371                 }
  372                 if (j == oncmds)
  373                         return (ENOTCAPABLE);
  374         }
  375 
  376         return (0);
  377 }
  378 
  379 int
  380 kern_cap_ioctls_limit(struct thread *td, int fd, u_long *cmds, size_t ncmds)
  381 {
  382         struct filedesc *fdp;
  383         u_long *ocmds;
  384         int error;
  385 
  386         AUDIT_ARG_FD(fd);
  387 
  388         fdp = td->td_proc->p_fd;
  389         FILEDESC_XLOCK(fdp);
  390 
  391         if (fget_locked(fdp, fd) == NULL) {
  392                 error = EBADF;
  393                 goto out;
  394         }
  395 
  396         error = cap_ioctl_limit_check(fdp, fd, cmds, ncmds);
  397         if (error != 0)
  398                 goto out;
  399 
  400         ocmds = fdp->fd_ofiles[fd].fde_ioctls;
  401         fdp->fd_ofiles[fd].fde_ioctls = cmds;
  402         fdp->fd_ofiles[fd].fde_nioctls = ncmds;
  403 
  404         cmds = ocmds;
  405         error = 0;
  406 out:
  407         FILEDESC_XUNLOCK(fdp);
  408         free(cmds, M_FILECAPS);
  409         return (error);
  410 }
  411 
  412 int
  413 sys_cap_ioctls_limit(struct thread *td, struct cap_ioctls_limit_args *uap)
  414 {
  415         u_long *cmds;
  416         size_t ncmds;
  417         int error;
  418 
  419         ncmds = uap->ncmds;
  420 
  421         if (ncmds > 256)        /* XXX: Is 256 sane? */
  422                 return (EINVAL);
  423 
  424         if (ncmds == 0) {
  425                 cmds = NULL;
  426         } else {
  427                 cmds = malloc(sizeof(cmds[0]) * ncmds, M_FILECAPS, M_WAITOK);
  428                 error = copyin(uap->cmds, cmds, sizeof(cmds[0]) * ncmds);
  429                 if (error != 0) {
  430                         free(cmds, M_FILECAPS);
  431                         return (error);
  432                 }
  433         }
  434 
  435         return (kern_cap_ioctls_limit(td, uap->fd, cmds, ncmds));
  436 }
  437 
  438 int
  439 sys_cap_ioctls_get(struct thread *td, struct cap_ioctls_get_args *uap)
  440 {
  441         struct filedesc *fdp;
  442         struct filedescent *fdep;
  443         u_long *cmds;
  444         size_t maxcmds;
  445         int error, fd;
  446 
  447         fd = uap->fd;
  448         cmds = uap->cmds;
  449         maxcmds = uap->maxcmds;
  450 
  451         AUDIT_ARG_FD(fd);
  452 
  453         fdp = td->td_proc->p_fd;
  454         FILEDESC_SLOCK(fdp);
  455 
  456         if (fget_locked(fdp, fd) == NULL) {
  457                 error = EBADF;
  458                 goto out;
  459         }
  460 
  461         /*
  462          * If all ioctls are allowed (fde_nioctls == -1 && fde_ioctls == NULL)
  463          * the only sane thing we can do is to not populate the given array and
  464          * return CAP_IOCTLS_ALL.
  465          */
  466 
  467         fdep = &fdp->fd_ofiles[fd];
  468         if (cmds != NULL && fdep->fde_ioctls != NULL) {
  469                 error = copyout(fdep->fde_ioctls, cmds,
  470                     sizeof(cmds[0]) * MIN(fdep->fde_nioctls, maxcmds));
  471                 if (error != 0)
  472                         goto out;
  473         }
  474         if (fdep->fde_nioctls == -1)
  475                 td->td_retval[0] = CAP_IOCTLS_ALL;
  476         else
  477                 td->td_retval[0] = fdep->fde_nioctls;
  478 
  479         error = 0;
  480 out:
  481         FILEDESC_SUNLOCK(fdp);
  482         return (error);
  483 }
  484 
  485 /*
  486  * Test whether a capability grants the given fcntl command.
  487  */
  488 int
  489 cap_fcntl_check(struct filedesc *fdp, int fd, int cmd)
  490 {
  491         uint32_t fcntlcap;
  492 
  493         KASSERT(fd >= 0 && fd < fdp->fd_nfiles,
  494             ("%s: invalid fd=%d", __func__, fd));
  495 
  496         fcntlcap = (1 << cmd);
  497         KASSERT((CAP_FCNTL_ALL & fcntlcap) != 0,
  498             ("Unsupported fcntl=%d.", cmd));
  499 
  500         if ((fdp->fd_ofiles[fd].fde_fcntls & fcntlcap) != 0)
  501                 return (0);
  502 
  503         return (ENOTCAPABLE);
  504 }
  505 
  506 int
  507 sys_cap_fcntls_limit(struct thread *td, struct cap_fcntls_limit_args *uap)
  508 {
  509         struct filedesc *fdp;
  510         uint32_t fcntlrights;
  511         int fd;
  512 
  513         fd = uap->fd;
  514         fcntlrights = uap->fcntlrights;
  515 
  516         AUDIT_ARG_FD(fd);
  517         AUDIT_ARG_FCNTL_RIGHTS(fcntlrights);
  518 
  519         if ((fcntlrights & ~CAP_FCNTL_ALL) != 0)
  520                 return (EINVAL);
  521 
  522         fdp = td->td_proc->p_fd;
  523         FILEDESC_XLOCK(fdp);
  524 
  525         if (fget_locked(fdp, fd) == NULL) {
  526                 FILEDESC_XUNLOCK(fdp);
  527                 return (EBADF);
  528         }
  529 
  530         if ((fcntlrights & ~fdp->fd_ofiles[fd].fde_fcntls) != 0) {
  531                 FILEDESC_XUNLOCK(fdp);
  532                 return (ENOTCAPABLE);
  533         }
  534 
  535         fdp->fd_ofiles[fd].fde_fcntls = fcntlrights;
  536         FILEDESC_XUNLOCK(fdp);
  537 
  538         return (0);
  539 }
  540 
  541 int
  542 sys_cap_fcntls_get(struct thread *td, struct cap_fcntls_get_args *uap)
  543 {
  544         struct filedesc *fdp;
  545         uint32_t rights;
  546         int fd;
  547 
  548         fd = uap->fd;
  549 
  550         AUDIT_ARG_FD(fd);
  551 
  552         fdp = td->td_proc->p_fd;
  553         FILEDESC_SLOCK(fdp);
  554         if (fget_locked(fdp, fd) == NULL) {
  555                 FILEDESC_SUNLOCK(fdp);
  556                 return (EBADF);
  557         }
  558         rights = fdp->fd_ofiles[fd].fde_fcntls;
  559         FILEDESC_SUNLOCK(fdp);
  560 
  561         return (copyout(&rights, uap->fcntlrightsp, sizeof(rights)));
  562 }
  563 
  564 #else /* !CAPABILITIES */
  565 
  566 /*
  567  * Stub Capability functions for when options CAPABILITIES isn't compiled
  568  * into the kernel.
  569  */
  570 
  571 int
  572 sys_cap_rights_limit(struct thread *td, struct cap_rights_limit_args *uap)
  573 {
  574 
  575         return (ENOSYS);
  576 }
  577 
  578 int
  579 sys___cap_rights_get(struct thread *td, struct __cap_rights_get_args *uap)
  580 {
  581 
  582         return (ENOSYS);
  583 }
  584 
  585 int
  586 sys_cap_ioctls_limit(struct thread *td, struct cap_ioctls_limit_args *uap)
  587 {
  588 
  589         return (ENOSYS);
  590 }
  591 
  592 int
  593 sys_cap_ioctls_get(struct thread *td, struct cap_ioctls_get_args *uap)
  594 {
  595 
  596         return (ENOSYS);
  597 }
  598 
  599 int
  600 sys_cap_fcntls_limit(struct thread *td, struct cap_fcntls_limit_args *uap)
  601 {
  602 
  603         return (ENOSYS);
  604 }
  605 
  606 int
  607 sys_cap_fcntls_get(struct thread *td, struct cap_fcntls_get_args *uap)
  608 {
  609 
  610         return (ENOSYS);
  611 }
  612 
  613 #endif /* CAPABILITIES */

Cache object: d7c8cf774bf1803ea2b28ff4c1120b35


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