Message ID | cover.1552679409.git.andreyknvl@google.com (mailing list archive) |
---|---|
Headers | show |
Series | arm64: untag user pointers passed to the kernel | expand |
On Fri, 15 Mar 2019 20:51:34 +0100 Andrey Konovalov <andreyknvl@google.com> wrote: > This patch is a part of a series that extends arm64 kernel ABI to allow to > pass tagged user pointers (with the top byte set to something else other > than 0x00) as syscall arguments. > > seq_print_user_ip() uses provided user pointers for vma lookups, which > can only by done with untagged pointers. > > Untag user pointers in this function. > > Signed-off-by: Andrey Konovalov <andreyknvl@google.com> > --- > kernel/trace/trace_output.c | 5 +++-- > p | 45 +++++++++++++++++++++++++++++++++++++ > 2 files changed, 48 insertions(+), 2 deletions(-) > create mode 100644 p > > diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c > index 54373d93e251..6376bee93c84 100644 > --- a/kernel/trace/trace_output.c > +++ b/kernel/trace/trace_output.c > @@ -370,6 +370,7 @@ static int seq_print_user_ip(struct trace_seq *s, struct mm_struct *mm, > { > struct file *file = NULL; > unsigned long vmstart = 0; > + unsigned long untagged_ip = untagged_addr(ip); > int ret = 1; > > if (s->full) > @@ -379,7 +380,7 @@ static int seq_print_user_ip(struct trace_seq *s, struct mm_struct *mm, > const struct vm_area_struct *vma; > > down_read(&mm->mmap_sem); > - vma = find_vma(mm, ip); > + vma = find_vma(mm, untagged_ip); > if (vma) { > file = vma->vm_file; > vmstart = vma->vm_start; > @@ -388,7 +389,7 @@ static int seq_print_user_ip(struct trace_seq *s, struct mm_struct *mm, > ret = trace_seq_path(s, &file->f_path); > if (ret) > trace_seq_printf(s, "[+0x%lx]", > - ip - vmstart); > + untagged_ip - vmstart); > } > up_read(&mm->mmap_sem); > } > diff --git a/p b/p > new file mode 100644 > index 000000000000..9d6fa5386e55 > --- /dev/null > +++ b/p > @@ -0,0 +1,45 @@ > +commit 1fa6fadf644859e8a6a8ecce258444b49be8c7ee > +Author: Andrey Konovalov <andreyknvl@google.com> > +Date: Mon Mar 4 17:20:32 2019 +0100 > + > + kasan: fix coccinelle warnings in kasan_p*_table > + > + kasan_p4d_table, kasan_pmd_table and kasan_pud_table are declared as > + returning bool, but return 0 instead of false, which produces a coccinelle > + warning. Fix it. > + > + Fixes: 0207df4fa1a8 ("kernel/memremap, kasan: make ZONE_DEVICE with work with KASAN") > + Reported-by: kbuild test robot <lkp@intel.com> > + Signed-off-by: Andrey Konovalov <andreyknvl@google.com> Did you mean to append this commit to this patch? -- Steve > + > +diff --git a/mm/kasan/init.c b/mm/kasan/init.c > +index 45a1b5e38e1e..fcaa1ca03175 100644 > +--- a/mm/kasan/init.c > ++++ b/mm/kasan/init.c > +@@ -42,7 +42,7 @@ static inline bool kasan_p4d_table(pgd_t pgd) > + #else > + static inline bool kasan_p4d_table(pgd_t pgd) > + { > +- return 0; > ++ return false; > + } > + #endif > + #if CONFIG_PGTABLE_LEVELS > 3 > +@@ -54,7 +54,7 @@ static inline bool kasan_pud_table(p4d_t p4d) > + #else > + static inline bool kasan_pud_table(p4d_t p4d) > + { > +- return 0; > ++ return false; > + } > + #endif > + #if CONFIG_PGTABLE_LEVELS > 2 > +@@ -66,7 +66,7 @@ static inline bool kasan_pmd_table(pud_t pud) > + #else > + static inline bool kasan_pmd_table(pud_t pud) > + { > +- return 0; > ++ return false; > + } > + #endif > + pte_t kasan_early_shadow_pte[PTRS_PER_PTE] __page_aligned_bss;
On Fri, Mar 15, 2019 at 9:14 PM Steven Rostedt <rostedt@goodmis.org> wrote: > > On Fri, 15 Mar 2019 20:51:34 +0100 > Andrey Konovalov <andreyknvl@google.com> wrote: > > > This patch is a part of a series that extends arm64 kernel ABI to allow to > > pass tagged user pointers (with the top byte set to something else other > > than 0x00) as syscall arguments. > > > > seq_print_user_ip() uses provided user pointers for vma lookups, which > > can only by done with untagged pointers. > > > > Untag user pointers in this function. > > > > Signed-off-by: Andrey Konovalov <andreyknvl@google.com> > > --- > > kernel/trace/trace_output.c | 5 +++-- > > p | 45 +++++++++++++++++++++++++++++++++++++ > > 2 files changed, 48 insertions(+), 2 deletions(-) > > create mode 100644 p > > > > diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c > > index 54373d93e251..6376bee93c84 100644 > > --- a/kernel/trace/trace_output.c > > +++ b/kernel/trace/trace_output.c > > @@ -370,6 +370,7 @@ static int seq_print_user_ip(struct trace_seq *s, struct mm_struct *mm, > > { > > struct file *file = NULL; > > unsigned long vmstart = 0; > > + unsigned long untagged_ip = untagged_addr(ip); > > int ret = 1; > > > > if (s->full) > > @@ -379,7 +380,7 @@ static int seq_print_user_ip(struct trace_seq *s, struct mm_struct *mm, > > const struct vm_area_struct *vma; > > > > down_read(&mm->mmap_sem); > > - vma = find_vma(mm, ip); > > + vma = find_vma(mm, untagged_ip); > > if (vma) { > > file = vma->vm_file; > > vmstart = vma->vm_start; > > @@ -388,7 +389,7 @@ static int seq_print_user_ip(struct trace_seq *s, struct mm_struct *mm, > > ret = trace_seq_path(s, &file->f_path); > > if (ret) > > trace_seq_printf(s, "[+0x%lx]", > > - ip - vmstart); > > + untagged_ip - vmstart); > > } > > up_read(&mm->mmap_sem); > > } > > diff --git a/p b/p > > new file mode 100644 > > index 000000000000..9d6fa5386e55 > > --- /dev/null > > +++ b/p > > @@ -0,0 +1,45 @@ > > +commit 1fa6fadf644859e8a6a8ecce258444b49be8c7ee > > +Author: Andrey Konovalov <andreyknvl@google.com> > > +Date: Mon Mar 4 17:20:32 2019 +0100 > > + > > + kasan: fix coccinelle warnings in kasan_p*_table > > + > > + kasan_p4d_table, kasan_pmd_table and kasan_pud_table are declared as > > + returning bool, but return 0 instead of false, which produces a coccinelle > > + warning. Fix it. > > + > > + Fixes: 0207df4fa1a8 ("kernel/memremap, kasan: make ZONE_DEVICE with work with KASAN") > > + Reported-by: kbuild test robot <lkp@intel.com> > > + Signed-off-by: Andrey Konovalov <andreyknvl@google.com> > > Did you mean to append this commit to this patch? No, did it by mistake. Will remove in v12, thanks for noticing! > > -- Steve > > > + > > +diff --git a/mm/kasan/init.c b/mm/kasan/init.c > > +index 45a1b5e38e1e..fcaa1ca03175 100644 > > +--- a/mm/kasan/init.c > > ++++ b/mm/kasan/init.c > > +@@ -42,7 +42,7 @@ static inline bool kasan_p4d_table(pgd_t pgd) > > + #else > > + static inline bool kasan_p4d_table(pgd_t pgd) > > + { > > +- return 0; > > ++ return false; > > + } > > + #endif > > + #if CONFIG_PGTABLE_LEVELS > 3 > > +@@ -54,7 +54,7 @@ static inline bool kasan_pud_table(p4d_t p4d) > > + #else > > + static inline bool kasan_pud_table(p4d_t p4d) > > + { > > +- return 0; > > ++ return false; > > + } > > + #endif > > + #if CONFIG_PGTABLE_LEVELS > 2 > > +@@ -66,7 +66,7 @@ static inline bool kasan_pmd_table(pud_t pud) > > + #else > > + static inline bool kasan_pmd_table(pud_t pud) > > + { > > +- return 0; > > ++ return false; > > + } > > + #endif > > + pte_t kasan_early_shadow_pte[PTRS_PER_PTE] __page_aligned_bss; >
On arm64 the TCR_EL1.TBI0 bit has been always enabled in the Linux
kernel hence the userspace (EL0) is allowed to set a non-zero value
in the top byte but the resulting pointers are not allowed at the
user-kernel syscall ABI boundary.
This patchset proposes a relaxation of the ABI and a mechanism to
advertise it to the userspace via an AT_FLAGS.
The rationale behind the choice of AT_FLAGS is that the Unix System V
ABI defines AT_FLAGS as "flags", leaving some degree of freedom in
interpretation.
There are two previous attempts of using AT_FLAGS in the Linux Kernel
for different reasons: the first was more generic and was used to expose
the support for the GNU STACK NX feature [1] and the second was done for
the MIPS architecture and was used to expose the support of "MIPS ABI
Extension for IEEE Std 754 Non-Compliant Interlinking" [2].
Both the changes are currently _not_ merged in mainline.
The only architecture that reserves some of the bits in AT_FLAGS is
currently MIPS, which introduced the concept of platform specific ABI
(psABI) reserving the top-byte [3].
When ARM64_AT_FLAGS_SYSCALL_TBI is set the kernel is advertising
to the userspace that a relaxed ABI is supported hence this type
of pointers are now allowed to be passed to the syscalls when they are
in memory ranges obtained by anonymous mmap() or brk().
The userspace _must_ verify that the flag is set before passing tagged
pointers to the syscalls allowed by this relaxation.
More in general, exposing the ARM64_AT_FLAGS_SYSCALL_TBI flag and mandating
to the software to check that the feature is present, before using the
associated functionality, it provides a degree of control on the decision
of disabling such a feature in future without consequently breaking the
userspace.
The change required a modification of the elf common code, because in Linux
the AT_FLAGS are currently set to zero by default by the kernel.
The newly added flag has been verified on arm64 using the code below.
#include <stdio.h>
#include <stdbool.h>
#include <sys/auxv.h>
#define ARM64_AT_FLAGS_SYSCALL_TBI (1 << 0)
bool arm64_syscall_tbi_is_present(void)
{
unsigned long at_flags = getauxval(AT_FLAGS);
if (at_flags & ARM64_AT_FLAGS_SYSCALL_TBI)
return true;
return false;
}
void main()
{
if (arm64_syscall_tbi_is_present())
printf("ARM64_AT_FLAGS_SYSCALL_TBI is present\n");
}
This patchset should be merged together with [4].
[1] https://patchwork.ozlabs.org/patch/579578/
[2] https://lore.kernel.org/patchwork/cover/618280/
[3] ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/psABI_mips3.0.pdf
[4] https://patchwork.kernel.org/cover/10674351/
ABI References:
---------------
Sco SysV ABI: http://www.sco.com/developers/gabi/2003-12-17/contents.html
PowerPC AUXV: http://openpowerfoundation.org/wp-content/uploads/resources/leabi/content/dbdoclet.50655242_98651.html
AMD64 ABI: https://www.cs.tufts.edu/comp/40-2012f/readings/amd64-abi.pdf
x86 ABI: https://www.uclibc.org/docs/psABI-i386.pdf
MIPS ABI: ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/psABI_mips3.0.pdf
ARM ABI: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044f/IHI0044F_aaelf.pdf
SPARC ABI: http://math-atlas.sourceforge.net/devel/assembly/abi_sysV_sparc.pdf
CC: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andrey Konovalov <andreyknvl@google.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Branislav Rankov <Branislav.Rankov@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Chintan Pandya <cpandya@codeaurora.org>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Dave Martin <Dave.Martin@arm.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Evgeniy Stepanov <eugenis@google.com>
Cc: Graeme Barnes <Graeme.Barnes@arm.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jacob Bramley <Jacob.Bramley@arm.com>
Cc: Kate Stewart <kstewart@linuxfoundation.org>
Cc: Kees Cook <keescook@chromium.org>
Cc: Kevin Brodsky <kevin.brodsky@arm.com>
Cc: "Kirill A . Shutemov" <kirill.shutemov@linux.intel.com>
Cc: Kostya Serebryany <kcc@google.com>
Cc: Lee Smith <Lee.Smith@arm.com>
Cc: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ramana Radhakrishnan <Ramana.Radhakrishnan@arm.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Ruben Ayrapetyan <Ruben.Ayrapetyan@arm.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Szabolcs Nagy <Szabolcs.Nagy@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
Changes:
--------
v2:
- Rebased on 5.1-rc1
- Addressed review comments
- Modified tagged-pointers.txt to be compliant with the
new ABI relaxation
Vincenzo Frascino (4):
elf: Make AT_FLAGS arch configurable
arm64: Define Documentation/arm64/elf_at_flags.txt
arm64: Relax Documentation/arm64/tagged-pointers.txt
arm64: elf: Advertise relaxed ABI
Documentation/arm64/elf_at_flags.txt | 133 ++++++++++++++++++++++++
Documentation/arm64/tagged-pointers.txt | 23 ++--
arch/arm64/include/asm/atflags.h | 7 ++
arch/arm64/include/asm/elf.h | 5 +
arch/arm64/include/uapi/asm/atflags.h | 8 ++
fs/binfmt_elf.c | 6 +-
fs/binfmt_elf_fdpic.c | 6 +-
fs/compat_binfmt_elf.c | 5 +
8 files changed, 184 insertions(+), 9 deletions(-)
create mode 100644 Documentation/arm64/elf_at_flags.txt
create mode 100644 arch/arm64/include/asm/atflags.h
create mode 100644 arch/arm64/include/uapi/asm/atflags.h