Skip to content

Linux map_file_cow leaks VMA entries (missing munmap on success path) #1290

Closed as duplicate

Description

@simongdavies

Summary

MultiUseSandbox::map_file_cow on Linux calls libc::mmap(MAP_PRIVATE) but never calls munmap on the success path. Each call leaks one kernel VMA (vm_area_struct), which counts against the per-process vm.max_map_count limit (default: 65530).

Physical memory is NOT leaked — all mmaps of the same file share the kernel page cache. The leak is purely a VMA slot leak (~200 bytes of kernel metadata per entry). However, a long-running service that churns sandboxes with map_file_cow will eventually hit vm.max_map_count and subsequent mmap calls will fail with ENOMEM.

The vm.max_map_count limit is a kernel-wide sysctl, not a per-process resource limit — it cannot be raised with ulimit, only via sudo sysctl -w vm.max_map_count=<value>.

What's leaked per call

Resource Leaked? Impact
Kernel VMA (vm_area_struct) Yes — ~200 bytes Counts against vm.max_map_count (default 65530)
Virtual address space Yes — one page-aligned region Negligible on 64-bit (128TB user VA space)
Physical RAM (page cache) No — shared across all mmaps of the same file Kernel reclaims under memory pressure
File descriptor No — File is dropped (fd closed) after mmap; kernel holds inode ref internally Released on munmap

Root Cause

The raw *mut c_void pointer returned by libc::mmap is cast to usize and stored in MemoryRegion.host_region — a plain integer with no ownership or Drop semantics. Nothing in the cleanup chain calls munmap:

  • HyperlightVm::unmap_region — removes the KVM/MSHV slot only, does not munmap
  • HyperlightVm::Drop — only calls interrupt_handle.set_dropped()
  • MultiUseSandbox — has no Drop impl
  • Snapshot restore() — calls unmap_region for stale regions (same problem)

The error path in map_file_cow correctly calls munmap, confirming the success path omission is an oversight.

Proposed Fix

Introduce a Linux OwnedFileMapping struct that stores the mmap pointer and size with a Drop impl calling libc::munmap. Track these in a Vec on MultiUseSandbox and clean up in restore() (when regions are unmapped during snapshot restore) and on MultiUseSandbox::Drop (catch-all for remaining mappings).

Activity

  1. simongdavies commented on Mar 11, 2026

    @simongdavies
    MemberAuthor

    Duplicate #700

  2. added
    lifecycle/confirmedBug is verified or proposal seems reasonable
    lifecycle/duplicateThis issue is a duplicate of another issue
    and removed
    lifecycle/confirmedBug is verified or proposal seems reasonable
    on Mar 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

lifecycle/duplicateThis issue is a duplicate of another issue

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions