Received: by 10.213.65.68 with SMTP id h4csp298871imn; Fri, 23 Mar 2018 05:03:01 -0700 (PDT) X-Google-Smtp-Source: AG47ELsybF9eoeKB8NbcoUWvftl1fBfD2S88+QcRSbmv2fQ5VinnWlBfeU3aGiTx2rXimXvCFFya X-Received: by 10.98.225.9 with SMTP id q9mr12138405pfh.23.1521806581475; Fri, 23 Mar 2018 05:03:01 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1521806581; cv=none; d=google.com; s=arc-20160816; b=osm04R6EHjXIYfWpUrIdWvUiASjCT/J8kzRWELtOO6f75gT+FQViQDqU6vhVvse1CI 8lWQRDGspA72bb2D1QCwygIuMo7TJ/OFcPdN1eUwdCicLG9UalOGja1s5lpvBxiS3bla CvUxABgTfPhTVnztryxbribLLSHToofOmUuIMzqUaTOyZIR66qNUP7MWSFQffwJjJr0K 9ghqi+o52vPlYSGoEM3P01c74/uW8gjrb9lqqMMla3WStzajjhej05TjAQ2ccIG366Z0 FvlFBhPcFjj5MdGrL8bGrrArE2IaG5ABWRYNF/hzIZncUnbBn4KlLMgW49qZCmbhEaDo NSDA== 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:arc-authentication-results; bh=f7VxbRF+9I2MA/j+zdTgQWQorRgFlOcyS9VaoGUX0+M=; b=du6v3kgErxGcxvmHigtJpyuqPDT3yTNXUuAikl/1nfqnSIrBynPTywEO2mmX/ibzGr qQ36A0Rh8q1aPcNTX0dFduaUYJVMDb+LNmtGgmGnw88QS8NEYKzk3TZF96i30bPwNyS4 xFoMfh4w3a2YgJn/WfZueD0e+9DiqAG+d+MXd6wVXFwFm9tIZ8Pk7L3DXgcv5zhvuots 9Juhodnb8DyoRhcOSefw9irn0n81ulymi4Xuh0AspUBNXM51iPcL5w0Vm+vxfsfGhYJx KfEwFyjIV5b5WFjhzC6lirlWeGVEGmD3eSScULXH2m+BDZ0Y3MjovcA5yzYhZ80MZ1DQ 1zwg== 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 a9si5955940pgf.172.2018.03.23.05.02.46; Fri, 23 Mar 2018 05:03:01 -0700 (PDT) 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 S1754112AbeCWMBA (ORCPT + 99 others); Fri, 23 Mar 2018 08:01:00 -0400 Received: from mx2.suse.de ([195.135.220.15]:39601 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753565AbeCWMA4 (ORCPT ); Fri, 23 Mar 2018 08:00:56 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id C77D3AED0; Fri, 23 Mar 2018 12:00:54 +0000 (UTC) From: Petr Mladek To: Jiri Kosina , Josh Poimboeuf , Miroslav Benes Cc: Jason Baron , Joe Lawrence , Jessica Yu , Evgenii Shatokhin , live-patching@vger.kernel.org, linux-kernel@vger.kernel.org, Petr Mladek Subject: [PATCH 4/8] livepatch: Add an extra flag to distinguish registered patches Date: Fri, 23 Mar 2018 13:00:24 +0100 Message-Id: <20180323120028.31451-5-pmladek@suse.com> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180323120028.31451-1-pmladek@suse.com> References: <20180323120028.31451-1-pmladek@suse.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The initial implementation of the atomic replace feature keeps the replaced patches on the stack. But people would like to remove the replaced patches from different reasons that will be described in the following patch. This patch is just a small preparation step. We will need to keep the replaced patches registered even when they are not longer on the stack. It is because they are typically unregistered by the module exit script. Therefore we need to detect the registered patches another way. We could not use kobj.state_initialized because it is racy. The kobject is destroyed by an asynchronous call and could not be synchronized using klp_mutex. This patch solves the problem by adding a flag into struct klp_patch. It is manipulated under klp_mutex and therefore it is safe. It is easy to understand and it is enough in most situations. The function klp_is_patch_registered() is not longer needed. Though it was renamed to klp_is_patch_on_stack() and used in __klp_enable_patch() as a new sanity check. This patch does not change the existing behavior. Signed-off-by: Petr Mladek Cc: Josh Poimboeuf Cc: Jessica Yu Cc: Jiri Kosina Cc: Miroslav Benes Cc: Jason Baron --- include/linux/livepatch.h | 2 ++ kernel/livepatch/core.c | 24 ++++++++++++++++++------ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h index f28af280f9e0..d6e6d8176995 100644 --- a/include/linux/livepatch.h +++ b/include/linux/livepatch.h @@ -150,6 +150,7 @@ struct klp_object { * @list: list node for global list of registered patches * @kobj: kobject for sysfs resources * @obj_list: dynamic list of the object entries + * @registered: reliable way to check registration status * @enabled: the patch is enabled (but operation may be incomplete) * @finish: for waiting till it is safe to remove the patch module */ @@ -163,6 +164,7 @@ struct klp_patch { struct list_head list; struct kobject kobj; struct list_head obj_list; + bool registered; bool enabled; struct completion finish; }; diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c index 18c400bd9a33..70c67a834e9a 100644 --- a/kernel/livepatch/core.c +++ b/kernel/livepatch/core.c @@ -45,6 +45,11 @@ */ DEFINE_MUTEX(klp_mutex); +/* + * Stack of patches. It defines the order in which the patches can be enabled. + * Only patches on this stack might be enabled. New patches are added when + * registered. They are removed when they are unregistered. + */ static LIST_HEAD(klp_patches); static struct kobject *klp_root_kobj; @@ -97,7 +102,7 @@ static void klp_find_object_module(struct klp_object *obj) mutex_unlock(&module_mutex); } -static bool klp_is_patch_registered(struct klp_patch *patch) +static bool klp_is_patch_on_stack(struct klp_patch *patch) { struct klp_patch *mypatch; @@ -378,7 +383,7 @@ int klp_disable_patch(struct klp_patch *patch) mutex_lock(&klp_mutex); - if (!klp_is_patch_registered(patch)) { + if (!patch->registered) { ret = -EINVAL; goto err; } @@ -407,7 +412,11 @@ static int __klp_enable_patch(struct klp_patch *patch) if (WARN_ON(patch->enabled)) return -EINVAL; - /* enforce stacking: only the first disabled patch can be enabled */ + /* Enforce stacking. */ + if (!klp_is_patch_on_stack(patch)) + return -EINVAL; + + /* Only the first disabled patch can be enabled. */ if (patch->list.prev != &klp_patches && !list_prev_entry(patch, list)->enabled) return -EBUSY; @@ -478,7 +487,7 @@ int klp_enable_patch(struct klp_patch *patch) mutex_lock(&klp_mutex); - if (!klp_is_patch_registered(patch)) { + if (!patch->registered) { ret = -EINVAL; goto err; } @@ -519,7 +528,7 @@ static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr, mutex_lock(&klp_mutex); - if (!klp_is_patch_registered(patch)) { + if (!patch->registered) { /* * Module with the patch could either disappear meanwhile or is * not properly initialized yet. @@ -528,6 +537,7 @@ static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr, goto err; } + if (patch->enabled == enabled) { /* already in requested state */ ret = -EINVAL; @@ -1004,6 +1014,7 @@ static int klp_init_patch(struct klp_patch *patch) } list_add_tail(&patch->list, &klp_patches); + patch->registered = true; mutex_unlock(&klp_mutex); @@ -1034,7 +1045,7 @@ int klp_unregister_patch(struct klp_patch *patch) mutex_lock(&klp_mutex); - if (!klp_is_patch_registered(patch)) { + if (!patch->registered) { ret = -EINVAL; goto err; } @@ -1045,6 +1056,7 @@ int klp_unregister_patch(struct klp_patch *patch) } klp_free_patch(patch); + patch->registered = false; mutex_unlock(&klp_mutex); -- 2.13.6