From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from fout-a1-smtp.messagingengine.com (fout-a1-smtp.messagingengine.com [103.168.172.144]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DE3A12F8EA4 for ; Sun, 17 May 2026 14:11:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.144 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779027114; cv=none; b=Ep/8w3V1YJbrrb2sJbY0h1kVzHC01SgrHPqK5MBSf2RK3o6u+uLDw2wevtYX7tP4VB3Nipuk2YVyGnZrWPH5G3vrjBhkv8gE1vhpuLXjGietphhFUEq390cMndUl2WxiH83GLUPeXnTFLhLjmUYSjlkv3dsUv1dCRRQPk7btRm4= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779027114; c=relaxed/simple; bh=z0CorojWAQ2TDCBq+VcoGydBtgXFXdSQWh43lJ7kyYU=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type; b=R5oNz9gHJMlf5YIkMIRmJSqnuIzZz6lGX6RKyBNkDm2ZHSCNa/AQumF92uM/h6/BYgofgVzwtKSDNZngiOTkN4ELXTwY0w9OGma+IhjNtd6kBhff++mdd6EeIu9QSCBVhykn6Zs3vOu3dOVtergFTMObAywhtP07R+9W3qtmC6w= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=bsbernd.com; spf=pass smtp.mailfrom=bsbernd.com; dkim=pass (2048-bit key) header.d=bsbernd.com header.i=@bsbernd.com header.b=exevHgSG; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=iFDP9+7E; arc=none smtp.client-ip=103.168.172.144 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=bsbernd.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bsbernd.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bsbernd.com header.i=@bsbernd.com header.b="exevHgSG"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="iFDP9+7E" Received: from phl-compute-03.internal (phl-compute-03.internal [10.202.2.43]) by mailfout.phl.internal (Postfix) with ESMTP id 94FE5EC0184; Sun, 17 May 2026 10:11:50 -0400 (EDT) Received: from phl-frontend-04 ([10.202.2.163]) by phl-compute-03.internal (MEProxy); Sun, 17 May 2026 10:11:50 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bsbernd.com; h= cc:cc:content-transfer-encoding:content-type:content-type:date :date:from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:subject:subject:to:to; s=fm2; t=1779027110; x=1779113510; bh=WABjwekSEKVVyuNIWTDc3TW39IGvrH+ZYaW8Ssau3cw=; b= exevHgSGeKBMi+mxxYo6KS2dXdAdjO2SPuaUU5e92WgUUoIzB8vLxeWevL4/ddtZ ojyD7v94t+l+PXxPwJORp+rRQTmQYfkKF00o+lNy3+vpVeqT6b0i1mp42pp8Xoot o0rS2Qfl6YGISJRORllrGIEMWTaAAllSo1YheeIl33jOkgjVQEi1IkbyWjU/lmDY Zyc0C9dXdFRIzi1iPipOonk4cPavwn3Z563XibMpIcukmq4r443sAG4X+2n0si7M cqBSoanieC3X/IrEEHN2wOA9Lv6erI9JiQJn0sNGElF+1Uyn+bHxnlRUEPnZdCTx FzpfJKLOO331pq6JgF5klg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:content-type:date:date:feedback-id:feedback-id :from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:subject:subject:to:to:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t=1779027110; x= 1779113510; bh=WABjwekSEKVVyuNIWTDc3TW39IGvrH+ZYaW8Ssau3cw=; b=i FDP9+7E0KdVki93QFuZD09sro283I5STACYpuNsg8PEx4/L3cYM7LXrXegDgAvzx CiahRP3u/Y5QpHW6RJyPv9jPLpUvQUFTL5UiYdqlwIGfs4i8EHAo5Z5tYb7wypaH H6ozj1y5YzqqemJ8C3aegTB8pQfPr3hy5oEKUEK9Q45QaKDfj5dLXYtiK4dqfJJx bEzBlKxESU9TGxj84qlvuLqhkrlWemJhnHmuFbq0YEYGmQO9ALi98Zm/tL6CSjvT ZXduzn7mtAn+8DGaCLLtqyyehvUv57R3wpstfE+bibdD9k9uFJgcyGZvUoyPyTFi zjVJHzO5UeAPnVOx0GEqQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefhedrtddtgddufeeiudelucetufdoteggodetrf dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfurfetoffkrfgpnffqhgenuceu rghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujf gurhepkfffgggfuffvvehfhfgjtgfgsehtjeertddtvdejnecuhfhrohhmpeeuvghrnhgu ucfutghhuhgsvghrthcuoegsvghrnhgusegsshgsvghrnhgurdgtohhmqeenucggtffrrg htthgvrhhnpeetfedtheelgfehheevheetheelhfeujeeitdejvedvvdejtdfgffefhfet hfffveenucffohhmrghinheprghkrgdrmhhsnecuvehluhhsthgvrhfuihiivgeptdenuc frrghrrghmpehmrghilhhfrhhomhepsggvrhhnugessghssggvrhhnugdrtghomhdpnhgs pghrtghpthhtohepkedpmhhouggvpehsmhhtphhouhhtpdhrtghpthhtohepmhgvsegsvg hrkhhotgdrtghomhdprhgtphhtthhopehgrhgvghhkhheslhhinhhugihfohhunhgurght ihhonhdrohhrghdprhgtphhtthhopehmihhklhhoshesshiivghrvgguihdrhhhupdhrtg hpthhtohepshgvtghurhhithihsehkvghrnhgvlhdrohhrghdprhgtphhtthhopehjohgr nhhnvghlkhhoohhnghesghhmrghilhdrtghomhdprhgtphhtthhopehlihhnuhigqdhfuh hsvgesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhigqdhkvghr nhgvlhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehkihhprhgvhiihhi esghhmrghilhdrtghomh X-ME-Proxy: Feedback-ID: i5c2e48a5:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 17 May 2026 10:11:49 -0400 (EDT) Message-ID: <3f1567cf-218e-405b-be7f-e9e9c44205d6@bsbernd.com> Date: Sun, 17 May 2026 16:11:47 +0200 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH 1/2] fuse: io-uring: clear ent->fuse_req in commit_fetch error path To: Berkant Koc , Greg KH , Miklos Szeredi Cc: security@kernel.org, Joanne Koong , linux-fuse@vger.kernel.org, linux-kernel@vger.kernel.org, Zhenghang Xiao References: <20260517095846.fuse-iouring-uaf.dc5f5dbb71dc@berkoc.com> <2026051703-equinox-multitude-91e2@gregkh> <20260517-fuse-uaf-cover@berkoc.com> <20260517-fuse-uaf-patch1@berkoc.com> From: Bernd Schubert Content-Language: fr, en-US, de-DE, ru-RU In-Reply-To: <20260517-fuse-uaf-patch1@berkoc.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit On 5/17/26 14:59, Berkant Koc wrote: > [You don't often get email from me@berkoc.com. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ] > > From: Berkant Koc > > fuse_uring_commit_fetch() locates a request, removes it from the > processing queue, clears req->ring_entry, then calls > fuse_ring_ent_set_commit() under queue->lock. On the error branch > (set_commit returning non-zero because the entry is not in > FRRS_USERSPACE) the function unlocks the queue and ends the request > directly with fuse_request_end(), but it never clears ent->fuse_req. > > ent->fuse_req then keeps pointing at the freed fuse_req while the entry > remains on a queue list. Subsequent teardown via > fuse_uring_entry_teardown() reads ent->fuse_req under queue->lock and > hands the dangling pointer to fuse_uring_stop_fuse_req_end(), which > dereferences it and calls fuse_request_end() a second time on freed > memory. > > Route the error branch through fuse_uring_req_end() instead. That > helper acquires queue->lock, clears ent->fuse_req under the lock, > removes the request from any list it is still on, drops the lock, sets > req->out.h.error, clears FR_SENT and ends the request. The > ent->fuse_req = NULL store under the lock is what closes the window > for the later teardown reader. > > Fixes: c090c8abae4b ("fuse: Add io-uring sqe commit and fetch support") > Cc: stable@vger.kernel.org # 6.14+ > Signed-off-by: Berkant Koc > --- > fs/fuse/dev_uring.c | 4 +--- > 1 file changed, 1 insertion(+), 3 deletions(-) > > diff --git a/fs/fuse/dev_uring.c b/fs/fuse/dev_uring.c > index 7b9822e8837b..7523569ffdce 100644 > --- a/fs/fuse/dev_uring.c > +++ b/fs/fuse/dev_uring.c > @@ -924,9 +924,7 @@ static int fuse_uring_commit_fetch(struct io_uring_cmd *cmd, int issue_flags, > pr_info_ratelimited("qid=%d commit_id %llu state %d", > queue->qid, commit_id, ent->state); > spin_unlock(&queue->lock); > - req->out.h.error = err; > - clear_bit(FR_SENT, &req->flags); > - fuse_request_end(req); > + fuse_uring_req_end(ent, req, err); > return err; > } > > -- > 2.47.3 We already had a security report for that on Friday > > [You don't often get email from kipreyyy@gmail.com. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ] > > fuse_uring_commit_fetch() error path calls fuse_request_end(req) without > clearing ent->fuse_req when fuse_ring_ent_set_commit() fails. The > still-pending fuse_uring_send_in_task() task-work later dereferences the > dangling pointer through fuse_uring_prepare_send(), causing a > use-after-free. > > Clear ent->fuse_req under queue->lock in the error path, matching the > pattern in fuse_uring_req_end(). Add a NULL check in > fuse_uring_send_in_task() so the entry is gracefully recycled if the > request was detached. > > Fixes: c090c8abae4b ("fuse: Add io-uring sqe commit and fetch support") > Signed-off-by: Zhenghang Xiao > --- > fs/fuse/dev_uring.c | 16 ++++++++++++++++ > 1 file changed, 16 insertions(+) > > diff --git a/fs/fuse/dev_uring.c b/fs/fuse/dev_uring.c > index 7b9822e8837b..5e51c36ae2a0 100644 > --- a/fs/fuse/dev_uring.c > +++ b/fs/fuse/dev_uring.c > @@ -921,6 +921,13 @@ static int fuse_uring_commit_fetch(struct io_uring_cmd *cmd, int issue_flags, > > err = fuse_ring_ent_set_commit(ent); > if (err != 0) { > + /* > + * Entry is not in FRRS_USERSPACE state. Clear the > + * back-pointer to prevent the still-pending > + * fuse_uring_send_in_task() from dereferencing a request > + * that is about to be freed. > + */ > + ent->fuse_req = NULL; > pr_info_ratelimited("qid=%d commit_id %llu state %d", > queue->qid, commit_id, ent->state); > spin_unlock(&queue->lock); > @@ -1220,6 +1227,15 @@ static void fuse_uring_send_in_task(struct io_tw_req tw_req, io_tw_token_t tw) > int err; > > if (!tw.cancel) { > + /* > + * If the request was detached (e.g. by fuse_uring_commit_fetch > + * error path), fuse_req will be NULL. Bail out and recycle the > + * entry for the next request. > + */ > + if (!ent->fuse_req) { > + fuse_uring_next_fuse_req(ent, queue, issue_flags); > + return; > + } > err = fuse_uring_prepare_send(ent, ent->fuse_req); > if (err) { > fuse_uring_next_fuse_req(ent, queue, issue_flags); > -- I had already replied to Zhenghang on Friday, I don't think it is enough. This condition > err = fuse_ring_ent_set_commit(ent); > if (err != 0) { can also be triggered by a bad fuse-server / user-space and a teardown race. The tear down race is easy, I think. Fuse-server that wants to trick us is harder, as checking for ent->fuse_req == NULL in fuse_uring_send_in_task() is not enough, the race is valid all over the copy operation (fuse_uring_prepare_send()). I didn't come to it yesterday (was working for main work), going to look into it a bit later today. Thanks, Bernd