lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<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

Powered by Openwall GNU/*/Linux Powered by OpenVZ