diff options
author | Mariusz Zaborski <oshogbo@FreeBSD.org> | 2023-12-11 11:09:31 +0000 |
---|---|---|
committer | Ed Maste <emaste@FreeBSD.org> | 2024-06-05 15:55:17 +0000 |
commit | e77813f7e4a32be5d0278c5cb38bcc0a759025d0 (patch) | |
tree | 70844d09ae182eda7bb3231f787f844df60155d0 | |
parent | 91badda4a2ddf243b654269c0689d748557d2be1 (diff) | |
download | src-e77813f7e4a32be5d0278c5cb38bcc0a759025d0.tar.gz src-e77813f7e4a32be5d0278c5cb38bcc0a759025d0.zip |
capsicum: introduce cap_rights_is_empty Function
Before this commit, we only had the capability to check if a specific
capability was set (using cap_rights_is_set function). However, there
was no efficient method to determine if a cap_rights_t structure doesn't
contain any capability. The cap_rights_is_empty function addresses
this gap.
PR: 275330
Reported by: vini.ipsmaker@gmail.com
Reviewed by: emaste, markj
Differential Revision: https://reviews.freebsd.org/D42780
(cherry picked from commit a7100ae23aca07976926bd8d50223c45149f65d6)
-rw-r--r-- | contrib/capsicum-test/capability-fd.cc | 15 | ||||
-rw-r--r-- | lib/libc/capability/Symbol.map | 4 | ||||
-rw-r--r-- | lib/libc/capability/cap_rights_init.3 | 19 | ||||
-rw-r--r-- | sys/kern/subr_capability.c | 19 | ||||
-rw-r--r-- | sys/sys/capsicum.h | 2 |
5 files changed, 58 insertions, 1 deletions
diff --git a/contrib/capsicum-test/capability-fd.cc b/contrib/capsicum-test/capability-fd.cc index f255c6425cdd..0551d9bd81ef 100644 --- a/contrib/capsicum-test/capability-fd.cc +++ b/contrib/capsicum-test/capability-fd.cc @@ -1342,3 +1342,18 @@ TEST(Capability, NoBypassDACIfRoot) { 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 index 0deff024a046..8bf11670a5a8 100644 --- a/lib/libc/capability/Symbol.map +++ b/lib/libc/capability/Symbol.map @@ -8,3 +8,7 @@ FBSD_1.3 { 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 index 80b522820097..98b50f653f2c 100644 --- 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 @@ function checks if all the given capability rights are set for the given 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 @@ if all the given capability rights are set in the 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 index e40c57c5307d..1f3a181a91cb 100644 --- a/sys/kern/subr_capability.c +++ b/sys/kern/subr_capability.c @@ -307,6 +307,25 @@ __cap_rights_is_set(const cap_rights_t *rights, ...) } 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) { cap_rights_t allrights; diff --git a/sys/sys/capsicum.h b/sys/sys/capsicum.h index e2f305462f0d..405a7af419bf 100644 --- a/sys/sys/capsicum.h +++ b/sys/sys/capsicum.h @@ -337,6 +337,8 @@ cap_rights_t *__cap_rights_clear(cap_rights_t *rights, ...); __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); |