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.2/sys/kern/sys_capability.c 330355 2018-03-03 21:05:28Z eadler $");
   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 
  158         if (!cap_rights_contains(havep, needp)) {
  159 #ifdef KTRACE
  160                 if (KTRPOINT(curthread, KTR_CAPFAIL))
  161                         ktrcapfail(type, needp, havep);
  162 #endif
  163                 return (ENOTCAPABLE);
  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 
  203 cap_rights_t *
  204 cap_rights_fde(struct filedescent *fde)
  205 {
  206 
  207         return (&fde->fde_rights);
  208 }
  209 
  210 cap_rights_t *
  211 cap_rights(struct filedesc *fdp, int fd)
  212 {
  213 
  214         return (cap_rights_fde(&fdp->fd_ofiles[fd]));
  215 }
  216 
  217 int
  218 kern_cap_rights_limit(struct thread *td, int fd, cap_rights_t *rights)
  219 {
  220         struct filedesc *fdp;
  221         int error;
  222 
  223         fdp = td->td_proc->p_fd;
  224         FILEDESC_XLOCK(fdp);
  225         if (fget_locked(fdp, fd) == NULL) {
  226                 FILEDESC_XUNLOCK(fdp);
  227                 return (EBADF);
  228         }
  229         error = _cap_check(cap_rights(fdp, fd), rights, CAPFAIL_INCREASE);
  230         if (error == 0) {
  231                 fdp->fd_ofiles[fd].fde_rights = *rights;
  232                 if (!cap_rights_is_set(rights, CAP_IOCTL)) {
  233                         free(fdp->fd_ofiles[fd].fde_ioctls, M_FILECAPS);
  234                         fdp->fd_ofiles[fd].fde_ioctls = NULL;
  235                         fdp->fd_ofiles[fd].fde_nioctls = 0;
  236                 }
  237                 if (!cap_rights_is_set(rights, CAP_FCNTL))
  238                         fdp->fd_ofiles[fd].fde_fcntls = 0;
  239         }
  240         FILEDESC_XUNLOCK(fdp);
  241         return (error);
  242 }
  243 
  244 /*
  245  * System call to limit rights of the given capability.
  246  */
  247 int
  248 sys_cap_rights_limit(struct thread *td, struct cap_rights_limit_args *uap)
  249 {
  250         cap_rights_t rights;
  251         int error, version;
  252 
  253         cap_rights_init(&rights);
  254 
  255         error = copyin(uap->rightsp, &rights, sizeof(rights.cr_rights[0]));
  256         if (error != 0)
  257                 return (error);
  258         version = CAPVER(&rights);
  259         if (version != CAP_RIGHTS_VERSION_00)
  260                 return (EINVAL);
  261 
  262         error = copyin(uap->rightsp, &rights,
  263             sizeof(rights.cr_rights[0]) * CAPARSIZE(&rights));
  264         if (error != 0)
  265                 return (error);
  266         /* Check for race. */
  267         if (CAPVER(&rights) != version)
  268                 return (EINVAL);
  269 
  270         if (!cap_rights_is_valid(&rights))
  271                 return (EINVAL);
  272 
  273         if (version != CAP_RIGHTS_VERSION) {
  274                 rights.cr_rights[0] &= ~(0x3ULL << 62);
  275                 rights.cr_rights[0] |= ((uint64_t)CAP_RIGHTS_VERSION << 62);
  276         }
  277 #ifdef KTRACE
  278         if (KTRPOINT(td, KTR_STRUCT))
  279                 ktrcaprights(&rights);
  280 #endif
  281 
  282         AUDIT_ARG_FD(uap->fd);
  283         AUDIT_ARG_RIGHTS(&rights);
  284         return (kern_cap_rights_limit(td, uap->fd, &rights));
  285 }
  286 
  287 /*
  288  * System call to query the rights mask associated with a capability.
  289  */
  290 int
  291 sys___cap_rights_get(struct thread *td, struct __cap_rights_get_args *uap)
  292 {
  293         struct filedesc *fdp;
  294         cap_rights_t rights;
  295         int error, fd, i, n;
  296 
  297         if (uap->version != CAP_RIGHTS_VERSION_00)
  298                 return (EINVAL);
  299 
  300         fd = uap->fd;
  301 
  302         AUDIT_ARG_FD(fd);
  303 
  304         fdp = td->td_proc->p_fd;
  305         FILEDESC_SLOCK(fdp);
  306         if (fget_locked(fdp, fd) == NULL) {
  307                 FILEDESC_SUNLOCK(fdp);
  308                 return (EBADF);
  309         }
  310         rights = *cap_rights(fdp, fd);
  311         FILEDESC_SUNLOCK(fdp);
  312         n = uap->version + 2;
  313         if (uap->version != CAPVER(&rights)) {
  314                 /*
  315                  * For older versions we need to check if the descriptor
  316                  * doesn't contain rights not understood by the caller.
  317                  * If it does, we have to return an error.
  318                  */
  319                 for (i = n; i < CAPARSIZE(&rights); i++) {
  320                         if ((rights.cr_rights[i] & ~(0x7FULL << 57)) != 0)
  321                                 return (EINVAL);
  322                 }
  323         }
  324         error = copyout(&rights, uap->rightsp, sizeof(rights.cr_rights[0]) * n);
  325 #ifdef KTRACE
  326         if (error == 0 && KTRPOINT(td, KTR_STRUCT))
  327                 ktrcaprights(&rights);
  328 #endif
  329         return (error);
  330 }
  331 
  332 /*
  333  * Test whether a capability grants the given ioctl command.
  334  * If descriptor doesn't have CAP_IOCTL, then ioctls list is empty and
  335  * ENOTCAPABLE will be returned.
  336  */
  337 int
  338 cap_ioctl_check(struct filedesc *fdp, int fd, u_long cmd)
  339 {
  340         u_long *cmds;
  341         ssize_t ncmds;
  342         long i;
  343 
  344         FILEDESC_LOCK_ASSERT(fdp);
  345         KASSERT(fd >= 0 && fd < fdp->fd_nfiles,
  346             ("%s: invalid fd=%d", __func__, fd));
  347 
  348         ncmds = fdp->fd_ofiles[fd].fde_nioctls;
  349         if (ncmds == -1)
  350                 return (0);
  351 
  352         cmds = fdp->fd_ofiles[fd].fde_ioctls;
  353         for (i = 0; i < ncmds; i++) {
  354                 if (cmds[i] == cmd)
  355                         return (0);
  356         }
  357 
  358         return (ENOTCAPABLE);
  359 }
  360 
  361 /*
  362  * Check if the current ioctls list can be replaced by the new one.
  363  */
  364 static int
  365 cap_ioctl_limit_check(struct filedesc *fdp, int fd, const u_long *cmds,
  366     size_t ncmds)
  367 {
  368         u_long *ocmds;
  369         ssize_t oncmds;
  370         u_long i;
  371         long j;
  372 
  373         oncmds = fdp->fd_ofiles[fd].fde_nioctls;
  374         if (oncmds == -1)
  375                 return (0);
  376         if (oncmds < (ssize_t)ncmds)
  377                 return (ENOTCAPABLE);
  378 
  379         ocmds = fdp->fd_ofiles[fd].fde_ioctls;
  380         for (i = 0; i < ncmds; i++) {
  381                 for (j = 0; j < oncmds; j++) {
  382                         if (cmds[i] == ocmds[j])
  383                                 break;
  384                 }
  385                 if (j == oncmds)
  386                         return (ENOTCAPABLE);
  387         }
  388 
  389         return (0);
  390 }
  391 
  392 int
  393 kern_cap_ioctls_limit(struct thread *td, int fd, u_long *cmds, size_t ncmds)
  394 {
  395         struct filedesc *fdp;
  396         u_long *ocmds;
  397         int error;
  398 
  399         AUDIT_ARG_FD(fd);
  400 
  401         fdp = td->td_proc->p_fd;
  402         FILEDESC_XLOCK(fdp);
  403 
  404         if (fget_locked(fdp, fd) == NULL) {
  405                 error = EBADF;
  406                 goto out;
  407         }
  408 
  409         error = cap_ioctl_limit_check(fdp, fd, cmds, ncmds);
  410         if (error != 0)
  411                 goto out;
  412 
  413         ocmds = fdp->fd_ofiles[fd].fde_ioctls;
  414         fdp->fd_ofiles[fd].fde_ioctls = cmds;
  415         fdp->fd_ofiles[fd].fde_nioctls = ncmds;
  416 
  417         cmds = ocmds;
  418         error = 0;
  419 out:
  420         FILEDESC_XUNLOCK(fdp);
  421         free(cmds, M_FILECAPS);
  422         return (error);
  423 }
  424 
  425 int
  426 sys_cap_ioctls_limit(struct thread *td, struct cap_ioctls_limit_args *uap)
  427 {
  428         u_long *cmds;
  429         size_t ncmds;
  430         int error;
  431 
  432         ncmds = uap->ncmds;
  433 
  434         if (ncmds > 256)        /* XXX: Is 256 sane? */
  435                 return (EINVAL);
  436 
  437         if (ncmds == 0) {
  438                 cmds = NULL;
  439         } else {
  440                 cmds = malloc(sizeof(cmds[0]) * ncmds, M_FILECAPS, M_WAITOK);
  441                 error = copyin(uap->cmds, cmds, sizeof(cmds[0]) * ncmds);
  442                 if (error != 0) {
  443                         free(cmds, M_FILECAPS);
  444                         return (error);
  445                 }
  446         }
  447 
  448         return (kern_cap_ioctls_limit(td, uap->fd, cmds, ncmds));
  449 }
  450 
  451 int
  452 sys_cap_ioctls_get(struct thread *td, struct cap_ioctls_get_args *uap)
  453 {
  454         struct filedesc *fdp;
  455         struct filedescent *fdep;
  456         u_long *cmds;
  457         size_t maxcmds;
  458         int error, fd;
  459 
  460         fd = uap->fd;
  461         cmds = uap->cmds;
  462         maxcmds = uap->maxcmds;
  463 
  464         AUDIT_ARG_FD(fd);
  465 
  466         fdp = td->td_proc->p_fd;
  467         FILEDESC_SLOCK(fdp);
  468 
  469         if (fget_locked(fdp, fd) == NULL) {
  470                 error = EBADF;
  471                 goto out;
  472         }
  473 
  474         /*
  475          * If all ioctls are allowed (fde_nioctls == -1 && fde_ioctls == NULL)
  476          * the only sane thing we can do is to not populate the given array and
  477          * return CAP_IOCTLS_ALL.
  478          */
  479 
  480         fdep = &fdp->fd_ofiles[fd];
  481         if (cmds != NULL && fdep->fde_ioctls != NULL) {
  482                 error = copyout(fdep->fde_ioctls, cmds,
  483                     sizeof(cmds[0]) * MIN(fdep->fde_nioctls, maxcmds));
  484                 if (error != 0)
  485                         goto out;
  486         }
  487         if (fdep->fde_nioctls == -1)
  488                 td->td_retval[0] = CAP_IOCTLS_ALL;
  489         else
  490                 td->td_retval[0] = fdep->fde_nioctls;
  491 
  492         error = 0;
  493 out:
  494         FILEDESC_SUNLOCK(fdp);
  495         return (error);
  496 }
  497 
  498 /*
  499  * Test whether a capability grants the given fcntl command.
  500  */
  501 int
  502 cap_fcntl_check_fde(struct filedescent *fde, int cmd)
  503 {
  504         uint32_t fcntlcap;
  505 
  506         fcntlcap = (1 << cmd);
  507         KASSERT((CAP_FCNTL_ALL & fcntlcap) != 0,
  508             ("Unsupported fcntl=%d.", cmd));
  509 
  510         if ((fde->fde_fcntls & fcntlcap) != 0)
  511                 return (0);
  512 
  513         return (ENOTCAPABLE);
  514 }
  515 
  516 int
  517 cap_fcntl_check(struct filedesc *fdp, int fd, int cmd)
  518 {
  519 
  520         KASSERT(fd >= 0 && fd < fdp->fd_nfiles,
  521             ("%s: invalid fd=%d", __func__, fd));
  522 
  523         return (cap_fcntl_check_fde(&fdp->fd_ofiles[fd], cmd));
  524 }
  525 
  526 int
  527 sys_cap_fcntls_limit(struct thread *td, struct cap_fcntls_limit_args *uap)
  528 {
  529         struct filedesc *fdp;
  530         uint32_t fcntlrights;
  531         int fd;
  532 
  533         fd = uap->fd;
  534         fcntlrights = uap->fcntlrights;
  535 
  536         AUDIT_ARG_FD(fd);
  537         AUDIT_ARG_FCNTL_RIGHTS(fcntlrights);
  538 
  539         if ((fcntlrights & ~CAP_FCNTL_ALL) != 0)
  540                 return (EINVAL);
  541 
  542         fdp = td->td_proc->p_fd;
  543         FILEDESC_XLOCK(fdp);
  544 
  545         if (fget_locked(fdp, fd) == NULL) {
  546                 FILEDESC_XUNLOCK(fdp);
  547                 return (EBADF);
  548         }
  549 
  550         if ((fcntlrights & ~fdp->fd_ofiles[fd].fde_fcntls) != 0) {
  551                 FILEDESC_XUNLOCK(fdp);
  552                 return (ENOTCAPABLE);
  553         }
  554 
  555         fdp->fd_ofiles[fd].fde_fcntls = fcntlrights;
  556         FILEDESC_XUNLOCK(fdp);
  557 
  558         return (0);
  559 }
  560 
  561 int
  562 sys_cap_fcntls_get(struct thread *td, struct cap_fcntls_get_args *uap)
  563 {
  564         struct filedesc *fdp;
  565         uint32_t rights;
  566         int fd;
  567 
  568         fd = uap->fd;
  569 
  570         AUDIT_ARG_FD(fd);
  571 
  572         fdp = td->td_proc->p_fd;
  573         FILEDESC_SLOCK(fdp);
  574         if (fget_locked(fdp, fd) == NULL) {
  575                 FILEDESC_SUNLOCK(fdp);
  576                 return (EBADF);
  577         }
  578         rights = fdp->fd_ofiles[fd].fde_fcntls;
  579         FILEDESC_SUNLOCK(fdp);
  580 
  581         return (copyout(&rights, uap->fcntlrightsp, sizeof(rights)));
  582 }
  583 
  584 #else /* !CAPABILITIES */
  585 
  586 /*
  587  * Stub Capability functions for when options CAPABILITIES isn't compiled
  588  * into the kernel.
  589  */
  590 
  591 int
  592 sys_cap_rights_limit(struct thread *td, struct cap_rights_limit_args *uap)
  593 {
  594 
  595         return (ENOSYS);
  596 }
  597 
  598 int
  599 sys___cap_rights_get(struct thread *td, struct __cap_rights_get_args *uap)
  600 {
  601 
  602         return (ENOSYS);
  603 }
  604 
  605 int
  606 sys_cap_ioctls_limit(struct thread *td, struct cap_ioctls_limit_args *uap)
  607 {
  608 
  609         return (ENOSYS);
  610 }
  611 
  612 int
  613 sys_cap_ioctls_get(struct thread *td, struct cap_ioctls_get_args *uap)
  614 {
  615 
  616         return (ENOSYS);
  617 }
  618 
  619 int
  620 sys_cap_fcntls_limit(struct thread *td, struct cap_fcntls_limit_args *uap)
  621 {
  622 
  623         return (ENOSYS);
  624 }
  625 
  626 int
  627 sys_cap_fcntls_get(struct thread *td, struct cap_fcntls_get_args *uap)
  628 {
  629 
  630         return (ENOSYS);
  631 }
  632 
  633 #endif /* CAPABILITIES */

Cache object: 4d65b3d0a8709362d2f13a6cb864a550


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