Linux-mm Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Yury Norov <ynorov@nvidia.com>
To: Farhad Alemi <farhad.alemi@berkeley.edu>
Cc: Andrew Morton <akpm@linux-foundation.org>,
	Yury Norov <yury.norov@gmail.com>,
	Waiman Long <longman@redhat.com>,
	David Hildenbrand <david@kernel.org>,
	Rasmus Villemoes <linux@rasmusvillemoes.dk>,
	cgroups@vger.kernel.org, linux-mm@kvack.org,
	linux-kernel@vger.kernel.org
Subject: Re: [BUG] lib/bitmap: divide error in bitmap_fold() when sz argument is 0
Date: Thu, 28 May 2026 15:07:35 -0400	[thread overview]
Message-ID: <ahiSd4NoTdrYs579@yury> (raw)
In-Reply-To: <CA+0ovCgxbZkXa+OU8w3s84R3KNPNxxRfmsNR-udh+afQBbGNmw@mail.gmail.com>

Hi Farhad,

Thanks for the report. Submitted the fix and added you in CC.

Thanks,
Yury

On Thu, May 28, 2026 at 11:25:36AM -0700, Farhad Alemi wrote:
> Hello,
> 
> I am reporting a divide-by-zero crash in bitmap_fold() found by syzkaller.
> 
> Summary:
> bitmap_fold() at lib/bitmap.c divides by its `sz` parameter without
> guarding sz != 0:
> 
>   void bitmap_fold(unsigned long *dst, const unsigned long *orig,
>                    unsigned int sz, unsigned int nbits)
>   {
>           ...
>           for_each_set_bit(oldbit, orig, nbits)
>                   set_bit(oldbit % sz, dst);
>   }
> 
> The call chain in the observed crash is:
> 
>   mpol_relative_nodemask()   mm/mempolicy.c
>     nodes_fold(tmp, *orig, nodes_weight(*rel))
>   __nodes_fold()              include/linux/nodemask.h
>     bitmap_fold(dstp->bits, origp->bits, sz, nbits)
>   bitmap_fold()               lib/bitmap.c
> 
> When `nodes_weight(*rel)` is 0 (i.e. the relative-nodes mask is empty),
> the `sz` argument passed to bitmap_fold() is 0, and the
> `oldbit % sz` expression executes a divl by zero.
> 
> Observed on:
> - Linux v6.18.32-dirty (where the bug was originally found), x86_64,
>   QEMU Q35
> - KASAN enabled; panic_on_warn set
> - The only local dirty file in my tree is drivers/tty/serial/serial_core.c,
>   containing a local ttyS0 console guard for the fuzzing harness. It is
>   unrelated to lib/bitmap, mm/mempolicy, or kernel/cgroup/cpuset.
> - The crash fires in a cpu-hotplug kernel thread (Comm: cpuhp/1, PID 21)
>   reached via sched_cpu_deactivate -> cpuset_handle_hotplug ->
>   cpuset_update_tasks_nodemask -> mpol_rebind_mm -> mpol_rebind_policy
>   -> mpol_rebind_nodemask -> mpol_relative_nodemask -> __nodes_fold ->
>   bitmap_fold.
> - Source inspection of linus/master at commit e8c2f9fdadee
>   (v7.1-rc4-754-ge8c2f9fdadee) shows the buggy structure is unchanged:
>   bitmap_fold() at lib/bitmap.c:718 still computes `oldbit % sz` with
>   no sz != 0 guard; __nodes_fold() at include/linux/nodemask.h:365
>   still forwards its sz argument; mpol_relative_nodemask() at
>   mm/mempolicy.c:370 still calls nodes_fold(tmp, *orig,
>   nodes_weight(*rel)). I have not re-run a reproducer against
>   e8c2f9fdadee as no standalone reproducer is available yet.
> 
> Impact:
> A divide-by-zero in a cpu-hotplug kernel thread context kills the
> kernel:
> 
>   Oops: divide error: 0000 [#1] SMP KASAN NOPTI
>   CPU: 1 UID: 0 PID: 21 Comm: cpuhp/1 Not tainted 6.18.32-dirty #1 PREEMPT(full)
>   RIP: 0010:bitmap_fold+0x5e/0xb0 lib/bitmap.c:713
> 
> The crash report's code disassembly pins the trapping instruction to
> `divl 0x4(%rsp)` (bytes `f7 74 24 04`) with %edx pre-zeroed by the
> preceding `xor %edx,%edx` -- i.e. a 32-bit unsigned divide by the
> on-stack `sz` value.
> 
> Relevant stack:
> 
>   bitmap_fold+0x5e/0xb0 lib/bitmap.c:713
>   __nodes_fold include/linux/nodemask.h:369 [inline]
>   mpol_relative_nodemask mm/mempolicy.c:372 [inline]
>   mpol_rebind_nodemask+0x1e9/0x2d0 mm/mempolicy.c:508
>   mpol_rebind_policy mm/mempolicy.c:542 [inline]
>   mpol_rebind_mm+0x3ab/0x680 mm/mempolicy.c:569
>   cpuset_update_tasks_nodemask+0x22e/0x340 kernel/cgroup/cpuset.c:2777
>   hotplug_update_tasks kernel/cgroup/cpuset.c:3882 [inline]
>   cpuset_hotplug_update_tasks kernel/cgroup/cpuset.c:3985 [inline]
>   cpuset_handle_hotplug+0xe52/0x1200 kernel/cgroup/cpuset.c:4089
>   cpuset_cpu_inactive kernel/sched/core.c:8377 [inline]
>   sched_cpu_deactivate+0x497/0x600 kernel/sched/core.c:8493
>   cpuhp_invoke_callback+0x44a/0x860 kernel/cpu.c:195
>   cpuhp_thread_fun+0x40f/0x870 kernel/cpu.c:1105
>   smpboot_thread_fn+0x546/0xa50 kernel/smpboot.c:160
>   kthread+0x73e/0x8c0 kernel/kthread.c:432
> 
> Expected behavior:
> Either bitmap_fold() should guard against sz == 0 (return early or
> WARN+return), or the callers in the nodes_fold / mpol_relative_nodemask
> chain should not pass a zero `sz` (e.g. short-circuit the rebind when
> the relative nodemask is empty).
> 
> Reproducer:
> A standalone .syz or C reproducer was not produced for this seed; the
> crash fired during broader cpu/cgroup/mempolicy fuzzing. The console
> report is attached as crash-report.txt.
> 
> Novelty check:
> I searched the syzbot dashboard's upstream open, fixed, stable, and
> invalid (per-subsystem mempolicy/mm/cgroups) namespaces, the Android
> dashboard, and the marc.info linux-mm and linux-kernel archives, for
> "bitmap_fold", "mpol_rebind_nodemask" + "divide error", "__nodes_fold"
> + "BUG"/"Oops", and "cpuset_handle_hotplug" + "BUG". I did not find an
> exact match. The recent Jinjiang Tu series (mainline commit
> 3d702678f57e, "mm/mempolicy: fix mpol_rebind_nodemask() for
> MPOL_F_NUMA_BALANCING") is a sibling fix in the same function but
> addresses wrong-rebind logic under NUMA balancing, not the
> divide-by-zero in bitmap_fold().
> 
> I appreciate your time and consideration, and I'm grateful for your
> work on this subsystem. I'd be glad to test any candidate patches.
> 
> Regards,

> Oops: divide error: 0000 [#1] SMP KASAN NOPTI
> CPU: 1 UID: 0 PID: 21 Comm: cpuhp/1 Not tainted 6.18.32-dirty #1 PREEMPT(full) 
> Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
> RIP: 0010:bitmap_fold+0x5e/0xb0 lib/bitmap.c:713
> Code: 31 f6 e8 a5 4e 20 fe 41 89 dc 44 89 ea 4c 89 f7 4c 89 e6 e8 84 f2 01 00 49 89 c5 44 39 eb 76 2d e8 f7 fc b9 fd 44 89 e8 31 d2 <f7> 74 24 04 89 d5 89 d0 c1 e8 06 49 8d 3c c7 be 08 00 00 00 e8 39
> RSP: 0018:ffffc9000016f520 EFLAGS: 00010246
> RAX: 0000000000000000 RBX: 0000000000000040 RCX: ffff8881026a0000
> RDX: 0000000000000000 RSI: 0000000000000040 RDI: ffff888126f6f218
> RBP: ffffc9000016f630 R08: ffffc9000016f5a7 R09: 0000000000000000
> R10: ffffc9000016f5a0 R11: fffff5200002deb5 R12: 0000000000000040
> R13: 0000000000000000 R14: ffff888126f6f218 R15: ffffc9000016f5a0
> FS:  0000000000000000(0000) GS:ffff8882abcc4000(0000) knlGS:0000000000000000
> CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: 00007fcd8c9c6fe8 CR3: 0000000192758000 CR4: 0000000000750ef0
> PKRU: 55555554
> Call Trace:
>  <TASK>
>  __nodes_fold include/linux/nodemask.h:369 [inline]
>  mpol_relative_nodemask mm/mempolicy.c:372 [inline]
>  mpol_rebind_nodemask+0x1e9/0x2d0 mm/mempolicy.c:508
>  mpol_rebind_policy mm/mempolicy.c:542 [inline]
>  mpol_rebind_mm+0x3ab/0x680 mm/mempolicy.c:569
>  cpuset_update_tasks_nodemask+0x22e/0x340 kernel/cgroup/cpuset.c:2777
>  hotplug_update_tasks kernel/cgroup/cpuset.c:3882 [inline]
>  cpuset_hotplug_update_tasks kernel/cgroup/cpuset.c:3985 [inline]
>  cpuset_handle_hotplug+0xe52/0x1200 kernel/cgroup/cpuset.c:4089
>  cpuset_cpu_inactive kernel/sched/core.c:8377 [inline]
>  sched_cpu_deactivate+0x497/0x600 kernel/sched/core.c:8493
>  cpuhp_invoke_callback+0x44a/0x860 kernel/cpu.c:195
>  cpuhp_thread_fun+0x40f/0x870 kernel/cpu.c:1105
>  smpboot_thread_fn+0x546/0xa50 kernel/smpboot.c:160
>  kthread+0x73e/0x8c0 kernel/kthread.c:432
>  ret_from_fork+0x4b4/0xa30 arch/x86/kernel/process.c:158
>  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
>  </TASK>
> Modules linked in:
> ---[ end trace 0000000000000000 ]---
> RIP: 0010:bitmap_fold+0x5e/0xb0 lib/bitmap.c:713
> Code: 31 f6 e8 a5 4e 20 fe 41 89 dc 44 89 ea 4c 89 f7 4c 89 e6 e8 84 f2 01 00 49 89 c5 44 39 eb 76 2d e8 f7 fc b9 fd 44 89 e8 31 d2 <f7> 74 24 04 89 d5 89 d0 c1 e8 06 49 8d 3c c7 be 08 00 00 00 e8 39
> RSP: 0018:ffffc9000016f520 EFLAGS: 00010246
> RAX: 0000000000000000 RBX: 0000000000000040 RCX: ffff8881026a0000
> RDX: 0000000000000000 RSI: 0000000000000040 RDI: ffff888126f6f218
> RBP: ffffc9000016f630 R08: ffffc9000016f5a7 R09: 0000000000000000
> R10: ffffc9000016f5a0 R11: fffff5200002deb5 R12: 0000000000000040
> R13: 0000000000000000 R14: ffff888126f6f218 R15: ffffc9000016f5a0
> FS:  0000000000000000(0000) GS:ffff8882abcc4000(0000) knlGS:0000000000000000
> CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: 00007fcd8c9c6fe8 CR3: 0000000192758000 CR4: 0000000000750ef0
> PKRU: 55555554
> ----------------
> Code disassembly (best guess):
>    0:	31 f6                	xor    %esi,%esi
>    2:	e8 a5 4e 20 fe       	call   0xfe204eac
>    7:	41 89 dc             	mov    %ebx,%r12d
>    a:	44 89 ea             	mov    %r13d,%edx
>    d:	4c 89 f7             	mov    %r14,%rdi
>   10:	4c 89 e6             	mov    %r12,%rsi
>   13:	e8 84 f2 01 00       	call   0x1f29c
>   18:	49 89 c5             	mov    %rax,%r13
>   1b:	44 39 eb             	cmp    %r13d,%ebx
>   1e:	76 2d                	jbe    0x4d
>   20:	e8 f7 fc b9 fd       	call   0xfdb9fd1c
>   25:	44 89 e8             	mov    %r13d,%eax
>   28:	31 d2                	xor    %edx,%edx
> * 2a:	f7 74 24 04          	divl   0x4(%rsp) <-- trapping instruction
>   2e:	89 d5                	mov    %edx,%ebp
>   30:	89 d0                	mov    %edx,%eax
>   32:	c1 e8 06             	shr    $0x6,%eax
>   35:	49 8d 3c c7          	lea    (%r15,%rax,8),%rdi
>   39:	be 08 00 00 00       	mov    $0x8,%esi
>   3e:	e8                   	.byte 0xe8
>   3f:	39                   	.byte 0x39
> 
> <<<<<<<<<<<<<<< tail report >>>>>>>>>>>>>>>
> 



      reply	other threads:[~2026-05-28 19:07 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-28 18:25 [BUG] lib/bitmap: divide error in bitmap_fold() when sz argument is 0 Farhad Alemi
2026-05-28 19:07 ` Yury Norov [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ahiSd4NoTdrYs579@yury \
    --to=ynorov@nvidia.com \
    --cc=akpm@linux-foundation.org \
    --cc=cgroups@vger.kernel.org \
    --cc=david@kernel.org \
    --cc=farhad.alemi@berkeley.edu \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=linux@rasmusvillemoes.dk \
    --cc=longman@redhat.com \
    --cc=yury.norov@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox