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:
parent
2abdae33b1
commit
bcd1cf4f03
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user