[PATCH v5 13/20] x86/kexec: Mark relocate_kernel page as ROX instead of RWX

David Woodhouse dwmw2 at infradead.org
Thu Dec 12 02:30:10 PST 2024


On Wed, 2024-12-11 at 18:44 -0700, Nathan Chancellor wrote:
> Hi David,
> 
> On Thu, Dec 05, 2024 at 03:05:19PM +0000, David Woodhouse wrote:
> > From: David Woodhouse <dwmw at amazon.co.uk>
> > 
> > All writes to the page now happen before it gets marked as executable
> > (or after it's already switched to the identmap page tables where it's
> > OK to be RWX).
> > 
> > Signed-off-by: David Woodhouse <dwmw at amazon.co.uk>
> > ---
> >   arch/x86/kernel/machine_kexec_64.c | 3 ++-
> >   1 file changed, 2 insertions(+), 1 deletion(-)
> > 
> > diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
> > index c9fd60f8f806..9232ad1562c8 100644
> > --- a/arch/x86/kernel/machine_kexec_64.c
> > +++ b/arch/x86/kernel/machine_kexec_64.c
> > @@ -323,7 +323,7 @@ int machine_kexec_prepare(struct kimage *image)
> >   
> >   	__memcpy(control_page, __relocate_kernel_start, reloc_end - reloc_start);
> >   
> > -	set_memory_x((unsigned long)control_page, 1);
> > +	set_memory_rox((unsigned long)control_page, 1);
> >   
> >   	return 0;
> >   }
> > @@ -333,6 +333,7 @@ void machine_kexec_cleanup(struct kimage *image)
> >   	void *control_page = page_address(image->control_code_page);
> >   
> >   	set_memory_nx((unsigned long)control_page, 1);
> > +	set_memory_rw((unsigned long)control_page, 1);
> >   
> >   	free_transition_pgtable(image);
> >   }
> > -- 
> > 2.47.0
> > 
> 
> I just bisected a change in behavior that I see in to this change in
> -next as commit 5a82223e0743 ("x86/kexec: Mark relocate_kernel page as
> ROX instead of RWX"). I usually kexec my machines by running:
> 
>   # kexec --load /boot/vmlinuz-linux --initrd /boot/initramfs-linux.img --reuse-cmdline
> 
>   # systemctl kexec
> 
> to cleanly shutdown userspace then kexec into the new kernel after
> installing it via the package manager. After this change, I get sent to
> systemd-boot after running 'systemctl kexec', which selects the default
> entry, my distribution kernel.
> 
> I just see:
> 
>   [  OK  ] Reached target Reboot via kexec.
>   BdsDxe: loading Boot0007 "Linux Boot Manager" from HD(1,GPT,4B5AFD80-5EC7-47FC-83EA-7EC88ACB15A7,0x800,0x200000)/\EFI\systemd\systemd-bootx64.efi
>   BdsDxe: starting Boot0007 "Linux Boot Manager" from HD(1,GPT,4B5AFD80-5EC7-47FC-83EA-7EC88ACB15A7,0x800,0x200000)/\EFI\systemd\systemd-bootx64.efi
> 
> then the systemd-boot menu in QEMU when reproducing this there.
> 
> Is this expected? If not, I am happy to provide any information or test
> patches as necessary.

No, definitely not expected. Thanks for the report. I'll see if I can
reproduce it; please could you share your kernel .config?

Please could you also confirm that it still occurs if you don't use
systemctl; for speed of testing I have mostly been booting my test
kernel with no actual root file system; just an initrd which does
'kexec -f' immediately.

Since you are running in QEMU, if you can reproduce with this patch to
QEMU itself which should dump the CPU state on a triple-fault, it would
be very useful please:

--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -3133,6 +3133,7 @@ int kvm_cpu_exec(CPUState *cpu)
             ret = EXCP_INTERRUPT;
             break;
         case KVM_EXIT_SHUTDOWN:
+            cpu_dump_state(cpu, stderr, CPU_DUMP_CODE);
             qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
             ret = EXCP_INTERRUPT;
             break;

If you get output from that, please also send the output of 'objdump -S
arch/x86/kernel/relocate_kernel_64.o' to help interpret it.

Thanks.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 5965 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/kexec/attachments/20241212/13cbcbe0/attachment.p7s>


More information about the kexec mailing list