elf_stack_put_user{,_ptr} both write pointer-sized items to the new user stack. The need for two distinct functions mainly stemmed from the additional "magic" elf_stack_put_user_ptr() had to perform in PCuABI, that is create a valid capability out of the specified address. This also meant that the functions are implemented three times (PCuABI, !PCuABI, compat).
Since the previous patch, this requirement no longer exists, as an actual user pointer is passed to elf_stack_put_user_ptr(). This allows us to make things a lot simpler: only one function, elf_stack_put_user(), with a unique native implementation. A couple of observations make this possible:
* The items being stored are always pointer-sized, as mentioned previously, and it is therefore appropriate to use put_user_ptr() regardless of the ABI.
* Any integer or pointer can be safely cast to user_uintptr_t, and put_user_ptr() is able to manipulate a user_uintptr_t instead of a void __user *, avoiding the awkward cast in PCuABI.
The compat implementation is still needed as items are compat-pointer-sized in compat, in other words smaller than a native user pointer; thus, put_user_ptr() is not appropriate in that case.
While at it, elf_copy_to_user_stack() is now also defined unconditionally in compat, regardless of PCuABI. This makes no difference as copy_to_user_with_ptr() is equivalent to copy_to_user() in !PCuABI.
Signed-off-by: Kevin Brodsky kevin.brodsky@arm.com --- fs/binfmt_elf.c | 4 ++-- fs/compat_binfmt_elf.c | 9 +-------- include/linux/elf.h | 11 +---------- 3 files changed, 4 insertions(+), 20 deletions(-)
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index fbe83ed56531..6455313d7f36 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -398,7 +398,7 @@ create_elf_tables(struct linux_binprm *bprm, const struct elfhdr *exec, ustr = sp + (mm->arg_start - user_ptr_addr(sp)); while (argc-- > 0) { size_t len; - if (elf_stack_put_user_ptr(ustr, stack_item++)) + if (elf_stack_put_user(ustr, stack_item++)) return -EFAULT; len = strnlen_user(ustr, MAX_ARG_STRLEN); if (!len || len > MAX_ARG_STRLEN) @@ -416,7 +416,7 @@ create_elf_tables(struct linux_binprm *bprm, const struct elfhdr *exec, mm->env_start = user_ptr_addr(ustr); while (envc-- > 0) { size_t len; - if (elf_stack_put_user_ptr(ustr, stack_item++)) + if (elf_stack_put_user(ustr, stack_item++)) return -EFAULT; len = strnlen_user(ustr, MAX_ARG_STRLEN); if (!len || len > MAX_ARG_STRLEN) diff --git a/fs/compat_binfmt_elf.c b/fs/compat_binfmt_elf.c index 062ab93e9503..5495cede2975 100644 --- a/fs/compat_binfmt_elf.c +++ b/fs/compat_binfmt_elf.c @@ -38,18 +38,11 @@ #undef elf_uaddr_to_user_ptr #define elf_uaddr_to_user_ptr(addr) addr
-#ifdef CONFIG_CHERI_PURECAP_UABI - #undef elf_copy_to_user_stack #define elf_copy_to_user_stack(to, from, len) copy_to_user(to, from, len)
-#undef elf_stack_put_user_ptr -#define elf_stack_put_user_ptr(val, ptr) put_user(user_ptr_addr(val), ptr) - #undef elf_stack_put_user -#define elf_stack_put_user(val, ptr) put_user(val, ptr) - -#endif /* CONFIG_CHERI_PURECAP_UABI */ +#define elf_stack_put_user(val, ptr) put_user((elf_addr_t)(user_uintptr_t)(val), (ptr))
#ifdef CONFIG_COMPAT32 /* diff --git a/include/linux/elf.h b/include/linux/elf.h index 5d936561a5aa..abfa9b96259b 100644 --- a/include/linux/elf.h +++ b/include/linux/elf.h @@ -67,16 +67,7 @@ extern Elf64_Dyn _DYNAMIC []; #define elf_stack_item_t user_uintptr_t #define elf_uaddr_to_user_ptr(addr) uaddr_to_user_ptr_safe(addr) #define elf_copy_to_user_stack(to, from, len) copy_to_user_with_ptr(to, from, len) -#ifdef CONFIG_CHERI_PURECAP_UABI -#define elf_stack_put_user_ptr(val, ptr) \ - put_user_ptr((val), (void * __capability * __capability)ptr) -#define elf_stack_put_user(val, ptr) \ - put_user_ptr(as_user_ptr(val), \ - (void * __capability * __capability)ptr) -#else -#define elf_stack_put_user_ptr(val, ptr) put_user(user_ptr_addr(val), ptr) -#define elf_stack_put_user(val, ptr) put_user(val, ptr) -#endif +#define elf_stack_put_user(val, ptr) put_user_ptr((user_uintptr_t)(val), (ptr))
/* Optional callbacks to write extra ELF notes. */ struct file;