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

[email protected]
Newsgroups gmane.os.freebsd.bugs
Message-ID <[email protected]/bugzilla/>
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: [email protected]
          Reporter: [email protected]

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.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.