Commit fa44042a authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'net_sched-fix-uaf-vulnerability-in-hfsc-qdisc'

Cong Wang says:

====================
net_sched: Fix UAF vulnerability in HFSC qdisc

This patchset contains two bug fixes and a selftest for the first one
which we have a reliable reproducer, please check each patch
description for details.
====================

Link: https://patch.msgid.link/20250417184732.943057-1-xiyou.wangcong@gmail.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents d861a5db 7629d1a0
Loading
Loading
Loading
Loading
+17 −6
Original line number Diff line number Diff line
@@ -961,6 +961,7 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,

	if (cl != NULL) {
		int old_flags;
		int len = 0;

		if (parentid) {
			if (cl->cl_parent &&
@@ -991,9 +992,13 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
		if (usc != NULL)
			hfsc_change_usc(cl, usc, cur_time);

		if (cl->qdisc->q.qlen != 0)
			len = qdisc_peek_len(cl->qdisc);
		/* Check queue length again since some qdisc implementations
		 * (e.g., netem/codel) might empty the queue during the peek
		 * operation.
		 */
		if (cl->qdisc->q.qlen != 0) {
			int len = qdisc_peek_len(cl->qdisc);

			if (cl->cl_flags & HFSC_RSC) {
				if (old_flags & HFSC_RSC)
					update_ed(cl, len);
@@ -1636,10 +1641,16 @@ hfsc_dequeue(struct Qdisc *sch)
		if (cl->qdisc->q.qlen != 0) {
			/* update ed */
			next_len = qdisc_peek_len(cl->qdisc);
			/* Check queue length again since some qdisc implementations
			 * (e.g., netem/codel) might empty the queue during the peek
			 * operation.
			 */
			if (cl->qdisc->q.qlen != 0) {
				if (realtime)
					update_ed(cl, next_len);
				else
					update_d(cl, next_len);
			}
		} else {
			/* the class becomes passive */
			eltree_remove(cl);
+39 −0
Original line number Diff line number Diff line
@@ -313,5 +313,44 @@
            "$TC qdisc del dev $DUMMY handle 1: root",
            "$IP addr del 10.10.10.10/24 dev $DUMMY || true"
        ]
    },
    {
        "id": "a4c3",
        "name": "Test HFSC with netem/blackhole - queue emptying during peek operation",
        "category": [
            "qdisc",
            "hfsc",
            "netem",
            "blackhole"
        ],
        "plugins": {
            "requires": "nsPlugin"
        },
        "setup": [
            "$IP link set dev $DUMMY up || true",
            "$IP addr add 10.10.10.10/24 dev $DUMMY || true",
            "$TC qdisc add dev $DUMMY handle 1:0 root drr",
            "$TC class add dev $DUMMY parent 1:0 classid 1:1 drr",
            "$TC class add dev $DUMMY parent 1:0 classid 1:2 drr",
            "$TC qdisc add dev $DUMMY parent 1:1 handle 2:0 plug limit 1024",
            "$TC qdisc add dev $DUMMY parent 1:2 handle 3:0 hfsc default 1",
            "$TC class add dev $DUMMY parent 3:0 classid 3:1 hfsc rt m1 5Mbit d 10ms m2 10Mbit",
            "$TC qdisc add dev $DUMMY parent 3:1 handle 4:0 netem delay 1ms",
            "$TC qdisc add dev $DUMMY parent 4:1 handle 5:0 blackhole",
            "ping -c 3 -W 0.01 -i 0.001 -s 1 10.10.10.10 -I $DUMMY > /dev/null 2>&1 || true",
            "$TC class change dev $DUMMY parent 3:0 classid 3:1 hfsc sc m1 5Mbit d 10ms m2 10Mbit",
            "$TC class del dev $DUMMY parent 3:0 classid 3:1",
            "$TC class add dev $DUMMY parent 3:0 classid 3:1 hfsc rt m1 5Mbit d 10ms m2 10Mbit",
            "ping -c 3 -W 0.01 -i 0.001 -s 1 10.10.10.10 -I $DUMMY > /dev/null 2>&1 || true"
        ],
        "cmdUnderTest": "$TC class change dev $DUMMY parent 3:0 classid 3:1 hfsc sc m1 5Mbit d 10ms m2 10Mbit",
        "expExitCode": "0",
        "verifyCmd": "$TC -s qdisc show dev $DUMMY",
        "matchPattern": "qdisc hfsc 3:.*parent 1:2.*default 1",
        "matchCount": "1",
        "teardown": [
            "$TC qdisc del dev $DUMMY handle 1:0 root",
            "$IP addr del 10.10.10.10/24 dev $DUMMY || true"
        ]
    }
]