From patchwork Sat Oct 22 07:20:16 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greg KH X-Patchwork-Id: 7612 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:4242:0:0:0:0:0 with SMTP id s2csp1106751wrr; Sat, 22 Oct 2022 01:38:52 -0700 (PDT) X-Google-Smtp-Source: AMsMyM4y+bGbB4t3ih0ivIrb/JgTdgtgxGbcKVEzgtq5cM3pYxEEtajRXY+7zbp/BVgRQAMDhT2p X-Received: by 2002:a17:907:e93:b0:78d:b8ff:9b5f with SMTP id ho19-20020a1709070e9300b0078db8ff9b5fmr19417752ejc.12.1666427932679; Sat, 22 Oct 2022 01:38:52 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1666427932; cv=none; d=google.com; s=arc-20160816; b=hNwdfbgqlCPVBocmOUVwtbkz/ytTjbcCc86B0fjCNTY3/8bTXFcsSbBguUhzVqWb1d yEPIQXviZNmSMWzs58zrg2YBASgFacMArDiENI1DJFto1JQadWLflgvATZlWO9laBTP0 eTD4ywU4wfO6vDjLwPOzJIvFsyd35N2PVuerusIQp+K/riaFLdAvMwT9+ht6QKImJBKK QpsBtya3MFOT6uVp39qeq3nth6qFOjyY3nKCTTC6W7uF5laUHG36jDyTOk3xXr2Ahl7m CpAFn36Pi4xRQIM02hpOYHgUzt3KGd4pE8vB/IdCjmEMXxFDiK5533RyJ8Il7z3Gx7gE AqRA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=NdJFjoiW/atX5bteV+PLDwjBGvX9amQkkYKPtpVOFqE=; b=wHwSsYCUayr9VFsH7+yvw7+zWlPV4Y+VnaejrCT5RGGfkOM0Q5ipcygIglHfxSI0Ip KjntcZjEt+KIw3x7WNQMtOP0dHjCvVsIJVOBfXtKb/nn2q5rFjAVQLPqp2Pb6ED+LZIz Be09dSmJa0wscJ+NbSlYH5m6g8sgv5CwIFZX5vjiQzCn+vOm2ThwSv0l+l0FYPrhR3Ha ZGd1qDoPlHB9zKkm7eo3/R+uoPTgId4BQSXREydKWPGi6jurRuMKZCKZ8i1IHlbH+uDj oyPnwkR8SiloTR1FeuG0CI34tsoy86nOj/BNL/qYYf3FSdZwRPKONtVvfM93d/7PA9gL 2o5g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=L+hTERTZ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id n1-20020a17090625c100b007417c6edb0asi18822808ejb.402.2022.10.22.01.38.25; Sat, 22 Oct 2022 01:38:52 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=L+hTERTZ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233698AbiJVIWc (ORCPT + 99 others); Sat, 22 Oct 2022 04:22:32 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43656 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233681AbiJVIUn (ORCPT ); Sat, 22 Oct 2022 04:20:43 -0400 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B03B82DF46A; Sat, 22 Oct 2022 00:58:46 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 16664B82DFA; Sat, 22 Oct 2022 07:41:37 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6252EC433D7; Sat, 22 Oct 2022 07:41:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1666424495; bh=muXk5+zb//UYPKqFzeIirwUDgkQcWmRmo0xZyDuWdZY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=L+hTERTZQICsM2vA6xZLGGfoMIQ6rbYg5N69M/QI7+T2lpNCOD0+mVQ73/I86TmCK NxDNzaXK9/NnUYam2Vb9UfZ6Jw32YM9fZAGm1FSv0v9bxVeyClqXlA1VwhonF6BH9l nlCXIPf28d8touhuIXZRxL5BprYxGTDbpdiLNfPk= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Rik van Riel , Breno Leitao , Petr Mladek , Josh Poimboeuf , stable@kernel.org Subject: [PATCH 5.19 137/717] livepatch: fix race between fork and KLP transition Date: Sat, 22 Oct 2022 09:20:16 +0200 Message-Id: <20221022072439.781084021@linuxfoundation.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20221022072415.034382448@linuxfoundation.org> References: <20221022072415.034382448@linuxfoundation.org> User-Agent: quilt/0.67 MIME-Version: 1.0 X-Spam-Status: No, score=-7.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1747376335633599860?= X-GMAIL-MSGID: =?utf-8?q?1747376335633599860?= From: Rik van Riel commit 747f7a2901174c9afa805dddfb7b24db6f65e985 upstream. The KLP transition code depends on the TIF_PATCH_PENDING and the task->patch_state to stay in sync. On a normal (forward) transition, TIF_PATCH_PENDING will be set on every task in the system, while on a reverse transition (after a failed forward one) first TIF_PATCH_PENDING will be cleared from every task, followed by it being set on tasks that need to be transitioned back to the original code. However, the fork code copies over the TIF_PATCH_PENDING flag from the parent to the child early on, in dup_task_struct and setup_thread_stack. Much later, klp_copy_process will set child->patch_state to match that of the parent. However, the parent's patch_state may have been changed by KLP loading or unloading since it was initially copied over into the child. This results in the KLP code occasionally hitting this warning in klp_complete_transition: for_each_process_thread(g, task) { WARN_ON_ONCE(test_tsk_thread_flag(task, TIF_PATCH_PENDING)); task->patch_state = KLP_UNDEFINED; } Set, or clear, the TIF_PATCH_PENDING flag in the child task depending on whether or not it is needed at the time klp_copy_process is called, at a point in copy_process where the tasklist_lock is held exclusively, preventing races with the KLP code. The KLP code does have a few places where the state is changed without the tasklist_lock held, but those should not cause problems because klp_update_patch_state(current) cannot be called while the current task is in the middle of fork, klp_check_and_switch_task() which is called under the pi_lock, which prevents rescheduling, and manipulation of the patch state of idle tasks, which do not fork. This should prevent this warning from triggering again in the future, and close the race for both normal and reverse transitions. Signed-off-by: Rik van Riel Reported-by: Breno Leitao Reviewed-by: Petr Mladek Acked-by: Josh Poimboeuf Fixes: d83a7cb375ee ("livepatch: change to a per-task consistency model") Cc: stable@kernel.org Signed-off-by: Petr Mladek Link: https://lore.kernel.org/r/20220808150019.03d6a67b@imladris.surriel.com Signed-off-by: Greg Kroah-Hartman --- kernel/livepatch/transition.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) --- a/kernel/livepatch/transition.c +++ b/kernel/livepatch/transition.c @@ -610,9 +610,23 @@ void klp_reverse_transition(void) /* Called from copy_process() during fork */ void klp_copy_process(struct task_struct *child) { - child->patch_state = current->patch_state; - /* TIF_PATCH_PENDING gets copied in setup_thread_stack() */ + /* + * The parent process may have gone through a KLP transition since + * the thread flag was copied in setup_thread_stack earlier. Bring + * the task flag up to date with the parent here. + * + * The operation is serialized against all klp_*_transition() + * operations by the tasklist_lock. The only exception is + * klp_update_patch_state(current), but we cannot race with + * that because we are current. + */ + if (test_tsk_thread_flag(current, TIF_PATCH_PENDING)) + set_tsk_thread_flag(child, TIF_PATCH_PENDING); + else + clear_tsk_thread_flag(child, TIF_PATCH_PENDING); + + child->patch_state = current->patch_state; } /*