Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,11 @@ <h2>Linux Kernel Ring 0 Visualization</h2>
<script src="/static/js/active-connections.js?v=4"></script>
<script src="/static/js/nginx_files.js?v=2"></script>
<script src="/static/js/right-semicircle-menu.js?v=48"></script>
<script src="/static/js/kernel-dna.js?v=27"></script>
<script src="/static/js/kernel-dna.js?v=31"></script>
<script src="/static/js/network-stack.js?v=6"></script>
<script src="/static/js/devices-belt.js?v=14"></script>
<script src="/static/js/crypto-belt.js?v=31"></script>
<script src="/static/js/security-belt.js?v=11"></script>
<script src="/static/js/crypto-belt.js?v=38"></script>
<script src="/static/js/security-belt.js?v=13"></script>
<script src="/static/js/filesystem-map.js?v=10"></script>
<script src="/static/js/kernel-context-menu.js?v=29"></script>
<script>
Expand Down
85 changes: 85 additions & 0 deletions kernel_ai/services/crypto/crypto_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,10 +211,94 @@ def collect_crypto_realtime(crypto_prev, callbacks=None, psutil_module=None, log
algorithm_requesters=algorithm_requesters,
)
entropy_cloud = collect_entropy_cloud_status_fn()
proc_crypto_names = {str(entry.get("name") or "").lower() for entry in proc_crypto_entries if isinstance(entry, dict)}
client_names = {str(row.get("name") or row.get("client") or "").lower() for row in kernel_clients if isinstance(row, dict)}
protocol_names = {str(item.get("protocol") or "").upper() for item in items}
process_names = {str(item.get("process") or "").lower() for item in items}
active_algos = {str(item.get("algorithm") or "").lower() for item in items}
entropy_ready = str((entropy_cloud or {}).get("crng_state") or "").lower() in {"ready", "initialized", "crng_ready"}

def _zone(zone_id, label, active, status, evidence, strength=0.5):
return {
"id": zone_id,
"label": label,
"active": bool(active),
"status": status,
"strength": round(max(0.0, min(1.0, float(strength))), 3),
"evidence": evidence,
}

protected_zones = [
_zone(
"tls",
"TLS / kTLS",
"TLS" in protocol_names,
"active" if "TLS" in protocol_names else "idle",
{"sessions": sum(1 for i in items if i.get("protocol") == "TLS"), "terminators": sorted(tls_listener_names)[:4]},
min(1.0, 0.35 + sum(1 for i in items if i.get("protocol") == "TLS") / 8.0),
),
_zone(
"block",
"dm-crypt / block",
any("xts" in algo or "aes" in algo for algo in active_algos | proc_crypto_names),
"active" if any("xts" in algo or "aes" in algo for algo in active_algos | proc_crypto_names) else "unknown",
{"algorithms": sorted([x for x in (active_algos | proc_crypto_names) if x])[:5]},
0.72 if any("aes" in algo for algo in active_algos | proc_crypto_names) else 0.35,
),
_zone(
"ipsec",
"IPsec / xfrm",
any("xfrm" in name or "ipsec" in name for name in process_names | client_names),
"active" if any("xfrm" in name or "ipsec" in name for name in process_names | client_names) else "idle",
{"clients": sorted([x for x in client_names if x])[:5]},
0.62,
),
_zone(
"fscrypt",
"fscrypt",
any("fscrypt" in name for name in client_names | proc_crypto_names),
"active" if any("fscrypt" in name for name in client_names | proc_crypto_names) else "unknown",
{"clients": sorted([x for x in client_names if "fs" in x])[:4]},
0.48,
),
_zone(
"keyring",
"keyring",
any("key" in name for name in client_names | process_names),
"active" if any("key" in name for name in client_names | process_names) else "idle",
{"signals": sorted([x for x in (client_names | process_names) if "key" in x])[:4]},
0.52,
),
_zone(
"entropy",
"random / entropy",
entropy_ready,
"active" if entropy_ready else "weak signal",
{"crng_state": (entropy_cloud or {}).get("crng_state"), "pool_bits": (entropy_cloud or {}).get("entropy_pool_bits")},
0.86 if entropy_ready else 0.34,
),
_zone(
"module_sig",
"module signature",
any("sha" in algo or "rsa" in algo or "ecdsa" in algo for algo in proc_crypto_names | active_algos),
"active" if any("sha" in algo or "rsa" in algo or "ecdsa" in algo for algo in proc_crypto_names | active_algos) else "unknown",
{"algorithms": sorted([x for x in (proc_crypto_names | active_algos) if "sha" in x or "rsa" in x or "ecdsa" in x])[:5]},
0.58,
),
_zone(
"ima_evm",
"IMA / EVM",
any("ima" in name or "evm" in name for name in client_names | process_names),
"active" if any("ima" in name or "evm" in name for name in client_names | process_names) else "unknown",
{"signals": sorted([x for x in (client_names | process_names) if "ima" in x or "evm" in x])[:4]},
0.42,
),
]

return {
"items": items[:24],
"processes": unique_processes[:16],
"protected_zones": protected_zones,
"meta": {
"ops_per_sec": ops_per_sec,
"tls_sessions": sum(1 for i in items if i.get("protocol") == "TLS"),
Expand All @@ -228,6 +312,7 @@ def collect_crypto_realtime(crypto_prev, callbacks=None, psutil_module=None, log
"entropy_cloud": entropy_cloud,
"crypto_decision_pipeline": crypto_decision_pipelines.get("aes", {}),
"crypto_decision_pipelines": crypto_decision_pipelines,
"protected_zones": protected_zones,
"source": "live-heuristic-v2",
"timestamp": datetime.utcnow().isoformat() + "Z",
},
Expand Down
173 changes: 173 additions & 0 deletions kernel_ai/services/execution.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,178 @@
from kernel_ai.sentry_helpers import capture_exception


def _read_key_value_proc_file(path: str) -> dict:
out = {}
try:
with open(path, "r", encoding="utf-8", errors="ignore") as f:
for raw in f:
parts = raw.split()
if len(parts) != 2:
continue
try:
out[parts[0]] = int(parts[1])
except ValueError:
continue
except OSError:
return {}
return out


def _read_memory_psi_avg10() -> dict:
result = {"some": 0.0, "full": 0.0}
try:
with open("/proc/pressure/memory", "r", encoding="utf-8", errors="ignore") as f:
for raw in f:
parts = raw.split()
if not parts:
continue
scope = parts[0]
if scope not in result:
continue
for token in parts[1:]:
if token.startswith("avg10="):
try:
result[scope] = float(token.split("=", 1)[1])
except ValueError:
pass
break
except OSError:
return result
return result


def _read_tcp_retrans_segs() -> int:
try:
with open("/proc/net/snmp", "r", encoding="utf-8", errors="ignore") as f:
lines = [line.strip() for line in f if line.startswith("Tcp:")]
except OSError:
return 0
if len(lines) < 2:
return 0
headers = lines[-2].split()[1:]
values = lines[-1].split()[1:]
for key, value in zip(headers, values):
if key != "RetransSegs":
continue
try:
return int(value)
except ValueError:
return 0
return 0


def _read_softirq_totals() -> dict:
totals = {}
try:
with open("/proc/softirqs", "r", encoding="utf-8", errors="ignore") as f:
lines = f.readlines()
except OSError:
return totals
for raw in lines[1:]:
if ":" not in raw:
continue
left, right = raw.split(":", 1)
name = left.strip()
total = 0
for token in right.split():
if token.isdigit():
total += int(token)
if total:
totals[name] = total
return totals


def _read_loadavg() -> dict:
try:
with open("/proc/loadavg", "r", encoding="utf-8", errors="ignore") as f:
parts = f.read().split()
except OSError:
return {"load1": 0.0, "runnable": 0, "threads": 0}
runnable = 0
threads = 0
if len(parts) >= 4 and "/" in parts[3]:
left, right = parts[3].split("/", 1)
try:
runnable = int(left)
threads = int(right)
except ValueError:
pass
try:
load1 = float(parts[0])
except (IndexError, ValueError):
load1 = 0.0
return {"load1": load1, "runnable": runnable, "threads": threads}


def build_kernel_anomaly_mutations() -> list[dict]:
"""Build lightweight Kernel DNA mutations from procfs symptom counters."""
mutations = []
vmstat = _read_key_value_proc_file("/proc/vmstat")
psi = _read_memory_psi_avg10()
loadavg = _read_loadavg()
retrans = _read_tcp_retrans_segs()
softirq = _read_softirq_totals()
cpu_count = max(1, psutil.cpu_count() or 1)

if float(psi.get("some") or 0.0) >= 1.0 or float(psi.get("full") or 0.0) >= 0.2:
mutations.append(
{
"type": "memory_pressure",
"severity": "high" if float(psi.get("full") or 0.0) >= 0.2 else "medium",
"message": f"Memory PSI pressure some10={float(psi.get('some') or 0.0):.2f} full10={float(psi.get('full') or 0.0):.2f}",
"position": 0.64,
"source": "/proc/pressure/memory",
}
)

if int(vmstat.get("pgmajfault") or 0) > 0 and int(vmstat.get("pgscan_direct") or 0) > 0:
mutations.append(
{
"type": "page_reclaim_pressure",
"severity": "medium",
"message": f"Major faults and direct reclaim observed pgmajfault={int(vmstat.get('pgmajfault') or 0)} pgscan_direct={int(vmstat.get('pgscan_direct') or 0)}",
"position": 0.72,
"source": "/proc/vmstat",
}
)

if retrans > 0:
mutations.append(
{
"type": "tcp_retransmission",
"severity": "medium",
"message": f"TCP retransmissions observed RetransSegs={retrans}",
"position": 0.34,
"source": "/proc/net/snmp",
}
)

net_softirq = int(softirq.get("NET_RX") or 0) + int(softirq.get("NET_TX") or 0)
timer_softirq = int(softirq.get("TIMER") or 0)
if net_softirq > 0 and timer_softirq > 0 and net_softirq > timer_softirq * 3:
mutations.append(
{
"type": "net_softirq_pressure",
"severity": "medium",
"message": f"NET softirq dominates timer path net={net_softirq} timer={timer_softirq}",
"position": 0.86,
"source": "/proc/softirqs",
}
)

if int(loadavg.get("runnable") or 0) > cpu_count * 2:
mutations.append(
{
"type": "scheduler_runqueue_pressure",
"severity": "medium",
"message": f"Runnable tasks exceed CPU capacity runnable={int(loadavg.get('runnable') or 0)} cpus={cpu_count}",
"position": 0.18,
"source": "/proc/loadavg",
}
)
return mutations[:6]


def get_execution_context_data(syscall_names, map_interrupt_to_subsystem_fn, exec_context_prev):
"""Collect execution context payload used by Ring-1 visualization."""
if platform.system() != "Linux":
Expand Down Expand Up @@ -383,5 +555,6 @@ def get_kernel_dna_data(get_real_system_calls_fn, map_syscall_to_subsystem_fn, m
if locks and locks[0]["count"] > 100:
mutations.append({"type": "lock_contention", "severity": "medium", "message": f'High lock contention: {locks[0]["count"]} active locks', "position": 0.7})

mutations.extend(build_kernel_anomaly_mutations())
dna_data["mutations"] = mutations
return dna_data
46 changes: 46 additions & 0 deletions kernel_ai/services/processes_runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,46 @@ def _parse_tcp_snmp_counters() -> dict:
return out


def _build_procfs_map(sampled_pid_count: int, network_count: int, memory_visual: dict) -> dict:
"""Build a lightweight /proc coverage map without walking every proc file."""
try:
proc_entries = os.listdir("/proc")
except OSError:
proc_entries = []
pid_dirs = [name for name in proc_entries if name.isdigit()]
known_sources = [
("/proc/[pid]/status", "process", max(0, int(sampled_pid_count))),
("/proc/[pid]/fd", "process", max(0, int(sampled_pid_count))),
("/proc/[pid]/stat", "process", max(0, int(sampled_pid_count))),
("/proc/net/tcp", "network", max(0, int(network_count))),
("/proc/net/snmp", "network", 1),
("/proc/meminfo", "memory", 1),
("/proc/vmstat", "memory", len((memory_visual.get("kernel_memory_state") or {}).get("vmstat") or {})),
("/proc/pressure/memory", "memory", len((memory_visual.get("kernel_memory_state") or {}).get("psi_memory") or {})),
("/proc/sys/kernel/yama/ptrace_scope", "security", 1),
("/proc/interrupts", "devices", 1),
]
sources = []
for path, group, count in known_sources:
static_path = path.replace("[pid]", "1")
exists = path.startswith("/proc/[pid]") or os.path.exists(static_path)
sources.append(
{
"path": path,
"group": group,
"active": bool(exists and count >= 0),
"samples": int(count or 0),
}
)
return {
"pid_dirs": len(pid_dirs),
"top_level_entries": len(proc_entries),
"sampled_pids": max(0, int(sampled_pid_count)),
"coverage_note": "procfs atlas is sampled, not a full recursive /proc mirror",
"sources": sources,
}


def _semantic_op(label: str, op_type: str, active: bool, weight: float, source: str, evidence: dict | None = None) -> dict:
return {
"label": label,
Expand Down Expand Up @@ -960,13 +1000,19 @@ def _add_edge(src_pid, dst_pid, edge_type, weight):
"psi_factor": 1.0,
},
}
procfs_map = _build_procfs_map(
sampled_pid_count=len(nodes),
network_count=len(network_tracing),
memory_visual=memory_visual,
)

return {
"timestamp": datetime.utcnow().isoformat() + "Z",
"syscalls_interception": syscall_nodes,
"network_tracing": network_tracing,
"security_hooks": security_hooks,
"semantic_ops": semantic_ops,
"procfs_map": procfs_map,
"neural_graph": {"nodes": nodes, "edges": edges},
"memory_visual": memory_visual,
"meta": {
Expand Down
Loading
Loading