[Bug 297437] netmap: unchecked NR_REG_NULL slot count overflows ring allocation size

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