On Thu, Feb 02, 2023 at 09:56:16AM +0100, Kevin Brodsky wrote:
On 31/01/2023 12:24, Beata Michalska wrote:
diff --git a/include/linux/cheri.h b/include/linux/cheri.h new file mode 100644 index 000000000000..5f95f1ac8f01 --- /dev/null +++ b/include/linux/cheri.h @@ -0,0 +1,132 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef _LINUX_CHERI_H +#define _LINUX_CHERI_H
+#ifdef __CHERI__
+#include <cheriintrin.h>
+#include <linux/types.h>
+#include <uapi/asm/cheri.h> +#ifdef CONFIG_HAVE_ARCH_CHERI_H +#include <asm/cheri.h> +#endif
+/*
- Standard permission sets for new capabilities. Can be overridden by
- architectures to add arch-specific permissions.
- */
+#ifndef CHERI_PERMS_READ +#define CHERI_PERMS_READ \
- (CHERI_PERM_LOAD | CHERI_PERM_LOAD_CAP)
+#endif
+#ifndef CHERI_PERMS_WRITE +#define CHERI_PERMS_WRITE \
- (CHERI_PERM_STORE | CHERI_PERM_STORE_CAP | CHERI_PERM_STORE_LOCAL_CAP)
+#endif
+#ifndef CHERI_PERMS_EXEC +#define CHERI_PERMS_EXEC \
- (CHERI_PERM_EXECUTE | CHERI_PERM_SYSTEM_REGS)
+#endif
+#ifndef CHERI_PERMS_ROOTCAP +#define CHERI_PERMS_ROOTCAP \
- (CHERI_PERM_GLOBAL | CHERI_PERM_SW_VMEM)
+#endif
+/**
- cheri_build_user_cap() - Create a userspace capability.
- @addr: Requested capability address.
- @len: Requested capability length.
- @perms: Requested capability permissions.
- Return: A new capability derived from cheri_user_root_cap. Its address and
permissions are set according to @addr and @perms respectively. Its
bounds are set exactly with @addr as base address and @len as
length.
- The caller is responsible to ensure that:
- @addr is a valid userspace address.
- The (@addr, @len) tuple can be represented as capability bounds.
- @perms are valid permissions for a regular userspace capability.
- If either 1. or 2. does not hold, the resulting capability will be invalid.
- If 3. does not hold, the returned capability will not have any of the invalid
- permissions.
- */
+void * __capability +cheri_build_user_cap(ptraddr_t addr, size_t len, cheri_perms_t perms);
The returned capability might be invalid as of having tag cleared. I assume in most of the cases it will be just fine, but wondering if it would make sense to return either capability with null capability , or one that could be validated with PTR_ERR somewhat ? Just thinking at loud here, how one would verify the result is valid (currently it would need check tag but maybe we could utilize more generic way of validating pointers ... On the other hand those new helpers are available only when __CHERI__ is defined so I assume there are only to be used in CHERI-related contexts ?
Yes, those helpers can only be used directly by CHERI-specific code. As to the issue of the returned capability being invalid, that would be a bug, i.e. the caller asked for bounds that are not representable (in the exact case) or are not within the userspace range. That's why there is a WARN() in the implementation: in such a case, the caller broke the contract and we report a bug. I think it makes more sense to do it this way than require the caller to check for errors, because there is no "normal error" here, only invalid usage.
Noted & agreed.
+/**
- cheri_build_user_cap_inexact_bounds() - Create a userspace capability,
allowing bounds to be enlarged.
- @addr: Requested capability address.
- @len: Requested capability length.
- @perms: Requested capability permissions.
- Return: A new capability derived from cheri_user_root_cap. Its address and
permissions are set according to @addr and @perms respectively. Its
bounds are set to the smallest representable range that includes the
range [@addr, @addr + @len[.
- This variant of cheri_build_user_cap() should only be used when it is safe to
- enlarge the bounds of the capability. In particular, it should never be used
- when creating a capability that is to be provided to userspace, because the
- potentially enlarged bounds might give access to unrelated objects.
- The caller is responsible to ensure that:
- @addr is a valid userspace address.
- @perms are valid permissions for a regular userspace capability.
- If 1. does not hold, the resulting capability will be invalid.
- If 2. does not hold, the returned capability will not have any of the invalid
- permissions.
- */
+void * __capability +cheri_build_user_cap_inexact_bounds(ptraddr_t addr, size_t len,
cheri_perms_t perms);
+/**
- cheri_check_cap() - Check whether a capability gives access to a range of
addresses.
- @cap: Capability to check.
- @len: Length of the access.
- @perms: Required permissions.
- Checks whether @cap gives access to a given range of addresses and has the
- requested permissions. This means that:
- @cap is valid and unsealed.
- The range [@cap.address, @cap.address + @len[ is within the bounds
- of @cap.
- The permissions of @cap include at least @perms.
- Return: true if @cap passes the checks.
- */
+bool cheri_check_cap(void * __capability cap, size_t len, cheri_perms_t perms);
Minor but maybe void * __capability with const qualifier ?
Makes sense yes, capabilities are still pointers after all, and const correctness never hurts :)
+/*
- Root capabilities. Should be set in arch code during the early init phase,
- read-only after that.
- cheri_user_root_cap is the standard root capability to derive new regular
- (data/code) capabilities from. It does not include the special permissions
- Seal/Unseal and CompartmentID; those are available separately via
- cheri_user_root_{seal,cid}_cap. Finally cheri_user_root_all_cap includes all
- permissions accessible to userspace and is ultimately the root of all user
- capabilities; it should only be used in very specific situations.
- The helpers above should be used instead where possible.
- */
+extern uintcap_t cheri_user_root_cap; /* Userspace (data/code) root */ +extern uintcap_t cheri_user_root_seal_cap; /* Userspace sealing root */ +extern uintcap_t cheri_user_root_cid_cap; /* Userspace compartment ID root */ +extern uintcap_t cheri_user_root_all_cap; /* Userspace root (all permissions) */
xxx_root_all_cap somehwat reads to me as 'all capabilities' instead of 'capability with all permissions' even the context guards the interpretation, but maybe xxx_root_fill_cap instead ?
Right, that's the issue with this naming scheme. I'm not sure what you're referring to with "fill" though? How about explicitly "allperms"?
My usual misspelling ... I meant 'full' as of : cheri_user_root_full_cap. Having 'allperms' seems adequate as well.
--- BR B.
Kevin
+#endif /* __CHERI__ */
+#endif /* _LINUX_CHERI_H */