From a7d0b38d0df1dac5e799fe19ac1faa1e013ddf1b Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Fri, 22 Mar 2024 12:07:22 +0100 Subject: parisc: Avoid trashing MPE IPL bootloader stack The MPE IPL boot loader calls PDC_MODEL when running in narrow mode. The return buffer pointed to by arg2 holds space for eigth 32-bit integers directly followed by the stack used by MPE. So, when pdc_model() writes 32 64-bit integers to arg2, it unintentionally overwrites MPE's call stack. Fix it by limiting returned bytes depending if PDC_MODEL was called in WIDE or NARROW mode. Signed-off-by: Helge Deller --- src/parisc/parisc.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/parisc/parisc.c b/src/parisc/parisc.c index 1c7b109..2d1f833 100644 --- a/src/parisc/parisc.c +++ b/src/parisc/parisc.c @@ -1499,11 +1499,14 @@ static int pdc_pim(unsigned long *arg) return PDC_BAD_OPTION; } -static int pdc_model(unsigned long *arg) +static int pdc_model(unsigned long *arg, unsigned long narrow_mode) { const char *model_str = current_machine->pdc_modelstr; unsigned long option = ARG1; unsigned long *result = (unsigned long *)ARG2; + unsigned int *result_narrow = (unsigned int *)ARG2; + unsigned long *source; + int i; switch (option) { case PDC_MODEL_INFO: @@ -1512,10 +1515,21 @@ static int pdc_model(unsigned long *arg) * with old qemu versions which will try to run 64-bit instructions * kernel sr_disable_hash() function */ - memset(result, 0, 32 * sizeof(unsigned long)); - memcpy(result, (is_64bit_CPU()) ? - ¤t_machine->pdc_model : &machine_B160L.pdc_model, - sizeof(current_machine->pdc_model)); + source = is_64bit_CPU() ? ¤t_machine->pdc_model.hversion + : &machine_B160L.pdc_model.hversion; + + /* make sure to only copy the necessary bytes. */ + NO_COMPAT_RETURN_VALUE(ARG2); + for (i = 0; i < sizeof(machine_B160L.pdc_model)/sizeof(unsigned long); i++) { + if (is_64bit_PDC() && narrow_mode) { + *result_narrow = *source; + result_narrow++; + } else { + *result = *source; + result++; + } + source++; + } return PDC_OK; case PDC_MODEL_VERSIONS: switch (ARG3) { @@ -2387,7 +2401,7 @@ int __VISIBLE parisc_pdc_entry(unsigned long *arg, unsigned long narrow_mode) return pdc_pim(arg); case PDC_MODEL: /* model information */ - return pdc_model(arg); + return pdc_model(arg, narrow_mode); case PDC_CACHE: return pdc_cache(arg); -- cgit v1.1