Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15-SP2:Update
kexec-tools.17677
kexec-tools-fix-kexec_file_load-error-handling....
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File kexec-tools-fix-kexec_file_load-error-handling.patch of Package kexec-tools.17677
From 0ec1fd23847ba103f967e3377e2a1b13712cff6e Mon Sep 17 00:00:00 2001 From: Petr Tesarik <ptesarik@suse.com> 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 References: bsc#1166105 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 <ptesarik@suse.com> --- 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
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor