mirror of https://lore.kernel.org/lkml/
 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

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

all inboxes | Powered by JetHome®