diff --git a/zipl/include/zipl.h b/zipl/include/zipl.h index 9040d425..c299ec0e 100644 --- a/zipl/include/zipl.h +++ b/zipl/include/zipl.h @@ -23,7 +23,8 @@ #define ADDRESS_LIMIT 0x80000000UL #define UNSPECIFIED_ADDRESS -1UL -#define MAXIMUM_PARMLINE_SIZE 0x380UL +#define LEGACY_MAXIMUM_PARMLINE_SIZE 0x380UL +#define MAXIMUM_PARMLINE_SIZE 0x10000UL #define MAXIMUM_PHYSICAL_BLOCKSIZE 0x1000UL #define BOOTMAP_FILENAME "bootmap" diff --git a/zipl/src/job.c b/zipl/src/job.c index 3e1d75aa..198f8049 100644 --- a/zipl/src/job.c +++ b/zipl/src/job.c @@ -758,15 +758,36 @@ static void error_text_section(const char *text, const char *section, const char static int check_common_ipl_data(struct job_common_ipl_data *common, const char *section) { + uint64_t max_parm_size, len; + char *buffer = NULL; + size_t size; int rc; if (common->image != NULL) { - rc = misc_check_readable_file(common->image); + rc = misc_read_file(common->image, &buffer, &size, 0); if (rc) { error_text_section("Image file", section, common->image); return rc; } + + if (size < MAX_COMMAND_LINE_SIZE + sizeof(uint64_t)) { + error_text_section("Image file", section, common->image); + return -1; + } + + max_parm_size = *(uint64_t *)(buffer + MAX_COMMAND_LINE_SIZE); + if (!max_parm_size) + max_parm_size = LEGACY_MAXIMUM_PARMLINE_SIZE; + + len = strlen(common->parmline); + if (len > max_parm_size) { + error_text("The length of the parameters line " + "(%d bytes) exceeds the allowed maximum " + "(%d bytes) in section '%s'", len, max_parm_size, section); + return -1; + } } + if (common->ramdisk != NULL) { rc = misc_check_readable_file(common->ramdisk); if (rc) { @@ -1152,17 +1173,6 @@ get_parmline(char* filename, char* line, char** parmline, address_t* address, return -1; } else result = NULL; - /* Check for maximum length */ - if (result) { - len = strlen(result); - if (len > MAXIMUM_PARMLINE_SIZE) { - error_text("The length of the parameters line " - "(%d bytes) exceeds the allowed maximum " - "(%d bytes)", len, MAXIMUM_PARMLINE_SIZE); - free(result); - return -1; - } - } *parmline = result; *address = addr; return 0;