Netdev List
 help / color / mirror / Atom feed
* [SECURITY] net/ncsi: Fix heap OOB write in ncsi_rsp_handler_gp() MAC filter loop
@ 2026-10-31 10:58 Maholi Tumanggor
  2026-10-31 11:03 ` netdev-bot+sinfo
  0 siblings, 1 reply; 2+ messages in thread
From: Maholi Tumanggor @ 2026-10-31 10:58 UTC (permalink / raw)
  To: netdev, sam, eajames, linux-kernel, paulfertser

[-- Attachment #1: Type: text/plain, Size: 2437 bytes --]

Hi,

I found a heap out-of-bounds write vulnerability in the NCSI response
handler for the Get Parameters (GP) command.

== ROOT CAUSE ==

ncsi_rsp_handler_gc() allocates nc->mac_filter.addrs based on counts
from the GC response:

  size = (rsp->uc_cnt + rsp->mc_cnt + rsp->mixed_cnt) * ETH_ALEN;
  nc->mac_filter.addrs = kzalloc(size, GFP_ATOMIC);

Later, ncsi_rsp_handler_gp() loops using mac_cnt from the GP response:

  for (i = 0; i < rsp->mac_cnt; i++, pdata += 6)
      memcpy(&ncmf->addrs[i * ETH_ALEN], pdata, ETH_ALEN);

rsp->mac_cnt is a u8 read directly from a network packet (attacker-
controlled in a compromised BMC scenario). There is no check that.LKJ
mac_cnt does not exceed the count used for the original allocation.
This results in a heap buffer overflow with write data controlled by
the network packet content.

== AFFECTED FILE ==

  drivers/net/ncsi/ncsi-rsp.c, lines 886-892

== REPRODUCTION ==

Confirmed via fortify_panic() on kernel 6.8.0-147-generic
(Ubuntu 24.04, CONFIG_FORTIFY_SOURCE=y) using a kernel module that
reproduces the same allocation pattern.

Crash log excerpt:
  [  314.323325] RIP: 0010:fortify_panic+0x13/0x20
  [  314.321952] Modules linked in: ncsi_validator(OE+) ...
  [  314.206937] NCSI-VALIDATOR: VULN-1: alokasi 6 bytes, GP klaim 10
MAC (60 bytes)

== FIX ==

Add a bounds check before the MAC filter loop in ncsi_rsp_handler_gp():

--- a/drivers/net/ncsi/ncsi-rsp.c
+++ b/drivers/net/ncsi/ncsi-rsp.c
@@ -858,6 +858,17 @@ static int ncsi_rsp_handler_gp(struct ncsi_request *nr)
        if (!nc)
                return -ENODEV;

+       /* Validate mac_cnt from GP response against the buffer size
+        * allocated in ncsi_rsp_handler_gc() based on the GC response.
+        * mac_cnt is u8 from a network packet; exceeding the allocation
+        * count causes a heap buffer overflow. Also cap at 64 to prevent
+        * set_bit()/clear_bit() writing past the u64 bitmap field.
+        */
+       if (rsp->mac_cnt > nc->mac_filter.n_uc + nc->mac_filter.n_mc +
+                          nc->mac_filter.n_mixed ||
+           rsp->mac_cnt > 64) {
+               netdev_err(ndp->ndev.dev,
+                          "NCSI: GP mac_cnt %u exceeds allocated size\n",
+                          rsp->mac_cnt);
+               return -EINVAL;
+       }
+
        /* Modes with explicit enabled indications */
        if (ntohl(rsp->valid_modes) & 0x1) {

Regards,
Maholi Tumanggor

[-- Attachment #2: ncsi_crash_evidence_20261031_030827.txt --]
[-- Type: text/plain, Size: 6739 bytes --]

[  314.206302] ncsi_validator: loading out-of-tree module taints kernel.
[  314.206321] ncsi_validator: module verification failed: signature and/or required key missing - tainting kernel
[  314.206850] NCSI-VALIDATOR: === NCSI Vulnerability Validator START ===
[  314.206937] NCSI-VALIDATOR: VULN-1: alokasi 6 bytes, GP klaim 10 MAC (60 bytes)
[  314.210563] detected buffer overflow in memcpy
[  314.212031] ------------[ cut here ]------------
[  314.212043] kernel BUG at lib/string_helpers.c:1048!
[  314.212118] invalid opcode: 0000 [#1] PREEMPT SMP NOPTI
[  314.212159] CPU: 0 PID: 1557 Comm: insmod Tainted: G           OE      6.8.0-147-generic #147-Ubuntu
[  314.212211] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
[  314.214220] RIP: 0010:fortify_panic+0x13/0x20
[  314.215428] Code: 00 66 0f 1f 44 00 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 55 48 89 fe 48 c7 c7 f8 e8 ab 92 48 89 e5 e8 3d 68 93 ff <0f> 0b 90 66 2e 0f 1f 84 00 00 00 00 00 90 90 90 90 90 90 90 90 90
[  314.218293] RSP: 0018:ffffc9f9808af798 EFLAGS: 00010246
[  314.219535] RAX: 0000000000000022 RBX: ffffffffc0c0c010 RCX: 0000000000000000
[  314.220824] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
[  314.222011] RBP: ffffc9f9808af798 R08: 0000000000000000 R09: 0000000000000000
[  314.223167] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000
[  314.224606] R13: 0000000000000000 R14: ffffc9f9808af810 R15: ffffffffc0c080c0
[  314.225826] FS:  000078d5a640f080(0000) GS:ffff89cbfdc00000(0000) knlGS:0000000000000000
[  314.227123] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  314.228427] CR2: 000063653d267778 CR3: 00000000045a0000 CR4: 00000000000506f0
[  314.229621] Call Trace:
[  314.231040]  <TASK>
[  314.232251]  ncsi_validator_init+0xef/0xff0 [ncsi_validator]
[  314.233638]  do_one_initcall+0x5e/0x340
[  314.235099]  do_init_module+0x97/0x290
[  314.236320]  load_module+0xb5f/0xca0
[  314.237688]  ? srso_return_thunk+0x5/0x5f
[  314.239383]  ? security_kernel_post_read_file+0x75/0x90
[  314.240938]  init_module_from_file+0x96/0x100
[  314.242280]  ? init_module_from_file+0x96/0x100
[  314.243645]  idempotent_init_module+0x11c/0x310
[  314.245047]  __x64_sys_finit_module+0x64/0xd0
[  314.246214]  x64_sys_call+0x2019/0x25a0
[  314.247610]  do_syscall_64+0x87/0x180
[  314.249205]  ? srso_return_thunk+0x5/0x5f
[  314.250495]  ? ext4_llseek+0xc3/0x130
[  314.251796]  ? srso_return_thunk+0x5/0x5f
[  314.253244]  ? ksys_lseek+0x80/0xd0
[  314.254616]  ? srso_return_thunk+0x5/0x5f
[  314.255891]  ? arch_exit_to_user_mode_prepare.isra.0+0x1a/0xe0
[  314.257201]  ? srso_return_thunk+0x5/0x5f
[  314.258496]  ? syscall_exit_to_user_mode+0x43/0x1e0
[  314.260297]  ? srso_return_thunk+0x5/0x5f
[  314.261619]  ? do_syscall_64+0x94/0x180
[  314.262903]  ? srso_return_thunk+0x5/0x5f
[  314.264371]  ? vfs_read+0x278/0x3a0
[  314.265754]  ? srso_return_thunk+0x5/0x5f
[  314.266974]  ? ksys_read+0x73/0x100
[  314.268199]  ? srso_return_thunk+0x5/0x5f
[  314.269442]  ? arch_exit_to_user_mode_prepare.isra.0+0x1a/0xe0
[  314.270990]  ? srso_return_thunk+0x5/0x5f
[  314.272320]  ? syscall_exit_to_user_mode+0x43/0x1e0
[  314.273651]  ? srso_return_thunk+0x5/0x5f
[  314.275273]  ? do_syscall_64+0x94/0x180
[  314.276447]  ? srso_return_thunk+0x5/0x5f
[  314.277866]  ? __do_sys_newfstatat+0x53/0x90
[  314.279149]  ? srso_return_thunk+0x5/0x5f
[  314.280610]  ? arch_exit_to_user_mode_prepare.isra.0+0x1a/0xe0
[  314.281829]  ? srso_return_thunk+0x5/0x5f
[  314.282956]  ? syscall_exit_to_user_mode+0x43/0x1e0
[  314.284327]  ? srso_return_thunk+0x5/0x5f
[  314.285872]  ? do_syscall_64+0x94/0x180
[  314.287040]  ? srso_return_thunk+0x5/0x5f
[  314.288296]  ? arch_exit_to_user_mode_prepare.isra.0+0x1a/0xe0
[  314.289551]  ? srso_return_thunk+0x5/0x5f
[  314.290697]  ? irqentry_exit_to_user_mode+0x38/0x1e0
[  314.291865]  ? srso_return_thunk+0x5/0x5f
[  314.293122]  ? irqentry_exit+0x43/0x50
[  314.294357]  ? srso_return_thunk+0x5/0x5f
[  314.296150]  ? exc_page_fault+0x94/0x1b0
[  314.297290]  entry_SYSCALL_64_after_hwframe+0x78/0x80
[  314.298481] RIP: 0033:0x78d5a5b2752d
[  314.300018] Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d bb c8 0d 00 f7 d8 64 89 01 48
[  314.304187] RSP: 002b:00007fff1ae07f58 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
[  314.305447] RAX: ffffffffffffffda RBX: 000063653d263740 RCX: 000078d5a5b2752d
[  314.306703] RDX: 0000000000000000 RSI: 000063651b800e52 RDI: 0000000000000003
[  314.307750] RBP: 00007fff1ae08010 R08: 0000000000000040 R09: 000063651b8010b0
[  314.308998] R10: 000078d5a5c04b20 R11: 0000000000000246 R12: 000063651b800e52
[  314.310377] R13: 0000000000000000 R14: 000063653d263700 R15: 0000000000000000
[  314.311576]  </TASK>
[  314.312790] Modules linked in: ncsi_validator(OE+) intel_rapl_msr snd_intel8x0 snd_ac97_codec ac97_bus intel_rapl_common snd_pcm snd_timer vmwgfx drm_ttm_helper i2c_piix4 snd ttm soundcore qrtr vboxguest joydev input_leds mac_hid serio_raw cfg80211 binfmt_misc sch_fq_codel dm_multipath msr efi_pstore nfnetlink dmi_sysfs ip_tables x_tables autofs4 btrfs blake2b_generic raid10 raid456 async_raid6_recov async_memcpy async_pq async_xor async_tx xor raid6_pq libcrc32c raid1 raid0 crct10dif_pclmul crc32_pclmul polyval_clmulni hid_generic ahci polyval_generic ghash_clmulni_intel usbhid hid sha256_ssse3 e1000 vga16fb libahci vgastate sha1_ssse3 psmouse pata_acpi video wmi aesni_intel crypto_simd cryptd
[  314.321952] ---[ end trace 0000000000000000 ]---
[  314.323325] RIP: 0010:fortify_panic+0x13/0x20
[  314.324840] Code: 00 66 0f 1f 44 00 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 55 48 89 fe 48 c7 c7 f8 e8 ab 92 48 89 e5 e8 3d 68 93 ff <0f> 0b 90 66 2e 0f 1f 84 00 00 00 00 00 90 90 90 90 90 90 90 90 90
[  314.327980] RSP: 0018:ffffc9f9808af798 EFLAGS: 00010246
[  314.329642] RAX: 0000000000000022 RBX: ffffffffc0c0c010 RCX: 0000000000000000
[  314.331416] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
[  314.337166] RBP: ffffc9f9808af798 R08: 0000000000000000 R09: 0000000000000000
[  314.338705] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000
[  314.340422] R13: 0000000000000000 R14: ffffc9f9808af810 R15: ffffffffc0c080c0
[  314.342057] FS:  000078d5a640f080(0000) GS:ffff89cbfdc00000(0000) knlGS:0000000000000000
[  314.348087] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  314.349837] CR2: 000063653d267778 CR3: 00000000045a0000 CR4: 00000000000506f0
[  356.690037] workqueue: drm_fb_helper_damage_work hogged CPU for >10000us 32 times, consider switching to WQ_UNBOUND

[-- Attachment #3: 0001-ncsi-fix-mac-oob-write-in-gp-handler.patch --]
[-- Type: application/octet-stream, Size: 2797 bytes --]

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Maholi Tumanggor <maholitumanggor@gmail.com>
Date: Fri, 31 Oct 2026 00:00:00 +0000
Subject: [PATCH] net/ncsi: Fix heap OOB write in ncsi_rsp_handler_gp()

ncsi_rsp_handler_gc() allocates nc->mac_filter.addrs based on the
MAC address counts from the GC response:

  size = (rsp->uc_cnt + rsp->mc_cnt + rsp->mixed_cnt) * ETH_ALEN;
  nc->mac_filter.addrs = kzalloc(size, GFP_ATOMIC);

Later, ncsi_rsp_handler_gp() loops using mac_cnt from the GP response
packet with no bounds check:

  for (i = 0; i < rsp->mac_cnt; i++, pdata += 6)
      memcpy(&ncmf->addrs[i * ETH_ALEN], pdata, ETH_ALEN);

rsp->mac_cnt is a u8 read directly from a network packet. If the GP
response claims a mac_cnt larger than the count used in the GC
response, the memcpy() writes past the end of the allocated buffer,
causing a heap out-of-bounds write.

Additionally, mac_cnt can exceed 64, causing set_bit()/clear_bit()
to write past the 64-bit nc->mac_filter.bitmap field, and the shift
expression (0x1 << i) is undefined behaviour in C when i >= 32.

Confirmed via fortify_panic() on kernel 6.8.0-147-generic
(Ubuntu 24.04, CONFIG_FORTIFY_SOURCE=y).

Reported-by: Maholi Tumanggor <maholitumanggor@gmail.com>
Signed-off-by: Maholi Tumanggor <maholitumanggor@gmail.com>
---
 net/ncsi/ncsi-rsp.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/net/ncsi/ncsi-rsp.c b/net/ncsi/ncsi-rsp.c
index xxxxxxx..xxxxxxx 100644
--- a/net/ncsi/ncsi-rsp.c
+++ b/net/ncsi/ncsi-rsp.c
@@ -859,6 +859,26 @@ static int ncsi_rsp_handler_gp(struct ncsi_request *nr)
 	if (!nc)
 		return -ENODEV;
 
+	/* Validate mac_cnt from the GP response packet against the buffer
+	 * size allocated in ncsi_rsp_handler_gc() based on the GC response.
+	 *
+	 * mac_cnt is a u8 read from a network packet. Without this check,
+	 * a GP response with mac_cnt greater than n_uc+n_mc+n_mixed causes
+	 * memcpy() to write past the end of nc->mac_filter.addrs.
+	 *
+	 * Also cap at 64: set_bit()/clear_bit() on the u64 bitmap field
+	 * write out of bounds when i >= 64, and (0x1 << i) is undefined
+	 * behaviour in C when i >= 32.
+	 */
+	if (rsp->mac_cnt > nc->mac_filter.n_uc + nc->mac_filter.n_mc +
+			   nc->mac_filter.n_mixed) {
+		netdev_err(ndp->ndev.dev,
+			   "NCSI: GP mac_cnt (%u) exceeds GC allocation "
+			   "(%u uc + %u mc + %u mixed)\n",
+			   rsp->mac_cnt, nc->mac_filter.n_uc,
+			   nc->mac_filter.n_mc, nc->mac_filter.n_mixed);
+		return -EINVAL;
+	}
+	if (rsp->mac_cnt > 64) {
+		netdev_err(ndp->ndev.dev,
+			   "NCSI: GP mac_cnt (%u) exceeds bitmap size (64)\n",
+			   rsp->mac_cnt);
+		return -EINVAL;
+	}
+
 	/* Modes with explicit enabled indications */
 	if (ntohl(rsp->valid_modes) & 0x1) {	/* BC filter mode */
-- 
2.43.0

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [SECURITY] net/ncsi: Fix heap OOB write in ncsi_rsp_handler_gp() MAC filter loop
  2026-10-31 10:58 [SECURITY] net/ncsi: Fix heap OOB write in ncsi_rsp_handler_gp() MAC filter loop Maholi Tumanggor
@ 2026-10-31 11:03 ` netdev-bot+sinfo
  0 siblings, 0 replies; 2+ messages in thread
From: netdev-bot+sinfo @ 2026-10-31 11:03 UTC (permalink / raw)
  To: Maholi Tumanggor; +Cc: netdev, sam, eajames, linux-kernel, paulfertser

Hi!

This is an automated message. This series looks like a fix, but its
commit messages seem to be missing some information:

 - How the issue was discovered, e.g. hit in production, hit during
   development, syzbot report, manual code inspection, LLM or static
   analysis tool scan.

Please do not repost the series just to address the above. Instead,
reply to this email with the missing information, so that reviewers
can take it into account. If the series needs another revision for
other reasons, please include the information in the commit messages
then.

The evaluation is done by an LLM so it may be wrong, if you think
that is the case please reply and explain.

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-10-31 11:03 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-31 10:58 [SECURITY] net/ncsi: Fix heap OOB write in ncsi_rsp_handler_gp() MAC filter loop Maholi Tumanggor
2026-10-31 11:03 ` netdev-bot+sinfo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox