From 5c6595e4c08d6911084441def0f7b71367d80071 Mon Sep 17 00:00:00 2001 From: Philipp Rudo Date: Apr 06 2022 16:05:47 +0000 Subject: s390: add variable command line size Resolves: bz2060824 Upstream: git.kernel.org/pub/scm/utils/kernel/kexec/kexec-tools.git Conflicts: None commit defb80a20bf1e4d778596ce2447e19d44f31ae5a Author: Sven Schnelle Date: Thu Dec 16 12:43:52 2021 +0100 s390: add variable command line size Newer s390 kernels support a command line size longer than 896 bytes. Such kernels contain a new member in the parameter area, which might be utilized by tools like kexec. Older kernels have the location initialized to zero, so we check whether there's a non-zero number present and use that. If there isn't, we fallback to the legacy command line size of 896 bytes. Signed-off-by: Sven Schnelle Reviewed-by: Alexander Egorenkov Signed-off-by: Simon Horman Signed-off-by: Philipp Rudo --- diff --git a/kexec-tools-2.0.23-01-s390_add_variable_command_line_size.patch b/kexec-tools-2.0.23-01-s390_add_variable_command_line_size.patch new file mode 100644 index 0000000..31b9840 --- /dev/null +++ b/kexec-tools-2.0.23-01-s390_add_variable_command_line_size.patch @@ -0,0 +1,224 @@ + commit defb80a20bf1e4d778596ce2447e19d44f31ae5a + Author: Sven Schnelle + Date: Thu Dec 16 12:43:52 2021 +0100 + + s390: add variable command line size + + Newer s390 kernels support a command line size longer than 896 + bytes. Such kernels contain a new member in the parameter area, + which might be utilized by tools like kexec. Older kernels have + the location initialized to zero, so we check whether there's a + non-zero number present and use that. If there isn't, we fallback + to the legacy command line size of 896 bytes. + + Signed-off-by: Sven Schnelle + Reviewed-by: Alexander Egorenkov + Signed-off-by: Simon Horman + + diff --git a/kexec/arch/s390/crashdump-s390.c b/kexec/arch/s390/crashdump-s390.c + index 10f4d607bbcc1aea362de3de687b0e7b2401d879..3bd9efe6dafebab2f364c656ae703c71c4494c35 100644 + --- a/kexec/arch/s390/crashdump-s390.c + +++ b/kexec/arch/s390/crashdump-s390.c + @@ -52,7 +52,8 @@ static int create_elf_header(struct kexec_info *info, unsigned long crash_base, + elfcorehdr_size = bufsz; + snprintf(str, sizeof(str), " elfcorehdr=%ld@%ldK\n", + elfcorehdr_size, elfcorehdr / 1024); + - command_line_add(str); + + if (command_line_add(info, str)) + + return -1; + #endif + return 0; + } + diff --git a/kexec/arch/s390/kexec-image.c b/kexec/arch/s390/kexec-image.c + index 3c24fdfe3c7ccafddee9fb4a68c0d8874cf6a61e..a52399eafd2abd4a24142f0512251598ea812ca5 100644 + --- a/kexec/arch/s390/kexec-image.c + +++ b/kexec/arch/s390/kexec-image.c + @@ -25,7 +25,6 @@ + #include + + static uint64_t crash_base, crash_end; + -static char command_line[COMMAND_LINESIZE]; + + static void add_segment_check(struct kexec_info *info, const void *buf, + size_t bufsz, unsigned long base, size_t memsz) + @@ -36,13 +35,18 @@ static void add_segment_check(struct kexec_info *info, const void *buf, + add_segment(info, buf, bufsz, crash_base + base, memsz); + } + + -int command_line_add(const char *str) + +int command_line_add(struct kexec_info *info, const char *str) + { + - if (strlen(command_line) + strlen(str) + 1 > COMMAND_LINESIZE) { + - fprintf(stderr, "Command line too long.\n"); + + char *tmp = NULL; + + + + tmp = concat_cmdline(info->command_line, str); + + if (!tmp) { + + fprintf(stderr, "out of memory\n"); + return -1; + } + - strcat(command_line, str); + + + + free(info->command_line); + + info->command_line = tmp; + return 0; + } + + @@ -64,7 +68,7 @@ int image_s390_load_file(int argc, char **argv, struct kexec_info *info) + while ((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) { + switch(opt) { + case OPT_APPEND: + - if (command_line_add(optarg)) + + if (command_line_add(info, optarg)) + return -1; + break; + case OPT_RAMDISK: + @@ -78,13 +82,16 @@ int image_s390_load_file(int argc, char **argv, struct kexec_info *info) + if (info->initrd_fd == -1) { + fprintf(stderr, "Could not open initrd file %s:%s\n", + ramdisk, strerror(errno)); + + free(info->command_line); + + info->command_line = NULL; + return -1; + } + } + + - info->command_line = command_line; + - info->command_line_len = strlen (command_line) + 1; + - + + if (info->command_line) + + info->command_line_len = strlen(info->command_line) + 1; + + else + + info->command_line_len = 0; + return 0; + } + + @@ -97,7 +104,7 @@ image_s390_load(int argc, char **argv, const char *kernel_buf, + const char *ramdisk; + off_t ramdisk_len; + unsigned int ramdisk_origin; + - int opt; + + int opt, ret = -1; + + if (info->file_mode) + return image_s390_load_file(argc, argv, info); + @@ -112,7 +119,6 @@ image_s390_load(int argc, char **argv, const char *kernel_buf, + }; + static const char short_options[] = KEXEC_OPT_STR ""; + + - command_line[0] = 0; + ramdisk = NULL; + ramdisk_len = 0; + ramdisk_origin = 0; + @@ -120,7 +126,7 @@ image_s390_load(int argc, char **argv, const char *kernel_buf, + while ((opt = getopt_long(argc,argv,short_options,options,0)) != -1) { + switch(opt) { + case OPT_APPEND: + - if (command_line_add(optarg)) + + if (command_line_add(info, optarg)) + return -1; + break; + case OPT_RAMDISK: + @@ -132,7 +138,7 @@ image_s390_load(int argc, char **argv, const char *kernel_buf, + if (info->kexec_flags & KEXEC_ON_CRASH) { + if (parse_iomem_single("Crash kernel\n", &crash_base, + &crash_end)) + - return -1; + + goto out; + } + + /* Add kernel segment */ + @@ -151,7 +157,7 @@ image_s390_load(int argc, char **argv, const char *kernel_buf, + rd_buffer = slurp_file_mmap(ramdisk, &ramdisk_len); + if (rd_buffer == NULL) { + fprintf(stderr, "Could not read ramdisk.\n"); + - return -1; + + goto out; + } + ramdisk_origin = MAX(RAMDISK_ORIGIN_ADDR, kernel_size); + ramdisk_origin = _ALIGN_UP(ramdisk_origin, 0x100000); + @@ -160,7 +166,7 @@ image_s390_load(int argc, char **argv, const char *kernel_buf, + } + if (info->kexec_flags & KEXEC_ON_CRASH) { + if (load_crashdump_segments(info, crash_base, crash_end)) + - return -1; + + goto out; + } else { + info->entry = (void *) IMAGE_READ_OFFSET; + } + @@ -183,15 +189,28 @@ image_s390_load(int argc, char **argv, const char *kernel_buf, + *tmp = crash_end - crash_base + 1; + } + } + - /* + - * We will write a probably given command line. + - * First, erase the old area, then setup the new parameters: + - */ + - if (strlen(command_line) != 0) { + - memset(krnl_buffer + COMMAND_LINE_OFFS, 0, COMMAND_LINESIZE); + - memcpy(krnl_buffer + COMMAND_LINE_OFFS, command_line, strlen(command_line)); + + + + if (info->command_line) { + + unsigned long maxsize; + + char *dest = krnl_buffer + COMMAND_LINE_OFFS; + + + + maxsize = *(unsigned long *)(krnl_buffer + MAX_COMMAND_LINESIZE_OFFS); + + if (!maxsize) + + maxsize = LEGACY_COMMAND_LINESIZE; + + + + if (strlen(info->command_line) > maxsize-1) { + + fprintf(stderr, "command line too long, maximum allowed size %ld\n", + + maxsize-1); + + goto out; + + } + + strncpy(dest, info->command_line, maxsize-1); + + dest[maxsize-1] = '\0'; + } + - return 0; + + ret = 0; + +out: + + free(info->command_line); + + info->command_line = NULL; + + return ret; + } + + int + diff --git a/kexec/arch/s390/kexec-s390.h b/kexec/arch/s390/kexec-s390.h + index ef53b111e16719d15e5364c18435e272f98b9086..6a99518c1c9e411ed853489daf0de6463972ab6f 100644 + --- a/kexec/arch/s390/kexec-s390.h + +++ b/kexec/arch/s390/kexec-s390.h + @@ -10,16 +10,17 @@ + #ifndef KEXEC_S390_H + #define KEXEC_S390_H + + -#define IMAGE_READ_OFFSET 0x10000 + +#define IMAGE_READ_OFFSET 0x10000 + + -#define RAMDISK_ORIGIN_ADDR 0x800000 + -#define INITRD_START_OFFS 0x408 + -#define INITRD_SIZE_OFFS 0x410 + -#define OLDMEM_BASE_OFFS 0x418 + -#define OLDMEM_SIZE_OFFS 0x420 + -#define COMMAND_LINE_OFFS 0x480 + -#define COMMAND_LINESIZE 896 + -#define MAX_MEMORY_RANGES 1024 + +#define RAMDISK_ORIGIN_ADDR 0x800000 + +#define INITRD_START_OFFS 0x408 + +#define INITRD_SIZE_OFFS 0x410 + +#define OLDMEM_BASE_OFFS 0x418 + +#define OLDMEM_SIZE_OFFS 0x420 + +#define MAX_COMMAND_LINESIZE_OFFS 0x430 + +#define COMMAND_LINE_OFFS 0x480 + +#define LEGACY_COMMAND_LINESIZE 896 + +#define MAX_MEMORY_RANGES 1024 + + #define MAX(x, y) ((x) > (y) ? (x) : (y)) + #define MIN(x, y) ((x) < (y) ? (x) : (y)) + @@ -32,6 +33,6 @@ extern int load_crashdump_segments(struct kexec_info *info, + unsigned long crash_end); + extern int get_memory_ranges_s390(struct memory_range range[], int *ranges, + int with_crashk); + -extern int command_line_add(const char *str); + +extern int command_line_add(struct kexec_info *info, const char *str); + + #endif /* KEXEC_S390_H */ diff --git a/kexec-tools.spec b/kexec-tools.spec index a762a10..5ce60c8 100644 --- a/kexec-tools.spec +++ b/kexec-tools.spec @@ -104,6 +104,8 @@ Requires: systemd-udev%{?_isa} # # Patches 401 through 500 are meant for s390 kexec-tools enablement # +Patch401: ./kexec-tools-2.0.23-01-s390_add_variable_command_line_size.patch + # # Patches 501 through 600 are meant for ARM kexec-tools enablement # @@ -133,6 +135,7 @@ mkdir -p -m755 kcp tar -z -x -v -f %{SOURCE9} tar -z -x -v -f %{SOURCE19} +%patch401 -p1 %patch601 -p1 %patch602 -p1 %patch603 -p1