Files
sunfish-admin deaaf42caa 009: Magisk ship pack through US-S5-1 + US-S4 OpenSSH/Jelly/Gallery2.
Release-keys/AVB, CVE clean+hi batches, Yama/slabrand, Pro branding,
bundled apps, and AXP-class product surface docs/scripts.
2026-10-05 10:42:00 +02:00

165 lines
5.1 KiB
Bash

#!/usr/bin/env bash
# Apply AXP CVE allowlist onto msm-4.14 (after Stage1+combo4).
# Source: AXP kernel_patches + cve_checker strict list / bisect slices.
#
# Safety (2026-09-29 review):
# - Default: ABORT on first patch failure (no continue-with-partial-tree).
# - Keep *.rej / *.orig under CVE_REJECT_DIR (do not silently delete).
# - Treat large line-offsets / fuzz as WARN or FAIL (mis-apply risk).
# - Set CVE_STRICT_CONTINUE=1 only for forensic runs (explicit).
set -euo pipefail
KP="${AXP_KERNEL_PATCHES:-/srv/rom/references/axp/kernel_patches}"
KERNEL_DIR="${1:-/srv/rom/src/lineage/kernel/google/msm-4.14}"
HERE="$(cd "$(dirname "$0")" && pwd)"
LIST="${CVE_STRICT_LIST:-$HERE/cve-strict.list}"
DENY="${CVE_DENYLIST:-$HERE/cve-denylist.txt}"
LOG_DIR="${CVE_APPLY_LOG_DIR:-/srv/rom/artifacts/009-axp-los23-port/cve-stage}"
CONTINUE="${CVE_STRICT_CONTINUE:-0}"
# Reject apply if GNU patch reports fuzz >= this (0 = disable fuzz fail)
MAX_FUZZ="${CVE_MAX_FUZZ:-1}"
# Reject if any hunk offset abs(lines) >= this (0 = disable)
MAX_ABS_OFFSET="${CVE_MAX_ABS_OFFSET:-200}"
DRY_RUN=0
[[ "${2:-}" == "--dry-run" ]] && DRY_RUN=1
if [[ ! -d "$KERNEL_DIR/include/linux" ]]; then
echo "error: kernel dir missing: $KERNEL_DIR" >&2
exit 1
fi
if [[ ! -d "$KP" ]]; then
echo "error: AXP kernel_patches missing: $KP" >&2
exit 1
fi
if [[ ! -f "$LIST" ]]; then
echo "error: list missing: $LIST" >&2
exit 1
fi
mkdir -p "$LOG_DIR"
STAMP=$(date -u +%Y%m%dT%H%M%SZ)
LOG="$LOG_DIR/apply-cve-strict-${STAMP}.log"
FAIL_LIST="$LOG_DIR/apply-cve-strict-${STAMP}.fail.txt"
REJECT_DIR="${CVE_REJECT_DIR:-$LOG_DIR/rejects-${STAMP}}"
mkdir -p "$REJECT_DIR"
: >"$FAIL_LIST"
declare -A DENY_MAP=()
if [[ -f "$DENY" ]]; then
while IFS= read -r d || [[ -n "$d" ]]; do
[[ -z "$d" || "$d" =~ ^# ]] && continue
if [[ "$d" == *"/kernel_patches/"* ]]; then
DENY_MAP["${d##*/kernel_patches/}"]=1
else
DENY_MAP["$d"]=1
fi
done <"$DENY"
fi
ok=0
fail=0
skip=0
miss=0
quality_fail=0
echo "=== CVE strict apply kernel=$KERNEL_DIR dry_run=$DRY_RUN continue=$CONTINUE max_fuzz=$MAX_FUZZ max_abs_offset=$MAX_ABS_OFFSET ===" | tee "$LOG"
while IFS= read -r rel || [[ -n "$rel" ]]; do
[[ -z "$rel" || "$rel" =~ ^# ]] && continue
if [[ -n "${DENY_MAP[$rel]:-}" ]]; then
echo "SKIP_DENY $rel" | tee -a "$LOG"
skip=$((skip + 1))
continue
fi
p="$KP/$rel"
if [[ ! -f "$p" ]]; then
echo "MISS $rel" | tee -a "$LOG"
miss=$((miss + 1))
echo "$rel" >>"$FAIL_LIST"
if [[ "$CONTINUE" != "1" ]]; then
echo "error: missing patch (abort)" >&2
exit 1
fi
continue
fi
args=(-p1 --batch -d "$KERNEL_DIR" --forward --no-backup-if-mismatch)
if [[ "$DRY_RUN" -eq 1 ]]; then
args+=(--dry-run)
fi
patch_log=$(mktemp)
set +e
patch "${args[@]}" <"$p" >"$patch_log" 2>&1
prc=$?
set -e
cat "$patch_log" >>"$LOG"
# Quality: fuzz / large offsets even when exit 0
fuzz_max=0
abs_off_max=0
eval "$(python3 -c '
import re, sys
text = open(sys.argv[1], errors="replace").read()
fuzz = off = 0
for m in re.finditer(r"with fuzz (\d+)", text):
fuzz = max(fuzz, int(m.group(1)))
for m in re.finditer(r"\(offset ([+-]?\d+) lines\)", text):
off = max(off, abs(int(m.group(1))))
print(f"fuzz_max={fuzz}")
print(f"abs_off_max={off}")
' "$patch_log")"
rm -f "$patch_log"
qbad=0
if [[ "$MAX_FUZZ" -gt 0 && "$fuzz_max" -ge "$MAX_FUZZ" ]]; then
echo "QUALITY_FAIL fuzz=$fuzz_max>=$MAX_FUZZ $rel" | tee -a "$LOG"
qbad=1
fi
if [[ "$MAX_ABS_OFFSET" -gt 0 && "$abs_off_max" -ge "$MAX_ABS_OFFSET" ]]; then
echo "QUALITY_FAIL abs_offset=$abs_off_max>=$MAX_ABS_OFFSET $rel" | tee -a "$LOG"
qbad=1
fi
if [[ "$prc" -eq 0 && "$qbad" -eq 0 ]]; then
echo "OK $rel (fuzz_max=$fuzz_max abs_off_max=$abs_off_max)" | tee -a "$LOG"
ok=$((ok + 1))
continue
fi
# Failure path: preserve rejects
echo "FAIL $rel patch_rc=$prc fuzz_max=$fuzz_max abs_off_max=$abs_off_max" | tee -a "$LOG"
echo "$rel" >>"$FAIL_LIST"
fail=$((fail + 1))
[[ "$qbad" -eq 1 ]] && quality_fail=$((quality_fail + 1))
safe=$(echo "$rel" | tr '/' '_')
dest="$REJECT_DIR/$safe"
mkdir -p "$dest"
# move any rej/orig created under kernel tree
while IFS= read -r -d '' rej; do
mv "$rej" "$dest/" 2>/dev/null || cp -a "$rej" "$dest/" || true
done < <(find "$KERNEL_DIR" -name '*.rej' -print0 2>/dev/null)
while IFS= read -r -d '' orig; do
mv "$orig" "$dest/" 2>/dev/null || cp -a "$orig" "$dest/" || true
done < <(find "$KERNEL_DIR" -name '*.orig' -print0 2>/dev/null)
cp -a "$p" "$dest/patch" 2>/dev/null || true
echo "rejects_kept=$dest" | tee -a "$LOG"
if [[ "$CONTINUE" != "1" ]]; then
echo "error: abort on FAIL (set CVE_STRICT_CONTINUE=1 to keep going)" >&2
echo "CVE strict ABORT OK=$ok FAIL=$fail QUALITY_FAIL=$quality_fail SKIP_DENY=$skip MISS=$miss log=$LOG" | tee -a "$LOG"
exit 1
fi
done <"$LIST"
echo "CVE strict done OK=$ok FAIL=$fail QUALITY_FAIL=$quality_fail SKIP_DENY=$skip MISS=$miss dry_run=$DRY_RUN continue=$CONTINUE log=$LOG rejects=$REJECT_DIR" | tee -a "$LOG"
if [[ "$fail" -gt 0 && "$CONTINUE" != "1" ]]; then
exit 1
fi
if [[ "$ok" -eq 0 && "$DRY_RUN" -eq 0 ]]; then
echo "error: zero CVE patches applied" >&2
exit 1
fi