Release-keys/AVB, CVE clean+hi batches, Yama/slabrand, Pro branding, bundled apps, and AXP-class product surface docs/scripts.
165 lines
5.1 KiB
Bash
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
|