Received: by 2002:a05:6358:d09b:b0:dc:cd0c:909e with SMTP id jc27csp22887rwb; Wed, 14 Dec 2022 13:26:56 -0800 (PST) X-Google-Smtp-Source: AA0mqf5vYnnr8iR9RZb6QTMvD695KleLiUgPSQidS0gYx79/o+3sXNrjEDYdgUfkKCr9s3JLrQSM X-Received: by 2002:a17:906:1851:b0:7c1:1dc7:8837 with SMTP id w17-20020a170906185100b007c11dc78837mr28010054eje.66.1671053216041; Wed, 14 Dec 2022 13:26:56 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1671053216; cv=none; d=google.com; s=arc-20160816; b=BEjBg4xO6bMU6B8U0/DW4MRVdVNVg1E5s8z1d9Otiwlva5+zCd7GdvzD6RDbIvo17Z dXQFQ9E8WRC5mmaK7AX4Oe7D0nhHnrAb7huy5ptktxpnaKp/C7QYCGCjBSxLyp2RonMP 0Nf9Z2uD4MnyBP+dShTDFME+N+xy3MEip5rWMYchDGJC6nvFEHHaasgYl7DIm/hsgSjY 4o69DUmwSjSZVyOQM6vMdOvMMKnSdCh7Z4+gnaW+hCJ7pG416uwSGU1MFO4MJX2egczq N+VlmbMb0UaSQreoZGDlb0N2dRppDy8tBbqwoXvnQZDyPaEv6jVFAGG0RVMuSij5266D qbMg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:in-reply-to:content-disposition :mime-version:references:message-id:subject:cc:to:from:date :dkim-signature; bh=D4mbWoI/BMsxaMSLndE9NzSrR7QAr2JilFiw1m28l/E=; b=vBnVanOIHQgEhW5C/lJ5p1hXnkImMsVMqsqhvd8J3YWZm737/0257EojIR9QIqxxks 6BiJJYbJ2rnU1gdciNcfdGZFeUvv8RdO8CxC6SxLizf+7bgQN4vYkc7pRKm8PHGtAT9r EvjKGiloCEoXaWtWd4ObQLYIKq0q1UZ2uJr68UW5fbcIYi8yfEz8u3SIYUSTmpnn7/a5 MPFg3xdsI2G2SF6+Xu0wjhpp4hAvy+feH6qNGFW52R6aCE+B8n+XqNJKzFnUlf1KTAfA hBmX9VeQWZesw8PELU2o80dzttlKU6DOsDO0lQ+pY44i+riTS+87H3GQWJl48nQSvPgJ RoBQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@infradead.org header.s=bombadil.20210309 header.b="FH/mTlfj"; 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=kernel.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id hv22-20020a17090760d600b007c1247d65a8si12864631ejc.687.2022.12.14.13.26.39; Wed, 14 Dec 2022 13:26:56 -0800 (PST) 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=@infradead.org header.s=bombadil.20210309 header.b="FH/mTlfj"; 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=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229819AbiLNUE0 (ORCPT + 69 others); Wed, 14 Dec 2022 15:04:26 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35702 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229744AbiLNUDk (ORCPT ); Wed, 14 Dec 2022 15:03:40 -0500 Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 38C182ED42 for ; Wed, 14 Dec 2022 11:58:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20210309; h=Sender:In-Reply-To:Content-Type: MIME-Version:References:Message-ID:Subject:Cc:To:From:Date:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description; bh=D4mbWoI/BMsxaMSLndE9NzSrR7QAr2JilFiw1m28l/E=; b=FH/mTlfjS7KPLhJKuJ5YOFmSqd R6yFovbOxTsT717WdxIUe0ntmN9V5tF3bQoEe/l1FXtwPM+HqM8Ayk7DB114Hn3NYcbfoZUr22y91 GANrMH9Wr7tM1cA/UKHCuruxbTgMWUgKYD00AWfqOEBRXfd/Pr4z9Z8uS5wlfZR9fD/8K7drcKMiS jr/RpYkPJ0rA34kx38DtvUPw5Y5J7b+ABfgsAWYhaxHR6wCWSShbHSuNExJX9yXCthlIDL0PONKKG M8BCnFmUMZolbnVbNPDASsfsA8cbcIDsgbPOiOnfW5RQz5OnhjneTVsa5wP3JVncG0CqWt9YlNCi3 rBDex6cA==; Received: from mcgrof by bombadil.infradead.org with local (Exim 4.94.2 #2 (Red Hat Linux)) id 1p5Xt8-002O5K-Oy; Wed, 14 Dec 2022 19:57:58 +0000 Date: Wed, 14 Dec 2022 11:57:58 -0800 From: Luis Chamberlain To: Schspa Shi , mingo@redhat.com, peterz@infradead.org, rostedt@goodmis.org Cc: juri.lelli@redhat.com, vincent.guittot@linaro.org, dietmar.eggemann@arm.com, rostedt@goodmis.org, bsegall@google.com, mgorman@suse.de, bristot@redhat.com, vschneid@redhat.com, linux-kernel@vger.kernel.org, syzbot+10d19d528d9755d9af22@syzkaller.appspotmail.com, syzbot+70d5d5d83d03db2c813d@syzkaller.appspotmail.com, syzbot+83cb0411d0fcf0a30fc1@syzkaller.appspotmail.com Subject: Re: [PATCH] umh: fix UAF when the process is being killed Message-ID: References: <20221115140233.21981-1-schspa@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: Sender: Luis Chamberlain X-Spam-Status: No, score=-4.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_EF,HEADER_FROM_DIFFERENT_DOMAINS, RCVD_IN_DNSWL_MED,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 Peter, Ingo, Steven would like you're review. On Tue, Dec 13, 2022 at 03:03:53PM -0800, Luis Chamberlain wrote: > On Mon, Dec 12, 2022 at 09:38:31PM +0800, Schspa Shi wrote: > > I'd like to upload a V2 patch with the new solution if you prefer the > > following way. > > > > diff --git a/kernel/umh.c b/kernel/umh.c > > index 850631518665..8023f11fcfc0 100644 > > --- a/kernel/umh.c > > +++ b/kernel/umh.c > > @@ -452,6 +452,11 @@ int call_usermodehelper_exec(struct subprocess_info *sub_info, int wait) > > /* umh_complete() will see NULL and free sub_info */ > > if (xchg(&sub_info->complete, NULL)) > > goto unlock; > > + /* > > + * kthreadd (or new kernel thread) will call complete() > > + * shortly. > > + */ > > + wait_for_completion(&done); > > } > > Yes much better. Did you verify it fixes the splat found by the bots? Wait, I'm not sure yet why this would fix it... I first started thinking that this may be a good example of a Coccinelle SmPL rule, something like: DECLARE_COMPLETION_ONSTACK(done); foo *foo; ... foo->completion = &done; ... queue_work(system_unbound_wq, &foo->work); .... ret = wait_for_completion_state(&done, state); ... if (!ret) S ... +wait_for_completion(&done); But that is pretty complex, and while it may be useful to know how many patterns we have like this, it begs the question if generalizing this inside the callers is best for -ERESTARTSYS condition is best. What do folks think? The rationale here is that if you queue stuff and give access to the completion variable but its on-stack obviously you can end up with the queued stuff complete() on a on-stack variable. The issue seems to be that wait_for_completion_state() for -ERESTARTSYS still means that the already scheduled queue'd work is *about* to run and the process with the completion on-stack completed. So we race with the end of the routine and the completion on-stack. It makes me wonder if wait_for_completion() above really is doing something more, if it is just helping with timing and is still error prone. The queued work will try the the completion as follows: static void umh_complete(struct subprocess_info *sub_info) { struct completion *comp = xchg(&sub_info->complete, NULL); /* * See call_usermodehelper_exec(). If xchg() returns NULL * we own sub_info, the UMH_KILLABLE caller has gone away * or the caller used UMH_NO_WAIT. */ if (comp) complete(comp); else call_usermodehelper_freeinfo(sub_info); } So the race is getting -ERESTARTSYS on the process with completion on-stack and the above running complete(comp). Why would sprinkling wait_for_completion(&done) *after* wait_for_completion_state(&done, state) fix this UAF? } diff --git a/kernel/sched/completion.c b/kernel/sched/completion.c index d57a5c1c1cd9..aa7031faca04 100644 --- a/kernel/sched/completion.c +++ b/kernel/sched/completion.c @@ -205,8 +205,10 @@ int __sched wait_for_completion_interruptible(struct completion *x) { long t = wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_INTERRUPTIBLE); - if (t == -ERESTARTSYS) + if (t == -ERESTARTSYS) { + wait_for_completion(x); return t; + } return 0; } EXPORT_SYMBOL(wait_for_completion_interruptible); @@ -243,8 +245,10 @@ int __sched wait_for_completion_killable(struct completion *x) { long t = wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_KILLABLE); - if (t == -ERESTARTSYS) + if (t == -ERESTARTSYS) { + wait_for_completion(x); return t; + } return 0; } EXPORT_SYMBOL(wait_for_completion_killable); @@ -253,8 +257,10 @@ int __sched wait_for_completion_state(struct completion *x, unsigned int state) { long t = wait_for_common(x, MAX_SCHEDULE_TIMEOUT, state); - if (t == -ERESTARTSYS) + if (t == -ERESTARTSYS) { + wait_for_completion(x); return t; + } return 0; } EXPORT_SYMBOL(wait_for_completion_state);