Re: [PATCH 2/2] s390/ipl: Fix NULL deref in dump_reipl without re-IPL parm block
Mikhail Zaslonko <[email protected]>
| Newsgroups | org.kernel.vger.linux-s390 |
|---|---|
| Message-ID | <[email protected]> |
On 13-Aug-26 13:06, Vasily Gorbik wrote:
> Unlike kdump, which passes the re-IPL parameter block through os_info,
> the stand-alone dump passes it through the IPL parm block address and
> checksum in lowcore.
>
> Some IPL types, like HMC FTP boot or QEMU direct kernel boot, might not
> provide an IPL parameter block. In this case reipl_type_init() selects
> IPL_TYPE_UNKNOWN and reipl_block_actual remains NULL. Nevertheless,
> dump_reipl_run() unconditionally dereferences it when preparing the
> lowcore fields. This may happen to work by chance when address zero
> contains readable lowcore data. A zero IPL parameter block address is
> then stored in lowcore, causing the stand-alone dumper to enter disabled
> wait after completing the dump.
>
> Explicitly store a zero IPL parameter block address and checksum when no
> re-IPL parameter block is available. This does not change the behavior:
> the stand-alone dumper completes the dump and halts, while valid re-IPL
> parameter blocks continue to be handled as before.
>
> Fixes: 099b76513992 ("[S390] Automatic IPL after dump")
> Signed-off-by: Vasily Gorbik <[email protected]>
> ---
> arch/s390/kernel/ipl.c | 10 +++++++---
> 1 file changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
> index 7024fc413715..68fdd5616dfe 100644
> --- a/arch/s390/kernel/ipl.c
> +++ b/arch/s390/kernel/ipl.c
> @@ -1929,7 +1929,8 @@ static struct shutdown_action __refdata dump_action = {
> static void dump_reipl_run(struct shutdown_trigger *trigger)
> {
> struct lowcore *abs_lc;
> - unsigned int csum;
> + unsigned long ipib = 0;
> + unsigned int csum = 0;
>
> /*
> * Set REIPL_CLEAR flag in os_info flags entry indicating
> @@ -1945,9 +1946,12 @@ static void dump_reipl_run(struct shutdown_trigger *trigger)
> reipl_type == IPL_TYPE_UNKNOWN)
> os_info_flags |= OS_INFO_FLAG_REIPL_CLEAR;
> os_info_entry_add_data(OS_INFO_FLAGS_ENTRY, &os_info_flags, sizeof(os_info_flags));
> - csum = (__force unsigned int)cksm(reipl_block_actual, reipl_block_actual->hdr.len, 0);
> + if (reipl_block_actual) {
> + ipib = __pa(reipl_block_actual);
> + csum = (__force unsigned int)cksm(reipl_block_actual, reipl_block_actual->hdr.len, 0);
> + }
> abs_lc = get_abs_lowcore();
> - abs_lc->ipib = __pa(reipl_block_actual);
> + abs_lc->ipib = ipib;
> abs_lc->ipib_checksum = csum;
> put_abs_lowcore(abs_lc);
> dump_run(trigger);
Reviewed-by: Mikhail Zaslonko <[email protected]>