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.
This commit is contained in:
Mateusz Guzik 2020-02-03 17:08:11 +00:00
parent 2abdae33b1
commit bcd1cf4f03
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=357452
4 changed files with 42 additions and 24 deletions

View File

@ -2724,7 +2724,7 @@ fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp,
if (fp == NULL)
return (EBADF);
#ifdef CAPABILITIES
error = cap_check(&haverights, needrightsp);
error = cap_check_inline(&haverights, needrightsp);
if (error != 0)
return (error);
#endif

View File

@ -394,25 +394,3 @@ cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src)
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);
}

View File

@ -179,6 +179,17 @@ cap_check(const cap_rights_t *havep, const cap_rights_t *needp)
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.
*/

View File

@ -342,9 +342,38 @@ 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 {
cap_rights_t *cria_rights;