In the Linux kernel, the following vulnerability has been resolved:
net/sched: Restrict conditions for adding duplicating netems to qdisc tree
netem_enqueue's duplication prevention logic breaks when a netem resides in a qdisc tree with other netems - this can lead to a soft lockup and OOM loop in netem_dequeue, as seen in [1]. Ensure that a duplicating netem cannot exist in a tree with other netems.
Previous approaches suggested in discussions in chronological order:
Track duplication status or ttl in the sk_buff struct. Considered too specific a use case to extend such a struct, though this would be a resilient fix and address other previous and potential future DOS bugs like the one described in loopy fun [2].
Restrict netem_enqueue recursion depth like in act_mirred with a per cpu variable. However, netem_dequeue can call enqueue on its child, and the depth restriction could be bypassed if the child is a netem.
Use the same approach as in 2, but add metadata in netem_skb_cb to handle the netem_dequeue case and track a packet's involvement in duplication. This is an overly complex approach, and Jamal notes that the skb cb can be overwritten to circumvent this safeguard.
Prevent the addition of a netem to a qdisc tree if its ancestral path contains a netem. However, filters and actions can cause a packet to change paths when re-enqueued to the root from netem duplication, leading us to the current solution: prevent a duplicating netem from inhabiting the same tree as other netems.
[1] https://lore.kernel.org/netdev/8DuRWwfqjoRDLDmBMlIfbrsZg9Gx50DHJc1ilxsEBNe2D6NMoigR_eIRIG0LOjMc3r10nUUZtArXx4oZBIdUfZQrwjcQhdinnMis_0G7VEk=@willsroot.io/ [2] https://lwn.net/Articles/719297/
| Software | From | Fixed in |
|---|---|---|
| linux / linux_kernel | 2.6.13 | 5.4.297 |
| linux / linux_kernel | 5.5 | 5.10.241 |
| linux / linux_kernel | 5.11 | 5.15.190 |
| linux / linux_kernel | 5.16 | 6.1.148 |
| linux / linux_kernel | 6.2 | 6.6.102 |
| linux / linux_kernel | 6.7 | 6.12.42 |
| linux / linux_kernel | 6.13 | 6.15.10 |
| linux / linux_kernel | 6.16 | 6.16.1 |
| linux / linux_kernel | 2.6.12 | 2.6.12.x |
| debian / debian_linux | 11.0 | 11.0.x |