Received: by 2002:a05:6830:16d2:b0:61c:ac69:ca1b with SMTP id l18csp2084687otr; Mon, 25 Jul 2022 07:01:24 -0700 (PDT) X-Google-Smtp-Source: AGRyM1t2+rNQ27ZyiZe1+5BnajjprxWSZ0QpeDsqbu5C1WP7ySdAnx0lnjYLVliwi4WZgEeYUtEZ X-Received: by 2002:a05:6402:2741:b0:434:fe8a:1f96 with SMTP id z1-20020a056402274100b00434fe8a1f96mr13707602edd.331.1658757684224; Mon, 25 Jul 2022 07:01:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1658757684; cv=none; d=google.com; s=arc-20160816; b=i96uqXDZOanh8QUB67RkxJD7ad8+p/NVsixRC49GE88X0L/mafDSNFAQL1gQokQRGm 8qfMhYrnMdJDnFfaJQrQv6O0jsBHIPlP8wD3TJIYVsYq58E7zn5hwgyNyu7TiiKpyHIH +FoIWHJpX+a1ys7FF82cgJ95mgeDHkSAdVldH2UqFKhpNqd5li/1GENMTfRElwCEmqA9 9JCWRQUTzk3xLx9JYG7TIH6NtF5E10SxdLYekqR1fsOZf0UPf4NMoQ/XjVuq/N1J52+D FGd920XeJE+7RN9Se6R5VQB8+lnpPNIgrn+POrAS50zd5eAWS2oJEJLTxek1iAyhlEWq 8Q+A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:subject:cc:to:from:date; bh=aXvmKdUJ9iw3rPVCGxOdCB24VKK7CLKbhm8OnXj2rlY=; b=bTsAZUMMt7ORrG6/u7DHONUJT8EnFB7UjD/1o8q8TCXXJX7XSkOk2rUkx4bZn4dRZE Z/QBw4Y7zsbYrzn2SaOYnSA2UWxmw7TvkvupcDcVK4CuTFynwT5XouboSmUNMpIeAvY8 Od+QqmzL2dEQ5d5z94k2ZvQPRjUcerjpTtxTt1qj8pjPqnlor+BDxBgQsDXNd3Y2lLik AN4Di+QYZLfDUj0mEkQUFQgNNfEwv6Nc3ACxljla4HpcUCLZI02DLGOSFRP/DZGFdZB0 6Hydae6DFpJUYGCue7UfW5kwYX8T5HvNh0APW2T8REDdSWS9kQGCcLL7m8Lg65Xu5FQd vpXQ== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id q6-20020a50c346000000b0043bb8332c50si12100358edb.403.2022.07.25.07.00.58; Mon, 25 Jul 2022 07:01:24 -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; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234718AbiGYNtc (ORCPT + 99 others); Mon, 25 Jul 2022 09:49:32 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34692 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232047AbiGYNta (ORCPT ); Mon, 25 Jul 2022 09:49:30 -0400 Received: from shelob.surriel.com (shelob.surriel.com [96.67.55.147]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1DDE5EE3F; Mon, 25 Jul 2022 06:49:29 -0700 (PDT) Received: from [2603:3005:d05:2b00:6e0b:84ff:fee2:98bb] (helo=imladris.surriel.com) by shelob.surriel.com with esmtpsa (TLS1.2) tls TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1oFySW-00085J-5z; Mon, 25 Jul 2022 09:49:20 -0400 Date: Mon, 25 Jul 2022 09:49:19 -0400 From: Rik van Riel To: Petr Mladek Cc: linux-kernel@vger.kernel.org, live-patching@vger.kernel.org, kernel-team@fb.com, Josh Poimboeuf , Jiri Kosina , Miroslav Benes , Joe Lawrence , Breno Leitao Subject: [PATCH v3] livepatch: fix race between fork and klp_reverse_transition Message-ID: <20220725094919.52bcde19@imladris.surriel.com> In-Reply-To: References: <20220720121023.043738bb@imladris.surriel.com> <20220722150106.683f3704@imladris.surriel.com> X-Mailer: Claws Mail 4.0.0 (GTK+ 3.24.31; x86_64-redhat-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Sender: riel@shelob.surriel.com X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE 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 On Mon, 25 Jul 2022 15:32:22 +0200 Petr Mladek wrote: > We should update the commit message and mention also the other > two locations where the state is manipulated without tasklist_lock. > I am sorry that I did not mention it on Friday. Done. Thank you for reviewing this patch so carefully! I had looked at those other places in the code as well, but do not have as complete a picture of the KLP code as you. v2: a better approach, suggested by Petr (thank you) v3: update changelog (thank you Petr) ---8<--- When a KLP fails to apply, klp_reverse_transition will clear the TIF_PATCH_PENDING flag on all tasks, except for newly created tasks which are not on the task list yet. Meanwhile, fork will copy over the TIF_PATCH_PENDING flag from the parent to the child early on, in dup_task_struct -> 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; } This patch will set, or clear, the TIF_PATCH_PENDING flag in the child process 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. Signed-off-by: Rik van Riel Reported-by: Breno Leitao Reviewed-by: Petr Mladek --- kernel/livepatch/transition.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/kernel/livepatch/transition.c b/kernel/livepatch/transition.c index 5d03a2ad1066..30187b1d8275 100644 --- 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; } /* -- 2.35.1