diff --git a/contrib/capsicum-test/capability-fd.cc b/contrib/capsicum-test/capability-fd.cc --- a/contrib/capsicum-test/capability-fd.cc +++ b/contrib/capsicum-test/capability-fd.cc @@ -1342,3 +1342,18 @@ close(fd); unlink(TmpFile("cap_root_owned")); } + +TEST(Capability, CheckIsEmpty) { + cap_rights_t rights; + + cap_rights_init(&rights); + EXPECT_TRUE(cap_rights_is_empty(&rights)); + + size_t num_known = (sizeof(known_rights)/sizeof(known_rights[0])); + for (size_t ii = 0; ii < num_known; ii++) { + cap_rights_init(&rights, known_rights[ii].right); + EXPECT_FALSE(cap_rights_is_empty(&rights)); + cap_rights_clear(&rights, known_rights[ii].right); + EXPECT_TRUE(cap_rights_is_empty(&rights)); + } +} diff --git a/lib/libc/capability/Symbol.map b/lib/libc/capability/Symbol.map --- a/lib/libc/capability/Symbol.map +++ b/lib/libc/capability/Symbol.map @@ -8,3 +8,7 @@ cap_rights_remove; __cap_rights_set; }; + +FBSD_1.8 { + cap_rights_is_empty; +}; diff --git a/lib/libc/capability/cap_rights_init.3 b/lib/libc/capability/cap_rights_init.3 --- a/lib/libc/capability/cap_rights_init.3 +++ b/lib/libc/capability/cap_rights_init.3 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd May 5, 2020 +.Dd November 25, 2023 .Dt CAP_RIGHTS_INIT 3 .Os .Sh NAME @@ -33,6 +33,7 @@ .Nm cap_rights_set , .Nm cap_rights_clear , .Nm cap_rights_is_set , +.Nm cap_rights_is_empty , .Nm cap_rights_is_valid , .Nm cap_rights_merge , .Nm cap_rights_remove , @@ -51,6 +52,8 @@ .Ft bool .Fn cap_rights_is_set "const cap_rights_t *rights" "..." .Ft bool +.Fn cap_rights_is_empty "const cap_rights_t *rights" +.Ft bool .Fn cap_rights_is_valid "const cap_rights_t *rights" .Ft cap_rights_t * .Fn cap_rights_merge "cap_rights_t *dst" "const cap_rights_t *src" @@ -118,6 +121,12 @@ structure. .Pp The +.Fn cap_rights_is_empty +function checks if the +.Fa rights +structure is empty. +.Pp +The .Fn cap_rights_is_valid function verifies if the given .Vt cap_rights_t @@ -182,6 +191,14 @@ argument. .Pp The +.Fn cap_rights_is_empty +function returns +.Va true +if none of the capability rights are set in the +.Fa rights +structure. +.Pp +The .Fn cap_rights_is_valid function performs various checks to see if the given .Vt cap_rights_t diff --git a/sys/kern/subr_capability.c b/sys/kern/subr_capability.c --- a/sys/kern/subr_capability.c +++ b/sys/kern/subr_capability.c @@ -306,6 +306,25 @@ return (ret); } +bool +cap_rights_is_empty(const cap_rights_t *rights) +{ +#ifndef _KERNEL + cap_rights_t cap_no_rights; + cap_rights_init(&cap_no_rights); +#endif + + assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00); + assert(CAPVER(&cap_no_rights) == CAP_RIGHTS_VERSION_00); + + for (int i = 0; i < CAPARSIZE(rights); i++) { + if (rights->cr_rights[i] != cap_no_rights.cr_rights[i]) + return (false); + } + + return (true); +} + bool cap_rights_is_valid(const cap_rights_t *rights) { diff --git a/sys/sys/capsicum.h b/sys/sys/capsicum.h --- a/sys/sys/capsicum.h +++ b/sys/sys/capsicum.h @@ -336,6 +336,8 @@ __cap_rights_is_set(__VA_ARGS__, 0ULL) bool __cap_rights_is_set(const cap_rights_t *rights, ...); +bool cap_rights_is_empty(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);