Messages in this thread | | | Date | Tue, 1 Mar 2022 19:06:21 -0800 | From | Peter Collingbourne <> | Subject | Re: [RFC][PATCH 6/6] objtool: Add IBT validation / fixups |
| |
Hi Peter,
One issue with this call sequence is that:
On Fri, Feb 11, 2022 at 02:38:03PM +0100, Peter Zijlstra wrote: > caller: > cmpl $0xdeadbeef, -0x4(%rax) # 7 bytes
Because this instruction ends in the constant 0xdeadbeef, it may be used as a "gadget" that would effectively allow branching to an arbitrary address in %rax if the attacker can arrange to set ZF=1.
> je 1f # 2 bytes > ud2 # 2 bytes > 1: call __x86_indirect_thunk_rax # 5 bytes > > > .align 16 > .byte 0xef, 0xbe, 0xad, 0xde # 4 bytes > func: > endbr # 4 bytes > ... > ret
I think we can avoid this problem with a slight tweak to your instruction sequence, at the cost of 2 bytes per function prologue. First, change the call sequence like so:
cmpl $0xdeadbeef, -0x6(%rax) # 6 bytes je 1f # 2 bytes ud2 # 2 bytes 1: call __x86_indirect_thunk_rax # 5 bytes
The key difference is that we've changed 0x4 to 0x6.
Then change the function prologue to this:
.align 16 .byte 0xef, 0xbe, 0xad, 0xde # 4 bytes .zero 2 # 2 bytes func:
The end result of the above is that the constant embedded in the cmpl instruction may only be used to reach the following ud2 instruction, which will "harmlessly" terminate execution in the same way as if the prologue signature did not match.
Peter
| |