Received: by 10.223.185.116 with SMTP id b49csp4777632wrg; Wed, 7 Mar 2018 00:23:29 -0800 (PST) X-Google-Smtp-Source: AG47ELsAaXVx86ZaFsVQ46GfkfI8FkF95LznMpgY7idq/eMi+NBB29ux4S8IGknnRtviPoQLpsIm X-Received: by 10.99.95.15 with SMTP id t15mr17194014pgb.183.1520411009152; Wed, 07 Mar 2018 00:23:29 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1520411009; cv=none; d=google.com; s=arc-20160816; b=NR0O3i41OpsiFCwp5ls8CDGWOoro7Q2F8DUl6H8C3z17vIC3wiTGXCEGoTN/X6fxgu 2cithr31JNNEzebKGqSYGx5cBDee9Pl87S37Ps+tgbMxwX8QnfIbS6+3t5GnnpincIJt mL3WBv43UBizT0SJCbHSY/aj6F6YmcnFIMBFTI6QNFIfwPriHdbf3OdUCJpxHDKrJRha xRGN3gKUHO+jjOfAydhiyoOz20/0jihFAPBAF0KAqralsJ9fBDm+KuSjf5/DqKRiNPSL ugKQcx0vuZt7NiATRHtD2HuZWNlwIRsTFC4eCdwRw3YnX3MYUlCk/jGYAhlYFdEXaM1B Lp/w== 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=qUhy7wKZDLnN9jQSnZpsmfkRXq622+dQ4k9KkCcjGXE=; b=H5QWf9ufRnmhMLE+P+LwCpOdqGv4O9uidRbO7a0y0rcnhMardUnfFiEol3pSH7cHBh YMFIB7f1GxGmh728t2CabvwjdV+wFO1sJHgvB0IUO8/OG2gsUv/UhPBxiWVz+jVEkWJF GC/560guOsCRbO+Map7L9EwKotXpnM2l3IIlmbN3kVnY4EZdn9/Si9Ov5GBgwpOrXWWA KyeMAhDZFvXpWBFphg8kniODZQezrdYHr35xpZ0C8SR6jlOWaBKfgYkPAKSv83Vd510Q YPmASqJNFjdB+OQEhE91vTvrGJ+VkpcbxMBzJgiiz7lgvB4lVS2LBjKR3J9wT90vO90V VFJA== 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 3-v6si12424214plr.440.2018.03.07.00.23.14; Wed, 07 Mar 2018 00:23:29 -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 S933533AbeCGIV7 (ORCPT + 99 others); Wed, 7 Mar 2018 03:21:59 -0500 Received: from mx2.suse.de ([195.135.220.15]:50149 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933206AbeCGIVF (ORCPT ); Wed, 7 Mar 2018 03:21:05 -0500 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 61EE4AF94; Wed, 7 Mar 2018 08:21:04 +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 v10 07/10] livepatch: Correctly handle atomic replace for not yet loaded modules Date: Wed, 7 Mar 2018 09:20:36 +0100 Message-Id: <20180307082039.10196-8-pmladek@suse.com> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180307082039.10196-1-pmladek@suse.com> References: <20180307082039.10196-1-pmladek@suse.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The atomic replace feature uses dynamically allocated struct klp_func to handle functions that will no longer be patched. These structures are of the type KLP_FUNC_NOP. They cause the ftrace handler to jump to the original code. But the address of the original code is not known until the patched module is loaded. This patch allows the late initialization. Also it adds a sanity check into the ftrace handler. Alternative solution would be not to set the address at all. The ftrace handler could just return to the original code when NOP struct klp_func is used. But this would require another changes. For example, in the stack checking. Note that NOP structures might be available even when the patch is being disabled. This would happen when the patch enable transition is reverted. Signed-off-by: Petr Mladek --- kernel/livepatch/core.c | 24 ++++++++++++++++++++---- kernel/livepatch/patch.c | 5 +++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c index ad508a86b2f9..67aa4ec9e087 100644 --- a/kernel/livepatch/core.c +++ b/kernel/livepatch/core.c @@ -781,8 +781,10 @@ static struct klp_func *klp_alloc_func_nop(struct klp_func *old_func, } } func->old_sympos = old_func->old_sympos; - /* NOP func is the same as using the original implementation. */ - func->new_func = (void *)old_func->old_addr; + /* + * func->new_func is same as func->old_addr. These addresses are + * set when the object is loaded, see klp_init_object_loaded(). + */ func->ftype = KLP_FUNC_NOP; return func; @@ -945,8 +947,12 @@ static void klp_free_object_loaded(struct klp_object *obj) obj->mod = NULL; - klp_for_each_func(obj, func) + klp_for_each_func(obj, func) { func->old_addr = 0; + + if (klp_is_func_type(func, KLP_FUNC_NOP)) + func->new_func = NULL; + } } /* @@ -984,7 +990,14 @@ static void klp_free_patch(struct klp_patch *patch) static int klp_init_func(struct klp_object *obj, struct klp_func *func) { - if (!func->old_name || !func->new_func) + if (!func->old_name) + return -EINVAL; + + /* + * NOPs get the address later. The the patched module must be loaded, + * see klp_init_object_loaded(). + */ + if (!func->new_func && !klp_is_func_type(func, KLP_FUNC_NOP)) return -EINVAL; INIT_LIST_HEAD(&func->stack_node); @@ -1039,6 +1052,9 @@ static int klp_init_object_loaded(struct klp_patch *patch, return -ENOENT; } + if (klp_is_func_type(func, KLP_FUNC_NOP)) + func->new_func = (void *)func->old_addr; + ret = kallsyms_lookup_size_offset((unsigned long)func->new_func, &func->new_size, NULL); if (!ret) { diff --git a/kernel/livepatch/patch.c b/kernel/livepatch/patch.c index 54b3c379bb0f..1f5c3eea9ee1 100644 --- a/kernel/livepatch/patch.c +++ b/kernel/livepatch/patch.c @@ -118,7 +118,12 @@ static void notrace klp_ftrace_handler(unsigned long ip, } } + /* Survive ugly mistakes, for example, when handling NOPs. */ + if (WARN_ON_ONCE(!func->new_func)) + goto unlock; + klp_arch_set_pc(regs, (unsigned long)func->new_func); + unlock: preempt_enable_notrace(); } -- 2.13.6