Skip to content

feat: implement stack protection - #2462

Open
zyuiop wants to merge 2 commits into
hermit-os:mainfrom
hermit-sev:feat/stack-protection
Open

zyuiop wants to merge 2 commits into
hermit-os:mainfrom
hermit-sev:feat/stack-protection

Conversation

@zyuiop

@zyuiop zyuiop commented Jun 3, 2026 •

Copy link
Copy Markdown
Contributor

Isolate stacks in a separate virtual address space, just before the heap.
This ensures that stack overflows cause a page fault instead of silently corrupting the heap (for heap based stacks) or the page table (for the boot stack).

This has been tested only for x86_64 with UEFI, and will definitely not work on other platforms.

TODO:

  • Test/Fix on other platforms
  • Ensure we do this for all stacks (maybe it's not the case for IDT stacks after the first one)

@zyuiop
zyuiop marked this pull request as draft June 3, 2026 11:04

@github-actions github-actions Bot left a comment •

Copy link
Copy Markdown

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: b5c5ad2 Previous: 2e23902 Performance Ratio
startup_benchmark Build Time 89.88 s 80.34 s 1.12 ❗
startup_benchmark File Size 0.86 MB 0.80 MB 1.08 ❗
Startup Time - 1 core 0.73 s (±0.02 s) 0.75 s (±0.02 s) 0.98
Startup Time - 2 cores 0.74 s (±0.02 s) 0.74 s (±0.02 s) 1.01
Startup Time - 4 cores 0.75 s (±0.02 s) 0.74 s (±0.02 s) 1.02
multithreaded_benchmark Build Time 92.44 s 82.11 s 1.13 ❗
multithreaded_benchmark File Size 0.90 MB 0.86 MB 1.05 ❗
Multithreaded Pi Efficiency - 2 Threads 88.39 % (±9.65 %) 85.89 % (±6.61 %) 1.03
Multithreaded Pi Efficiency - 4 Threads 44.26 % (±3.47 %) 43.43 % (±2.56 %) 1.02
Multithreaded Pi Efficiency - 8 Threads 25.63 % (±1.65 %) 25.76 % (±1.53 %) 1.00
micro_benchmarks Build Time 97.65 s 80.40 s 1.21 ❗
micro_benchmarks File Size 0.90 MB 0.86 MB 1.05 ❗
Scheduling time - 1 thread 64.16 ticks (±3.20 ticks) 62.65 ticks (±4.06 ticks) 1.02
Scheduling time - 2 threads 34.89 ticks (±3.01 ticks) 34.08 ticks (±4.10 ticks) 1.02
Micro - Time for syscall (getpid) 3.77 ticks (±0.65 ticks) 3.45 ticks (±0.58 ticks) 1.09
Memcpy speed - (built_in) block size 4096 81176.67 MByte/s (±56258.31 MByte/s) 82448.38 MByte/s (±56997.13 MByte/s) 0.98
Memcpy speed - (built_in) block size 1048576 30171.36 MByte/s (±24431.69 MByte/s) 30585.98 MByte/s (±24707.84 MByte/s) 0.99
Memcpy speed - (built_in) block size 16777216 26514.13 MByte/s (±21950.41 MByte/s) 26340.06 MByte/s (±21720.96 MByte/s) 1.01
Memset speed - (built_in) block size 4096 80841.29 MByte/s (±56031.38 MByte/s) 82292.76 MByte/s (±56891.50 MByte/s) 0.98
Memset speed - (built_in) block size 1048576 30904.09 MByte/s (±24856.46 MByte/s) 31323.85 MByte/s (±25145.86 MByte/s) 0.99
Memset speed - (built_in) block size 16777216 27255.30 MByte/s (±22407.85 MByte/s) 27104.68 MByte/s (±22209.94 MByte/s) 1.01
Memcpy speed - (rust) block size 4096 72475.66 MByte/s (±50676.10 MByte/s) 74097.96 MByte/s (±51811.44 MByte/s) 0.98
Memcpy speed - (rust) block size 1048576 30008.05 MByte/s (±24356.26 MByte/s) 30361.60 MByte/s (±24602.37 MByte/s) 0.99
Memcpy speed - (rust) block size 16777216 26929.93 MByte/s (±22250.45 MByte/s) 27625.34 MByte/s (±22806.88 MByte/s) 0.97
Memset speed - (rust) block size 4096 72458.85 MByte/s (±50665.29 MByte/s) 74373.47 MByte/s (±51976.48 MByte/s) 0.97
Memset speed - (rust) block size 1048576 30765.46 MByte/s (±24798.95 MByte/s) 31110.89 MByte/s (±25033.24 MByte/s) 0.99
Memset speed - (rust) block size 16777216 27705.69 MByte/s (±22736.00 MByte/s) 28386.93 MByte/s (±23265.03 MByte/s) 0.98
alloc_benchmarks Build Time 83.49 s 74.76 s 1.12 ❗
alloc_benchmarks File Size 0.94 MB 0.87 MB 1.07 ❗
Allocations - Allocation success 91.37 % 91.31 % 1.00 ❗
Allocations - Deallocation success 100.00 % 100.00 % 1
Allocations - Pre-fail Allocations 61.60 % 61.44 % 1.00 ❗
Allocations - Average Allocation time 3994.58 Ticks (±776.93 Ticks) 5860.58 Ticks (±98.43 Ticks) 0.68 ❗
Allocations - Average Allocation time (no fail) 4929.33 Ticks (±735.98 Ticks) 6554.81 Ticks (±92.86 Ticks) 0.75 ❗
Allocations - Average Deallocation time 1284.58 Ticks (±181.07 Ticks) 1805.01 Ticks (±250.35 Ticks) 0.71 ❗
mutex_benchmark Build Time 143.49 s 79.82 s 1.80 ❗
mutex_benchmark File Size 0.90 MB 0.86 MB 1.05 ❗
Mutex Stress Test Average Time per Iteration - 1 Threads 12.16 ns (±0.42 ns) 12.10 ns (±0.41 ns) 1.00
Mutex Stress Test Average Time per Iteration - 2 Threads 65.34 ns (±3.17 ns) 40.26 ns (±1.68 ns) 1.62 ❗

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

@zyuiop
zyuiop force-pushed the feat/stack-protection branch 2 times, most recently from 8b21c11 to 2774988 Compare June 5, 2026 15:20
@zyuiop

zyuiop commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

Okay I have spent some time trying to port to arm/riscV

@zyuiop
zyuiop marked this pull request as ready for review June 5, 2026 15:21
@zyuiop
zyuiop force-pushed the feat/stack-protection branch 4 times, most recently from c1c52b7 to 7b12cb1 Compare June 5, 2026 17:25
@zyuiop

zyuiop commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

I extracted the first two commits to #2466 so they can be merged independently :)

@zyuiop
zyuiop force-pushed the feat/stack-protection branch 2 times, most recently from 0a487f6 to cb2b4e8 Compare June 5, 2026 20:43
@zyuiop

zyuiop commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

Note than on ARM/RISC, the boot stack is not moved as we do in x86_64, so it is not protected.

I have a branch for RISCV on my PC, I can push it if there is interest.

@zyuiop

zyuiop commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

I can reproduce the Laplace iterations problem locally on main too, so I don't think this is my fault

@mkroening mkroening left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could you rebase and squash any fixup commits? I believe some are already merged, though.

@zyuiop

zyuiop commented Aug 24, 2026 •

Copy link
Copy Markdown
Contributor Author

my local rustfmt disagrees with the CI, how??
image

@zyuiop
zyuiop force-pushed the feat/stack-protection branch from 6035308 to 19da4fe Compare August 24, 2026 10:54
@github-actions github-actions Bot added the xtask label Aug 24, 2026
@zyuiop
zyuiop force-pushed the feat/stack-protection branch 5 times, most recently from a3e2aa8 to 3390f08 Compare August 24, 2026 13:41
@zyuiop

zyuiop commented Aug 25, 2026 •

Copy link
Copy Markdown
Contributor Author

I had to reduce the task stack size, otherwise the multi-processor/multi-task uhyve task was failing (4MB available for stacks was not enough when each stack takes 1MB).

In practice, user tasks spawned by the hermit-rs still use the old value, so this fix just frees-up the necessary 512KB for the multiple guard pages.

@stlankes

stlankes commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

@zyuiop Can you resolve the conflicts.

@zyuiop
zyuiop force-pushed the feat/stack-protection branch 2 times, most recently from 5427ec9 to 89fe984 Compare September 9, 2026 15:47
@zyuiop
zyuiop force-pushed the feat/stack-protection branch from 89fe984 to c487bc6 Compare September 29, 2026 10:02
@zyuiop
zyuiop force-pushed the feat/stack-protection branch from c487bc6 to b5c5ad2 Compare October 5, 2026 12:52

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants