Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
parent
93e3a48004
commit
b38dea0597
25901 changed files with 9982925 additions and 369 deletions
98
tundra/runtime/hal_policy.py
Normal file
98
tundra/runtime/hal_policy.py
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
# SPDX-License-Identifier: MPL-2.0
|
||||
"""Reduce Android init to display HAL services for the read-only Sargo trial.
|
||||
|
||||
Input files retain their upstream copyright notices. Removed commands and services
|
||||
are reported; this is not a general Android init parser or a production policy.
|
||||
"""
|
||||
import shlex
|
||||
|
||||
SERVICES = frozenset(('ueventd','logd','servicemanager','hwservicemanager','vndservicemanager',
|
||||
'vendor.hwcomposer-2-2','vendor.qti.hardware.display.allocator','vendor.configstore-hal',
|
||||
'vendor.power-hal-1-3','vendor.thermal-engine','thermal-hal-1-1','hidl_memory'))
|
||||
COMMANDS = frozenset(('mkdir','chmod','chown','write','setprop','symlink','copy',
|
||||
'restorecon','restorecon_recursive','trigger','class_start','class_stop',
|
||||
'load_system_props','load_persist_props','export','setrlimit','hostname','domainname','loglevel','sysclktz','start','stop','restart'))
|
||||
PSEUDO_FS = frozenset(('cgroup','cgroup2','cpuset','tmpfs','proc','sysfs','debugfs','pstore','bpf'))
|
||||
|
||||
# The native network trial supplies rmt_storage with RAM copies of NV files.
|
||||
# It retains the blanket denial of block-device access for this container.
|
||||
NETWORK_SERVICES = frozenset(('irsc_util', 'vendor.per_mgr', 'vendor.rmt_storage',
|
||||
'vendor.tftp_server', 'cnss-daemon', 'pd_mapper'))
|
||||
|
||||
|
||||
HARDWARE_SERVICES = frozenset(('vendor.qcrild', 'vendor.google.radioext@1.0',
|
||||
'vendor.audio-hal-2-0', 'vendor.camera-provider-2-4',
|
||||
'camera_service', 'minimedia', 'minisf', 'miniaf'))
|
||||
|
||||
def is_init_script(path):
|
||||
# ueventd uses a different grammar: these files define device permissions.
|
||||
return not path.name.startswith('ueventd')
|
||||
|
||||
|
||||
def command_allowed(tokens):
|
||||
if not tokens:
|
||||
return True
|
||||
op=tokens[0]
|
||||
if op=='onrestart':
|
||||
return command_allowed(tokens[1:])
|
||||
if op in ('start','stop','restart'):
|
||||
return len(tokens)==2 and tokens[1] in SERVICES
|
||||
if op=='mount':
|
||||
return len(tokens)>3 and tokens[1] in PSEUDO_FS and not tokens[2].startswith('/dev/')
|
||||
if op not in COMMANDS:
|
||||
return False
|
||||
if any('/dev/block' in t or '/dev/mmcblk' in t or '/sys/kernel/config' in t or '/sys/class/android_usb' in t or '/config/usb_gadget' in t or '/proc/sys/kernel/panic' in t or '/proc/sysrq-trigger' in t for t in tokens[1:]):
|
||||
return False
|
||||
if op=='setprop' and len(tokens)>2 and tokens[1].startswith('ctl.'):
|
||||
return tokens[1] in ('ctl.start','ctl.stop','ctl.restart') and tokens[2] in SERVICES
|
||||
return True
|
||||
|
||||
|
||||
def logical_lines(text):
|
||||
pending = ''
|
||||
first = 1
|
||||
for number, line in enumerate(text.splitlines(), 1):
|
||||
if not pending: first = number
|
||||
pending += line
|
||||
if pending.endswith('\\'):
|
||||
pending = pending[:-1]+' '
|
||||
continue
|
||||
try:
|
||||
shlex.split(pending.strip(), comments=True)
|
||||
except ValueError:
|
||||
pending += '\n'
|
||||
continue
|
||||
yield first, pending
|
||||
pending = ''
|
||||
if pending:
|
||||
raise ValueError('Unterminated Android init command at line '+str(first))
|
||||
|
||||
|
||||
def filter_rc(text):
|
||||
output=[];removed=[];kept=[];section=None;keep=True
|
||||
for number,line in logical_lines(text):
|
||||
stripped=line.strip()
|
||||
if not stripped or stripped.startswith('#'):
|
||||
if keep:output.append(line)
|
||||
continue
|
||||
tokens=shlex.split(stripped,comments=True)
|
||||
if not line[0].isspace():
|
||||
section=tokens[0];keep=True
|
||||
if section=='service':
|
||||
keep=len(tokens)>2 and tokens[1] in SERVICES and not any('_DISABLED' in t for t in tokens[2:])
|
||||
if keep:kept.append(tokens[1])
|
||||
elif section=='import':
|
||||
# USB, recovery, and Android app processes are outside this trial.
|
||||
keep=not any(word in stripped for word in ('usb','recovery','zygote'))
|
||||
elif section!='on':
|
||||
keep=False
|
||||
if keep:output.append(line)
|
||||
else:removed.append({'line':number,'text':line})
|
||||
continue
|
||||
accepted=keep and (section=='service' or command_allowed(tokens))
|
||||
# Keep failed trial services inspectable instead of rebooting the device.
|
||||
if section=='service' and tokens[0]=='critical':accepted=False
|
||||
if section=='service' and tokens[0]=='onrestart':accepted=keep and command_allowed(tokens)
|
||||
if accepted:output.append(line)
|
||||
else:removed.append({'line':number,'text':line})
|
||||
return '\n'.join(output)+'\n',{'services':kept,'removed':removed}
|
||||
Loading…
Reference in a new issue