kern_kexec_load() could not tear down a staged image without leaking
it or panicking:
- stage_addr was never set, so replacing or unloading an image unmapped nothing and leaked its KVA and wired pages.
- obj->size, a page count, was passed as a byte length to vm_object_unwire() and vm_map_remove(). With INVARIANTS this trips the length KASSERT in vm_object_unwire().
- The error path used kexec_obj, which is NULL on the first call.
- The OBJT_PHYS object came from vm_object_allocate(), which leaves un_pager.phys.ops NULL, so freeing it faults in phys_pager_dealloc().
- Unloading deregistered the reboot handler but kept the tag, so a second unload faults in _eventhandler_deregister().
kexec_load(2) documents that mem and memsz must be page aligned, but the
kernel never checked. atop(memsz) rounds down while the copy loop
advances by memsz, so an unaligned memsz writes past the staging
mapping. segment_fits() also did not check mem + memsz for overflow.
Add tests/sys/kern/kexec_test.c. On GENERIC in a bhyve guest the
unpatched kernel panics in the first case ("vm_object_unwire: length is
not a multiple of PAGE_SIZE"); with this change all three cases pass.
All of this needs root and securelevel <= 0.
Sponsored by: Advanced Micro Devices, Inc.
Signed-off-by: Osvaldo Janeri Filho <ojanerif@amd.com>