From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4C3DAC18E5B for ; Tue, 17 Mar 2020 11:13:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 2157920658 for ; Tue, 17 Mar 2020 11:13:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1584443609; bh=2gNUVrFf3z0eqzjHAqn4loYBqESHZkwaMZOw7bbK8Vc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=rc9c5z//cPmNqmQrKOxCEAPUN3YnNweKCIM4Zlmv5PMeV/l0jKngNAIZgLmvfBMNV e7EnBoXSA/LcYZZ3DlZZyTmQKX+ruKiEAa0sBmfKGVyk6veY6fdT5+QUzxQ56z88Rz wBvw3e7WRf8AB/3QLaWr9phfsdPeTv8toGelA5g0= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729373AbgCQLN2 (ORCPT ); Tue, 17 Mar 2020 07:13:28 -0400 Received: from mail.kernel.org ([198.145.29.99]:57304 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729344AbgCQLNY (ORCPT ); Tue, 17 Mar 2020 07:13:24 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id C2C322076F; Tue, 17 Mar 2020 11:13:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1584443604; bh=2gNUVrFf3z0eqzjHAqn4loYBqESHZkwaMZOw7bbK8Vc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=sx15Wo48iPMroMJ1znYyIPU0Vx85umINqKnFLOdqd+HV6YMm2qTBy2BQ/ahXuVUz6 Njs0nv+mNdpzG9i3syr25fZrGRnZ+rs2QViunQ/jbrQY2ExYVOSSfvLpFgUPQWqhT9 q6Z5OPM8/OmC6kGkQfGIt+DMjHirHoSaUTJb2Mi0= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Kyle Sanderson , Michael Stapelberg , Miklos Szeredi Subject: [PATCH 5.5 101/151] fuse: fix stack use after return Date: Tue, 17 Mar 2020 11:55:11 +0100 Message-Id: <20200317103333.636383044@linuxfoundation.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200317103326.593639086@linuxfoundation.org> References: <20200317103326.593639086@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Miklos Szeredi commit 3e8cb8b2eaeb22f540f1cbc00cbb594047b7ba89 upstream. Normal, synchronous requests will have their args allocated on the stack. After the FR_FINISHED bit is set by receiving the reply from the userspace fuse server, the originating task may return and reuse the stack frame, resulting in an Oops if the args structure is dereferenced. Fix by setting a flag in the request itself upon initializing, indicating whether it has an asynchronous ->end() callback. Reported-by: Kyle Sanderson Reported-by: Michael Stapelberg Fixes: 2b319d1f6f92 ("fuse: don't dereference req->args on finished request") Cc: # v5.4 Tested-by: Michael Stapelberg Signed-off-by: Miklos Szeredi Signed-off-by: Greg Kroah-Hartman --- fs/fuse/dev.c | 6 +++--- fs/fuse/fuse_i.h | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -276,12 +276,10 @@ static void flush_bg_queue(struct fuse_c void fuse_request_end(struct fuse_conn *fc, struct fuse_req *req) { struct fuse_iqueue *fiq = &fc->iq; - bool async; if (test_and_set_bit(FR_FINISHED, &req->flags)) goto put_request; - async = req->args->end; /* * test_and_set_bit() implies smp_mb() between bit * changing and below intr_entry check. Pairs with @@ -324,7 +322,7 @@ void fuse_request_end(struct fuse_conn * wake_up(&req->waitq); } - if (async) + if (test_bit(FR_ASYNC, &req->flags)) req->args->end(fc, req->args, req->out.h.error); put_request: fuse_put_request(fc, req); @@ -471,6 +469,8 @@ static void fuse_args_to_req(struct fuse req->in.h.opcode = args->opcode; req->in.h.nodeid = args->nodeid; req->args = args; + if (args->end) + __set_bit(FR_ASYNC, &req->flags); } ssize_t fuse_simple_request(struct fuse_conn *fc, struct fuse_args *args) --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -301,6 +301,7 @@ struct fuse_io_priv { * FR_SENT: request is in userspace, waiting for an answer * FR_FINISHED: request is finished * FR_PRIVATE: request is on private list + * FR_ASYNC: request is asynchronous */ enum fuse_req_flag { FR_ISREPLY, @@ -314,6 +315,7 @@ enum fuse_req_flag { FR_SENT, FR_FINISHED, FR_PRIVATE, + FR_ASYNC, }; /**