Syscalls operating on memory mappings manage their address space via
owning capabilities. They must adhere to a certain set of rules[1] in
order to ensure memory safety. Address space management syscalls are
only allowed to manipulate mappings that are within the range of the
owning capability and have the appropriate permissions. Tests to check
the capability's tag, bounds, range as well as permissions have been
added. Finally, as certain flags and syscalls conflict with the
reservation model or lack implementation, a check to verify appropriate
handling of the same has also been added.
The mincore() tests are expected to fail in this iteration as they are
not fully supported. The next iterations will contain representability
testcases.
Review branch:
https://git.morello-project.org/chaitanya_prakash/linux/-/tree/review/purec…
This patch series has been tested on:
https://git.morello-project.org/amitdaniel/linux/-/tree/review/purecap_mm_r…
[1] https://git.morello-project.org/morello/kernel/linux/-/wikis/Morello-pure-c…
Changes in V3:
- Added get_pagesize() function and VERRIFY_ERRNO() macro
- Added LoadCap and StoreCap permissions testcase
- Added validity_tag_check testcases
- Added reservation tests
- Renamed variable "addr" to "ptr" to avoid confusion when manipulating
both addresses and capabilities
- Cleaned up syscall_mmap and syscall_mmap2 testcases
- Restructured code into testcases that check tags, range, bounds
and permissions
- Improved range_check testcases
- Improved commit messages
- Removed helper functions, tests directly written in testcase functions
- Removed signal handling and ddc register testcases
Changes in V2:
https://op-lists.linaro.org/archives/list/linux-morello@op-lists.linaro.org…
- Added link to the review branch
- Removed unnecessary whitespace
Changes in V1:
https://op-lists.linaro.org/archives/list/linux-morello@op-lists.linaro.org…
Chaitanya S Prakash (11):
kselftests/arm64: morello: Create wrapper functions for frequently
invoked syscalls
kselftests/arm64: morello: Add get_pagesize() function
kselftests/arm64: morello: Add VERIFY_ERRNO() macro
kselftests/arm64: morello: mmap: Clean up existing testcases
kselftests/arm64: morello: mmap: Add MAP_GROWSDOWN testcase
kselftests/arm64: morello: mmap: Add validity tag check testcases
kselftests/arm64: morello: mmap: Add capability range testcases
kselftests/arm64: morello: mmap: Add mmap() bounds check testcases
kselftests/arm64: morello: mmap: Add mremap() bounds check testcases
kselftests/arm64: morello: mmap: Add permission check testcases
kselftests/arm64: morello: mmap: Add brk() testcase
.../selftests/arm64/morello/bootstrap.c | 13 -
.../selftests/arm64/morello/freestanding.c | 16 +-
.../selftests/arm64/morello/freestanding.h | 74 ++-
tools/testing/selftests/arm64/morello/mmap.c | 547 +++++++++++++++++-
4 files changed, 606 insertions(+), 44 deletions(-)
--
2.25.1
Next version of Harry's tcp_zerocopy_receive series. It aims to enable
purecap applications to utilise tcp_zerocopy_receive to map packets
directly from a network interface card into a shared space with the
process and kernel.
v3..v4:
- Remove function tcp_zerocopy_receive_size() as it's used in only
one spot
- Change form compat to compat64 in the commit messages.
- Make initialisation of compat_zc more compact in
set_compat64_tcp_zerocopy_receive()
- Split copy_{from,to}_sockptr_with_ptr() into a separate commit
- Leave address tcp_zerocopy_vm_insert_batch() as just an address, not
a pointer
- Change the check_user_ptr_read() to a check for CHERI_PERM_SW_VMEM
v2..v3:
- Fix the split between compat enablement and capability support
- Reorganise comments in struct tcp_zerocopy_receive
- Fix the order of arguments for the *_to_sockptr functions
- Change a few variables to user_uintptr_t as they were originally
unsigned long
- Remove unnecessary checks
- Fix cast warnings
- Add compat handling for offsetofend
- Move a check_user_ptr closer to where its metadata is dropped
- Format misc nits
Gitlab Issue:
https://git.morello-project.org/morello/kernel/linux/-/issues/46
Review branch:
https://git.morello-project.org/tudcre01/linux/-/commits/morello/tcp_v4
Cc: Harry Ramsey <harry.ramsey(a)arm.com>
Harry Ramsey (3):
sockptr: Preserve capability tags with copy_{from,to}_sockptr_with_ptr
tcp: Implement compat64 handling for struct tcp_zerocopy_receive
tcp: Support capabilities in tcp_zerocopy_receive
include/linux/sockptr.h | 28 ++++++++
include/uapi/linux/tcp.h | 10 +--
net/ipv4/tcp.c | 148 +++++++++++++++++++++++++++++++--------
3 files changed, 151 insertions(+), 35 deletions(-)
--
2.34.1
Next version of Harry's tcp_zerocopy_receive series. It aims to enable
purecap applications to utilise tcp_zerocopy_receive to map packets
directly from a network interface card into a shared space with the
process and kernel.
v2..v3:
- Fix the split between compat enablement and capability support
- Reorganise comments in struct tcp_zerocopy_receive
- Fix the order of arguments for the *_to_sockptr functions
- Change a few variables to user_uintptr_t as they were originally
unsigned long
- Remove unnecessary checks
- Fix cast warnings
- Add compat handling for offsetofend
- Move a check_user_ptr closer to where its metadata is dropped
- Format misc nits
Gitlab Issue:
https://git.morello-project.org/morello/kernel/linux/-/issues/46
Review branch:
https://git.morello-project.org/tudcre01/linux/-/commits/morello/tcp_v3
Cc: Harry Ramsey <harry.ramsey(a)arm.com>
Harry Ramsey (2):
tcp: Implement compat handling for struct tcp_zerocopy_receive
tcp: Support capabilities in tcp_zerocopy_receive
include/linux/sockptr.h | 28 +++++++
include/uapi/linux/tcp.h | 10 +--
net/ipv4/tcp.c | 157 +++++++++++++++++++++++++++++++--------
3 files changed, 157 insertions(+), 38 deletions(-)
--
2.34.1
Hello,
This patch series enables purecap applications to utilise
tcp_zerocopy_receive to map packets directly from a network interface
card into a shared space with the process and kernel.
I do not think I shall have time to continue revising this patch series
and debugging the bus error generated by the latest patch. Hopefully
this provides a start to tcp_zerocopy_receive for capability
architecture.
v2:
- There appears to be a new error generated against musl resulting in a
BUS error when using memcpy to copy between allocated shared space
and other regions of memory.
- Rebase patch order to ensure aarch64 support throughout commits.
- Fix naming convention format issues for compat structs and functions.
- Remove uaddr_to_user_ptr usage to enforce capability model.
v1:
I have tested these changes against musl and there still exists an issue
in this implementation with copybuf and potentially msg_control
generating an EFAULT error.
Gitlab Issue:
- https://git.morello-project.org/morello/kernel/linux/-/issues/46
Review branch:
- https://git.morello-project.org/harryramsey/linux/-/commits/tcp_zerocopy
Thanks,
Harry
Harry Ramsey (2):
tcp: Implement compat version of tcp_zerocopy_receive
tcp: Support userspace capabilities for tcp_zerocopy_receive
include/linux/sockptr.h | 28 ++++++++
include/uapi/linux/tcp.h | 6 +-
net/ipv4/tcp.c | 135 ++++++++++++++++++++++++++++++++++-----
3 files changed, 149 insertions(+), 20 deletions(-)
--
2.34.1
Hello,
This patch series enables purecap applications to utilise
tcp_zerocopy_receive to map packets directly from a network interface
card into a shared space with the process and kernel.
I have tested these changes against musl and there still exists an issue
in this implementation with copybuf and potentially msg_control
generating an EFAULT error.
Gitlab Issue:
- https://git.morello-project.org/morello/kernel/linux/-/issues/46
Review branch:
- https://git.morello-project.org/harryramsey/linux/-/commits/tcp_zerocopy
Thanks,
Harry
Harry Ramsey (2):
tcp: Support userspace capabilities for tcp_zerocopy_receive
tcp: Implement compat version of tcp_zerocopy_receive
include/linux/sockptr.h | 28 ++++++++++
include/uapi/linux/tcp.h | 27 +++++++---
net/ipv4/tcp.c | 111 +++++++++++++++++++++++++++++++++------
3 files changed, 145 insertions(+), 21 deletions(-)
--
2.34.1
Now that explicit capability checking is carried out in the core
kernel and the drivers that are already supported in PCuABI, add a
section to the porting guide explaining in which situations explicit
checking might be required and what should be done.
Also add a few notes to the table of code examples, to make it clear
that using the new user pointer API is not necessarily enough in
itself.
Signed-off-by: Kevin Brodsky <kevin.brodsky(a)arm.com>
---
A follow-up to Luca's explicit checking series.
Rendered doc:
https://git.morello-project.org/kbrodsky-arm/linux/-/blob/porting_guide_exp…
Documentation/cheri/pcuabi-porting.rst | 81 +++++++++++++++++++++-----
1 file changed, 67 insertions(+), 14 deletions(-)
diff --git a/Documentation/cheri/pcuabi-porting.rst b/Documentation/cheri/pcuabi-porting.rst
index 2a38862e869a..fcda3b0f1d83 100644
--- a/Documentation/cheri/pcuabi-porting.rst
+++ b/Documentation/cheri/pcuabi-porting.rst
@@ -15,20 +15,25 @@ The appropriate API to represent and convert user pointers is described
in the `user pointer documentation`_. A few examples of modifications
required for PCuABI compliance:
-+--------------------------------+------------------------------------+
-| Invalid code | Potential replacement |
-+================================+====================================+
-| ``(unsigned long)uptr`` | ``user_ptr_addr(uptr)`` |
-+--------------------------------+------------------------------------+
-| ``(void __user *)u64`` | | ``uaddr_to_user_ptr(u64)`` |
-| | | ``as_user_ptr(u64)`` |
-+--------------------------------+------------------------------------+
-| ``get_user(uptr, &uarg->ptr)`` | ``get_user_ptr(uptr, &uarg->ptr)`` |
-+--------------------------------+------------------------------------+
-| ``IS_ERR(ubuf)`` | ``USER_PTR_IS_ERR(ubuf)`` |
-+--------------------------------+------------------------------------+
-| ... | ... |
-+--------------------------------+------------------------------------+
++--------------------------------+------------------------------------+------------------------------------------+
+| Invalid code | Potential replacement | Notes |
++================================+====================================+==========================================+
+| ``(unsigned long)uptr`` | ``user_ptr_addr(uptr)`` | Extracting the address of a user pointer |
+| | | may indicate that explicit capability |
+| | | checking is required, see the |
+| | | `Explicit capability checking`_ section. |
++--------------------------------+------------------------------------+------------------------------------------+
+| ``(void __user *)u64`` | | ``uaddr_to_user_ptr(u64)`` | Creating a user pointer from an address |
+| | | ``as_user_ptr(u64)`` | should be avoided. |
+| | | uapi structs may need to be modified to |
+| | | hold full user pointers. |
++--------------------------------+------------------------------------+------------------------------------------+
+| ``get_user(uptr, &uarg->ptr)`` | ``get_user_ptr(uptr, &uarg->ptr)`` | |
++--------------------------------+------------------------------------+------------------------------------------+
+| ``IS_ERR(ubuf)`` | ``USER_PTR_IS_ERR(ubuf)`` | |
++--------------------------------+------------------------------------+------------------------------------------+
+| ... | ... | |
++--------------------------------+------------------------------------+------------------------------------------+
``ioctl`` handlers' third argument
==================================
@@ -363,6 +368,54 @@ of the `PCuABI documentation`_. For instance::
Fortunately, ``__user`` is mostly used in simple types, and such fixups
are rarely needed in driver code.
+Explicit capability checking
+============================
+
+In the vast majority of cases, the memory referenced by user pointers is
+accessed through the user mapping, using uaccess functions such as
+``copy_from_user()``. As long as the original user pointer is wholly
+propagated to the uaccess function, no particular attention is required.
+
+In certain situations, such accesses may instead occur via a kernel
+mapping (of the same underlying pages). Often, this kernel mapping is
+created by a function in the GUP family (``get_user_pages()``,
+``pin_user_pages()``). These cases should be carefully considered and
+typically require the user pointer to be explicitly checked (see below).
+
+The following code patterns may indicate that user memory is being
+accessed via a kernel mapping:
+
+* A call to any function named ``get_user_pages*`` or
+ ``pin_user_pages*``. Explicit checking is generally required before
+ calling such a function. Note that this does not normally apply to
+ ``{get,pin}_user_pages_remote()``, because they are intended to access
+ another process's memory and such an operation does not need to (and
+ typically cannot) be authorised by a capability.
+
+* Casting a user pointer to an integer (``(unsigned long)uptr``). This
+ typically indicates that an address-based operation, such as GUP, is
+ going to be carried out. ``user_ptr_addr()`` should be used instead of
+ the cast, but the way the address is used should also be carefully
+ considered.
+
+* Calling ``access_ok()``. Standard uaccess functions call that function
+ themselves, so an explicit call indicates either that a low-level
+ uaccess function (e.g. ``__copy_from_user()``) is going to be used -
+ which is fine - or that the access is not going to be done via uaccess
+ at all - which requires explicit checking. Note that ``access_ok()``
+ does not itself require a valid capability (i.e. it only considers the
+ address) and ``as_user_ptr()`` may occasionally be needed to pass it
+ a raw user address, but in general a full user pointer should be
+ provided by userspace and validated (either by uaccess or explicit
+ checking).
+
+Explicit checking should be done using one of the ``check_user_ptr_*()``
+functions, see the "Explicit checking" section of the `user pointer
+documentation`_. The required permissions (R/W/RW) should be minimal: if
+the kernel only reads memory via the pointer, then
+``check_user_ptr_read()`` should be used, so that a pointer without
+write permission will pass the check.
+
.. _user pointer documentation: Documentation/core-api/user_ptr.rst
.. _PCuABI documentation: Documentation/cheri/pcuabi.rst
.. _pure-capability kernel-user ABI: `PCuABI documentation`_
--
2.38.1
Hi,
This small series disables KSM (Kernel Samepage Merging) in the Morello
defconfig, as it is currently unsafe in the presence of tags - see patch
1 for details. To guarantee correctness even if it is manually enabled,
patch 2 forces memcmp_pages() to report a difference.
It is quite possible that KSM would still be worthwhile even with the
extra cost of comparing tags. Issue #62 [1] covers that investigation.
Review branch:
https://git.morello-project.org/kbrodsky-arm/linux/-/commits/morello/disabl…
Cheers,
Kevin
[1] https://git.morello-project.org/morello/kernel/linux/-/issues/62
Kevin Brodsky (2):
arm64: morello: Disable KSM in defconfig
arm64: morello: Make memcmp_pages() always report a difference
.../configs/morello_transitional_pcuabi_defconfig | 1 -
arch/arm64/kernel/morello.c | 14 ++++++++++++++
2 files changed, 14 insertions(+), 1 deletion(-)
--
2.38.1
Hi,
This is a short series that makes a few simplifications we can now
afford: getting rid of morello_capcpy(), as it is unnecessary now that
the kernel is a "proper" hybrid binary with a tag-preserving memcpy();
and making use of <linux/cheri.h> to simplify includes.
The Morello helpers could be further simplified by reimplementing many
of them in C instead of assembly, issue #61 [1] was created to that end.
Review branch:
https://git.morello-project.org/kbrodsky-arm/linux/-/commits/morello/cheri_…
Cheers,
Kevin
[1] https://git.morello-project.org/morello/kernel/linux/-/issues/61
Kevin Brodsky (3):
arm64: morello: Replace morello_capcpy() with standard copy
arm64: Replace cheriintrin.h with linux/cheri.h
lib: Replace cheriintrin.h with linux/cheri.h
arch/arm64/include/asm/morello.h | 6 ------
arch/arm64/kernel/process.c | 9 +--------
arch/arm64/kernel/signal.c | 5 +----
arch/arm64/lib/morello.S | 18 ------------------
lib/test_printf.c | 4 +---
lib/vsprintf.c | 5 +----
6 files changed, 4 insertions(+), 43 deletions(-)
--
2.38.1
Hi,
This short series refactors the way pointers to the stack are
manipulated in binfmt_elf. The changes are generic and arguably improve
binfmt_elf, but the main objective is to eliminate unnecessary creation
of capabilities in PCuABI (through calls to uaddr_to_user_ptr_safe()).
This is done by using an actual user pointer to keep track of the
current position on the stack, and writing all data through that
pointer, instead of using an addresss and creating a new user pointer
for every access. This is what patch 1 does. Patch 2 simplifies the
elf_stack_put_user* macros we previously introduced, as we do not need
them to do something special in PCuABI any more.
This series should help with further work on restricting initial
capabilities [1]. It does not have any user-visible effect itself
however. The new "root stack capability" is still unrestricted, but the
fact that all capabilities to the stack are derived from it means that
any later narrowing of its bounds or permissions will automatically
propagate.
Note that these changes are mostly orthogonal to Téo's series [2] that
partially addresses [1]; it just means that using
uaddr_to_user_ptr_safe() is no longer necessary to derive the argv /
envp capabilities.
Review branch:
https://git.morello-project.org/kbrodsky-arm/linux/-/commits/morello/binfmt…
Thanks,
Kevin
[1] https://git.morello-project.org/morello/kernel/linux/-/issues/19
[2] https://op-lists.linaro.org/archives/list/linux-morello@op-lists.linaro.org…
Kevin Brodsky (2):
fs/binfmt_elf: Improve SP manipulation in PCuABI
fs/binfmt_elf: Simplify elf_stack_put_user*
fs/binfmt_elf.c | 85 +++++++++++++++++++++++-------------------
fs/compat_binfmt_elf.c | 9 +----
include/linux/elf.h | 12 +-----
3 files changed, 48 insertions(+), 58 deletions(-)
--
2.38.1