> On Sep 11, 2020, at 11:14 AM, Segher Boessenkool <seg...@kernel.crashing.org>
> wrote:
>
> On Fri, Sep 11, 2020 at 11:06:03AM +0100, Richard Sandiford wrote:
>> This might have already been discussed/answered, sorry, but:
>> when there's a choice, is there an obvious winner between:
>>
>> (1) clearing call-clobbered registers and then restoring call-preserved ones
>> (2) restoring call-preserved registers and then clearing call-clobbered ones
>>
>> Is one option more likely to be useful to attackers than the other?
for mitigating ROP purpose, I think that (2) is better than (1). i.e, the
clearing
call-clobbered register sequence will be immediately before “ret” instruction.
This will prevent the gadget from doing any useful things.
>>
>> (For some frames, it might be necessary to use a small number of
>> call-clobbered registers to perform the restore sequence, so (1)
>> wouldn't be fully achievable in all cases.)
>
Yes, looks like that (1) is also not correct.
> The same is true for what you have to do *after* restoring registers, as
> I said before. Clearing all is not correct in all cases, and also it is
> not useful in all cases (code right after it might write the registers
> again.
I don’t understand why it’s not correct if we clearing call-clobbered registers
AFTER restoring call-preserved registers?
Even though we might need to use some call-clobbered registers to restore
the call-preserved registers, after the restoring is done, we can use data flow
to make sure the call-clobbered registers not lived at that point anymore, then
Clearing those not-lived call-clobbered registers immediately before “ret”.
For me, this should be correct.
Let me know anything I am missing here.
Thanks.
Qing
>
> This really is very (sub-)target-specific, it cannot be done by generic
> code on its own *at all*.
>
>
> Segher