https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=297437

            Bug ID: 297437
           Summary: netmap: unchecked NR_REG_NULL slot count overflows
                    ring allocation size
           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 273624
  --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=273624&action=edit
Deterministic two-call RX slot-count overflow reproducer

Overview
  ========

  The NETMAP_REQ_REGISTER path for an NR_REG_NULL adapter accepts
  user-controlled TX/RX ring and slot counts without applying the geometry
  bounds used by other netmap adapter types.

  A slot count of 0xfffffffe reaches netmap_mem2_rings_create(), where the ring
  allocation length is calculated in a 32-bit u_int. The multiplication and
  addition wrap to a small allocation size. The kernel then initializes or
  traverses the allocation using the original slot count, causing an
  out-of-bounds kernel memory access and panic.

  Both the RX-slot and TX-slot variants reproduced deterministically.

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

  Operating system: FreeBSD 14.4-STABLE
  Architecture: amd64
  Kernel ident: SYZKALLER
  Base image source revision: cc921088d9ee
  Base image date: 2026-05-14
  Virtualization: QEMU/KVM

  The kernel is based on the FreeBSD 14.4-STABLE amd64 image identified by
  revision cc921088d9ee, with the SYZKALLER kernel
  configuration/instrumentation.

  The reported reproductions were performed as root in clean snapshot VMs.
  Unprivileged-user and jail reachability have not been tested.

  Reproducer
  ==========

  The attached RX .syz reproducer executes two calls:

      r0 = openat$netmap(...)
      ioctl$NIOCCTRL(r0, NIOCCTRL, {
          nr_reqtype = NETMAP_REQ_REGISTER,
          nr_name = "null-overflow-rx",
          nr_mode = NR_REG_NULL,
          nr_mem_id = 1,
          nr_tx_slots = 0x10,
          nr_rx_slots = 0xfffffffe
      })

  The attached TX variant exchanges the slot counts:

      nr_tx_slots = 0xfffffffe
      nr_rx_slots = 0x10

  The RX program panicked on its first execution in two independent cold boots.
  The TX program panicked on its first execution in a third independent cold
  boot.

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

  All three deterministic runs produced:

      panic: vm_fault_lookup: fault on nofault entry,
          addr: 0xfffffe007bc00000

  Relevant stack:

      panic
      vm_fault
      vm_fault_trap
      trap_pfault
      netmap_mem_rings_create+0x84
      netmap_do_regif+0x5b3
      netmap_ioctl+0x1cf0
      freebsd_netmap_ioctl+0xa5
      devfs_ioctl
      vn_ioctl
      kern_ioctl
      sys_ioctl

  The same fault address was observed in both RX cold-boot runs and in the
  independent TX cold-boot run.

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

  The kernel should reject or safely bound invalid ring geometry. A
  user-controlled slot count must not overflow the kernel allocation length or
  cause an out-of-bounds kernel memory access.

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

  netmap_get_null_na() copies all four geometry values from the
  nmreq_register request without applying the nm_bound_var() checks used by
  VALE, pipe, and monitor adapters:

      nna->up.num_tx_rings = req->nr_tx_rings;
      nna->up.num_rx_rings = req->nr_rx_rings;
      nna->up.num_tx_desc = req->nr_tx_slots;
      nna->up.num_rx_desc = req->nr_rx_slots;

  The minimal reproducer selects the existing default allocator with
  nr_mem_id = 1.

  The unchecked slot count is copied to kring->nkr_num_slots. In
  netmap_mem2_rings_create(), the allocation length is calculated using
  32-bit u_int variables:

      u_int len, ndesc;

      ndesc = kring->nkr_num_slots;
      len = sizeof(struct netmap_ring) +
          ndesc * sizeof(struct netmap_slot);

  For ndesc = 0xfffffffe, this expression wraps in 32 bits. A small allocation
  can consequently be returned and later accessed as if it contained almost
  UINT32_MAX slots.

  This is an arithmetic and validation bug, rather than a normal allocation
  failure.

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

  Two layers of validation are suggested:

  1. Apply explicit ring-count and slot-count limits in netmap_get_null_na(),
     consistent with the bounds applied to other software adapter types.

  2. Add a common integer-overflow check in netmap_mem2_rings_create() before
     calculating:

         sizeof(struct netmap_ring) +
             ndesc * sizeof(struct netmap_slot)

  A proposed stable/14 patch is attached. It has not yet been tested against
  FreeBSD main and is provided for discussion rather than as a final reviewed
  fix.

  Impact
  ======

  The demonstrated impact is a deterministic local kernel panic and an
  out-of-bounds kernel memory access caused by an integer-overflowed allocation
  size.

  Because the issue involves kernel memory corruption, a stronger security
  impact may be possible, but exploitability has not been assessed.

  Triggering the issue requires access to /dev/netmap. The reproductions
  reported here were performed as root. Default unprivileged and jail
  reachability have not been tested.

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

  The issue was reproduced on stable/14. Source review found the same relevant
  unchecked NULL-adapter geometry and 32-bit allocation calculation in the
  corresponding current netmap code, but the panic has not yet been reproduced
  on FreeBSD main.

  Reproduction evidence
  =====================

  Three independent clean cold-boot runs are attached:

  1. RX slot overflow, first run:
     SHA-256:
     ca04e711334b9d78d4ee501eae130678b9e7e5b89a193b2077569b0f1b7dedae

  2. RX slot overflow, second run:
     SHA-256:
     b4b51888a18eb6c37d0b4b2b48abbfa08283f8e8c7f61ffe2eebaf8fcb13bb2

  3. TX slot overflow:
     SHA-256:
     f7cff58b82631f92dc2850b0c9e827b4118084431b5367980ecbefd2ddb484eb

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

  The issue was discovered and reproduced using syzkaller with locally
  developed FreeBSD netmap syscall descriptions and structured seed programs.

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

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

Reply via email to