This adds xor cookies to the arm setjmp family.
To make the register jockeying easier, it rearranges the order of the
registers in the jmpbuf, moving up the (cookied) sp and lr registers to
before r4-r11, and then completely leaving out r12, as it's not
callee-saved in the ABI. Thus the first file in the diff here,
<arm/setjmp.h>, showing the new layout.
This is an ABI break for anything that pokes into jmpbuf; does it need to
ride on a libc major bump?
Philip
Index: sys/arch/arm/include/setjmp.h
===================================================================
RCS file: /cvs/src/sys/arch/arm/include/setjmp.h,v
retrieving revision 1.3
diff -u -p -w -r1.3 setjmp.h
--- sys/arch/arm/include/setjmp.h 9 Feb 2013 20:52:12 -0000 1.3
+++ sys/arch/arm/include/setjmp.h 6 Aug 2016 19:22:09 -0000
@@ -8,11 +8,6 @@
#define _JBLEN 64 /* size, in longs, of a jmp_buf */
/*
- * NOTE: The internal structure of a jmp_buf is *PRIVATE*
- * This information is provided as there is software
- * that fiddles with this with obtain the stack pointer
- * (yes really ! and it's commercial !).
- *
* Description of the setjmp buffer
*
* word 0 magic number (dependant on creator)
@@ -21,17 +16,17 @@
* 7 - 9 f6 fp register 6
* 10 - 12 f7 fp register 7
* 13 fpsr fp status register
- * 14 r4 register 4
- * 15 r5 register 5
- * 16 r6 register 6
- * 17 r7 register 7
- * 18 r8 register 8
- * 19 r9 register 9
- * 20 r10 register 10 (sl)
- * 21 r11 register 11 (fp)
- * 22 r12 register 12 (ip)
- * 23 r13 register 13 (sp)
- * 24 r14 register 14 (lr)
+ * 14 r13 register 13 (sp) XOR cookie0
+ * 15 r14 register 14 (lr) XOR cookie1
+ * 16 r4 register 4
+ * 17 r5 register 5
+ * 18 r6 register 6
+ * 19 r7 register 7
+ * 20 r8 register 8
+ * 21 r9 register 9
+ * 22 r10 register 10 (sl)
+ * 23 r11 register 11 (fp)
+ * 24 unused unused
* 25 signal mask (dependant on magic)
* 26 (con't)
* 27 (con't)
@@ -66,17 +61,14 @@
#define _JB_REG_F6 7
#define _JB_REG_F7 10
#define _JB_REG_FPSR 13
-#define _JB_REG_R4 14
-#define _JB_REG_R5 15
-#define _JB_REG_R6 16
-#define _JB_REG_R7 17
-#define _JB_REG_R8 18
-#define _JB_REG_R9 19
-#define _JB_REG_R10 20
-#define _JB_REG_R11 21
-#define _JB_REG_R12 22
-#define _JB_REG_R13 23
-#define _JB_REG_R14 24
+#define _JB_REG_R4 16
+#define _JB_REG_R5 17
+#define _JB_REG_R6 18
+#define _JB_REG_R7 19
+#define _JB_REG_R8 20
+#define _JB_REG_R9 21
+#define _JB_REG_R10 22
+#define _JB_REG_R11 23
/* Only valid with the _JB_MAGIC_SETJMP magic */
Index: lib/libc/arch/arm/gen/_setjmp.S
===================================================================
RCS file: /cvs/src/lib/libc/arch/arm/gen/_setjmp.S,v
retrieving revision 1.4
diff -u -p -w -r1.4 _setjmp.S
--- lib/libc/arch/arm/gen/_setjmp.S 6 Aug 2016 19:16:09 -0000 1.4
+++ lib/libc/arch/arm/gen/_setjmp.S 6 Aug 2016 19:22:09 -0000
@@ -36,6 +36,15 @@
#include "DEFS.h"
#include <machine/setjmp.h>
+ .section .openbsd.randomdata,"aw",%progbits
+ .align 4
+ .globl __jmpxor
+__jmpxor:
+ .zero 4*2 /* (sp, lr) */
+ END(__jmpxor)
+ .type __jmpxor,%object
+
+
/*
* C library -- _setjmp, _longjmp
*
@@ -52,6 +61,13 @@
ENTRY(_setjmp)
ldr r1, .L_setjmp_magic
str r1, [r0], #4
+ ldr r2, .L_jmpxor_setjmp
+1: add r2, pc, r2 /* r2 = &__jmpxor */
+ ldr r3, [r2], #4 /* r3 = __jmpxor[1] */
+ ldr r2, [r2] /* r2 = __jmpxor[0] */
+ eor r2, r13, r2 /* r2 = sp ^ __jmpxor[0] */
+ eor r3, lr, r3 /* r3 = lr ^ __jmpxor[1] */
+
#ifdef SOFTFLOAT
add r0, r0, #52
#else
@@ -62,13 +78,17 @@ ENTRY(_setjmp)
str r1, [r0], #0x0004
#endif /* SOFTFLOAT */
/* Store integer registers */
- stmia r0, {r4-r14}
+ stmia r0, {r2-r11}
mov r0, #0x00000000
- mov r15, r14
+ mov r2, r0 /* overwrite __jmpxor copies */
+ mov r3, r0
+ mov pc, lr
.L_setjmp_magic:
.word _JB_MAGIC__SETJMP
+.L_jmpxor_setjmp:
+ .word __jmpxor - 1b
END_STRONG(_setjmp)
ENTRY(_longjmp)
@@ -87,18 +107,30 @@ ENTRY(_longjmp)
wfs r4
#endif /* SOFTFLOAT */
/* Restore integer registers */
- ldmia r0, {r4-r14}
+ ldmia r0, {r2-r11}
- /* Validate sp and r14 */
+ ldr r0, .L_jmpxor_longjmp
+1: add r0, pc, r0 /* r0 = &__jmpxor */
+ ldr lr, [r0], #4 /* lr = __jmpxor[1] */
+ eor lr, r3, lr /* lr ^= jmpbuf[LR] */
+ ldr r0, [r0] /* r0 = __jmpxor[0] */
+ eor r13, r0, r2 /* sp = __jmpxor[0] ^ jmpbuf[SP] */
+ mov r2, r1 /* overwrite __jmpxor copies */
+ mov r3, r1
+
+ /* Validate sp and lr */
teq sp, #0
- teqne r14, #0
+ teqne lr, #0
beq botch
/* Set return value */
mov r0, r1
teq r0, #0x00000000
moveq r0, #0x00000001
- mov r15, r14
+ mov pc, lr
+
+.L_jmpxor_longjmp:
+ .word __jmpxor - 1b
/* validation failed, die die die. */
botch:
Index: lib/libc/arch/arm/gen/setjmp.S
===================================================================
RCS file: /cvs/src/lib/libc/arch/arm/gen/setjmp.S,v
retrieving revision 1.5
diff -u -p -w -r1.5 setjmp.S
--- lib/libc/arch/arm/gen/setjmp.S 6 Aug 2016 19:16:09 -0000 1.5
+++ lib/libc/arch/arm/gen/setjmp.S 6 Aug 2016 19:22:09 -0000
@@ -33,9 +33,11 @@
* SUCH DAMAGE.
*/
-#include "DEFS.h"
+#include "SYS.h"
#include <machine/setjmp.h>
+ .hidden __jmpxor
+
/*
* C library -- setjmp, longjmp
*
@@ -48,36 +50,45 @@
ENTRY(setjmp)
/* Block all signals and retrieve the old signal mask */
- stmfd sp!, {r0, r14}
- mov r0, #0x00000000
-
- bl _HIDDEN(sigblock)
- mov r1, r0
-
- ldmfd sp!, {r0, r14}
+ mov r2, r0
+ mov r1, #0x00000000
+ mov r0, #0x00000001 /* SIG_BLOCK */
+ SYSTRAP(sigprocmask)
/* Store signal mask */
- str r1, [r0, #(25 * 4)]
+ str r0, [r2, #(25 * 4)]
ldr r1, .Lsetjmp_magic
- str r1, [r0], #4
+ str r1, [r2], #4
+
+ ldr r12, .L_jmpxor_setjmp
+1: add r12, pc, r12 /* r12 = &__jmpxor */
+ ldr r3, [r12], #4 /* r3 = __jmpxor[1] */
+ ldr r12, [r12] /* r12 = __jmpxor[0] */
+ eor r12, r13, r12 /* r12 = sp ^ __jmpxor[0] */
+ eor r3, lr, r3 /* r3 = lr ^ __jmpxor[1] */
#ifdef SOFTFLOAT
- add r0, r0, #52
+ add r2, r2, #52
#else
/* Store fp registers */
- sfm f4, 4, [r0], #48
+ sfm f4, 4, [r2], #48
/* Store fpsr */
rfs r1
- str r1, [r0], #0x0004
+ str r1, [r2], #0x0004
#endif /*SOFTFLOAT*/
/* Store integer registers */
- stmia r0, {r4-r14}
+ stmia r2, {r3-r12}
+
mov r0, #0x00000000
- mov r15, r14
+ mov r12, r0 /* overwrite __jmpxor copies */
+ mov r3, r0
+ mov pc, lr
.Lsetjmp_magic:
.word _JB_MAGIC_SETJMP
+.L_jmpxor_setjmp:
+ .word __jmpxor - 1b
END_STRONG(setjmp)
@@ -87,47 +98,48 @@ ENTRY(longjmp)
teq r2, r3
bne botch
- /* Fetch signal mask */
- ldr r2, [r0, #(25 * 4)]
-
- /* Set signal mask */
- stmfd sp!, {r0, r1, r14}
- sub sp, sp, #4 /* align the stack */
+ /* Fetch signal mask and call sigprocmask */
+ mov r3, r0 /* r3 = jmpbuf */
+ mov r2, r1 /* r2 = retvalue */
+ ldr r1, [r0, #(25 * 4)]
+ mov r0, #0x00000003 /* SIG_SETMASK */
+ SYSTRAP(sigprocmask)
- mov r0, r2
- bl _HIDDEN(sigsetmask)
-
- add sp, sp, #4 /* unalign the stack */
- ldmfd sp!, {r0, r1, r14}
-
- add r0, r0, #4
+ add r3, r3, #4
#ifdef SOFTFLOAT
- add r0, r0, #52
+ add r3, r3, #52
#else
/* Restore fp registers */
- lfm f4, 4, [r0], #48
+ lfm f4, 4, [r3], #48
/* Restore FPSR */
- ldr r4, [r0], #0x0004
+ ldr r4, [r3], #0x0004
wfs r4
#endif /* SOFTFLOAT */
/* Restore integer registers */
- ldmia r0, {r4-r14}
+ ldmia r3, {r3-r12}
+
+ ldr r0, .L_jmpxor_longjmp
+1: add r0, pc, r0 /* r0 = &__jmpxor */
+ ldr lr, [r0], #4 /* lr = __jmpxor[1] */
+ eor lr, r3, lr /* lr ^= jmpbuf[LR] */
+ ldr r0, [r0] /* r0 = __jmpxor[0] */
+ eor r13, r0, r12 /* sp = __jmpxor[0] ^ jmpbuf[SP] */
+ mov r12, r2 /* overwrite __jmpxor copies */
+ mov r3, r2
- /* Validate sp and r14 */
+ /* Validate sp and lr */
teq sp, #0
- teqne r14, #0
+ teqne lr, #0
beq botch
/* Set return value */
-
- mov r0, r1
+ mov r0, r12
teq r0, #0x00000000
moveq r0, #0x00000001
-#ifdef __ARM_26__
- mov r15, r14
-#else
- mov r15, r14
-#endif
+ mov pc, lr
+
+.L_jmpxor_longjmp:
+ .word __jmpxor - 1b
/* validation failed, die die die. */
botch: