From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 582B951476F; Wed, 30 Sep 2026 17:24:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790789077; cv=none; b=IMmCy+6dNJURZw++MTr77uYJFHSY27clsMf7RsZSp/sBRoMrDLtVxptcuRIJlSaEnZGhipJ2zjG6qJSETllZWltqhsnnm+UvCL11jhpuDczxFC9dq41i4xAr/8SOe6As5KMHPGyJR07zbt3DCgEtQ7I6zE7XSg4P7GcR7ovqw20= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790789077; c=relaxed/simple; bh=futcTsCZOPArNohmIF6YyPUnEIrccfpQPVM0U5eT8Jo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=bqtiKlH2y1nuQq5aS9oj1q2zHxHc2Ph7vzGohKIo3Gbwrcg2czA026WQyi4LchUyfkfbZcqfvfRFptMguGmyNPMbY6fcJKNjvfKvaCFhcZPgFVC7bSgNMbLxYgZkNWplrqJA/QlLtbA40WVeMsm4vb5pf1tOghF1Cq+3Rdw2BBo= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b=LTwZ4FkN; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b="LTwZ4FkN" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B2BFA1F000FF; Wed, 30 Sep 2026 17:24:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1790789076; bh=aQfS1ZNDcXWJ13itNGTtnRvFN+bZxFWhMu83Es60XLE=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=LTwZ4FkN7XRSIAg/dTk/GIAka/rBu3J8y3UhMSu5wivB2i6HiZZWp3DRyIbvbbLXH 9d2/Wsi3Sn1Sw+BoIesUQ5bjNOGEaucBM6sOx9dzxxk/i2SorcSMv5snBMCgyDFEJE 4xq+yq71TDJ43zCagOTCdrgdkTD0BrcvYSMBfpD8= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, =?UTF-8?q?J=C3=A9r=C3=A9my=20Jean?= , Pablo Neira Ayuso , Sasha Levin Subject: [PATCH 6.12 348/877] netfilter: flowtable: publish HW_DEAD after worker is done Date: Wed, 30 Sep 2026 17:20:59 +0200 Message-ID: <20260930152422.181158986@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260930152414.738996857@linuxfoundation.org> References: <20260930152414.738996857@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore Precedence: bulk X-Mailing-List: patches@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 6.12-stable review patch. If anyone has any objections, please let me know. ------------------ From: Jérémy Jean [ Upstream commit d644b23afe1ef509c9961a6d84a093c2587edf02 ] flow_offload_work_del() sets NF_FLOW_HW_DEAD before the work handler clears NF_FLOW_HW_PENDING. Once a flow is both HW_DYING and HW_DEAD, a concurrent garbage collection pass can remove it and schedule it for RCU freeing. The offload worker holds neither an RCU read lock nor a reference to the flow. If it is preempted after publishing HW_DEAD, the RCU callback can free the flow before the worker resumes and clears HW_PENDING, resulting in a use-after-free. Move HW_DEAD publication to the common worker epilogue after the pending bit is cleared, making it the final flow access by destroy work. Order all preceding flow accesses before publishing the bit that allows garbage collection to free the object. Fixes: 2c8897953f3b ("netfilter: flowtable: Add pending bit for offload work") Assisted-by: Codex:gpt-5 Signed-off-by: Jérémy Jean Signed-off-by: Pablo Neira Ayuso Signed-off-by: Sasha Levin --- net/netfilter/nf_flow_table_offload.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/net/netfilter/nf_flow_table_offload.c b/net/netfilter/nf_flow_table_offload.c index 4f346f51d7d74..8e3edc7c37b38 100644 --- a/net/netfilter/nf_flow_table_offload.c +++ b/net/netfilter/nf_flow_table_offload.c @@ -993,7 +993,6 @@ static void flow_offload_work_del(struct flow_offload_work *offload) flow_offload_tuple_del(offload, FLOW_OFFLOAD_DIR_ORIGINAL); if (test_bit(NF_FLOW_HW_BIDIRECTIONAL, &offload->flow->flags)) flow_offload_tuple_del(offload, FLOW_OFFLOAD_DIR_REPLY); - set_bit(NF_FLOW_HW_DEAD, &offload->flow->flags); } static void flow_offload_tuple_stats(struct flow_offload_work *offload, @@ -1057,6 +1056,12 @@ static void flow_offload_work_handler(struct work_struct *work) } clear_bit(NF_FLOW_HW_PENDING, &offload->flow->flags); + if (offload->cmd == FLOW_CLS_DESTROY) { + /* Publish after the worker's last flow access. */ + smp_mb__before_atomic(); + set_bit(NF_FLOW_HW_DEAD, &offload->flow->flags); + } + kfree(offload); } -- 2.53.0