On Fri, Apr 19, 2024 at 7:08 AM Mikulas Patocka <mpatocka@xxxxxxxxxx> wrote: > > Hi > > As a part of LVM2, we are developing the libdevmapper library. The library > may be used to load cryptographic keys to the kernel, so it avoids leaking > the data to kernel memory and to the swap partition. > > After the use of cryptographic data, the libdevmapper library clears them > with memset and frees them afterwards. It executes __asm__ volatile("" ::: > "memory") to thwart some compiler optimization regarding writing to > to-be-freed memory. > > We have a test "dmsecuretest.sh" that loads cryptographic keys into the > kernel, dumps a core, the core file is analyzed and if it contains the > key, the test fails. > > This test fails on AMD Zen 4 - the reason for the failure is that the > "memcpy" function uses ZMM registers for data copying. When memcpy exits, > the encryption key is present in the ZMM registers and the key remains > there even after both source and destination buffers of memcpy were > cleared. > > When we perform dynamic symbol lookup, the ZMM registers are spilled on > the stack and they remain there forever - this is the reason why the core > file contains the encryption key and the test fails. > > I'd like to ask what to do with it? We could use LD_BIND_NOW=1 (or > -Wl,-z,now) - it mostly works, but not entirely - the key may still be > present on the stack even if we use LD_BIND_NOW=1. Since vector registers are saved on stack only during symbol lookup, shouldn't disabling lazy binding solve this issue? > When I hack the file glibc/sysdeps/x86_64/multiarch/ifunc-memmove.h so > that it always selects the ERMS variant of memcpy, the problem goes away. > > Could it be possible to add some switch to glibc, that could be turned on > by security-sensitive programs and that would prevent glibc from using the > vector registers? Or, do you suggest another solution? > > Mikulas > -- H.J.