Ship Magisk like GOLDEN; KernelSU optional recycle only; parallel to sunfish-a16-rom standby.
52 lines
1.8 KiB
Python
52 lines
1.8 KiB
Python
#!/usr/bin/env python3
|
|
"""Check a Linux module's versioned imports against its target Module.symvers.
|
|
|
|
Requires kmod's modprobe. A pass checks symbol CRCs only, not complete ABI,
|
|
vermagic, CFI, signatures, firmware or hardware behaviour.
|
|
"""
|
|
import argparse
|
|
from pathlib import Path
|
|
import subprocess
|
|
import sys
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("symvers", type=Path)
|
|
parser.add_argument("modules", nargs="+", type=Path)
|
|
args = parser.parse_args()
|
|
exports = {}
|
|
for line in args.symvers.read_text().splitlines():
|
|
fields = line.split()
|
|
if len(fields) >= 2:
|
|
exports[fields[1]] = int(fields[0], 16)
|
|
if not exports:
|
|
parser.error("Module.symvers contains no exports")
|
|
failed = False
|
|
for module in args.modules:
|
|
result = subprocess.run(
|
|
["modprobe", "--show-modversions", str(module.resolve())],
|
|
text=True, capture_output=True,
|
|
)
|
|
if result.returncode or not result.stdout.strip():
|
|
print(f"UNVERIFIED {module}: {result.stderr.strip() or 'no versioned imports'}")
|
|
failed = True
|
|
continue
|
|
mismatch = 0
|
|
imports = result.stdout.splitlines()
|
|
for line in imports:
|
|
crc, symbol = line.split()
|
|
expected = exports.get(symbol)
|
|
if expected != int(crc, 16):
|
|
mismatch += 1
|
|
target = "missing export" if expected is None else f"0x{expected:08x}"
|
|
print(f" {symbol}: module={crc}, kernel={target}")
|
|
failed |= bool(mismatch)
|
|
print(f"{'FAIL' if mismatch else 'PASS'} {module}: "
|
|
f"{mismatch}/{len(imports)} incompatible versioned imports")
|
|
return int(failed)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|