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/11.1/sys/kern/sys_capability.c 306398 2016-09-28 09:28:26Z kib $");
   60 
   61 #include "opt_capsicum.h"
   62 #include "opt_ktrace.h"
   63 
   64 #include <sys/param.h>
   65 #include <sys/capsicum.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 int trap_enotcap;
   87 SYSCTL_INT(_kern, OID_AUTO, trap_enotcap, CTLFLAG_RW, &trap_enotcap, 0,
   88     "Deliver SIGTRAP on ENOTCAPABLE");
   89 
   90 #ifdef CAPABILITY_MODE
   91 
   92 FEATURE(security_capability_mode, "Capsicum Capability Mode");
   93 
   94 /*
   95  * System call to enter capability mode for the process.
   96  */
   97 int
   98 sys_cap_enter(struct thread *td, struct cap_enter_args *uap)
   99 {
  100         struct ucred *newcred, *oldcred;
  101         struct proc *p;
  102 
  103         if (IN_CAPABILITY_MODE(td))
  104                 return (0);
  105 
  106         newcred = crget();
  107         p = td->td_proc;
  108         PROC_LOCK(p);
  109         oldcred = crcopysafe(p, newcred);
  110         newcred->cr_flags |= CRED_FLAG_CAPMODE;
  111         proc_set_cred(p, newcred);
  112         PROC_UNLOCK(p);
  113         crfree(oldcred);
  114         return (0);
  115 }
  116 
  117 /*
  118  * System call to query whether the process is in capability mode.
  119  */
  120 int
  121 sys_cap_getmode(struct thread *td, struct cap_getmode_args *uap)
  122 {
  123         u_int i;
  124 
  125         i = IN_CAPABILITY_MODE(td) ? 1 : 0;
  126         return (copyout(&i, uap->modep, sizeof(i)));
  127 }
  128 
  129 #else /* !CAPABILITY_MODE */
  130 
  131 int
  132 sys_cap_enter(struct thread *td, struct cap_enter_args *uap)
  133 {
  134 
  135         return (ENOSYS);
  136 }
  137 
  138 int
  139 sys_cap_getmode(struct thread *td, struct cap_getmode_args *uap)
  140 {
  141 
  142         return (ENOSYS);
  143 }
  144 
  145 #endif /* CAPABILITY_MODE */
  146 
  147 #ifdef CAPABILITIES
  148 
  149 FEATURE(security_capabilities, "Capsicum Capabilities");
  150 
  151 MALLOC_DECLARE(M_FILECAPS);
  152 
  153 static inline int
  154 _cap_check(const cap_rights_t *havep, const cap_rights_t *needp,
  155     enum ktr_cap_fail_type type)
  156 {
  157         int i;
  158 
  159         for (i = 0; i < nitems(havep->cr_rights); i++) {
  160                 if (!cap_rights_contains(havep, needp)) {
  161 #ifdef KTRACE
  162                         if (KTRPOINT(curthread, KTR_CAPFAIL))
  163                                 ktrcapfail(type, needp, havep);
  164 #endif
  165                         return (ENOTCAPABLE);
  166                 }
  167         }
  168         return (0);
  169 }
  170 
  171 /*
  172  * Test whether a capability grants the requested rights.
  173  */
  174 int
  175 cap_check(const cap_rights_t *havep, const cap_rights_t *needp)
  176 {
  177 
  178         return (_cap_check(havep, needp, CAPFAIL_NOTCAPABLE));
  179 }
  180 
  181 /*
  182  * Convert capability rights into VM access flags.
  183  */
  184 u_char
  185 cap_rights_to_vmprot(cap_rights_t *havep)
  186 {
  187         u_char maxprot;
  188 
  189         maxprot = VM_PROT_NONE;
  190         if (cap_rights_is_set(havep, CAP_MMAP_R))
  191                 maxprot |= VM_PROT_READ;
  192         if (cap_rights_is_set(havep, CAP_MMAP_W))
  193                 maxprot |= VM_PROT_WRITE;
  194         if (cap_rights_is_set(havep, CAP_MMAP_X))
  195                 maxprot |= VM_PROT_EXECUTE;
  196 
  197         return (maxprot);
  198 }
  199 
  200 /*
  201  * Extract rights from a capability for monitoring purposes -- not for use in
  202  * any other way, as we want to keep all capability permission evaluation in
  203  * this one file.
  204  */
  205 
  206 cap_rights_t *
  207 cap_rights_fde(struct filedescent *fde)
  208 {
  209 
  210         return (&fde->fde_rights);
  211 }
  212 
  213 cap_rights_t *
  214 cap_rights(struct filedesc *fdp, int fd)
  215 {
  216 
  217         return (cap_rights_fde(&fdp->fd_ofiles[fd]));
  218 }
  219 
  220 int
  221 kern_cap_rights_limit(struct thread *td, int fd, cap_rights_t *rights)
  222 {
  223         struct filedesc *fdp;
  224         int error;
  225 
  226         fdp = td->td_proc->p_fd;
  227         FILEDESC_XLOCK(fdp);
  228         if (fget_locked(fdp, fd) == NULL) {
  229                 FILEDESC_XUNLOCK(fdp);
  230                 return (EBADF);
  231         }
  232         error = _cap_check(cap_rights(fdp, fd), rights, CAPFAIL_INCREASE);
  233         if (error == 0) {
  234                 fdp->fd_ofiles[fd].fde_rights = *rights;
  235                 if (!cap_rights_is_set(rights, CAP_IOCTL)) {
  236                         free(fdp->fd_ofiles[fd].fde_ioctls, M_FILECAPS);
  237                         fdp->fd_ofiles[fd].fde_ioctls = NULL;
  238                         fdp->fd_ofiles[fd].fde_nioctls = 0;
  239                 }
  240                 if (!cap_rights_is_set(rights, CAP_FCNTL))
  241                         fdp->fd_ofiles[fd].fde_fcntls = 0;
  242         }
  243         FILEDESC_XUNLOCK(fdp);
  244         return (error);
  245 }
  246 
  247 /*
  248  * System call to limit rights of the given capability.
  249  */
  250 int
  251 sys_cap_rights_limit(struct thread *td, struct cap_rights_limit_args *uap)
  252 {
  253         cap_rights_t rights;
  254         int error, version;
  255 
  256         cap_rights_init(&rights);
  257 
  258         error = copyin(uap->rightsp, &rights, sizeof(rights.cr_rights[0]));
  259         if (error != 0)
  260                 return (error);
  261         version = CAPVER(&rights);
  262         if (version != CAP_RIGHTS_VERSION_00)
  263                 return (EINVAL);
  264 
  265         error = copyin(uap->rightsp, &rights,
  266             sizeof(rights.cr_rights[0]) * CAPARSIZE(&rights));
  267         if (error != 0)
  268                 return (error);
  269         /* Check for race. */
  270         if (CAPVER(&rights) != version)
  271                 return (EINVAL);
  272 
  273         if (!cap_rights_is_valid(&rights))
  274                 return (EINVAL);
  275 
  276         if (version != CAP_RIGHTS_VERSION) {
  277                 rights.cr_rights[0] &= ~(0x3ULL << 62);
  278                 rights.cr_rights[0] |= ((uint64_t)CAP_RIGHTS_VERSION << 62);
  279         }
  280 #ifdef KTRACE
  281         if (KTRPOINT(td, KTR_STRUCT))
  282                 ktrcaprights(&rights);
  283 #endif
  284 
  285         AUDIT_ARG_FD(uap->fd);
  286         AUDIT_ARG_RIGHTS(&rights);
  287         return (kern_cap_rights_limit(td, uap->fd, &rights));
  288 }
  289 
  290 /*
  291  * System call to query the rights mask associated with a capability.
  292  */
  293 int
  294 sys___cap_rights_get(struct thread *td, struct __cap_rights_get_args *uap)
  295 {
  296         struct filedesc *fdp;
  297         cap_rights_t rights;
  298         int error, fd, i, n;
  299 
  300         if (uap->version != CAP_RIGHTS_VERSION_00)
  301                 return (EINVAL);
  302 
  303         fd = uap->fd;
  304 
  305         AUDIT_ARG_FD(fd);
  306 
  307         fdp = td->td_proc->p_fd;
  308         FILEDESC_SLOCK(fdp);
  309         if (fget_locked(fdp, fd) == NULL) {
  310                 FILEDESC_SUNLOCK(fdp);
  311                 return (EBADF);
  312         }
  313         rights = *cap_rights(fdp, fd);
  314         FILEDESC_SUNLOCK(fdp);
  315         n = uap->version + 2;
  316         if (uap->version != CAPVER(&rights)) {
  317                 /*
  318                  * For older versions we need to check if the descriptor
  319                  * doesn't contain rights not understood by the caller.
  320                  * If it does, we have to return an error.
  321                  */
  322                 for (i = n; i < CAPARSIZE(&rights); i++) {
  323                         if ((rights.cr_rights[i] & ~(0x7FULL << 57)) != 0)
  324                                 return (EINVAL);
  325                 }
  326         }
  327         error = copyout(&rights, uap->rightsp, sizeof(rights.cr_rights[0]) * n);
  328 #ifdef KTRACE
  329         if (error == 0 && KTRPOINT(td, KTR_STRUCT))
  330                 ktrcaprights(&rights);
  331 #endif
  332         return (error);
  333 }
  334 
  335 /*
  336  * Test whether a capability grants the given ioctl command.
  337  * If descriptor doesn't have CAP_IOCTL, then ioctls list is empty and
  338  * ENOTCAPABLE will be returned.
  339  */
  340 int
  341 cap_ioctl_check(struct filedesc *fdp, int fd, u_long cmd)
  342 {
  343         u_long *cmds;
  344         ssize_t ncmds;
  345         long i;
  346 
  347         FILEDESC_LOCK_ASSERT(fdp);
  348         KASSERT(fd >= 0 && fd < fdp->fd_nfiles,
  349             ("%s: invalid fd=%d", __func__, fd));
  350 
  351         ncmds = fdp->fd_ofiles[fd].fde_nioctls;
  352         if (ncmds == -1)
  353                 return (0);
  354 
  355         cmds = fdp->fd_ofiles[fd].fde_ioctls;
  356         for (i = 0; i < ncmds; i++) {
  357                 if (cmds[i] == cmd)
  358                         return (0);
  359         }
  360 
  361         return (ENOTCAPABLE);
  362 }
  363 
  364 /*
  365  * Check if the current ioctls list can be replaced by the new one.
  366  */
  367 static int
  368 cap_ioctl_limit_check(struct filedesc *fdp, int fd, const u_long *cmds,
  369     size_t ncmds)
  370 {
  371         u_long *ocmds;
  372         ssize_t oncmds;
  373         u_long i;
  374         long j;
  375 
  376         oncmds = fdp->fd_ofiles[fd].fde_nioctls;
  377         if (oncmds == -1)
  378                 return (0);
  379         if (oncmds < (ssize_t)ncmds)
  380                 return (ENOTCAPABLE);
  381 
  382         ocmds = fdp->fd_ofiles[fd].fde_ioctls;
  383         for (i = 0; i < ncmds; i++) {
  384                 for (j = 0; j < oncmds; j++) {
  385                         if (cmds[i] == ocmds[j])
  386                                 break;
  387                 }
  388                 if (j == oncmds)
  389                         return (ENOTCAPABLE);
  390         }
  391 
  392         return (0);
  393 }
  394 
  395 int
  396 kern_cap_ioctls_limit(struct thread *td, int fd, u_long *cmds, size_t ncmds)
  397 {
  398         struct filedesc *fdp;
  399         u_long *ocmds;
  400         int error;
  401 
  402         AUDIT_ARG_FD(fd);
  403 
  404         fdp = td->td_proc->p_fd;
  405         FILEDESC_XLOCK(fdp);
  406 
  407         if (fget_locked(fdp, fd) == NULL) {
  408                 error = EBADF;
  409                 goto out;
  410         }
  411 
  412         error = cap_ioctl_limit_check(fdp, fd, cmds, ncmds);
  413         if (error != 0)
  414                 goto out;
  415 
  416         ocmds = fdp->fd_ofiles[fd].fde_ioctls;
  417         fdp->fd_ofiles[fd].fde_ioctls = cmds;
  418         fdp->fd_ofiles[fd].fde_nioctls = ncmds;
  419 
  420         cmds = ocmds;
  421         error = 0;
  422 out:
  423         FILEDESC_XUNLOCK(fdp);
  424         free(cmds, M_FILECAPS);
  425         return (error);
  426 }
  427 
  428 int
  429 sys_cap_ioctls_limit(struct thread *td, struct cap_ioctls_limit_args *uap)
  430 {
  431         u_long *cmds;
  432         size_t ncmds;
  433         int error;
  434 
  435         ncmds = uap->ncmds;
  436 
  437         if (ncmds > 256)        /* XXX: Is 256 sane? */
  438                 return (EINVAL);
  439 
  440         if (ncmds == 0) {
  441                 cmds = NULL;
  442         } else {
  443                 cmds = malloc(sizeof(cmds[0]) * ncmds, M_FILECAPS, M_WAITOK);
  444                 error = copyin(uap->cmds, cmds, sizeof(cmds[0]) * ncmds);
  445                 if (error != 0) {
  446                         free(cmds, M_FILECAPS);
  447                         return (error);
  448                 }
  449         }
  450 
  451         return (kern_cap_ioctls_limit(td, uap->fd, cmds, ncmds));
  452 }
  453 
  454 int
  455 sys_cap_ioctls_get(struct thread *td, struct cap_ioctls_get_args *uap)
  456 {
  457         struct filedesc *fdp;
  458         struct filedescent *fdep;
  459         u_long *cmds;
  460         size_t maxcmds;
  461         int error, fd;
  462 
  463         fd = uap->fd;
  464         cmds = uap->cmds;
  465         maxcmds = uap->maxcmds;
  466 
  467         AUDIT_ARG_FD(fd);
  468 
  469         fdp = td->td_proc->p_fd;
  470         FILEDESC_SLOCK(fdp);
  471 
  472         if (fget_locked(fdp, fd) == NULL) {
  473                 error = EBADF;
  474                 goto out;
  475         }
  476 
  477         /*
  478          * If all ioctls are allowed (fde_nioctls == -1 && fde_ioctls == NULL)
  479          * the only sane thing we can do is to not populate the given array and
  480          * return CAP_IOCTLS_ALL.
  481          */
  482 
  483         fdep = &fdp->fd_ofiles[fd];
  484         if (cmds != NULL && fdep->fde_ioctls != NULL) {
  485                 error = copyout(fdep->fde_ioctls, cmds,
  486                     sizeof(cmds[0]) * MIN(fdep->fde_nioctls, maxcmds));
  487                 if (error != 0)
  488                         goto out;
  489         }
  490         if (fdep->fde_nioctls == -1)
  491                 td->td_retval[0] = CAP_IOCTLS_ALL;
  492         else
  493                 td->td_retval[0] = fdep->fde_nioctls;
  494 
  495         error = 0;
  496 out:
  497         FILEDESC_SUNLOCK(fdp);
  498         return (error);
  499 }
  500 
  501 /*
  502  * Test whether a capability grants the given fcntl command.
  503  */
  504 int
  505 cap_fcntl_check_fde(struct filedescent *fde, int cmd)
  506 {
  507         uint32_t fcntlcap;
  508 
  509         fcntlcap = (1 << cmd);
  510         KASSERT((CAP_FCNTL_ALL & fcntlcap) != 0,
  511             ("Unsupported fcntl=%d.", cmd));
  512 
  513         if ((fde->fde_fcntls & fcntlcap) != 0)
  514                 return (0);
  515 
  516         return (ENOTCAPABLE);
  517 }
  518 
  519 int
  520 cap_fcntl_check(struct filedesc *fdp, int fd, int cmd)
  521 {
  522 
  523         KASSERT(fd >= 0 && fd < fdp->fd_nfiles,
  524             ("%s: invalid fd=%d", __func__, fd));
  525 
  526         return (cap_fcntl_check_fde(&fdp->fd_ofiles[fd], cmd));
  527 }
  528 
  529 int
  530 sys_cap_fcntls_limit(struct thread *td, struct cap_fcntls_limit_args *uap)
  531 {
  532         struct filedesc *fdp;
  533         uint32_t fcntlrights;
  534         int fd;
  535 
  536         fd = uap->fd;
  537         fcntlrights = uap->fcntlrights;
  538 
  539         AUDIT_ARG_FD(fd);
  540         AUDIT_ARG_FCNTL_RIGHTS(fcntlrights);
  541 
  542         if ((fcntlrights & ~CAP_FCNTL_ALL) != 0)
  543                 return (EINVAL);
  544 
  545         fdp = td->td_proc->p_fd;
  546         FILEDESC_XLOCK(fdp);
  547 
  548         if (fget_locked(fdp, fd) == NULL) {
  549                 FILEDESC_XUNLOCK(fdp);
  550                 return (EBADF);
  551         }
  552 
  553         if ((fcntlrights & ~fdp->fd_ofiles[fd].fde_fcntls) != 0) {
  554                 FILEDESC_XUNLOCK(fdp);
  555                 return (ENOTCAPABLE);
  556         }
  557 
  558         fdp->fd_ofiles[fd].fde_fcntls = fcntlrights;
  559         FILEDESC_XUNLOCK(fdp);
  560 
  561         return (0);
  562 }
  563 
  564 int
  565 sys_cap_fcntls_get(struct thread *td, struct cap_fcntls_get_args *uap)
  566 {
  567         struct filedesc *fdp;
  568         uint32_t rights;
  569         int fd;
  570 
  571         fd = uap->fd;
  572 
  573         AUDIT_ARG_FD(fd);
  574 
  575         fdp = td->td_proc->p_fd;
  576         FILEDESC_SLOCK(fdp);
  577         if (fget_locked(fdp, fd) == NULL) {
  578                 FILEDESC_SUNLOCK(fdp);
  579                 return (EBADF);
  580         }
  581         rights = fdp->fd_ofiles[fd].fde_fcntls;
  582         FILEDESC_SUNLOCK(fdp);
  583 
  584         return (copyout(&rights, uap->fcntlrightsp, sizeof(rights)));
  585 }
  586 
  587 #else /* !CAPABILITIES */
  588 
  589 /*
  590  * Stub Capability functions for when options CAPABILITIES isn't compiled
  591  * into the kernel.
  592  */
  593 
  594 int
  595 sys_cap_rights_limit(struct thread *td, struct cap_rights_limit_args *uap)
  596 {
  597 
  598         return (ENOSYS);
  599 }
  600 
  601 int
  602 sys___cap_rights_get(struct thread *td, struct __cap_rights_get_args *uap)
  603 {
  604 
  605         return (ENOSYS);
  606 }
  607 
  608 int
  609 sys_cap_ioctls_limit(struct thread *td, struct cap_ioctls_limit_args *uap)
  610 {
  611 
  612         return (ENOSYS);
  613 }
  614 
  615 int
  616 sys_cap_ioctls_get(struct thread *td, struct cap_ioctls_get_args *uap)
  617 {
  618 
  619         return (ENOSYS);
  620 }
  621 
  622 int
  623 sys_cap_fcntls_limit(struct thread *td, struct cap_fcntls_limit_args *uap)
  624 {
  625 
  626         return (ENOSYS);
  627 }
  628 
  629 int
  630 sys_cap_fcntls_get(struct thread *td, struct cap_fcntls_get_args *uap)
  631 {
  632 
  633         return (ENOSYS);
  634 }
  635 
  636 #endif /* CAPABILITIES */

Cache object: e44ab3fbc74b97e1bb797c52cfe94f42


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