CVE-2022-48644

Source
https://cve.org/CVERecord?id=CVE-2022-48644
Import Source
https://storage.googleapis.com/osv-test-cve-osv-conversion/osv-output/CVE-2022-48644.json
JSON Data
https://api.test.osv.dev/v1/vulns/CVE-2022-48644
Downstream
Related
Published
2024-04-28T13:00:07.584Z
Modified
2026-03-20T12:21:39.080295Z
Summary
net/sched: taprio: avoid disabling offload when it was never enabled
Details

In the Linux kernel, the following vulnerability has been resolved:

net/sched: taprio: avoid disabling offload when it was never enabled

In an incredibly strange API design decision, qdisc->destroy() gets called even if qdisc->init() never succeeded, not exclusively since commit 87b60cfacf9f ("netsched: fix error recovery at qdisc creation"), but apparently also earlier (in the case of qdisccreate_dflt()).

The taprio qdisc does not fully acknowledge this when it attempts full offload, because it starts off with q->flags = TAPRIOFLAGSINVALID in taprioinit(), then it replaces q->flags with TCATAPRIOATTRFLAGS parsed from netlink (in tapriochange(), tail called from taprioinit()).

But in tapriodestroy(), we call tapriodisableoffload(), and this determines what to do based on FULLOFFLOADISENABLED(q->flags).

But looking at the implementation of FULLOFFLOADISENABLED() (a bitwise check of bit 1 in q->flags), it is invalid to call this macro on q->flags when it contains TAPRIOFLAGSINVALID, because that is set to U32MAX, and therefore FULLOFFLOADIS_ENABLED() will return true on an invalid set of flags.

As a result, it is possible to crash the kernel if user space forces an error between setting q->flags = TAPRIOFLAGSINVALID, and the calling of taprioenableoffload(). This is because drivers do not expect the offload to be disabled when it was never enabled.

The error that we force here is to attach taprio as a non-root qdisc, but instead as child of an mqprio root qdisc:

$ tc qdisc add dev swp0 root handle 1: \ mqprio numtc 8 map 0 1 2 3 4 5 6 7 \ queues 1@0 1@1 1@2 1@3 1@4 1@5 1@6 1@7 hw 0 $ tc qdisc replace dev swp0 parent 1:1 \ taprio numtc 8 map 0 1 2 3 4 5 6 7 \ queues 1@0 1@1 1@2 1@3 1@4 1@5 1@6 1@7 base-time 0 \ sched-entry S 0x7f 990000 sched-entry S 0x80 100000 \ flags 0x0 clockid CLOCKTAI Unable to handle kernel paging request at virtual address fffffffffffffff8 [fffffffffffffff8] pgd=0000000000000000, p4d=0000000000000000 Internal error: Oops: 96000004 [#1] PREEMPT SMP Call trace: tapriodump+0x27c/0x310 vsc9959portsetuptc+0x1f4/0x460 felixportsetuptc+0x24/0x3c dsaslavesetuptc+0x54/0x27c tapriodisableoffload.isra.0+0x58/0xe0 tapriodestroy+0x80/0x104 qdisccreate+0x240/0x470 tcmodifyqdisc+0x1fc/0x6b0 rtnetlinkrcvmsg+0x12c/0x390 netlinkrcvskb+0x5c/0x130 rtnetlinkrcv+0x1c/0x2c

Fix this by keeping track of the operations we made, and undo the offload only if we actually did it.

I've added "bool offloaded" inside a 4 byte hole between "int clockid" and "atomic64t picosper_byte". Now the first cache line looks like below:

$ pahole -C tapriosched net/sched/schtaprio.o struct taprio_sched { struct Qdisc * * qdiscs; /* 0 8 / struct Qdisc * root; / 8 8 / u32 flags; / 16 4 / enum tkoffsets tkoffset; / 20 4 / int clockid; / 24 4 / bool offloaded; / 28 1 */

    /* XXX 3 bytes hole, try to pack */

    atomic64_t                 picos_per_byte;       /*    32     0 */

    /* XXX 8 bytes hole, try to pack */

    spinlock_t                 current_entry_lock;   /*    40     0 */

    /* XXX 8 bytes hole, try to pack */

    struct sched_entry *       current_entry;        /*    48     8 */
    struct sched_gate_list *   oper_sched;           /*    56     8 */
    /* --- cacheline 1 boundary (64 bytes) --- */
Database specific
{
    "cna_assigner": "Linux",
    "osv_generated_from": "https://github.com/CVEProject/cvelistV5/tree/main/cves/2022/48xxx/CVE-2022-48644.json"
}
References

Affected packages

Git / git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git

Affected ranges

Type
GIT
Repo
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
Events
Introduced
9c66d15646760eb8982242b4531c4d4fd36118fd
Fixed
d12a1eb07003e597077329767c6aa86a7e972c76
Fixed
586def6ebed195f3594a4884f7c5334d0e1ad1bb
Fixed
f58e43184226e5e9662088ccf1389e424a3a4cbd
Fixed
c7c9c7eb305ab8b4e93e4e4e1b78d8cfcbc26323
Fixed
db46e3a88a09c5cf7e505664d01da7238cd56c92

Database specific

source
"https://storage.googleapis.com/osv-test-cve-osv-conversion/osv-output/CVE-2022-48644.json"