Files
git.stella-ops.org/docs/contracts/init-section-roots.md
StellaOps Bot f1a39c4ce3
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Notify Smoke Test / Notify Unit Tests (push) Has been cancelled
Notify Smoke Test / Notifier Service Tests (push) Has been cancelled
Notify Smoke Test / Notification Smoke Test (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
Manifest Integrity / Validate Schema Integrity (push) Has been cancelled
Manifest Integrity / Validate Contract Documents (push) Has been cancelled
Manifest Integrity / Validate Pack Fixtures (push) Has been cancelled
Manifest Integrity / Audit SHA256SUMS Files (push) Has been cancelled
Manifest Integrity / Verify Merkle Roots (push) Has been cancelled
devportal-offline / build-offline (push) Has been cancelled
Mirror Thin Bundle Sign & Verify / mirror-sign (push) Has been cancelled
up
2025-12-13 18:08:55 +02:00

327 lines
8.0 KiB
Markdown

# CONTRACT-INIT-ROOTS-401: Init-Section Synthetic Roots
> **Status:** Published
> **Version:** 1.0.0
> **Published:** 2025-12-13
> **Owners:** Scanner Guild, Policy Guild, Signals Guild
> **Unblocks:** SCANNER-INITROOT-401-036, EDGE-BUNDLE-401-054, and downstream tasks
## Overview
This contract defines how ELF/PE/Mach-O initialization sections (`.init_array`, `.ctors`, `DT_INIT`, etc.) are modeled as synthetic roots in reachability graphs. These roots represent code that executes during program load, before `main()`, and must be included in reachability analysis for complete vulnerability assessment.
---
## 1. Init-Section Categories
### 1.1 ELF Init Sections
| Section/Tag | Phase | Order | Description |
|-------------|-------|-------|-------------|
| `.preinit_array` / `DT_PREINIT_ARRAY` | `preinit` | 0-N | Executed before dynamic linker init |
| `.init` / `DT_INIT` | `init` | 0 | Single init function |
| `.init_array` / `DT_INIT_ARRAY` | `init` | 1-N | Array of init function pointers |
| `.ctors` | `init` | after init_array | Legacy C++ constructors |
| `.fini` / `DT_FINI` | `fini` | 0 | Single cleanup function |
| `.fini_array` / `DT_FINI_ARRAY` | `fini` | 1-N | Array of cleanup function pointers |
| `.dtors` | `fini` | after fini_array | Legacy C++ destructors |
### 1.2 PE Init Sections
| Mechanism | Phase | Order | Description |
|-----------|-------|-------|-------------|
| `DllMain` (DLL_PROCESS_ATTACH) | `init` | 0 | DLL initialization |
| TLS callbacks | `init` | 1-N | Thread-local storage callbacks |
| C++ global constructors | `init` | after TLS | Via CRT init table |
| `DllMain` (DLL_PROCESS_DETACH) | `fini` | 0 | DLL cleanup |
### 1.3 Mach-O Init Sections
| Section | Phase | Order | Description |
|---------|-------|-------|-------------|
| `__mod_init_func` | `init` | 0-N | Module init functions |
| `__mod_term_func` | `fini` | 0-N | Module termination functions |
---
## 2. Synthetic Root Schema
### 2.1 Root Object in richgraph-v1
```json
{
"roots": [
{
"id": "root:init:0:sym:binary:abc123...",
"phase": "init",
"source": "init_array",
"order": 0,
"target_id": "sym:binary:abc123...",
"binary_path": "/usr/lib/libfoo.so.1",
"build_id": "gnu-build-id:5f0c7c3c..."
}
]
}
```
### 2.2 Root ID Format
```
root:{phase}:{order}:{target_symbol_id}
```
**Examples:**
- `root:preinit:0:sym:binary:abc...` - First preinit function
- `root:init:0:sym:binary:def...` - DT_INIT function
- `root:init:1:sym:binary:ghi...` - First init_array entry
- `root:main:0:sym:binary:jkl...` - main() function
- `root:fini:0:sym:binary:mno...` - DT_FINI function
### 2.3 Phase Enumeration
| Phase | Numeric Order | Execution Time |
|-------|---------------|----------------|
| `load` | 0 | Dynamic linker resolution |
| `preinit` | 1 | Before dynamic init |
| `init` | 2 | During initialization |
| `main` | 3 | Program entry (main) |
| `fini` | 4 | During termination |
---
## 3. Root Discovery Algorithm
### 3.1 ELF Root Discovery
```
1. Parse .dynamic section for DT_PREINIT_ARRAY, DT_INIT, DT_INIT_ARRAY
2. For each array:
a. Read function pointer addresses
b. Resolve to symbol (if available) or emit unknown
c. Create root with phase + order
3. Find _start, main, _init, _fini symbols and add as roots
4. Sort roots by (phase, order, target_id) for determinism
```
### 3.2 Handling Unresolved Targets
When init array contains address without symbol:
```json
{
"roots": [
{
"id": "root:init:2:unknown:0x12345678",
"phase": "init",
"source": "init_array",
"order": 2,
"target_id": "unknown:0x12345678",
"resolved": false,
"reason": "No symbol at address 0x12345678"
}
],
"unknowns": [
{
"id": "unknown:0x12345678",
"type": "unresolved_init_target",
"address": "0x12345678",
"source": "init_array[2]"
}
]
}
```
---
## 4. DT_NEEDED Dependency Modeling
### 4.1 Purpose
`DT_NEEDED` entries specify shared library dependencies. These execute their init code before the depending binary's init code.
### 4.2 Schema
```json
{
"dependencies": [
{
"id": "dep:libssl.so.3",
"name": "libssl.so.3",
"source": "DT_NEEDED",
"order": 0,
"resolved_path": "/usr/lib/x86_64-linux-gnu/libssl.so.3",
"resolved_build_id": "gnu-build-id:abc..."
}
]
}
```
### 4.3 Init Order with Dependencies
```
1. libssl.so.3 preinit → init
2. libcrypto.so.3 preinit → init
3. libc.so.6 preinit → init
4. main_binary preinit → init → main
```
---
## 5. Patch Oracle Integration
### 5.1 Oracle Expected Roots
```json
{
"expected_roots": [
{
"id": "root:init:*:sym:binary:*",
"phase": "init",
"source": "init_array",
"required": true,
"reason": "Init function must be detected for CVE-2023-XXXX"
}
]
}
```
### 5.2 Oracle Forbidden Roots
```json
{
"forbidden_roots": [
{
"id": "root:preinit:*:*",
"phase": "preinit",
"reason": "Preinit code should not exist after patch"
}
]
}
```
---
## 6. Policy Integration
### 6.1 Reachability State with Init Roots
When evaluating reachability:
1. If vulnerable function is reachable from `main``REACHABLE`
2. If vulnerable function is reachable from `init` roots → `REACHABLE_INIT`
3. If vulnerable function is reachable only from `fini``REACHABLE_FINI`
### 6.2 Policy DSL Extensions
```yaml
# Require init-phase reachability for not_affected
rules:
- name: init-reachability-required
condition: |
vuln.phase_reachable.includes("init") and
reachability.confidence >= 0.8
action: require_evidence
- name: init-only-lower-severity
condition: |
reachability.reachable_phases == ["init"] and
not reachability.reachable_phases.includes("main")
action: reduce_severity
severity_adjustment: -1
```
---
## 7. Evidence Requirements
### 7.1 Init Root Evidence Bundle
```json
{
"root_evidence": {
"root_id": "root:init:0:sym:binary:...",
"extraction_method": "dynamic_section",
"source_offset": "0x1234",
"target_address": "0x5678",
"target_symbol": "frame_dummy",
"evidence_hash": "sha256:...",
"evidence_uri": "cas://binary/roots/sha256:..."
}
}
```
### 7.2 CAS Storage Layout
```
cas://reachability/roots/{graph_hash}/
init.json # All init-phase roots
fini.json # All fini-phase roots
dependencies.json # DT_NEEDED graph
evidence/
root:{id}.json # Per-root evidence
```
---
## 8. Determinism Rules
### 8.1 Root Ordering
Roots are sorted by:
1. Phase (numeric: load=0, preinit=1, init=2, main=3, fini=4)
2. Order within phase (numeric)
3. Target ID (string, ordinal)
### 8.2 Root ID Canonicalization
```
root_id = "root:" + phase + ":" + order + ":" + target_id
```
All components lowercase, no whitespace.
---
## 9. Implementation Status
| Component | Location | Status |
|-----------|----------|--------|
| ELF init parser | `NativeCallgraphBuilder.cs` | Implemented |
| Root model | `NativeSyntheticRoot` | Implemented |
| richgraph-v1 roots | `RichGraph.cs` | Implemented |
| Patch oracle roots | `PatchOracleComparer.cs` | Implemented |
| Policy integration | - | Pending |
| DT_NEEDED graph | - | Pending |
---
## 10. Test Fixtures
Location: `tests/Binary/fixtures/init-roots/`
| Fixture | Description |
|---------|-------------|
| `elf-simple-init/` | Binary with single init function |
| `elf-init-array/` | Binary with multiple init_array entries |
| `elf-preinit/` | Binary with preinit_array |
| `elf-ctors/` | Binary with .ctors section |
| `elf-stripped-init/` | Stripped binary with init |
| `pe-dllmain/` | PE DLL with DllMain |
| `pe-tls-callbacks/` | PE with TLS callbacks |
---
## 11. Related Contracts
- [richgraph-v1](./richgraph-v1.md) - Root schema in graphs
- [Build-ID Propagation](./buildid-propagation.md) - Binary identification
- [Patch Oracles](../reachability/patch-oracles.md) - Oracle validation
---
## Changelog
| Version | Date | Author | Changes |
|---------|------|--------|---------|
| 1.0.0 | 2025-12-13 | Scanner Guild | Initial contract for init-section roots |