feat: add native Windows hierarchy test harness

This commit is contained in:
2026-09-09 16:48:54 +00:00
parent 8985457d37
commit 409b64a2fb
30 changed files with 1033 additions and 44 deletions
@@ -43,7 +43,13 @@ type NativeOptions struct {
MaxWrapperBytes uint64
MaxOutputChunk uint64
WindowsTermGrace time.Duration
Now func() time.Time
// TestContextFailures is populated only by the separately tagged native
// fixture binary. It is deliberately not protocol or TOML policy: it lets
// the fixture fail token preparation before launch so the real daemon can
// prove its fallback order without creating a second broker or weakening a
// release binary.
TestContextFailures map[ExecutionContext]bool
Now func() time.Time
}
// JobProfile is the validated administrator policy for one protocol profile.
@@ -388,6 +388,10 @@ func (manager *execSupervisor) selectToken(elevated bool) (winapi.Token, supervi
}
for _, attempt := range selection.Attempts {
token, identity, err := openTokenForAttempt(attempt.Context, selected)
if err == nil && manager.options.TestContextFailures[attempt.Context] {
_ = token.Close()
err = errors.New("native test fixture forced pre-launch context failure")
}
if err == nil {
return token, withEvidence(identity), nil
}
@@ -396,6 +400,33 @@ func (manager *execSupervisor) selectToken(elevated bool) (winapi.Token, supervi
return 0, supervisor.EffectiveIdentity{}, rejection(err)
}
}
// Select stops at the first policy-available elevated context. Native
// preparation can still fail after that point (a linked token can vanish or
// SeTcbPrivilege can be unavailable), so preserve the documented order by
// trying ACTIVE_SYSTEM before the final LOCAL_SYSTEM fallback. This is a
// preparation fallback only: no child has been created yet.
if elevated && selected != nil {
seenActiveSystem := false
for _, contextName := range attempted {
if contextName == string(ContextActiveSystem) {
seenActiveSystem = true
break
}
}
if !seenActiveSystem {
addAttempt(ContextActiveSystem, "fallback after active-user-elevated preparation failure")
if token, identity, err := openTokenForAttempt(ContextActiveSystem, selected); err == nil {
if manager.options.TestContextFailures[ContextActiveSystem] {
_ = token.Close()
addAttempt(ContextActiveSystem, "native test fixture forced pre-launch context failure")
} else {
return token, withEvidence(identity), nil
}
} else {
addAttempt(ContextActiveSystem, "native preparation failed: "+err.Error())
}
}
}
// The pure selector stops as soon as ACTIVE_SYSTEM is available. A native
// privilege/session operation can still fail (for example, SeTcb was
// removed), so the final LOCAL_SYSTEM fallback is attempted here before
@@ -0,0 +1,15 @@
//go:build !rvbox_native_test
package windows
import "fmt"
// NativeTestContextFailures is intentionally unavailable in shipped binaries.
// The native fixture compiles a separately tagged test executable when it
// needs to prove a pre-launch fallback row.
func NativeTestContextFailures(raw string) (map[ExecutionContext]bool, error) {
if raw != "" {
return nil, fmt.Errorf("--test-fail-contexts requires the rvbox_native_test fixture build")
}
return nil, nil
}
@@ -0,0 +1,28 @@
//go:build rvbox_native_test
package windows
import (
"fmt"
"strings"
)
// NativeTestContextFailures accepts only the two active elevated preparation
// stages. It is compiled into the disposable native-fixture binary, never a
// release binary, and is applied before a process is launched.
func NativeTestContextFailures(raw string) (map[ExecutionContext]bool, error) {
if raw == "" {
return nil, nil
}
result := make(map[ExecutionContext]bool)
for _, item := range strings.Split(raw, ",") {
contextName := ExecutionContext(strings.TrimSpace(item))
switch contextName {
case ContextActiveUserElevated, ContextActiveSystem:
result[contextName] = true
default:
return nil, fmt.Errorf("unsupported native test context %q", item)
}
}
return result, nil
}