Live data from Hacker News

Please restore our registers when you’re done with them

randomascii.wordpress.com

71–80 of 142 posts

Re: Please restore our registers when you’re done with them

#71
post #35

I used to take point for Mozilla's efforts dealing with third-party interference in our binaries. Browsers are ripe targets for this kind of shit. The stories we could tell...

And from our perspective you should! Would be interesting.

Re: Please restore our registers when you’re done with them

#72
post #63
post #3

It’s interesting that there is a zero stored in a register and used for hours - is that significantly faster than just using some actual zero each time? Perhaps CPUs need a “always zero” register or some similar menomic to help harden.

Where it's not optimized away, getting "an actual zero" requires a memory operation of some kind. Register ops are faster in that they are right there, no fetch needed.

Depends on the instruction architecture. 68000 had some ways of burying a small literal operand in the instruction. If I recall correctly, MOVEQ.L would let you move zero to a register without touching memory (other than the instruction fetch), and it wasn't a long instruction.

Re: Please restore our registers when you’re done with them

#73
post #6
post #4

Earlier quoted context omitted.

Many architectures do have a 0 register because the value is useful. Others have a zero instruction (or both). What would an "actual zero" be -- a literal?

Yeah, something like "mov ax, 0h" but I suppose that is way more memory intensive as you have to load a 0 into memory somewhere and then copy it into the register. It strikes me as somehow the compiler is making assumptions that aren't being enforced by the ... OS? Language? not sure what, but it's assuming functions restore registers used but that isn't enforced by anything. From my (long ago) time there was PUSHA a…

Why would you have to load 0 into memory somewhere (other than in the instruction itself)? Or did you mean that it is in fact in the instruction?

Re: Please restore our registers when you’re done with them

#74

In this particular example, why not just PXOR XMM7 XMM7 before using XMM7 to zero anything? That way the compiler doesn't have to assume that XMM7 is zero, it can know . Yes it's an extra instruction but XORing a register with itself is such a common metaphor for zeroing that register that CPU designers try to make it fast. Edit: Just noticed that Veliladon essentially made the same comment herein and explained the r…

It's not just that. If you can't trust the ABI then everything else is wrong too. Everything. Not just zeroing registers. It only just so happens that in this case XMM7 is used for zeroing, but it could be used to save a variable across a function call. Then there is no trick to get it set back to the right value.

The ABI is not optional, or best effort, or best practice, or any other BS that passes in the ordinary world. It is just as required as the correct operation of instructions (e.g., add should actually add things, mul should actually multiply them, and so on).

Re: Please restore our registers when you’re done with them

#75

In this particular example, why not just PXOR XMM7 XMM7 before using XMM7 to zero anything? That way the compiler doesn't have to assume that XMM7 is zero, it can know . Yes it's an extra instruction but XORing a register with itself is such a common metaphor for zeroing that register that CPU designers try to make it fast. Edit: Just noticed that Veliladon essentially made the same comment herein and explained the r…

My reading of it was that the bug was caused by XMM7 not being restored to its previous value.

E.g. on Linux, functions should restore the values of ebx, esi, edi, ... once they're done with them. The article says (on Windows) that XMM7 needs to be restored too.

If you can't trust one register being preserved (per the ABI), then you really can't trust the values of any registers.

Re: Please restore our registers when you’re done with them

#76

Earlier quoted context omitted.

The webrtc fix was thematically similar in that the programmer declared what registers were trashed and then the compiler knows which registers need to be saved. I'm not sure why the compiler doesn't notice when registers are used without being declared as being trashed - I'm really not an expert at _writing_ assembly language.

It's literally undecidable in principle whether some assembler correctly restores some register R. That's a non-trivial semantic property, Rice's theorem applies. So the compiler's only practical option if it worked this way would be a conservative option - any time it's unclear whether register R is clobbered, treat it as clobbered. As a trivial example of why a register might not be clobbered even though my code to…

[deleted]

Re: Please restore our registers when you’re done with them

#77
post #15

Sounds like there should be an option when you write assembly code to tell the compiler "please save/restore any register that I'm modifying in this asm code according to the target you are compiling for"

You could totally design a better convention in your own high-level language which compiled down to assembly, as long as you stayed inside it. But once you need to interface with external code you need to use a shared convention.

Your scheme sounds like it would make your code well-behaved as the callee (with perhaps some performance penalty?). But as a caller, you couldn't trust the external code not to clobber registers.

Re: Please restore our registers when you’re done with them

#78
post #75

In this particular example, why not just PXOR XMM7 XMM7 before using XMM7 to zero anything? That way the compiler doesn't have to assume that XMM7 is zero, it can know . Yes it's an extra instruction but XORing a register with itself is such a common metaphor for zeroing that register that CPU designers try to make it fast. Edit: Just noticed that Veliladon essentially made the same comment herein and explained the r…

My reading of it was that the bug was caused by XMM7 not being restored to its previous value. E.g. on Linux, functions should restore the values of ebx, esi, edi, ... once they're done with them. The article says (on Windows) that XMM7 needs to be restored too. If you can't trust one register being preserved (per the ABI), then you really can't trust the values of any registers.

Fair point, which is why I used the phrase "this particular example." In fact the compiler's lazy assumption about XMM7 was the key to determining that the ABI was being violated. It would have taken longer to figure this out if the compiler had been doing things my way, because then a failure of the callee to preserve XMM7 wouldn't have mattered.

Re: Please restore our registers when you’re done with them

#79
post #32

Why does a „3rd party encryption software” appear in the call stack of a user mode process in the first place? Is this another case where a “security” software injects broken DLL files into all processes in your system?

Yes. That's pretty common, unfortunately.

I'd love to see Chrome and Firefox and IE working together to detect this kind of thing and put up a malware warning explaining how to uninstall it, and see how quickly it can be eliminated.

Seriously, there is zero valid reason to ever inject code into another program, other than as a debugging tool on a system being debugged.

Re: Please restore our registers when you’re done with them

#80
I think the real fix is to set all registers to a canary value at the start of int main(), and then when exiting check the canary value is still there.

If anything has messed with any registers without permission, you crash and collect as much data as possible about any injected dll's.

Then you correlate these to find the culprits, and for each you contact the authors of the DLL and figure out a way to block the injection of any unfixed versions that cause crashes.

Post reply on HN