[Bug 297436] netmap: signed nr_port_idx causes out-of-bounds access in netmap_vale_list()

From: <bugzilla-noreply_at_freebsd.org>
Date: Tue, 11 Aug 2026 13:16:39 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=297436

            Bug ID: 297436
           Summary: netmap: signed nr_port_idx causes out-of-bounds access
                    in netmap_vale_list()
           Product: Base System
           Version: 14.4-STABLE
          Hardware: amd64
                OS: Any
            Status: New
          Severity: Affects Some People
          Priority: ---
         Component: kern
          Assignee: bugs@FreeBSD.org
          Reporter: yangyang20250212@163.com

Created attachment 273622
  --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=273622&action=edit
netmap: signed nr_port_idx causes out-of-bounds access in netmap_vale_list()C
reproducer

Overview
  ========

  The NETMAP_REQ_VALE_LIST request accepts nr_port_idx as a uint32_t, but
  netmap_vale_list() assigns it to a signed int and subsequently uses it as an
  array index without validating that it is non-negative.

  On amd64, values greater than INT_MAX become negative after the conversion.
  A request with nr_port_idx = 0x80000000 therefore causes an out-of-bounds
  access to b->bdg_ports[j] and a kernel page fault.

  Tested environment
  ==================

  Operating system: FreeBSD 14.4-STABLE
  Architecture: amd64
  Kernel configuration: <fill in>
  Kernel source commit: <fill in>
  uname -a: <fill in>

  The issue was reproduced in a clean QEMU/KVM virtual machine.

  Reproducer
  ==========

  The attached native C program performs:

  1. open("/dev/netmap", O_RDWR)
  2. NIOCCTRL with:
     - nr_reqtype = NETMAP_REQ_VALE_LIST
     - nr_port_idx = 0x80000000

  Compile and execute on FreeBSD:

      cc -Wall -O2 -o netmap_vale_list_oob manual_negative_port_idx.c
      ./netmap_vale_list_oob

  The trigger caused the same kernel panic on the first execution in two
  independent cold boots.

  Observed result
  ===============

  Fatal trap 12: page fault while in kernel mode

  The deterministic runs had:

      instruction pointer: 0xffffffff80a26750
      fault address:       0xfffffdfc0ccd0828
      function:            netmap_vale_list+0x150
      caller:              netmap_ioctl+0xe3e

  Relevant stack:

      panic
      trap_pfault
      netmap_vale_list+0x150
      netmap_ioctl+0xe3e
      freebsd_netmap_ioctl
      devfs_ioctl
      vn_ioctl
      kern_ioctl
      sys_ioctl

  Expected result
  ===============

  The kernel should reject an out-of-range nr_port_idx and return an error. A
  user-supplied request must not cause an out-of-bounds kernel array access or
  panic.

  Root cause
  ==========

  nr_port_idx is defined as uint32_t, but netmap_vale_list() stores it in the
  signed variable j:

      int error = 0, i, j;

      j = req->nr_port_idx;

  The loop checks only:

      j < NM_BDG_MAXPORTS

  It does not check j >= 0. After conversion, 0x80000000 becomes a negative
  signed int on the tested amd64 kernel and is used directly in:

      b->bdg_ports[j]

  Suggested fix
  =============

  Keep the port index unsigned, or explicitly reject values greater than
  INT_MAX / outside the valid port range before indexing the array.

  A proposed stable/14 patch is attached. It changes j from int to uint32_t.
  The patch has not yet been tested against FreeBSD main.

  Impact
  ======

  The demonstrated impact is a local kernel panic and out-of-bounds kernel
  memory access. Exploitability has not been assessed.

  Triggering the issue requires access to /dev/netmap. The reproductions were
  performed as <root/non-root -- fill in the actual result>. I have not yet
  determined whether the issue is reachable by an unprivileged user under the
  default device permissions or from a jail.

  Affected branches
  =================

  The issue was reproduced on stable/14. The corresponding source pattern
  appears to be present in FreeBSD main, but I have not yet reproduced the
panic
  on main.

  Tools used
  ==========

  The issue was initially discovered using syzkaller with locally developed
  FreeBSD netmap syscall descriptions and structured seeds. The final native C
  reproducer does not require syzkaller.

  AI-assisted tools were used to help organize experiment artifacts, inspect
  crash logs, and draft the report. The fault location, source-level analysis,
  and reproduction results were manually checked against the saved kernel
  image and source tree

-- 
You are receiving this mail because:
You are the assignee for the bug.