From 27efdc99ef09088bf9ad00d1abfad9b6d1c517e66c1ac5ad88efab5ef712b5e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Tesa=C5=99=C3=ADk?= Date: Fri, 13 Mar 2020 09:21:31 +0000 Subject: [PATCH] Accepting request 784585 from home:ptesarik:branches:Kernel:kdump - kexec-tools-fix-kexec_file_load-error-handling.patch: Fix the error handling if kexec_file_load() fails (bsc#1166105). OBS-URL: https://build.opensuse.org/request/show/784585 OBS-URL: https://build.opensuse.org/package/show/Kernel:kdump/kexec-tools?expand=0&rev=122 --- ...s-fix-kexec_file_load-error-handling.patch | 229 ++++++++++++++++++ kexec-tools.changes | 6 + kexec-tools.spec | 2 + 3 files changed, 237 insertions(+) create mode 100644 kexec-tools-fix-kexec_file_load-error-handling.patch diff --git a/kexec-tools-fix-kexec_file_load-error-handling.patch b/kexec-tools-fix-kexec_file_load-error-handling.patch new file mode 100644 index 0000000..b635f78 --- /dev/null +++ b/kexec-tools-fix-kexec_file_load-error-handling.patch @@ -0,0 +1,229 @@ +From 0ec1fd23847ba103f967e3377e2a1b13712cff6e Mon Sep 17 00:00:00 2001 +From: Petr Tesarik +Date: Thu, 12 Mar 2020 20:12:12 +0100 +Upstream: not yet, patch sent 2020-03-12 +Subject: Fix kexec_file_load(2) error handling + +The handling of kexec_file_load() error conditions needs some +improvement. + +First, on failure, the system call itself returns -1 and sets +errno. It is wrong to check the return value itself. + +Second, do_kexec_file_load() mixes different types of error +codes (-1, return value of a load method, negative kernel error +number). Let it always return one of the reason codes defined in +kexec/kexec.h. + +Third, the caller of do_kexec_file_load() cannot know what exactly +failed inside that function, so it should not check errno directly. +All it needs to know is whether it makes sense to fall back to the +other syscall. Add an error code for that purpose (EFALLBACK), and +let do_kexec_file_load() decide. + +Fourth, do_kexec_file_load() should not print any error message if +it returns EFALLBACK, because the fallback syscall may succeed +later, and the user is confused whether the command failed, or not. +Move the error message towards the end of main(). + +Signed-off-by: Petr Tesarik +--- + kexec/kexec.c | 114 ++++++++++++++++++++++++++++++---------------------------- + kexec/kexec.h | 1 + + 2 files changed, 61 insertions(+), 54 deletions(-) + +diff --git a/kexec/kexec.c b/kexec/kexec.c +index bc6ab3d..33c1b4b 100644 +--- a/kexec/kexec.c ++++ b/kexec/kexec.c +@@ -836,11 +836,21 @@ static int kexec_file_unload(unsigned long kexec_file_flags) + { + int ret = 0; + ++ if (!is_kexec_file_load_implemented()) ++ return EFALLBACK; ++ + ret = kexec_file_load(-1, -1, 0, NULL, kexec_file_flags); + if (ret != 0) { +- /* The unload failed, print some debugging information */ +- fprintf(stderr, "kexec_file_load(unload) failed\n: %s\n", +- strerror(errno)); ++ if (errno == ENOSYS) { ++ ret = EFALLBACK; ++ } else { ++ /* ++ * The unload failed, print some debugging ++ * information */ ++ fprintf(stderr, "kexec_file_load(unload) failed: %s\n", ++ strerror(errno)); ++ ret = EFAILED; ++ } + } + return ret; + } +@@ -1182,15 +1192,13 @@ static int do_kexec_file_load(int fileind, int argc, char **argv, + info.file_mode = 1; + info.initrd_fd = -1; + +- if (!is_kexec_file_load_implemented()) { +- fprintf(stderr, "syscall kexec_file_load not available.\n"); +- return -ENOSYS; +- } ++ if (!is_kexec_file_load_implemented()) ++ return EFALLBACK; + + if (argc - fileind <= 0) { + fprintf(stderr, "No kernel specified\n"); + usage(); +- return -1; ++ return EFAILED; + } + + kernel = argv[fileind]; +@@ -1199,7 +1207,7 @@ static int do_kexec_file_load(int fileind, int argc, char **argv, + if (kernel_fd == -1) { + fprintf(stderr, "Failed to open file %s:%s\n", kernel, + strerror(errno)); +- return -1; ++ return EFAILED; + } + + /* slurp in the input kernel */ +@@ -1225,7 +1233,7 @@ static int do_kexec_file_load(int fileind, int argc, char **argv, + if (i == file_types) { + fprintf(stderr, "Cannot determine the file type " "of %s\n", + kernel); +- return -1; ++ return EFAILED; + } + + ret = file_type[i].load(argc, argv, kernel_buf, kernel_size, &info); +@@ -1243,9 +1251,43 @@ static int do_kexec_file_load(int fileind, int argc, char **argv, + + ret = kexec_file_load(kernel_fd, info.initrd_fd, info.command_line_len, + info.command_line, info.kexec_flags); +- if (ret != 0) +- fprintf(stderr, "kexec_file_load failed: %s\n", +- strerror(errno)); ++ if (ret != 0) { ++ switch (errno) { ++ /* ++ * Something failed with signature verification. ++ * Reject the image. ++ */ ++ case ELIBBAD: ++ case EKEYREJECTED: ++ case ENOPKG: ++ case ENOKEY: ++ case EBADMSG: ++ case EMSGSIZE: ++ /* Reject by default. */ ++ default: ++ ret = EFAILED; ++ break; ++ ++ /* Not implemented. */ ++ case ENOSYS: ++ /* ++ * Parsing image or other options failed ++ * The image may be invalid or image ++ * type may not supported by kernel so ++ * retry parsing in kexec-tools. ++ */ ++ case EINVAL: ++ case ENOEXEC: ++ /* ++ * ENOTSUP can be unsupported image ++ * type or unsupported PE signature ++ * wrapper type, duh. ++ */ ++ case ENOTSUP: ++ ret = EFALLBACK; ++ break; ++ } ++ } + + close(kernel_fd); + return ret; +@@ -1496,7 +1538,7 @@ int main(int argc, char *argv[]) + if (do_unload) { + if (do_kexec_file_syscall) { + result = kexec_file_unload(kexec_file_flags); +- if ((result == -ENOSYS) && do_kexec_fallback) ++ if (result == EFALLBACK && do_kexec_fallback) + do_kexec_file_syscall = 0; + } + if (!do_kexec_file_syscall) +@@ -1506,46 +1548,8 @@ int main(int argc, char *argv[]) + if (do_kexec_file_syscall) { + result = do_kexec_file_load(fileind, argc, argv, + kexec_file_flags); +- if (do_kexec_fallback) switch (result) { +- /* +- * Something failed with signature verification. +- * Reject the image. +- */ +- case -ELIBBAD: +- case -EKEYREJECTED: +- case -ENOPKG: +- case -ENOKEY: +- case -EBADMSG: +- case -EMSGSIZE: +- /* +- * By default reject or do nothing if +- * succeded +- */ +- default: break; +- case -ENOSYS: /* not implemented */ +- /* +- * Parsing image or other options failed +- * The image may be invalid or image +- * type may not supported by kernel so +- * retry parsing in kexec-tools. +- */ +- case -EINVAL: +- case -ENOEXEC: +- /* +- * ENOTSUP can be unsupported image +- * type or unsupported PE signature +- * wrapper type, duh +- * +- * The kernel sometimes wrongly +- * returns ENOTSUPP (524) - ignore +- * that. It is not supposed to be seen +- * by userspace so seeing it is a +- * kernel bug +- */ +- case -ENOTSUP: +- do_kexec_file_syscall = 0; +- break; +- } ++ if (result == EFALLBACK && do_kexec_fallback) ++ do_kexec_file_syscall = 0; + } + if (!do_kexec_file_syscall) + result = my_load(type, fileind, argc, argv, +@@ -1570,6 +1574,8 @@ int main(int argc, char *argv[]) + if ((result == 0) && do_load_jump_back_helper) { + result = my_load_jump_back_helper(kexec_flags, entry); + } ++ if (result == EFALLBACK) ++ fputs("syscall kexec_file_load not available.\n", stderr); + + fflush(stdout); + fflush(stderr); +diff --git a/kexec/kexec.h b/kexec/kexec.h +index a97b9ce..28fd129 100644 +--- a/kexec/kexec.h ++++ b/kexec/kexec.h +@@ -63,6 +63,7 @@ + */ + #define EFAILED -1 /* default error code */ + #define ENOCRASHKERNEL -2 /* no memory reserved for crashkernel */ ++#define EFALLBACK -3 /* fallback to kexec_load(2) may work */ + + /* + * This function doesn't actually exist. The idea is that when someone +-- +2.16.4 + diff --git a/kexec-tools.changes b/kexec-tools.changes index 8a17ebf..a8b0e4a 100644 --- a/kexec-tools.changes +++ b/kexec-tools.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Fri Mar 13 08:37:58 UTC 2020 - Petr Tesařík + +- kexec-tools-fix-kexec_file_load-error-handling.patch: Fix the + error handling if kexec_file_load() fails (bsc#1166105). + ------------------------------------------------------------------- Wed Jan 29 07:35:18 UTC 2020 - Petr Tesařík diff --git a/kexec-tools.spec b/kexec-tools.spec index 54849cd..0c53e12 100644 --- a/kexec-tools.spec +++ b/kexec-tools.spec @@ -36,6 +36,7 @@ Patch7: %{name}-arm64-kdump-deal-with-resource-entries-in-proc-iomem.pat Patch8: %{name}-build-multiboot2-for-i386.patch Patch9: %{name}-video-capability.patch Patch10: %{name}-SYS_getrandom.patch +Patch11: %{name}-fix-kexec_file_load-error-handling.patch BuildRequires: autoconf BuildRequires: automake BuildRequires: systemd-rpm-macros @@ -68,6 +69,7 @@ the loaded kernel after it panics. %patch8 -p1 %patch9 -p1 %patch10 -p1 +%patch11 -p1 %build autoreconf -fvi