mirror of
https://github.com/speed47/spectre-meltdown-checker.git
synced 2026-09-13 14:23:27 +02:00
Compare commits
14
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff8e6ff861 | ||
|
|
4bfd452931 | ||
|
|
dcaed638f1 | ||
|
|
8f3f295a14 | ||
|
|
85e5daad8f | ||
|
|
a441987adb | ||
|
|
c1aee44717 | ||
|
|
4031b0f3bd | ||
|
|
d6624c30af | ||
|
|
26cf31b282 | ||
|
|
3f4801e6a7 | ||
|
|
9a3688b6fd | ||
|
|
0c89d162a3 | ||
|
|
02fa416bab |
@@ -7,30 +7,117 @@ on:
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
autoupdate:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: source
|
||||
- name: Install prerequisites
|
||||
run: sudo apt-get update && sudo apt-get install -y --no-install-recommends iucode-tool sqlite3 unzip
|
||||
run: sudo apt-get update && sudo apt-get install -y --no-install-recommends iucode-tool sqlite3 unzip shfmt python3
|
||||
- name: Update microcode versions
|
||||
run: ./spectre-meltdown-checker.sh --update-builtin-fwdb
|
||||
run: ./scripts/update_mcedb.sh
|
||||
- name: Update Intel models
|
||||
run: ./scripts/update_intel_models.sh
|
||||
- name: Update Intel affected processors
|
||||
run: |
|
||||
git clone https://github.com/intel/Intel-affected-processor-list.git \
|
||||
"$RUNNER_TEMP/Intel-affected-processor-list"
|
||||
python3 scripts/intel-affected-processor-list/build_inteldb.py \
|
||||
"$RUNNER_TEMP/Intel-affected-processor-list" src/db/100_inteldb.sh \
|
||||
--base-db scripts/intel-affected-processor-list/historical_records.db
|
||||
- name: Check git diff
|
||||
id: diff
|
||||
run: |
|
||||
echo change="$(git diff spectre-meltdown-checker.sh | awk '/MCEDB/ { if(V) { print V" to "$4; exit } else { V=$4 } }')" >> "$GITHUB_OUTPUT"
|
||||
echo nbdiff="$(git diff spectre-meltdown-checker.sh | grep -cE -- '^\+# [AI],')" >> "$GITHUB_OUTPUT"
|
||||
if git diff --quiet -- src/db/200_mcedb.sh src/libs/003_intel_models.sh src/db/100_inteldb.sh; then
|
||||
echo "changed=false" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "changed=true" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
python3 - <<'PY'
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
def previous(path):
|
||||
return subprocess.check_output(['git', 'show', f'HEAD:{path}'], text=True)
|
||||
|
||||
def records(text, kind):
|
||||
result = {}
|
||||
for line in text.splitlines():
|
||||
if kind == 'microcode' and re.match(r'^# [AI],', line):
|
||||
fields = line[2:].split(',')
|
||||
result[tuple(fields[:3])] = tuple(fields[3:])
|
||||
elif kind == 'models':
|
||||
match = re.match(r'\s*readonly (INTEL_\w+)=(.*)', line)
|
||||
if match:
|
||||
result[match[1]] = match[2]
|
||||
elif kind == 'processors' and line.startswith('# 0x'):
|
||||
fields = line[2:].rstrip(',').split(',')
|
||||
qualifier = fields[1] if fields[1].startswith('H=') else ''
|
||||
result[(fields[0], qualifier)] = tuple(fields[2:] if qualifier else fields[1:])
|
||||
return result
|
||||
|
||||
outputs = {}
|
||||
for kind, path in (
|
||||
('microcode', 'src/db/200_mcedb.sh'),
|
||||
('models', 'src/libs/003_intel_models.sh'),
|
||||
('processors', 'src/db/100_inteldb.sh'),
|
||||
):
|
||||
old_text = previous(path)
|
||||
new_text = Path(path).read_text(encoding='utf-8')
|
||||
old = records(old_text, kind)
|
||||
new = records(new_text, kind)
|
||||
added = len(new.keys() - old.keys())
|
||||
removed = len(old.keys() - new.keys())
|
||||
updated = sum(old[key] != new[key] for key in old.keys() & new.keys())
|
||||
outputs[kind] = f'{added} added, {updated} updated, {removed} removed ({len(new)} total)'
|
||||
if kind == 'microcode':
|
||||
def version(text):
|
||||
match = re.search(r'^# %%% MCEDB (\S+)', text, re.MULTILINE)
|
||||
if not match:
|
||||
raise ValueError('Missing MCEDB version marker')
|
||||
return match[1]
|
||||
before, after = version(old_text), version(new_text)
|
||||
outputs['mcedb'] = f'{before} -> {after}' if before != after else f'{after} (unchanged)'
|
||||
outputs['microcode_changes'] = added + updated + removed
|
||||
outputs['intel_revision'] = subprocess.check_output(
|
||||
['git', '-C', os.path.join(os.environ['RUNNER_TEMP'], 'Intel-affected-processor-list'),
|
||||
'rev-parse', 'HEAD'], text=True,
|
||||
).strip()
|
||||
with open(os.environ['GITHUB_OUTPUT'], 'a', encoding='utf-8') as stream:
|
||||
for key, value in outputs.items():
|
||||
print(f'{key}={value}', file=stream)
|
||||
PY
|
||||
git diff
|
||||
cat "$GITHUB_OUTPUT"
|
||||
- name: Create Pull Request if needed
|
||||
if: steps.diff.outputs.nbdiff != '0'
|
||||
if: steps.diff.outputs.changed == 'true'
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
with:
|
||||
base: source
|
||||
branch: autoupdate-fwdb
|
||||
commit-message: "update: fwdb from ${{ steps.diff.outputs.change }}, ${{ steps.diff.outputs.nbdiff }} microcode changes"
|
||||
title: "[Auto] Update fwdb from ${{ steps.diff.outputs.change }}"
|
||||
add-paths: |
|
||||
src/db/200_mcedb.sh
|
||||
src/libs/003_intel_models.sh
|
||||
src/db/100_inteldb.sh
|
||||
commit-message: |
|
||||
update: CPU databases, ${{ steps.diff.outputs.microcode_changes }} microcode changes
|
||||
|
||||
MCEDB: ${{ steps.diff.outputs.mcedb }}
|
||||
Microcode records: ${{ steps.diff.outputs.microcode }}
|
||||
Intel models: ${{ steps.diff.outputs.models }}
|
||||
Intel affected-processor profiles: ${{ steps.diff.outputs.processors }}
|
||||
Intel CSV revision: ${{ steps.diff.outputs.intel_revision }}
|
||||
title: "[Auto] Update CPU databases: MCEDB ${{ steps.diff.outputs.mcedb }}, ${{ steps.diff.outputs.microcode_changes }} microcode changes"
|
||||
body: |
|
||||
Automated PR to update fwdb from ${{ steps.diff.outputs.change }}
|
||||
Detected ${{ steps.diff.outputs.nbdiff }} microcode changes
|
||||
Automated PR to refresh the CPU/microcode databases:
|
||||
|
||||
- **MCEDB version:** ${{ steps.diff.outputs.mcedb }}
|
||||
- **Microcode records:** ${{ steps.diff.outputs.microcode }}
|
||||
- **Intel CPU models:** ${{ steps.diff.outputs.models }}
|
||||
- **Intel affected-processor profiles:** ${{ steps.diff.outputs.processors }}
|
||||
|
||||
@@ -25,21 +25,81 @@ jobs:
|
||||
mv spectre-meltdown-checker.sh dist/
|
||||
- name: check direct execution
|
||||
run: |
|
||||
set -x
|
||||
expected=$(cat .github/workflows/expected_cve_count)
|
||||
cd dist
|
||||
nb=$(sudo ./spectre-meltdown-checker.sh --batch json | jq '.[]|.CVE' | wc -l)
|
||||
|
||||
json=$(sudo ./spectre-meltdown-checker.sh --batch json || true)
|
||||
|
||||
# Validate JSON is well-formed (and show it if not)
|
||||
echo "$json" | jq . >/dev/null || {
|
||||
echo "Invalid JSON produced by spectre-meltdown-checker.sh"
|
||||
echo "$json"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Validate required keys exist
|
||||
for key in meta system cpu cpu_microcode vulnerabilities; do
|
||||
echo "$json" | jq -e ".$key" >/dev/null || {
|
||||
echo "Missing top-level key: $key"
|
||||
echo "$json" | jq .
|
||||
exit 1
|
||||
}
|
||||
done
|
||||
|
||||
# Use -r to get raw scalars (no quotes)
|
||||
fmtver=$(echo "$json" | jq -r '.meta.format_version // empty')
|
||||
if [ "$fmtver" != "1" ]; then
|
||||
echo "Unexpected format_version: $fmtver"
|
||||
echo "$json" | jq .
|
||||
exit 1
|
||||
fi
|
||||
|
||||
run_as_root=$(echo "$json" | jq -r '.meta.run_as_root // empty')
|
||||
if [ "$run_as_root" != "true" ]; then
|
||||
echo "Expected run_as_root=true, got: $run_as_root"
|
||||
echo "$json" | jq .
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mocked=$(echo "$json" | jq -r '.meta.mocked // "false"')
|
||||
if [ "$mocked" = "true" ]; then
|
||||
echo "mocked=true must never appear in production"
|
||||
echo "$json" | jq .
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Count CVEs robustly (as a number)
|
||||
nb=$(echo "$json" | jq -r '[.vulnerabilities[].cve] | length')
|
||||
if [ "$nb" -ne "$expected" ]; then
|
||||
echo "Invalid number of CVEs reported: $nb instead of $expected"
|
||||
echo "$json" | jq '.vulnerabilities[].cve'
|
||||
exit 1
|
||||
else
|
||||
echo "OK $nb CVEs reported"
|
||||
fi
|
||||
|
||||
# Validate json-terse backward compatibility
|
||||
nb_terse=$(sudo ./spectre-meltdown-checker.sh --batch json-terse | jq -r 'map(.CVE) | length')
|
||||
if [ "$nb_terse" -ne "$expected" ]; then
|
||||
echo "json-terse backward compat broken: $nb_terse CVEs instead of $expected"
|
||||
exit 1
|
||||
else
|
||||
echo "OK json-terse backward compat: $nb_terse CVEs"
|
||||
fi
|
||||
- name: check docker compose run execution
|
||||
run: |
|
||||
expected=$(cat .github/workflows/expected_cve_count)
|
||||
cd dist
|
||||
docker compose build
|
||||
nb=$(docker compose run --rm spectre-meltdown-checker --batch json | jq '.[]|.CVE' | wc -l)
|
||||
json=$(docker compose run --rm spectre-meltdown-checker --batch json || true)
|
||||
echo "$json" | jq . > /dev/null
|
||||
fmtver=$(echo "$json" | jq '.meta.format_version')
|
||||
if [ "$fmtver" != "1" ]; then
|
||||
echo "Unexpected format_version: $fmtver"
|
||||
exit 1
|
||||
fi
|
||||
nb=$(echo "$json" | jq '.vulnerabilities[].cve' | wc -l)
|
||||
if [ "$nb" -ne "$expected" ]; then
|
||||
echo "Invalid number of CVEs reported: $nb instead of $expected"
|
||||
exit 1
|
||||
@@ -51,7 +111,14 @@ jobs:
|
||||
expected=$(cat .github/workflows/expected_cve_count)
|
||||
cd dist
|
||||
docker build -t spectre-meltdown-checker .
|
||||
nb=$(docker run --rm --privileged -v /boot:/boot:ro -v /dev/cpu:/dev/cpu:ro -v /lib/modules:/lib/modules:ro spectre-meltdown-checker --batch json | jq '.[]|.CVE' | wc -l)
|
||||
json=$(docker run --rm --privileged -v /boot:/boot:ro -v /dev/cpu:/dev/cpu:ro -v /lib/modules:/lib/modules:ro spectre-meltdown-checker --batch json || true)
|
||||
echo "$json" | jq . > /dev/null
|
||||
fmtver=$(echo "$json" | jq '.meta.format_version')
|
||||
if [ "$fmtver" != "1" ]; then
|
||||
echo "Unexpected format_version: $fmtver"
|
||||
exit 1
|
||||
fi
|
||||
nb=$(echo "$json" | jq '.vulnerabilities[].cve' | wc -l)
|
||||
if [ "$nb" -ne "$expected" ]; then
|
||||
echo "Invalid number of CVEs reported: $nb instead of $expected"
|
||||
exit 1
|
||||
@@ -92,15 +159,19 @@ jobs:
|
||||
fi
|
||||
- name: create a pull request to ${{ github.ref_name }}-build
|
||||
run: |
|
||||
# all the files in dist/* and .github/* must be moved as is to the -build branch root, move them out for now:
|
||||
tmpdir=$(mktemp -d)
|
||||
mv ./dist/* .github $tmpdir/
|
||||
rm -rf ./dist
|
||||
|
||||
git fetch origin ${{ github.ref_name }}-build
|
||||
git checkout -f ${{ github.ref_name }}-build
|
||||
rm -rf doc/
|
||||
mv $tmpdir/* .
|
||||
rm -rf src/
|
||||
rm -rf src/ scripts/ img/
|
||||
mkdir -p .github
|
||||
rsync -vaP --delete $tmpdir/.github/ .github/
|
||||
|
||||
git add --all
|
||||
echo =#=#= DIFF CACHED
|
||||
git diff --cached
|
||||
|
||||
@@ -1 +1 @@
|
||||
26
|
||||
32
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
name: release
|
||||
|
||||
# Manual, path-scoped release helper for master.
|
||||
#
|
||||
# `master` is BOTH the distribution branch (users download the script here)
|
||||
# AND the default branch that hosts the scheduled CI workflows
|
||||
# (autoupdate / stale / vuln-watch). `source-build` is a build-OUTPUT branch.
|
||||
#
|
||||
# We therefore never merge source-build into master: that would drag source-build's
|
||||
# whole tree, including the *absence* of the master-only workflows.
|
||||
# Instead we copy only the assembled artifact files across, and cut GitHub
|
||||
# releases from master directly.
|
||||
#
|
||||
# Two independent manual actions to run against the `master` branch:
|
||||
#
|
||||
# 1. sync-from-source-build : open a PR against master carrying the assembled
|
||||
# files (everything on source-build EXCEPT
|
||||
# .github/). Nothing lands on master until the PR
|
||||
# is reviewed and merged.
|
||||
# 2. draft-github-release : create a DRAFT GitHub release from the script
|
||||
# currently on master, with an auto-drafted
|
||||
# changelog.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
action:
|
||||
description: What to do
|
||||
type: choice
|
||||
required: true
|
||||
default: sync-from-source-build
|
||||
options:
|
||||
- sync-from-source-build
|
||||
- draft-github-release
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
concurrency:
|
||||
group: release-master
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
# ---------------------------------------------------------------------------
|
||||
# 1. Copy assembled files from source-build onto master (no .github/),
|
||||
# as a pull request.
|
||||
# ---------------------------------------------------------------------------
|
||||
sync-from-source-build:
|
||||
if: inputs.action == 'sync-from-source-build'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: master
|
||||
fetch-depth: 0
|
||||
persist-credentials: true
|
||||
|
||||
- name: sync assembled files from source-build
|
||||
id: sync
|
||||
run: |
|
||||
set -eu
|
||||
git fetch --no-tags origin source-build
|
||||
|
||||
# Every top-level entry on source-build EXCEPT .github/ (master keeps
|
||||
# its own CI). Computed dynamically so any new top-level artifact is
|
||||
# picked up automatically.
|
||||
readarray -t paths < <(git ls-tree --name-only origin/source-build | grep -vxF '.github')
|
||||
echo "Syncing: ${paths[*]}"
|
||||
|
||||
# Mirror source-build exactly for those paths, removing first so that
|
||||
# deletions/renames inside doc/ etc. propagate too.
|
||||
for p in "${paths[@]}"; do rm -rf -- "$p"; done
|
||||
git checkout origin/source-build -- "${paths[@]}"
|
||||
git add --all -- "${paths[@]}"
|
||||
|
||||
if git diff --cached --quiet; then
|
||||
echo "master already up to date with source-build; nothing to sync."
|
||||
echo "changed=false" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
{
|
||||
echo "changed=true"
|
||||
echo "version=$(grep -m1 "^VERSION=" spectre-meltdown-checker.sh | cut -d"'" -f2)"
|
||||
echo "sb=$(git rev-parse origin/source-build)"
|
||||
echo "sbdate=$(git log -1 --format=%ai origin/source-build)"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
# Note: the repo must have "Allow GitHub Actions to create and approve
|
||||
# pull requests" enabled for this to work.
|
||||
- name: open the sync pull request
|
||||
if: steps.sync.outputs.changed == 'true'
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
with:
|
||||
base: master
|
||||
branch: release/sync-from-source-build
|
||||
delete-branch: true
|
||||
committer: "github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>"
|
||||
author: "github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>"
|
||||
title: "release: sync v${{ steps.sync.outputs.version }} from source-build"
|
||||
commit-message: |
|
||||
release: sync v${{ steps.sync.outputs.version }} from source-build
|
||||
|
||||
built from source-build commit ${{ steps.sync.outputs.sb }}
|
||||
dated ${{ steps.sync.outputs.sbdate }}
|
||||
body: |
|
||||
Assembled files copied from `source-build` onto `master` (everything
|
||||
except `.github/`, which stays master-only).
|
||||
|
||||
- version: `${{ steps.sync.outputs.version }}`
|
||||
- built from source-build commit: ${{ steps.sync.outputs.sb }}
|
||||
- dated: ${{ steps.sync.outputs.sbdate }}
|
||||
|
||||
Once merged, run this workflow again with the `draft-github-release`
|
||||
action to cut the release, if required.
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 2. Draft a GitHub release from the script currently on master.
|
||||
# ---------------------------------------------------------------------------
|
||||
draft-github-release:
|
||||
if: inputs.action == 'draft-github-release'
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: master
|
||||
fetch-depth: 0
|
||||
persist-credentials: true
|
||||
|
||||
- name: draft a release from the current master script
|
||||
run: |
|
||||
set -eu
|
||||
ver=$(grep -m1 "^VERSION=" spectre-meltdown-checker.sh | cut -d"'" -f2)
|
||||
tag="v${ver}"
|
||||
|
||||
if gh release view "$tag" >/dev/null 2>&1; then
|
||||
echo "A release for $tag already exists; refusing to recreate." >&2
|
||||
echo "Delete it first if needed." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Draft the changelog from the source-build commits assembled since the
|
||||
# previous published release. We locate the source-build commit whose
|
||||
# built VERSION equals the last release tag, then list what came after.
|
||||
git fetch --no-tags origin source-build
|
||||
last_tag=$(gh release list --exclude-drafts --limit 1 --json tagName --jq '.[0].tagName // empty')
|
||||
old_ver="${last_tag#v}"
|
||||
|
||||
base=""
|
||||
if [ -n "$old_ver" ]; then
|
||||
while read -r h; do
|
||||
v=$(git show "$h:spectre-meltdown-checker.sh" 2>/dev/null | grep -m1 "^VERSION=" | cut -d"'" -f2 || true)
|
||||
if [ "$v" = "$old_ver" ]; then base="$h"; break; fi
|
||||
done < <(git rev-list --max-count=500 origin/source-build)
|
||||
fi
|
||||
|
||||
{
|
||||
echo "## ${tag}"
|
||||
echo
|
||||
if [ -n "$base" ]; then
|
||||
git log --no-merges --format='- %s' "${base}..origin/source-build"
|
||||
else
|
||||
echo "_Could not determine the previous release point automatically — please fill in the changelog. Last 30 assembled commits below as a starting point:_"
|
||||
echo
|
||||
git log --no-merges --format='- %s' --max-count=30 origin/source-build
|
||||
fi
|
||||
} > notes.md
|
||||
|
||||
echo "----- draft notes -----"; cat notes.md; echo "-----------------------"
|
||||
|
||||
gh release create "$tag" \
|
||||
--draft \
|
||||
--target "$GITHUB_SHA" \
|
||||
--title "$tag" \
|
||||
--notes-file notes.md \
|
||||
spectre-meltdown-checker.sh
|
||||
|
||||
echo "Draft release $tag created."
|
||||
@@ -8,7 +8,7 @@ on:
|
||||
action:
|
||||
description: "dry-run"
|
||||
required: true
|
||||
default: "dryrun"
|
||||
default: "apply"
|
||||
type: choice
|
||||
options:
|
||||
- dryrun
|
||||
@@ -30,4 +30,7 @@ jobs:
|
||||
days-before-close: 7
|
||||
stale-issue-label: stale
|
||||
remove-stale-when-updated: true
|
||||
close-issue-reason: completed
|
||||
stale-issue-message: "If there are no further comments or activity on this issue, it'll be closed automatically in 7 days."
|
||||
close-issue-message: "Automatically closing this issue due to inactivity, don't hesitate to open a new issue if needed."
|
||||
debug-only: ${{ case(inputs.action == 'dryrun', true, false) }}
|
||||
|
||||
@@ -45,14 +45,14 @@ jobs:
|
||||
# workflow file itself MUST stay on the default branch, as GitHub only
|
||||
# honors `schedule:` triggers on the default branch.
|
||||
- name: Checkout vuln-watch branch (scripts + prompt)
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: vuln-watch
|
||||
fetch-depth: 1
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: '3.12'
|
||||
|
||||
@@ -84,7 +84,7 @@ jobs:
|
||||
|
||||
- name: Download previous state artifact
|
||||
if: steps.prev.outputs.run_id != ''
|
||||
uses: actions/download-artifact@v5
|
||||
uses: actions/download-artifact@v8
|
||||
continue-on-error: true # tolerate retention expiry
|
||||
with:
|
||||
name: vuln-watch-state
|
||||
@@ -115,7 +115,7 @@ jobs:
|
||||
# implemented?". Only fetched on days with something to classify.
|
||||
- name: Checkout checker code (test branch) for coverage grep
|
||||
if: steps.diff.outputs.new_count != '0' || steps.diff.outputs.reconsider_count != '0'
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: test
|
||||
path: checker
|
||||
@@ -150,7 +150,7 @@ jobs:
|
||||
|
||||
- name: Upload Claude execution log
|
||||
if: ${{ always() && steps.classify.outputs.execution_file != '' }}
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: claude-execution-log-${{ github.run_id }}
|
||||
path: ${{ steps.classify.outputs.execution_file }}
|
||||
@@ -168,7 +168,7 @@ jobs:
|
||||
|
||||
- name: Upload new state artifact
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: vuln-watch-state
|
||||
path: state/seen.json
|
||||
@@ -177,7 +177,7 @@ jobs:
|
||||
|
||||
- name: Upload daily report
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: vuln-watch-report-${{ github.run_id }}
|
||||
path: |
|
||||
|
||||
@@ -40,6 +40,14 @@ CVE | Name | Aliases
|
||||
[CVE-2024-45332](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-45332) | Branch Privilege Injection | BPI
|
||||
[CVE-2025-54505](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2025-54505) | AMD Zen1 Floating-Point Divider Stale Data Leak | FPDSS
|
||||
|
||||
The following entries are ARM64 silicon errata that the kernel actively works around. They have no assigned CVE; they are tracked only by ARM's erratum numbers. Select them with `--errata <number>` or the associated `--variant` mnemonic.
|
||||
|
||||
ID | Name | Affected cores
|
||||
-- | ---- | --------------
|
||||
CVE-0001-0001 | Speculative AT TLB corruption (errata 1165522, 1319367, 1319537, 1530923) | Cortex-A55/A57/A72/A76
|
||||
CVE-0001-0002 | Speculative unprivileged load (errata 2966298, 3117295) | Cortex-A510/A520
|
||||
CVE-0001-0003 | MSR SSBS not self-synchronizing (erratum 3194386 + siblings) | Cortex-A76/A77/A78/A78C/A710/A715/A720/A720AE/A725, X1/X1C/X2/X3/X4/X925, Neoverse-N1/N2/N3/V1/V2/V3/V3AE
|
||||
|
||||
## Am I at risk?
|
||||
|
||||
Depending on your situation, the table below answers whether an attacker in a given position can extract data from a given target.
|
||||
@@ -272,23 +280,23 @@ In **Hardware-only** mode, the script only reports CPU information and per-CVE h
|
||||
|
||||
- Get the latest version of the script using `curl` *or* `wget`
|
||||
|
||||
```bash
|
||||
curl -L https://meltdown.ovh -o spectre-meltdown-checker.sh
|
||||
wget https://meltdown.ovh -O spectre-meltdown-checker.sh
|
||||
```
|
||||
```bash
|
||||
curl -L https://meltdown.ovh -o spectre-meltdown-checker.sh
|
||||
wget https://meltdown.ovh -O spectre-meltdown-checker.sh
|
||||
```
|
||||
|
||||
- Inspect the script. You never blindly run scripts you downloaded from the Internet, do you?
|
||||
|
||||
```bash
|
||||
vim spectre-meltdown-checker.sh
|
||||
```
|
||||
```bash
|
||||
vim spectre-meltdown-checker.sh
|
||||
```
|
||||
|
||||
- When you're ready, run the script as root
|
||||
|
||||
```bash
|
||||
chmod +x spectre-meltdown-checker.sh
|
||||
sudo ./spectre-meltdown-checker.sh
|
||||
```
|
||||
```bash
|
||||
chmod +x spectre-meltdown-checker.sh
|
||||
sudo ./spectre-meltdown-checker.sh
|
||||
```
|
||||
|
||||
### Using a docker container
|
||||
|
||||
|
||||
@@ -188,6 +188,18 @@ Observable timing discrepancy in some Intel processors allows an authenticated u
|
||||
|
||||
**Why out of scope:** Like CVE-2020-24511, this is a microcode-only fix with no Linux kernel sysfs entry, no CPUID bit, no MSR, and no kernel configuration option. Detection would require a per-CPU-stepping microcode version lookup table. The vulnerability has low severity (CVSS 2.8) and practical exploitation is limited. Intel dropped microcode support for Sandy Bridge and Ivy Bridge, leaving those generations permanently vulnerable.
|
||||
|
||||
## CVE-2021-26314 / CVE-2021-26313 — Floating-Point Value Injection (FPVI) and Speculative Code Store Bypass (SCSB)
|
||||
|
||||
- **Bulletin:** [AMD-SB-1003](https://www.amd.com/en/resources/product-security/bulletin/amd-sb-1003.html) (FPVI and SCSB); [AMD-SB-7050](https://www.amd.com/en/resources/product-security/bulletin/amd-sb-7050.html) (FPVI variant, informational)
|
||||
- **Intel advisory:** [Floating Point Value Injection](https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/advisory-guidance/floating-point-value-injection.html)
|
||||
- **Research paper:** [Rage Against the Machine Clear (FPVI/SCSB) — VUSec, USENIX Security '21](https://www.vusec.net/projects/fpvi-scsb/)
|
||||
- **Affected CPUs:** All supported AMD CPU products; Intel CPUs (FPVI)
|
||||
- **CVSS:** 5.5 (Medium) for both
|
||||
|
||||
FPVI (CVE-2021-26314) lets an attacker inject arbitrary floating-point values into the transient execution window opened by a floating-point machine clear, so that dependent operations transiently compute on attacker-influenced values that can then be inferred through a microarchitectural covert channel. SCSB (CVE-2021-26313) is the companion vulnerability where overwritten instructions may still be executed speculatively. AMD-SB-7050 documents an FPVI variant (from the "TREVEX" detection-framework paper) that can be triggered without denormal inputs; AMD considers it to fall within the existing scope of CVE-2021-26314 and assigned it no new CVE, classifying it as informational only.
|
||||
|
||||
**Why out of scope:** The mitigation responsibility falls on individual software, not on the kernel or microcode. Both AMD and Intel recommend that software vendors analyze their code for vulnerable speculative floating-point sequences and insert an `LFENCE` to serialize execution. No microcode update, no CPUID flag, no MSR, and no kernel configuration option was issued, and there is no `/sys/devices/system/cpu/vulnerabilities/` entry for FPVI or SCSB — the kernel never added one, because the fix is not a kernel-level control. This is the same situation as [SLAM (CVE-2020-12965)](#cve-2020-12965--transient-execution-of-non-canonical-accesses-slam) and "Take A Way": the vendor's guidance is "software inserts LFENCE in its own code," leaving nothing for this tool to check. The AMD-SB-7050 variant adds nothing detectable, as it is informational and reuses the existing (software-only) FPVI guidance.
|
||||
|
||||
## CVE-2021-26318 — AMD Prefetch Attacks through Power and Time
|
||||
|
||||
- **Issue:** [#412](https://github.com/speed47/spectre-meltdown-checker/issues/412)
|
||||
@@ -307,3 +319,35 @@ A weakness in AMD's microcode signature verification (AES-CMAC hash) allows load
|
||||
Exploits a synchronization failure in the AMD stack engine via an undocumented MSR bit, targeting AMD SEV-SNP confidential VMs. Requires hypervisor-level (ring 0) access.
|
||||
|
||||
**Why out of scope:** Not a transient/speculative execution side channel. This is an architectural attack on AMD SEV-SNP confidential computing that requires hypervisor access, which is outside the threat model of this tool.
|
||||
|
||||
## CVE-2025-52533 — AMD On-Chip Debug Interface Improper Access Control
|
||||
|
||||
- **Advisory:** [NVD CVE-2025-52533](https://nvd.nist.gov/vuln/detail/CVE-2025-52533)
|
||||
- **Affected CPUs:** AMD (various; on-chip debug/test interface)
|
||||
- **CVSS:** 8.7 (High)
|
||||
- **CWE:** [CWE-1191 (On-Chip Debug and Test Interface With Improper Access Control)](https://cwe.mitre.org/data/definitions/1191.html)
|
||||
|
||||
Improper access control in an on-chip debug interface could allow a privileged attacker to enable a debug interface and potentially compromise data confidentiality or integrity.
|
||||
|
||||
**Why out of scope:** Not a transient or speculative execution vulnerability — this is an access-control flaw in a hardware debug/test interface (CWE-1191), with no side-channel or speculative execution component, and it requires a privileged attacker. There is no Linux kernel sysfs entry, no CPUID flag, and no kernel-side mitigation: the fix is delivered as platform/PSP firmware and proven via remote attestation against AMD's Key Distribution Service (KDS), with several SKUs marked "no fix planned." None of this is detectable by this tool, which inspects OS-loadable microcode revisions, CPUID/MSR bits, kernel capabilities, and sysfs.
|
||||
|
||||
## CVE-2026-46174 — AMD Zen 2 Op Cache Improper Resource Isolation
|
||||
|
||||
- **Bulletin:** [AMD-SB-7052](https://www.amd.com/en/resources/product-security/bulletin/amd-sb-7052.html) (CPU OP Cache Corruption)
|
||||
- **Kernel fix:** [commit 1e23b30a80b1](https://github.com/torvalds/linux/commit/1e23b30a80b14e5764657401ee2cca030525ae8e) — `x86/CPU/AMD: Prevent improper isolation of shared resources in Zen2's op cache`
|
||||
- **Affected CPUs:** AMD Zen 2
|
||||
- **CVSS:** 8.8 (High)
|
||||
|
||||
Resources in the Zen 2 micro-op (op) cache can be improperly shared, causing instruction corruption that may be leveraged to execute instructions at a higher privilege level (userspace-to-kernel escalation). The Linux fix sets a bug-fix bit (bit 33) in the AMD `BP_CFG` model-specific register (`0xc001102e`) via `msr_set_bit()` in `init_amd_zen2()`, and only on bare metal (skipped when `X86_FEATURE_HYPERVISOR` is set, as the mitigation is the host's responsibility for guests).
|
||||
|
||||
**Why out of scope:** Not a transient or speculative execution vulnerability — this is an op-cache resource-isolation bug that causes *instruction corruption* (an integrity/correctness erratum), with no side-channel or speculative data-leak component, which places it outside the vulnerability class this tool detects. It is also undetectable by this tool's standard framework: the kernel deliberately adds no `/sys/devices/system/cpu/vulnerabilities/` entry, no `X86_BUG_*` flag (so nothing in `/proc/cpuinfo`), no dmesg message, and no kernel command-line parameter. The mitigation is an unconditional inline MSR bit-set with no greppable named symbol, so it leaves no handle for no-runtime (kernel image / `System.map`) detection. The only possible check would be a live read of `BP_CFG` bit 33, which requires root and the `msr` module, works on bare metal only (guests report `N/A`), and would be a bespoke one-off outside the established CVE-detection model — the same situation as the [JCC Erratum](#no-cve--jump-conditional-code-jcc-erratum) below, but for AMD.
|
||||
|
||||
## No CVE — Jump Conditional Code (JCC) Erratum
|
||||
|
||||
- **Issue:** [#329](https://github.com/speed47/spectre-meltdown-checker/issues/329)
|
||||
- **Intel whitepaper:** [Mitigations for Jump Conditional Code Erratum](https://www.intel.com/content/dam/support/us/en/documents/processors/mitigations-jump-conditional-code-erratum.pdf)
|
||||
- **Affected CPUs:** Intel 6th through 10th generation Core and Xeon processors (Skylake through Cascade Lake)
|
||||
|
||||
A microarchitectural correctness erratum where a conditional jump instruction that straddles or ends at a 64-byte instruction fetch boundary can corrupt the branch predictor state, potentially causing incorrect execution. Intel addressed this in a November 2019 microcode update. Compilers and assemblers (GCC, LLVM, binutils) also introduced alignment options (`-mbranch-alignment`, `-x86-branches-within-32B-boundaries`) to pad jump instructions away from boundary conditions, preserving performance on CPUs with updated microcode.
|
||||
|
||||
**Why out of scope:** The JCC erratum is a microarchitectural correctness bug, not a transient or speculative execution side-channel vulnerability. No CVE was ever assigned. Red Hat noted that privilege escalation "has not been ruled out" but made no definitive security finding, and no exploit has been demonstrated. There is no Linux sysfs entry, no CPUID bit, and no MSR flag exposing the mitigation status. The microcode fix introduces no detectable hardware indicator, so checking for it would require maintaining a per-CPU-stepping minimum microcode version table (the design principle 3 exception) — costly to maintain without a CVE anchor or confirmed exploitability to justify the ongoing work. The kernel compiler mitigation is a build-time-only change (instruction alignment) with no observable runtime state.
|
||||
|
||||
+1114
-291
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user