From: Philip Guenther Subject: Re: kcopy fault DF bit restore To: Alexander Bluhm Cc: tech@openbsd.org Date: Wed, 5 Jun 2024 11:50:29 -0700 On Wed, Jun 5, 2024 at 8:05 AM Alexander Bluhm wrote: > I have seen a crash in pcb_lookup -> SipHash_End -> explicit_bzero > -> memset. Retguard found that the stack was corrupt with 0 bytes. > Message is SipHash_End+0x16d int $3. Instead of clearing the > SIPHASH_CTX on the stack, rep stosb in memset destroyed the stack > frame. The DF bit in the rflags is set, so the stack has been > cleared in the wrong direction. > > Only kcopy and memmove use std to set DF bit. kcopy has the special > property that it can fault. Then DF is set in the trap frame. > kpageflttrap() changes the return address to copy_fault via > pcb_onfault. When alltraps_kern returns, it restores the rflags > with DF set and jumps into copy_fault. From there we do a function > return into the kernel. From now on DF is set, but kernel memset > expects that it is cleared. Wow, amazing we managed to miss that in the previous rounds of DF fixes. > A possible place where kcopy() may fail is sys_kbind(). uvm_map_extract() > creates an uvm object, but when kcopy() faults, it may have been > destroyed by another thread. That...doesn't sound right, but it doesn't matter for this. If nothing else, kbind's use of kcopy() is from the thread's kernel stack to that page from uvm_map_extract() and those _can't_ overlap without world-ending issues. The uiomove->kcopy path is more suspect, IMHO. > Fix is easy, after copy fault, also reset the DF bit. Crash happend > on OpenBSD 7.4 amd64, i386 code looks similar. > > ok? ok guenther@