[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAGfirffTyUrB=MkXjw8N-gEA0Qvr42mbUndybG0+6wyFdGiajw@mail.gmail.com>
Date: Thu, 29 Jan 2026 13:19:53 +0900
From: GangMin Kim <km.kim1503@...il.com>
To: davem@...emloft.net, Eric Dumazet <edumazet@...gle.com>,
Jamal Hadi Salim <jhs@...atatu.com>, jiri@...nulli.us, kuba@...nel.org,
netdev@...r.kernel.org, pabeni@...hat.com, stephen@...workplumber.org,
xiyou.wangcong@...il.com
Cc: horms@...nel.org, linux-kernel@...r.kernel.org, syzkaller@...glegroups.com
Subject: [BUG] divide error in tabledist
Dear Linux kernel developers and maintainers,
Using a modified version of syzkaller, I identified a new bug and
refined the PoC, and the bug-related information is attached
below.Please let me know if you need any further information.
Summary
In netem, when jitter is set to 0x80000000, a divide error occurs when
tabledist is processed during the subsequent netem_enqueue operation.
Keywords
- net/sched
Kernel Info
Version: (Output of /proc/version)
- Linux version 6.19.0-rc7
Commit: (Git hash if applicable)
- 63804fed149a6750ffd28610c5c1c98cce6bd377
Description(Root Cause)
```
static int netem_change(struct Qdisc *sch, struct nlattr *opt,
struct netlink_ext_ack *extack)
{
struct netem_sched_data *q = qdisc_priv(sch);
struct nlattr *tb[TCA_NETEM_MAX + 1];
struct disttable *delay_dist = NULL;
struct disttable *slot_dist = NULL;
struct tc_netem_qopt *qopt;
struct clgstate old_clg;
int old_loss_model = CLG_RANDOM;
int ret;
qopt = nla_data(opt);
...
sch->limit = qopt->limit;
q->latency = PSCHED_TICKS2NS(qopt->latency);
q->jitter = PSCHED_TICKS2NS(qopt->jitter); // [1]
q->limit = qopt->limit;
q->gap = qopt->gap;
q->counter = 0;
q->loss = qopt->loss;
ret = check_netem_in_tree(sch, qopt->duplicate, extack); // [2]
if (ret)
goto unlock;
...
/* capping jitter to the range acceptable by tabledist() */
q->jitter = min_t(s64, abs(q->jitter), INT_MAX); // [3]
...
unlock:
sch_tree_unlock(sch);
table_free:
dist_free(delay_dist);
dist_free(slot_dist);
return ret;
}
```
When qopt->jitter is 0x6e000000, at [1] q->jitter is set to
0x1b80000000. If netem is already configured and a change operation is
attempted but fails at [2], the q values are modified but the process
at [3] is not executed. Therefore, q->jitter can be set to a value
exceeding INT_MAX.
```
static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
struct sk_buff **to_free)
{
struct netem_sched_data *q = qdisc_priv(sch);
/* We don't fill cb now as skb_unshare() may invalidate it */
struct netem_skb_cb *cb;
struct sk_buff *skb2 = NULL;
struct sk_buff *segs = NULL;
unsigned int prev_len = qdisc_pkt_len(skb);
int count = 1;
...
if (q->gap == 0 || /* not doing reordering */
q->counter < q->gap - 1 || /* inside last reordering gap */
q->reorder < get_crandom(&q->reorder_cor, &q->prng)) {
u64 now;
s64 delay;
delay = tabledist(q->latency, q->jitter, // [4]
&q->delay_cor, &q->prng, q->delay_dist);
...
}
...
return NET_XMIT_SUCCESS;
}
static s64 tabledist(s64 mu, s32 sigma,
struct crndstate *state,
struct prng *prng,
const struct disttable *dist)
{
s64 x;
long t;
u32 rnd;
if (sigma == 0)
return mu;
rnd = get_crandom(state, prng);
/* default uniform distribution */
if (dist == NULL)
return ((rnd % (2 * (u32)sigma)) + mu) - sigma; // [5]
...
return x / NETEM_DIST_SCALE + (sigma / NETEM_DIST_SCALE) * t + mu;
}
```
Subsequently, in netem_enqueue(), the previously set value is passed
at [4], and in tabledist(), sigma is set to 0x80000000. This causes
the calculation at [5] to become 2 * 0x80000000, which overflows to 0,
resulting in a divide-by-zero error.
Kasan Report
Oops: divide error: 0000 [#1] SMP KASAN NOPTI
CPU: 0 UID: 0 PID: 332 Comm: test Not tainted 6.19.0-rc7 #8 PREEMPT(full)
Hardware name: QEMU Ubuntu 24.04 PC (i440FX + PIIX, 1996), BIOS
1.16.3-debian-1.16.3-2 04/01/2014
RIP: 0010:tabledist.part.0+0x21e/0x290 net/sched/sch_netem.c:345
Code: 4c 01 f0 48 c1 e8 20 41 89 45 00 41 89 c6 e8 49 d1 9a fd 48 85
db 0f 85 78 fe ff ff e8 3b d1 9a fd 8d 4c 2d 00 44 89 f0 31 d2 <f7> f1
49 29 ec 49 01 d4 e9 2a ff ff ff e8 20 d1 9a fd 48 81 eb 00
RSP: 0018:ffff88810f61f1f8 EFLAGS: 00010246
RAX: 00000000aecf3ad7 RBX: 0000000000000000 RCX: 0000000000000000
RDX: 0000000000000000 RSI: 0000000080000000 RDI: ffff88810900da7c
RBP: ffffffff80000000 R08: 0000000000000000 R09: ffffed10233895cc
R10: ffff888119c4ae67 R11: 0000000000000000 R12: 0000000001000300
R13: ffff88810900da3c R14: 00000000aecf3ad7 R15: ffff88810900da40
FS: 00007f2531e11540(0000) GS:ffff88834ad89000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f2531cfe1c0 CR3: 00000001215fe000 CR4: 0000000000750ef0
PKRU: 55555554
Call Trace:
<TASK>
tabledist net/sched/sch_netem.c:559 [inline]
netem_enqueue+0x4f4/0x3180 net/sched/sch_netem.c:559
qdisc_enqueue include/net/sch_generic.h:887 [inline]
qfq_enqueue+0x46f/0x13c0 net/sched/sch_qfq.c:1256
dev_qdisc_enqueue+0x45/0x160 net/core/dev.c:4147
__dev_xmit_skb net/core/dev.c:4262 [inline]
__dev_queue_xmit+0x1eea/0x3060 net/core/dev.c:4798
dev_queue_xmit include/linux/netdevice.h:3381 [inline]
neigh_hh_output include/net/neighbour.h:540 [inline]
neigh_output include/net/neighbour.h:554 [inline]
ip_finish_output2+0xdd2/0x1710 net/ipv4/ip_output.c:237
__ip_finish_output.part.0+0x182/0x2f0 net/ipv4/ip_output.c:315
__ip_finish_output net/ipv4/ip_output.c:444 [inline]
ip_finish_output net/ipv4/ip_output.c:325 [inline]
NF_HOOK_COND include/linux/netfilter.h:307 [inline]
ip_output+0x288/0x510 net/ipv4/ip_output.c:438
dst_output include/net/dst.h:464 [inline]
ip_local_out net/ipv4/ip_output.c:131 [inline]
ip_send_skb+0x160/0x1b0 net/ipv4/ip_output.c:1508
udp_send_skb+0x6d6/0x1000 net/ipv4/udp.c:1195
udp_sendmsg+0x1463/0x1eb0 net/ipv4/udp.c:1484
inet_sendmsg+0xfa/0x140 net/ipv4/af_inet.c:859
sock_sendmsg_nosec net/socket.c:727 [inline]
__sock_sendmsg net/socket.c:742 [inline]
sock_write_iter+0x493/0x5b0 net/socket.c:1195
new_sync_write fs/read_write.c:593 [inline]
vfs_write+0x657/0xd30 fs/read_write.c:686
ksys_write+0x1b2/0x200 fs/read_write.c:738
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xa4/0x320 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f2531d27513
Code: 8b 15 81 29 0e 00 f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b7 0f
1f 00 64 8b 04 25 18 00 00 00 85 c0 75 14 b8 01 00 00 00 0f 05 <48> 3d
00 f0 ff ff 77 55 c3 0f 1f 40 00 48 83 ec 28 48 89 54 24 18
RSP: 002b:00007ffe09e5d858 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f2531d27513
RDX: 0000000000000040 RSI: 00007ffe09e5d890 RDI: 0000000000000004
RBP: 00007ffe09e5d8f0 R08: 0000000000000004 R09: 0000000000020000
R10: 00007ffe09e5d87c R11: 0000000000000246 R12: 000055c28686a100
R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
</TASK>
Modules linked in:
---[ end trace 0000000000000000 ]---
RIP: 0010:tabledist.part.0+0x21e/0x290 net/sched/sch_netem.c:345
Code: 4c 01 f0 48 c1 e8 20 41 89 45 00 41 89 c6 e8 49 d1 9a fd 48 85
db 0f 85 78 fe ff ff e8 3b d1 9a fd 8d 4c 2d 00 44 89 f0 31 d2 <f7> f1
49 29 ec 49 01 d4 e9 2a ff ff ff e8 20 d1 9a fd 48 81 eb 00
RSP: 0018:ffff88810f61f1f8 EFLAGS: 00010246
RAX: 00000000aecf3ad7 RBX: 0000000000000000 RCX: 0000000000000000
RDX: 0000000000000000 RSI: 0000000080000000 RDI: ffff88810900da7c
RBP: ffffffff80000000 R08: 0000000000000000 R09: ffffed10233895cc
R10: ffff888119c4ae67 R11: 0000000000000000 R12: 0000000001000300
R13: ffff88810900da3c R14: 00000000aecf3ad7 R15: ffff88810900da40
FS: 00007f2531e11540(0000) GS:ffff88834ad89000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f2531cfe1c0 CR3: 00000001215fe000 CR4: 0000000000750ef0
PKRU: 55555554
----------------
Code disassembly (best guess):
0: 4c 01 f0 add %r14,%rax
3: 48 c1 e8 20 shr $0x20,%rax
7: 41 89 45 00 mov %eax,0x0(%r13)
b: 41 89 c6 mov %eax,%r14d
e: e8 49 d1 9a fd call 0xfd9ad15c
13: 48 85 db test %rbx,%rbx
16: 0f 85 78 fe ff ff jne 0xfffffe94
1c: e8 3b d1 9a fd call 0xfd9ad15c
21: 8d 4c 2d 00 lea 0x0(%rbp,%rbp,1),%ecx
25: 44 89 f0 mov %r14d,%eax
28: 31 d2 xor %edx,%edx
* 2a: f7 f1 div %ecx <-- trapping instruction
2c: 49 29 ec sub %rbp,%r12
2f: 49 01 d4 add %rdx,%r12
32: e9 2a ff ff ff jmp 0xffffff61
37: e8 20 d1 9a fd call 0xfd9ad15c
3c: 48 rex.W
3d: 81 .byte 0x81
3e: eb 00 jmp 0x40
View attachment "repro.c" of type "text/plain" (8325 bytes)
Download attachment ".config" of type "application/xml" (164537 bytes)
Powered by blists - more mailing lists