All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/8] ELF-FDPIC support for ARM
@ 2017-08-17  7:23 Nicolas Pitre
  2017-08-17  7:23 ` [PATCH v2 1/8] ARM: implement get_tls syscall Nicolas Pitre
                   ` (8 more replies)
  0 siblings, 9 replies; 26+ messages in thread
From: Nicolas Pitre @ 2017-08-17  7:23 UTC (permalink / raw)
  To: linux-arm-kernel

This series provides the needed changes to suport the ELF_FDPIC binary
format on ARM. Both MMU and non-MMU systems are supported. This format
has many advantages over the BFLT format used on MMU-less systems, such
as being real ELF that can be parsed by standard tools, can support
shared dynamic libs, etc.

This series is also available in the following git repository:

http://git.linaro.org/people/nicolas.pitre/linux fdpic

A complete toolchain and prebuilt packages can be obtained here:

https://github.com/mickael-guene/fdpic_manifest

Changes from v1:

- Reworked the signal return code to be compatible with a non-executable
  stack.
- Rebased on v4.13-rc3 to pick up latest signal changes.
- Added MMU support.
- Fixed crash in the ELF-FDPIC loader when loading an executable with
  shared libs on a system with an MMU.
- Made the regular ELF loader reject FDPIC binaries.

diffstat:

 arch/arm/include/asm/elf.h         | 16 +++++++--
 arch/arm/include/asm/mmu.h         |  8 +++++
 arch/arm/include/asm/processor.h   | 22 +++++++++----
 arch/arm/include/asm/ucontext.h    |  1 +
 arch/arm/include/uapi/asm/ptrace.h |  4 +++
 arch/arm/include/uapi/asm/unistd.h |  1 +
 arch/arm/kernel/asm-offsets.c      |  4 +++
 arch/arm/kernel/elf.c              | 24 +++++++++++++-
 arch/arm/kernel/signal.c           | 53 +++++++++++++++++++++---------
 arch/arm/kernel/signal.h           | 11 +++++++
 arch/arm/kernel/sigreturn_codes.S  | 56 +++++++++++++++++++++++++++++---
 arch/arm/kernel/traps.c            |  3 ++
 fs/Kconfig.binfmt                  |  4 +--
 fs/binfmt_elf.c                    | 15 +++++++--
 fs/binfmt_elf_fdpic.c              | 13 ++++++--
 15 files changed, 199 insertions(+), 36 deletions(-)

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

* [PATCH v2 1/8] ARM: implement get_tls syscall
  2017-08-17  7:23 [PATCH v2 0/8] ELF-FDPIC support for ARM Nicolas Pitre
@ 2017-08-17  7:23 ` Nicolas Pitre
  2017-08-28 14:05   ` [v2,1/8] " Vincent ABRIOU
  2017-08-17  7:23 ` [PATCH v2 2/8] arm_elf_read_implies_exec(): remove unused argument Nicolas Pitre
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 26+ messages in thread
From: Nicolas Pitre @ 2017-08-17  7:23 UTC (permalink / raw)
  To: linux-arm-kernel

When there is no dedicated register to hold the tp value and no MMU
to provide a fixed address kuser helper entry point, all that is
left as fallback is a syscall.

Signed-off-by: Nicolas Pitre <nico@linaro.org>
---
 arch/arm/include/uapi/asm/unistd.h | 1 +
 arch/arm/kernel/traps.c            | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/arch/arm/include/uapi/asm/unistd.h b/arch/arm/include/uapi/asm/unistd.h
index 28bd456494..575b25fc29 100644
--- a/arch/arm/include/uapi/asm/unistd.h
+++ b/arch/arm/include/uapi/asm/unistd.h
@@ -35,5 +35,6 @@
 #define __ARM_NR_usr26			(__ARM_NR_BASE+3)
 #define __ARM_NR_usr32			(__ARM_NR_BASE+4)
 #define __ARM_NR_set_tls		(__ARM_NR_BASE+5)
+#define __ARM_NR_get_tls		(__ARM_NR_BASE+6)
 
 #endif /* _UAPI__ASM_ARM_UNISTD_H */
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 948c648fea..43c0560f7b 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -647,6 +647,9 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
 		set_tls(regs->ARM_r0);
 		return 0;
 
+	case NR(get_tls):
+		return current_thread_info()->tp_value[0];
+
 	default:
 		/* Calls 9f00xx..9f07ff are defined to return -ENOSYS
 		   if not implemented, rather than raising SIGILL.  This
-- 
2.9.5

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

* [PATCH v2 2/8] arm_elf_read_implies_exec(): remove unused argument
  2017-08-17  7:23 [PATCH v2 0/8] ELF-FDPIC support for ARM Nicolas Pitre
  2017-08-17  7:23 ` [PATCH v2 1/8] ARM: implement get_tls syscall Nicolas Pitre
@ 2017-08-17  7:23 ` Nicolas Pitre
  2017-08-28 14:06   ` [v2,2/8] " Vincent ABRIOU
  2017-08-17  7:23 ` [PATCH v2 3/8] ARM: start_thread(): don't always clear all regs Nicolas Pitre
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 26+ messages in thread
From: Nicolas Pitre @ 2017-08-17  7:23 UTC (permalink / raw)
  To: linux-arm-kernel

The first argument to elf_read_implies_exec() is either the actual
header structure or a pointer to that structure whether one looks
at fs/binfmt_elf.c or fs/binfmt_elf_fdpic.c. This ought to be fixed
of course, but in the mean time let's sidestep the issue by removing
that first argument from arm_elf_read_implies_exec() as it is unused
anyway.

Signed-off-by: Nicolas Pitre <nico@linaro.org>
---
 arch/arm/include/asm/elf.h | 4 ++--
 arch/arm/kernel/elf.c      | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h
index f13ae153fb..e2786acf82 100644
--- a/arch/arm/include/asm/elf.h
+++ b/arch/arm/include/asm/elf.h
@@ -102,8 +102,8 @@ extern int elf_check_arch(const struct elf32_hdr *);
 
 #define vmcore_elf64_check_arch(x) (0)
 
-extern int arm_elf_read_implies_exec(const struct elf32_hdr *, int);
-#define elf_read_implies_exec(ex,stk) arm_elf_read_implies_exec(&(ex), stk)
+extern int arm_elf_read_implies_exec(int);
+#define elf_read_implies_exec(ex,stk) arm_elf_read_implies_exec(stk)
 
 struct task_struct;
 int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs);
diff --git a/arch/arm/kernel/elf.c b/arch/arm/kernel/elf.c
index d0d1e83150..52fb98358d 100644
--- a/arch/arm/kernel/elf.c
+++ b/arch/arm/kernel/elf.c
@@ -80,7 +80,7 @@ EXPORT_SYMBOL(elf_set_personality);
  *  - the binary requires an executable stack
  *  - we're running on a CPU which doesn't support NX.
  */
-int arm_elf_read_implies_exec(const struct elf32_hdr *x, int executable_stack)
+int arm_elf_read_implies_exec(int executable_stack)
 {
 	if (executable_stack != EXSTACK_DISABLE_X)
 		return 1;
-- 
2.9.5

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

* [PATCH v2 3/8] ARM: start_thread(): don't always clear all regs
  2017-08-17  7:23 [PATCH v2 0/8] ELF-FDPIC support for ARM Nicolas Pitre
  2017-08-17  7:23 ` [PATCH v2 1/8] ARM: implement get_tls syscall Nicolas Pitre
  2017-08-17  7:23 ` [PATCH v2 2/8] arm_elf_read_implies_exec(): remove unused argument Nicolas Pitre
@ 2017-08-17  7:23 ` Nicolas Pitre
  2017-08-28 14:07   ` [v2,3/8] " Vincent ABRIOU
  2017-08-17  7:23 ` [PATCH v2 4/8] ARM: signal handling support for FDPIC_FUNCPTRS functions Nicolas Pitre
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 26+ messages in thread
From: Nicolas Pitre @ 2017-08-17  7:23 UTC (permalink / raw)
  To: linux-arm-kernel

The elf_fdpic binary format driver has to initialize extra registers
beside the stack and program counter as required by the corresponding
ABI. So reinstate them after the regs structure has been cleared.

While at it let's get rid of start_thread_nommu().

Signed-off-by: Nicolas Pitre <nico@linaro.org>
---
 arch/arm/include/asm/processor.h | 22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h
index c3d5fc124a..338cbe0a18 100644
--- a/arch/arm/include/asm/processor.h
+++ b/arch/arm/include/asm/processor.h
@@ -47,15 +47,24 @@ struct thread_struct {
 
 #define INIT_THREAD  {	}
 
-#ifdef CONFIG_MMU
-#define nommu_start_thread(regs) do { } while (0)
-#else
-#define nommu_start_thread(regs) regs->ARM_r10 = current->mm->start_data
-#endif
-
 #define start_thread(regs,pc,sp)					\
 ({									\
+	unsigned long r7, r8, r9;					\
+									\
+	if (IS_ENABLED(CONFIG_BINFMT_ELF_FDPIC)) {			\
+		r7 = regs->ARM_r7;					\
+		r8 = regs->ARM_r8;					\
+		r9 = regs->ARM_r9;					\
+	}								\
 	memset(regs->uregs, 0, sizeof(regs->uregs));			\
+	if (IS_ENABLED(CONFIG_BINFMT_ELF_FDPIC) &&			\
+	    current->personality & FDPIC_FUNCPTRS) {			\
+		regs->ARM_r7 = r7;					\
+		regs->ARM_r8 = r8;					\
+		regs->ARM_r9 = r9;					\
+		regs->ARM_r10 = current->mm->start_data;		\
+	} else if (!IS_ENABLED(CONFIG_MMU))				\
+		regs->ARM_r10 = current->mm->start_data;		\
 	if (current->personality & ADDR_LIMIT_32BIT)			\
 		regs->ARM_cpsr = USR_MODE;				\
 	else								\
@@ -65,7 +74,6 @@ struct thread_struct {
 	regs->ARM_cpsr |= PSR_ENDSTATE;					\
 	regs->ARM_pc = pc & ~1;		/* pc */			\
 	regs->ARM_sp = sp;		/* sp */			\
-	nommu_start_thread(regs);					\
 })
 
 /* Forward declaration, a strange C thing */
-- 
2.9.5

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

* [PATCH v2 4/8] ARM: signal handling support for FDPIC_FUNCPTRS functions
  2017-08-17  7:23 [PATCH v2 0/8] ELF-FDPIC support for ARM Nicolas Pitre
                   ` (2 preceding siblings ...)
  2017-08-17  7:23 ` [PATCH v2 3/8] ARM: start_thread(): don't always clear all regs Nicolas Pitre
@ 2017-08-17  7:23 ` Nicolas Pitre
  2017-08-28 14:07   ` [v2,4/8] " Vincent ABRIOU
  2017-08-17  7:23 ` [PATCH v2 5/8] ARM: add ELF_FDPIC support Nicolas Pitre
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 26+ messages in thread
From: Nicolas Pitre @ 2017-08-17  7:23 UTC (permalink / raw)
  To: linux-arm-kernel

Signal handlers are not direct function pointers but pointers to function
descriptor in that case. Therefore we must retrieve the actual function
address and load the GOT value into r9 from the descriptor before branching
to the actual handler.

If a restorer is provided, we also have to load its address and GOT from
its descriptor. That descriptor address and the code to load it is pushed
onto the stack to be executed as soon as the signal handler returns.

However, to be compatible with NX stacks, the FDPIC bounce code is also
copied to the signal page along with the other code stubs. Therefore this
code must get at the descriptor address whether it executes from the stack
or the signal page. To do so we use the stack pointer which points at the
signal stack frame where the descriptor address was stored. Because the
rt signal frame is different from the simpler frame, two versions of the
bounce code are needed, and two variants (ARM and Thumb) as well. The
asm-offsets facility is used to determine the actual offset in the signal
frame for each version, meaning that struct sigframe and rt_sigframe had
to be moved to a separate file.

Signed-off-by: Nicolas Pitre <nico@linaro.org>
---
 arch/arm/include/asm/ucontext.h   |  1 +
 arch/arm/kernel/asm-offsets.c     |  4 +++
 arch/arm/kernel/signal.c          | 53 +++++++++++++++++++++++++-----------
 arch/arm/kernel/signal.h          | 11 ++++++++
 arch/arm/kernel/sigreturn_codes.S | 56 +++++++++++++++++++++++++++++++++++----
 5 files changed, 105 insertions(+), 20 deletions(-)
 create mode 100644 arch/arm/kernel/signal.h

diff --git a/arch/arm/include/asm/ucontext.h b/arch/arm/include/asm/ucontext.h
index 921d827485..b42c75ae0d 100644
--- a/arch/arm/include/asm/ucontext.h
+++ b/arch/arm/include/asm/ucontext.h
@@ -2,6 +2,7 @@
 #define _ASMARM_UCONTEXT_H
 
 #include <asm/fpstate.h>
+#include <asm/user.h>
 
 /*
  * struct sigcontext only has room for the basic registers, but struct
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 608008229c..13c1558508 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -28,6 +28,7 @@
 #include <asm/vdso_datapage.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <linux/kbuild.h>
+#include "signal.h"
 
 /*
  * Make sure that the compiler and target are compatible.
@@ -112,6 +113,9 @@ int main(void)
   DEFINE(SVC_ADDR_LIMIT,	offsetof(struct svc_pt_regs, addr_limit));
   DEFINE(SVC_REGS_SIZE,		sizeof(struct svc_pt_regs));
   BLANK();
+  DEFINE(SIGFRAME_RC3_OFFSET,	offsetof(struct sigframe, retcode[3]));
+  DEFINE(RT_SIGFRAME_RC3_OFFSET, offsetof(struct rt_sigframe, sig.retcode[3]));
+  BLANK();
 #ifdef CONFIG_CACHE_L2X0
   DEFINE(L2X0_R_PHY_BASE,	offsetof(struct l2x0_regs, phy_base));
   DEFINE(L2X0_R_AUX_CTRL,	offsetof(struct l2x0_regs, aux_ctrl));
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 5814298ef0..1f3574ec4f 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -18,11 +18,12 @@
 #include <asm/elf.h>
 #include <asm/cacheflush.h>
 #include <asm/traps.h>
-#include <asm/ucontext.h>
 #include <asm/unistd.h>
 #include <asm/vfp.h>
 
-extern const unsigned long sigreturn_codes[7];
+#include "signal.h"
+
+extern const unsigned long sigreturn_codes[17];
 
 static unsigned long signal_return_offset;
 
@@ -171,15 +172,6 @@ static int restore_vfp_context(char __user **auxp)
 /*
  * Do a signal return; undo the signal stack.  These are aligned to 64-bit.
  */
-struct sigframe {
-	struct ucontext uc;
-	unsigned long retcode[2];
-};
-
-struct rt_sigframe {
-	struct siginfo info;
-	struct sigframe sig;
-};
 
 static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
 {
@@ -365,9 +357,20 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig,
 	     unsigned long __user *rc, void __user *frame)
 {
 	unsigned long handler = (unsigned long)ksig->ka.sa.sa_handler;
+	unsigned long handler_fdpic_GOT = 0;
 	unsigned long retcode;
-	int thumb = 0;
+	unsigned int idx, thumb = 0;
 	unsigned long cpsr = regs->ARM_cpsr & ~(PSR_f | PSR_E_BIT);
+	bool fdpic = IS_ENABLED(CONFIG_BINFMT_ELF_FDPIC) &&
+		     (current->personality & FDPIC_FUNCPTRS);
+
+	if (fdpic) {
+		unsigned long __user *fdpic_func_desc =
+					(unsigned long __user *)handler;
+		if (__get_user(handler, &fdpic_func_desc[0]) ||
+		    __get_user(handler_fdpic_GOT, &fdpic_func_desc[1]))
+			return 1;
+	}
 
 	cpsr |= PSR_ENDSTATE;
 
@@ -407,9 +410,26 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig,
 
 	if (ksig->ka.sa.sa_flags & SA_RESTORER) {
 		retcode = (unsigned long)ksig->ka.sa.sa_restorer;
+		if (fdpic) {
+			/*
+			 * We need code to load the function descriptor.
+			 * That code follows the standard sigreturn code
+			 * (6 words), and is made of 3 + 2 words for each
+			 * variant. The 4th copied word is the actual FD
+			 * address that the assembly code expects.
+			 */
+			idx = 6 + thumb * 3;
+			if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+				idx += 5;
+			if (__put_user(sigreturn_codes[idx],   rc  ) ||
+			    __put_user(sigreturn_codes[idx+1], rc+1) ||
+			    __put_user(sigreturn_codes[idx+2], rc+2) ||
+			    __put_user(retcode,                rc+3))
+				return 1;
+			goto rc_finish;
+		}
 	} else {
-		unsigned int idx = thumb << 1;
-
+		idx = thumb << 1;
 		if (ksig->ka.sa.sa_flags & SA_SIGINFO)
 			idx += 3;
 
@@ -421,6 +441,7 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig,
 		    __put_user(sigreturn_codes[idx+1], rc+1))
 			return 1;
 
+rc_finish:
 #ifdef CONFIG_MMU
 		if (cpsr & MODE32_BIT) {
 			struct mm_struct *mm = current->mm;
@@ -440,7 +461,7 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig,
 			 * the return code written onto the stack.
 			 */
 			flush_icache_range((unsigned long)rc,
-					   (unsigned long)(rc + 2));
+					   (unsigned long)(rc + 3));
 
 			retcode = ((unsigned long)rc) + thumb;
 		}
@@ -450,6 +471,8 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig,
 	regs->ARM_sp = (unsigned long)frame;
 	regs->ARM_lr = retcode;
 	regs->ARM_pc = handler;
+	if (fdpic)
+		regs->ARM_r9 = handler_fdpic_GOT;
 	regs->ARM_cpsr = cpsr;
 
 	return 0;
diff --git a/arch/arm/kernel/signal.h b/arch/arm/kernel/signal.h
new file mode 100644
index 0000000000..b7b838b052
--- /dev/null
+++ b/arch/arm/kernel/signal.h
@@ -0,0 +1,11 @@
+#include <asm/ucontext.h>
+
+struct sigframe {
+	struct ucontext uc;
+	unsigned long retcode[4];
+};
+
+struct rt_sigframe {
+	struct siginfo info;
+	struct sigframe sig;
+};
diff --git a/arch/arm/kernel/sigreturn_codes.S b/arch/arm/kernel/sigreturn_codes.S
index b84d0cb136..2c7b22e321 100644
--- a/arch/arm/kernel/sigreturn_codes.S
+++ b/arch/arm/kernel/sigreturn_codes.S
@@ -14,6 +14,8 @@
  * GNU General Public License for more details.
  */
 
+#include <asm/assembler.h>
+#include <asm/asm-offsets.h>
 #include <asm/unistd.h>
 
 /*
@@ -51,6 +53,17 @@ ARM_OK(	.arm	)
 	.thumb
 	.endm
 
+	.macro arm_fdpic_slot n
+	.org	sigreturn_codes + 24 + 20 * (\n)
+ARM_OK(	.arm	)
+	.endm
+
+	.macro thumb_fdpic_slot n
+	.org	sigreturn_codes + 24 + 20 * (\n) + 12
+	.thumb
+	.endm
+
+
 #if __LINUX_ARM_ARCH__ <= 4
 	/*
 	 * Note we manually set minimally required arch that supports
@@ -90,13 +103,46 @@ ARM_OK(	swi	#(__NR_rt_sigreturn)|(__NR_OABI_SYSCALL_BASE)	)
 	movs	r7, #(__NR_rt_sigreturn - __NR_SYSCALL_BASE)
 	swi	#0
 
+	/* ARM sigreturn restorer FDPIC bounce code snippet */
+	arm_fdpic_slot 0
+ARM_OK(	ldr	r3, [sp, #SIGFRAME_RC3_OFFSET] )
+ARM_OK(	ldmia	r3, {r3, r9} )
+#ifdef CONFIG_ARM_THUMB
+ARM_OK(	bx	r3 )
+#else
+ARM_OK(	ret	r3 )
+#endif
+
+	/* Thumb sigreturn restorer FDPIC bounce code snippet */
+	thumb_fdpic_slot 0
+	ldr	r3, [sp, #SIGFRAME_RC3_OFFSET]
+	ldmia	r3, {r2, r3}
+	mov	r9, r3
+	bx	r2
+
+	/* ARM sigreturn_rt restorer FDPIC bounce code snippet */
+	arm_fdpic_slot 1
+ARM_OK(	ldr	r3, [sp, #RT_SIGFRAME_RC3_OFFSET] )
+ARM_OK(	ldmia	r3, {r3, r9} )
+#ifdef CONFIG_ARM_THUMB
+ARM_OK(	bx	r3 )
+#else
+ARM_OK(	ret	r3 )
+#endif
+
+	/* Thumb sigreturn_rt restorer FDPIC bounce code snippet */
+	thumb_fdpic_slot 1
+	ldr	r3, [sp, #RT_SIGFRAME_RC3_OFFSET]
+	ldmia	r3, {r2, r3}
+	mov	r9, r3
+	bx	r2
+
 	/*
-	 * Note on addtional space: setup_return in signal.c
-	 * algorithm uses two words copy regardless whether
-	 * it is thumb case or not, so we need additional
-	 * word after real last entry.
+	 * Note on additional space: setup_return in signal.c
+	 * always copies the same number of words regardless whether
+	 * it is thumb case or not, so we need one additional padding
+	 * word after the last entry.
 	 */
-	arm_slot 2
 	.space	4
 
 	.size	sigreturn_codes, . - sigreturn_codes
-- 
2.9.5

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

* [PATCH v2 5/8] ARM: add ELF_FDPIC support
  2017-08-17  7:23 [PATCH v2 0/8] ELF-FDPIC support for ARM Nicolas Pitre
                   ` (3 preceding siblings ...)
  2017-08-17  7:23 ` [PATCH v2 4/8] ARM: signal handling support for FDPIC_FUNCPTRS functions Nicolas Pitre
@ 2017-08-17  7:23 ` Nicolas Pitre
  2017-08-28 14:07   ` [v2,5/8] " Vincent ABRIOU
  2017-08-17  7:23 ` [PATCH v2 6/8] ARM: enable elf_fdpic on systems with an MMU Nicolas Pitre
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 26+ messages in thread
From: Nicolas Pitre @ 2017-08-17  7:23 UTC (permalink / raw)
  To: linux-arm-kernel

This includes the necessary code to recognise the FDPIC format on ARM
and the ptrace command definitions used by the common ptrace code.

Based on patches originally from Mickael Guene <mickael.guene@st.com>.

Signed-off-by: Nicolas Pitre <nico@linaro.org>
---
 arch/arm/include/asm/elf.h         | 12 ++++++++++++
 arch/arm/include/asm/mmu.h         |  4 ++++
 arch/arm/include/uapi/asm/ptrace.h |  4 ++++
 fs/Kconfig.binfmt                  |  2 +-
 4 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h
index e2786acf82..ad0ca4f2ba 100644
--- a/arch/arm/include/asm/elf.h
+++ b/arch/arm/include/asm/elf.h
@@ -100,6 +100,11 @@ struct elf32_hdr;
 extern int elf_check_arch(const struct elf32_hdr *);
 #define elf_check_arch elf_check_arch
 
+#define ELFOSABI_ARM_FDPIC  65	/* ARM FDPIC platform */
+#define elf_check_fdpic(x)  ((x)->e_ident[EI_OSABI] == ELFOSABI_ARM_FDPIC)
+#define elf_check_const_displacement(x)  ((x)->e_flags & EF_ARM_PIC)
+#define ELF_FDPIC_CORE_EFLAGS  0
+
 #define vmcore_elf64_check_arch(x) (0)
 
 extern int arm_elf_read_implies_exec(int);
@@ -120,6 +125,13 @@ int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs);
    have no such handler.  */
 #define ELF_PLAT_INIT(_r, load_addr)	(_r)->ARM_r0 = 0
 
+#define ELF_FDPIC_PLAT_INIT(_r, _exec_map_addr, _interp_map_addr, dynamic_addr) \
+	do { \
+		(_r)->ARM_r7 = _exec_map_addr; \
+		(_r)->ARM_r8 = _interp_map_addr; \
+		(_r)->ARM_r9 = dynamic_addr; \
+	} while(0)
+
 extern void elf_set_personality(const struct elf32_hdr *);
 #define SET_PERSONALITY(ex)	elf_set_personality(&(ex))
 
diff --git a/arch/arm/include/asm/mmu.h b/arch/arm/include/asm/mmu.h
index a5b4742105..e0eb16680a 100644
--- a/arch/arm/include/asm/mmu.h
+++ b/arch/arm/include/asm/mmu.h
@@ -33,6 +33,10 @@ typedef struct {
  */
 typedef struct {
 	unsigned long	end_brk;
+#ifdef CONFIG_BINFMT_ELF_FDPIC
+	unsigned long	exec_fdpic_loadmap;
+	unsigned long	interp_fdpic_loadmap;
+#endif
 } mm_context_t;
 
 #endif
diff --git a/arch/arm/include/uapi/asm/ptrace.h b/arch/arm/include/uapi/asm/ptrace.h
index 5af0ed1b82..3173eb9751 100644
--- a/arch/arm/include/uapi/asm/ptrace.h
+++ b/arch/arm/include/uapi/asm/ptrace.h
@@ -31,6 +31,10 @@
 #define PTRACE_SETVFPREGS	28
 #define PTRACE_GETHBPREGS	29
 #define PTRACE_SETHBPREGS	30
+#define PTRACE_GETFDPIC		31
+
+#define PTRACE_GETFDPIC_EXEC	0
+#define PTRACE_GETFDPIC_INTERP	1
 
 /*
  * PSR bits
diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt
index b2f82cf6bf..6ef70ce8e9 100644
--- a/fs/Kconfig.binfmt
+++ b/fs/Kconfig.binfmt
@@ -35,7 +35,7 @@ config ARCH_BINFMT_ELF_STATE
 config BINFMT_ELF_FDPIC
 	bool "Kernel support for FDPIC ELF binaries"
 	default y
-	depends on (FRV || BLACKFIN || (SUPERH32 && !MMU) || C6X)
+	depends on ((ARM && !MMU) || FRV || BLACKFIN || (SUPERH32 && !MMU) || C6X)
 	select ELFCORE
 	help
 	  ELF FDPIC binaries are based on ELF, but allow the individual load
-- 
2.9.5

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

* [PATCH v2 6/8] ARM: enable elf_fdpic on systems with an MMU
  2017-08-17  7:23 [PATCH v2 0/8] ELF-FDPIC support for ARM Nicolas Pitre
                   ` (4 preceding siblings ...)
  2017-08-17  7:23 ` [PATCH v2 5/8] ARM: add ELF_FDPIC support Nicolas Pitre
@ 2017-08-17  7:23 ` Nicolas Pitre
  2017-08-28 14:07   ` [v2,6/8] " Vincent ABRIOU
  2017-08-17  7:23 ` [PATCH v2 7/8] binfmt_elf: don't attempt to load FDPIC binaries Nicolas Pitre
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 26+ messages in thread
From: Nicolas Pitre @ 2017-08-17  7:23 UTC (permalink / raw)
  To: linux-arm-kernel

Provide the necessary changes to be able to execute ELF-FDPIC binaries
on ARM systems with an MMU.

The default for CONFIG_BINFMT_ELF_FDPIC is also set to n if the regular
ELF loader is already configured so not to force FDPIC support on
everyone. Given that CONFIG_BINFMT_ELF depends on CONFIG_MMU, this means
CONFIG_BINFMT_ELF_FDPIC will still default to y when !MMU.

Signed-off-by: Nicolas Pitre <nico@linaro.org>
---
 arch/arm/include/asm/mmu.h |  4 ++++
 arch/arm/kernel/elf.c      | 22 ++++++++++++++++++++++
 fs/Kconfig.binfmt          |  4 ++--
 fs/binfmt_elf_fdpic.c      |  5 +++++
 4 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/arch/arm/include/asm/mmu.h b/arch/arm/include/asm/mmu.h
index e0eb16680a..bdec37c6ac 100644
--- a/arch/arm/include/asm/mmu.h
+++ b/arch/arm/include/asm/mmu.h
@@ -14,6 +14,10 @@ typedef struct {
 #ifdef CONFIG_VDSO
 	unsigned long	vdso;
 #endif
+#ifdef CONFIG_BINFMT_ELF_FDPIC
+	unsigned long	exec_fdpic_loadmap;
+	unsigned long	interp_fdpic_loadmap;
+#endif
 } mm_context_t;
 
 #ifdef CONFIG_CPU_HAS_ASID
diff --git a/arch/arm/kernel/elf.c b/arch/arm/kernel/elf.c
index 52fb98358d..569e69ece5 100644
--- a/arch/arm/kernel/elf.c
+++ b/arch/arm/kernel/elf.c
@@ -3,6 +3,7 @@
 #include <linux/personality.h>
 #include <linux/binfmts.h>
 #include <linux/elf.h>
+#include <linux/elf-fdpic.h>
 #include <asm/system_info.h>
 
 int elf_check_arch(const struct elf32_hdr *x)
@@ -89,3 +90,24 @@ int arm_elf_read_implies_exec(int executable_stack)
 	return 0;
 }
 EXPORT_SYMBOL(arm_elf_read_implies_exec);
+
+#if defined(CONFIG_MMU) && defined(CONFIG_BINFMT_ELF_FDPIC)
+
+void elf_fdpic_arch_lay_out_mm(struct elf_fdpic_params *exec_params,
+			       struct elf_fdpic_params *interp_params,
+			       unsigned long *start_stack,
+			       unsigned long *start_brk)
+{
+	elf_set_personality(&exec_params->hdr);
+
+	exec_params->load_addr = 0x8000;
+	interp_params->load_addr = ELF_ET_DYN_BASE;
+	*start_stack = TASK_SIZE - SZ_16M;
+
+	if ((exec_params->flags & ELF_FDPIC_FLAG_ARRANGEMENT) == ELF_FDPIC_FLAG_INDEPENDENT) {
+		exec_params->flags &= ~ELF_FDPIC_FLAG_ARRANGEMENT;
+		exec_params->flags |= ELF_FDPIC_FLAG_CONSTDISP;
+	}
+}
+
+#endif
diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt
index 6ef70ce8e9..58c2bbd385 100644
--- a/fs/Kconfig.binfmt
+++ b/fs/Kconfig.binfmt
@@ -34,8 +34,8 @@ config ARCH_BINFMT_ELF_STATE
 
 config BINFMT_ELF_FDPIC
 	bool "Kernel support for FDPIC ELF binaries"
-	default y
-	depends on ((ARM && !MMU) || FRV || BLACKFIN || (SUPERH32 && !MMU) || C6X)
+	default y if !BINFMT_ELF
+	depends on (ARM || FRV || BLACKFIN || (SUPERH32 && !MMU) || C6X)
 	select ELFCORE
 	help
 	  ELF FDPIC binaries are based on ELF, but allow the individual load
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index cf93a4fad0..692e2a1fd2 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -377,6 +377,11 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm)
 				 executable_stack);
 	if (retval < 0)
 		goto error;
+#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
+	retval = arch_setup_additional_pages(bprm, !!interpreter_name);
+	if (retval < 0)
+		goto error;
+#endif
 #endif
 
 	/* load the executable and interpreter into memory */
-- 
2.9.5

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

* [PATCH v2 7/8] binfmt_elf: don't attempt to load FDPIC binaries
  2017-08-17  7:23 [PATCH v2 0/8] ELF-FDPIC support for ARM Nicolas Pitre
                   ` (5 preceding siblings ...)
  2017-08-17  7:23 ` [PATCH v2 6/8] ARM: enable elf_fdpic on systems with an MMU Nicolas Pitre
@ 2017-08-17  7:23 ` Nicolas Pitre
  2017-08-28 14:08   ` [v2,7/8] " Vincent ABRIOU
  2017-08-17  7:23 ` [PATCH v2 8/8] binfmt_elf_fdpic: fix crash on MMU system with dynamic binaries Nicolas Pitre
  2017-08-17  8:37 ` [PATCH v2 0/8] ELF-FDPIC support for ARM Russell King - ARM Linux
  8 siblings, 1 reply; 26+ messages in thread
From: Nicolas Pitre @ 2017-08-17  7:23 UTC (permalink / raw)
  To: linux-arm-kernel

On platforms where both ELF and ELF-FDPIC variants are available, the
regular ELF loader will happily identify FDPIC binaries as proper ELF
and load them without the necessary FDPIC fixups, resulting in an
immediate user space crash. Let's prevent binflt_elf from loading those
binaries so binfmt_elf_fdpic has a chance to pick them up. For those
architectures that don't define elf_check_fdpic(), a default version
returning false is provided.

Signed-off-by: Nicolas Pitre <nico@linaro.org>
---
 fs/binfmt_elf.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 879ff9c7ff..84d64afaea 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -51,6 +51,11 @@
 #define user_siginfo_t siginfo_t
 #endif
 
+/* That's for binfmt_elf_fdpic to deal with */
+#ifndef elf_check_fdpic
+#define elf_check_fdpic(ex) false
+#endif
+
 static int load_elf_binary(struct linux_binprm *bprm);
 static unsigned long elf_map(struct file *, unsigned long, struct elf_phdr *,
 				int, int, unsigned long);
@@ -541,7 +546,8 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
 	if (interp_elf_ex->e_type != ET_EXEC &&
 	    interp_elf_ex->e_type != ET_DYN)
 		goto out;
-	if (!elf_check_arch(interp_elf_ex))
+	if (!elf_check_arch(interp_elf_ex) ||
+	    elf_check_fdpic(interp_elf_ex))
 		goto out;
 	if (!interpreter->f_op->mmap)
 		goto out;
@@ -718,6 +724,8 @@ static int load_elf_binary(struct linux_binprm *bprm)
 		goto out;
 	if (!elf_check_arch(&loc->elf_ex))
 		goto out;
+	if (elf_check_fdpic(&loc->elf_ex))
+		goto out;
 	if (!bprm->file->f_op->mmap)
 		goto out;
 
@@ -817,7 +825,8 @@ static int load_elf_binary(struct linux_binprm *bprm)
 		if (memcmp(loc->interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
 			goto out_free_dentry;
 		/* Verify the interpreter has a valid arch */
-		if (!elf_check_arch(&loc->interp_elf_ex))
+		if (!elf_check_arch(&loc->interp_elf_ex) ||
+		    elf_check_fdpic(&loc->interp_elf_ex))
 			goto out_free_dentry;
 
 		/* Load the interpreter program headers */
@@ -1189,6 +1198,8 @@ static int load_elf_library(struct file *file)
 	if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
 	    !elf_check_arch(&elf_ex) || !file->f_op->mmap)
 		goto out;
+	if (elf_check_fdpic(&elf_ex))
+		goto out;
 
 	/* Now read in all of the header information */
 
-- 
2.9.5

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

* [PATCH v2 8/8] binfmt_elf_fdpic: fix crash on MMU system with dynamic binaries
  2017-08-17  7:23 [PATCH v2 0/8] ELF-FDPIC support for ARM Nicolas Pitre
                   ` (6 preceding siblings ...)
  2017-08-17  7:23 ` [PATCH v2 7/8] binfmt_elf: don't attempt to load FDPIC binaries Nicolas Pitre
@ 2017-08-17  7:23 ` Nicolas Pitre
  2017-08-28 14:08   ` [v2, " Vincent ABRIOU
  2017-08-17  8:37 ` [PATCH v2 0/8] ELF-FDPIC support for ARM Russell King - ARM Linux
  8 siblings, 1 reply; 26+ messages in thread
From: Nicolas Pitre @ 2017-08-17  7:23 UTC (permalink / raw)
  To: linux-arm-kernel

In elf_fdpic_map_file() there is a test to ensure the dynamic section in
user space is properly terminated. However it does so by dereferencing
a user address directly. Add proper user space accessor.

Signed-off-by: Nicolas Pitre <nico@linaro.org>
---
 fs/binfmt_elf_fdpic.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index 692e2a1fd2..6a56dea138 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -835,6 +835,9 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
 			if (phdr->p_vaddr >= seg->p_vaddr &&
 			    phdr->p_vaddr + phdr->p_memsz <=
 			    seg->p_vaddr + seg->p_memsz) {
+				Elf32_Dyn __user *dyn;
+				Elf32_Sword d_tag;
+
 				params->dynamic_addr =
 					(phdr->p_vaddr - seg->p_vaddr) +
 					seg->addr;
@@ -847,8 +850,9 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
 					goto dynamic_error;
 
 				tmp = phdr->p_memsz / sizeof(Elf32_Dyn);
-				if (((Elf32_Dyn *)
-				     params->dynamic_addr)[tmp - 1].d_tag != 0)
+				dyn = (Elf32_Dyn __user *)params->dynamic_addr;
+				__get_user(d_tag, &dyn[tmp - 1].d_tag);
+				if (d_tag != 0)
 					goto dynamic_error;
 				break;
 			}
-- 
2.9.5

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

* [PATCH v2 0/8] ELF-FDPIC support for ARM
  2017-08-17  7:23 [PATCH v2 0/8] ELF-FDPIC support for ARM Nicolas Pitre
                   ` (7 preceding siblings ...)
  2017-08-17  7:23 ` [PATCH v2 8/8] binfmt_elf_fdpic: fix crash on MMU system with dynamic binaries Nicolas Pitre
@ 2017-08-17  8:37 ` Russell King - ARM Linux
  2017-08-23 16:41   ` Nicolas Pitre
  2017-08-25 14:27   ` Mickael GUENE
  8 siblings, 2 replies; 26+ messages in thread
From: Russell King - ARM Linux @ 2017-08-17  8:37 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Aug 17, 2017 at 03:23:39AM -0400, Nicolas Pitre wrote:
> This series provides the needed changes to suport the ELF_FDPIC binary
> format on ARM. Both MMU and non-MMU systems are supported. This format
> has many advantages over the BFLT format used on MMU-less systems, such
> as being real ELF that can be parsed by standard tools, can support
> shared dynamic libs, etc.

I don't see anything issues from the core arch point of view with this,
most of it looks straight forward, and the impact on existing users
should be low.  However, it would be nice to get some acks (if possible)
for the non-arch stuff and some tested-by's on this.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up

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

* [PATCH v2 0/8] ELF-FDPIC support for ARM
  2017-08-17  8:37 ` [PATCH v2 0/8] ELF-FDPIC support for ARM Russell King - ARM Linux
@ 2017-08-23 16:41   ` Nicolas Pitre
  2017-08-24  8:22     ` Vladimir Murzin
  2017-08-25 14:27   ` Mickael GUENE
  1 sibling, 1 reply; 26+ messages in thread
From: Nicolas Pitre @ 2017-08-23 16:41 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 17 Aug 2017, Russell King - ARM Linux wrote:

> On Thu, Aug 17, 2017 at 03:23:39AM -0400, Nicolas Pitre wrote:
> > This series provides the needed changes to suport the ELF_FDPIC binary
> > format on ARM. Both MMU and non-MMU systems are supported. This format
> > has many advantages over the BFLT format used on MMU-less systems, such
> > as being real ELF that can be parsed by standard tools, can support
> > shared dynamic libs, etc.
> 
> I don't see anything issues from the core arch point of view with this,
> most of it looks straight forward, and the impact on existing users
> should be low.  However, it would be nice to get some acks (if possible)
> for the non-arch stuff and some tested-by's on this.

Well...

I did prod a few people for testing. Either they're on vacation, or not 
interested, but I've received no tested-by's nor ACK's what so ever at 
this point. I did test it myself of course, on both MMU and non-MMU 
targets, and with static and dynamic binaries.

For the non-arch stuff I did post the relevant patches separately to 
viro and cc to lkml a while ago. So far I've been greated with silence 
there as well. Here's what those changes are:

1) binfmt_elf: don't attempt to load FDPIC binaries

This adds a default definition for elf_check_fdpic returning false. 
Therefore on architectures with no ELF-FDPIC support this is a no-op. 
Among those architectures actually defining elf_check_fdpic, only ARM 
(with this series applied) does support standard ELF as well. The FRV 
architecture could possibly do both but it is currently marked BROKEN. 
Maybe this patch could potentially "fix" FRV too? So in practice the 
only place where this has an effect right now is on ARM.

2) binfmt_elf_fdpic: fix crash on MMU system with dynamic binaries

This one should be obvious enough to people actually _using_ it. 
Apparently there aren't that many or this would have been fixed long 
ago. This is turning a direct user space access into one with a proper 
accessor. On no-MMU targets those accessors are transparent so this 
won't change anything to the compiled code.

3) ARM: enable elf_fdpic on systems with an MMU

This adds a block surrounded by #ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES 
in fs/binfmt_elf_fdpic.c inside a block already surrounded by #ifdef 
CONFIG_MMU. As indicated in #2, the MMU version of fs/binfmt_elf_fdpic.c 
was already non-functional so this is unlikely to affect anyone. 
Furthermore, none of the architectures that may enable this code (MMU or 
not) have ARCH_HAS_SETUP_ADDITIONAL_PAGES defined, except for ARM.

So I think that the non-arch changes is demonstrably not going to affect 
any existing users.

Therefore at this point I'd suggest you pull the branch so it gets some 
exposure in linux-next to see if this clashes with other people's work 
somehow (I doubt it will). If ever ACKs come by I'll add them and ask 
you to repull before the merge window.

http://git.linaro.org/people/nicolas.pitre/linux fdpic


Nicolas

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

* [PATCH v2 0/8] ELF-FDPIC support for ARM
  2017-08-23 16:41   ` Nicolas Pitre
@ 2017-08-24  8:22     ` Vladimir Murzin
  2017-08-24 12:37       ` Nicolas Pitre
  0 siblings, 1 reply; 26+ messages in thread
From: Vladimir Murzin @ 2017-08-24  8:22 UTC (permalink / raw)
  To: linux-arm-kernel

On 23/08/17 17:41, Nicolas Pitre wrote:
> On Thu, 17 Aug 2017, Russell King - ARM Linux wrote:
> 
>> On Thu, Aug 17, 2017 at 03:23:39AM -0400, Nicolas Pitre wrote:
>>> This series provides the needed changes to suport the ELF_FDPIC binary
>>> format on ARM. Both MMU and non-MMU systems are supported. This format
>>> has many advantages over the BFLT format used on MMU-less systems, such
>>> as being real ELF that can be parsed by standard tools, can support
>>> shared dynamic libs, etc.
>>
>> I don't see anything issues from the core arch point of view with this,
>> most of it looks straight forward, and the impact on existing users
>> should be low.  However, it would be nice to get some acks (if possible)
>> for the non-arch stuff and some tested-by's on this.
> 
> Well...
> 
> I did prod a few people for testing. Either they're on vacation, or not 
> interested, but I've received no tested-by's nor ACK's what so ever at 
> this point. I did test it myself of course, on both MMU and non-MMU 
> targets, and with static and dynamic binaries.

IIRC, Andras (CCed) has been running FDPIC for a while. Also, I can try to
give it a go on M/R class systems around next week.

I've noticed under Mickael's repo extra patches:

- Add tls support for cortex-m cpu family
- Workaround to fix futex bug on mmu less

It'd be nice if you shed some light on why they are not present in your
series.

Thanks
Vladimir

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

* [PATCH v2 0/8] ELF-FDPIC support for ARM
  2017-08-24  8:22     ` Vladimir Murzin
@ 2017-08-24 12:37       ` Nicolas Pitre
  2017-08-24 12:46         ` Mickael GUENE
  0 siblings, 1 reply; 26+ messages in thread
From: Nicolas Pitre @ 2017-08-24 12:37 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 24 Aug 2017, Vladimir Murzin wrote:

> On 23/08/17 17:41, Nicolas Pitre wrote:
> > On Thu, 17 Aug 2017, Russell King - ARM Linux wrote:
> > 
> >> On Thu, Aug 17, 2017 at 03:23:39AM -0400, Nicolas Pitre wrote:
> >>> This series provides the needed changes to suport the ELF_FDPIC binary
> >>> format on ARM. Both MMU and non-MMU systems are supported. This format
> >>> has many advantages over the BFLT format used on MMU-less systems, such
> >>> as being real ELF that can be parsed by standard tools, can support
> >>> shared dynamic libs, etc.
> >>
> >> I don't see anything issues from the core arch point of view with this,
> >> most of it looks straight forward, and the impact on existing users
> >> should be low.  However, it would be nice to get some acks (if possible)
> >> for the non-arch stuff and some tested-by's on this.
> > 
> > Well...
> > 
> > I did prod a few people for testing. Either they're on vacation, or not 
> > interested, but I've received no tested-by's nor ACK's what so ever at 
> > this point. I did test it myself of course, on both MMU and non-MMU 
> > targets, and with static and dynamic binaries.
> 
> IIRC, Andras (CCed) has been running FDPIC for a while. Also, I can try to
> give it a go on M/R class systems around next week.

Thanks.

> I've noticed under Mickael's repo extra patches:
> 
> - Add tls support for cortex-m cpu family
> - Workaround to fix futex bug on mmu less
> 
> It'd be nice if you shed some light on why they are not present in your
> series.

The first one is.

The second one concerns a different maintainer entirely and is 
orthogonal to FDPIC support so I didn't include it here.


Nicolas

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

* [PATCH v2 0/8] ELF-FDPIC support for ARM
  2017-08-24 12:37       ` Nicolas Pitre
@ 2017-08-24 12:46         ` Mickael GUENE
  2017-08-24 15:48           ` Nicolas Pitre
  0 siblings, 1 reply; 26+ messages in thread
From: Mickael GUENE @ 2017-08-24 12:46 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Nicolas,

> The first one is.
  It also seems to me that 'Add tls support for cortex-m cpu family'
patch is missing. There is the one that add the get_tls syscall but
not this one which enable usage for cortex-m family.

Regards
Mickael

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

* [PATCH v2 0/8] ELF-FDPIC support for ARM
  2017-08-24 12:46         ` Mickael GUENE
@ 2017-08-24 15:48           ` Nicolas Pitre
  2017-08-25  6:23             ` Mickael GUENE
  0 siblings, 1 reply; 26+ messages in thread
From: Nicolas Pitre @ 2017-08-24 15:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 24 Aug 2017, Mickael GUENE wrote:

> Hi Nicolas,
> 
> > The first one is.
>   It also seems to me that 'Add tls support for cortex-m cpu family'
> patch is missing. There is the one that add the get_tls syscall but
> not this one which enable usage for cortex-m family.

The patch titled "Add tls support for cortex-m cpu family" in your 
repository does 3 things:

- It defines switch_tls to switch_tls_none. Without the patch the 
  default is switch_tls_software. But this has no purpose as on Cortex-M
  targets there is simply no switch_tls usage at all. The switch_tls 
  macro is invoked in entry-armv.S within __switch_to whereas Cortex-M
  uses a different implementation of __switch_to in entry-v7m.S.

- The patch also defines has_tls_reg to 0. That's the same as de default 
  without the patch.

- It also defines tls_emu to 1. That makes no sense as this is for ARMv6 
  that lack the dedicated CP15 register and is completely wrong for 
  Cortex-M. I suspect the actual reason for defining this to 1 was a 
  dubious workaround to prevent set_tls() from storing the TLS value at 
  the absolute address 0xffff0ff0. In recent kernels that particular 
  code is properly conditioned on CONFIG_KUSER_HELPERS instead.

So in the current mainline kernel this patch is useless. This is why I 
didn't consider it.


Nicolas

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

* [PATCH v2 0/8] ELF-FDPIC support for ARM
  2017-08-24 15:48           ` Nicolas Pitre
@ 2017-08-25  6:23             ` Mickael GUENE
  0 siblings, 0 replies; 26+ messages in thread
From: Mickael GUENE @ 2017-08-25  6:23 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Nicolas,

  Thanks for explanation.

Regards
Mickael

On 08/24/2017 05:48 PM, Nicolas Pitre wrote:
> On Thu, 24 Aug 2017, Mickael GUENE wrote:
> 
>> Hi Nicolas,
>>
>>> The first one is.
>>    It also seems to me that 'Add tls support for cortex-m cpu family'
>> patch is missing. There is the one that add the get_tls syscall but
>> not this one which enable usage for cortex-m family.
> 
> The patch titled "Add tls support for cortex-m cpu family" in your
> repository does 3 things:
> 
> - It defines switch_tls to switch_tls_none. Without the patch the
>    default is switch_tls_software. But this has no purpose as on Cortex-M
>    targets there is simply no switch_tls usage at all. The switch_tls
>    macro is invoked in entry-armv.S within __switch_to whereas Cortex-M
>    uses a different implementation of __switch_to in entry-v7m.S.
> 
> - The patch also defines has_tls_reg to 0. That's the same as de default
>    without the patch.
> 
> - It also defines tls_emu to 1. That makes no sense as this is for ARMv6
>    that lack the dedicated CP15 register and is completely wrong for
>    Cortex-M. I suspect the actual reason for defining this to 1 was a
>    dubious workaround to prevent set_tls() from storing the TLS value at
>    the absolute address 0xffff0ff0. In recent kernels that particular
>    code is properly conditioned on CONFIG_KUSER_HELPERS instead.
> 
> So in the current mainline kernel this patch is useless. This is why I
> didn't consider it.
> 
> 
> Nicolas
> 

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

* [PATCH v2 0/8] ELF-FDPIC support for ARM
  2017-08-17  8:37 ` [PATCH v2 0/8] ELF-FDPIC support for ARM Russell King - ARM Linux
  2017-08-23 16:41   ` Nicolas Pitre
@ 2017-08-25 14:27   ` Mickael GUENE
  1 sibling, 0 replies; 26+ messages in thread
From: Mickael GUENE @ 2017-08-25 14:27 UTC (permalink / raw)
  To: linux-arm-kernel

Acked-by: Mickael GUENE <mickael.guene@st.com> for the whole patch series.

Thanks to you Nicolas for your upstreaming efforts.

Regards
Mickael

On 08/17/2017 10:37 AM, Russell King - ARM Linux wrote:
> On Thu, Aug 17, 2017 at 03:23:39AM -0400, Nicolas Pitre wrote:
>> This series provides the needed changes to suport the ELF_FDPIC binary
>> format on ARM. Both MMU and non-MMU systems are supported. This format
>> has many advantages over the BFLT format used on MMU-less systems, such
>> as being real ELF that can be parsed by standard tools, can support
>> shared dynamic libs, etc.
> 
> I don't see anything issues from the core arch point of view with this,
> most of it looks straight forward, and the impact on existing users
> should be low.  However, it would be nice to get some acks (if possible)
> for the non-arch stuff and some tested-by's on this.
> 

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

* [v2,1/8] ARM: implement get_tls syscall
  2017-08-17  7:23 ` [PATCH v2 1/8] ARM: implement get_tls syscall Nicolas Pitre
@ 2017-08-28 14:05   ` Vincent ABRIOU
  0 siblings, 0 replies; 26+ messages in thread
From: Vincent ABRIOU @ 2017-08-28 14:05 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Nicolas,

I have successfully tested your set of patches on cortex-M7 STM32 MCU.


On 08/17/2017 09:23 AM, Nicolas Pitre wrote:
> When there is no dedicated register to hold the tp value and no MMU
> to provide a fixed address kuser helper entry point, all that is
> left as fallback is a syscall.
> 
> Signed-off-by: Nicolas Pitre <nico@linaro.org>
Tested-by: Vincent Abriou <vincent.abriou@st.com>

BR
Vincent

> ---
>   arch/arm/include/uapi/asm/unistd.h | 1 +
>   arch/arm/kernel/traps.c            | 3 +++
>   2 files changed, 4 insertions(+)
> 
> diff --git a/arch/arm/include/uapi/asm/unistd.h b/arch/arm/include/uapi/asm/unistd.h
> index 28bd456494..575b25fc29 100644
> --- a/arch/arm/include/uapi/asm/unistd.h
> +++ b/arch/arm/include/uapi/asm/unistd.h
> @@ -35,5 +35,6 @@
>   #define __ARM_NR_usr26			(__ARM_NR_BASE+3)
>   #define __ARM_NR_usr32			(__ARM_NR_BASE+4)
>   #define __ARM_NR_set_tls		(__ARM_NR_BASE+5)
> +#define __ARM_NR_get_tls		(__ARM_NR_BASE+6)
>   
>   #endif /* _UAPI__ASM_ARM_UNISTD_H */
> diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
> index 948c648fea..43c0560f7b 100644
> --- a/arch/arm/kernel/traps.c
> +++ b/arch/arm/kernel/traps.c
> @@ -647,6 +647,9 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
>   		set_tls(regs->ARM_r0);
>   		return 0;
>   
> +	case NR(get_tls):
> +		return current_thread_info()->tp_value[0];
> +
>   	default:
>   		/* Calls 9f00xx..9f07ff are defined to return -ENOSYS
>   		   if not implemented, rather than raising SIGILL.  This
> 

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

* [v2,2/8] arm_elf_read_implies_exec(): remove unused argument
  2017-08-17  7:23 ` [PATCH v2 2/8] arm_elf_read_implies_exec(): remove unused argument Nicolas Pitre
@ 2017-08-28 14:06   ` Vincent ABRIOU
  0 siblings, 0 replies; 26+ messages in thread
From: Vincent ABRIOU @ 2017-08-28 14:06 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Nicolas,

On 08/17/2017 09:23 AM, Nicolas Pitre wrote:
> The first argument to elf_read_implies_exec() is either the actual
> header structure or a pointer to that structure whether one looks
> at fs/binfmt_elf.c or fs/binfmt_elf_fdpic.c. This ought to be fixed
> of course, but in the mean time let's sidestep the issue by removing
> that first argument from arm_elf_read_implies_exec() as it is unused
> anyway.
> 
> Signed-off-by: Nicolas Pitre <nico@linaro.org>
Tested-by: Vincent Abriou <vincent.abriou@st.com>

BR
Vincent

> ---
>   arch/arm/include/asm/elf.h | 4 ++--
>   arch/arm/kernel/elf.c      | 2 +-
>   2 files changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h
> index f13ae153fb..e2786acf82 100644
> --- a/arch/arm/include/asm/elf.h
> +++ b/arch/arm/include/asm/elf.h
> @@ -102,8 +102,8 @@ extern int elf_check_arch(const struct elf32_hdr *);
>   
>   #define vmcore_elf64_check_arch(x) (0)
>   
> -extern int arm_elf_read_implies_exec(const struct elf32_hdr *, int);
> -#define elf_read_implies_exec(ex,stk) arm_elf_read_implies_exec(&(ex), stk)
> +extern int arm_elf_read_implies_exec(int);
> +#define elf_read_implies_exec(ex,stk) arm_elf_read_implies_exec(stk)
>   
>   struct task_struct;
>   int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs);
> diff --git a/arch/arm/kernel/elf.c b/arch/arm/kernel/elf.c
> index d0d1e83150..52fb98358d 100644
> --- a/arch/arm/kernel/elf.c
> +++ b/arch/arm/kernel/elf.c
> @@ -80,7 +80,7 @@ EXPORT_SYMBOL(elf_set_personality);
>    *  - the binary requires an executable stack
>    *  - we're running on a CPU which doesn't support NX.
>    */
> -int arm_elf_read_implies_exec(const struct elf32_hdr *x, int executable_stack)
> +int arm_elf_read_implies_exec(int executable_stack)
>   {
>   	if (executable_stack != EXSTACK_DISABLE_X)
>   		return 1;
> 

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

* [v2,3/8] ARM: start_thread(): don't always clear all regs
  2017-08-17  7:23 ` [PATCH v2 3/8] ARM: start_thread(): don't always clear all regs Nicolas Pitre
@ 2017-08-28 14:07   ` Vincent ABRIOU
  0 siblings, 0 replies; 26+ messages in thread
From: Vincent ABRIOU @ 2017-08-28 14:07 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Nicolas,

On 08/17/2017 09:23 AM, Nicolas Pitre wrote:
> The elf_fdpic binary format driver has to initialize extra registers
> beside the stack and program counter as required by the corresponding
> ABI. So reinstate them after the regs structure has been cleared.
> 
> While at it let's get rid of start_thread_nommu().
> 
> Signed-off-by: Nicolas Pitre <nico@linaro.org>
Tested-by: Vincent Abriou <vincent.abriou@st.com>

BR
Vincent

> ---
>   arch/arm/include/asm/processor.h | 22 +++++++++++++++-------
>   1 file changed, 15 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h
> index c3d5fc124a..338cbe0a18 100644
> --- a/arch/arm/include/asm/processor.h
> +++ b/arch/arm/include/asm/processor.h
> @@ -47,15 +47,24 @@ struct thread_struct {
>   
>   #define INIT_THREAD  {	}
>   
> -#ifdef CONFIG_MMU
> -#define nommu_start_thread(regs) do { } while (0)
> -#else
> -#define nommu_start_thread(regs) regs->ARM_r10 = current->mm->start_data
> -#endif
> -
>   #define start_thread(regs,pc,sp)					\
>   ({									\
> +	unsigned long r7, r8, r9;					\
> +									\
> +	if (IS_ENABLED(CONFIG_BINFMT_ELF_FDPIC)) {			\
> +		r7 = regs->ARM_r7;					\
> +		r8 = regs->ARM_r8;					\
> +		r9 = regs->ARM_r9;					\
> +	}								\
>   	memset(regs->uregs, 0, sizeof(regs->uregs));			\
> +	if (IS_ENABLED(CONFIG_BINFMT_ELF_FDPIC) &&			\
> +	    current->personality & FDPIC_FUNCPTRS) {			\
> +		regs->ARM_r7 = r7;					\
> +		regs->ARM_r8 = r8;					\
> +		regs->ARM_r9 = r9;					\
> +		regs->ARM_r10 = current->mm->start_data;		\
> +	} else if (!IS_ENABLED(CONFIG_MMU))				\
> +		regs->ARM_r10 = current->mm->start_data;		\
>   	if (current->personality & ADDR_LIMIT_32BIT)			\
>   		regs->ARM_cpsr = USR_MODE;				\
>   	else								\
> @@ -65,7 +74,6 @@ struct thread_struct {
>   	regs->ARM_cpsr |= PSR_ENDSTATE;					\
>   	regs->ARM_pc = pc & ~1;		/* pc */			\
>   	regs->ARM_sp = sp;		/* sp */			\
> -	nommu_start_thread(regs);					\
>   })
>   
>   /* Forward declaration, a strange C thing */
> 

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

* [v2,4/8] ARM: signal handling support for FDPIC_FUNCPTRS functions
  2017-08-17  7:23 ` [PATCH v2 4/8] ARM: signal handling support for FDPIC_FUNCPTRS functions Nicolas Pitre
@ 2017-08-28 14:07   ` Vincent ABRIOU
  0 siblings, 0 replies; 26+ messages in thread
From: Vincent ABRIOU @ 2017-08-28 14:07 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Nicolas,

On 08/17/2017 09:23 AM, Nicolas Pitre wrote:
> Signal handlers are not direct function pointers but pointers to function
> descriptor in that case. Therefore we must retrieve the actual function
> address and load the GOT value into r9 from the descriptor before branching
> to the actual handler.
> 
> If a restorer is provided, we also have to load its address and GOT from
> its descriptor. That descriptor address and the code to load it is pushed
> onto the stack to be executed as soon as the signal handler returns.
> 
> However, to be compatible with NX stacks, the FDPIC bounce code is also
> copied to the signal page along with the other code stubs. Therefore this
> code must get at the descriptor address whether it executes from the stack
> or the signal page. To do so we use the stack pointer which points at the
> signal stack frame where the descriptor address was stored. Because the
> rt signal frame is different from the simpler frame, two versions of the
> bounce code are needed, and two variants (ARM and Thumb) as well. The
> asm-offsets facility is used to determine the actual offset in the signal
> frame for each version, meaning that struct sigframe and rt_sigframe had
> to be moved to a separate file.
> 
> Signed-off-by: Nicolas Pitre <nico@linaro.org>
Tested-by: Vincent Abriou <vincent.abriou@st.com>

BR
Vincent

> ---
>   arch/arm/include/asm/ucontext.h   |  1 +
>   arch/arm/kernel/asm-offsets.c     |  4 +++
>   arch/arm/kernel/signal.c          | 53 +++++++++++++++++++++++++-----------
>   arch/arm/kernel/signal.h          | 11 ++++++++
>   arch/arm/kernel/sigreturn_codes.S | 56 +++++++++++++++++++++++++++++++++++----
>   5 files changed, 105 insertions(+), 20 deletions(-)
>   create mode 100644 arch/arm/kernel/signal.h
> 
> diff --git a/arch/arm/include/asm/ucontext.h b/arch/arm/include/asm/ucontext.h
> index 921d827485..b42c75ae0d 100644
> --- a/arch/arm/include/asm/ucontext.h
> +++ b/arch/arm/include/asm/ucontext.h
> @@ -2,6 +2,7 @@
>   #define _ASMARM_UCONTEXT_H
>   
>   #include <asm/fpstate.h>
> +#include <asm/user.h>
>   
>   /*
>    * struct sigcontext only has room for the basic registers, but struct
> diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
> index 608008229c..13c1558508 100644
> --- a/arch/arm/kernel/asm-offsets.c
> +++ b/arch/arm/kernel/asm-offsets.c
> @@ -28,6 +28,7 @@
>   #include <asm/vdso_datapage.h>
>   #include <asm/hardware/cache-l2x0.h>
>   #include <linux/kbuild.h>
> +#include "signal.h"
>   
>   /*
>    * Make sure that the compiler and target are compatible.
> @@ -112,6 +113,9 @@ int main(void)
>     DEFINE(SVC_ADDR_LIMIT,	offsetof(struct svc_pt_regs, addr_limit));
>     DEFINE(SVC_REGS_SIZE,		sizeof(struct svc_pt_regs));
>     BLANK();
> +  DEFINE(SIGFRAME_RC3_OFFSET,	offsetof(struct sigframe, retcode[3]));
> +  DEFINE(RT_SIGFRAME_RC3_OFFSET, offsetof(struct rt_sigframe, sig.retcode[3]));
> +  BLANK();
>   #ifdef CONFIG_CACHE_L2X0
>     DEFINE(L2X0_R_PHY_BASE,	offsetof(struct l2x0_regs, phy_base));
>     DEFINE(L2X0_R_AUX_CTRL,	offsetof(struct l2x0_regs, aux_ctrl));
> diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
> index 5814298ef0..1f3574ec4f 100644
> --- a/arch/arm/kernel/signal.c
> +++ b/arch/arm/kernel/signal.c
> @@ -18,11 +18,12 @@
>   #include <asm/elf.h>
>   #include <asm/cacheflush.h>
>   #include <asm/traps.h>
> -#include <asm/ucontext.h>
>   #include <asm/unistd.h>
>   #include <asm/vfp.h>
>   
> -extern const unsigned long sigreturn_codes[7];
> +#include "signal.h"
> +
> +extern const unsigned long sigreturn_codes[17];
>   
>   static unsigned long signal_return_offset;
>   
> @@ -171,15 +172,6 @@ static int restore_vfp_context(char __user **auxp)
>   /*
>    * Do a signal return; undo the signal stack.  These are aligned to 64-bit.
>    */
> -struct sigframe {
> -	struct ucontext uc;
> -	unsigned long retcode[2];
> -};
> -
> -struct rt_sigframe {
> -	struct siginfo info;
> -	struct sigframe sig;
> -};
>   
>   static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
>   {
> @@ -365,9 +357,20 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig,
>   	     unsigned long __user *rc, void __user *frame)
>   {
>   	unsigned long handler = (unsigned long)ksig->ka.sa.sa_handler;
> +	unsigned long handler_fdpic_GOT = 0;
>   	unsigned long retcode;
> -	int thumb = 0;
> +	unsigned int idx, thumb = 0;
>   	unsigned long cpsr = regs->ARM_cpsr & ~(PSR_f | PSR_E_BIT);
> +	bool fdpic = IS_ENABLED(CONFIG_BINFMT_ELF_FDPIC) &&
> +		     (current->personality & FDPIC_FUNCPTRS);
> +
> +	if (fdpic) {
> +		unsigned long __user *fdpic_func_desc =
> +					(unsigned long __user *)handler;
> +		if (__get_user(handler, &fdpic_func_desc[0]) ||
> +		    __get_user(handler_fdpic_GOT, &fdpic_func_desc[1]))
> +			return 1;
> +	}
>   
>   	cpsr |= PSR_ENDSTATE;
>   
> @@ -407,9 +410,26 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig,
>   
>   	if (ksig->ka.sa.sa_flags & SA_RESTORER) {
>   		retcode = (unsigned long)ksig->ka.sa.sa_restorer;
> +		if (fdpic) {
> +			/*
> +			 * We need code to load the function descriptor.
> +			 * That code follows the standard sigreturn code
> +			 * (6 words), and is made of 3 + 2 words for each
> +			 * variant. The 4th copied word is the actual FD
> +			 * address that the assembly code expects.
> +			 */
> +			idx = 6 + thumb * 3;
> +			if (ksig->ka.sa.sa_flags & SA_SIGINFO)
> +				idx += 5;
> +			if (__put_user(sigreturn_codes[idx],   rc  ) ||
> +			    __put_user(sigreturn_codes[idx+1], rc+1) ||
> +			    __put_user(sigreturn_codes[idx+2], rc+2) ||
> +			    __put_user(retcode,                rc+3))
> +				return 1;
> +			goto rc_finish;
> +		}
>   	} else {
> -		unsigned int idx = thumb << 1;
> -
> +		idx = thumb << 1;
>   		if (ksig->ka.sa.sa_flags & SA_SIGINFO)
>   			idx += 3;
>   
> @@ -421,6 +441,7 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig,
>   		    __put_user(sigreturn_codes[idx+1], rc+1))
>   			return 1;
>   
> +rc_finish:
>   #ifdef CONFIG_MMU
>   		if (cpsr & MODE32_BIT) {
>   			struct mm_struct *mm = current->mm;
> @@ -440,7 +461,7 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig,
>   			 * the return code written onto the stack.
>   			 */
>   			flush_icache_range((unsigned long)rc,
> -					   (unsigned long)(rc + 2));
> +					   (unsigned long)(rc + 3));
>   
>   			retcode = ((unsigned long)rc) + thumb;
>   		}
> @@ -450,6 +471,8 @@ setup_return(struct pt_regs *regs, struct ksignal *ksig,
>   	regs->ARM_sp = (unsigned long)frame;
>   	regs->ARM_lr = retcode;
>   	regs->ARM_pc = handler;
> +	if (fdpic)
> +		regs->ARM_r9 = handler_fdpic_GOT;
>   	regs->ARM_cpsr = cpsr;
>   
>   	return 0;
> diff --git a/arch/arm/kernel/signal.h b/arch/arm/kernel/signal.h
> new file mode 100644
> index 0000000000..b7b838b052
> --- /dev/null
> +++ b/arch/arm/kernel/signal.h
> @@ -0,0 +1,11 @@
> +#include <asm/ucontext.h>
> +
> +struct sigframe {
> +	struct ucontext uc;
> +	unsigned long retcode[4];
> +};
> +
> +struct rt_sigframe {
> +	struct siginfo info;
> +	struct sigframe sig;
> +};
> diff --git a/arch/arm/kernel/sigreturn_codes.S b/arch/arm/kernel/sigreturn_codes.S
> index b84d0cb136..2c7b22e321 100644
> --- a/arch/arm/kernel/sigreturn_codes.S
> +++ b/arch/arm/kernel/sigreturn_codes.S
> @@ -14,6 +14,8 @@
>    * GNU General Public License for more details.
>    */
>   
> +#include <asm/assembler.h>
> +#include <asm/asm-offsets.h>
>   #include <asm/unistd.h>
>   
>   /*
> @@ -51,6 +53,17 @@ ARM_OK(	.arm	)
>   	.thumb
>   	.endm
>   
> +	.macro arm_fdpic_slot n
> +	.org	sigreturn_codes + 24 + 20 * (\n)
> +ARM_OK(	.arm	)
> +	.endm
> +
> +	.macro thumb_fdpic_slot n
> +	.org	sigreturn_codes + 24 + 20 * (\n) + 12
> +	.thumb
> +	.endm
> +
> +
>   #if __LINUX_ARM_ARCH__ <= 4
>   	/*
>   	 * Note we manually set minimally required arch that supports
> @@ -90,13 +103,46 @@ ARM_OK(	swi	#(__NR_rt_sigreturn)|(__NR_OABI_SYSCALL_BASE)	)
>   	movs	r7, #(__NR_rt_sigreturn - __NR_SYSCALL_BASE)
>   	swi	#0
>   
> +	/* ARM sigreturn restorer FDPIC bounce code snippet */
> +	arm_fdpic_slot 0
> +ARM_OK(	ldr	r3, [sp, #SIGFRAME_RC3_OFFSET] )
> +ARM_OK(	ldmia	r3, {r3, r9} )
> +#ifdef CONFIG_ARM_THUMB
> +ARM_OK(	bx	r3 )
> +#else
> +ARM_OK(	ret	r3 )
> +#endif
> +
> +	/* Thumb sigreturn restorer FDPIC bounce code snippet */
> +	thumb_fdpic_slot 0
> +	ldr	r3, [sp, #SIGFRAME_RC3_OFFSET]
> +	ldmia	r3, {r2, r3}
> +	mov	r9, r3
> +	bx	r2
> +
> +	/* ARM sigreturn_rt restorer FDPIC bounce code snippet */
> +	arm_fdpic_slot 1
> +ARM_OK(	ldr	r3, [sp, #RT_SIGFRAME_RC3_OFFSET] )
> +ARM_OK(	ldmia	r3, {r3, r9} )
> +#ifdef CONFIG_ARM_THUMB
> +ARM_OK(	bx	r3 )
> +#else
> +ARM_OK(	ret	r3 )
> +#endif
> +
> +	/* Thumb sigreturn_rt restorer FDPIC bounce code snippet */
> +	thumb_fdpic_slot 1
> +	ldr	r3, [sp, #RT_SIGFRAME_RC3_OFFSET]
> +	ldmia	r3, {r2, r3}
> +	mov	r9, r3
> +	bx	r2
> +
>   	/*
> -	 * Note on addtional space: setup_return in signal.c
> -	 * algorithm uses two words copy regardless whether
> -	 * it is thumb case or not, so we need additional
> -	 * word after real last entry.
> +	 * Note on additional space: setup_return in signal.c
> +	 * always copies the same number of words regardless whether
> +	 * it is thumb case or not, so we need one additional padding
> +	 * word after the last entry.
>   	 */
> -	arm_slot 2
>   	.space	4
>   
>   	.size	sigreturn_codes, . - sigreturn_codes
> 

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

* [v2,5/8] ARM: add ELF_FDPIC support
  2017-08-17  7:23 ` [PATCH v2 5/8] ARM: add ELF_FDPIC support Nicolas Pitre
@ 2017-08-28 14:07   ` Vincent ABRIOU
  0 siblings, 0 replies; 26+ messages in thread
From: Vincent ABRIOU @ 2017-08-28 14:07 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Nicolas

On 08/17/2017 09:23 AM, Nicolas Pitre wrote:
> This includes the necessary code to recognise the FDPIC format on ARM
> and the ptrace command definitions used by the common ptrace code.
> 
> Based on patches originally from Mickael Guene <mickael.guene@st.com>.
> 
> Signed-off-by: Nicolas Pitre <nico@linaro.org>
Tested-by: Vincent Abriou <vincent.abriou@st.com>

BR
Vincent

> ---
>   arch/arm/include/asm/elf.h         | 12 ++++++++++++
>   arch/arm/include/asm/mmu.h         |  4 ++++
>   arch/arm/include/uapi/asm/ptrace.h |  4 ++++
>   fs/Kconfig.binfmt                  |  2 +-
>   4 files changed, 21 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h
> index e2786acf82..ad0ca4f2ba 100644
> --- a/arch/arm/include/asm/elf.h
> +++ b/arch/arm/include/asm/elf.h
> @@ -100,6 +100,11 @@ struct elf32_hdr;
>   extern int elf_check_arch(const struct elf32_hdr *);
>   #define elf_check_arch elf_check_arch
>   
> +#define ELFOSABI_ARM_FDPIC  65	/* ARM FDPIC platform */
> +#define elf_check_fdpic(x)  ((x)->e_ident[EI_OSABI] == ELFOSABI_ARM_FDPIC)
> +#define elf_check_const_displacement(x)  ((x)->e_flags & EF_ARM_PIC)
> +#define ELF_FDPIC_CORE_EFLAGS  0
> +
>   #define vmcore_elf64_check_arch(x) (0)
>   
>   extern int arm_elf_read_implies_exec(int);
> @@ -120,6 +125,13 @@ int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs);
>      have no such handler.  */
>   #define ELF_PLAT_INIT(_r, load_addr)	(_r)->ARM_r0 = 0
>   
> +#define ELF_FDPIC_PLAT_INIT(_r, _exec_map_addr, _interp_map_addr, dynamic_addr) \
> +	do { \
> +		(_r)->ARM_r7 = _exec_map_addr; \
> +		(_r)->ARM_r8 = _interp_map_addr; \
> +		(_r)->ARM_r9 = dynamic_addr; \
> +	} while(0)
> +
>   extern void elf_set_personality(const struct elf32_hdr *);
>   #define SET_PERSONALITY(ex)	elf_set_personality(&(ex))
>   
> diff --git a/arch/arm/include/asm/mmu.h b/arch/arm/include/asm/mmu.h
> index a5b4742105..e0eb16680a 100644
> --- a/arch/arm/include/asm/mmu.h
> +++ b/arch/arm/include/asm/mmu.h
> @@ -33,6 +33,10 @@ typedef struct {
>    */
>   typedef struct {
>   	unsigned long	end_brk;
> +#ifdef CONFIG_BINFMT_ELF_FDPIC
> +	unsigned long	exec_fdpic_loadmap;
> +	unsigned long	interp_fdpic_loadmap;
> +#endif
>   } mm_context_t;
>   
>   #endif
> diff --git a/arch/arm/include/uapi/asm/ptrace.h b/arch/arm/include/uapi/asm/ptrace.h
> index 5af0ed1b82..3173eb9751 100644
> --- a/arch/arm/include/uapi/asm/ptrace.h
> +++ b/arch/arm/include/uapi/asm/ptrace.h
> @@ -31,6 +31,10 @@
>   #define PTRACE_SETVFPREGS	28
>   #define PTRACE_GETHBPREGS	29
>   #define PTRACE_SETHBPREGS	30
> +#define PTRACE_GETFDPIC		31
> +
> +#define PTRACE_GETFDPIC_EXEC	0
> +#define PTRACE_GETFDPIC_INTERP	1
>   
>   /*
>    * PSR bits
> diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt
> index b2f82cf6bf..6ef70ce8e9 100644
> --- a/fs/Kconfig.binfmt
> +++ b/fs/Kconfig.binfmt
> @@ -35,7 +35,7 @@ config ARCH_BINFMT_ELF_STATE
>   config BINFMT_ELF_FDPIC
>   	bool "Kernel support for FDPIC ELF binaries"
>   	default y
> -	depends on (FRV || BLACKFIN || (SUPERH32 && !MMU) || C6X)
> +	depends on ((ARM && !MMU) || FRV || BLACKFIN || (SUPERH32 && !MMU) || C6X)
>   	select ELFCORE
>   	help
>   	  ELF FDPIC binaries are based on ELF, but allow the individual load
> 

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

* [v2,6/8] ARM: enable elf_fdpic on systems with an MMU
  2017-08-17  7:23 ` [PATCH v2 6/8] ARM: enable elf_fdpic on systems with an MMU Nicolas Pitre
@ 2017-08-28 14:07   ` Vincent ABRIOU
  0 siblings, 0 replies; 26+ messages in thread
From: Vincent ABRIOU @ 2017-08-28 14:07 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Nicolas,

On 08/17/2017 09:23 AM, Nicolas Pitre wrote:
> Provide the necessary changes to be able to execute ELF-FDPIC binaries
> on ARM systems with an MMU.
> 
> The default for CONFIG_BINFMT_ELF_FDPIC is also set to n if the regular
> ELF loader is already configured so not to force FDPIC support on
> everyone. Given that CONFIG_BINFMT_ELF depends on CONFIG_MMU, this means
> CONFIG_BINFMT_ELF_FDPIC will still default to y when !MMU.
> 
> Signed-off-by: Nicolas Pitre <nico@linaro.org>
Tested-by: Vincent Abriou <vincent.abriou@st.com>

BR
Vincent

> ---
>   arch/arm/include/asm/mmu.h |  4 ++++
>   arch/arm/kernel/elf.c      | 22 ++++++++++++++++++++++
>   fs/Kconfig.binfmt          |  4 ++--
>   fs/binfmt_elf_fdpic.c      |  5 +++++
>   4 files changed, 33 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/include/asm/mmu.h b/arch/arm/include/asm/mmu.h
> index e0eb16680a..bdec37c6ac 100644
> --- a/arch/arm/include/asm/mmu.h
> +++ b/arch/arm/include/asm/mmu.h
> @@ -14,6 +14,10 @@ typedef struct {
>   #ifdef CONFIG_VDSO
>   	unsigned long	vdso;
>   #endif
> +#ifdef CONFIG_BINFMT_ELF_FDPIC
> +	unsigned long	exec_fdpic_loadmap;
> +	unsigned long	interp_fdpic_loadmap;
> +#endif
>   } mm_context_t;
>   
>   #ifdef CONFIG_CPU_HAS_ASID
> diff --git a/arch/arm/kernel/elf.c b/arch/arm/kernel/elf.c
> index 52fb98358d..569e69ece5 100644
> --- a/arch/arm/kernel/elf.c
> +++ b/arch/arm/kernel/elf.c
> @@ -3,6 +3,7 @@
>   #include <linux/personality.h>
>   #include <linux/binfmts.h>
>   #include <linux/elf.h>
> +#include <linux/elf-fdpic.h>
>   #include <asm/system_info.h>
>   
>   int elf_check_arch(const struct elf32_hdr *x)
> @@ -89,3 +90,24 @@ int arm_elf_read_implies_exec(int executable_stack)
>   	return 0;
>   }
>   EXPORT_SYMBOL(arm_elf_read_implies_exec);
> +
> +#if defined(CONFIG_MMU) && defined(CONFIG_BINFMT_ELF_FDPIC)
> +
> +void elf_fdpic_arch_lay_out_mm(struct elf_fdpic_params *exec_params,
> +			       struct elf_fdpic_params *interp_params,
> +			       unsigned long *start_stack,
> +			       unsigned long *start_brk)
> +{
> +	elf_set_personality(&exec_params->hdr);
> +
> +	exec_params->load_addr = 0x8000;
> +	interp_params->load_addr = ELF_ET_DYN_BASE;
> +	*start_stack = TASK_SIZE - SZ_16M;
> +
> +	if ((exec_params->flags & ELF_FDPIC_FLAG_ARRANGEMENT) == ELF_FDPIC_FLAG_INDEPENDENT) {
> +		exec_params->flags &= ~ELF_FDPIC_FLAG_ARRANGEMENT;
> +		exec_params->flags |= ELF_FDPIC_FLAG_CONSTDISP;
> +	}
> +}
> +
> +#endif
> diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt
> index 6ef70ce8e9..58c2bbd385 100644
> --- a/fs/Kconfig.binfmt
> +++ b/fs/Kconfig.binfmt
> @@ -34,8 +34,8 @@ config ARCH_BINFMT_ELF_STATE
>   
>   config BINFMT_ELF_FDPIC
>   	bool "Kernel support for FDPIC ELF binaries"
> -	default y
> -	depends on ((ARM && !MMU) || FRV || BLACKFIN || (SUPERH32 && !MMU) || C6X)
> +	default y if !BINFMT_ELF
> +	depends on (ARM || FRV || BLACKFIN || (SUPERH32 && !MMU) || C6X)
>   	select ELFCORE
>   	help
>   	  ELF FDPIC binaries are based on ELF, but allow the individual load
> diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
> index cf93a4fad0..692e2a1fd2 100644
> --- a/fs/binfmt_elf_fdpic.c
> +++ b/fs/binfmt_elf_fdpic.c
> @@ -377,6 +377,11 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm)
>   				 executable_stack);
>   	if (retval < 0)
>   		goto error;
> +#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
> +	retval = arch_setup_additional_pages(bprm, !!interpreter_name);
> +	if (retval < 0)
> +		goto error;
> +#endif
>   #endif
>   
>   	/* load the executable and interpreter into memory */
> 

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

* [v2,7/8] binfmt_elf: don't attempt to load FDPIC binaries
  2017-08-17  7:23 ` [PATCH v2 7/8] binfmt_elf: don't attempt to load FDPIC binaries Nicolas Pitre
@ 2017-08-28 14:08   ` Vincent ABRIOU
  0 siblings, 0 replies; 26+ messages in thread
From: Vincent ABRIOU @ 2017-08-28 14:08 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Nicolas,

On 08/17/2017 09:23 AM, Nicolas Pitre wrote:
> On platforms where both ELF and ELF-FDPIC variants are available, the
> regular ELF loader will happily identify FDPIC binaries as proper ELF
> and load them without the necessary FDPIC fixups, resulting in an
> immediate user space crash. Let's prevent binflt_elf from loading those
> binaries so binfmt_elf_fdpic has a chance to pick them up. For those
> architectures that don't define elf_check_fdpic(), a default version
> returning false is provided.
> 
> Signed-off-by: Nicolas Pitre <nico@linaro.org>
Tested-by: Vincent Abriou <vincent.abriou@st.com>

BR
Vincent

> ---
>   fs/binfmt_elf.c | 15 +++++++++++++--
>   1 file changed, 13 insertions(+), 2 deletions(-)
> 
> diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
> index 879ff9c7ff..84d64afaea 100644
> --- a/fs/binfmt_elf.c
> +++ b/fs/binfmt_elf.c
> @@ -51,6 +51,11 @@
>   #define user_siginfo_t siginfo_t
>   #endif
>   
> +/* That's for binfmt_elf_fdpic to deal with */
> +#ifndef elf_check_fdpic
> +#define elf_check_fdpic(ex) false
> +#endif
> +
>   static int load_elf_binary(struct linux_binprm *bprm);
>   static unsigned long elf_map(struct file *, unsigned long, struct elf_phdr *,
>   				int, int, unsigned long);
> @@ -541,7 +546,8 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
>   	if (interp_elf_ex->e_type != ET_EXEC &&
>   	    interp_elf_ex->e_type != ET_DYN)
>   		goto out;
> -	if (!elf_check_arch(interp_elf_ex))
> +	if (!elf_check_arch(interp_elf_ex) ||
> +	    elf_check_fdpic(interp_elf_ex))
>   		goto out;
>   	if (!interpreter->f_op->mmap)
>   		goto out;
> @@ -718,6 +724,8 @@ static int load_elf_binary(struct linux_binprm *bprm)
>   		goto out;
>   	if (!elf_check_arch(&loc->elf_ex))
>   		goto out;
> +	if (elf_check_fdpic(&loc->elf_ex))
> +		goto out;
>   	if (!bprm->file->f_op->mmap)
>   		goto out;
>   
> @@ -817,7 +825,8 @@ static int load_elf_binary(struct linux_binprm *bprm)
>   		if (memcmp(loc->interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
>   			goto out_free_dentry;
>   		/* Verify the interpreter has a valid arch */
> -		if (!elf_check_arch(&loc->interp_elf_ex))
> +		if (!elf_check_arch(&loc->interp_elf_ex) ||
> +		    elf_check_fdpic(&loc->interp_elf_ex))
>   			goto out_free_dentry;
>   
>   		/* Load the interpreter program headers */
> @@ -1189,6 +1198,8 @@ static int load_elf_library(struct file *file)
>   	if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
>   	    !elf_check_arch(&elf_ex) || !file->f_op->mmap)
>   		goto out;
> +	if (elf_check_fdpic(&elf_ex))
> +		goto out;
>   
>   	/* Now read in all of the header information */
>   
> 

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

* [v2, 8/8] binfmt_elf_fdpic: fix crash on MMU system with dynamic binaries
  2017-08-17  7:23 ` [PATCH v2 8/8] binfmt_elf_fdpic: fix crash on MMU system with dynamic binaries Nicolas Pitre
@ 2017-08-28 14:08   ` Vincent ABRIOU
  2017-08-29  0:31     ` Nicolas Pitre
  0 siblings, 1 reply; 26+ messages in thread
From: Vincent ABRIOU @ 2017-08-28 14:08 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Nicolas,

On 08/17/2017 09:23 AM, Nicolas Pitre wrote:
> In elf_fdpic_map_file() there is a test to ensure the dynamic section in
> user space is properly terminated. However it does so by dereferencing
> a user address directly. Add proper user space accessor.
> 
> Signed-off-by: Nicolas Pitre <nico@linaro.org>
Tested-by: Vincent Abriou <vincent.abriou@st.com>

BR
Vincent

> ---
>   fs/binfmt_elf_fdpic.c | 8 ++++++--
>   1 file changed, 6 insertions(+), 2 deletions(-)
> 
> diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
> index 692e2a1fd2..6a56dea138 100644
> --- a/fs/binfmt_elf_fdpic.c
> +++ b/fs/binfmt_elf_fdpic.c
> @@ -835,6 +835,9 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
>   			if (phdr->p_vaddr >= seg->p_vaddr &&
>   			    phdr->p_vaddr + phdr->p_memsz <=
>   			    seg->p_vaddr + seg->p_memsz) {
> +				Elf32_Dyn __user *dyn;
> +				Elf32_Sword d_tag;
> +
>   				params->dynamic_addr =
>   					(phdr->p_vaddr - seg->p_vaddr) +
>   					seg->addr;
> @@ -847,8 +850,9 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
>   					goto dynamic_error;
>   
>   				tmp = phdr->p_memsz / sizeof(Elf32_Dyn);
> -				if (((Elf32_Dyn *)
> -				     params->dynamic_addr)[tmp - 1].d_tag != 0)
> +				dyn = (Elf32_Dyn __user *)params->dynamic_addr;
> +				__get_user(d_tag, &dyn[tmp - 1].d_tag);
> +				if (d_tag != 0)
>   					goto dynamic_error;
>   				break;
>   			}
> 
> 

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

* [v2, 8/8] binfmt_elf_fdpic: fix crash on MMU system with dynamic binaries
  2017-08-28 14:08   ` [v2, " Vincent ABRIOU
@ 2017-08-29  0:31     ` Nicolas Pitre
  0 siblings, 0 replies; 26+ messages in thread
From: Nicolas Pitre @ 2017-08-29  0:31 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, 28 Aug 2017, Vincent ABRIOU wrote:

> Hi Nicolas,
> 
> On 08/17/2017 09:23 AM, Nicolas Pitre wrote:
> > In elf_fdpic_map_file() there is a test to ensure the dynamic section in
> > user space is properly terminated. However it does so by dereferencing
> > a user address directly. Add proper user space accessor.
> > 
> > Signed-off-by: Nicolas Pitre <nico@linaro.org>
> Tested-by: Vincent Abriou <vincent.abriou@st.com>

Excellent, thank you!


Nicolas

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

end of thread, other threads:[~2017-08-29  0:31 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-17  7:23 [PATCH v2 0/8] ELF-FDPIC support for ARM Nicolas Pitre
2017-08-17  7:23 ` [PATCH v2 1/8] ARM: implement get_tls syscall Nicolas Pitre
2017-08-28 14:05   ` [v2,1/8] " Vincent ABRIOU
2017-08-17  7:23 ` [PATCH v2 2/8] arm_elf_read_implies_exec(): remove unused argument Nicolas Pitre
2017-08-28 14:06   ` [v2,2/8] " Vincent ABRIOU
2017-08-17  7:23 ` [PATCH v2 3/8] ARM: start_thread(): don't always clear all regs Nicolas Pitre
2017-08-28 14:07   ` [v2,3/8] " Vincent ABRIOU
2017-08-17  7:23 ` [PATCH v2 4/8] ARM: signal handling support for FDPIC_FUNCPTRS functions Nicolas Pitre
2017-08-28 14:07   ` [v2,4/8] " Vincent ABRIOU
2017-08-17  7:23 ` [PATCH v2 5/8] ARM: add ELF_FDPIC support Nicolas Pitre
2017-08-28 14:07   ` [v2,5/8] " Vincent ABRIOU
2017-08-17  7:23 ` [PATCH v2 6/8] ARM: enable elf_fdpic on systems with an MMU Nicolas Pitre
2017-08-28 14:07   ` [v2,6/8] " Vincent ABRIOU
2017-08-17  7:23 ` [PATCH v2 7/8] binfmt_elf: don't attempt to load FDPIC binaries Nicolas Pitre
2017-08-28 14:08   ` [v2,7/8] " Vincent ABRIOU
2017-08-17  7:23 ` [PATCH v2 8/8] binfmt_elf_fdpic: fix crash on MMU system with dynamic binaries Nicolas Pitre
2017-08-28 14:08   ` [v2, " Vincent ABRIOU
2017-08-29  0:31     ` Nicolas Pitre
2017-08-17  8:37 ` [PATCH v2 0/8] ELF-FDPIC support for ARM Russell King - ARM Linux
2017-08-23 16:41   ` Nicolas Pitre
2017-08-24  8:22     ` Vladimir Murzin
2017-08-24 12:37       ` Nicolas Pitre
2017-08-24 12:46         ` Mickael GUENE
2017-08-24 15:48           ` Nicolas Pitre
2017-08-25  6:23             ` Mickael GUENE
2017-08-25 14:27   ` Mickael GUENE

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.