zipl/boot: Fix unsigned long overflow

Fix two issues in boot menu input parsing:

1. ebcdic_strtoul returns unsigned long but the value was stored in an int.
2. ebcdic_strtoul could overflow if @value exceeds ULONG_MAX.

Both problems are easy to trigger by entering an excessively large value
in the boot menu, which can lead to unsigned long overflow and memory
corruption.

Use a checked addition to prevent overflow and change menu_read() return
type to unsigned long.

Suggested-by: Eduard Shishkin <edward6@linux.ibm.com>
Reviewed-by: Eduard Shishkin <edward6@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Marc Hartmayer
2026-01-08 11:26:06 +00:00
committed by Jan Höppner
parent 12d9d24437
commit a2663ec8d3
2 changed files with 8 additions and 5 deletions

View File

@@ -8,11 +8,13 @@
*
*/
#include <limits.h>
#include "ebcdic.h"
/*
* Convert ebcdic string to number with given base
* Convert EBCDIC string to number with given base. In case of an overflow,
* ULONG_MAX is returned and @endptr is not updated.
*/
unsigned long ebcdic_strtoul(char *nptr, char **endptr, int base)
{
@@ -21,7 +23,8 @@ unsigned long ebcdic_strtoul(char *nptr, char **endptr, int base)
while (ebcdic_isdigit(*nptr)) {
if (val != 0)
val *= base;
val += *nptr - 0xf0;
if (__builtin_uaddl_overflow(val, *nptr - 0xf0, &val))
return ULONG_MAX;
nptr++;
}
if (endptr)

View File

@@ -27,12 +27,12 @@ static void menu_prompt(int timeout)
printf("Please choose:");
}
static int menu_read(void)
static unsigned long menu_read(void)
{
char *temp_area = (char *)get_zeroed_page();
int timeout, rc, i, count = 0;
unsigned long value;
char *endptr;
int value;
timeout = __stage2_params.timeout;