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

Cache object: 226482a0dd754caefd26448bdfd60c8e


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