Date: Mon, 3 Feb 2020 17:08:12 +0000 (UTC) From: Mateusz Guzik <mjg@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r357452 - in head/sys: kern sys Message-ID: <202002031708.013H8CV7076993@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mjg Date: Mon Feb 3 17:08:11 2020 New Revision: 357452 URL: https://svnweb.freebsd.org/changeset/base/357452 Log: capsicum: faster cap_rights_contains Instead of doing a 2 iteration loop (determined at runeimt), take advantage of the fact that the size is already known. While here provdie cap_check_inline so that fget_unlocked does not have to do a function call. Verified with the capsicum suite /usr/tests. Modified: head/sys/kern/kern_descrip.c head/sys/kern/subr_capability.c head/sys/kern/sys_capability.c head/sys/sys/capsicum.h Modified: head/sys/kern/kern_descrip.c ============================================================================== --- head/sys/kern/kern_descrip.c Mon Feb 3 17:06:21 2020 (r357451) +++ head/sys/kern/kern_descrip.c Mon Feb 3 17:08:11 2020 (r357452) @@ -2724,7 +2724,7 @@ fget_unlocked(struct filedesc *fdp, int fd, cap_rights if (fp == NULL) return (EBADF); #ifdef CAPABILITIES - error = cap_check(&haverights, needrightsp); + error = cap_check_inline(&haverights, needrightsp); if (error != 0) return (error); #endif Modified: head/sys/kern/subr_capability.c ============================================================================== --- head/sys/kern/subr_capability.c Mon Feb 3 17:06:21 2020 (r357451) +++ head/sys/kern/subr_capability.c Mon Feb 3 17:08:11 2020 (r357452) @@ -394,25 +394,3 @@ cap_rights_remove(cap_rights_t *dst, const cap_rights_ return (dst); } - -bool -cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little) -{ - unsigned int i, n; - - assert(CAPVER(big) == CAP_RIGHTS_VERSION_00); - assert(CAPVER(little) == CAP_RIGHTS_VERSION_00); - assert(CAPVER(big) == CAPVER(little)); - - n = CAPARSIZE(big); - assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX); - - for (i = 0; i < n; i++) { - if ((big->cr_rights[i] & little->cr_rights[i]) != - little->cr_rights[i]) { - return (false); - } - } - - return (true); -} Modified: head/sys/kern/sys_capability.c ============================================================================== --- head/sys/kern/sys_capability.c Mon Feb 3 17:06:21 2020 (r357451) +++ head/sys/kern/sys_capability.c Mon Feb 3 17:08:11 2020 (r357452) @@ -179,6 +179,17 @@ cap_check(const cap_rights_t *havep, const cap_rights_ return (_cap_check(havep, needp, CAPFAIL_NOTCAPABLE)); } +int +cap_check_failed_notcapable(const cap_rights_t *havep, const cap_rights_t *needp) +{ + +#ifdef KTRACE + if (KTRPOINT(curthread, KTR_CAPFAIL)) + ktrcapfail(CAPFAIL_NOTCAPABLE, needp, havep); +#endif + return (ENOTCAPABLE); +} + /* * Convert capability rights into VM access flags. */ Modified: head/sys/sys/capsicum.h ============================================================================== --- head/sys/sys/capsicum.h Mon Feb 3 17:06:21 2020 (r357451) +++ head/sys/sys/capsicum.h Mon Feb 3 17:08:11 2020 (r357452) @@ -342,8 +342,37 @@ bool __cap_rights_is_set(const cap_rights_t *rights, . bool cap_rights_is_valid(const cap_rights_t *rights); cap_rights_t *cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src); cap_rights_t *cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src); -bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little); void __cap_rights_sysinit(void *arg); + + +/* + * We only support one size to reduce branching. + */ +_Static_assert(CAP_RIGHTS_VERSION == CAP_RIGHTS_VERSION_00, + "unsupported version of capsicum rights"); + +static inline bool +cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little) +{ + + if (__predict_true( + (big->cr_rights[0] & little->cr_rights[0]) == little->cr_rights[0] && + (big->cr_rights[1] & little->cr_rights[1]) == little->cr_rights[1])) + return (true); + return (false); +} + +int cap_check_failed_notcapable(const cap_rights_t *havep, + const cap_rights_t *needp); + +static inline int +cap_check_inline(const cap_rights_t *havep, const cap_rights_t *needp) +{ + + if (__predict_false(!cap_rights_contains(havep, needp))) + return (cap_check_failed_notcapable(havep, needp)); + return (0); +} __END_DECLS struct cap_rights_init_args {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202002031708.013H8CV7076993>