Home Home > GIT Browse > openSUSE-15.0
diff options
authorLuis R. Chamberlain <mcgrof@suse.com>2018-07-11 10:04:20 -0700
committerNikolay Borisov <nborisov@suse.com>2018-07-17 09:59:14 +0300
commit45a2c80d35755a56d8f4d404cd29ede8cffb5be7 (patch)
parentbd08482609f9174da0d3d53d2656e7957ab262c9 (diff)
kmod: fix wait on recursive loop (bsc#1099792).
2 files changed, 110 insertions, 0 deletions
diff --git a/patches.fixes/kmod-fix-wait-on-recursive-loop.patch b/patches.fixes/kmod-fix-wait-on-recursive-loop.patch
new file mode 100644
index 0000000000..e903e56bc0
--- /dev/null
+++ b/patches.fixes/kmod-fix-wait-on-recursive-loop.patch
@@ -0,0 +1,109 @@
+From 2ba293c9e7db150943f06b12d3eb7213e7fae624 Mon Sep 17 00:00:00 2001
+From: "Luis R. Rodriguez" <mcgrof@kernel.org>
+Date: Fri, 18 Aug 2017 15:15:58 -0700
+Subject: [PATCH] kmod: fix wait on recursive loop
+Git-commit: 2ba293c9e7db150943f06b12d3eb7213e7fae624
+Patch-mainline: v4.13-rc6
+References: bsc#1099792
+Recursive loops with module loading were previously handled in kmod by
+restricting the number of modprobe calls to 50 and if that limit was
+breached request_module() would return an error and a user would see the
+following on their kernel dmesg:
+ request_module: runaway loop modprobe binfmt-464c
+ Starting init:/sbin/init exists but couldn't execute it (error -8)
+This issue could happen for instance when a 64-bit kernel boots a 32-bit
+userspace on some architectures and has no 32-bit binary format
+hanlders. This is visible, for instance, when a CONFIG_MODULES enabled
+64-bit MIPS kernel boots a into o32 root filesystem and the binfmt
+handler for o32 binaries is not built-in.
+After commit 6d7964a722af ("kmod: throttle kmod thread limit") we now
+don't have any visible signs of an error and the kernel just waits for
+the loop to end somehow.
+Although this *particular* recursive loop could also be addressed by
+doing a sanity check on search_binary_handler() and disallowing a
+modular binfmt to be required for modprobe, a generic solution for any
+recursive kernel kmod issues is still needed.
+This should catch these loops. We can investigate each loop and address
+each one separately as they come in, this however puts a stop gap for
+them as before.
+Link: http://lkml.kernel.org/r/20170809234635.13443-3-mcgrof@kernel.org
+Fixes: 6d7964a722af ("kmod: throttle kmod thread limit")
+Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
+Reported-by: Matt Redfearn <matt.redfearn@imgtec.com>
+Tested-by: Matt Redfearn <matt.redfearn@imgetc.com>
+Cc: "Eric W. Biederman" <ebiederm@xmission.com>
+Cc: Colin Ian King <colin.king@canonical.com>
+Cc: Dan Carpenter <dan.carpenter@oracle.com>
+Cc: Daniel Mentz <danielmentz@google.com>
+Cc: David Binderman <dcb314@hotmail.com>
+Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Jessica Yu <jeyu@redhat.com>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Cc: Kees Cook <keescook@chromium.org>
+Cc: Michal Marek <mmarek@suse.com>
+Cc: Miroslav Benes <mbenes@suse.cz>
+Cc: Peter Zijlstra (Intel) <peterz@infradead.org>
+Cc: Petr Mladek <pmladek@suse.com>
+Cc: Rusty Russell <rusty@rustcorp.com.au>
+Cc: Shuah Khan <shuah@kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Luis R. Chamberlain <mcgrof@suse.com>
+ kernel/kmod.c | 25 +++++++++++++++++++++++--
+ 1 file changed, 23 insertions(+), 2 deletions(-)
+diff --git a/kernel/kmod.c b/kernel/kmod.c
+index 6d016c5d97c8..2f37acde640b 100644
+--- a/kernel/kmod.c
++++ b/kernel/kmod.c
+@@ -70,6 +70,18 @@ static DECLARE_RWSEM(umhelper_sem);
+ static atomic_t kmod_concurrent_max = ATOMIC_INIT(MAX_KMOD_CONCURRENT);
+ static DECLARE_WAIT_QUEUE_HEAD(kmod_wq);
++ * This is a restriction on having *all* MAX_KMOD_CONCURRENT threads
++ * running at the same time without returning. When this happens we
++ * believe you've somehow ended up with a recursive module dependency
++ * creating a loop.
++ *
++ * We have no option but to fail.
++ *
++ * Userspace should proactively try to detect and prevent these.
++ */
+ /*
+ modprobe_path is set via /proc/sys.
+ */
+@@ -167,8 +179,17 @@ int __request_module(bool wait, const char *fmt, ...)
+ pr_warn_ratelimited("request_module: kmod_concurrent_max (%u) close to 0 (max_modprobes: %u), for module %s, throttling...",
+ atomic_read(&kmod_concurrent_max),
+ MAX_KMOD_CONCURRENT, module_name);
+- wait_event_interruptible(kmod_wq,
+- atomic_dec_if_positive(&kmod_concurrent_max) >= 0);
++ ret = wait_event_killable_timeout(kmod_wq,
++ atomic_dec_if_positive(&kmod_concurrent_max) >= 0,
++ if (!ret) {
++ pr_warn_ratelimited("request_module: modprobe %s cannot be processed, kmod busy with %d threads for more than %d seconds now",
++ return -ETIME;
++ } else if (ret == -ERESTARTSYS) {
++ pr_warn_ratelimited("request_module: sigkill sent for modprobe %s, giving up", module_name);
++ return ret;
++ }
+ }
+ trace_module_request(module_name, wait, _RET_IP_);
diff --git a/series.conf b/series.conf
index ed93fbfef6..79aee46db3 100644
--- a/series.conf
+++ b/series.conf
@@ -16005,6 +16005,7 @@
+ patches.fixes/kmod-fix-wait-on-recursive-loop.patch