[PATCH v4 06/14] kexec: Add KHO parsing support

Mike Rapoport rppt at kernel.org
Mon Mar 10 10:08:01 PDT 2025


Hi Pratyush,

On Mon, Mar 10, 2025 at 04:20:01PM +0000, Pratyush Yadav wrote:
> Hi Mike,
> 
> On Thu, Feb 06 2025, Mike Rapoport wrote:
> [...]
> > @@ -444,7 +576,141 @@ static void kho_reserve_scratch(void)
> >  	kho_enable = false;
> >  }
> >  
> > +/*
> > + * Scan the DT for any memory ranges and make sure they are reserved in
> > + * memblock, otherwise they will end up in a weird state on free lists.
> > + */
> > +static void kho_init_reserved_pages(void)
> > +{
> > +	const void *fdt = kho_get_fdt();
> > +	int offset = 0, depth = 0, initial_depth = 0, len;
> > +
> > +	if (!fdt)
> > +		return;
> > +
> > +	/* Go through the mem list and add 1 for each reference */
> > +	for (offset = 0;
> > +	     offset >= 0 && depth >= initial_depth;
> > +	     offset = fdt_next_node(fdt, offset, &depth)) {
> > +		const struct kho_mem *mems;
> > +		u32 i;
> > +
> > +		mems = fdt_getprop(fdt, offset, "mem", &len);
> > +		if (!mems || len & (sizeof(*mems) - 1))
> > +			continue;
> > +
> > +		for (i = 0; i < len; i += sizeof(*mems)) {
> > +			const struct kho_mem *mem = &mems[i];
> 
> i goes from 0 to len in steps of 16, but you use it to dereference an
> array of type struct kho_mem. So you end up only looking at only one of
> every 16 mems and do an out of bounds access. I found this when testing
> the memfd patches and any time the file was more than 1 page, it started
> to crash randomly.

Thanks! Changyuan already pointed that out privately.
But I'm going to adopt the memory reservation scheme Jason proposed so
this code is going to go away anyway :)

> Below patch should fix that:
> 
> ---- 8< ----
> diff --git a/kernel/kexec_handover.c b/kernel/kexec_handover.c
> index c26753d613cbc..40d1d8ac68d44 100644
> --- a/kernel/kexec_handover.c
> +++ b/kernel/kexec_handover.c
> @@ -685,13 +685,15 @@ static void kho_init_reserved_pages(void)
>              offset >= 0 && depth >= initial_depth;
>              offset = fdt_next_node(fdt, offset, &depth)) {
>                 const struct kho_mem *mems;
> -               u32 i;
> +               u32 i, nr_mems;
>  
>                 mems = fdt_getprop(fdt, offset, "mem", &len);
>                 if (!mems || len & (sizeof(*mems) - 1))
>                         continue;
>  
> -               for (i = 0; i < len; i += sizeof(*mems)) {
> +               nr_mems = len / sizeof(*mems);
> +
> +               for (i = 0; i < nr_mems; i++) {
>                         const struct kho_mem *mem = &mems[i];
>  
>                         memblock_reserve(mem->addr, mem->size);
> ---- >8 ----
> [...]
> 
> -- 
> Regards,
> Pratyush Yadav

-- 
Sincerely yours,
Mike.



More information about the kexec mailing list