From: Greg Kroah-Hartman Date: Sat, 28 Jan 2023 09:28:14 +0000 (+0100) Subject: 4.14-stable patches X-Git-Tag: v5.10.166~58 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b564c3ab417921b9feda63cac2150816a7b83d36;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: module-don-t-wait-for-going-modules.patch tracing-make-sure-trace_printk-can-output-as-soon-as-it-can-be-used.patch --- diff --git a/queue-4.14/module-don-t-wait-for-going-modules.patch b/queue-4.14/module-don-t-wait-for-going-modules.patch new file mode 100644 index 00000000000..02208f9c266 --- /dev/null +++ b/queue-4.14/module-don-t-wait-for-going-modules.patch @@ -0,0 +1,111 @@ +From 0254127ab977e70798707a7a2b757c9f3c971210 Mon Sep 17 00:00:00 2001 +From: Petr Pavlu +Date: Mon, 5 Dec 2022 11:35:57 +0100 +Subject: module: Don't wait for GOING modules + +From: Petr Pavlu + +commit 0254127ab977e70798707a7a2b757c9f3c971210 upstream. + +During a system boot, it can happen that the kernel receives a burst of +requests to insert the same module but loading it eventually fails +during its init call. For instance, udev can make a request to insert +a frequency module for each individual CPU when another frequency module +is already loaded which causes the init function of the new module to +return an error. + +Since commit 6e6de3dee51a ("kernel/module.c: Only return -EEXIST for +modules that have finished loading"), the kernel waits for modules in +MODULE_STATE_GOING state to finish unloading before making another +attempt to load the same module. + +This creates unnecessary work in the described scenario and delays the +boot. In the worst case, it can prevent udev from loading drivers for +other devices and might cause timeouts of services waiting on them and +subsequently a failed boot. + +This patch attempts a different solution for the problem 6e6de3dee51a +was trying to solve. Rather than waiting for the unloading to complete, +it returns a different error code (-EBUSY) for modules in the GOING +state. This should avoid the error situation that was described in +6e6de3dee51a (user space attempting to load a dependent module because +the -EEXIST error code would suggest to user space that the first module +had been loaded successfully), while avoiding the delay situation too. + +This has been tested on linux-next since December 2022 and passes +all kmod selftests except test 0009 with module compression enabled +but it has been confirmed that this issue has existed and has gone +unnoticed since prior to this commit and can also be reproduced without +module compression with a simple usleep(5000000) on tools/modprobe.c [0]. +These failures are caused by hitting the kernel mod_concurrent_max and can +happen either due to a self inflicted kernel module auto-loead DoS somehow +or on a system with large CPU count and each CPU count incorrectly triggering +many module auto-loads. Both of those issues need to be fixed in-kernel. + +[0] https://lore.kernel.org/all/Y9A4fiobL6IHp%2F%2FP@bombadil.infradead.org/ + +Fixes: 6e6de3dee51a ("kernel/module.c: Only return -EEXIST for modules that have finished loading") +Co-developed-by: Martin Wilck +Signed-off-by: Martin Wilck +Signed-off-by: Petr Pavlu +Cc: stable@vger.kernel.org +Reviewed-by: Petr Mladek +[mcgrof: enhance commit log with testing and kmod test result interpretation ] +Signed-off-by: Luis Chamberlain +Signed-off-by: Greg Kroah-Hartman +--- + kernel/module.c | 26 +++++++++++++++++++++----- + 1 file changed, 21 insertions(+), 5 deletions(-) + +--- a/kernel/module.c ++++ b/kernel/module.c +@@ -3451,7 +3451,8 @@ static bool finished_loading(const char + sched_annotate_sleep(); + mutex_lock(&module_mutex); + mod = find_module_all(name, strlen(name), true); +- ret = !mod || mod->state == MODULE_STATE_LIVE; ++ ret = !mod || mod->state == MODULE_STATE_LIVE ++ || mod->state == MODULE_STATE_GOING; + mutex_unlock(&module_mutex); + + return ret; +@@ -3603,20 +3604,35 @@ static int add_unformed_module(struct mo + + mod->state = MODULE_STATE_UNFORMED; + +-again: + mutex_lock(&module_mutex); + old = find_module_all(mod->name, strlen(mod->name), true); + if (old != NULL) { +- if (old->state != MODULE_STATE_LIVE) { ++ if (old->state == MODULE_STATE_COMING ++ || old->state == MODULE_STATE_UNFORMED) { + /* Wait in case it fails to load. */ + mutex_unlock(&module_mutex); + err = wait_event_interruptible(module_wq, + finished_loading(mod->name)); + if (err) + goto out_unlocked; +- goto again; ++ ++ /* The module might have gone in the meantime. */ ++ mutex_lock(&module_mutex); ++ old = find_module_all(mod->name, strlen(mod->name), ++ true); + } +- err = -EEXIST; ++ ++ /* ++ * We are here only when the same module was being loaded. Do ++ * not try to load it again right now. It prevents long delays ++ * caused by serialized module load failures. It might happen ++ * when more devices of the same type trigger load of ++ * a particular module. ++ */ ++ if (old && old->state == MODULE_STATE_LIVE) ++ err = -EEXIST; ++ else ++ err = -EBUSY; + goto out; + } + mod_update_bounds(mod); diff --git a/queue-4.14/series b/queue-4.14/series index ede16c54f89..62c41be6e60 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -23,3 +23,5 @@ comedi-adv_pci1760-fix-pwm-instruction-handling.patch fs-reiserfs-remove-useless-new_opts-in-reiserfs_remount.patch bluetooth-hci_sync-cancel-cmd_timer-if-hci_open-fail.patch scsi-hpsa-fix-allocation-size-for-scsi_host_alloc.patch +module-don-t-wait-for-going-modules.patch +tracing-make-sure-trace_printk-can-output-as-soon-as-it-can-be-used.patch diff --git a/queue-4.14/tracing-make-sure-trace_printk-can-output-as-soon-as-it-can-be-used.patch b/queue-4.14/tracing-make-sure-trace_printk-can-output-as-soon-as-it-can-be-used.patch new file mode 100644 index 00000000000..969cccf861d --- /dev/null +++ b/queue-4.14/tracing-make-sure-trace_printk-can-output-as-soon-as-it-can-be-used.patch @@ -0,0 +1,80 @@ +From 3bb06eb6e9acf7c4a3e1b5bc87aed398ff8e2253 Mon Sep 17 00:00:00 2001 +From: "Steven Rostedt (Google)" +Date: Wed, 4 Jan 2023 16:14:12 -0500 +Subject: tracing: Make sure trace_printk() can output as soon as it can be used + +From: Steven Rostedt (Google) + +commit 3bb06eb6e9acf7c4a3e1b5bc87aed398ff8e2253 upstream. + +Currently trace_printk() can be used as soon as early_trace_init() is +called from start_kernel(). But if a crash happens, and +"ftrace_dump_on_oops" is set on the kernel command line, all you get will +be: + + [ 0.456075] -0 0dN.2. 347519us : Unknown type 6 + [ 0.456075] -0 0dN.2. 353141us : Unknown type 6 + [ 0.456075] -0 0dN.2. 358684us : Unknown type 6 + +This is because the trace_printk() event (type 6) hasn't been registered +yet. That gets done via an early_initcall(), which may be early, but not +early enough. + +Instead of registering the trace_printk() event (and other ftrace events, +which are not trace events) via an early_initcall(), have them registered at +the same time that trace_printk() can be used. This way, if there is a +crash before early_initcall(), then the trace_printk()s will actually be +useful. + +Link: https://lkml.kernel.org/r/20230104161412.019f6c55@gandalf.local.home + +Cc: stable@vger.kernel.org +Cc: Masami Hiramatsu +Fixes: e725c731e3bb1 ("tracing: Split tracing initialization into two for early initialization") +Reported-by: "Joel Fernandes (Google)" +Tested-by: Joel Fernandes (Google) +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/trace.c | 2 ++ + kernel/trace/trace.h | 1 + + kernel/trace/trace_output.c | 3 +-- + 3 files changed, 4 insertions(+), 2 deletions(-) + +--- a/kernel/trace/trace.c ++++ b/kernel/trace/trace.c +@@ -8487,6 +8487,8 @@ void __init early_trace_init(void) + static_key_enable(&tracepoint_printk_key.key); + } + tracer_alloc_buffers(); ++ ++ init_events(); + } + + void __init trace_init(void) +--- a/kernel/trace/trace.h ++++ b/kernel/trace/trace.h +@@ -1531,6 +1531,7 @@ trace_find_event_field(struct trace_even + extern void trace_event_enable_cmd_record(bool enable); + extern void trace_event_enable_tgid_record(bool enable); + ++extern int init_events(void); + extern int event_trace_add_tracer(struct dentry *parent, struct trace_array *tr); + extern int event_trace_del_tracer(struct trace_array *tr); + +--- a/kernel/trace/trace_output.c ++++ b/kernel/trace/trace_output.c +@@ -1394,7 +1394,7 @@ static struct trace_event *events[] __in + NULL + }; + +-__init static int init_events(void) ++__init int init_events(void) + { + struct trace_event *event; + int i, ret; +@@ -1412,4 +1412,3 @@ __init static int init_events(void) + + return 0; + } +-early_initcall(init_events);