Re: [PATCH v3 3/3] LoongArch: Avoid initrd overlap during kernel relocation
Huacai Chen <[email protected]>
| Newsgroups | org.kernel.vger.linux-efi,dev.linux.lists.loongarch,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <CAAhV-H60vUx8PyT6nhxbog3=sYFL+E5Hgt1aS+7HWHddtLdb7w@mail.gmail.com> |
Hi, Rui, On Wed, Apr 29, 2026 at 1:14 PM WANG Rui <[email protected]> wrote: > > Validate the relocation address against the initrd region specified > via "initrd=" or "initrdmem=" on the command line. Reject relocation > targets that overlap the initrd to prevent memory corruption during > early boot. > > Signed-off-by: WANG Rui <[email protected]> > --- > arch/loongarch/kernel/relocate.c | 45 ++++++++++++++++++++++++++++++++ > 1 file changed, 45 insertions(+) > > diff --git a/arch/loongarch/kernel/relocate.c b/arch/loongarch/kernel/relocate.c > index c36604a81d08..c303c0be8f06 100644 > --- a/arch/loongarch/kernel/relocate.c > +++ b/arch/loongarch/kernel/relocate.c > @@ -214,14 +214,59 @@ static inline void __init *determine_relocation_address(void) > return RELOCATED_KASLR(destination); > } > > +static unsigned long __init try_get_initrd(unsigned long *size) Rename to determine_initrd_address() can keep consistency. > +{ > + unsigned long start = 0; > + unsigned int key_length; It's type should be "unsigned long" because strstr() returns "unsigned long". Huacai > + const char *key; > + char *p; > + > + key = "initrd="; > + key_length = strlen(key); > + p = strstr(boot_command_line, key); > + > + if (!p) { > + key = "initrdmem="; > + key_length = strlen(key); > + p = strstr(boot_command_line, key); > + } > + > + if (p == boot_command_line || (p > boot_command_line && *(p - 1) == ' ')) { > + char *endp; > + > + p += key_length; > + start = memparse(p, &endp); > + if (*endp == ',') > + *size = memparse(endp + 1, NULL); > + } > + > + return start; > +} > + > static inline int __init relocation_addr_valid(void *location_new) > { > + unsigned long initrd_start; > + unsigned long initrd_size = 0; > + > if ((unsigned long)location_new & 0x00000ffff) > return 0; /* Inappropriately aligned new location */ > > if ((unsigned long)location_new < (unsigned long)_end) > return 0; /* New location overlaps original kernel */ > > + initrd_start = try_get_initrd(&initrd_size); > + if (initrd_start && initrd_size) { > + unsigned long kernel_start; > + unsigned long kernel_size; > + > + kernel_start = PHYSADDR(location_new); > + kernel_size = (unsigned long)_end - (unsigned long)_text; > + > + if (kernel_start < (initrd_start + initrd_size) && > + initrd_start < (kernel_start + kernel_size)) > + return 0; /* Initrd overlaps kernel */ > + } > + > return 1; > } > #endif > -- > 2.54.0 >