[PATCH net v3 0/6] net: sched: fix quantum/mtu overflow in fq, fq_codel, sch_codel, fq_pie, hhf, sfq

Jamal Hadi Salim <[email protected]>
Newsgroups org.kernel.vger.netdev,org.kernel.vger.stable
Message-ID <[email protected]>
Several qdiscs derive their per-flow quantum or CoDel mtu from
psched_mtu() without an overflow or zero clamp, which can drive the
dequeue/credit-refill loop into a soft lockup or silently disable the
AQM. [email protected] provided reports and PoCs for the following qdiscs:
sch_fq, sch_fq_codel, sch_fq_pie, sch_hhf, and sch_sfq.

sch_codel was found by inspection for the same pattern. It's TheLinuxWay
(i.e cutnpaste code from somewhere for your new feature) and the AIs
are having a lot of fun finding patterns. We must overcome!

Clamp the quantum (and, for the codel family, the cparams/params mtu)
to a sane range at init/change time so the dequeue loops terminate and
the AQM stays armed. The clamps live in the init/change paths, not the
per-packet fast path, so no hot-path cost is added for a configuration
issue.

This series depends on "net/sched: bound qdisc_pkt_len to prevent qdisc
soft lockup", which caps qdisc_pkt_len() at GSO_MAX_SIZE in
__qdisc_calculate_pkt_len(). That cap closes the fq_codel TCA_STAB
backlog-wrap vector (qdisc_pkt_len inflated to ~1 GiB wrapping the u32
per-flow backlog to 0 and NULL-derefing in fq_codel_drop()); with it
upstream this series no longer needs the fq_codel_drop() hardening hunk
that the earlier respin carried. The five quantum/mtu fixes here are
psched_mtu()-driven and orthogonal to the qdisc_pkt_len() cap.

Q: Why not bound the MTU at the source instead? dummy's max_mtu == 0 is
intentional (dev_validate_mtu() treats 0 as unbounded), other drivers
can legitimately advertise large MTUs, and qdiscs must not trust
psched_mtu() regardless.

Conditions to recreate the bug: a device whose MTU (plus
hard_header_len) wraps 2 * psched_mtu() or psched_mtu() into the sign
bit (e.g. a dummy device with max_mtu == 0 accepting a huge MTU).
Requires CAP_NET_ADMIN in a user namespace.

---
v2 to v3
General: Feeback from Eric and Sashiko and one addtional qdisc from
inspection.
1. Split into one patch per file (Eric Dumazet).
2. Clamp to a range [256, FQ_CODEL_QUANTUM_MAX], not just a lower
   bound, in fq_codel/fq_pie init (Sashiko).
3. Clamp psched_mtu() before multiplying in fq_init() (Sashiko).
4. Move hhf clamp before hhf_change() (Sashiko).
5. Fold fq_codel cparams.mtu clamp: same unclamped psched_mtu() six
   lines below q->quantum disables codel; hoist one clamped mtu.
6. New patch 3: add sch_codel -- same params.mtu issue.
7. Drop the fq_codel_drop() hardening hunk: the qdisc_pkt_len() cap
   in the posted "bound qdisc_pkt_len" dependency closes the TCA_STAB
   backlog wrap at the source, making the empty-flow fallback unreachable.
8. Switch sfq to clamp_t(..., 256, 1 << 20) - all patches now 
   have same pattern.
9. Drop the stale TCA_FQ_INITIAL_QUANTUM narrowing: .max = INT_MAX was
   set deliberately by 7041101ff6c3 and already guarantees f->credit
   stays non-negative; lowering it would reject working configs.

v1 to v2
Changes based on feedback from Eric and Sashikos on V1.

1. Drop the fast-path changes in fq_dequeue() (Eric).
2. Clamp to a range, not just a lower bound (Eric); upper bound 1M
   matches fq_change()'s TCA_FQ_QUANTUM cap, not Eric's 16M.
3. Dropped the TCA_FQ_INITIAL_QUANTUM policy narrowing (see v2 to v3
   note 9 for why).
4. Fold fq_codel_init() quantum clamp (Sashiko).
5. Fold fq_pie_init()/fq_pie_change() quantum clamp (Sashiko).
6. Reword the hhf/sfq comments (Sashiko).

Sashiko links:
  https://sashiko.dev/#/patchset/[email protected]
  https://netdev-ai.bots.linux.dev/sashiko/#/patchset/[email protected]
  https://sashiko.dev/#/patchset/[email protected]
  https://netdev-ai.bots.linux.dev/sashiko/#/patchset/[email protected]

---
Jamal Hadi Salim (6):
  net/sched: fq: add overflow bounds to quantum and initial quantum
  net/sched: fq_codel: clamp default quantum and mtu
  net/sched: sch_codel: clamp default mtu to avoid disabling CoDel
  net/sched: fq_pie: clamp default quantum to avoid signed overflow
  net/sched: hhf: clamp quantum before hhf_change() to avoid overflow
  net/sched: sfq: clamp quantum to avoid signed overflow soft lockup

 net/sched/sch_codel.c    |  2 +-
 net/sched/sch_fq.c       |  6 ++++--
 net/sched/sch_fq_codel.c |  6 ++++--
 net/sched/sch_fq_pie.c   |  3 ++-
 net/sched/sch_hhf.c      |  4 ++++
 net/sched/sch_sfq.c      |  3 ++-
 6 files changed, 17 insertions(+), 7 deletions(-)

--
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.