{"id":"AZL-109257","summary":"CVE-2026-98797 affecting package kernel 6.6.157.1-1","details":"In the Linux kernel, the following vulnerability has been resolved:\n\nnet: cap skb-\u003equeue_mapping when the tx queue is picked\n\nskbedit can set skb-\u003equeue_mapping and raise the per-CPU skip_txqueue\nflag so __dev_queue_xmit() honours the mapping. __dev_queue_xmit()\ncleared the flag before sch_handle_egress() and only read it afterwards,\nso the flag was not confined to the xmit that set it: a nested xmit\n(mirred redirect or mirror, or a drop after skbedit) could set the flag\nand the outer xmit would consume it for an skb that never went through\nskbedit.\n\nA forwarded packet still carries the ingress NIC's rx_queue + 1 in\nskb-\u003equeue_mapping, so the outer device then indexes its tx queue state\nwith that stale value. Taprio's child array q-\u003eqdiscs[] is sized to the\ndevice's queue count, so taprio_enqueue() indexes past its allocation\nand dereferences the result as a struct Qdisc *.\n\nWe (ab)use the skb-\u003enf_skip_egress which means \"skip netfilter egress\nfor this packet\" to tag to \"am I in tc egress?\". Despite the overload\nI dont see it as a conflict since the marker is set only around the\nsingle sch_handle_egress() call and ingress path is guarded by\ntc_at_ingress.\nI will send a followup(net-next) patch once this hits net-next to\nrename the skb-\u003enf_skip_egress bit/flag to skb-\u003eskip_egress\n\nArm the flag only from the egress classifier that can use it: raise\nskip_txqueue from tcf_skbedit_act() only when it runs inside\nsch_handle_egress(), thanks to skb-\u003enf_skip_egress. An egress qdisc\nclassifier runs in q-\u003eenqueue(), after the tx queue has been picked,\nso a mapping it sets cannot affect the current packet; arming the flag\nthere only pollutes it for a later xmit. Then own the flag for the xmit\nframe the egress hook runs in: save the incoming value and clear it just\nbefore sch_handle_egress(), and restore it after the hook - on the\nconsumed (drop) path, or, in the same call that reads it, on the\nsurviving path. The save and the restores stay inside the\negress_needed_key static branch, so a packet pays for them only when\negress hooks are active (2f1e85b1aee4).\n\nStore the value netdev_cap_txqueue() selected back into skb-\u003equeue_mapping\nin netdev_tx_queue_mapping(), as netdev_core_pick_tx() already does, so\nthe skip_txqueue path never hands a later reader on the xmit path a\nmapping the device cannot serve. A store made still later in the same\nframe, by a tc BPF program attached to a transmit qdisc, is outside this\npath and is not re-capped; a separate followup will resolve that path.\n\nnetdev_xmit_skip_txqueue() returns the previous flag value so the\nsave-and-clear is one call, and a no-op stub is provided when\nCONFIG_NET_EGRESS is disabled. skb-\u003enf_skip_egress is compiled under\nCONFIG_NET_EGRESS rather than CONFIG_NETFILTER_SKIP_EGRESS, so\nskb_at_tc_egress() is valid whenever the egress path is built.\n\nA local user in a network namespace can redirect a packet from a device\nwith more TX queues to one with fewer after setting a mapping valid only\non the larger device. That reaches these reads and, under KASAN, faults\nwith \"slab-out-of-bounds in taprio_enqueue\".\n\nConditions to recreate the bug: the report's own trigger is a local user\nwith CAP_NET_ADMIN in a network namespace, so no eBPF program is needed.\nWith CONFIG_NET_SCH_TAPRIO=y, CONFIG_NET_ACT_SKBEDIT=y,\nCONFIG_NET_ACT_MIRRED=y, CONFIG_NET_CLS_MATCHALL=y,\nCONFIG_NET_SCH_PRIO=y and KASAN enabled, create qa (3 queues), qb\n(2 queues) and qc (1 queue) as dummy devices; put a taprio root on qb\n(num_tc 1, queues 2@0) and clsact on all three; then add an egress\nmatchall filter on every device. On qa: \"action skbedit queue_mapping 2\npipe action mirred egress redirect dev qb\". On qb: \"action mirred egress\nmirror dev qc\". On qc: \"action skbedit queue_mapping 0 pipe\". Send one\npacket out qa. qc's skbedit sets the flag while qb's outer xmit is in\nflight; without the fix qb consumes it and reads its two-entry taprio\nchild array with the forwarded packet's stale mapping. A qc whose\nskb\n---truncated---","modified":"2026-10-19T14:17:06.078635820Z","published":"2026-10-18T16:17:33Z","upstream":["CVE-2026-98797"],"references":[{"type":"WEB","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-98797"}],"affected":[{"package":{"name":"kernel","ecosystem":"Azure Linux:3","purl":"pkg:rpm/azure-linux/kernel"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"6.6.157.1-1"}]}],"database_specific":{"source":"https://github.com/microsoft/AzureLinuxVulnerabilityData/blob/main/osv/AZL-109257.json"}}],"schema_version":"1.9.0"}