Received: by 2002:a05:6358:d09b:b0:dc:cd0c:909e with SMTP id jc27csp6219397rwb; Sun, 11 Dec 2022 21:37:29 -0800 (PST) X-Google-Smtp-Source: AA0mqf4eZIYQmL5sqgZsb/kvuBZ01rPDgTT/zsCgUK7HuqbtFMf8gAr8oQ5shiPMk1uC2rujMvVc X-Received: by 2002:a17:90b:d96:b0:221:5897:d46d with SMTP id bg22-20020a17090b0d9600b002215897d46dmr2445124pjb.1.1670823449010; Sun, 11 Dec 2022 21:37:29 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1670823448; cv=none; d=google.com; s=arc-20160816; b=zyXcVj1TpI9tpssOgTiOU3OoZPlLSJ4iW2l2QIZ4sBtWcDxuM305LzltpZX0gAj93U v+FRLYrCJiXz/lyhexD1dcjyCKgh/l/0fj6IT885OKMGSRG22ZNjSImsBSw8wQ4CJYHW e3P+kIX/E6k0DUol9368bkN7lF9WYXyYzKB8M+fFPdacaY7GmGzRTCMkkgtHK2/EEnMa P3UJtzmuqkP1J9ba5FCJVqwTp2zYK8Vj4KSyOkV8CyOSoT8JodTXuVdXyEo4kj/KQhcr FHOpuzwv1d0MA3/X6sRLclU0qB+VTy0F2lWRbXr+/fVBXMPUv1Rfe9wsdICEy01x3f2f ymOg== 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=POf9oeSms+bzfikKu+9Cuok+QbFIm3n9v/2ZXifOcIM=; b=ICnh69hwgtMVBBI57mUc8XkinxktTsMQGDdbYcUR7CI3+Ls7vGRGL4pxQMN+L1Yy68 70ZJ4gUsJPNVL8LHpbf2Te5DUwm/6FArb7+lbQOXTYWoY2K6R3aydS+msM6GnMTWwSch rdMbBiZ9GZ7gJbGJr4r2jL5YLObCAfdknDwlOWQKQRGSqAobA7OYwhB8z79r+AyGsEJ2 Us7GmMu14VzrUPAUIj3sI5gHgscshFPtcQhOPxa6yEfFlPu2mmySPkDERimn6ib5Q0hu e142khgZxxCbcSIoUf3VdrDx7kOaOGNEYf6fX7o8fwKa2Tpw9WHSJ7U5mhLlf1z6zoBE CCaA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@infradead.org header.s=bombadil.20210309 header.b=WiNnPyER; 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 kb5-20020a17090ae7c500b001fe4eebefe5si9729259pjb.135.2022.12.11.21.37.18; Sun, 11 Dec 2022 21:37:28 -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=WiNnPyER; 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 S229666AbiLLFK1 (ORCPT + 78 others); Mon, 12 Dec 2022 00:10:27 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52438 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229379AbiLLFKY (ORCPT ); Mon, 12 Dec 2022 00:10:24 -0500 Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 56EDB95BD for ; Sun, 11 Dec 2022 21:10:20 -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=POf9oeSms+bzfikKu+9Cuok+QbFIm3n9v/2ZXifOcIM=; b=WiNnPyERFUgb+q9NKdxdiFtJHB QYfvR2Z5jWELG4ZSD7IYBSHM0+PKVrf0t79bCI0wpwkbUnXz9UrevRmpJJbnB6TKdDBGtqNgfYeq4 s4VUZGVGJ0gzwkTxud/JbbREtMc7oSTErM+76T/rdJ30pvAuS6znZeSOClW3LAHbm3VVFE51SJHpw xIqfXH4/+mFcd5Y7s+slcFPLSskHOhjDm05cho57/2CluBIqfbcmosWH2wf7LW4MO2bH8Fq89p39H HneXSAmdPhuMFFyp/GvSQwOLONbezUfdqUMAwxXjDfZe8C9mftcUdOph/1EIRuPHBBAM9Or6sKu7U wUJtmqUw==; Received: from mcgrof by bombadil.infradead.org with local (Exim 4.94.2 #2 (Red Hat Linux)) id 1p4b4m-00857G-A5; Mon, 12 Dec 2022 05:10:04 +0000 Date: Sun, 11 Dec 2022 21:10:04 -0800 From: Luis Chamberlain To: Schspa Shi , mingo@redhat.com, peterz@infradead.org, 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 Cc: 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 On Mon, Dec 05, 2022 at 07:38:21PM +0800, Schspa Shi wrote: > > Schspa Shi writes: > > > When the process is killed, wait_for_completion_state will return with > > -ERESTARTSYS, and the completion variable in the stack will be freed. There is no free'ing here, it's just not availabel anymore, which is different. > > If the user-mode thread is complete at the same time, there will be a UAF. > > > > Please refer to the following scenarios. > > T1 T2 > > ------------------------------------------------------------------ > > call_usermodehelper_exec > > call_usermodehelper_exec_async > > << do something >> > > umh_complete(sub_info); > > comp = xchg(&sub_info->complete, NULL); > > /* we got the completion */ > > << context switch >> > > > > << Being killed >> > > retval = wait_for_completion_state(sub_info->complete, state); > > if (!retval) > > goto wait_done; > > > > if (wait & UMH_KILLABLE) { > > /* umh_complete() will see NULL and free sub_info */ > > if (xchg(&sub_info->complete, NULL)) > > goto unlock; > > << we can't got the completion >> I'm sorry I don't understand what you tried to say here, we can't got? > > } > > .... > > unlock: > > helper_unlock(); > > return retval; > > } > > > > /** > > * the completion variable in stack is end of life cycle. > > * and maybe freed due to process is recycled. > > */ > > --------UAF here---------- > > if (comp) > > complete(comp); > > > > To fix it, we can put the completion variable in the subprocess_info > > variable. > > > > Reported-by: syzbot+10d19d528d9755d9af22@syzkaller.appspotmail.com > > Reported-by: syzbot+70d5d5d83d03db2c813d@syzkaller.appspotmail.com > > Reported-by: syzbot+83cb0411d0fcf0a30fc1@syzkaller.appspotmail.com > > > > Signed-off-by: Schspa Shi > > --- > > include/linux/umh.h | 1 + > > kernel/umh.c | 6 +++--- > > 2 files changed, 4 insertions(+), 3 deletions(-) > > > > diff --git a/include/linux/umh.h b/include/linux/umh.h > > index 5d1f6129b847..801f7efbc825 100644 > > --- a/include/linux/umh.h > > +++ b/include/linux/umh.h > > @@ -20,6 +20,7 @@ struct file; > > struct subprocess_info { > > struct work_struct work; > > struct completion *complete; > > + struct completion done; > > const char *path; > > char **argv; > > char **envp; > > diff --git a/kernel/umh.c b/kernel/umh.c > > index 850631518665..3ed39956c777 100644 > > --- a/kernel/umh.c > > +++ b/kernel/umh.c > > @@ -380,6 +380,7 @@ struct subprocess_info *call_usermodehelper_setup(const char *path, char **argv, > > sub_info->cleanup = cleanup; > > sub_info->init = init; > > sub_info->data = data; > > + init_completion(&sub_info->done); > > out: > > return sub_info; > > } > > @@ -405,7 +406,6 @@ EXPORT_SYMBOL(call_usermodehelper_setup); > > int call_usermodehelper_exec(struct subprocess_info *sub_info, int wait) > > { > > unsigned int state = TASK_UNINTERRUPTIBLE; > > - DECLARE_COMPLETION_ONSTACK(done); > > int retval = 0; > > > > if (!sub_info->path) { > > @@ -431,7 +431,7 @@ int call_usermodehelper_exec(struct subprocess_info *sub_info, int wait) > > * This makes it possible to use umh_complete to free > > * the data structure in case of UMH_NO_WAIT. > > */ > > - sub_info->complete = (wait == UMH_NO_WAIT) ? NULL : &done; > > + sub_info->complete = (wait == UMH_NO_WAIT) ? NULL : &sub_info->done; > > sub_info->wait = wait; > > > > queue_work(system_unbound_wq, &sub_info->work); > > @@ -444,7 +444,7 @@ int call_usermodehelper_exec(struct subprocess_info *sub_info, int wait) > > if (wait & UMH_FREEZABLE) > > state |= TASK_FREEZABLE; > > > > - retval = wait_for_completion_state(&done, state); > > + retval = wait_for_completion_state(sub_info->complete, state); > > if (!retval) > > goto wait_done; > > Hi Luis Chamberlain: > > Could you help to review this patch? I'm not sure why we define the > amount of completion here on the stack. But this UAF can be fixed by > moving the completion variable to the heap. It would seem to me that if this is an issue other areas would have similar races as well, so I was hard pressed about the approach / fix. Wouldn't something like this be a bit more explicit about ensuring we don't let the work item race beyond? diff --git a/kernel/umh.c b/kernel/umh.c index 850631518665..55fc698115a7 100644 --- a/kernel/umh.c +++ b/kernel/umh.c @@ -447,6 +447,8 @@ int call_usermodehelper_exec(struct subprocess_info *sub_info, int wait) retval = wait_for_completion_state(&done, state); if (!retval) goto wait_done; + else if (retval == -ERESTARTSYS) + cancel_work_sync(&sub_info->work); if (wait & UMH_KILLABLE) { /* umh_complete() will see NULL and free sub_info */