Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
46be97e
Add optional source-built pdx235 vold timeout module
Oct 21, 2026
b17ca23
fix(vold): preserve selection fingerprints when module is off
0cwa Oct 21, 2026
ee47c45
test(vold): cover disabled fingerprint stability and selected digest
0cwa Oct 21, 2026
f72851c
fix(vold): verify actual SELinux xattr and preserve exact system-entr…
0cwa Oct 21, 2026
0f1c4ce
test(vold): exercise image injection metadata and SELinux preservation
0cwa Oct 21, 2026
8a72093
fix(vold): validate Lineage build identity in product partition
0cwa Oct 21, 2026
cf3df83
test(vold): require exact product-partition Lineage properties
0cwa Oct 21, 2026
7d37f7a
feat(vold): require independently approved SHA before published repla…
0cwa Oct 21, 2026
55d4f4b
policy(vold): leave publication digest unapproved until real validation
0cwa Oct 21, 2026
65fbb91
fix(vold): bind OTA source identity and approved hash before selection
0cwa Oct 21, 2026
5695490
fix(vold): reverify approved artifact at injection time
0cwa Oct 21, 2026
7e69e13
fix(vold): close artifact verifier shell condition
0cwa Oct 21, 2026
345c0f5
fix(vold): fingerprint vetted verifier code for selected module
0cwa Oct 21, 2026
05f5875
fix(vold): hash publication verifier and gate the selected source
0cwa Oct 21, 2026
602fd35
test(vold): cover published verifier SHA in module selection
0cwa Oct 21, 2026
3af29b3
test(vold): reject unapproved publication and mismatched source OTA
0cwa Oct 21, 2026
9f029c0
policy(vold): reserve digest-pinned staging release coordinates
0cwa Oct 21, 2026
b14e77c
feat(vold): fetch only cryptographically pinned staging release artif…
0cwa Oct 21, 2026
0e7398d
fix(vold): import standalone artifact verifier without path side effects
0cwa Oct 21, 2026
e67b3e5
feat(vold): load explicit scoped schedule selector; reject GrapheneOS
0cwa Oct 21, 2026
f96dac1
policy(vold): keep scheduled production disabled pending pinned binar…
0cwa Oct 21, 2026
1f6a7c1
policy(vold): keep scheduled production disabled pending pinned binar…
0cwa Oct 21, 2026
20168ba
feat(vold): wire approved artifact through scheduled and manual Linea…
0cwa Oct 21, 2026
440ec87
feat(vold): fetch independently pinned artifact in reusable build; sc…
0cwa Oct 21, 2026
8d0d806
test(vold): enforce digest-pinned staging asset download and fail-clo…
0cwa Oct 21, 2026
52a1790
test(vold): scheduled defaults and selector forwarding stay explicit
0cwa Oct 21, 2026
1bd0eb6
test(vold): reject tampered GrapheneOS scheduled selection
0cwa Oct 21, 2026
b8fd488
docs(vold): document product properties and artifact qualification to…
0cwa Oct 21, 2026
43a2cbf
docs(vold): clarify release staging, qualification and disabled default
0cwa Oct 21, 2026
e69628d
test(vold): enforce fail-closed workflow transport and GrapheneOS iso…
0cwa Oct 21, 2026
55bdbac
ci(vold): verify workflow routing and independent staging approval gates
0cwa Oct 21, 2026
a588d26
merge(main): preserve GrapheneOS isolation regressions alongside vold…
0cwa Oct 21, 2026
36344dd
merge(main): preserve GrapheneOS isolation regressions alongside vold…
0cwa Oct 21, 2026
0ce2519
merge(main): retain upstream SELinux and GrapheneOS isolation fixes
0cwa Oct 21, 2026
406fe52
merge(main): retain upstream SELinux and GrapheneOS isolation fixes
0cwa Oct 21, 2026
bb94fe3
merge(main): retain upstream SELinux and GrapheneOS isolation fixes
0cwa Oct 21, 2026
863e089
merge(main): preserve GrapheneOS protection in shared build and schedule
0cwa Oct 21, 2026
c78f166
merge(main): preserve GrapheneOS protection in shared build and schedule
0cwa Oct 21, 2026
6101f41
merge(main): retain GrapheneOS fsck isolation and SELinux fixes for v…
0cwa Oct 21, 2026
fd44a2a
fix(vold): require clean complete source checkouts and reject linked …
0cwa Oct 21, 2026
04b52c0
test(vold): reject dirty or symlinked source dependencies
0cwa Oct 21, 2026
c43c826
fix(vold): use standalone comment to preserve strict TOML boolean par…
0cwa Oct 21, 2026
3f9f2c1
fix(vold): use standalone comment to preserve strict TOML boolean par…
0cwa Oct 21, 2026
cb27737
test(vold): prove Graphene schedule failure comes from scope guard
0cwa Oct 21, 2026
a570c39
feat(vold): enforce byte-exact unmodified reproduction against OTA bi…
0cwa Oct 21, 2026
1b2f1b3
feat(vold): build unchanged baseline first, require byte-identical OT…
0cwa Oct 21, 2026
e334e0e
feat(vold): resolve only immutable historical OTA from official Linea…
0cwa Oct 21, 2026
cf7bc22
fix(vold): canonicalize ELF dependencies for reproducibility receipts
0cwa Oct 21, 2026
592dbca
test(vold): prove identical-baseline gate and rejection of ABI-only m…
0cwa Oct 21, 2026
14ba13f
feat(vold): authenticate official OTA and extract unmodified referenc…
0cwa Oct 21, 2026
b97a9ea
ci(vold): add opt-in large-runner unmodified byte-exact reproduction …
0cwa Oct 21, 2026
92f29cf
fix(vold): use portable Info-ZIP certificate extraction
0cwa Oct 21, 2026
eed70cc
fix(vold): fail cleanly on invalid baseline input and ELF
0cwa Oct 21, 2026
610026b
test(vold): surface exact failed scope-check diagnostic
0cwa Oct 21, 2026
6e09144
test(vold): accept earlier typed-config denial when Graphene emits no…
0cwa Oct 21, 2026
e01e85b
docs(vold): require CI byte-exact unmodified reproduction before time…
0cwa Oct 21, 2026
58bb448
docs(vold): make byte-identical baseline the first release gate
0cwa Oct 21, 2026
4fafee8
fix(vold): handle omitted optional selector under strict shell mode
0cwa Oct 21, 2026
1ffe107
test(vold): enforce nonpublishing authentic baseline CI before any patch
0cwa Oct 21, 2026
c357397
test(vold): add independent read-only device module health check
0cwa Oct 21, 2026
8ffd758
fix(vold): register dedicated pdx235 module health check
0cwa Oct 21, 2026
e26ab22
test(vold): audit disabled-by-default and never assert runtime functi…
0cwa Oct 21, 2026
15a0a83
policy(vold): prohibit offline metadata injection into official OTA r…
0cwa Oct 21, 2026
643e139
fix(vold): normalize isolated scratch path before baseline cleanup
0cwa Oct 21, 2026
997d542
docs(vold): CI baseline evidence is not a substitute for later byte r…
0cwa Oct 21, 2026
1a2a3f8
fix(vold): resolve historical OTA with proven HTTPS curl provider path
0cwa Oct 21, 2026
5a17181
lock(vold): pin authenticated 20261016 OTA source SHA and official ar…
0cwa Oct 22, 2026
6ad2dae
feat(vold): allow SHA-pinned authenticated archive when official API …
0cwa Oct 22, 2026
57c4071
test(vold): prove official SHA-pinned archive fallback rejects API di…
0cwa Oct 22, 2026
37ec07a
docs(vold): ground historical source SHA pin in verified ModOS runs
0cwa Oct 22, 2026
dc92f36
ci(vold): label the source resolver's immutable archive fallback
0cwa Oct 22, 2026
5cbcf54
refactor(vold): keep baseline reproduction independent of timeout pat…
0cwa Oct 22, 2026
4480429
policy(vold): require exact independently pinned OTA digest in baseli…
0cwa Oct 22, 2026
0038a55
test(vold): align fixtures to independently pinned source OTA SHA
0cwa Oct 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/schedules/grapheneos-shiba.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ MAGISK_PREINIT = "sda10"
# These modules are only supported on LineageOS pdx235, not GrapheneOS.
'ADDITIONALS[EXFATPROGS_FSCK]' = false
'ADDITIONALS[FSCK_SYSFS_SEPOLICY]' = false
# Vold remains disabled until an independently qualified binary is pinned.
'ADDITIONALS[LINEAGE_VOLD_EXFAT_TIMEOUT]' = false
FORCE_UPDATE = false
2 changes: 2 additions & 0 deletions .github/schedules/lineageos-pdx235.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ MAGISK_PREINIT = "sda47"
'ADDITIONALS[MAS_COMPATIBLE_SEPOLICY]' = true
'ADDITIONALS[EXFATPROGS_FSCK]' = true
'ADDITIONALS[FSCK_SYSFS_SEPOLICY]' = true
# Vold remains disabled until an independently qualified binary is pinned.
'ADDITIONALS[LINEAGE_VOLD_EXFAT_TIMEOUT]' = false
FORCE_UPDATE = false
22 changes: 22 additions & 0 deletions .github/workflows/build-rom.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ on:
required: false
type: boolean
default: false
lineage-vold-exfat-timeout:
description: Replace pdx235 vold with an independently qualified and SHA-pinned source-built binary
required: false
type: boolean
default: false
update-channel:
required: true
type: string
Expand Down Expand Up @@ -152,6 +157,7 @@ env:
ADDITIONALS_SHIZUKU: ${{ inputs.shizuku }}
ADDITIONALS_EXFATPROGS_FSCK: ${{ inputs.exfatprogs-fsck }}
ADDITIONALS_FSCK_SYSFS_SEPOLICY: ${{ inputs.fsck-sysfs-sepolicy }}
ADDITIONALS_LINEAGE_VOLD_EXFAT_TIMEOUT: ${{ inputs.lineage-vold-exfat-timeout }}
ADDITIONALS_BOOT_ANIMATION: ${{ inputs.boot-animation }}

# Publishing inherits the caller job's permission ceiling. A reusable
Expand All @@ -178,6 +184,11 @@ jobs:
DEVICE_CANDIDATE_RECIPIENT_BASE64: ${{ inputs.device-candidate-recipient-base64 }}
PUBLISH_REQUEST: ${{ inputs.publish }}
run: |
if [[ "${ADDITIONALS_LINEAGE_VOLD_EXFAT_TIMEOUT:-false}" == true ]] &&
[[ "${ROM_FAMILY}" != lineageos || "${DEVICE_NAME}" != pdx235 ]]; then
echo '::error::Source-built vold is supported only for LineageOS pdx235'
exit 1
fi
if [[ "${EXPORT_DEVICE_CANDIDATE}" == true ]]; then
[[ ("${DEVELOPMENT_PROFILE}" == care-map-pdx235 ||
"${DEVELOPMENT_PROFILE}" == care-map-pdx235-lineage24) &&
Expand Down Expand Up @@ -229,6 +240,17 @@ jobs:
fetch-depth: 0
persist-credentials: ${{ inputs.publish && inputs.release-type != 'build-only' }}

- name: Download approved source-built vold artifact
if: inputs.lineage-vold-exfat-timeout
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
python3 src/ci/fetch_lineage_vold_artifact.py --output-dir "${RUNNER_TEMP}/lineage-vold-artifact"
echo "PIXENEOS_VOLD_ARTIFACT_DIR=${RUNNER_TEMP}/lineage-vold-artifact" >> "${GITHUB_ENV}"
echo "PIXENEOS_VOLD_BASE_BUILD_ID=lineage-24.0-20261016-nightly-pdx235-signed" >> "${GITHUB_ENV}"

- name: Build and verify exfatprogs corresponding-source bundle
if: inputs.exfatprogs-fsck && inputs.publish && inputs.release-type != 'build-only' && inputs.rom-family == 'lineageos' && inputs.device-id == 'pdx235'
shell: bash
Expand Down
102 changes: 102 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,15 @@ jobs:
- name: Test exfatprogs image metadata diagnostics
run: python3 tests/exfat_adapter_metadata_test.py

- name: Test source-built Vold module contract
run: python3 tests/lineage_vold_contract_test.py

- name: Test byte-exact unmodified Vold reproduction contract
run: python3 tests/lineage_vold_baseline_test.py

- name: Test source-built Vold workflow routing
run: python3 tests/lineage_vold_workflow_contract_test.py

- name: Test pdx235 Custota metadata preparation
run: bash tests/pdx235_custota_metadata_test.sh

Expand Down Expand Up @@ -171,3 +180,96 @@ jobs:
signing-mode: disposable
release-type: build-only
publish: false

# Manual opt-in on the owned review branch only. No publishing keys, release
# credentials, rootless/Magisk patching, or binary-injection paths are used.
# The runner must have a large isolated scratch volume and Android build deps.
lineage_vold_exact_baseline:
if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && github.head_ref == 'codex/lineage-vold-exfat-timeout-pr' && vars.MODOS_VOLD_BASELINE_RUNNER_READY == 'true' && vars.MODOS_LINEAGE_LARGE_SCRATCH != '' }}
runs-on: [self-hosted, linux, x64, modos-lineage-large]
timeout-minutes: 360
permissions:
contents: read
concurrency:
group: lineage-vold-unmodified-baseline
cancel-in-progress: false
env:
MODOS_LINEAGE_LARGE_SCRATCH: ${{ vars.MODOS_LINEAGE_LARGE_SCRATCH }}
steps:
- name: Checkout exact PR source without retained credentials
uses: actions/checkout@v7
with:
persist-credentials: false
fetch-depth: 0

- name: Check isolated build host and initialize scratch workspace
shell: bash
run: |
set -euo pipefail
for tool in repo avbroot unzip debugfs curl openssl python3 git; do
command -v "${tool}" >/dev/null || { echo "::error::Missing host tool: ${tool}"; exit 1; }
done
scratch="${MODOS_LINEAGE_LARGE_SCRATCH}"
[[ "${scratch}" == /* && -d "${scratch}" && ! -L "${scratch}" ]] ||
{ echo "::error::A real absolute large scratch directory is required"; exit 1; }
scratch="$(realpath -e -- "${scratch}")"
echo "MODOS_LINEAGE_LARGE_SCRATCH=${scratch}" >> "${GITHUB_ENV}"
free="$(df -PB1 -- "${scratch}" | awk 'END {print $4}')"
(( free >= 220000000000 )) ||
{ echo "::error::Baseline source build needs at least 220GB available"; exit 1; }
work="$(mktemp -d -- "${scratch}/modos-vold-baseline.XXXXXXXX")"
echo "VOLD_BASELINE_WORK=${work}" >> "${GITHUB_ENV}"

- name: Resolve exact authenticated 2026-10-16 OTA or reviewed archive
id: official
shell: bash
run: python3 src/ci/resolve_lineage_vold_ota.py --output "${GITHUB_OUTPUT}"

- name: Download, authenticate and extract original OTA vold
shell: bash
env:
OTA_URL: ${{ steps.official.outputs.ota_url }}
OTA_SHA256: ${{ steps.official.outputs.ota_sha256 }}
run: |
set -euo pipefail
[[ "${OTA_SHA256}" =~ ^[0-9a-f]{64}$ ]] || exit 1
curl --fail --location --retry 3 --proto '=https' --proto-redir '=https' \
--output "${VOLD_BASELINE_WORK}/source.zip" "${OTA_URL}"
bash src/ci/prepare_lineage_vold_reference.sh \
"${VOLD_BASELINE_WORK}/source.zip" "${VOLD_BASELINE_WORK}/reference" "${OTA_SHA256}"

- name: Sync full immutable LineageOS source manifest
shell: bash
run: |
set -euo pipefail
python3 src/ci/build_lineage_vold.py sync \
--source-root "${VOLD_BASELINE_WORK}/source" --jobs 4

- name: Reproduce unmodified vold and check byte-exact OTA identity
shell: bash
env:
OTA_SHA256: ${{ steps.official.outputs.ota_sha256 }}
run: |
set -euo pipefail
python3 src/ci/build_lineage_vold.py baseline \
--source-root "${VOLD_BASELINE_WORK}/source" \
--reference-vold "${VOLD_BASELINE_WORK}/reference/reference-vold" \
--source-ota-sha256 "${OTA_SHA256}" \
--output-dir "${VOLD_BASELINE_WORK}/baseline" --jobs 4

- name: Preserve comparison receipt only (no signed or patched OTA)
if: always() && env.VOLD_BASELINE_WORK != ''
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: lineage-pdx235-original-vold-baseline-report
path: ${{ env.VOLD_BASELINE_WORK }}/baseline/baseline-report.json
if-no-files-found: warn
retention-days: 14

- name: Erase isolated source and extracted images
if: always() && env.VOLD_BASELINE_WORK != ''
shell: bash
run: |
set -euo pipefail
[[ "${VOLD_BASELINE_WORK}" == "${MODOS_LINEAGE_LARGE_SCRATCH}"/modos-vold-baseline.* ]] || exit 1
rm -rf -- "${VOLD_BASELINE_WORK}"
18 changes: 18 additions & 0 deletions .github/workflows/release-lineage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ on:
required: false
type: boolean
default: false
lineage-vold-exfat-timeout:
description: Use the independently qualified, hash-pinned pdx235 vold (requires approved staging artifact)
required: false
type: boolean
default: false
disable-system-updater:
description: Remove the stock ROM updater app (use with Custota)
required: false
Expand Down Expand Up @@ -145,6 +150,7 @@ jobs:
compatible_sepolicy_patching: ${{ steps.definition.outputs.compatible_sepolicy_patching }}
exfatprogs_fsck: ${{ steps.definition.outputs.exfatprogs_fsck }}
fsck_sysfs_sepolicy: ${{ steps.definition.outputs.fsck_sysfs_sepolicy }}
lineage_vold_exfat_timeout: ${{ steps.definition.outputs.lineage_vold_exfat_timeout }}
should_build: ${{ steps.existing.outputs.should_build }}
steps:
- name: Checkout code
Expand Down Expand Up @@ -179,6 +185,16 @@ jobs:
shell: bash
run: python3 src/ci/build_exfatprogs_source_bundle.py --output-dir "${RUNNER_TEMP}/exfatprogs-source" --check-deterministic

- name: Download approved vold artifact for scheduled preflight
if: steps.definition.outputs.lineage_vold_exfat_timeout == 'true'
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
python3 src/ci/fetch_lineage_vold_artifact.py --output-dir "${RUNNER_TEMP}/lineage-vold-artifact"
echo "PIXENEOS_VOLD_ARTIFACT_DIR=${RUNNER_TEMP}/lineage-vold-artifact" >> "${GITHUB_ENV}"
echo "PIXENEOS_VOLD_BASE_BUILD_ID=lineage-24.0-20261016-nightly-pdx235-signed" >> "${GITHUB_ENV}"

- name: Check for an already-published matching OTA pair
id: existing
shell: bash
Expand Down Expand Up @@ -212,6 +228,7 @@ jobs:
compatible-sepolicy-patching: ${{ needs.schedule_config.outputs.compatible_sepolicy_patching == 'true' }}
exfatprogs-fsck: ${{ needs.schedule_config.outputs.exfatprogs_fsck == 'true' }}
fsck-sysfs-sepolicy: ${{ needs.schedule_config.outputs.fsck_sysfs_sepolicy == 'true' }}
lineage-vold-exfat-timeout: ${{ needs.schedule_config.outputs.lineage_vold_exfat_timeout == 'true' }}
allow-unauthorized-adb: false
boot-animation: ${{ needs.schedule_config.outputs.boot_animation == 'true' }}
release-type: default
Expand All @@ -236,6 +253,7 @@ jobs:
shizuku: ${{ inputs.shizuku }}
exfatprogs-fsck: ${{ inputs.exfatprogs-fsck }}
fsck-sysfs-sepolicy: ${{ inputs.fsck-sysfs-sepolicy }}
lineage-vold-exfat-timeout: ${{ inputs.lineage-vold-exfat-timeout }}
disable-system-updater: ${{ inputs.disable-system-updater }}
boot-animation: ${{ inputs.boot-animation }}
export-device-candidate: ${{ inputs.export-device-candidate }}
Expand Down
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,29 @@ any new OTA assets. Local-unpublished builds do not require source publication.
The recorded signed APT metadata is audit provenance; builds verify the lock's
package URL, size, and SHA-256, but do not repeat the APT signature check.

### Source-built vold timeout for LineageOS pdx235

The experimental `lineage-vold-exfat-timeout` module aims to raise only the
exFAT fsck timeout from 45 to 120 seconds. **It is default-off and has not
passed a real unmodified-binary reproduction test.** Before compiling a patched
`vold`, the dedicated, nonpublishing large-runner CI must build **unmodified
`vold`** from the locked 1,243-project LineageOS 2026-10-16 manifest and
demonstrate a *byte-for-byte match* against the executable extracted from the
publisher-authenticated official OTA. A matching ABI or source revision is
not sufficient. A mismatch blocks all subsequent patched builds.

After that baseline gate passes, the separate `build` command requires the
baseline report, exact unmodified binary and OTA reference before applying
the isolated exFAT timeout patch. System/product identity, ELF dependencies,
root ownership, actual `vold_exec` metadata, and independently approved
binary SHA-256 are also checked prior to production use. Public scheduled
LineageOS and manual selectors remain **disabled**, and GrapheneOS is excluded.

See [`docs/lineage-vold-exfat-timeout.md`](docs/lineage-vold-exfat-timeout.md)
for the complete CI runner setup, baseline-first acceptance sequence,
provenance requirements and remaining device qualification gates. No vold OTA
has been authorized for force-publish.

### Custom boot animation (enabled by default)

All builds use the checked-in `custom/boot-animation/bootanimation.zip` by
Expand Down
Loading
Loading