Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
70 lines
4 KiB
Python
70 lines
4 KiB
Python
#!/usr/bin/env python3
|
|
# SPDX-License-Identifier: MPL-2.0
|
|
"""Inspect a running native RAM trial. Execute inside its main root as root."""
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
import subprocess
|
|
import time
|
|
|
|
|
|
def inspect():
|
|
if 'tundra.rescue=1' not in Path('/proc/cmdline').read_text():
|
|
raise RuntimeError('This inspector is for a native RAM trial')
|
|
result={'recordedAtUnix':time.time(),'uptime':Path('/proc/uptime').read_text().strip()}
|
|
commands={
|
|
'failedUnits':['systemctl','--failed','--no-legend','--no-pager'],
|
|
'activeUnits':['systemctl','is-active','tundra-hal','tundra-display','systemd-logind','user@32011'],
|
|
'displayRestarts':['systemctl','show','tundra-display','-p','NRestarts','--value'],
|
|
'kernel':['uname','-r'],
|
|
'halPid':['lxc-info','-n','tundra-hal','-pH'],
|
|
}
|
|
for name,command in commands.items():
|
|
process=subprocess.run(command,capture_output=True,text=True,timeout=10)
|
|
result[name]={'code':process.returncode,'stdout':process.stdout,'stderr':process.stderr}
|
|
kernel = subprocess.run(['dmesg'], capture_output=True, text=True, timeout=10)
|
|
result['kernelFaults'] = [line for line in kernel.stdout.splitlines()
|
|
if any(marker in line for marker in
|
|
('Internal error: Oops', 'Kernel panic', 'Kernel BUG', 'BUG:'))]
|
|
result['memoryKills'] = [line for line in kernel.stdout.splitlines()
|
|
if any(marker in line for marker in
|
|
('lowmemorykiller: Killing', 'Out of memory: Kill', 'oom-kill:', 'Killed process'))]
|
|
result['kernelLogReadable'] = kernel.returncode == 0
|
|
result['pid1']=Path('/proc/1/cmdline').read_text().replace('\0',' ')
|
|
result['identity']=Path('/etc/os-release').read_text()
|
|
result['mounts']=Path('/proc/1/mounts').read_text()
|
|
result['memory']=Path('/proc/meminfo').read_text()
|
|
pid=result['halPid']['stdout'].strip()
|
|
result['halCgroups']=Path('/proc',pid,'cgroup').read_text() if pid.isdigit() else None
|
|
result['halMemoryLimits']={str(p):p.read_text().strip() for p in Path('/sys/fs/cgroup').rglob('memory.max') if 'lxc.payload.tundra-hal' in str(p)}
|
|
result['gaia']=json.loads(Path('/opt/vulpes/logs/test.json').read_text())
|
|
processes=[]
|
|
for path in Path('/proc').glob('[0-9]*/cmdline'):
|
|
try:
|
|
command=path.read_text().replace('\0',' ').strip()
|
|
if not command:continue
|
|
status=dict(line.split(':',1) for line in (path.parent/'status').read_text().splitlines() if ':' in line)
|
|
processes.append({'pid':int(path.parent.name),'command':command,
|
|
'uid':status.get('Uid','').strip(),'seccomp':status.get('Seccomp','').strip(),
|
|
'capabilities':status.get('CapEff','').strip()})
|
|
except (OSError,ProcessLookupError):continue
|
|
result['processes']=processes
|
|
result['checks']={
|
|
'noKernelFaults':result['kernelLogReadable'] and not result['kernelFaults'],
|
|
'noMemoryKills':result['kernelLogReadable'] and not result['memoryKills'],
|
|
'tundraPid1':'--unit=tundra.target' in result['pid1'],
|
|
'noFailedUnits':result['failedUnits']['code']==0 and not result['failedUnits']['stdout'].strip(),
|
|
'servicesActive':result['activeUnits']['code']==0 and result['activeUnits']['stdout'].split()==['active']*4,
|
|
'noDisplayRestart':result['displayRestarts']['stdout'].strip()=='0',
|
|
'gaia':result['gaia']['passed'],
|
|
'halLegacyDeviceGuard':bool(result['halCgroups'] and ':devices:/hal' in result['halCgroups']),
|
|
'halMemoryBounded':'536870912' in result['halMemoryLimits'].values(),
|
|
'noAndroidAppRuntime':not any(p['command'].split()[0].rsplit('/',1)[-1] in ('zygote','zygote64','app_process','app_process64','phosh') for p in processes),
|
|
}
|
|
return result
|
|
|
|
|
|
if __name__=='__main__':
|
|
result=inspect()
|
|
print(json.dumps(result,indent=2))
|
|
raise SystemExit(0 if all(result['checks'].values()) else 1)
|