Received: by 2002:a25:8b91:0:0:0:0:0 with SMTP id j17csp9147812ybl; Fri, 17 Jan 2020 07:06:55 -0800 (PST) X-Google-Smtp-Source: APXvYqxFaei/F5J4FyCGbOsY3jsKijkJkquzh4Wz4yfCJkNWcbecccURkdk2VG286lX07BF5YiUD X-Received: by 2002:a9d:222f:: with SMTP id o44mr6382473ota.51.1579273615004; Fri, 17 Jan 2020 07:06:55 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1579273614; cv=none; d=google.com; s=arc-20160816; b=BJXUObajNsqkioMYFwCENbZClzzDOzBot5NLEsb//4oQ+ZQ7boVWD92CUTYD8Klv6T 3KdoMC2HXqh1pp6/neRSd46WVIFHFVQ/WcJ3lPBjKPYy23wdJtmRyDU/1zZwp4XL4ChB i//ssLXb7Uo+EJu+yOQtYvTgjsFhWlJZ1bTnkfg1cFBmFlqNymNov4KmuYUV6n8WD9K9 14SeAgeITirNnGqGvRejPbgqvv5fXUgqiatWf8koQvmG+zMwwO74ygTomEz6QvPfZxMi aGij2SWegW01RYwt58yqhiYr26TMfYngdMUBKNCdTL4zpwP3uVhY/0ua2KUNy6/EcTsI //9Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from; bh=qibv2g8+IHKdqBvJqNF1YJWaV23Ea03p9Jp/10yNDcY=; b=Pz2/2DpOqL+NDtTsTUjZX7kuNIuHeL3Q4YDbR3K8BLC6nDbPS/tixzsQWYRK+e295X gESmATthlZCxSTM8nYB0hV+dtEJtpsji7jQhDprd3N2bWUrnxVW8sGIh9RDkV/JeFt+V 4bXybdmBTPauQZeik10lL6E4bVA5GRSJ+1fnpL32c/kNTynuXZPzBpvOQLHT5pGhyYKJ iITVrUiEE2XTIXMhNgFTQT3iyCWfP5aK0UOllZ6za7UVSl31mQRKVGR8MRrfSxmUQVwV Pz4TDBSCBrcdcZLTPu7oIo8/z3snnOCChoyWzjtU6Wl7t75AOuuKqQyAAng0Fi91Q4IX xXUA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id w1si14046914oia.169.2020.01.17.07.06.43; Fri, 17 Jan 2020 07:06:54 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729340AbgAQPEd (ORCPT + 99 others); Fri, 17 Jan 2020 10:04:33 -0500 Received: from mx2.suse.de ([195.135.220.15]:46416 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729130AbgAQPEC (ORCPT ); Fri, 17 Jan 2020 10:04:02 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 040D5BBB2; Fri, 17 Jan 2020 15:04:00 +0000 (UTC) From: Petr Mladek To: Jiri Kosina , Josh Poimboeuf , Miroslav Benes Cc: Joe Lawrence , Kamalesh Babulal , Nicolai Stange , live-patching@vger.kernel.org, linux-kernel@vger.kernel.org, Petr Mladek Subject: [POC 13/23] livepatch: Remove livepatch module when the livepatched module is unloaded Date: Fri, 17 Jan 2020 16:03:13 +0100 Message-Id: <20200117150323.21801-14-pmladek@suse.com> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20200117150323.21801-1-pmladek@suse.com> References: <20200117150323.21801-1-pmladek@suse.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org klp_module_going() does very similar things as before splitting the livepatches. Especially, it unpatches the related code, calls the callbacks, unlinks the structures from the linked lists. It does not have to clean up the structure because the entire livepatch module is going to be freed and removed. Signed-off-by: Petr Mladek --- kernel/livepatch/core.c | 84 ++++++++++++++++++------------------------------- 1 file changed, 31 insertions(+), 53 deletions(-) diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c index 6c51b194da57..73462b66f63f 100644 --- a/kernel/livepatch/core.c +++ b/kernel/livepatch/core.c @@ -599,21 +599,6 @@ static void __klp_free_funcs(struct klp_object *obj, bool nops_only) } } -/* Clean up when a patched object is unloaded */ -static void klp_free_object_loaded(struct klp_object *obj) -{ - struct klp_func *func; - - obj->mod = NULL; - - klp_for_each_func(obj, func) { - func->old_func = NULL; - - if (func->nop) - func->new_func = NULL; - } -} - static void klp_free_object(struct klp_object *obj, bool nops_only) { __klp_free_funcs(obj, nops_only); @@ -909,6 +894,24 @@ static int klp_init_patch(struct klp_patch *patch) return 0; } +static void klp_remove_object(struct klp_object *obj) +{ + struct klp_patch *patch = + container_of(obj->kobj.parent, struct klp_patch, kobj); + + if (patch != klp_transition_patch) + klp_pre_unpatch_callback(obj); + + pr_notice("reverting patch '%s' on unloading module '%s'\n", + patch->obj->patch_name, obj->name); + + klp_unpatch_object(obj); + + klp_post_unpatch_callback(obj); + + klp_free_object(obj, false); +} + static int klp_check_module_name(struct klp_object *obj, bool is_module) { char mod_name[MODULE_NAME_LEN]; @@ -1313,40 +1316,6 @@ void klp_discard_nops(struct klp_patch *new_patch) klp_free_objects_dynamic(klp_transition_patch); } -/* - * Remove parts of patches that touch a given kernel module. The list of - * patches processed might be limited. When limit is NULL, all patches - * will be handled. - */ -static void klp_cleanup_module_patches_limited(struct module *mod, - struct klp_patch *limit) -{ - struct klp_patch *patch; - struct klp_object *obj; - - klp_for_each_patch(patch) { - if (patch == limit) - break; - - klp_for_each_object(patch, obj) { - if (!klp_is_module(obj) || strcmp(obj->name, mod->name)) - continue; - - if (patch != klp_transition_patch) - klp_pre_unpatch_callback(obj); - - pr_notice("reverting patch '%s' on unloading module '%s'\n", - patch->obj->patch_name, obj->name); - klp_unpatch_object(obj); - - klp_post_unpatch_callback(obj); - - klp_free_object_loaded(obj); - break; - } - } -} - int klp_module_coming(struct module *mod) { char patch_name[MODULE_NAME_LEN]; @@ -1404,19 +1373,28 @@ int klp_module_coming(struct module *mod) void klp_module_going(struct module *mod) { + struct klp_patch *patch; + struct klp_object *obj, *tmp_obj; + if (WARN_ON(mod->state != MODULE_STATE_GOING && mod->state != MODULE_STATE_COMING)) return; mutex_lock(&klp_mutex); /* - * Each module has to know that klp_module_going() - * has been called. We never know what module will - * get patched by a new patch. + * All already enabled livepatches for this module as going to be + * removed now. From this point, klp_enable_patch() must not load + * any new livepatch modules for this module. */ mod->klp_alive = false; - klp_cleanup_module_patches_limited(mod, NULL); + klp_for_each_patch(patch) { + klp_for_each_object_safe(patch, obj, tmp_obj) { + if (obj->name && !strcmp(obj->name, mod->name)) { + klp_remove_object(obj); + } + } + } mutex_unlock(&klp_mutex); } -- 2.16.4