Nit: the commit title should ideally be less than 68 characters, which is sometimes difficult but in this case we can certainly "compress" the last 4 words.
On 12/10/2023 12:36, Aditya Deshpande wrote:
Provide purecap userspace binaries with a vDSO they can use. Redefine the aarch64 vDSO as the compat vDSO, therefore allowing both regular arm64 and purecap binaries to use a vDSO under PCuABI.
Signed-off-by: Aditya Deshpande aditya.deshpande@arm.com
arch/arm64/include/asm/elf.h | 16 ++++++-- arch/arm64/include/asm/vdso.h | 1 + arch/arm64/kernel/Makefile | 4 +- arch/arm64/kernel/vdso-purecap-wrap.S | 22 ++++++++++ arch/arm64/kernel/vdso.c | 58 ++++++++++++++++++++++++++- fs/compat_binfmt_elf.c | 16 ++++++++ include/linux/elf.h | 2 +- 7 files changed, 111 insertions(+), 8 deletions(-) create mode 100644 arch/arm64/kernel/vdso-purecap-wrap.S
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h index f01f1f99cf03..86805d6e5180 100644 --- a/arch/arm64/include/asm/elf.h +++ b/arch/arm64/include/asm/elf.h @@ -190,17 +190,20 @@ do { \ #ifdef CONFIG_CHERI_PURECAP_UABI /*
- TODO [PCuABI]: In Transitional PCuABI, AT_SYSINFO_EHDR is passed as NULL
- as there is no purecap vDSO yet.
- In Transitional PCuABI, we put a valid unsealed capability into the
- auxiliary vector.
I think we can skip this, this is not about the transitional ABI as it precisely did not include a vDSO.
- TODO [PCuABI]: Look into restricting the bounds of this capability to just
*/
- the vDSO pages, as currently the bounds are of the root user capability.
-#define ARCH_DLINFO SETUP_DLINFO(0) +#define ARCH_DLINFO SETUP_DLINFO(elf_uaddr_to_user_ptr((elf_addr_t)current->mm->context.vdso))
elf_uaddr_to_user_ptr() is only useful for code shared between native and compat. Since this is only used in native, we can use uaddr_to_user_ptr_safe() directly (while waiting for the bounds to be narrowed).
[...]
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c index c9d961249894..8f1305128799 100644 --- a/arch/arm64/kernel/vdso.c +++ b/arch/arm64/kernel/vdso.c @@ -32,6 +32,7 @@ enum vdso_abi { VDSO_ABI_AA64, VDSO_ABI_AA32,
- VDSO_ABI_PURECAP,
}; enum vvar_pages { @@ -64,6 +65,13 @@ static struct vdso_abi_info vdso_info[] __ro_after_init = { .vdso_code_end = vdso32_end, }, #endif /* CONFIG_COMPAT_VDSO */ +#ifdef CONFIG_CHERI_PURECAP_UABI
- [VDSO_ABI_PURECAP] = {
.name = "vdso_purecap",
.vdso_code_start = vdso_purecap_start,
.vdso_code_end = vdso_purecap_end,
- },
+#endif /* CONFIG_CHERI_PURECAP_UABI */ }; /* @@ -79,7 +87,6 @@ static int vdso_mremap(const struct vm_special_mapping *sm, struct vm_area_struct *new_vma) { current->mm->context.vdso = (void *)new_vma->vm_start;
Spurious change, also in __setup_additional_pages().
return 0; } @@ -143,6 +150,10 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns) #ifdef CONFIG_COMPAT_VDSO if (vma_is_special_mapping(vma, vdso_info[VDSO_ABI_AA32].dm)) zap_vma_pages(vma); +#endif +#ifdef CONFIG_CHERI_PURECAP_UABI
if (vma_is_special_mapping(vma, vdso_info[VDSO_ABI_PURECAP].dm))
zap_vma_pages(vma);
#endif } @@ -194,6 +205,7 @@ static int __setup_additional_pages(enum vdso_abi abi, unsigned long gp_flags = 0; void *ret;
- BUILD_BUG_ON(VVAR_NR_PAGES != __VVAR_PAGES);
vdso_text_len = vdso_info[abi].vdso_pages << PAGE_SHIFT; @@ -411,6 +423,48 @@ int aarch32_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) } #endif /* CONFIG_COMPAT32 */ +#ifdef CONFIG_CHERI_PURECAP_UABI +enum purecap_map {
- PURECAP_MAP_VVAR,
- PURECAP_MAP_VDSO,
+};
+static struct vm_special_mapping purecap_vdso_maps[] __ro_after_init = {
- [PURECAP_MAP_VVAR] = {
.name = "[vvar]",
.fault = vvar_fault,
- },
- [PURECAP_MAP_VDSO] = {
.name = "[vdso]",
.mremap = vdso_mremap,
- },
+}; +\
That \ probably wasn't meant to be there :D
+static int __init purecap_vdso_init(void) {
- vdso_info[VDSO_ABI_PURECAP].dm = &purecap_vdso_maps[PURECAP_MAP_VVAR];
- vdso_info[VDSO_ABI_PURECAP].cm = &purecap_vdso_maps[PURECAP_MAP_VDSO];
- return __vdso_init(VDSO_ABI_PURECAP);
+} +arch_initcall(purecap_vdso_init);
+int purecap_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) +{
- struct mm_struct *mm = current->mm;
- int ret;
- if (mmap_write_lock_killable(mm))
return -EINTR;
- ret = __setup_additional_pages(VDSO_ABI_PURECAP, mm, bprm, uses_interp);
- mmap_write_unlock(mm);
- return ret;
+}
+#endif /* CONFIG CHERI PURECAP UABI */
enum aarch64_map { AA64_MAP_VVAR, AA64_MAP_VDSO, @@ -436,7 +490,7 @@ static int __init vdso_init(void) } arch_initcall(vdso_init); -int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) +int aarch64_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) { struct mm_struct *mm = current->mm; int ret; diff --git a/fs/compat_binfmt_elf.c b/fs/compat_binfmt_elf.c index b6b453b35946..e22e866d587f 100644 --- a/fs/compat_binfmt_elf.c +++ b/fs/compat_binfmt_elf.c @@ -150,6 +150,22 @@ #endif /* CONFIG_COMPAT32 */ +#ifdef CONFIG_COMPAT64
+#ifdef compat_arch_setup_additional_pages +#define COMPAT_ARCH_SETUP_ADDITIONAL_PAGES(bprm, ex, interpreter) \
- compat_arch_setup_additional_pages(bprm, interpreter)
+#endif
+#ifdef COMPAT_ARCH_SETUP_ADDITIONAL_PAGES +#undef ARCH_HAS_SETUP_ADDITIONAL_PAGES +#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1 +#undef ARCH_SETUP_ADDITIONAL_PAGES +#define ARCH_SETUP_ADDITIONAL_PAGES COMPAT_ARCH_SETUP_ADDITIONAL_PAGES +#endif
These definitions were #ifdef'ed out in compat64 by [1]. Now that we want them in compat64 too, we should move them to the common part of the file (the one that is not #ifdef'ed), instead of duplicating them for compat64. The appropriate place, to preserve the original order, would be at the end, just before #include "binfmt_elf.c".
[1] https://git.morello-project.org/morello/kernel/linux/-/commit/84080b0
+#endif /* CONFIG_COMPAT64*/
#undef elf_check_arch #define elf_check_arch compat_elf_check_arch diff --git a/include/linux/elf.h b/include/linux/elf.h index 039ad1867045..2b66123c1f94 100644 --- a/include/linux/elf.h +++ b/include/linux/elf.h @@ -32,7 +32,7 @@ #if defined(ARCH_HAS_SETUP_ADDITIONAL_PAGES) && !defined(ARCH_SETUP_ADDITIONAL_PAGES) #define ARCH_SETUP_ADDITIONAL_PAGES(bprm, ex, interpreter) \
- arch_setup_additional_pages(bprm, interpreter)
- purecap_setup_additional_pages(bprm, interpreter)
Such a generic hook should not be changed, as it will break all other architectures (and even arm64 in !PCuABI) right away. Using a similar approach as for compat would be appropriate: make arch_setup_additional_pages a macro and define it as either the standard arm64 one or the purecap one depending on CONFIG_CHERI_PURECAP_UABI.
Kevin
#endif #define ELF32_GNU_PROPERTY_ALIGN 4