In PCuABI, we need compat_ptr() to create a valid capability from an
arbitrary compat pointer, to enable uaccess to the underlying
memory. However, if the compat pointer is clearly an invalid
address, it is preferable to return a null-derived (invalid)
capability. This is especially true when the address is null: we
clearly want to return the null capability in that case.
This should be a non-functional change (uaccess would fail anyway
due to the absence of underlying mapping), but it avoids some
confusion when debugging compat64 handling (and reduces the creation
of capabilities).
Signed-off-by: Kevin Brodsky <kevin.brodsky(a)arm.com>
---
Review branch:
https://git.morello-project.org/kbrodsky-arm/linux/-/commits/morello/null_c…
arch/arm64/include/asm/compat.h | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h
index 4556bed1704f..acf5487985b5 100644
--- a/arch/arm64/include/asm/compat.h
+++ b/arch/arm64/include/asm/compat.h
@@ -93,7 +93,9 @@ static inline void __user *compat_ptr(compat_uptr_t uptr)
* TODO [Morello] - this should be done using the current user DDC, not
* the root user capability.
*/
- return (void __user *)cheri_address_set(cheri_user_root_allperms_cap, uptr);
+ return likely(uptr >= PAGE_SIZE && uptr < TASK_SIZE_MAX) ?
+ (void __user *)cheri_address_set(cheri_user_root_allperms_cap, uptr) :
+ as_user_ptr(uptr);
}
#define compat_ptr(uptr) compat_ptr(uptr)
#endif
--
2.43.0
Hi,
This is a small series adding various firmware-related options to the
Morello defconfig. These options work out of the box in PCuABI (no
build or runtime issue).
Patch 1 is useful to inspect the EFI configuration on a live system, and
is used by tools like bootctl (systemd-boot).
Patch 2 enables the DPU to be successfully probed when using the
firmware-provided device tree (part of upstream TF-A), as it relies on
the DPU clock being provided by SCMI. This should be useful for
controlling other functionalities as well (e.g. power management).
Review branch:
https://git.morello-project.org/kbrodsky-arm/linux/-/commits/morello/defcon…
Thanks,
Kevin
Kevin Brodsky (2):
arm64: morello: Enable EFIVAR_FS in defconfig
arm64: morello: Enable SCMI in defconfig
arch/arm64/configs/morello_transitional_pcuabi_defconfig | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
--
2.43.0
These definitions were needed to build arch/arm64/kernel/ptrace.c
with CONFIG_COMPAT64 a long time ago, before "arm64: ptrace: Support
compat64". This is not the case any more, however since
"fs/compat_binfmt_elf: Align compat64 with compat32" we do need to
define compat_elf_gregset_t to keep linux/elfcore-compat.h happy.
This is the correct approach and there is no plan to change it, so
let's remove the outdated TODO.
Signed-off-by: Kevin Brodsky <kevin.brodsky(a)arm.com>
---
arch/arm64/include/asm/elf.h | 5 -----
1 file changed, 5 deletions(-)
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
index b54070e80867..63f6f50599e6 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -209,11 +209,6 @@ extern int purecap_setup_additional_pages(struct linux_binprm *bprm,
#define compat_elf_check_arch(x) ((x)->e_machine == EM_AARCH64 && \
!((x)->e_flags & EF_AARCH64_CHERI_PURECAP))
-/*
- * TODO [PCuABI]: Redefine below macros and typedefs to let ptrace pick them
- * and build. These redefinitions are not permanent and might not be required if
- * the ptrace is modified for complete COMPAT64 support.
- */
#define COMPAT_ELF_NGREG ELF_NGREG
typedef unsigned long compat_elf_greg_t;
typedef compat_elf_greg_t compat_elf_gregset_t[COMPAT_ELF_NGREG];
--
2.43.0
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
A previous patch which introduced support for capabilities in the
MMC_IOC_{MULTI_}CMD ioctls also hard-coded the ioctl values to
maintain compatibility with non-PCuABI ioctl handlers such as those
found in block.c.
This patch therefore removes the hard-coding of these ioctl values,
and enforces compatibility by accounting for the change in values
if the ioctl handler is running in compat64.
Signed-off-by: Akram Ahmad <Akram.Ahmad(a)arm.com>
---
drivers/mmc/core/block.c | 21 +++++++++++++++++++++
include/uapi/linux/mmc/ioctl.h | 21 +++++++++------------
2 files changed, 30 insertions(+), 12 deletions(-)
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
index 17a1d24bdaed..acb7f3a9b31a 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -76,6 +76,15 @@ MODULE_ALIAS("mmc:block");
#define MMC_EXTRACT_INDEX_FROM_ARG(x) ((x & 0x00FF0000) >> 16)
#define MMC_EXTRACT_VALUE_FROM_ARG(x) ((x & 0x0000FF00) >> 8)
+/*
+ * The compat_mmc_ioc_{multi_}cmd structs have different sizes in PCuABI and in
+ * compat64, which affects the expected MMC_IOC_{MULTI_}CMD ioctl values. The
+ * following ioctl values reflect the sizes of the compat64 structs defined in
+ * this file.
+ */
+#define COMPAT64_MMC_IOC_CMD _IOWR(MMC_BLOCK_MAJOR, 0, struct compat_mmc_ioc_cmd)
+#define COMPAT64_MMC_IOC_MULTI_CMD _IOWR(MMC_BLOCK_MAJOR, 1, struct compat_mmc_ioc_multi_cmd)
+
static DEFINE_MUTEX(block_mutex);
/*
@@ -858,6 +867,9 @@ static int mmc_blk_ioctl(struct block_device *bdev, blk_mode_t mode,
int ret;
switch (cmd) {
+ case COMPAT64_MMC_IOC_CMD:
+ if (!in_compat64_syscall())
+ return -EINVAL;
case MMC_IOC_CMD:
ret = mmc_blk_check_blkdev(bdev);
if (ret)
@@ -870,6 +882,9 @@ static int mmc_blk_ioctl(struct block_device *bdev, blk_mode_t mode,
NULL);
mmc_blk_put(md);
return ret;
+ case COMPAT64_MMC_IOC_MULTI_CMD:
+ if (!in_compat64_syscall())
+ return -EINVAL;
case MMC_IOC_MULTI_CMD:
ret = mmc_blk_check_blkdev(bdev);
if (ret)
@@ -2678,11 +2693,17 @@ static long mmc_rpmb_ioctl(struct file *filp, unsigned int cmd,
int ret;
switch (cmd) {
+ case COMPAT64_MMC_IOC_CMD:
+ if (!in_compat64_syscall())
+ return -EINVAL;
case MMC_IOC_CMD:
ret = mmc_blk_ioctl_cmd(rpmb->md,
(struct mmc_ioc_cmd __user *)arg,
rpmb);
break;
+ case COMPAT64_MMC_IOC_MULTI_CMD:
+ if (!in_compat64_syscall())
+ return -EINVAL;
case MMC_IOC_MULTI_CMD:
ret = mmc_blk_ioctl_multi_cmd(rpmb->md,
(struct mmc_ioc_multi_cmd __user *)arg,
diff --git a/include/uapi/linux/mmc/ioctl.h b/include/uapi/linux/mmc/ioctl.h
index 9d34bfc49198..e99d932268c6 100644
--- a/include/uapi/linux/mmc/ioctl.h
+++ b/include/uapi/linux/mmc/ioctl.h
@@ -67,26 +67,23 @@ struct mmc_ioc_multi_cmd {
/*
* The size of struct mmc_ioc_cmd changes in PCuABI due to the use of
* __kernel_uintptr_t, which in turn modifies the command value for this
- * ioctl. It is therefore necessary to hard-code the value for the ioctl
- * using the size of the struct that is expected in any ABI other than
- * PCuABI, to ensure that the value for MMC_IOC_CMD is unchanged. The
- * original definition is as follows:
- *
- * #define MMC_IOC_CMD _IOWR(MMC_BLOCK_MAJOR, 0, struct mmc_ioc_cmd)
+ * ioctl. As this command value is not hard-coded to represent the original
+ * size of the struct, any ioctl handlers in compat64 must handle this change
+ * in values instead.
*/
-#define MMC_IOC_CMD _IOC(_IOC_READ|_IOC_WRITE, MMC_BLOCK_MAJOR, 0, 72)
+#define MMC_IOC_CMD _IOWR(MMC_BLOCK_MAJOR, 0, struct mmc_ioc_cmd)
+
/*
* MMC_IOC_MULTI_CMD: Used to send an array of MMC commands described by
* the structure mmc_ioc_multi_cmd. The MMC driver will issue all
* commands in array in sequence to card.
*
* Note: the size of struct mmc_ioc_multi_cmd changes in PCuABI, due to the
- * increased alignment of struct mmc_ioc_cmd. For that reason, its value needs
- * to be hard-coded too. Original definition:
- *
- * #define MMC_IOC_MULTI_CMD _IOWR(MMC_BLOCK_MAJOR, 1, struct mmc_ioc_multi_cmd)
+ * increased alignment of struct mmc_ioc_cmd. Similarly to MMC_IOC_CMD, any
+ * ioctl handlers must account for this change when running in compat64.
*/
-#define MMC_IOC_MULTI_CMD _IOC(_IOC_READ|_IOC_WRITE, MMC_BLOCK_MAJOR, 1, 8)
+#define MMC_IOC_MULTI_CMD _IOWR(MMC_BLOCK_MAJOR, 1, struct mmc_ioc_multi_cmd)
+
/*
* Since this ioctl is only meant to enhance (and not replace) normal access
* to the mmc bus device, an upper data transfer limit of MMC_IOC_MAX_BYTES
--
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. We try to create the unnamed file
under /tmp if it exists, as /tmp should be writable by any user,
while / may not be writable at all.
Signed-off-by: Kevin Brodsky <kevin.brodsky(a)arm.com>
---
v1..v2:
* Replaced open_file() with tmpfd() in the new uaccess tests.
* Attempt to create the unnamed file under /tmp first, to avoid
requiring write access to /.
Review branch:
https://git.morello-project.org/kbrodsky-arm/linux/-/commits/morello/kselft…
.../selftests/arm64/morello/freestanding.h | 19 +++++++++++++++++++
tools/testing/selftests/arm64/morello/mmap.c | 4 +---
.../selftests/arm64/morello/read_write.c | 7 ++-----
.../testing/selftests/arm64/morello/uaccess.c | 13 +------------
4 files changed, 23 insertions(+), 20 deletions(-)
diff --git a/tools/testing/selftests/arm64/morello/freestanding.h b/tools/testing/selftests/arm64/morello/freestanding.h
index 8dab905d2b54..0969b518bad2 100644
--- a/tools/testing/selftests/arm64/morello/freestanding.h
+++ b/tools/testing/selftests/arm64/morello/freestanding.h
@@ -8,6 +8,8 @@
#include <stdint.h>
#include <stddef.h>
#include <asm/unistd.h>
+#include <linux/errno.h>
+#include <linux/fcntl.h>
#include <linux/posix_types.h>
#include <linux/resource.h>
#include <linux/signal.h>
@@ -229,4 +231,21 @@ 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;
+
+ /* First try /tmp, fall back to / if it doesn't exist */
+ fd = syscall(__NR_openat, 0, "/tmp", O_TMPFILE | O_RDWR, 0666);
+ if (fd == -ENOENT)
+ 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)
diff --git a/tools/testing/selftests/arm64/morello/uaccess.c b/tools/testing/selftests/arm64/morello/uaccess.c
index a1667d9b6bfc..7a48a35c67c5 100644
--- a/tools/testing/selftests/arm64/morello/uaccess.c
+++ b/tools/testing/selftests/arm64/morello/uaccess.c
@@ -5,11 +5,8 @@
#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>
@@ -22,14 +19,11 @@
#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,
@@ -48,11 +42,6 @@ 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);
@@ -181,7 +170,7 @@ TEST(test_explicit_iov_iter)
int iovcnt = sizeof(iov) / sizeof(struct iovec);
int fd;
- fd = open_file();
+ fd = tmpfd();
ASSERT_NE(fd, -1);
iov[0].iov_base = (void *)write_buf0;
--
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
Hi All,
This patch series introduces the mm reservation interface to manage
the owning capability of the allocated addresses. This series adds reservation
details in the VMA structure and different capability/reservation constraint checks.
Looking for feedback regarding API names, directory structure etc.
Details about several rules implemented can be found in PCuABI spec here [1].
This series is based on tree [2].
Changes in this v2 as compared with v1(Based on suggestions from Kevin):
1) Separated the user pointer related helpers from reservation helpers
and added them in lib/user_ptr.c.
2) Added new helpers user_ptr_is_valid() and user_ptr_set_addr()
to reduce CONFIG_CHERI_PURECAP_UABI ifdefs.
3) Fixed max gap issues in unmapped_area_topdown().
4) Dropped patch "mm,fs: Use address as user_uintptr_t in generic get_unmapped_area()".
However, due to this get_unmapped_area() cannot be called for
MAP_FIXED type valid capabilities. A special sanity check function is created
vm_area_range_within_limit() and is to be used for sanity checks in
those cases.
5) Some fixes regarding adding reservation details in VMA merging/expansions.
6) A new patch "fs/binfmt_elf: Add PCuABI reservation constraints" is
added in this series to demostrate the use of API
reserv_range_set_reserv() and kernel mapping functions vm_mmap() and vm_munmap().
7) Some code fixes and cleanups as suggested by Kevin.
Future works:
1) Users of vm_mmap/vm_munmap() i.e. filesystems, vdso, exec stack to be
modified to preserve capability addresses.
2) Cover remaining memory addressing syscalls.
Testing:
1) All tests by Chaitanya in v3 selftests [3] passes.
2) Purecap/Compat Busybox boot passes after adding [WIP] patches present in [4].
The whole series can be found here [4].
[1]: https://git.morello-project.org/morello/kernel/linux/-/wikis/Morello-pure-c…
[2]: https://git.morello-project.org/morello/kernel/linux morello/next
[3]: https://git.morello-project.org/chaitanya_prakash/linux.git review/purecap_mmap_testcases_v8
[4]: https://git.morello-project.org/amitdaniel/linux.git review/purecap_mm_reservation_v2
Thanks,
Amit Daniel
Amit Daniel Kachhap (22):
uapi: errno.h: Introduce PCuABI memory reservation error
linux/sched/coredump.h: Add MMF_PCUABI_RESERV mm flag
mm/cap_addr_mgmt: Add capability reservation interfaces in VMA
linux/user_ptr.h: Add two helpers to operate on user pointers
lib/user_ptr: Add helpers to be used by mm syscalls
mm/(mmap,mremap): Modify unmapped address space management code
mm: Add and use PCuABI reservation during VMA operation
mm/mmap: Add reservation constraints in mmap/munmap parameters
mm/mremap: Add reservation constraints in mremap syscall
mm/mprotect: Add the PCuABI reservation constraints
mm/madvise: Add the PCuABI reservation constraints
mm/mlock: Add the PCuABI reservation constraints
mm/msync: Add the PCuABI reservation constraints
mm/mmap: Disable MAP_GROWSDOWN mapping flag for PCuABI
uapi: mman-common.h: Macros for maximum capability permissions
lib/user_ptr: Add user pointer permission helpers for PCuABI
arm64: user_ptr: Implement morello capability permission helpers
mm/mmap: Add capability permission constraints for PCuABI
mm/mremap: Add capability permission constraints for PCuABI
mm/mprotect: Add capability permission constraints for PCuABI
mm/mincore: Add PCuABI reservation/capability constraints
fs/binfmt_elf: Add PCuABI reservation constraints
Documentation/core-api/user_ptr.rst | 28 ++++
arch/Kconfig | 3 +
arch/arm64/Kconfig | 1 +
arch/arm64/include/asm/user_ptr.h | 33 ++++
fs/binfmt_elf.c | 100 ++++++++----
include/linux/cap_addr_mgmt.h | 217 +++++++++++++++++++++++++
include/linux/mm.h | 19 ++-
include/linux/mm_types.h | 9 +
include/linux/sched/coredump.h | 2 +
include/linux/user_ptr.h | 101 ++++++++++++
include/uapi/asm-generic/errno.h | 2 +
include/uapi/asm-generic/mman-common.h | 6 +
io_uring/advise.c | 2 +-
kernel/fork.c | 3 +
lib/user_ptr.c | 93 +++++++++++
mm/Makefile | 2 +-
mm/cap_addr_mgmt.c | 152 +++++++++++++++++
mm/damon/vaddr.c | 2 +-
mm/madvise.c | 26 ++-
mm/mincore.c | 46 +++++-
mm/mlock.c | 36 +++-
mm/mmap.c | 207 +++++++++++++++++++----
mm/mprotect.c | 26 ++-
mm/mremap.c | 122 +++++++++++---
mm/msync.c | 13 +-
mm/util.c | 16 +-
26 files changed, 1137 insertions(+), 130 deletions(-)
create mode 100644 arch/arm64/include/asm/user_ptr.h
create mode 100644 include/linux/cap_addr_mgmt.h
create mode 100644 mm/cap_addr_mgmt.c
--
2.25.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