All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v9 0/5] linux-user: User support for AArch64 BTI
@ 2020-05-20 17:27 Richard Henderson
  2020-05-20 17:27 ` [PATCH v9 1/5] linux-user/aarch64: Reset btype for signals Richard Henderson
                   ` (5 more replies)
  0 siblings, 6 replies; 11+ messages in thread
From: Richard Henderson @ 2020-05-20 17:27 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee, laurent

The kernel ABI for this is (finally) close to being merged:

https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git/log/?h=for-next/bti-user

I've made a couple of tweaks from v8:

 (1) Only map the interpreter or a static executable with BTI.
     The interpreter is responsible for handling the pages of
     a dynamic executable.  This is a behaviour change in the
     kernel ABI since the last time I audited the code.

 (2) Rely on the recently released gcc 10 for building the test case.
     Thanks to Alex for helping me get a docker setup for that.

Based-on: <20200519185645.3915-1-richard.henderson@linaro.org>
("linux-user: mmap/mprotect prot values")

Based-on: An unpublished version of stsquad's testing/next

So for avoidance of doubt, the complete tree may be found at

https://github.com/rth7680/qemu/tree/tgt-arm-bti


r~


Richard Henderson (5):
  linux-user/aarch64: Reset btype for signals
  linux-user: Set PAGE_TARGET_1 for TARGET_PROT_BTI
  include/elf: Add defines related to GNU property notes for AArch64
  linux-user: Parse NT_GNU_PROPERTY_TYPE_0 notes
  tests/tcg/aarch64: Add bti smoke test

 include/elf.h                     |  22 +++++
 include/exec/cpu-all.h            |   2 +
 linux-user/qemu.h                 |   4 +
 linux-user/syscall_defs.h         |   4 +
 linux-user/aarch64/signal.c       |  10 ++-
 linux-user/elfload.c              | 143 ++++++++++++++++++++++--------
 linux-user/mmap.c                 |  16 ++++
 target/arm/translate-a64.c        |   6 +-
 tests/tcg/aarch64/bti-1.c         |  62 +++++++++++++
 tests/tcg/aarch64/bti-crt.inc.c   |  51 +++++++++++
 tests/tcg/aarch64/Makefile.target |   7 ++
 tests/tcg/configure.sh            |   4 +
 12 files changed, 291 insertions(+), 40 deletions(-)
 create mode 100644 tests/tcg/aarch64/bti-1.c
 create mode 100644 tests/tcg/aarch64/bti-crt.inc.c

-- 
2.20.1



^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v9 1/5] linux-user/aarch64: Reset btype for signals
  2020-05-20 17:27 [PATCH v9 0/5] linux-user: User support for AArch64 BTI Richard Henderson
@ 2020-05-20 17:27 ` Richard Henderson
  2020-07-06 11:02   ` Peter Maydell
  2020-05-20 17:27 ` [PATCH v9 2/5] linux-user: Set PAGE_TARGET_1 for TARGET_PROT_BTI Richard Henderson
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 11+ messages in thread
From: Richard Henderson @ 2020-05-20 17:27 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee, laurent

The kernel sets btype for the signal handler as if for a call.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 linux-user/aarch64/signal.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
index cd521ee42d..2c596a7088 100644
--- a/linux-user/aarch64/signal.c
+++ b/linux-user/aarch64/signal.c
@@ -506,10 +506,16 @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
             + offsetof(struct target_rt_frame_record, tramp);
     }
     env->xregs[0] = usig;
-    env->xregs[31] = frame_addr;
     env->xregs[29] = frame_addr + fr_ofs;
-    env->pc = ka->_sa_handler;
     env->xregs[30] = return_addr;
+    env->xregs[31] = frame_addr;
+    env->pc = ka->_sa_handler;
+
+    /* Invoke the signal handler as if by indirect call.  */
+    if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
+        env->btype = 2;
+    }
+
     if (info) {
         tswap_siginfo(&frame->info, info);
         env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info);
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v9 2/5] linux-user: Set PAGE_TARGET_1 for TARGET_PROT_BTI
  2020-05-20 17:27 [PATCH v9 0/5] linux-user: User support for AArch64 BTI Richard Henderson
  2020-05-20 17:27 ` [PATCH v9 1/5] linux-user/aarch64: Reset btype for signals Richard Henderson
@ 2020-05-20 17:27 ` Richard Henderson
  2020-07-06 11:09   ` Peter Maydell
  2020-05-20 17:27 ` [PATCH v9 3/5] include/elf: Add defines related to GNU property notes for AArch64 Richard Henderson
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 11+ messages in thread
From: Richard Henderson @ 2020-05-20 17:27 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee, laurent

Transform the prot bit to a qemu internal page bit, and save
it in the page tables.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/exec/cpu-all.h     |  2 ++
 linux-user/syscall_defs.h  |  4 ++++
 linux-user/mmap.c          | 16 ++++++++++++++++
 target/arm/translate-a64.c |  6 +++---
 4 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index d14374bdd4..2bd023d692 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -276,6 +276,8 @@ extern intptr_t qemu_host_page_mask;
 /* FIXME: Code that sets/uses this is broken and needs to go away.  */
 #define PAGE_RESERVED  0x0020
 #endif
+/* Target-specific bits that will be used via page_get_flags().  */
+#define PAGE_TARGET_1  0x0080
 
 #if defined(CONFIG_USER_ONLY)
 void page_dump(FILE *f);
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 152ec637cb..36bdafb3f1 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -1194,6 +1194,10 @@ struct target_winsize {
 #define TARGET_PROT_SEM         0x08
 #endif
 
+#ifdef TARGET_AARCH64
+#define TARGET_PROT_BTI         0x10
+#endif
+
 /* Common */
 #define TARGET_MAP_SHARED	0x01		/* Share changes */
 #define TARGET_MAP_PRIVATE	0x02		/* Changes are private */
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 84662c3311..40f03e3174 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -83,6 +83,22 @@ static int validate_prot_to_pageflags(int *host_prot, int prot)
     *host_prot = (prot & (PROT_READ | PROT_WRITE))
                | (prot & PROT_EXEC ? PROT_READ : 0);
 
+#ifdef TARGET_AARCH64
+    /*
+     * The PROT_BTI bit is only accepted if the cpu supports the feature.
+     * Since this is the unusual case, don't bother checking unless
+     * the bit has been requested.  If set and valid, record the bit
+     * within QEMU's page_flags as PAGE_TARGET_1.
+     */
+    if (prot & TARGET_PROT_BTI) {
+        ARMCPU *cpu = ARM_CPU(thread_cpu);
+        if (cpu_isar_feature(aa64_bti, cpu)) {
+            valid |= TARGET_PROT_BTI;
+            page_flags |= PAGE_TARGET_1;
+        }
+    }
+#endif
+
     return prot & ~valid ? 0 : page_flags;
 }
 
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 991e451644..59ae236c84 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -13989,10 +13989,10 @@ static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
  */
 static bool is_guarded_page(CPUARMState *env, DisasContext *s)
 {
-#ifdef CONFIG_USER_ONLY
-    return false;  /* FIXME */
-#else
     uint64_t addr = s->base.pc_first;
+#ifdef CONFIG_USER_ONLY
+    return page_get_flags(addr) & PAGE_TARGET_1;
+#else
     int mmu_idx = arm_to_core_mmu_idx(s->mmu_idx);
     unsigned int index = tlb_index(env, mmu_idx, addr);
     CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v9 3/5] include/elf: Add defines related to GNU property notes for AArch64
  2020-05-20 17:27 [PATCH v9 0/5] linux-user: User support for AArch64 BTI Richard Henderson
  2020-05-20 17:27 ` [PATCH v9 1/5] linux-user/aarch64: Reset btype for signals Richard Henderson
  2020-05-20 17:27 ` [PATCH v9 2/5] linux-user: Set PAGE_TARGET_1 for TARGET_PROT_BTI Richard Henderson
@ 2020-05-20 17:27 ` Richard Henderson
  2020-05-20 17:27 ` [PATCH v9 4/5] linux-user: Parse NT_GNU_PROPERTY_TYPE_0 notes Richard Henderson
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Richard Henderson @ 2020-05-20 17:27 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee, laurent

These are all of the defines required to parse
GNU_PROPERTY_AARCH64_FEATURE_1_AND, copied from binutils.
Other missing defines related to other GNU program headers
and notes are elided for now.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/elf.h | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/include/elf.h b/include/elf.h
index 8fbfe60e09..9db4aae40c 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -26,9 +26,13 @@ typedef int64_t  Elf64_Sxword;
 #define PT_NOTE    4
 #define PT_SHLIB   5
 #define PT_PHDR    6
+#define PT_LOOS    0x60000000
+#define PT_HIOS    0x6fffffff
 #define PT_LOPROC  0x70000000
 #define PT_HIPROC  0x7fffffff
 
+#define PT_GNU_PROPERTY   (PT_LOOS + 0x474e553)
+
 #define PT_MIPS_REGINFO   0x70000000
 #define PT_MIPS_RTPROC    0x70000001
 #define PT_MIPS_OPTIONS   0x70000002
@@ -1652,6 +1656,24 @@ typedef struct elf64_shdr {
 #define NT_ARM_SYSTEM_CALL      0x404   /* ARM system call number */
 #define NT_ARM_SVE      0x405           /* ARM Scalable Vector Extension regs */
 
+/* Defined note types for GNU systems.  */
+
+#define NT_GNU_PROPERTY_TYPE_0  5       /* Program property */
+
+/* Values used in GNU .note.gnu.property notes (NT_GNU_PROPERTY_TYPE_0).  */
+
+#define GNU_PROPERTY_STACK_SIZE                 1
+#define GNU_PROPERTY_NO_COPY_ON_PROTECTED       2
+
+#define GNU_PROPERTY_LOPROC                     0xc0000000
+#define GNU_PROPERTY_HIPROC                     0xdfffffff
+#define GNU_PROPERTY_LOUSER                     0xe0000000
+#define GNU_PROPERTY_HIUSER                     0xffffffff
+
+#define GNU_PROPERTY_AARCH64_FEATURE_1_AND      0xc0000000
+#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI      (1u << 0)
+#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC      (1u << 1)
+
 /*
  * Physical entry point into the kernel.
  *
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v9 4/5] linux-user: Parse NT_GNU_PROPERTY_TYPE_0 notes
  2020-05-20 17:27 [PATCH v9 0/5] linux-user: User support for AArch64 BTI Richard Henderson
                   ` (2 preceding siblings ...)
  2020-05-20 17:27 ` [PATCH v9 3/5] include/elf: Add defines related to GNU property notes for AArch64 Richard Henderson
@ 2020-05-20 17:27 ` Richard Henderson
  2020-07-06 11:26   ` Peter Maydell
  2020-05-20 17:28 ` [PATCH v9 5/5] tests/tcg/aarch64: Add bti smoke test Richard Henderson
  2020-06-27 18:39 ` [PATCH v9 0/5] linux-user: User support for AArch64 BTI Richard Henderson
  5 siblings, 1 reply; 11+ messages in thread
From: Richard Henderson @ 2020-05-20 17:27 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee, laurent

For aarch64, this includes the GNU_PROPERTY_AARCH64_FEATURE_1_BTI bit,
which indicates that the image should be mapped with guarded pages.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
v9: Only map the startup executable with BTI; anything else must be
    handled by the interpreter.
---
 linux-user/qemu.h    |   4 ++
 linux-user/elfload.c | 143 ++++++++++++++++++++++++++++++++-----------
 2 files changed, 112 insertions(+), 35 deletions(-)

diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index ce902f5132..d36b18b678 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -61,6 +61,10 @@ struct image_info {
         abi_ulong       interpreter_loadmap_addr;
         abi_ulong       interpreter_pt_dynamic_addr;
         struct image_info *other_info;
+
+        /* For target-specific processing of NT_GNU_PROPERTY_TYPE_0. */
+        uint32_t        note_flags;
+
 #ifdef TARGET_MIPS
         int             fp_abi;
         int             interp_fp_abi;
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 01a9323a63..c84c9991fd 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -2319,7 +2319,7 @@ static void load_elf_image(const char *image_name, int image_fd,
     struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
     struct elf_phdr *phdr;
     abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
-    int i, retval;
+    int i, retval, prot_exec;
     const char *errmsg;
 
     /* First of all, some simple consistency checks */
@@ -2354,17 +2354,90 @@ static void load_elf_image(const char *image_name, int image_fd,
     loaddr = -1, hiaddr = 0;
     info->alignment = 0;
     for (i = 0; i < ehdr->e_phnum; ++i) {
-        if (phdr[i].p_type == PT_LOAD) {
-            abi_ulong a = phdr[i].p_vaddr - phdr[i].p_offset;
+        struct elf_phdr *eppnt = phdr + i;
+
+        if (eppnt->p_type == PT_LOAD) {
+            abi_ulong a = eppnt->p_vaddr - eppnt->p_offset;
             if (a < loaddr) {
                 loaddr = a;
             }
-            a = phdr[i].p_vaddr + phdr[i].p_memsz;
+            a = eppnt->p_vaddr + eppnt->p_memsz;
             if (a > hiaddr) {
                 hiaddr = a;
             }
             ++info->nsegs;
-            info->alignment |= phdr[i].p_align;
+            info->alignment |= eppnt->p_align;
+        } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
+            char *interp_name;
+
+            if (*pinterp_name) {
+                errmsg = "Multiple PT_INTERP entries";
+                goto exit_errmsg;
+            }
+            interp_name = malloc(eppnt->p_filesz);
+            if (!interp_name) {
+                goto exit_perror;
+            }
+
+            if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
+                memcpy(interp_name, bprm_buf + eppnt->p_offset,
+                       eppnt->p_filesz);
+            } else {
+                retval = pread(image_fd, interp_name, eppnt->p_filesz,
+                               eppnt->p_offset);
+                if (retval != eppnt->p_filesz) {
+                    goto exit_perror;
+                }
+            }
+            if (interp_name[eppnt->p_filesz - 1] != 0) {
+                errmsg = "Invalid PT_INTERP entry";
+                goto exit_errmsg;
+            }
+            *pinterp_name = interp_name;
+        } else if (eppnt->p_type == PT_GNU_PROPERTY) {
+            /* Process NT_GNU_PROPERTY_TYPE_0. */
+            const uint32_t gnu0_magic = const_le32('G' | 'N' << 8 | 'U' << 16);
+            uint32_t note[7];
+
+            /*
+             * The note contents are 7 words, but depending on LP64 vs ILP32
+             * there may be an 8th padding word at the end.  Check for and
+             * read the minimum size.  Further checks below will validate
+             * that the sizes of everything involved are as we expect.
+             */
+            if (eppnt->p_filesz < sizeof(note)) {
+                continue;
+            }
+            if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
+                memcpy(note, bprm_buf + eppnt->p_offset, sizeof(note));
+            } else {
+                retval = pread(image_fd, note, sizeof(note), eppnt->p_offset);
+                if (retval != sizeof(note)) {
+                    goto exit_perror;
+                }
+            }
+#ifdef BSWAP_NEEDED
+            for (i = 0; i < ARRAY_SIZE(note); ++i) {
+                bswap32s(note + i);
+            }
+#endif
+            /*
+             * Check that this is a NT_GNU_PROPERTY_TYPE_0 note.
+             * Again, descsz includes padding.  Full size validation
+             * awaits checking the final payload.
+             */
+            if (note[0] != 4 ||                       /* namesz */
+                note[1] < 12 ||                       /* descsz */
+                note[2] != NT_GNU_PROPERTY_TYPE_0 ||  /* type */
+                note[3] != gnu0_magic) {              /* name */
+                continue;
+            }
+#ifdef TARGET_AARCH64
+            if (note[4] == GNU_PROPERTY_AARCH64_FEATURE_1_AND &&
+                note[5] == 4) {
+                info->note_flags = note[6];
+            }
+#endif /* TARGET_AARCH64 */
         }
     }
 
@@ -2453,15 +2526,42 @@ static void load_elf_image(const char *image_name, int image_fd,
     info->brk = 0;
     info->elf_flags = ehdr->e_flags;
 
+    prot_exec = PROT_EXEC;
+#ifdef TARGET_AARCH64
+    /*
+     * If the BTI feature is present, this indicates that the executable
+     * pages of the startup binary should be mapped with PROT_BTI, so that
+     * branch targets are enforced.
+     *
+     * The startup executable is either the interpreter or the static
+     * binary.  The interpreter is responsible for all pages of a
+     * dynamic executable.
+     *
+     * Elf notes are backward compatible to older cpus.
+     * Do not enable BTI unless it is supported.
+     */
+    if ((info->note_flags & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
+        && (pinterp_name == NULL || *pinterp_name == 0)
+        && cpu_isar_feature(aa64_bti, ARM_CPU(thread_cpu))) {
+        prot_exec |= TARGET_PROT_BTI;
+    }
+#endif
+
     for (i = 0; i < ehdr->e_phnum; i++) {
         struct elf_phdr *eppnt = phdr + i;
         if (eppnt->p_type == PT_LOAD) {
             abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em, vaddr_len;
             int elf_prot = 0;
 
-            if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ;
-            if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
-            if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
+            if (eppnt->p_flags & PF_R) {
+                elf_prot |= PROT_READ;
+            }
+            if (eppnt->p_flags & PF_W) {
+                elf_prot |= PROT_WRITE;
+            }
+            if (eppnt->p_flags & PF_X) {
+                elf_prot |= prot_exec;
+            }
 
             vaddr = load_bias + eppnt->p_vaddr;
             vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
@@ -2511,33 +2611,6 @@ static void load_elf_image(const char *image_name, int image_fd,
                     info->brk = vaddr_em;
                 }
             }
-        } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
-            char *interp_name;
-
-            if (*pinterp_name) {
-                errmsg = "Multiple PT_INTERP entries";
-                goto exit_errmsg;
-            }
-            interp_name = malloc(eppnt->p_filesz);
-            if (!interp_name) {
-                goto exit_perror;
-            }
-
-            if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
-                memcpy(interp_name, bprm_buf + eppnt->p_offset,
-                       eppnt->p_filesz);
-            } else {
-                retval = pread(image_fd, interp_name, eppnt->p_filesz,
-                               eppnt->p_offset);
-                if (retval != eppnt->p_filesz) {
-                    goto exit_perror;
-                }
-            }
-            if (interp_name[eppnt->p_filesz - 1] != 0) {
-                errmsg = "Invalid PT_INTERP entry";
-                goto exit_errmsg;
-            }
-            *pinterp_name = interp_name;
 #ifdef TARGET_MIPS
         } else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
             Mips_elf_abiflags_v0 abiflags;
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v9 5/5] tests/tcg/aarch64: Add bti smoke test
  2020-05-20 17:27 [PATCH v9 0/5] linux-user: User support for AArch64 BTI Richard Henderson
                   ` (3 preceding siblings ...)
  2020-05-20 17:27 ` [PATCH v9 4/5] linux-user: Parse NT_GNU_PROPERTY_TYPE_0 notes Richard Henderson
@ 2020-05-20 17:28 ` Richard Henderson
  2020-07-06 11:15   ` Peter Maydell
  2020-06-27 18:39 ` [PATCH v9 0/5] linux-user: User support for AArch64 BTI Richard Henderson
  5 siblings, 1 reply; 11+ messages in thread
From: Richard Henderson @ 2020-05-20 17:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee, laurent

This test requires gcc 10 for -mbranch-protection=standard.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
v9: Expect and require gcc 10.
---
 tests/tcg/aarch64/bti-1.c         | 62 +++++++++++++++++++++++++++++++
 tests/tcg/aarch64/bti-crt.inc.c   | 51 +++++++++++++++++++++++++
 tests/tcg/aarch64/Makefile.target |  7 ++++
 tests/tcg/configure.sh            |  4 ++
 4 files changed, 124 insertions(+)
 create mode 100644 tests/tcg/aarch64/bti-1.c
 create mode 100644 tests/tcg/aarch64/bti-crt.inc.c

diff --git a/tests/tcg/aarch64/bti-1.c b/tests/tcg/aarch64/bti-1.c
new file mode 100644
index 0000000000..61924f0d7a
--- /dev/null
+++ b/tests/tcg/aarch64/bti-1.c
@@ -0,0 +1,62 @@
+/*
+ * Branch target identification, basic notskip cases.
+ */
+
+#include "bti-crt.inc.c"
+
+static void skip2_sigill(int sig, siginfo_t *info, ucontext_t *uc)
+{
+    uc->uc_mcontext.pc += 8;
+    uc->uc_mcontext.pstate = 1;
+}
+
+#define NOP       "nop"
+#define BTI_N     "hint #32"
+#define BTI_C     "hint #34"
+#define BTI_J     "hint #36"
+#define BTI_JC    "hint #38"
+
+#define BTYPE_1(DEST) \
+    asm("mov %0,#1; adr x16, 1f; br x16; 1: " DEST "; mov %0,#0" \
+        : "=r"(skipped) : : "x16")
+
+#define BTYPE_2(DEST) \
+    asm("mov %0,#1; adr x16, 1f; blr x16; 1: " DEST "; mov %0,#0" \
+        : "=r"(skipped) : : "x16", "x30")
+
+#define BTYPE_3(DEST) \
+    asm("mov %0,#1; adr x15, 1f; br x15; 1: " DEST "; mov %0,#0" \
+        : "=r"(skipped) : : "x15")
+
+#define TEST(WHICH, DEST, EXPECT) \
+    do { WHICH(DEST); fail += skipped ^ EXPECT; } while (0)
+
+
+int main()
+{
+    int fail = 0;
+    int skipped;
+
+    /* Signal-like with SA_SIGINFO.  */
+    signal_info(SIGILL, skip2_sigill);
+
+    TEST(BTYPE_1, NOP, 1);
+    TEST(BTYPE_1, BTI_N, 1);
+    TEST(BTYPE_1, BTI_C, 0);
+    TEST(BTYPE_1, BTI_J, 0);
+    TEST(BTYPE_1, BTI_JC, 0);
+
+    TEST(BTYPE_2, NOP, 1);
+    TEST(BTYPE_2, BTI_N, 1);
+    TEST(BTYPE_2, BTI_C, 0);
+    TEST(BTYPE_2, BTI_J, 1);
+    TEST(BTYPE_2, BTI_JC, 0);
+
+    TEST(BTYPE_3, NOP, 1);
+    TEST(BTYPE_3, BTI_N, 1);
+    TEST(BTYPE_3, BTI_C, 1);
+    TEST(BTYPE_3, BTI_J, 0);
+    TEST(BTYPE_3, BTI_JC, 0);
+
+    return fail;
+}
diff --git a/tests/tcg/aarch64/bti-crt.inc.c b/tests/tcg/aarch64/bti-crt.inc.c
new file mode 100644
index 0000000000..47805f4e35
--- /dev/null
+++ b/tests/tcg/aarch64/bti-crt.inc.c
@@ -0,0 +1,51 @@
+/*
+ * Minimal user-environment for testing BTI.
+ *
+ * Normal libc is not (yet) built with BTI support enabled,
+ * and so could generate a BTI TRAP before ever reaching main.
+ */
+
+#include <stdlib.h>
+#include <signal.h>
+#include <ucontext.h>
+#include <asm/unistd.h>
+
+int main(void);
+
+void _start(void)
+{
+    exit(main());
+}
+
+void exit(int ret)
+{
+    register int x0 __asm__("x0") = ret;
+    register int x8 __asm__("x8") = __NR_exit;
+
+    asm volatile("svc #0" : : "r"(x0), "r"(x8));
+    __builtin_unreachable();
+}
+
+/*
+ * Irritatingly, the user API struct sigaction does not match the
+ * kernel API struct sigaction.  So for simplicity, isolate the
+ * kernel ABI here, and make this act like signal.
+ */
+void signal_info(int sig, void (*fn)(int, siginfo_t *, ucontext_t *))
+{
+    struct kernel_sigaction {
+        void (*handler)(int, siginfo_t *, ucontext_t *);
+        unsigned long flags;
+        unsigned long restorer;
+        unsigned long mask;
+    } sa = { fn, SA_SIGINFO, 0, 0 };
+
+    register int x0 __asm__("x0") = sig;
+    register void *x1 __asm__("x1") = &sa;
+    register void *x2 __asm__("x2") = 0;
+    register int x3 __asm__("x3") = sizeof(unsigned long);
+    register int x8 __asm__("x8") = __NR_rt_sigaction;
+
+    asm volatile("svc #0"
+                 : : "r"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x8) : "memory");
+}
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
index 312f36cde5..cf84787eb6 100644
--- a/tests/tcg/aarch64/Makefile.target
+++ b/tests/tcg/aarch64/Makefile.target
@@ -24,6 +24,13 @@ run-pauth-%: QEMU_OPTS += -cpu max
 pauth-%: CFLAGS += -march=armv8.3-a
 endif
 
+# BTI Tests
+ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_ARMV8_BTI),)
+AARCH64_TESTS += bti-1
+bti-%: CFLAGS += -mbranch-protection=standard
+bti-%: LDFLAGS += -nostdlib
+endif
+
 # Semihosting smoke test for linux-user
 AARCH64_TESTS += semihosting
 run-semihosting: semihosting
diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh
index 2326f97856..ebfe3e2ce5 100755
--- a/tests/tcg/configure.sh
+++ b/tests/tcg/configure.sh
@@ -231,6 +231,10 @@ for target in $target_list; do
                -march=armv8.3-a -o $TMPE $TMPC; then
                 echo "CROSS_CC_HAS_ARMV8_3=y" >> $config_target_mak
             fi
+            if do_compiler "$target_compiler" $target_compiler_cflags \
+               -mbranch-protection=standard -o $TMPE $TMPC; then
+                echo "CROSS_CC_HAS_ARMV8_BTI=y" >> $config_target_mak
+            fi
         ;;
     esac
 
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH v9 0/5] linux-user: User support for AArch64 BTI
  2020-05-20 17:27 [PATCH v9 0/5] linux-user: User support for AArch64 BTI Richard Henderson
                   ` (4 preceding siblings ...)
  2020-05-20 17:28 ` [PATCH v9 5/5] tests/tcg/aarch64: Add bti smoke test Richard Henderson
@ 2020-06-27 18:39 ` Richard Henderson
  5 siblings, 0 replies; 11+ messages in thread
From: Richard Henderson @ 2020-06-27 18:39 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, alex.bennee, laurent

On 5/20/20 10:27 AM, Richard Henderson wrote:
> The kernel ABI for this is (finally) close to being merged:
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git/log/?h=for-next/bti-user
> 
> I've made a couple of tweaks from v8:
> 
>  (1) Only map the interpreter or a static executable with BTI.
>      The interpreter is responsible for handling the pages of
>      a dynamic executable.  This is a behaviour change in the
>      kernel ABI since the last time I audited the code.
> 
>  (2) Rely on the recently released gcc 10 for building the test case.
>      Thanks to Alex for helping me get a docker setup for that.
> 
> Based-on: <20200519185645.3915-1-richard.henderson@linaro.org>
> ("linux-user: mmap/mprotect prot values")
> 
> Based-on: An unpublished version of stsquad's testing/next
> 
> So for avoidance of doubt, the complete tree may be found at
> 
> https://github.com/rth7680/qemu/tree/tgt-arm-bti

The Linux ABI on which this is based has been merged for v5.8-rc1, so pinging
this series.

Alex's testing/next is upstream, but the "mmap/mprotect prot values" patch is
still outstanding.

Everything rebases without issue onto qemu master.  Again for avoidance of
doubt, I have updated my branch.


r~


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v9 1/5] linux-user/aarch64: Reset btype for signals
  2020-05-20 17:27 ` [PATCH v9 1/5] linux-user/aarch64: Reset btype for signals Richard Henderson
@ 2020-07-06 11:02   ` Peter Maydell
  0 siblings, 0 replies; 11+ messages in thread
From: Peter Maydell @ 2020-07-06 11:02 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Alex Bennée, QEMU Developers, Laurent Vivier

On Wed, 20 May 2020 at 18:28, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> The kernel sets btype for the signal handler as if for a call.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  linux-user/aarch64/signal.c | 10 ++++++++--
>  1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c
> index cd521ee42d..2c596a7088 100644
> --- a/linux-user/aarch64/signal.c
> +++ b/linux-user/aarch64/signal.c
> @@ -506,10 +506,16 @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
>              + offsetof(struct target_rt_frame_record, tramp);
>      }
>      env->xregs[0] = usig;
> -    env->xregs[31] = frame_addr;
>      env->xregs[29] = frame_addr + fr_ofs;
> -    env->pc = ka->_sa_handler;
>      env->xregs[30] = return_addr;
> +    env->xregs[31] = frame_addr;
> +    env->pc = ka->_sa_handler;
> +
> +    /* Invoke the signal handler as if by indirect call.  */
> +    if (cpu_isar_feature(aa64_bti, env_archcpu(env))) {
> +        env->btype = 2;
> +    }
> +

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v9 2/5] linux-user: Set PAGE_TARGET_1 for TARGET_PROT_BTI
  2020-05-20 17:27 ` [PATCH v9 2/5] linux-user: Set PAGE_TARGET_1 for TARGET_PROT_BTI Richard Henderson
@ 2020-07-06 11:09   ` Peter Maydell
  0 siblings, 0 replies; 11+ messages in thread
From: Peter Maydell @ 2020-07-06 11:09 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Alex Bennée, QEMU Developers, Laurent Vivier

On Wed, 20 May 2020 at 18:28, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Transform the prot bit to a qemu internal page bit, and save
> it in the page tables.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  include/exec/cpu-all.h     |  2 ++
>  linux-user/syscall_defs.h  |  4 ++++
>  linux-user/mmap.c          | 16 ++++++++++++++++
>  target/arm/translate-a64.c |  6 +++---
>  4 files changed, 25 insertions(+), 3 deletions(-)
>
> diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
> index d14374bdd4..2bd023d692 100644
> --- a/include/exec/cpu-all.h
> +++ b/include/exec/cpu-all.h
> @@ -276,6 +276,8 @@ extern intptr_t qemu_host_page_mask;
>  /* FIXME: Code that sets/uses this is broken and needs to go away.  */
>  #define PAGE_RESERVED  0x0020
>  #endif
> +/* Target-specific bits that will be used via page_get_flags().  */
> +#define PAGE_TARGET_1  0x0080

I think it would also be nice to have

/* Target-specific names for the target-specific bits */
#ifdef TARGET_AARCH64
#define PAGE_BTI PAGE_TARGET_1
#endif

which can then (a) act as documentation of which PAGE_TARGET_n
each target is actually using and (b) mean that code that's
using the target-specific bits can use more friendly names.

Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v9 5/5] tests/tcg/aarch64: Add bti smoke test
  2020-05-20 17:28 ` [PATCH v9 5/5] tests/tcg/aarch64: Add bti smoke test Richard Henderson
@ 2020-07-06 11:15   ` Peter Maydell
  0 siblings, 0 replies; 11+ messages in thread
From: Peter Maydell @ 2020-07-06 11:15 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Alex Bennée, QEMU Developers, Laurent Vivier

On Wed, 20 May 2020 at 18:28, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> This test requires gcc 10 for -mbranch-protection=standard.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> v9: Expect and require gcc 10.
> ---
>  tests/tcg/aarch64/bti-1.c         | 62 +++++++++++++++++++++++++++++++
>  tests/tcg/aarch64/bti-crt.inc.c   | 51 +++++++++++++++++++++++++
>  tests/tcg/aarch64/Makefile.target |  7 ++++
>  tests/tcg/configure.sh            |  4 ++
>  4 files changed, 124 insertions(+)
>  create mode 100644 tests/tcg/aarch64/bti-1.c
>  create mode 100644 tests/tcg/aarch64/bti-crt.inc.c

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v9 4/5] linux-user: Parse NT_GNU_PROPERTY_TYPE_0 notes
  2020-05-20 17:27 ` [PATCH v9 4/5] linux-user: Parse NT_GNU_PROPERTY_TYPE_0 notes Richard Henderson
@ 2020-07-06 11:26   ` Peter Maydell
  0 siblings, 0 replies; 11+ messages in thread
From: Peter Maydell @ 2020-07-06 11:26 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Alex Bennée, QEMU Developers, Laurent Vivier

On Wed, 20 May 2020 at 18:28, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> For aarch64, this includes the GNU_PROPERTY_AARCH64_FEATURE_1_BTI bit,
> which indicates that the image should be mapped with guarded pages.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> v9: Only map the startup executable with BTI; anything else must be
>     handled by the interpreter.
> ---
>  linux-user/qemu.h    |   4 ++
>  linux-user/elfload.c | 143 ++++++++++++++++++++++++++++++++-----------
>  2 files changed, 112 insertions(+), 35 deletions(-)

Hi; this patch has some changes which seem to be just code motion
(moving the PT_INTERP handling higher up in the function), some
changes which are coding style fixes (braces), some which are
no-behaviour-change changes (using eppnt->foo instead of phdr[i].foo)
and also the actual BTI related functional change. Could you
split them out, please? I think it would make this easier to review.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2020-07-06 11:27 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-20 17:27 [PATCH v9 0/5] linux-user: User support for AArch64 BTI Richard Henderson
2020-05-20 17:27 ` [PATCH v9 1/5] linux-user/aarch64: Reset btype for signals Richard Henderson
2020-07-06 11:02   ` Peter Maydell
2020-05-20 17:27 ` [PATCH v9 2/5] linux-user: Set PAGE_TARGET_1 for TARGET_PROT_BTI Richard Henderson
2020-07-06 11:09   ` Peter Maydell
2020-05-20 17:27 ` [PATCH v9 3/5] include/elf: Add defines related to GNU property notes for AArch64 Richard Henderson
2020-05-20 17:27 ` [PATCH v9 4/5] linux-user: Parse NT_GNU_PROPERTY_TYPE_0 notes Richard Henderson
2020-07-06 11:26   ` Peter Maydell
2020-05-20 17:28 ` [PATCH v9 5/5] tests/tcg/aarch64: Add bti smoke test Richard Henderson
2020-07-06 11:15   ` Peter Maydell
2020-06-27 18:39 ` [PATCH v9 0/5] linux-user: User support for AArch64 BTI Richard Henderson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.