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?
Please restore our registers when you’re done with them
51–60 of 142 posts
Re: Please restore our registers when you’re done with them
#52I'm sure some C++ lawyer can correct me, but isn't branching off of `m_ptr` (e.g. `CHECK()`ing the value) after `std::move(m_ptr)` technically Unspecified Behavior since `std::move(m_ptr)` leaves `m_ptr` as an Unspecified Value? It would be up to the compiler to define the behavior if they so pleased, but the C++ spec would not require such behavior to be defined at all.
However, the bigger issue with that code is that it can easily stop working with a simple refactor. Consider:
void foo(std::unique_ptr ptr) {}
void bar(std::unique_ptr&& ptr) {}
int main()
{
std::unique_ptr p1{new int{1}};
std::unique_ptr p2{new int{2}};
foo(std::move(p1));
assert(p1 == nullptr);
bar(std::move(p2));
assert(p2 != nullptr);
}
Neither of the above asserts will fire, but from the calling site, they look exactly the same. In my opinion, the more explicit option would be to do something like `bar(std::exchange(p2, nullptr))`[0]: overload (5) https://en.cppreference.com/w/cpp/memory/unique_ptr/unique_p...
Re: Please restore our registers when you’re done with them
#53Sounds 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"
Maybe we need some kind of higher level language that gets boiled down into assembly.
Re: Please restore our registers when you’re done with them
#54To what degree is this possible to check statically? It feels like at least simple breaks of the ABI rules like this can be detected somewhat statically. The author already started with a very simple and incomplete version. In general, I wonder, are there any (many?) static analyzers for assembled binaries.
Curiously, I found a register clobber bug in the NaCl cryptography library today. Apparently, they used a custom assembler-preprocessor (qhasm) that avoids certain classes of bugs and aids with porting, but while the tool seems to actually model the register in some way, it does not treat it as callee-saved.
Re: Please restore our registers when you’re done with them
#55Re: Please restore our registers when you’re done with them
#56Naïve question about ABIs: shouldn’t the caller be responsible for that? If I want a function to restore certain registers, wouldn’t it be simpler if I was the one that save them on my memory, call the function, and then override the registers with whatever values the function set? Otherwise it seems we’re just… asking for trouble, so to speak.
> If I want a function to restore certain registers, wouldn’t it be simpler if I was the one that save them on my memory, call the function, and then override the registers with whatever values the function set? That's a waste if the callee doesn't use them.
Re: Please restore our registers when you’re done with them
#57I'm sure some C++ lawyer can correct me, but isn't branching off of `m_ptr` (e.g. `CHECK()`ing the value) after `std::move(m_ptr)` technically Unspecified Behavior since `std::move(m_ptr)` leaves `m_ptr` as an Unspecified Value? It would be up to the compiler to define the behavior if they so pleased, but the C++ spec would not require such behavior to be defined at all.
It’s an unspecified but required to be valid value for the moved type. The author mentions it’s a smart pointer type, which could easily be defined to act like this.
Re: Please restore our registers when you’re done with them
#58Earlier quoted context omitted.
Yes, but it's not a property of the assembly (or assembler), it's a necessity for the compiler to correctly codegen around the inline assembly. Historically, assemblers have been really dumb, so ABI is not a thing they'd track, especially as... I don't think they know what functions are? So while they can notice call/ret, they have no knowledge of a label being a jump or call target per-se, do they? So you'd need an…
> I don't think they know what functions are? It's a long time since I tangled with x86 assembler; but as I recall, ENTER and LEAVE were specifically for functions, and I'm not aware of any other use for them.
Re: Please restore our registers when you’re done with them
#59It’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.
RISC-V has such a register. It returns zero when read, and ignored writes.
Re: Please restore our registers when you’re done with them
#60Earlier quoted context omitted.
> If I want a function to restore certain registers, wouldn’t it be simpler if I was the one that save them on my memory, call the function, and then override the registers with whatever values the function set? That's a waste if the callee doesn't use them.
Indeed. But isn’t it also a waste when someone doesn’t follow through and then we have situations like the one described on the article?
Preemptively saving and restoring all registers in all callers would appreciably slow down every single function call on every device in the world using that ABI.
The cumulative cost would be astronomical.