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 appropriate permissions.
Tests to validate the capability's tag, bounds, range as well as
permissions have been added. 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. Lastly,
testcases to verify mmap/unmap of CHERI unreprentable address/length
have been added.
Review branch:
https://git.morello-project.org/chaitanya_prakash/linux/-/tree/review/morel…
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…
Changes in V8:
- Added co-developed by for patch 11.
Changes in V7:
https://op-lists.linaro.org/archives/list/linux-morello@op-lists.linaro.org…
- Modified the do-while loop used to generate unrepresentable address/length
- Added tag validity check for test_cheri_representability()
- Corrected representable_base such that the value is computed using
address rather than the base
- Updated commit messages
Changes in V6:
https://op-lists.linaro.org/archives/list/linux-morello@op-lists.linaro.org…
- Updated commit messages and in code comments as required.
- Moved struct initial_data back to bootstrap.c
- Defined __maybe_unused in freestanding.h
- Defined a fixed address to be shared among the tests.
- Modified negative madvise() test to make use of the common private
mapping.
- Renamed test_mmap_bounds_check and test_mremap_bounds_check testcases
to test_check_mmap_reservation and test_check_mremap_reservation
respectively.
- Modified the do-while loop used to generate unrepresentable
length/address.
- Added checks to validate that the bounds and length of ptr1 and ptr2
are of cheri representable length and their base is aligned according
to the alignment mask.
- Added a test to ensure mmap(owning_cap,..., MAP_FIXED fails if the
underlying reservation has been destroyed.
Changes in V5:
https://op-lists.linaro.org/archives/list/linux-morello@op-lists.linaro.org…
- Added representability testcase.
- Removed global struct reg_data and called get_pagesize() with auxv
passed in main().
- Removed VERIFY_ERRNO macro and made use of extended EXPECT_EQ
- As helper functions have been removed, the inline attribute line is of
no use and has been deleted.
- Used a common mapping to avoid creating and destroying mappings
repeatedly.
- Removed positive testcases as they are not unique to PCuABI
- Corrected the error code to reflect -ENOMEM instead of -ERESERVATION
when mremap() tries to move a mapping without MREMAP_MAYMOVE flag
- Reworded commit messages and restructured code.
Changes in V4:
https://op-lists.linaro.org/archives/list/linux-morello@op-lists.linaro.org…
-Corrected subject of cover letter
Changes in V3:
https://op-lists.linaro.org/archives/list/linux-morello@op-lists.linaro.org…
- 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…
Amit Daniel Kachhap (1):
kselftests/arm64: morello: mmap: Test unrepresentable addresses
Chaitanya S Prakash (10):
kselftests/arm64: morello: Create wrapper functions for frequently
invoked syscalls
kselftests/arm64: morello: Add get_pagesize() function
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() reservation testcases
kselftests/arm64: morello: mmap: Add mremap() reservation check
testcases
kselftests/arm64: morello: mmap: Add permission check testcases
kselftests/arm64: morello: mmap: Add brk() testcase
.../selftests/arm64/morello/bootstrap.c | 6 -
.../selftests/arm64/morello/freestanding.c | 15 +
.../selftests/arm64/morello/freestanding.h | 68 ++-
tools/testing/selftests/arm64/morello/mmap.c | 552 +++++++++++++++++-
4 files changed, 603 insertions(+), 38 deletions(-)
--
2.34.1
Hi,
This small series aligns the kernel with the latest release of Morello
Clang (1.7). Patch 1 removes a warning when building kselftests, while
patch 2 simplifies pieces of inline assembly that are not specific to
PCuABI, by making use of a relaxation in asm constraints.
Review branch:
https://git.morello-project.org/kbrodsky-arm/linux/-/commits/morello%2Flate…
Thanks,
Kevin
Kevin Brodsky (2):
kselftests/arm64: morello: Drop +c64 from -march
arm64: Switch to standard asm constraints for capabilities
arch/arm64/include/asm/futex.h | 23 ++++++++-----------
arch/arm64/include/asm/uaccess.h | 14 ++++-------
arch/arm64/include/asm/vdso/gettimeofday.h | 15 ++++--------
.../testing/selftests/arm64/morello/Makefile | 2 +-
4 files changed, 18 insertions(+), 36 deletions(-)
--
2.43.0
Hello all,
Many of the Morello helper functions are implemented in assembly due
to historical reasons. This patch series aims to translate the helpers into
C functions to improve their readability, introducing additional helpers
where necessary such as to access capability-based system registers. The
newly translated helpers are defined directly in morello.c.
This patch series also removes the now empty morello.S file, and updates
the Makefile accordingly. It also tidies up definitions of assembly-only
values, removing these where necessary.
V1 -> V2:
- Minor adjustments to improve code readability
- Correction to cheri_cap_build usage
- Remove duplicate calls to read_cap_sysreg
V1 separates the patch series into two patches; one to add the register
helpers, and another to translate the assembly helpers (and tidy up). V1
also corrects the more complicated helpers, whilst removing unnecessary
casts and finally implementing some feedback for improving code clarity.
The review branch is accessible here:
https://git.morello-project.org/arkamnite/linux/-/commits/morello%2Farm64_v2
The related issue is here:
https://git.morello-project.org/morello/kernel/linux/-/issues/61
Many thanks,
Akram
Akram Ahmad (2):
arm64: morello: add {read, write}_cap_sysreg helpers
arm64: morello: rewrite Morello helpers in C
arch/arm64/include/asm/assembler.h | 10 --
arch/arm64/include/asm/morello.h | 7 +-
arch/arm64/include/asm/sysreg.h | 14 ++
arch/arm64/kernel/asm-offsets.c | 8 --
arch/arm64/kernel/morello.c | 150 ++++++++++++++++++---
arch/arm64/lib/Makefile | 3 +-
arch/arm64/lib/morello.S | 205 -----------------------------
7 files changed, 152 insertions(+), 245 deletions(-)
delete mode 100644 arch/arm64/lib/morello.S
--
2.34.1
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 appropriate permissions.
Tests to validate the capability's tag, bounds, range as well as
permissions have been added. 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. Lastly,
testcases to verify mmap/unmap of CHERI unreprentable address/length
have been added.
Review branch:
https://git.morello-project.org/chaitanya_prakash/linux/-/tree/review/morel…
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…
Changes in V7:
- Modified the do-while loop used to generate unrepresentable address/length
- Added tag validity check for test_cheri_representability()
- Corrected representable_base such that the value is computed using
address rather than the base
- Updated commit messages
Changes in V6:
https://op-lists.linaro.org/archives/list/linux-morello@op-lists.linaro.org…
- Updated commit messages and in code comments as required.
- Moved struct initial_data back to bootstrap.c
- Defined __maybe_unused in freestanding.h
- Defined a fixed address to be shared among the tests.
- Modified negative madvise() test to make use of the common private
mapping.
- Renamed test_mmap_bounds_check and test_mremap_bounds_check testcases
to test_check_mmap_reservation and test_check_mremap_reservation
respectively.
- Modified the do-while loop used to generate unrepresentable
length/address.
- Added checks to validate that the bounds and length of ptr1 and ptr2
are of cheri representable length and their base is aligned according
to the alignment mask.
- Added a test to ensure mmap(owning_cap,..., MAP_FIXED fails if the
underlying reservation has been destroyed.
Changes in V5:
https://op-lists.linaro.org/archives/list/linux-morello@op-lists.linaro.org…
- Added representability testcase.
- Removed global struct reg_data and called get_pagesize() with auxv
passed in main().
- Removed VERIFY_ERRNO macro and made use of extended EXPECT_EQ
- As helper functions have been removed, the inline attribute line is of
no use and has been deleted.
- Used a common mapping to avoid creating and destroying mappings
repeatedly.
- Removed positive testcases as they are not unique to PCuABI
- Corrected the error code to reflect -ENOMEM instead of -ERESERVATION
when mremap() tries to move a mapping without MREMAP_MAYMOVE flag
- Reworded commit messages and restructured code.
Changes in V4:
https://op-lists.linaro.org/archives/list/linux-morello@op-lists.linaro.org…
-Corrected subject of cover letter
Changes in V3:
https://op-lists.linaro.org/archives/list/linux-morello@op-lists.linaro.org…
- 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…
Amit Daniel Kachhap (1):
kselftests/arm64: morello: mmap: Test unrepresentable addresses
Chaitanya S Prakash (10):
kselftests/arm64: morello: Create wrapper functions for frequently
invoked syscalls
kselftests/arm64: morello: Add get_pagesize() function
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() reservation testcases
kselftests/arm64: morello: mmap: Add mremap() reservation check
testcases
kselftests/arm64: morello: mmap: Add permission check testcases
kselftests/arm64: morello: mmap: Add brk() testcase
.../selftests/arm64/morello/bootstrap.c | 6 -
.../selftests/arm64/morello/freestanding.c | 15 +
.../selftests/arm64/morello/freestanding.h | 68 ++-
tools/testing/selftests/arm64/morello/mmap.c | 552 +++++++++++++++++-
4 files changed, 603 insertions(+), 38 deletions(-)
--
2.34.1
A few tests currently create temporary files in / to obtain an fd
for testing further syscalls. This is suboptimal as these files may
be used for other purposes, they are not deleted after the tests are
run, and we should generally avoid creating files at the root.
We could create files in /tmp instead, with some naming pattern à la
mkstemp(), but it turns out there is an even simpler solution.
open() can be passed O_TMPFILE to create an unnamed file under a
given directory. The file disappears once the fd is closed, so there
can be no leftover. This approach is used to implement tmpfile() in
glibc, if available.
On the model of tmpfile(), add a new helper tmpfd() in
freestanding.h and make use of it in the tests that need a temporary
fd, replacing the hardcoded files.
Signed-off-by: Kevin Brodsky <kevin.brodsky(a)arm.com>
---
This will also help for Akram's uaccess kselftests.
Review branch:
https://git.morello-project.org/kbrodsky-arm/linux/-/commits/morello/kselft…
.../selftests/arm64/morello/freestanding.h | 15 +++++++++++++++
tools/testing/selftests/arm64/morello/mmap.c | 4 +---
.../testing/selftests/arm64/morello/read_write.c | 7 ++-----
3 files changed, 18 insertions(+), 8 deletions(-)
diff --git a/tools/testing/selftests/arm64/morello/freestanding.h b/tools/testing/selftests/arm64/morello/freestanding.h
index 8dab905d2b54..5ab02dee1270 100644
--- a/tools/testing/selftests/arm64/morello/freestanding.h
+++ b/tools/testing/selftests/arm64/morello/freestanding.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include <stddef.h>
#include <asm/unistd.h>
+#include <linux/fcntl.h>
#include <linux/posix_types.h>
#include <linux/resource.h>
#include <linux/signal.h>
@@ -229,4 +230,18 @@ static inline int waitpid(pid_t pid, int *wstatus, int options)
return syscall(__NR_wait4, pid, wstatus, options, 0);
}
+/*
+ * Creates a new temporary file and returns an fd to it. The file has no name
+ * (see open(2) regarding O_TMPFILE) and is deleted when the fd is closed.
+ */
+static inline int tmpfd(void)
+{
+ int fd;
+
+ fd = syscall(__NR_openat, 0, "/", O_TMPFILE | O_RDWR, 0666);
+ ASSERT_GE(fd, 0);
+
+ return fd;
+}
+
#endif
diff --git a/tools/testing/selftests/arm64/morello/mmap.c b/tools/testing/selftests/arm64/morello/mmap.c
index 62fc14d14d46..618eb221d0ae 100644
--- a/tools/testing/selftests/arm64/morello/mmap.c
+++ b/tools/testing/selftests/arm64/morello/mmap.c
@@ -7,7 +7,6 @@
#include <linux/mman.h>
#include <linux/errno.h>
#include <linux/fs.h>
-#include <linux/fcntl.h>
#include <cheriintrin.h>
#include "freestanding.h"
@@ -65,13 +64,12 @@ void syscall_mmap2(void)
{
const char msg[] = "foo";
unsigned int msg_len = sizeof(msg); /* No need for the terminator */
- const char *sample_file = "/limbo.dat";
void *addr;
int fd;
int retval;
/* create a sample file to map onto with mmap */
- fd = syscall(__NR_openat, 0, sample_file, O_RDWR | O_CREAT, FILE_PERM);
+ fd = tmpfd();
ASSERT_GE(fd, 0);
diff --git a/tools/testing/selftests/arm64/morello/read_write.c b/tools/testing/selftests/arm64/morello/read_write.c
index a68b5efeb5ab..6425c8449baa 100644
--- a/tools/testing/selftests/arm64/morello/read_write.c
+++ b/tools/testing/selftests/arm64/morello/read_write.c
@@ -7,7 +7,6 @@
#include <linux/fs.h>
#include <linux/stat.h>
#include <linux/uio.h>
-#include <asm/fcntl.h>
#include <asm/unistd.h>
#include "freestanding.h"
@@ -26,8 +25,6 @@ static const char w_vec_msg2[VEC_MSG_LEN] = " is vector\n";
static char r_vec_msg1[VEC_MSG_LEN];
static char r_vec_msg2[VEC_MSG_LEN];
-static const char file[] = "/check_cap.txt";
-
static const struct iovec w_iovec[VEC_MSG_NUM] = {
{.iov_base = (char *) w_vec_msg1, .iov_len = VEC_MSG_LEN},
{.iov_base = (char *) w_vec_msg2, .iov_len = VEC_MSG_LEN},
@@ -58,8 +55,8 @@ TEST(test_writev)
TEST(test_open)
{
- fd = syscall(__NR_openat, 0, file, O_RDWR | O_CREAT, 0666);
- ASSERT_LE(1, fd) TH_LOG("open failed");
+ /* tmpfd() asserts that the openat syscall succeeds */
+ fd = tmpfd();
}
TEST(test_read)
--
2.42.1
Hello all,
Many of the Morello helper functions are implemented in assembly due
to historical reasons. This patch series aims to translate the helpers into
C functions to improve their readability, introducing additional helpers
where necessary such as to access capability-based system registers. The
newly translated helpers are defined directly in morello.c.
This patch series also removes the now empty morello.S file, and updates
the Makefile accordingly. It also tidies up definitions of assembly-only
values, removing these where necessary.
V1 separates the patch series into two patches; one to add the register
helpers, and another to translate the assembly helpers (and tidy up). V1
also corrects the more complicated helpers, whilst removing unnecessary
casts and finally implementing some feedback for improving code clarity.
The review branch is accessible here:
https://git.morello-project.org/arkamnite/linux/-/commits/morello%2Farm64_v1
The related issue is here:
https://git.morello-project.org/morello/kernel/linux/-/issues/61
Many thanks,
Akram
Akram Ahmad (2):
arm64: add {read, write, clear}_cap_sysreg helpers for Morello
arm64: rewrite Morello helpers in C
arch/arm64/include/asm/assembler.h | 10 --
arch/arm64/include/asm/morello.h | 4 +
arch/arm64/include/asm/sysreg.h | 18 +++
arch/arm64/kernel/asm-offsets.c | 8 --
arch/arm64/kernel/morello.c | 125 +++++++++++++++++-
arch/arm64/lib/Makefile | 3 +-
arch/arm64/lib/morello.S | 205 -----------------------------
7 files changed, 141 insertions(+), 232 deletions(-)
delete mode 100644 arch/arm64/lib/morello.S
--
2.34.1
%#lp results in the address being prefixed with 0x, like %#p, but
not if the capability is null-derived. Make sure the prefix is used
in all cases.
Fixes: ("lib/vsprintf: Add support for architectural capabilities")
Signed-off-by: Kevin Brodsky <kevin.brodsky(a)arm.com>
---
This is probably the result of some confusion during the review process
for the original patch, as the first version never printed the prefix.
Review branch:
https://git.morello-project.org/kbrodsky-arm/linux/-/commits/morello/printk…
lib/vsprintf.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 0b551cf89880..1a2a01843775 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -2550,13 +2550,9 @@ char *capability(const char *fmt, char *buf, char *end, void * __capability cap,
* Same applies when hashing is active.
*/
if ((!cheri_tag_get(cap) && !__builtin_cheri_copy_from_high(cap)) ||
- (likely(!no_hash_pointers) && *fmt != 'x')) {
-
- /* Avoid adding prefix */
- spec.flags &= ~SPECIAL;
+ (likely(!no_hash_pointers) && *fmt != 'x'))
return pointer(fmt, buf, end, (void *)cheri_address_get(cap),
spec);
- }
if (spec.flags & SPECIAL) { /* Simplified format for capabilities */
int orig_field_width = spec.field_width;
--
2.43.0
Add tests for capability enforcement via the standard copy routines
(copy_{to, from}_user, {get, put}_user), futex operations and the
explicit uaccess checks used in iov_iter via preadv and writev.
Signed-off-by: Akram Ahmad <Akram.Ahmad(a)arm.com>
---
Hi everyone,
This is v6 of the uaccess kselftest patch. Aside from some minor
corrections, v6 fixes a bug where readv would not fail correctly
in some circumstances. It has been replaced with preadv and the
tests are all passing correctly now.
V4, V5 introduced the following changes:
- Simplification of the futex test to only use one futex
- Move FUTEX_WAKE_OP description to futex test
- Various minor corrections
- Tightening of bounds for out-of-bounds access test cases.
V3 introduced the following changes:
- Corrections to function prototypes to remove void * in favour of the
actual struct pointer types and other minor corrections.
- Correction to the futex test, which now tests for a correctly enforced
uaccess routine when used in an atomic operation.
- Reintroduction of the out-of-bounds checking in tests.
V2 introduced the following changes:
- More concise formatting changes
- Corrections to various mistakes in tests
- Addition of a strlen_user() test
- Fixed futex test
The review branch can be found at:
https://git.morello-project.org/arkamnite/linux/-/commits/morello/uaccess_v6
The related issue can also be found at:
https://git.morello-project.org/morello/kernel/linux/-/issues/58
Many thanks,
Akram
---
.../testing/selftests/arm64/morello/Makefile | 2 +-
.../testing/selftests/arm64/morello/uaccess.c | 257 ++++++++++++++++++
2 files changed, 258 insertions(+), 1 deletion(-)
create mode 100644 tools/testing/selftests/arm64/morello/uaccess.c
diff --git a/tools/testing/selftests/arm64/morello/Makefile b/tools/testing/selftests/arm64/morello/Makefile
index ecfa6fc5e989..7b794d3e436c 100644
--- a/tools/testing/selftests/arm64/morello/Makefile
+++ b/tools/testing/selftests/arm64/morello/Makefile
@@ -17,7 +17,7 @@ CFLAGS += $(CLANG_FLAGS) $(CFLAGS_PURECAP) $(CFLAGS_COMMON)
LDFLAGS += $(CLANG_LDFLAGS) $(CLANG_FLAGS) -nostdlib -static
SRCS := $(wildcard *.c) $(wildcard *.S)
-PROGS := bootstrap clone exit mmap read_write sched signal
+PROGS := bootstrap clone exit mmap read_write sched signal uaccess
DEPS := $(wildcard *.h)
# these are the final executables
diff --git a/tools/testing/selftests/arm64/morello/uaccess.c b/tools/testing/selftests/arm64/morello/uaccess.c
new file mode 100644
index 000000000000..c448aeda0aad
--- /dev/null
+++ b/tools/testing/selftests/arm64/morello/uaccess.c
@@ -0,0 +1,257 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2023 Arm Limited
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdbool.h>
+
+#include <asm/fcntl.h>
+#include <asm-generic/errno-base.h>
+#include <cheriintrin.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/futex.h>
+#include <linux/mman.h>
+#include <linux/signal.h>
+#include <linux/sysinfo.h>
+#include <linux/socket.h>
+#include <linux/time.h>
+#include <linux/uio.h>
+
+#include "freestanding.h"
+
+#define MSG_LEN 16
+
+static const char file[] = "/my_file.txt";
+
+static inline int fsopen(const char *string)
+{
+ return syscall(__NR_fsopen, string);
+}
+
+
+static inline int futex_wake_op(uint32_t *uaddr, uint32_t *uaddr2, uint32_t val3)
+{
+ return syscall(__NR_futex, uaddr, FUTEX_WAKE_OP, 1, 1,
+ uaddr2, val3);
+}
+
+typedef unsigned short sa_family_t;
+
+struct sockaddr {
+ sa_family_t sa_family;
+ char sa_data[14];
+};
+
+static int getsockname(int socket, struct sockaddr *sockaddr, int *socklen)
+{
+ return syscall(__NR_getsockname, socket, sockaddr, socklen);
+}
+
+static int open_file(void)
+{
+ return syscall(__NR_openat, 0, file, O_RDWR | O_CREAT, 0666);
+}
+
+static inline int preadv(int fd, struct iovec *iov, int iovcnt)
+{
+ return syscall(__NR_preadv, fd, iov, iovcnt, 0);
+}
+
+static inline int writev(int fd, struct iovec *iov, int iovcnt)
+{
+ return syscall(__NR_writev, fd, iov, iovcnt);
+}
+
+static inline int sigaction(int sig, struct sigaction *old, struct sigaction *new)
+{
+ return syscall(__NR_rt_sigaction, sig, old, new, sizeof(sigset_t));
+}
+
+static inline int sysinfo(struct sysinfo *ptr)
+{
+ return syscall(__NR_sysinfo, ptr);
+}
+
+TEST(test_copy_to_user)
+{
+ struct sysinfo my_sysinfo;
+
+ ASSERT_EQ(sysinfo(&my_sysinfo), 0);
+
+ ASSERT_EQ(sysinfo(&my_sysinfo + 1), -EFAULT);
+
+ ASSERT_EQ(sysinfo(cheri_tag_clear(&my_sysinfo)), -EFAULT);
+
+ ASSERT_EQ(sysinfo(cheri_perms_and(&my_sysinfo, 0)), -EFAULT);
+}
+
+/*
+ * sigaction() tests both copy_to_user and copy_from_user by copying
+ * into and from a pointer to struct sigaction. The resulting action
+ * in this case is a no-op, but this does not affect the validity of
+ * the test. sigaction attempts to copy the new action from user space
+ * and the old action to user space, if the arguments is valid in either
+ * case.
+ */
+TEST(test_copy_user)
+{
+ struct sigaction act;
+
+ ASSERT_EQ(sigaction(SIGSEGV, NULL, &act), 0);
+ ASSERT_EQ(sigaction(SIGSEGV, &act, NULL), 0);
+
+ ASSERT_EQ(sigaction(SIGSEGV, NULL, &act + 1), -EFAULT);
+ ASSERT_EQ(sigaction(SIGSEGV, &act + 1, NULL), -EFAULT);
+
+ ASSERT_EQ(sigaction(SIGSEGV, NULL, cheri_tag_clear(&act)), -EFAULT);
+ ASSERT_EQ(sigaction(SIGSEGV, cheri_tag_clear(&act), NULL), -EFAULT);
+
+ ASSERT_EQ(sigaction(SIGSEGV, NULL, cheri_perms_and(&act, 0)), -EFAULT);
+ ASSERT_EQ(sigaction(SIGSEGV, cheri_perms_and(&act, 0), NULL), -EFAULT);
+}
+
+/*
+ * getsockname(2) uses both get_user and put_user to copy the addrlen argument
+ * from and to user space respectively. getsockname(2) calls move_addr_to_user
+ * to copy an address to user space. move_addr_to_user also uses copy_to_user;
+ * if copy_to_user is successful, but either of get_user or put_user fail then
+ * getsockname(2) will return -EFAULT appropriately.
+ */
+TEST(test_get_put_user)
+{
+ struct sockaddr sa;
+ int sa_len = sizeof(sa);
+ int my_socket;
+
+ // socket(AF_INET, SOCK_STREAM, 0)
+ my_socket = syscall(__NR_socket, 2, 1, 0);
+
+ // The socket must be successfully opened before proceeding.
+ ASSERT_GE(my_socket, 0);
+
+ ASSERT_EQ(getsockname(my_socket, &sa, &sa_len), 0);
+ ASSERT_EQ(getsockname(my_socket, &sa, &sa_len + 1), -EFAULT);
+ ASSERT_EQ(getsockname(my_socket, &sa, cheri_tag_clear(&sa_len)), -EFAULT);
+ ASSERT_EQ(getsockname(my_socket, &sa, cheri_perms_and(&sa_len, 0)), -EFAULT);
+ close(my_socket);
+}
+
+/*
+ * The FUTEX_WAKE_OP operation in the futex(2) syscall is used to handle more
+ * than one futex at the same time. This is an atomic operation that attempts
+ * to read, modify and write a value at a second uaddr (uaddr2) and also wake
+ * up waiters on the futex words at uaddr1 and uaddr2. uaddr1 and uaddr2 are
+ * provided via capabilities, and so this futex tests the case of an atomic
+ * uaccess operation.
+ *
+ * When using FUTEX_WAKE_OP, val3 is an encoding of both the operation as
+ * well as the comparison to be performed on the futex word at uaddr2. If val3
+ * is set to 0, this represents an operation of FUTEX_OP_SET and a comparison
+ * FUTEX_OP_CMP_EQ, where both oparg and comparg are 0.
+ */
+TEST(test_futex)
+{
+ uint32_t futex = 0;
+
+ ASSERT_GE(futex_wake_op(&futex, &futex, 0), 0);
+ ASSERT_EQ(futex_wake_op(&futex, &futex + 1, 0), -EFAULT);
+ ASSERT_EQ(futex_wake_op(&futex, cheri_tag_clear(&futex), 0), -EFAULT);
+ ASSERT_EQ(futex_wake_op(&futex, cheri_perms_and(&futex, 0), 0),
+ -EFAULT);
+}
+
+/*
+ * Test explicit accesses used in iov_iter via preadv and writev. Both
+ * syscalls use explicit checking on the iov_base field of struct iovec,
+ * so the metadata of the capability provided for iov_base is modified as
+ * per the needs of each individual test. preadv is used to ensure that the
+ * file is read with a file offset of 0, as the calls to writev modify the file
+ * offset.
+ */
+TEST(test_explicit_iov_iter)
+{
+ char buf0[2];
+ char buf1[4];
+ char buf2[6];
+ const char *write_buf0 = "Hello I am the first char buffer!\n";
+ const char *write_buf1 = "Hello, I am the second char buffer.\n";
+ const char *write_buf2 = "Hello, I am the third and final char buffer.\n";
+ struct iovec iov[3];
+ int iovcnt;
+ int fd;
+
+ fd = open_file();
+ ASSERT_NE(fd, -1);
+
+ iov[0].iov_base = (void *)write_buf0;
+ iov[0].iov_len = strlen(write_buf0);
+ iov[1].iov_base = (void *)write_buf1;
+ iov[1].iov_len = strlen(write_buf1);
+ iov[2].iov_base = (void *)write_buf2;
+ iov[2].iov_len = strlen(write_buf2);
+
+ iovcnt = sizeof(iov) / sizeof(struct iovec);
+ ASSERT_GE(writev(fd, iov, iovcnt), 0);
+
+ iov[0].iov_base = (void *)write_buf0 + 100;
+ ASSERT_EQ(writev(fd, iov, iovcnt), -EFAULT);
+
+ iov[0].iov_base = (void *)cheri_tag_clear(write_buf0);
+ ASSERT_EQ(writev(fd, iov, iovcnt), -EFAULT);
+
+ iov[0].iov_base = (void *)cheri_perms_and(write_buf0, 0);
+ ASSERT_EQ(writev(fd, iov, iovcnt), -EFAULT);
+
+ iov[0].iov_base = buf0;
+ iov[0].iov_len = sizeof(buf0);
+ iov[1].iov_base = buf1;
+ iov[1].iov_len = sizeof(buf1);
+ iov[2].iov_base = buf2;
+ iov[2].iov_len = sizeof(buf2);
+
+ ASSERT_GE(preadv(fd, iov, iovcnt), 0);
+
+ iov[0].iov_base = buf0 + 100;
+ ASSERT_EQ(preadv(fd, iov, iovcnt), -EFAULT);
+
+ iov[0].iov_base = cheri_tag_clear(buf0);
+ ASSERT_EQ(preadv(fd, iov, iovcnt), -EFAULT);
+
+ iov[0].iov_base = cheri_perms_and(buf0, 0);
+ ASSERT_EQ(preadv(fd, iov, iovcnt), -EFAULT);
+
+ close(fd);
+}
+
+/*
+ * strlen_user() explicitly inspects an input capability, the behaviour
+ * of which must also be verified within these tests. The fsopen() syscall
+ * makes use of strlen_user() by duplicating a string (representing the name
+ * of a filesystem) with the strndup_user() function. strlen_user() can
+ * therefore be tested with a call to fsopen().
+ */
+TEST(test_strlen_user)
+{
+ const char *fsname = "my_nonexistent_filesystem";
+
+ // strndup_user() will still be called, so fsopen() fails after this.
+ ASSERT_EQ(fsopen(fsname), -ENODEV);
+
+ ASSERT_EQ(fsopen(fsname + strlen(fsname) * 10), -EFAULT);
+
+ ASSERT_EQ(fsopen(cheri_tag_clear(fsname)), -EFAULT);
+
+ ASSERT_EQ(fsopen(cheri_perms_and(fsname, 0)), -EFAULT);
+}
+
+int main(void)
+{
+ test_copy_to_user();
+ test_copy_user();
+ test_get_put_user();
+ test_futex();
+ test_explicit_iov_iter();
+ test_strlen_user();
+ return 0;
+}
--
2.34.1
Hi all,
Many of the Morello helper functions are implemented in assembly due
to historical reasons. This patch series aims to translate the helpers into
C functions to improve their readability, introducing additional helpers
where necessary such as to access capability-based system registers. The
newly translated helpers are defined directly in morello.c. I would like
to draw particular attention to my translation of
morello_build_any_user_cap, as I'm not sure if this a correct approach.
This patch series also removes the now empty morello.S file, and updates
the Makefile accordingly.
The review branch is accessible here:
https://git.morello-project.org/arkamnite/linux/-/commits/morello%2Farm64_v0
The related issue is here:
https://git.morello-project.org/morello/kernel/linux/-/issues/61
Many thanks,
Akram
Akram Ahmad (3):
arm64: rewrite Morello helpers in C
arm64: add system register helpers for __morello_thread_init_user
arm64: translate Morello helpers in assembly to C
arch/arm64/include/asm/morello.h | 16 +++
arch/arm64/kernel/morello.c | 108 +++++++++++++++-
arch/arm64/lib/Makefile | 3 +-
arch/arm64/lib/morello.S | 205 -------------------------------
4 files changed, 120 insertions(+), 212 deletions(-)
delete mode 100644 arch/arm64/lib/morello.S
--
2.34.1