diff mbox

[6/6] arm64: switch to relative exception tables

Message ID 1451837157-447-7-git-send-email-ard.biesheuvel@linaro.org
State New
Headers show

Commit Message

Ard Biesheuvel Jan. 3, 2016, 4:05 p.m. UTC
Instead of using absolute addresses for both the exception location
and the fixup, use offsets relative to the exception table entry values.
Not only does this cut the size of the exception table in half, it is
also a prerequisite for KASLR, since absolute exception table entries
are subject to dynamic relocation, which is incompatible with the sorting
of the exception table that occurs at build time.

Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

---

Note that this patch supersedes the version I sent as part of the series that
implements KASLR for arm64: http://thread.gmane.org/gmane.linux.kernel/2116531

 arch/arm64/include/asm/assembler.h   |  2 +-
 arch/arm64/include/asm/futex.h       |  4 ++--
 arch/arm64/include/asm/uaccess.h     | 18 ++++++++++--------
 arch/arm64/kernel/armv8_deprecated.c |  4 ++--
 arch/arm64/mm/extable.c              |  2 +-
 scripts/sortextable.c                |  2 +-
 6 files changed, 17 insertions(+), 15 deletions(-)

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Comments

Will Deacon Jan. 4, 2016, 2:46 p.m. UTC | #1
On Sun, Jan 03, 2016 at 05:05:57PM +0100, Ard Biesheuvel wrote:
> Instead of using absolute addresses for both the exception location

> and the fixup, use offsets relative to the exception table entry values.

> Not only does this cut the size of the exception table in half, it is

> also a prerequisite for KASLR, since absolute exception table entries

> are subject to dynamic relocation, which is incompatible with the sorting

> of the exception table that occurs at build time.

> 

> Cc: Catalin Marinas <catalin.marinas@arm.com>

> Cc: Will Deacon <will.deacon@arm.com>

> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>

> ---

> 

> Note that this patch supersedes the version I sent as part of the series that

> implements KASLR for arm64: http://thread.gmane.org/gmane.linux.kernel/2116531

> 

>  arch/arm64/include/asm/assembler.h   |  2 +-

>  arch/arm64/include/asm/futex.h       |  4 ++--

>  arch/arm64/include/asm/uaccess.h     | 18 ++++++++++--------

>  arch/arm64/kernel/armv8_deprecated.c |  4 ++--

>  arch/arm64/mm/extable.c              |  2 +-

>  scripts/sortextable.c                |  2 +-

>  6 files changed, 17 insertions(+), 15 deletions(-)


This looks good to me, so for the arm64 part (i.e. this patch):

  Acked-by: Will Deacon <will.deacon@arm.com>


Will

> diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h

> index 12eff928ef8b..8094d50f05bc 100644

> --- a/arch/arm64/include/asm/assembler.h

> +++ b/arch/arm64/include/asm/assembler.h

> @@ -98,7 +98,7 @@

>  9999:	x;					\

>  	.section __ex_table,"a";		\

>  	.align	3;				\

> -	.quad	9999b,l;			\

> +	.long	(9999b - .), (l - .);		\

>  	.previous

>  

>  /*

> diff --git a/arch/arm64/include/asm/futex.h b/arch/arm64/include/asm/futex.h

> index 007a69fc4f40..35e73e255ad3 100644

> --- a/arch/arm64/include/asm/futex.h

> +++ b/arch/arm64/include/asm/futex.h

> @@ -44,7 +44,7 @@

>  "	.popsection\n"							\

>  "	.pushsection __ex_table,\"a\"\n"				\

>  "	.align	3\n"							\

> -"	.quad	1b, 4b, 2b, 4b\n"					\

> +"	.long	(1b - .), (4b - .), (2b - .), (4b - .)\n"		\

>  "	.popsection\n"							\

>  	ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN,		\

>  		    CONFIG_ARM64_PAN)					\

> @@ -135,7 +135,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,

>  "	.popsection\n"

>  "	.pushsection __ex_table,\"a\"\n"

>  "	.align	3\n"

> -"	.quad	1b, 4b, 2b, 4b\n"

> +"	.long	(1b - .), (4b - .), (2b - .), (4b - .)\n"

>  "	.popsection\n"

>  	: "+r" (ret), "=&r" (val), "+Q" (*uaddr), "=&r" (tmp)

>  	: "r" (oldval), "r" (newval), "Ir" (-EFAULT)

> diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h

> index b2ede967fe7d..ab627e6c06c9 100644

> --- a/arch/arm64/include/asm/uaccess.h

> +++ b/arch/arm64/include/asm/uaccess.h

> @@ -36,11 +36,11 @@

>  #define VERIFY_WRITE 1

>  

>  /*

> - * The exception table consists of pairs of addresses: the first is the

> - * address of an instruction that is allowed to fault, and the second is

> - * the address at which the program should continue.  No registers are

> - * modified, so it is entirely up to the continuation code to figure out

> - * what to do.

> + * The exception table consists of pairs of relative offsets: the first

> + * is the relative offset to an instruction that is allowed to fault,

> + * and the second is the relative offset at which the program should

> + * continue. No registers are modified, so it is entirely up to the

> + * continuation code to figure out what to do.

>   *

>   * All the routines below use bits of fixup code that are out of line

>   * with the main instruction path.  This means when everything is well,

> @@ -50,9 +50,11 @@

>  

>  struct exception_table_entry

>  {

> -	unsigned long insn, fixup;

> +	int insn, fixup;

>  };

>  

> +#define ARCH_HAS_RELATIVE_EXTABLE

> +

>  extern int fixup_exception(struct pt_regs *regs);

>  

>  #define KERNEL_DS	(-1UL)

> @@ -125,7 +127,7 @@ static inline void set_fs(mm_segment_t fs)

>  	"	.previous\n"						\

>  	"	.section __ex_table,\"a\"\n"				\

>  	"	.align	3\n"						\

> -	"	.quad	1b, 3b\n"					\

> +	"	.long	(1b - .), (3b - .)\n"				\

>  	"	.previous"						\

>  	: "+r" (err), "=&r" (x)						\

>  	: "r" (addr), "i" (-EFAULT))

> @@ -192,7 +194,7 @@ do {									\

>  	"	.previous\n"						\

>  	"	.section __ex_table,\"a\"\n"				\

>  	"	.align	3\n"						\

> -	"	.quad	1b, 3b\n"					\

> +	"	.long	(1b - .), (3b - .)\n"				\

>  	"	.previous"						\

>  	: "+r" (err)							\

>  	: "r" (x), "r" (addr), "i" (-EFAULT))

> diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c

> index 937f5e58a4d3..8f21b1363387 100644

> --- a/arch/arm64/kernel/armv8_deprecated.c

> +++ b/arch/arm64/kernel/armv8_deprecated.c

> @@ -299,8 +299,8 @@ static void register_insn_emulation_sysctl(struct ctl_table *table)

>  	"	.popsection"					\

>  	"	.pushsection	 __ex_table,\"a\"\n"		\

>  	"	.align		3\n"				\

> -	"	.quad		0b, 4b\n"			\

> -	"	.quad		1b, 4b\n"			\

> +	"	.long		(0b - .), (4b - .)\n"		\

> +	"	.long		(1b - .), (4b - .)\n"		\

>  	"	.popsection\n"					\

>  	ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN,	\

>  		CONFIG_ARM64_PAN)				\

> diff --git a/arch/arm64/mm/extable.c b/arch/arm64/mm/extable.c

> index 79444279ba8c..81acd4706878 100644

> --- a/arch/arm64/mm/extable.c

> +++ b/arch/arm64/mm/extable.c

> @@ -11,7 +11,7 @@ int fixup_exception(struct pt_regs *regs)

>  

>  	fixup = search_exception_tables(instruction_pointer(regs));

>  	if (fixup)

> -		regs->pc = fixup->fixup;

> +		regs->pc = (unsigned long)&fixup->fixup + fixup->fixup;

>  

>  	return fixup != NULL;

>  }

> diff --git a/scripts/sortextable.c b/scripts/sortextable.c

> index c2423d913b46..af247c70fb66 100644

> --- a/scripts/sortextable.c

> +++ b/scripts/sortextable.c

> @@ -282,12 +282,12 @@ do_file(char const *const fname)

>  	case EM_386:

>  	case EM_X86_64:

>  	case EM_S390:

> +	case EM_AARCH64:

>  		custom_sort = sort_relative_table;

>  		break;

>  	case EM_ARCOMPACT:

>  	case EM_ARCV2:

>  	case EM_ARM:

> -	case EM_AARCH64:

>  	case EM_MICROBLAZE:

>  	case EM_MIPS:

>  	case EM_XTENSA:

> -- 

> 1.9.1

> 

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/
Ard Biesheuvel Jan. 4, 2016, 7:28 p.m. UTC | #2
On 4 January 2016 at 20:21, H. Peter Anvin <hpa@zytor.com> wrote:
> On 01/04/2016 10:20 AM, Luck, Tony wrote:

>>> May I humbly ask why the [Finnish] you don't use the equivalent of the

>>> x86 _ASM_EXTABLE() macro?  In fact, why don't we make that one generic, too?

>>

>> I'm messing with that right now (with help from Andy Lutomirski and Boris) to

>> add different classes of exception table (so I can tag some instructions as being

>> suitable for fixup from the machine check handler).  So it might not be generic

>> for much longer.

>>

>> http://marc.info/?l=linux-kernel&m=145187079504846&w=2

>>

>

> I suspect that means we will also need to go back to arch-specific

> sorting for x86.

>


AFAICT, Tony's patches are not incompatible with mine. The fixup
address is offset with a large constant, but this does not affect the
sort order (since that is based on the other member), and the swap
operation that adds/subtracts the delta should not care about the
class bits. (I don't see any changes to sort_extable() in Tony's
patch)

@Tony: any comments? And do you have any objections to the ia64 patch
in this series?

I agree that it makes sense to define a macro to emit the extable
entries in this patch, but I am not sure how that extrapolates to the
other architectures, and testing those is going to be cumbersome for
me, so I'd prefer to keep that a local change for arm64 for now.

Thanks,
Ard.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/
diff mbox

Patch

diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
index 12eff928ef8b..8094d50f05bc 100644
--- a/arch/arm64/include/asm/assembler.h
+++ b/arch/arm64/include/asm/assembler.h
@@ -98,7 +98,7 @@ 
 9999:	x;					\
 	.section __ex_table,"a";		\
 	.align	3;				\
-	.quad	9999b,l;			\
+	.long	(9999b - .), (l - .);		\
 	.previous
 
 /*
diff --git a/arch/arm64/include/asm/futex.h b/arch/arm64/include/asm/futex.h
index 007a69fc4f40..35e73e255ad3 100644
--- a/arch/arm64/include/asm/futex.h
+++ b/arch/arm64/include/asm/futex.h
@@ -44,7 +44,7 @@ 
 "	.popsection\n"							\
 "	.pushsection __ex_table,\"a\"\n"				\
 "	.align	3\n"							\
-"	.quad	1b, 4b, 2b, 4b\n"					\
+"	.long	(1b - .), (4b - .), (2b - .), (4b - .)\n"		\
 "	.popsection\n"							\
 	ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN,		\
 		    CONFIG_ARM64_PAN)					\
@@ -135,7 +135,7 @@  futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 "	.popsection\n"
 "	.pushsection __ex_table,\"a\"\n"
 "	.align	3\n"
-"	.quad	1b, 4b, 2b, 4b\n"
+"	.long	(1b - .), (4b - .), (2b - .), (4b - .)\n"
 "	.popsection\n"
 	: "+r" (ret), "=&r" (val), "+Q" (*uaddr), "=&r" (tmp)
 	: "r" (oldval), "r" (newval), "Ir" (-EFAULT)
diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
index b2ede967fe7d..ab627e6c06c9 100644
--- a/arch/arm64/include/asm/uaccess.h
+++ b/arch/arm64/include/asm/uaccess.h
@@ -36,11 +36,11 @@ 
 #define VERIFY_WRITE 1
 
 /*
- * The exception table consists of pairs of addresses: the first is the
- * address of an instruction that is allowed to fault, and the second is
- * the address at which the program should continue.  No registers are
- * modified, so it is entirely up to the continuation code to figure out
- * what to do.
+ * The exception table consists of pairs of relative offsets: the first
+ * is the relative offset to an instruction that is allowed to fault,
+ * and the second is the relative offset at which the program should
+ * continue. No registers are modified, so it is entirely up to the
+ * continuation code to figure out what to do.
  *
  * All the routines below use bits of fixup code that are out of line
  * with the main instruction path.  This means when everything is well,
@@ -50,9 +50,11 @@ 
 
 struct exception_table_entry
 {
-	unsigned long insn, fixup;
+	int insn, fixup;
 };
 
+#define ARCH_HAS_RELATIVE_EXTABLE
+
 extern int fixup_exception(struct pt_regs *regs);
 
 #define KERNEL_DS	(-1UL)
@@ -125,7 +127,7 @@  static inline void set_fs(mm_segment_t fs)
 	"	.previous\n"						\
 	"	.section __ex_table,\"a\"\n"				\
 	"	.align	3\n"						\
-	"	.quad	1b, 3b\n"					\
+	"	.long	(1b - .), (3b - .)\n"				\
 	"	.previous"						\
 	: "+r" (err), "=&r" (x)						\
 	: "r" (addr), "i" (-EFAULT))
@@ -192,7 +194,7 @@  do {									\
 	"	.previous\n"						\
 	"	.section __ex_table,\"a\"\n"				\
 	"	.align	3\n"						\
-	"	.quad	1b, 3b\n"					\
+	"	.long	(1b - .), (3b - .)\n"				\
 	"	.previous"						\
 	: "+r" (err)							\
 	: "r" (x), "r" (addr), "i" (-EFAULT))
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
index 937f5e58a4d3..8f21b1363387 100644
--- a/arch/arm64/kernel/armv8_deprecated.c
+++ b/arch/arm64/kernel/armv8_deprecated.c
@@ -299,8 +299,8 @@  static void register_insn_emulation_sysctl(struct ctl_table *table)
 	"	.popsection"					\
 	"	.pushsection	 __ex_table,\"a\"\n"		\
 	"	.align		3\n"				\
-	"	.quad		0b, 4b\n"			\
-	"	.quad		1b, 4b\n"			\
+	"	.long		(0b - .), (4b - .)\n"		\
+	"	.long		(1b - .), (4b - .)\n"		\
 	"	.popsection\n"					\
 	ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN,	\
 		CONFIG_ARM64_PAN)				\
diff --git a/arch/arm64/mm/extable.c b/arch/arm64/mm/extable.c
index 79444279ba8c..81acd4706878 100644
--- a/arch/arm64/mm/extable.c
+++ b/arch/arm64/mm/extable.c
@@ -11,7 +11,7 @@  int fixup_exception(struct pt_regs *regs)
 
 	fixup = search_exception_tables(instruction_pointer(regs));
 	if (fixup)
-		regs->pc = fixup->fixup;
+		regs->pc = (unsigned long)&fixup->fixup + fixup->fixup;
 
 	return fixup != NULL;
 }
diff --git a/scripts/sortextable.c b/scripts/sortextable.c
index c2423d913b46..af247c70fb66 100644
--- a/scripts/sortextable.c
+++ b/scripts/sortextable.c
@@ -282,12 +282,12 @@  do_file(char const *const fname)
 	case EM_386:
 	case EM_X86_64:
 	case EM_S390:
+	case EM_AARCH64:
 		custom_sort = sort_relative_table;
 		break;
 	case EM_ARCOMPACT:
 	case EM_ARCV2:
 	case EM_ARM:
-	case EM_AARCH64:
 	case EM_MICROBLAZE:
 	case EM_MIPS:
 	case EM_XTENSA: