Reproducible and Auditable Execution
A comprehensive framework ensuring deterministic execution for reproducibility and auditability. Provides mechanisms to capture, replay, and verify execution traces with cryptographic guarantees, enabling reproducible builds, forensic analysis, and compliance verification.
deterministic-executor enables reproducible execution by controlling sources of non-determinism in programs. It captures complete execution traces, supports deterministic replay, and provides cryptographic verification of execution correctness.
- Deterministic Execution: Control all sources of non-determinism
- Execution Recording: Capture complete execution traces
- Deterministic Replay: Reproduce exact execution behavior
- Cryptographic Verification: Tamper-proof execution logs
- Time Virtualization: Deterministic time and timestamps
- Entropy Control: Deterministic random number generation
- Input/Output Recording: Capture all I/O operations
- Multi-Process Support: Deterministic execution of process trees
- Network Replay: Record and replay network interactions
- File System Snapshots: Capture filesystem state
- Signal Determinism: Deterministic signal delivery
- Thread Scheduling: Deterministic multi-threaded execution
- System Call Recording: Complete syscall trace logs
- Merkle Trees: Cryptographic execution attestation
- Reproducible Builds: Ensure bit-for-bit identical builds
- Forensic Analysis: Analyze security incidents
- Compliance Auditing: Prove correct execution
- Testing & Debugging: Reproduce race conditions
- Scientific Computing: Reproducible experiments
- Blockchain Execution: Deterministic smart contracts
┌─────────────────────────────────────────────┐
│ Application Layer │
│ (Application under deterministic execution)│
└─────────────────┬───────────────────────────┘
│
┌─────────────────▼───────────────────────────┐
│ Determinism Control Layer │
│ - Time Virtualization │
│ - Entropy Management │
│ - Signal Control │
│ - Thread Scheduler │
└─────────────────┬───────────────────────────┘
│
┌─────────────────▼───────────────────────────┐
│ Recording & Replay Engine │
│ - Syscall Interceptor │
│ - I/O Recorder │
│ - State Snapshotter │
│ - Replay Controller │
└─────────────────┬───────────────────────────┘
│
┌─────────────────▼───────────────────────────┐
│ Cryptographic Verification │
│ - Hash Chain │
│ - Merkle Tree │
│ - Signature Generation │
│ - Attestation │
└─────────────────────────────────────────────┘
git submodule add https://github.com/navinBRuas/_SecureExecutionEnvironment.git vendor/secure-execution
cd vendor/secure-execution/deterministic-executor
makemake install PREFIX=/usr/local#include <deterministic-executor/detexec.h>
int main() {
// Create deterministic execution context
detexec_context_t *ctx = detexec_new();
// Configure determinism
detexec_config_t config = {
.deterministic_time = true,
.deterministic_entropy = true,
.record_execution = true,
.output_path = "execution.trace"
};
detexec_set_config(ctx, &config);
// Execute program deterministically
const char *argv[] = {"/usr/bin/myapp", "--option", NULL};
detexec_result_t result;
if (detexec_exec(ctx, "/usr/bin/myapp", argv, &result) != 0) {
fprintf(stderr, "Execution failed\n");
return 1;
}
printf("Execution completed: exit=%d\n", result.exit_code);
printf("Trace saved to: %s\n", config.output_path);
printf("Trace hash: %s\n", result.trace_hash);
detexec_free(ctx);
return 0;
}#include <deterministic-executor/detexec.h>
int main() {
// Create replay context
detexec_context_t *ctx = detexec_new();
// Load execution trace
detexec_trace_t *trace = detexec_load_trace("execution.trace");
if (!trace) {
fprintf(stderr, "Failed to load trace\n");
return 1;
}
// Verify trace integrity
if (!detexec_verify_trace(trace)) {
fprintf(stderr, "Trace verification failed\n");
return 1;
}
// Replay execution
detexec_result_t result;
if (detexec_replay(ctx, trace, &result) != 0) {
fprintf(stderr, "Replay failed\n");
return 1;
}
printf("Replay completed successfully\n");
printf("Output hash matches: %s\n",
result.output_verified ? "yes" : "no");
detexec_free_trace(trace);
detexec_free(ctx);
return 0;
}from deterministic_executor import DetExec, DetExecConfig
# Configure deterministic execution
config = DetExecConfig(
deterministic_time=True,
deterministic_entropy=True,
record_execution=True,
output_path='execution.trace'
)
# Execute deterministically
executor = DetExec(config)
result = executor.exec(['/usr/bin/myapp', '--option'])
print(f"Exit code: {result.exit_code}")
print(f"Trace hash: {result.trace_hash}")
# Later: replay execution
trace = DetExec.load_trace('execution.trace')
replay_result = executor.replay(trace)
assert replay_result.output_verifiedCreate a new deterministic execution context.
Free a context and release resources.
Configure deterministic execution parameters.
Execute a program deterministically.
Execute with custom environment.
Spawn a deterministic process.
Start recording execution trace.
Stop recording and finalize trace.
Get statistics about recorded trace.
Load a trace file.
Replay a recorded execution.
Replay up to a specific event.
Verify cryptographic integrity of trace.
Compute hash of execution trace.
Sign trace with private key.
Verify trace signature.
Set the virtual time for execution.
Set time scaling factor (1.0 = normal).
Set deterministic random seed.
Set custom entropy source.
typedef struct {
bool deterministic_time; /* Virtualize time */
bool deterministic_entropy; /* Control randomness */
bool deterministic_signals; /* Deterministic signal delivery */
bool deterministic_threads; /* Deterministic thread scheduling */
bool record_execution; /* Record trace */
const char *output_path; /* Trace output file */
uint64_t virtual_time_start; /* Starting virtual time */
uint64_t random_seed; /* Random seed */
} detexec_config_t;typedef struct {
bool record_syscalls; /* Record all syscalls */
bool record_io; /* Record I/O operations */
bool record_network; /* Record network traffic */
bool record_filesystem; /* Snapshot filesystem state */
bool cryptographic_verification;/* Enable crypto verification */
const char *hash_algorithm; /* Hash algorithm (SHA256, etc.) */
bool enable_compression; /* Compress trace files */
size_t max_trace_size; /* Maximum trace size */
} detexec_advanced_config_t;#include <deterministic-executor/detexec.h>
int reproducible_build(const char *source_dir, const char *output_dir) {
detexec_context_t *ctx = detexec_new();
detexec_config_t config = {
.deterministic_time = true,
.deterministic_entropy = true,
.virtual_time_start = 0, // Unix epoch
.random_seed = 42,
.record_execution = true,
.output_path = "build.trace"
};
detexec_set_config(ctx, &config);
// Execute build command
const char *argv[] = {
"make",
"-C", source_dir,
"OUTPUT=" output_dir,
NULL
};
detexec_result_t result;
int ret = detexec_exec(ctx, "/usr/bin/make", argv, &result);
if (ret == 0) {
printf("Build completed deterministically\n");
printf("Build hash: %s\n", result.trace_hash);
}
detexec_free(ctx);
return ret;
}#include <deterministic-executor/detexec.h>
void analyze_incident(const char *trace_path) {
detexec_trace_t *trace = detexec_load_trace(trace_path);
// Verify trace hasn't been tampered with
if (!detexec_verify_trace(trace)) {
fprintf(stderr, "Trace integrity check failed!\n");
return;
}
// Extract syscall sequence
detexec_event_t *events;
size_t count;
detexec_get_events(trace, &events, &count);
printf("Analyzing %zu events\n", count);
for (size_t i = 0; i < count; i++) {
if (events[i].type == DETEXEC_EVENT_SYSCALL) {
printf("Syscall: %s at time %lu\n",
events[i].syscall.name,
events[i].timestamp);
}
}
detexec_free_trace(trace);
}#include <deterministic-executor/detexec.h>
bool test_race_condition() {
detexec_context_t *ctx = detexec_new();
detexec_config_t config = {
.deterministic_threads = true,
.deterministic_signals = true,
.random_seed = 12345
};
detexec_set_config(ctx, &config);
// Run test with deterministic scheduling
const char *argv[] = {"./race_test", NULL};
detexec_result_t result;
detexec_exec(ctx, "./race_test", argv, &result);
// The same race condition will happen every time
bool test_passed = (result.exit_code == 0);
detexec_free(ctx);
return test_passed;
}#include <process-sandbox/sandbox.h>
#include <deterministic-executor/detexec.h>
// Combine sandboxing with deterministic execution
sandbox_config_t sandbox = sandbox_config_new();
sandbox_config_set_namespaces(&sandbox, SANDBOX_NS_ALL);
detexec_context_t *detexec = detexec_new();
detexec_config_t config = {
.deterministic_time = true,
.deterministic_entropy = true,
.record_execution = true
};
detexec_set_config(detexec, &config);
// Execute in sandbox with determinism
sandbox_config_set_detexec(&sandbox, detexec);
sandbox_exec(&sandbox, "/usr/bin/untrusted", argv, NULL);#include <deterministic-executor/detexec.h>
void create_execution_attestation(const char *trace_path) {
detexec_trace_t *trace = detexec_load_trace(trace_path);
// Compute merkle tree of execution
detexec_merkle_tree_t *tree = detexec_build_merkle_tree(trace);
// Get root hash (attestation)
uint8_t root_hash[32];
detexec_merkle_root(tree, root_hash);
printf("Execution attestation: ");
for (int i = 0; i < 32; i++) {
printf("%02x", root_hash[i]);
}
printf("\n");
// Sign attestation
detexec_sign_trace(trace, "private_key.pem");
detexec_save_trace(trace, "signed_trace.trace");
detexec_free_merkle_tree(tree);
detexec_free_trace(trace);
}Execution traces are stored in an efficient binary format:
Trace File Format:
┌──────────────────────┐
│ Header │
│ - Magic bytes │
│ - Version │
│ - Config │
│ - Start timestamp │
│ - Metadata │
├──────────────────────┤
│ Event Stream │
│ - Event 1 │
│ - Event 2 │
│ - ... │
│ - Event N │
├──────────────────────┤
│ Cryptographic Data │
│ - Hash chain │
│ - Merkle tree │
│ - Signature │
└──────────────────────┘
- Linux kernel 4.0+
- libssl-dev (for cryptography)
- libz-dev (for compression)
- GCC 9+ or Clang 10+
# Build library
make
# Build with debug symbols
make DEBUG=1
# Run tests
make test
# Install
sudo make install- Recording overhead: 5-15% execution time
- Replay speed: 1.5-3x faster than original execution
- Trace size: ~1-10 MB per minute of execution (compressed)
- Verification time: <100ms for typical traces
The executor controls:
- Time:
gettimeofday(),clock_gettime(), etc. - Randomness:
/dev/random,/dev/urandom,getrandom() - Thread Scheduling: Deterministic thread interleaving
- Signal Delivery: Deterministic signal timing
- Memory Addresses: ASLR disabled/virtualized
- PIDs/TIDs: Virtualized process/thread IDs
- File System: Snapshots and timestamps
- Network: Order of packet delivery
Check for uncontrolled sources:
detexec-analyze --check-determinism execution.traceVerify trace wasn't modified:
detexec-verify execution.traceEnable compression:
config.enable_compression = true;- Trace Integrity: Always verify trace signatures
- Private Keys: Protect signing keys
- Sensitive Data: Traces may contain sensitive information
- Replay Safety: Replay in isolated environments
- Time Rollback: Virtual time can be in the past
See CONTRIBUTING.md
MIT License - See LICENSE
- Deterministic Process Groups in TreadMarks
- rr: Record and Replay
- Determinator: OS for deterministic execution
- Time Travel Debugging
git submodule add https://github.com/navinBRuas/_SecureExecutionEnvironment.git vendor/secure-executionUse vendor/secure-execution/deterministic-executor for local builds and integration.
Follow the C or Python examples above and module headers for full API details.
Configure determinism, tracing, and verification via detexec_config_t and
advanced config structs.
Current version: 0.1.0 (see VERSION.md).
See CHANGELOG.md for release history.