Helper functions such as capability_owns_range() and build_owning_capability() are added as per PCuABI specifications.
These may be helpful in adding different PCuABI reservation constraints.
Note: These helper functions do not check for capability permission constraints and full support will be added later.
Signed-off-by: Amit Daniel Kachhap amit.kachhap@arm.com --- include/linux/cap_addr_mgmt.h | 22 ++++++++++++++++++++++ lib/cap_addr_mgmt.c | 21 +++++++++++++++++++++ 2 files changed, 43 insertions(+)
diff --git a/include/linux/cap_addr_mgmt.h b/include/linux/cap_addr_mgmt.h index fd67e9b21ecd..c8040871316b 100644 --- a/include/linux/cap_addr_mgmt.h +++ b/include/linux/cap_addr_mgmt.h @@ -107,6 +107,28 @@ int reserv_mt_delete_range(struct maple_tree *rv_mt, unsigned long start, */ void __init reserv_mt_init(void);
+/** + * capability_owns_range() - Check if the address range is within the valid + * capability bound. + * @cap: A Capability value. + * @addr: Address start value. + * @len: Address length. + * + * Return: True if address within the capability bound or false otherwise. + */ +bool capability_owns_range(uintcap_t cap, unsigned long addr, unsigned long len); + +/** + * build_owning_capability() - Creates a userspace capability after converting + * protection flags to the relevant capability permission fl. + * @addr: Requested capability address. + * @len: Requested capability length. + * @prot: Requested protection flags. + * + * Return: A new capability derived from cheri_user_root_cap. + */ +uintcap_t build_owning_capability(unsigned long addr, unsigned long len, int prot); + #endif /* CONFIG_CHERI_PURECAP_UABI */
#endif /* _LINUX_CAP_ADDR_MGMT_H */ diff --git a/lib/cap_addr_mgmt.c b/lib/cap_addr_mgmt.c index e22868506e70..f6007a4e9c4e 100644 --- a/lib/cap_addr_mgmt.c +++ b/lib/cap_addr_mgmt.c @@ -179,3 +179,24 @@ void __init reserv_mt_init(void) { reserv_mt_entry_cachep = KMEM_CACHE(reserv_mt_entry, SLAB_PANIC|SLAB_ACCOUNT); } + +bool capability_owns_range(uintcap_t cap, unsigned long addr, unsigned long len) +{ + unsigned long align_addr = round_down(addr, PAGE_SIZE); + unsigned long align_len = cheri_representable_length(round_up(len, PAGE_SIZE)); + + return cheri_check_cap((const void * __capability)cheri_address_set(cap, align_addr), + align_len, CHERI_PERM_GLOBAL | CHERI_PERM_SW_VMEM); +} + +uintcap_t build_owning_capability(unsigned long start, unsigned long len, int prot __maybe_unused) +{ + unsigned long align_start = round_down(start, PAGE_SIZE); + unsigned long align_len = cheri_representable_length(round_up(len, PAGE_SIZE)); + + /* TODO [PCuABI] - capability permission conversion from memory permission */ + cheri_perms_t perms = CHERI_PERMS_READ | CHERI_PERMS_WRITE | + CHERI_PERMS_EXEC | CHERI_PERMS_ROOTCAP; + + return (uintcap_t)cheri_build_user_cap(align_start, align_len, perms); +}