From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 35E031FF5EC; Wed, 7 May 2025 18:53:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746644026; cv=none; b=ZNBQM5UxfB3Osyll3aMMnYJc0MIh6+H4LNHLihDHDqrEeLEjyopm1wheFO54+BFpAZ5hZnUwPWkcbxcAaKSPM5hdKZOAvLk02isiJY/Fb3YV5ATVk8NWCocYeZnB8Sju6FZXs7UH0c/U2fW1EcGEuvfRwGOkr+MP0DkIIdtFa+Q= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1746644026; c=relaxed/simple; bh=Sakcz5K4/nzFFMt7m2qV3/2SLRK4NnQTd6SPP12du98=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RPNVKwEnzKN/njsYhmkky7DCm4P1K8Ua3QvqRrH7/pAOEEl0DWNbF51AqRYUepkvSKiC9E4kyKS66XqQWHcbbPYK8Uvv8BHESQd0LwRjkvB98tzdskJeEFDLhM4PmLGSgE1dhhjvkKwmBuzEeJqVW8uEHp41PVD94CBuXOyYUNM= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b=AFJ80L6E; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b="AFJ80L6E" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B2D08C4CEEB; Wed, 7 May 2025 18:53:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1746644026; bh=Sakcz5K4/nzFFMt7m2qV3/2SLRK4NnQTd6SPP12du98=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=AFJ80L6EV+MAIeWI9X4uGJSvJzy2YafkPgJQRmQe+3qoKMSSxdeU9DSQ4+PTeItc8 UzPv03ldEAnTYS2RbhiA+IG1Pp33sOoAXaFi7lWcRWj0PWCcVZOCMHR3REwwYoatU7 m77qL4NfAUHriz0ozYKtC/Fi47AVhKNSBcQed6PQ= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Jamal Hadi Salim , Victor Nogueira , Jakub Kicinski , Sasha Levin Subject: [PATCH 6.14 096/183] net_sched: drr: Fix double list add in class with netem as child qdisc Date: Wed, 7 May 2025 20:39:01 +0200 Message-ID: <20250507183828.712794134@linuxfoundation.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250507183824.682671926@linuxfoundation.org> References: <20250507183824.682671926@linuxfoundation.org> User-Agent: quilt/0.68 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-Transfer-Encoding: 8bit 6.14-stable review patch. If anyone has any objections, please let me know. ------------------ From: Victor Nogueira [ Upstream commit f99a3fbf023e20b626be4b0f042463d598050c9a ] As described in Gerrard's report [1], there are use cases where a netem child qdisc will make the parent qdisc's enqueue callback reentrant. In the case of drr, there won't be a UAF, but the code will add the same classifier to the list twice, which will cause memory corruption. In addition to checking for qlen being zero, this patch checks whether the class was already added to the active_list (cl_is_active) before adding to the list to cover for the reentrant case. [1] https://lore.kernel.org/netdev/CAHcdcOm+03OD2j6R0=YHKqmy=VgJ8xEOKuP6c7mSgnp-TEJJbw@mail.gmail.com/ Fixes: 37d9cf1a3ce3 ("sched: Fix detection of empty queues in child qdiscs") Acked-by: Jamal Hadi Salim Signed-off-by: Victor Nogueira Link: https://patch.msgid.link/20250425220710.3964791-2-victor@mojatatu.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- net/sched/sch_drr.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c index c69b999fae171..25b77ed0c1f28 100644 --- a/net/sched/sch_drr.c +++ b/net/sched/sch_drr.c @@ -35,6 +35,11 @@ struct drr_sched { struct Qdisc_class_hash clhash; }; +static bool cl_is_active(struct drr_class *cl) +{ + return !list_empty(&cl->alist); +} + static struct drr_class *drr_find_class(struct Qdisc *sch, u32 classid) { struct drr_sched *q = qdisc_priv(sch); @@ -336,7 +341,6 @@ static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct drr_sched *q = qdisc_priv(sch); struct drr_class *cl; int err = 0; - bool first; cl = drr_classify(skb, sch, &err); if (cl == NULL) { @@ -346,7 +350,6 @@ static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch, return err; } - first = !cl->qdisc->q.qlen; err = qdisc_enqueue(skb, cl->qdisc, to_free); if (unlikely(err != NET_XMIT_SUCCESS)) { if (net_xmit_drop_count(err)) { @@ -356,7 +359,7 @@ static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch, return err; } - if (first) { + if (!cl_is_active(cl)) { list_add_tail(&cl->alist, &q->active); cl->deficit = cl->quantum; } -- 2.39.5