On 18/10/2022 22:20, Beata Michalska wrote:
+/**
+ * cheri_build_user_cap() - Create a userspace capability.
+ * @addr: Requested capability address.
+ * @len: Requested capability length.
+ * @perms: Requested capability permissions.
+ *
+ * Returns a new capability derived from the root userspace
capability. 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:
+ * 1. @addr is a valid userspace address.
+ * 2. The (@addr, @len) tuple can be represented as capability bounds.
+ * 3. @perms are valid permissions for a 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);
This builds full capability data so may be cheri_build_user_cap_data(
used below for access function) or cheri_build_user_data.
I see your point. It all boils down to sealing in fact, as everything else
is specified to the function as parameters. For
cheri_check_cap_data_access() I thought it was important to say "data" as
you cannot use this function to check a function pointer - it would be
RB-sealed and therefore fail the sealing test.

I was less sure it made sense to say "data" for this function as it can be
used to construct capabilities with any permissions, including Executable,
but arguably it's also true that you can check for Executable using
cheri_check_cap_data_access(). We should probably say "data" in both or
neither.

I guess this choice is related to another, which is what we would do if we
had to handle function pointers (I don't expect we will, but it helps
thinking about it). There are essentially two options: 1. have a new set of
functions with "code" in their name, or 2. use the same functions and do the
sealing/unsealing manually. 1. corresponds to saying "data" for the present
functions, and 2. to not saying "data".

Maybe we should keep it simple and go for 2. but opinions welcome here.
I am not entirely convinced that having the distinction here 'data' vs 'code'
would be very much useful: this function could create both, and it can be
extended to cover sealing case needed - not sure why manual sealing though...

I suppose we could indeed add an argument later to ask for a sentry (RB-sealed capability on Morello).

(cheri_root_seal_cap_userspace is already/will be there ?)
(on a side note, sealed capability does not automatically denote function
pointers even though that is not the use case we will be supporting, I guess).

We are specifically talking about sentries here (RB object type on Morello). It is expected that all function pointers are sentries in purecap.

On the other hand chari_check_cap_data_access could potentially check whether
the cap has Executable permission set if selaed and consider that as valid ?

I would really like this to be explicit, but like the build function it could be a new argument.

So to summarise my thinking after your feedback (thanks for that!):
* cheri_build_user_cap() remains unchanged.
* cheri_check_cap_data_access() can be simply cheri_check_cap(), the meaning of "check" being inferred from the arguments passed to the function.

"data" is gone, if and when we want to handle things like function pointers we can add a new argument or create special functions.

Does that sound fair?

Kevin