On Wed, Jan 31, 2018 at 6:35 AM, Jeff Law <l...@redhat.com> wrote:
> Whee, fun, this appears to have been broken for a very long time,
> possibly since the introduction of -fstack-check in 2010.  Thankfully it
> only affects 32 bit and only in relatively constrained circumstances.
>
> -fstack-check and -fstack-clash both potentially create a loop for stack
> probing.  In that case they both need a scratch register to hold the
> loop upper bound.
>
> The code to allocate a scratch register first starts with the
> caller-saved registers as they're zero cost.  Then it'll use any callee
> saved register that is actually saved.  If neither is available (say
> because all the caller-saved regs are used for parameter passing and
> there are no callee saved register used), then the allocation routine
> will push %eax on the stack and the deallocation routine will pop it off
> to restore its value.
>
> Of course there is a *stack allocation* between those two points.  So
> the pop ends up restoring garbage into the register.
>
> Obviously the restore routine needs to use reg+d addressing to get to
> the stack slot and the allocated space needs to be deallocated by the
> epilogue.  But sadly there's enough assertions sprinkled around that
> prevent that from working as-is.
>
> So what this patch does is continue to use the push to allocate the
> register.  And it uses reg+d to restore the register after the probing
> loops.  The "trick" is that the space allocated by the push becomes part
> of the normal stack frame after we restore the scratch register's value.
>  Ie, if we push a 4 byte register, then we reduce the size of the main
> allocation request by 4 bytes.  And everything just works.
>
> Clearly this code had not be exercised.  So I hacked up things so that
> we always generated a probing loop and always assumed that we needed to
> save/restore a scratch register and enabled stack clash protections by
> default.  I bootstrapped that and compared testsuite runs against a run
> which just had stack clash protection on by default.  That did turn up
> an issue, but it was with my testing hacks, not with this patch :-)
>
>
> I (of course) also did the usual bootstrap and regression tests, using
> x86_64 and i686.  Hopefully this is the last iteration on the x86/x86_64
> stack clash bits :-)
>
> The one concern I have is do we need to tell the CFI machinery that
> %eax's value was restored to its entry value?

Can you or someone that knows CFI stuff please investigate this a bit?
I'm not expert in this area, and I don't feel comfortable to approve
the patch that has some known loose edges in the area I don't know
that well.

Uros.

Reply via email to