lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20200117150323.21801-16-pmladek@suse.com>
Date:   Fri, 17 Jan 2020 16:03:15 +0100
From:   Petr Mladek <pmladek@...e.com>
To:     Jiri Kosina <jikos@...nel.org>,
        Josh Poimboeuf <jpoimboe@...hat.com>,
        Miroslav Benes <mbenes@...e.cz>
Cc:     Joe Lawrence <joe.lawrence@...hat.com>,
        Kamalesh Babulal <kamalesh@...ux.vnet.ibm.com>,
        Nicolai Stange <nstange@...e.de>,
        live-patching@...r.kernel.org, linux-kernel@...r.kernel.org,
        Petr Mladek <pmladek@...e.com>
Subject: [POC 15/23] livepatch: Prevent infinite loop when loading livepatch module

Livepatch modules should get automatically removed when the patched
module gets removed. But the problem with forced flag has shown that
there might be situations where it did not work as expected.

The problem with forced flag is solved now. But there might be other
situations that are not known at the moment.

Be on the safe side and add a paranoid check for preventing an infinite
loop in klp_module_coming() callback. It might happen when it tries to load
a livepatch module that has already been loaded in the past and that
was not removed because of a bug somewhere.

POC NOTE: The main purpose of this patch is to show potential problems
	with the split livepatches. It is hard to say if the check is
	worth it or whether even more checks are needed.

Signed-off-by: Petr Mladek <pmladek@...e.com>
---
 kernel/livepatch/core.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 4b55d805f3ec..688ad81def14 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -1316,6 +1316,25 @@ void klp_discard_nops(struct klp_patch *new_patch)
 	klp_free_objects_dynamic(klp_transition_patch);
 }
 
+static bool klp_is_object_module_alive(const char *patch_name,
+				       const char *obj_name)
+{
+	static char mod_name[MODULE_NAME_LEN];
+	struct module *mod;
+	bool alive = false;
+
+	mutex_lock(&module_mutex);
+
+	snprintf(mod_name, sizeof(mod_name), "%s__%s", patch_name, obj_name);
+	mod = find_module(mod_name);
+	if (mod && mod->state & MODULE_STATE_LIVE)
+		alive = true;
+
+	mutex_unlock(&module_mutex);
+
+	return alive;
+}
+
 int klp_module_coming(struct module *mod)
 {
 	char patch_name[MODULE_NAME_LEN];
@@ -1335,6 +1354,19 @@ int klp_module_coming(struct module *mod)
 		if (klp_is_object_loaded(patch, mod->name))
 			continue;
 
+		/*
+		 * Paranoid check. Prevent infinite loop when a livepatch
+		 * module is alive and klp_is_object_loaded() does not
+		 * see it. It might happen when the object is removed
+		 * and module_put() is not called. This should never happen
+		 * when everything works as expected.
+		 */
+		if (klp_is_object_module_alive(patch->obj->mod->name,
+					       mod->name)) {
+			ret = -EBUSY;
+			goto err;
+		}
+
 		strncpy(patch_name, patch->obj->patch_name, sizeof(patch_name));
 		patch_ts = patch->ts;
 		mutex_unlock(&klp_mutex);
-- 
2.16.4

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ