Skip to content

Comments

fix(mmio): don't return MMIO virtual addresses to the free list (use-after-free)#2255

Open
edef1c wants to merge 1 commit intohermit-os:mainfrom
edef1c:push-tmolxxwyrpqn
Open

fix(mmio): don't return MMIO virtual addresses to the free list (use-after-free)#2255
edef1c wants to merge 1 commit intohermit-os:mainfrom
edef1c:push-tmolxxwyrpqn

Conversation

@edef1c
Copy link

@edef1c edef1c commented Feb 16, 2026

In check_linux_args, we return VAs to the free list while a VolatileRef to them is active. This breaks multi-device configurations. A similar bug exists in guess_device, but the current version of this patch doesn't fix it, since my reference target supplies mmio args.

@edef1c edef1c force-pushed the push-tmolxxwyrpqn branch 3 times, most recently from 5aa7ecd to 253b948 Compare February 16, 2026 01:15
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark Results

Details
Benchmark Current: cb881f1 Previous: 4912505 Performance Ratio
startup_benchmark Build Time 99.27 s 99.11 s 1.00
startup_benchmark File Size 0.86 MB 0.86 MB 1.00
Startup Time - 1 core 0.97 s (±0.02 s) 0.96 s (±0.03 s) 1.01
Startup Time - 2 cores 0.97 s (±0.03 s) 0.96 s (±0.03 s) 1.00
Startup Time - 4 cores 0.97 s (±0.03 s) 0.96 s (±0.02 s) 1.01
multithreaded_benchmark Build Time 101.80 s 102.01 s 1.00
multithreaded_benchmark File Size 0.95 MB 0.95 MB 1.00
Multithreaded Pi Efficiency - 2 Threads 91.12 % (±6.64 %) 85.65 % (±8.90 %) 1.06
Multithreaded Pi Efficiency - 4 Threads 45.02 % (±2.75 %) 43.12 % (±3.13 %) 1.04
Multithreaded Pi Efficiency - 8 Threads 26.44 % (±1.80 %) 25.03 % (±1.95 %) 1.06
micro_benchmarks Build Time 112.93 s 114.00 s 0.99
micro_benchmarks File Size 0.96 MB 0.96 MB 1.00
Scheduling time - 1 thread 69.86 ticks (±3.84 ticks) 70.19 ticks (±3.58 ticks) 1.00
Scheduling time - 2 threads 38.47 ticks (±4.79 ticks) 38.99 ticks (±4.43 ticks) 0.99
Micro - Time for syscall (getpid) 2.94 ticks (±0.26 ticks) 2.96 ticks (±0.24 ticks) 0.99
Memcpy speed - (built_in) block size 4096 63522.17 MByte/s (±45339.86 MByte/s) 64026.03 MByte/s (±45553.92 MByte/s) 0.99
Memcpy speed - (built_in) block size 1048576 29963.60 MByte/s (±24956.52 MByte/s) 29743.12 MByte/s (±24826.10 MByte/s) 1.01
Memcpy speed - (built_in) block size 16777216 25666.85 MByte/s (±21512.30 MByte/s) 24007.89 MByte/s (±20230.77 MByte/s) 1.07
Memset speed - (built_in) block size 4096 63985.25 MByte/s (±45622.98 MByte/s) 64637.10 MByte/s (±45951.78 MByte/s) 0.99
Memset speed - (built_in) block size 1048576 30754.88 MByte/s (±25394.92 MByte/s) 30516.60 MByte/s (±25260.76 MByte/s) 1.01
Memset speed - (built_in) block size 16777216 26362.96 MByte/s (±21919.69 MByte/s) 24779.16 MByte/s (±20739.68 MByte/s) 1.06
Memcpy speed - (rust) block size 4096 58330.20 MByte/s (±43048.88 MByte/s) 60077.78 MByte/s (±44331.51 MByte/s) 0.97
Memcpy speed - (rust) block size 1048576 29827.70 MByte/s (±24862.50 MByte/s) 29870.69 MByte/s (±24878.06 MByte/s) 1.00
Memcpy speed - (rust) block size 16777216 24954.47 MByte/s (±21049.51 MByte/s) 24212.89 MByte/s (±20297.89 MByte/s) 1.03
Memset speed - (rust) block size 4096 59114.01 MByte/s (±43499.71 MByte/s) 60925.02 MByte/s (±44834.41 MByte/s) 0.97
Memset speed - (rust) block size 1048576 30628.95 MByte/s (±25305.17 MByte/s) 30651.78 MByte/s (±25309.43 MByte/s) 1.00
Memset speed - (rust) block size 16777216 25729.58 MByte/s (±21546.95 MByte/s) 24986.00 MByte/s (±20809.17 MByte/s) 1.03
alloc_benchmarks Build Time 104.48 s 105.28 s 0.99
alloc_benchmarks File Size 0.93 MB 0.93 MB 1.00
Allocations - Allocation success 100.00 % 100.00 % 1
Allocations - Deallocation success 100.00 % 100.00 % 1
Allocations - Pre-fail Allocations 100.00 % 100.00 % 1
Allocations - Average Allocation time 12659.28 Ticks (±165.88 Ticks) 9727.01 Ticks (±267.20 Ticks) 1.30
Allocations - Average Allocation time (no fail) 12659.28 Ticks (±165.88 Ticks) 9727.01 Ticks (±267.20 Ticks) 1.30
Allocations - Average Deallocation time 1065.63 Ticks (±771.58 Ticks) 2219.93 Ticks (±959.95 Ticks) 0.48
mutex_benchmark Build Time 103.58 s 104.33 s 0.99
mutex_benchmark File Size 0.96 MB 0.96 MB 1.00
Mutex Stress Test Average Time per Iteration - 1 Threads 12.92 ns (±0.66 ns) 12.84 ns (±0.76 ns) 1.01
Mutex Stress Test Average Time per Iteration - 2 Threads 15.66 ns (±0.76 ns) 15.44 ns (±0.78 ns) 1.01

This comment was automatically generated by workflow using github-action-benchmark.

@mkroening mkroening self-assigned this Feb 16, 2026
@edef1c
Copy link
Author

edef1c commented Feb 16, 2026

FWIW, it is not totally clear to me why PageBox merely reserves the VA, and leaks the mapping / doesn't unmap on Drop; the VA use-after-free would have been dead obvious in all cases with a more RAII-style design.

check_linux_args MMIO device registers into a PageBox-allocated VA,
then return a VolatileRef<'static> pointing at it. When the PageBox
is dropped, the VA range goes back to the free list. A subsequent
allocation could reuse and remap the same VA, corrupting the driver's
VolatileRef.

Use into_raw() to prevent the VA from being reclaimed when a device
is found.
@edef1c edef1c changed the title fix(mmio) fix(mmio): don't return MMIO virtual addresses to the free list (use-after-free) Feb 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants