diff mbox series

powerpc64le: ROP changes for _init/_fini

Message ID 20241007145314.3938424-1-smonga@linux.ibm.com
State New
Headers show
Series powerpc64le: ROP changes for _init/_fini | expand

Commit Message

Sachin Monga Oct. 7, 2024, 2:53 p.m. UTC
Disable -mrop-protect for power7 files
Macro FRAME_ROP_SAVE defined for storing ROP pointer
Store/Retrieve ROP pointer next to FRAME_MIN_SIZE_PARM

Signed-off-by: Sachin Monga <smonga@linux.ibm.com>
---
 sysdeps/powerpc/powerpc64/crti.S             | 10 ++++++++++
 sysdeps/powerpc/powerpc64/crtn.S             | 14 ++++++++++++++
 sysdeps/powerpc/powerpc64/multiarch/Makefile |  2 ++
 sysdeps/powerpc/powerpc64/sysdep.h           |  1 +
 4 files changed, 27 insertions(+)

Comments

Andreas Schwab Oct. 7, 2024, 3:55 p.m. UTC | #1
On Okt 07 2024, Sachin Monga wrote:

> diff --git a/sysdeps/powerpc/powerpc64/multiarch/Makefile b/sysdeps/powerpc/powerpc64/multiarch/Makefile
> index b847c19049..769625b70d 100644
> --- a/sysdeps/powerpc/powerpc64/multiarch/Makefile
> +++ b/sysdeps/powerpc/powerpc64/multiarch/Makefile
> @@ -38,7 +38,9 @@ sysdep_routines += memchr-power10 memcmp-power10 memcpy-power10 \
>  		   strlen-power9 strncpy-power9 stpncpy-power9 strlen-power10
>  endif
>  CFLAGS-strncase-power7.c += -mcpu=power7 -funroll-loops
> +CFLAGS-strncase-power7.c := $(filter-out -mrop-protect, $(strncase-power7-CFLAGS))

Where is strncase-power7-CFLAGS coming from?
Sachin Monga Oct. 8, 2024, 7:09 a.m. UTC | #2
-mrop-protect is gcc flag for ROP enablement from "configure" command.
However, power7 files must not use this flag.

On 07/10/24 9:25 pm, Andreas Schwab wrote:
> On Okt 07 2024, Sachin Monga wrote:
>
>> diff --git a/sysdeps/powerpc/powerpc64/multiarch/Makefile b/sysdeps/powerpc/powerpc64/multiarch/Makefile
>> index b847c19049..769625b70d 100644
>> --- a/sysdeps/powerpc/powerpc64/multiarch/Makefile
>> +++ b/sysdeps/powerpc/powerpc64/multiarch/Makefile
>> @@ -38,7 +38,9 @@ sysdep_routines += memchr-power10 memcmp-power10 memcpy-power10 \
>>   		   strlen-power9 strncpy-power9 stpncpy-power9 strlen-power10
>>   endif
>>   CFLAGS-strncase-power7.c += -mcpu=power7 -funroll-loops
>> +CFLAGS-strncase-power7.c := $(filter-out -mrop-protect, $(strncase-power7-CFLAGS))
> Where is strncase-power7-CFLAGS coming from?
>
Adhemerval Zanella Netto Oct. 8, 2024, 12:15 p.m. UTC | #3
On 08/10/24 04:09, Sachin Monga wrote:
> -mrop-protect is gcc flag for ROP enablement from "configure" command.
> However, power7 files must not use this flag.
> 
> On 07/10/24 9:25 pm, Andreas Schwab wrote:
>> On Okt 07 2024, Sachin Monga wrote:
>>
>>> diff --git a/sysdeps/powerpc/powerpc64/multiarch/Makefile b/sysdeps/powerpc/powerpc64/multiarch/Makefile
>>> index b847c19049..769625b70d 100644
>>> --- a/sysdeps/powerpc/powerpc64/multiarch/Makefile
>>> +++ b/sysdeps/powerpc/powerpc64/multiarch/Makefile
>>> @@ -38,7 +38,9 @@ sysdep_routines += memchr-power10 memcmp-power10 memcpy-power10 \
>>>              strlen-power9 strncpy-power9 stpncpy-power9 strlen-power10
>>>   endif
>>>   CFLAGS-strncase-power7.c += -mcpu=power7 -funroll-loops
>>> +CFLAGS-strncase-power7.c := $(filter-out -mrop-protect, $(strncase-power7-CFLAGS))
>> Where is strncase-power7-CFLAGS coming from?
>>

I would be interesting to explain a bit on commit message what ROP aim
to do on, and when it was added on POWER ISA so the reviewed can have
some context here.
Paul E. Murphy Oct. 8, 2024, 3:14 p.m. UTC | #4
On 10/7/24 9:53 AM, Sachin Monga wrote:
> Disable -mrop-protect for power7 files
> Macro FRAME_ROP_SAVE defined for storing ROP pointer
> Store/Retrieve ROP pointer next to FRAME_MIN_SIZE_PARM
>
>   
>   # Called during static initialization
> diff --git a/sysdeps/powerpc/powerpc64/sysdep.h b/sysdeps/powerpc/powerpc64/sysdep.h
> index c439b06121..52253a6a0f 100644
> --- a/sysdeps/powerpc/powerpc64/sysdep.h
> +++ b/sysdeps/powerpc/powerpc64/sysdep.h
> @@ -24,6 +24,7 @@
>   /* Stack frame offsets.  */
>   #define FRAME_BACKCHAIN		0
>   #define FRAME_CR_SAVE		8
> +#define FRAME_ROP_SAVE		8 /* Generally to be stored in red zone */

If I read the patch correctly, it is stored in the redzone, and then a 
frame stacked around it.

Shouldn't the offset be written -8?

>   #define FRAME_LR_SAVE		16
>   #if _CALL_ELF != 2
>   #define FRAME_MIN_SIZE		112

Likewise, the frame size should always be 16B aligned. I think you need 
to update FRAME_MIN_SIZE when ROP is enabled to account for the 
additional save slot and alignment requirement. Alternatively, 
FRAME_ROP_SAVE could be split into FRAME_ROP_SIZE and FRAME_ROP_SAVE to 
signify the difference.
Andreas Schwab Oct. 8, 2024, 3:21 p.m. UTC | #5
On Okt 08 2024, Sachin Monga wrote:

> -mrop-protect is gcc flag for ROP enablement from "configure" command.
> However, power7 files must not use this flag.

That doesn't answer my question.
Sachin Monga Oct. 8, 2024, 6:31 p.m. UTC | #6
Sorry Andreas

Its was a typo from my side . It should be */CFLAGS-strncase-power7/ 
*actually*. *Will change it.

Could'nt catch since it didn't give any error while compilation and 
filtered my flag also.


On 08/10/24 8:51 pm, Andreas Schwab wrote:
> On Okt 08 2024, Sachin Monga wrote:
>
>> -mrop-protect is gcc flag for ROP enablement from "configure" command.
>> However, power7 files must not use this flag.
> That doesn't answer my question.
>
Paul E. Murphy Oct. 9, 2024, 12:07 a.m. UTC | #7
On 10/8/24 10:14 AM, Paul E. Murphy wrote:
>
> On 10/7/24 9:53 AM, Sachin Monga wrote:
>
>>   #define FRAME_LR_SAVE        16
>>   #if _CALL_ELF != 2
>>   #define FRAME_MIN_SIZE        112
>
> Likewise, the frame size should always be 16B aligned. I think you 
> need to update FRAME_MIN_SIZE when ROP is enabled to account for the 
> additional save slot and alignment requirement. Alternatively, 
> FRAME_ROP_SAVE could be split into FRAME_ROP_SIZE and FRAME_ROP_SAVE 
> to signify the difference.
>
Actually, don't change the minimum frame size if the hash must be stored 
relative to the old stack pointer.  Some assembly uses it as an offset 
to the parameter save space.

However, is it critical to store the hash before pushing the new frame?  
If not, you can store the hash alongside the other slots required for a 
minimal stack frame.
Peter Bergner Oct. 9, 2024, 3:13 a.m. UTC | #8
On 10/8/24 7:07 PM, Paul E. Murphy wrote:
> However, is it critical to store the hash before pushing the new frame?
> If not, you can store the hash alongside the other slots required for
> a minimal stack frame.

There is nothing that mandates we store the hash before creating the callee's
frame.  That said, the hashst and hashchk instructions are defined as:

    hashst  RB,offset(RA)
    hashchk RB,offset(RA)

...and implemented as X-form instructions, similar to ldx, etc.  Those types
of instructions have a 6-bit major opcode and a 10-bit secondary opcode,
3 5-bit register operands and a 1-bit RC operand.  The bits for the offset
operand is the concatenation of one of the 5-bit register fields and the
1-bit RC field, giving us a 6-bit offset field.  That field is used to encode
64 8-byte aligned offsets between the range -8 and -512.  This limitation
restricts us to using the caller's stack pointer value plus the negative
offset so we store below the caller's stack frame into was is or will
become the callee's stack frame.

If we emit the hashst before creating the callee's stack frame, then we
can use the caller's r1 as is.  If we emit the hashst after creating the
callee's stack frame, then we have to create a copy of the caller's r1
value before creating the new stack frame and then use that copy as the
base register.  It's just easier to use the caller's r1 and store the
hash in the red-zone below the caller's frame.

I'll note that the 32-bit ppc ABI does not have a red-zone, so if we ever
implement ROP protection for it, we'll have to use the method of creating
a copy of the caller's r1, create the callee's frame and then store the
hash using the copy of the caller's r1.  I'm unsure if we'll ever do that
though.

Peter
Peter Bergner Oct. 9, 2024, 3:24 a.m. UTC | #9
On 10/8/24 7:15 AM, Adhemerval Zanella Netto wrote:
> I would be interesting to explain a bit on commit message what ROP aim
> to do on, and when it was added on POWER ISA so the reviewed can have
> some context here.  

The ROP instructions were added in ISA 3.1 (ie, Power10), however they
were defined so that if executed on older cpus, they would behave as
nops.  This allows us to emit them on older cpus and they'd just be
ignored, but if run on a Power10, then the binary would be ROP protected.
Currently, the binutils assembler accepts hashst and hashchk back to
Power8, so that is what we are targeting for protecting in glibc.

Peter
diff mbox series

Patch

diff --git a/sysdeps/powerpc/powerpc64/crti.S b/sysdeps/powerpc/powerpc64/crti.S
index 71bdddfb3b..4f009158c7 100644
--- a/sysdeps/powerpc/powerpc64/crti.S
+++ b/sysdeps/powerpc/powerpc64/crti.S
@@ -68,7 +68,12 @@  BODY_LABEL (_init):
 	LOCALENTRY(_init)
 	mflr 0
 	std 0, FRAME_LR_SAVE(r1)
+#ifdef __ROP_PROTECT__
+	hashst 0, -FRAME_ROP_SAVE(r1)
+	stdu r1, -FRAME_MIN_SIZE_PARM-FRAME_ROP_SAVE(r1)
+#else
 	stdu r1, -FRAME_MIN_SIZE_PARM(r1)
+#endif
 #if PREINIT_FUNCTION_WEAK
 	addis r9, r2, .LC0@toc@ha
 	ld r0, .LC0@toc@l(r9)
@@ -87,4 +92,9 @@  BODY_LABEL (_fini):
 	LOCALENTRY(_fini)
 	mflr 0
 	std 0, FRAME_LR_SAVE(r1)
+#ifdef __ROP_PROTECT__
+	hashst 0, -FRAME_ROP_SAVE(r1)
+	stdu r1, -FRAME_MIN_SIZE_PARM-FRAME_ROP_SAVE(r1)
+#else
 	stdu r1, -FRAME_MIN_SIZE_PARM(r1)
+#endif
diff --git a/sysdeps/powerpc/powerpc64/crtn.S b/sysdeps/powerpc/powerpc64/crtn.S
index 4e91231f2c..45359dbe32 100644
--- a/sysdeps/powerpc/powerpc64/crtn.S
+++ b/sysdeps/powerpc/powerpc64/crtn.S
@@ -39,13 +39,27 @@ 
 #include <sysdep.h>
 
 	.section .init,"ax",@progbits
+#ifdef __ROP_PROTECT__
+	addi r1, r1, FRAME_MIN_SIZE_PARM+FRAME_ROP_SAVE
+#else
 	addi r1, r1, FRAME_MIN_SIZE_PARM
+#endif
 	ld r0, FRAME_LR_SAVE(r1)
 	mtlr r0
+#ifdef __ROP_PROTECT__
+	hashchk 0, -FRAME_ROP_SAVE(r1)
+#endif
 	blr
 
 	.section .fini,"ax",@progbits
+#ifdef __ROP_PROTECT__
+	addi r1, r1, FRAME_MIN_SIZE_PARM+FRAME_ROP_SAVE
+#else
 	addi r1, r1, FRAME_MIN_SIZE_PARM
+#endif
 	ld r0, FRAME_LR_SAVE(r1)
 	mtlr r0
+#ifdef __ROP_PROTECT__
+	hashchk 0, -FRAME_ROP_SAVE(r1)
+#endif
 	blr
diff --git a/sysdeps/powerpc/powerpc64/multiarch/Makefile b/sysdeps/powerpc/powerpc64/multiarch/Makefile
index b847c19049..769625b70d 100644
--- a/sysdeps/powerpc/powerpc64/multiarch/Makefile
+++ b/sysdeps/powerpc/powerpc64/multiarch/Makefile
@@ -38,7 +38,9 @@  sysdep_routines += memchr-power10 memcmp-power10 memcpy-power10 \
 		   strlen-power9 strncpy-power9 stpncpy-power9 strlen-power10
 endif
 CFLAGS-strncase-power7.c += -mcpu=power7 -funroll-loops
+CFLAGS-strncase-power7.c := $(filter-out -mrop-protect, $(strncase-power7-CFLAGS))
 CFLAGS-strncase_l-power7.c += -mcpu=power7 -funroll-loops
+CFLAGS-strncase_l-power7.c := $(filter-out -mrop-protect, $(strncase-power7_l-CFLAGS))
 endif
 
 # Called during static initialization
diff --git a/sysdeps/powerpc/powerpc64/sysdep.h b/sysdeps/powerpc/powerpc64/sysdep.h
index c439b06121..52253a6a0f 100644
--- a/sysdeps/powerpc/powerpc64/sysdep.h
+++ b/sysdeps/powerpc/powerpc64/sysdep.h
@@ -24,6 +24,7 @@ 
 /* Stack frame offsets.  */
 #define FRAME_BACKCHAIN		0
 #define FRAME_CR_SAVE		8
+#define FRAME_ROP_SAVE		8 /* Generally to be stored in red zone */
 #define FRAME_LR_SAVE		16
 #if _CALL_ELF != 2
 #define FRAME_MIN_SIZE		112