From 11b401b59954e380a5c776e1accc747e66cd10b1 Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Mon, 8 Nov 2021 10:31:35 +0100 Subject: [PATCH] zipl: move and make check for maximum command line length dynamic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The maximum command line length is now dependent on the kernel image that is loaded. Therefore move the check to check_common_ipl_data(). This function now reads the new kernel image, and check whether the command line length is in the allowed range. The command line size limit in zipl is now set to 64k, which is hopefully enough. Signed-off-by: Sven Schnelle Reviewed-by: Stefan Haberland Signed-off-by: Jan Höppner --- zipl/include/zipl.h | 3 ++- zipl/src/job.c | 34 ++++++++++++++++++++++------------ 2 files changed, 24 insertions(+), 13 deletions(-) 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;