{
  "affected": [
    {
      "ecosystem_specific": {
        "urgency": "not yet assigned"
      },
      "package": {
        "ecosystem": "Debian:12",
        "name": "linux"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "ecosystem_specific": {
        "urgency": "not yet assigned"
      },
      "package": {
        "ecosystem": "Debian:13",
        "name": "linux"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "6.12.113-1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "ecosystem_specific": {
        "urgency": "not yet assigned"
      },
      "package": {
        "ecosystem": "Debian:14",
        "name": "linux"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "7.2.10-1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "details": "In the Linux kernel, the following vulnerability has been resolved:  net: cap skb-\u003equeue_mapping when the tx queue is picked  skbedit can set skb-\u003equeue_mapping and raise the per-CPU skip_txqueue flag so __dev_queue_xmit() honours the mapping. __dev_queue_xmit() cleared the flag before sch_handle_egress() and only read it afterwards, so the flag was not confined to the xmit that set it: a nested xmit (mirred redirect or mirror, or a drop after skbedit) could set the flag and the outer xmit would consume it for an skb that never went through skbedit.  A forwarded packet still carries the ingress NIC's rx_queue + 1 in skb-\u003equeue_mapping, so the outer device then indexes its tx queue state with that stale value. Taprio's child array q-\u003eqdiscs[] is sized to the device's queue count, so taprio_enqueue() indexes past its allocation and dereferences the result as a struct Qdisc *.  We (ab)use the skb-\u003enf_skip_egress which means \"skip netfilter egress for this packet\" to tag to \"am I in tc egress?\". Despite the overload I dont see it as a conflict since the marker is set only around the single sch_handle_egress() call and ingress path is guarded by tc_at_ingress. I will send a followup(net-next) patch once this hits net-next to rename the skb-\u003enf_skip_egress bit/flag to skb-\u003eskip_egress  Arm the flag only from the egress classifier that can use it: raise skip_txqueue from tcf_skbedit_act() only when it runs inside sch_handle_egress(), thanks to skb-\u003enf_skip_egress. An egress qdisc classifier runs in q-\u003eenqueue(), after the tx queue has been picked, so a mapping it sets cannot affect the current packet; arming the flag there only pollutes it for a later xmit. Then own the flag for the xmit frame the egress hook runs in: save the incoming value and clear it just before sch_handle_egress(), and restore it after the hook - on the consumed (drop) path, or, in the same call that reads it, on the surviving path. The save and the restores stay inside the egress_needed_key static branch, so a packet pays for them only when egress hooks are active (2f1e85b1aee4).  Store the value netdev_cap_txqueue() selected back into skb-\u003equeue_mapping in netdev_tx_queue_mapping(), as netdev_core_pick_tx() already does, so the skip_txqueue path never hands a later reader on the xmit path a mapping the device cannot serve. A store made still later in the same frame, by a tc BPF program attached to a transmit qdisc, is outside this path and is not re-capped; a separate followup will resolve that path.  netdev_xmit_skip_txqueue() returns the previous flag value so the save-and-clear is one call, and a no-op stub is provided when CONFIG_NET_EGRESS is disabled. skb-\u003enf_skip_egress is compiled under CONFIG_NET_EGRESS rather than CONFIG_NETFILTER_SKIP_EGRESS, so skb_at_tc_egress() is valid whenever the egress path is built.  A local user in a network namespace can redirect a packet from a device with more TX queues to one with fewer after setting a mapping valid only on the larger device. That reaches these reads and, under KASAN, faults with \"slab-out-of-bounds in taprio_enqueue\".  Conditions to recreate the bug: the report's own trigger is a local user with CAP_NET_ADMIN in a network namespace, so no eBPF program is needed. With CONFIG_NET_SCH_TAPRIO=y, CONFIG_NET_ACT_SKBEDIT=y, CONFIG_NET_ACT_MIRRED=y, CONFIG_NET_CLS_MATCHALL=y, CONFIG_NET_SCH_PRIO=y and KASAN enabled, create qa (3 queues), qb (2 queues) and qc (1 queue) as dummy devices; put a taprio root on qb (num_tc 1, queues 2@0) and clsact on all three; then add an egress matchall filter on every device. On qa: \"action skbedit queue_mapping 2 pipe action mirred egress redirect dev qb\". On qb: \"action mirred egress mirror dev qc\". On qc: \"action skbedit queue_mapping 0 pipe\". Send one packet out qa. qc's skbedit sets the flag while qb's outer xmit is in flight; without the fix qb consumes it and reads its two-entry taprio child array with the forwarded packet's stale mapping. A qc whose skb ---truncated---",
  "id": "DEBIAN-CVE-2026-98797",
  "modified": "2026-10-19T04:47:30.642250087Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://security-tracker.debian.org/tracker/CVE-2026-98797"
    }
  ],
  "upstream": [
    "CVE-2026-98797"
  ]
}