initial commit

This commit is contained in:
2026-09-21 13:41:40 +09:00
commit 855c7328df
411 changed files with 85352 additions and 0 deletions
+139
View File
@@ -0,0 +1,139 @@
#!/usr/bin/env python3
"""Validate the installed local deb with original SDK/build prefixes hidden.
Runs only in the dedicated Ubuntu guest. Root is used for a private mount
namespace; the viewer, compositor, and document workers run as docview.
"""
import argparse
import hashlib
import json
import os
from pathlib import Path
import re
import subprocess
import sys
import tempfile
ROOT = Path(__file__).resolve().parents[2]
APP = Path('/opt/docview')
HIDDEN = ['/opt/docview-qt', '/opt/docview-deps', '/home/docview/docview-install',
'/home/docview/docview-build']
def sha(path):
with path.open('rb') as stream:
return hashlib.file_digest(stream, 'sha256').hexdigest()
def user_run(output):
assert os.getuid() != 0
assert not any(name in os.environ for name in ('LD_LIBRARY_PATH', 'QT_PLUGIN_PATH',
'QT_QPA_PLATFORM_PLUGIN_PATH', 'QML_IMPORT_PATH', 'QML2_IMPORT_PATH',
'QTWEBENGINEPROCESS_PATH', 'QTWEBENGINE_DISABLE_SANDBOX'))
hidden = {name: not Path(name).exists() or not any(Path(name).iterdir()) for name in HIDDEN}
assert all(hidden.values())
manifest = json.loads((APP / 'share/doc/docview/package-manifest.json').read_text())
installed = []
for row in manifest['files']:
if row['path'].startswith('DEBIAN/'):
continue
path = Path('/') / row['path']
value = path.stat()
assert value.st_uid == 0 and value.st_gid == 0
assert oct(value.st_mode & 0o7777) == row['mode']
assert value.st_size == row['size'] and sha(path) == row['sha256']
installed.append(row['path'])
environment = {**os.environ, 'LD_LIBRARY_PATH': str(APP / 'lib') + ':' + str(APP / 'qt/lib')}
dependencies = []
for path in sorted(APP.rglob('*')):
if not path.is_file(): continue
with path.open('rb') as stream:
if stream.read(4) != b'\x7fELF': continue
result = subprocess.run(['ldd', str(path)], env=environment, capture_output=True, text=True, timeout=30)
assert result.returncode == 0 and 'not found' not in result.stdout, str(path)
resolved = re.findall(r'(?:=>\s+)?(/[^\s]+)\s+\(', result.stdout)
no_needed = False
if not resolved:
dynamic = subprocess.check_output(['readelf', '-d', str(path)], text=True, timeout=30)
no_needed = '(NEEDED)' not in dynamic and result.stdout.strip() == 'statically linked'
assert (resolved or no_needed) and all(name.startswith(('/opt/docview/', '/lib/', '/lib64/', '/usr/lib/')) for name in resolved), str(path) + ': ' + result.stdout
dependencies.append({'path': str(path), 'sha256': sha(path), 'resolved': sorted(set(resolved)),
'noDynamicDependencies': no_needed})
identities = {name: sha(APP / 'bin' / name) for name in
['docview', 'docview-pdf-worker', 'docview-archive-worker']}
launcher = sha(Path('/usr/bin/docview'))
record = {'success': False, 'hiddenOriginalPrefixes': hidden, 'uid': os.getuid(),
'callerRuntimeVariablesAbsent': True, 'installedFilesVerified': len(installed),
'executables': identities, 'launcherSha256': launcher, 'elfDependencies': dependencies,
'runnerSha256': sha(Path(__file__)), 'smokeSourceSha256': sha(ROOT / 'tests/smoke.py'),
'waylandRunnerSha256': sha(ROOT / 'tests/run_wayland_validation.py'),
'scope': 'Dedicated existing Ubuntu VM, private mount namespace, Xvfb and headless Sway/software; not a clean OS or physical desktop'}
commands = [
('x11', ['dbus-run-session', '--', 'xvfb-run', '-a', '-s', '-screen 0 1100x760x24',
sys.executable, str(ROOT / 'tests/smoke.py'), '--binary', '/usr/bin/docview',
'--output', str(output / 'x11')]),
('wayland', [sys.executable, str(ROOT / 'tests/run_wayland_validation.py'),
'--build-dir', '/opt/docview/bin', '--smoke-binary', '/usr/bin/docview',
'--output', str(output / 'wayland'), '--mode', 'smoke'])]
runs = []
try:
for name, command in commands:
env = dict(os.environ)
if name == 'x11':
env.update(QT_QPA_PLATFORM='xcb', QT_QUICK_BACKEND='software',
QTWEBENGINE_CHROMIUM_FLAGS='--disable-gpu')
with (output / (name + '.log')).open('w') as log:
result = subprocess.run(command, env=env, stdout=log, stderr=subprocess.STDOUT, timeout=300)
runs.append({'name': name, 'exitCode': result.returncode})
assert result.returncode == 0, name + ' smoke failed'
values = json.loads((output / name / ('smoke/results.json' if name == 'wayland' else 'results.json')).read_text())
assert len(values) == 6 and all(row['state'] == 'Ready' and row['binarySha256'] == launcher for row in values)
assert all(sha(APP / 'bin' / name) == digest for name, digest in identities.items())
assert sha(Path('/usr/bin/docview')) == launcher
record.update(success=True, executableBytesUnchanged=True, smokeConditions=12)
finally:
record['runs'] = runs
(output / 'report.json').write_text(json.dumps(record, indent=2, sort_keys=True) + '\n')
print(json.dumps({key: record[key] for key in ('success', 'installedFilesVerified', 'smokeConditions')}))
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--output', type=Path, required=True)
parser.add_argument('--isolated', action='store_true')
parser.add_argument('--user-run', action='store_true')
parser.add_argument('--hide-prefix', action='append', default=[], type=Path,
help='Additional dedicated guest build/install prefix to hide in the private namespace')
args = parser.parse_args()
output = args.output.resolve()
assert len(args.hide_prefix) <= 8
additional = []
for prefix in args.hide_prefix:
assert prefix.is_absolute() and not prefix.is_symlink()
prefix = prefix.absolute()
assert prefix.is_relative_to('/home/docview') and prefix != Path('/home/docview')
assert '..' not in prefix.parts and not ROOT.is_relative_to(prefix) and not output.is_relative_to(prefix)
additional.extend(['--hide-prefix', str(prefix)])
if str(prefix) not in HIDDEN: HIDDEN.append(str(prefix))
if args.user_run:
user_run(output)
elif args.isolated:
assert os.getuid() == 0
with tempfile.TemporaryDirectory(prefix='docview-hidden-runtime-') as temporary:
Path(temporary).chmod(0o755)
for name in HIDDEN:
if Path(name).is_dir():
subprocess.run(['mount', '--bind', temporary, name], check=True)
subprocess.run(['runuser', '-u', 'docview', '--', 'env', '-i',
'HOME=/home/docview', 'USER=docview', 'LOGNAME=docview',
'PATH=/usr/bin:/bin', 'LANG=C.UTF-8', sys.executable,
str(Path(__file__)), '--user-run', '--output', str(output), *additional], check=True)
else:
assert os.getuid() != 0 and Path.home() == Path('/home/docview')
output.mkdir(parents=True, exist_ok=False)
subprocess.run(['sudo', 'unshare', '--mount', '--propagation', 'private',
sys.executable, str(Path(__file__)), '--isolated', '--output', str(output), *additional], check=True)
if __name__ == '__main__':
main()