On 4/20/24 05:29, Zack Weinberg wrote:
On Fri, Apr 19, 2024, at 7:27 PM, Florian Weimer wrote:
* Mikulas Patocka:
On Fri, 19 Apr 2024, Zack Weinberg wrote:
On Fri, Apr 19, 2024, at 4:15 PM, Mikulas Patocka wrote:
On Fri, 19 Apr 2024, Zack Weinberg wrote:
... the copy
of round_keys in the vector registers *won't* get erased -- the exact
problem being discussed in this thread.

On the SYSV ABI, all the vector registers are volatile, so you can erase
them in explicit_bzero.

On Windows 64-bit ABI, it is more problematic, because some of the vector
registers must be preserved.

Oh, huh. Yes, that would work.

I've just realized that this wouldn't work - if the function
explicit_bzero is lazily resolved, the dynamic linker would spill the
vector registers to the stack prior to calling explicit_bzero.

No, the dynamic linker makes a tail call to explicit_bzero.  There's no
register restore on the return path, all that happens before the tail
call.

Doesn't help — if the vector registers get spilled at all, we lose.
I've recently come across a similar issue as reported in this old thread. I was checking for key residue in memory dumps of a crashed system, and I saw parts of keys persist in memory long after they were deleted by the application. The leakage mechanism I observed was:

* app memcpy()s key from one place to another
-- key residue left in SIMD regs now (in my case ARM NEON, but would be
   the same on x86)
* app does something with it
* app properly zero's everything
-- key residue in SIMD regs not cleared
* app continues running
* context switch happens, kernel switches to another task. Kernel saves
  SIMD reg contents behind struct task_struct
* system crashes, RAM dump taken. Key residue in kernel memory.

So even if the vector regs never get spilled to the stack, they still can easily end up in kernel memory long after the original data was erased. While this is not a big issue if everything works alright, it's still counter-intuitive and I think it would be good to do defense in depth and zero these vector regs after they are no longer needed.

I'm not sure the general purpose memcpy() would be the right place for a mitigation though. While AVX has VZEROALL, ARM NEON doesn't and requires 32 separate instructions, which I think could impact in a measurable performance hit even if you only issue the ones a particular call actually uses.

- Jan

Reply via email to