[PATCH net] net/sched: ets: fix divide by zero in the offload path
Subsystems:
networking [general] , tc subsystem , the rest
STALE155d
6 messages,
4 authors,
2026-02-27
· open the first message on its own page
Offloading ETS requires computing each class' WRR weight: this is done by
averaging over the sums of quanta as 'q_sum' and 'q_psum'. Using unsigned
int, the same integer size as the individual DRR quanta, can overflow and
even cause division by zero, like it happened in the following splat:
Oops: divide error: 0000 [#1] SMP PTI
CPU: 13 UID: 0 PID: 487 Comm: tc Tainted: G E 6.19.0-virtme #45 PREEMPT(full)
Tainted: [E]=UNSIGNED_MODULE
Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
RIP: 0010:ets_offload_change+0x11f/0x290 [sch_ets]
Code: e4 45 31 ff eb 03 41 89 c7 41 89 cb 89 ce 83 f9 0f 0f 87 b7 00 00 00 45 8b 08 31 c0 45 01 cc 45 85 c9 74 09 41 6b c4 64 31 d2 <41> f7 f2 89 c2 44 29 fa 45 89 df 41 83 fb 0f 0f 87 c7 00 00 00 44
RSP: 0018:ffffd0a180d77588 EFLAGS: 00010246
RAX: 00000000ffffff38 RBX: ffff8d3d482ca000 RCX: 0000000000000000
RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffd0a180d77660
RBP: ffffd0a180d77690 R08: ffff8d3d482ca2d8 R09: 00000000fffffffe
R10: 0000000000000000 R11: 0000000000000000 R12: 00000000fffffffe
R13: ffff8d3d472f2000 R14: 0000000000000003 R15: 0000000000000000
FS: 00007f440b6c2740(0000) GS:ffff8d3dc9803000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 000000003cdd2000 CR3: 0000000007b58002 CR4: 0000000000172ef0
Call Trace:
<TASK>
ets_qdisc_change+0x870/0xf40 [sch_ets]
qdisc_create+0x12b/0x540
tc_modify_qdisc+0x6d7/0xbd0
rtnetlink_rcv_msg+0x168/0x6b0
netlink_rcv_skb+0x5c/0x110
netlink_unicast+0x1d6/0x2b0
netlink_sendmsg+0x22e/0x470
____sys_sendmsg+0x38a/0x3c0
___sys_sendmsg+0x99/0xe0
__sys_sendmsg+0x8a/0xf0
do_syscall_64+0x111/0xf80
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f440b81c77e
Code: 4d 89 d8 e8 d4 bc 00 00 4c 8b 5d f8 41 8b 93 08 03 00 00 59 5e 48 83 f8 fc 74 11 c9 c3 0f 1f 80 00 00 00 00 48 8b 45 10 0f 05 <c9> c3 83 e2 39 83 fa 08 75 e7 e8 13 ff ff ff 0f 1f 00 f3 0f 1e fa
RSP: 002b:00007fff951e4c10 EFLAGS: 00000202 ORIG_RAX: 000000000000002e
RAX: ffffffffffffffda RBX: 0000000000481820 RCX: 00007f440b81c77e
RDX: 0000000000000000 RSI: 00007fff951e4cd0 RDI: 0000000000000003
RBP: 00007fff951e4c20 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000202 R12: 00007fff951f4fa8
R13: 00000000699ddede R14: 00007f440bb01000 R15: 0000000000486980
</TASK>
Modules linked in: sch_ets(E) netdevsim(E)
---[ end trace 0000000000000000 ]---
RIP: 0010:ets_offload_change+0x11f/0x290 [sch_ets]
Code: e4 45 31 ff eb 03 41 89 c7 41 89 cb 89 ce 83 f9 0f 0f 87 b7 00 00 00 45 8b 08 31 c0 45 01 cc 45 85 c9 74 09 41 6b c4 64 31 d2 <41> f7 f2 89 c2 44 29 fa 45 89 df 41 83 fb 0f 0f 87 c7 00 00 00 44
RSP: 0018:ffffd0a180d77588 EFLAGS: 00010246
RAX: 00000000ffffff38 RBX: ffff8d3d482ca000 RCX: 0000000000000000
RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffd0a180d77660
RBP: ffffd0a180d77690 R08: ffff8d3d482ca2d8 R09: 00000000fffffffe
R10: 0000000000000000 R11: 0000000000000000 R12: 00000000fffffffe
R13: ffff8d3d472f2000 R14: 0000000000000003 R15: 0000000000000000
FS: 00007f440b6c2740(0000) GS:ffff8d3dc9803000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 000000003cdd2000 CR3: 0000000007b58002 CR4: 0000000000172ef0
Kernel panic - not syncing: Fatal exception
Kernel Offset: 0x30000000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff)
---[ end Kernel panic - not syncing: Fatal exception ]---
Fix this using 64-bit integers for 'q_sum' and 'q_psum'.
Cc: stable@vger.kernel.org
Fixes: d35eb52bd2ac ("net: sch_ets: Make the ETS qdisc offloadable")
Signed-off-by: Davide Caratti <redacted>
---
net/sched/sch_ets.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/net/sched/sch_ets.c b/net/sched/sch_ets.c
index 306e046276d4..a4b07b661b77 100644
--- a/net/sched/sch_ets.c
+++ b/net/sched/sch_ets.c @@ -115,12 +115,12 @@ static void ets_offload_change(struct Qdisc *sch)
struct ets_sched * q = qdisc_priv ( sch );
struct tc_ets_qopt_offload qopt ;
unsigned int w_psum_prev = 0 ;
- unsigned int q_psum = 0 ;
- unsigned int q_sum = 0 ;
unsigned int quantum ;
unsigned int w_psum ;
unsigned int weight ;
unsigned int i ;
+ u64 q_psum = 0 ;
+ u64 q_sum = 0 ;
if ( ! tc_can_offload ( dev ) || ! dev -> netdev_ops -> ndo_setup_tc )
return ; @@ -138,8 +138,12 @@ static void ets_offload_change(struct Qdisc *sch)
for ( i = 0 ; i < q -> nbands ; i ++ ) {
quantum = q -> classes [ i ]. quantum ;
- q_psum += quantum ;
- w_psum = quantum ? q_psum * 100 / q_sum : 0 ;
+ if ( quantum ) {
+ q_psum += quantum ;
+ w_psum = div64_u64 ( q_psum * 100 , q_sum );
+ } else {
+ w_psum = 0 ;
+ }
weight = w_psum - w_psum_prev ;
w_psum_prev = w_psum ;
--
2.52.0
Hi Davide,
On Tue, Feb 24, 2026 at 3:30 PM Davide Caratti [off-list ref] wrote:
Offloading ETS requires computing each class' WRR weight: this is done by
averaging over the sums of quanta as 'q_sum' and 'q_psum'. Using unsigned
int, the same integer size as the individual DRR quanta, can overflow and
even cause division by zero, like it happened in the following splat:
Was there a setup/test that resulted in the splat? It would be nice if
you could document it.
The fix looks good, so:
Reviewed-by: Jamal Hadi Salim <jhs@mojatatu.com>
cheers,
jamal
quoted hunk Oops: divide error: 0000 [#1] SMP PTI
CPU: 13 UID: 0 PID: 487 Comm: tc Tainted: G E 6.19.0-virtme #45 PREEMPT(full)
Tainted: [E]=UNSIGNED_MODULE
Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
RIP: 0010:ets_offload_change+0x11f/0x290 [sch_ets]
Code: e4 45 31 ff eb 03 41 89 c7 41 89 cb 89 ce 83 f9 0f 0f 87 b7 00 00 00 45 8b 08 31 c0 45 01 cc 45 85 c9 74 09 41 6b c4 64 31 d2 <41> f7 f2 89 c2 44 29 fa 45 89 df 41 83 fb 0f 0f 87 c7 00 00 00 44
RSP: 0018:ffffd0a180d77588 EFLAGS: 00010246
RAX: 00000000ffffff38 RBX: ffff8d3d482ca000 RCX: 0000000000000000
RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffd0a180d77660
RBP: ffffd0a180d77690 R08: ffff8d3d482ca2d8 R09: 00000000fffffffe
R10: 0000000000000000 R11: 0000000000000000 R12: 00000000fffffffe
R13: ffff8d3d472f2000 R14: 0000000000000003 R15: 0000000000000000
FS: 00007f440b6c2740(0000) GS:ffff8d3dc9803000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 000000003cdd2000 CR3: 0000000007b58002 CR4: 0000000000172ef0
Call Trace:
<TASK>
ets_qdisc_change+0x870/0xf40 [sch_ets]
qdisc_create+0x12b/0x540
tc_modify_qdisc+0x6d7/0xbd0
rtnetlink_rcv_msg+0x168/0x6b0
netlink_rcv_skb+0x5c/0x110
netlink_unicast+0x1d6/0x2b0
netlink_sendmsg+0x22e/0x470
____sys_sendmsg+0x38a/0x3c0
___sys_sendmsg+0x99/0xe0
__sys_sendmsg+0x8a/0xf0
do_syscall_64+0x111/0xf80
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f440b81c77e
Code: 4d 89 d8 e8 d4 bc 00 00 4c 8b 5d f8 41 8b 93 08 03 00 00 59 5e 48 83 f8 fc 74 11 c9 c3 0f 1f 80 00 00 00 00 48 8b 45 10 0f 05 <c9> c3 83 e2 39 83 fa 08 75 e7 e8 13 ff ff ff 0f 1f 00 f3 0f 1e fa
RSP: 002b:00007fff951e4c10 EFLAGS: 00000202 ORIG_RAX: 000000000000002e
RAX: ffffffffffffffda RBX: 0000000000481820 RCX: 00007f440b81c77e
RDX: 0000000000000000 RSI: 00007fff951e4cd0 RDI: 0000000000000003
RBP: 00007fff951e4c20 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000202 R12: 00007fff951f4fa8
R13: 00000000699ddede R14: 00007f440bb01000 R15: 0000000000486980
</TASK>
Modules linked in: sch_ets(E) netdevsim(E)
---[ end trace 0000000000000000 ]---
RIP: 0010:ets_offload_change+0x11f/0x290 [sch_ets]
Code: e4 45 31 ff eb 03 41 89 c7 41 89 cb 89 ce 83 f9 0f 0f 87 b7 00 00 00 45 8b 08 31 c0 45 01 cc 45 85 c9 74 09 41 6b c4 64 31 d2 <41> f7 f2 89 c2 44 29 fa 45 89 df 41 83 fb 0f 0f 87 c7 00 00 00 44
RSP: 0018:ffffd0a180d77588 EFLAGS: 00010246
RAX: 00000000ffffff38 RBX: ffff8d3d482ca000 RCX: 0000000000000000
RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffd0a180d77660
RBP: ffffd0a180d77690 R08: ffff8d3d482ca2d8 R09: 00000000fffffffe
R10: 0000000000000000 R11: 0000000000000000 R12: 00000000fffffffe
R13: ffff8d3d472f2000 R14: 0000000000000003 R15: 0000000000000000
FS: 00007f440b6c2740(0000) GS:ffff8d3dc9803000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 000000003cdd2000 CR3: 0000000007b58002 CR4: 0000000000172ef0
Kernel panic - not syncing: Fatal exception
Kernel Offset: 0x30000000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff)
---[ end Kernel panic - not syncing: Fatal exception ]---
Fix this using 64-bit integers for 'q_sum' and 'q_psum'.
Cc: stable@vger.kernel.org
Fixes: d35eb52bd2ac ("net: sch_ets: Make the ETS qdisc offloadable")
Signed-off-by: Davide Caratti <redacted>
---
net/sched/sch_ets.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/net/sched/sch_ets.c b/net/sched/sch_ets.c
index 306e046276d4..a4b07b661b77 100644
--- a/net/sched/sch_ets.c
+++ b/net/sched/sch_ets.c @@ -115,12 +115,12 @@ static void ets_offload_change(struct Qdisc *sch)
struct ets_sched * q = qdisc_priv ( sch );
struct tc_ets_qopt_offload qopt ;
unsigned int w_psum_prev = 0 ;
- unsigned int q_psum = 0 ;
- unsigned int q_sum = 0 ;
unsigned int quantum ;
unsigned int w_psum ;
unsigned int weight ;
unsigned int i ;
+ u64 q_psum = 0 ;
+ u64 q_sum = 0 ;
if ( ! tc_can_offload ( dev ) || ! dev -> netdev_ops -> ndo_setup_tc )
return ; @@ -138,8 +138,12 @@ static void ets_offload_change(struct Qdisc *sch)
for ( i = 0 ; i < q -> nbands ; i ++ ) {
quantum = q -> classes [ i ]. quantum ;
- q_psum += quantum ;
- w_psum = quantum ? q_psum * 100 / q_sum : 0 ;
+ if ( quantum ) {
+ q_psum += quantum ;
+ w_psum = div64_u64 ( q_psum * 100 , q_sum );
+ } else {
+ w_psum = 0 ;
+ }
weight = w_psum - w_psum_prev ;
w_psum_prev = w_psum ;
- - 2.52.0
On Wed, Feb 25, 2026 at 08:45:10AM -0500, Jamal Hadi Salim wrote: Hi Davide,
On Tue, Feb 24, 2026 at 3:30 PM Davide Caratti [off-list ref] wrote: quoted
Offloading ETS requires computing each class' WRR weight: this is done by
averaging over the sums of quanta as 'q_sum' and 'q_psum'. Using unsigned
int, the same integer size as the individual DRR quanta, can overflow and
even cause division by zero, like it happened in the following splat:
Was there a setup/test that resulted in the splat? It would be nice if
you could document it.
The fix looks good, so:
Reviewed-by: Jamal Hadi Salim <jhs@mojatatu.com>
hi Jamal, thanks for reviewing!
the test is a single line :
# tc qdisc add dev eth0 root ets bands 3 quanta 4294967294 1 1
but to see p_sum = 0 as divisor, eth0 must support offload for TC_SETUP_QDISC_ETS.
I see that netdevsim only supports TAPRIO offload, and I plan to follow-up on
net-next adding support for ETS offload on netdevsim (maybe also other qdiscs
deserve this, just to let syzkaller explore some "new" areas).
This way, I can write a TDC test-case similar to those we have for taprio
or cake-mq.
--
davide
On Wed, Feb 25, 2026 at 9:04 AM Davide Caratti [off-list ref] wrote:
On Wed, Feb 25, 2026 at 08:45:10AM -0500, Jamal Hadi Salim wrote: quoted Hi Davide,
On Tue, Feb 24, 2026 at 3:30 PM Davide Caratti [off-list ref] wrote: quoted
Offloading ETS requires computing each class' WRR weight: this is done by
averaging over the sums of quanta as 'q_sum' and 'q_psum'. Using unsigned
int, the same integer size as the individual DRR quanta, can overflow and
even cause division by zero, like it happened in the following splat:
Was there a setup/test that resulted in the splat? It would be nice if
you could document it.
The fix looks good, so:
Reviewed-by: Jamal Hadi Salim <jhs@mojatatu.com>
hi Jamal, thanks for reviewing!
the test is a single line :
# tc qdisc add dev eth0 root ets bands 3 quanta 4294967294 1 1
If you have to resend then add it to the commit - otherwise a tdc test
should cover it fine (when you get to the netdevsim change perhaps)
cheers,
jamal
but to see p_sum = 0 as divisor, eth0 must support offload for TC_SETUP_QDISC_ETS.
I see that netdevsim only supports TAPRIO offload, and I plan to follow-up on
net-next adding support for ETS offload on netdevsim (maybe also other qdiscs
deserve this, just to let syzkaller explore some "new" areas).
This way, I can write a TDC test-case similar to those we have for taprio
or cake-mq.
--
davide
Davide Caratti [off-list ref] writes:
Offloading ETS requires computing each class' WRR weight: this is done by
averaging over the sums of quanta as 'q_sum' and 'q_psum'. Using unsigned
int, the same integer size as the individual DRR quanta, can overflow and
even cause division by zero, like it happened in the following splat:
...
Fix this using 64-bit integers for 'q_sum' and 'q_psum'.
Cc: stable@vger.kernel.org
Fixes: d35eb52bd2ac ("net: sch_ets: Make the ETS qdisc offloadable")
Signed-off-by: Davide Caratti <redacted>
Thanks for the fix!
Reviewed-by: Petr Machata <petrm@nvidia.com>
Hello:
This patch was applied to netdev/net.git (main)
by Jakub Kicinski [off-list ref]:
On Tue, 24 Feb 2026 21:28:32 +0100 you wrote: Offloading ETS requires computing each class' WRR weight: this is done by
averaging over the sums of quanta as 'q_sum' and 'q_psum'. Using unsigned
int, the same integer size as the individual DRR quanta, can overflow and
even cause division by zero, like it happened in the following splat:
Oops: divide error: 0000 [#1] SMP PTI
CPU: 13 UID: 0 PID: 487 Comm: tc Tainted: G E 6.19.0-virtme #45 PREEMPT(full)
Tainted: [E]=UNSIGNED_MODULE
Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
RIP: 0010:ets_offload_change+0x11f/0x290 [sch_ets]
Code: e4 45 31 ff eb 03 41 89 c7 41 89 cb 89 ce 83 f9 0f 0f 87 b7 00 00 00 45 8b 08 31 c0 45 01 cc 45 85 c9 74 09 41 6b c4 64 31 d2 <41> f7 f2 89 c2 44 29 fa 45 89 df 41 83 fb 0f 0f 87 c7 00 00 00 44
RSP: 0018:ffffd0a180d77588 EFLAGS: 00010246
RAX: 00000000ffffff38 RBX: ffff8d3d482ca000 RCX: 0000000000000000
RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffd0a180d77660
RBP: ffffd0a180d77690 R08: ffff8d3d482ca2d8 R09: 00000000fffffffe
R10: 0000000000000000 R11: 0000000000000000 R12: 00000000fffffffe
R13: ffff8d3d472f2000 R14: 0000000000000003 R15: 0000000000000000
FS: 00007f440b6c2740(0000) GS:ffff8d3dc9803000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 000000003cdd2000 CR3: 0000000007b58002 CR4: 0000000000172ef0
Call Trace:
<TASK>
ets_qdisc_change+0x870/0xf40 [sch_ets]
qdisc_create+0x12b/0x540
tc_modify_qdisc+0x6d7/0xbd0
rtnetlink_rcv_msg+0x168/0x6b0
netlink_rcv_skb+0x5c/0x110
netlink_unicast+0x1d6/0x2b0
netlink_sendmsg+0x22e/0x470
____sys_sendmsg+0x38a/0x3c0
___sys_sendmsg+0x99/0xe0
__sys_sendmsg+0x8a/0xf0
do_syscall_64+0x111/0xf80
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f440b81c77e
Code: 4d 89 d8 e8 d4 bc 00 00 4c 8b 5d f8 41 8b 93 08 03 00 00 59 5e 48 83 f8 fc 74 11 c9 c3 0f 1f 80 00 00 00 00 48 8b 45 10 0f 05 <c9> c3 83 e2 39 83 fa 08 75 e7 e8 13 ff ff ff 0f 1f 00 f3 0f 1e fa
RSP: 002b:00007fff951e4c10 EFLAGS: 00000202 ORIG_RAX: 000000000000002e
RAX: ffffffffffffffda RBX: 0000000000481820 RCX: 00007f440b81c77e
RDX: 0000000000000000 RSI: 00007fff951e4cd0 RDI: 0000000000000003
RBP: 00007fff951e4c20 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000202 R12: 00007fff951f4fa8
R13: 00000000699ddede R14: 00007f440bb01000 R15: 0000000000486980
</TASK>
Modules linked in: sch_ets(E) netdevsim(E)
[...]
Here is the summary with links:
- [net] net/sched: ets: fix divide by zero in the offload path
https://git.kernel.org/netdev/net/c/e35626f610f3
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html