What changed, and why it matters
This commit updates Electrum's Android build setup so the app works on newer Android devices that require 16 KB memory page alignment. It swaps the Android NDK to a special canary/CI build, adds a small patch to the barcode scanner library, and adds a helper script to apply patches. There is no direct evidence this fixes an active security vulnerability; it appears to be a compatibility/build hardening change.
Treat as a routine build compatibility/hardening update. Review the NDK CI download script for robustness (error handling, TLS verification, checksum validation) before relying on it in release builds. Monitor Google/Android official guidance for stable NDK support for 16 KB alignment and migrate away from the CI/canary NDK once a stable release is available.
Security signals we found
Build-time change only
No runtime code changes in wallet/cryptography
No mention of CVE, vulnerability, bug bounty, or security advisory in commit message
Change aligns with Android 16 KB page size compatibility (future Android requirement)
NDK source switched from stable Google release to CI/canary build with SHA256 still checked
Evidence from the diff
The commit modifies the Android Dockerfile to download a 16 KB page-aligned Android NDK r23 canary build from Google’s CI instead of the stable release, updates the python-for-android checkout to a branch named electrum_20240930_android_16kb_page_alignment, adds a patch that links the zxing-cpp Android barcode library with -Wl,-z,max-page-size=16384, and introduces contrib/android/dl-ndk-ci.sh plus an apply_patch helper in contrib/build_tools_util.sh. The changes are build-time only and target Android 16 KB ELF alignment requirements.
Changed components
contrib/android/Dockerfilecontrib/android/dl-ndk-ci.shcontrib/android/barcode_16kb.patchcontrib/android/make_barcode_scanner.shcontrib/build_tools_util.shInspect captured patch +65 / −11
diff --git a/contrib/android/Dockerfile b/contrib/android/Dockerfile
index 59b44a8..d1f1c21 100644
--- a/contrib/android/Dockerfile
+++ b/contrib/android/Dockerfile
@@ -25,30 +25,48 @@ ENV LANG="en_US.UTF-8" \
RUN apt -y update -qq \
&& apt -y install -qq --no-install-recommends --allow-downgrades \
curl \
+ wget \
unzip \
ca-certificates \
+ python3 \
&& apt -y autoremove
ENV ANDROID_NDK_HOME="${ANDROID_HOME}/android-ndk"
-ENV ANDROID_NDK_VERSION="23b"
-ENV ANDROID_NDK_HASH="c6e97f9c8cfe5b7be0a9e6c15af8e7a179475b7ded23e2d1c1fa0945d6fb4382"
+#ENV ANDROID_NDK_VERSION="23b"
+#ENV ANDROID_NDK_HASH="c6e97f9c8cfe5b7be0a9e6c15af8e7a179475b7ded23e2d1c1fa0945d6fb4382"
+#ENV ANDROID_NDK_VERSION="27d"
+#ENV ANDROID_NDK_HASH="601246087a682d1944e1e16dd85bc6e49560fe8b6d61255be2829178c8ed15d9"
+ENV ANDROID_NDK_VERSION="23d-canary"
+ENV ANDROID_NDK_HASH="6944ffc20ab018ff4ef6a403048d0a99d50a0630c3eae690c8f803c452f46f3e"
ENV ANDROID_NDK_HOME_V="${ANDROID_NDK_HOME}-r${ANDROID_NDK_VERSION}"
# get the latest version from https://developer.android.com/ndk/downloads/index.html
ENV ANDROID_NDK_ARCHIVE="android-ndk-r${ANDROID_NDK_VERSION}-linux.zip"
ENV ANDROID_NDK_DL_URL="https://dl.google.com/android/repository/${ANDROID_NDK_ARCHIVE}"
+# below disabled in favor of CI build download
+
# download and install Android NDK
-RUN curl --location --progress-bar \
- "${ANDROID_NDK_DL_URL}" \
- --output "${ANDROID_NDK_ARCHIVE}" \
- && echo "${ANDROID_NDK_HASH} ${ANDROID_NDK_ARCHIVE}" | sha256sum -c - \
+#RUN curl --location --progress-bar \
+# "${ANDROID_NDK_DL_URL}" \
+# --output "${ANDROID_NDK_ARCHIVE}" \
+# && echo "${ANDROID_NDK_HASH} ${ANDROID_NDK_ARCHIVE}" | sha256sum -c - \
+# && mkdir --parents "${ANDROID_NDK_HOME_V}" \
+# && unzip -q "${ANDROID_NDK_ARCHIVE}" -d "${ANDROID_HOME}" \
+# && ln -sfn "${ANDROID_NDK_HOME_V}" "${ANDROID_NDK_HOME}" \
+# && rm -rf "${ANDROID_NDK_ARCHIVE}"
+
+# temporary build using NDK from CI
+ENV CI_REV="12186248"
+ENV CI_NDK_FILE="android-ndk-${CI_REV}-linux-x86_64.zip"
+COPY contrib/android/dl-ndk-ci.sh /tmp/
+RUN /tmp/dl-ndk-ci.sh https://ci.android.com/builds/submitted/${CI_REV}/linux/latest/${CI_NDK_FILE} \
+ && echo "${ANDROID_NDK_HASH} android-ndk-ci-linux-x86_64.zip" | sha256sum -c - \
&& mkdir --parents "${ANDROID_NDK_HOME_V}" \
- && unzip -q "${ANDROID_NDK_ARCHIVE}" -d "${ANDROID_HOME}" \
+ && unzip -q "android-ndk-ci-linux-x86_64.zip" -d "${ANDROID_HOME}" \
&& ln -sfn "${ANDROID_NDK_HOME_V}" "${ANDROID_NDK_HOME}" \
- && rm -rf "${ANDROID_NDK_ARCHIVE}"
-
+ && rm -rf "android-ndk-ci-linux-x86_64.zip"
ENV ANDROID_SDK_HOME="${ANDROID_HOME}/android-sdk"
@@ -190,8 +208,8 @@ RUN cd /opt \
&& /opt/venv/bin/python3 -m pip install --no-build-isolation --no-dependencies -e .
# install python-for-android
-ENV P4A_CHECKOUT_COMMIT="32a05cdedd41f0f569e9126fdfce23069c36fd9a"
-# ^ from branch electrum_20240930 (note: careful with force-pushing! see #8162)
+ENV P4A_CHECKOUT_COMMIT="003451604321deb1f10d879b63450ec76db4a758"
+# ^ from branch electrum_20240930_android_16kb_page_alignment (note: careful with force-pushing! see #8162)
RUN cd /opt \
&& git clone https://github.com/spesmilo/python-for-android \
&& cd python-for-android \
diff --git a/contrib/android/barcode_16kb.patch b/contrib/android/barcode_16kb.patch
new file mode 100644
index 0000000..bb9ea20
--- /dev/null
+++ b/contrib/android/barcode_16kb.patch
@@ -0,0 +1,9 @@
+diff --git a/wrappers/aar/zxingcpp/src/main/cpp/CMakeLists.txt b/wrappers/aar/zxingcpp/src/main/cpp/CMakeLists.txt
+index 11332e48..78f514f1 100644
+--- a/wrappers/aar/zxingcpp/src/main/cpp/CMakeLists.txt
++++ b/wrappers/aar/zxingcpp/src/main/cpp/CMakeLists.txt
+@@ -13,3 +13,4 @@ add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../core ZXing EXCLUD
+ add_library(zxingcpp_android SHARED ZxingCpp.cpp)
+
+ target_link_libraries(zxingcpp_android PRIVATE ZXing::ZXing jnigraphics)
++target_link_options(zxingcpp_android PRIVATE "-Wl,-z,max-page-size=16384")
diff --git a/contrib/android/dl-ndk-ci.sh b/contrib/android/dl-ndk-ci.sh
new file mode 100755
index 0000000..41b1922
--- /dev/null
+++ b/contrib/android/dl-ndk-ci.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+if [ -z "$1" ]; then
+ echo "missing url"
+ exit 1
+fi
+echo $1
+
+curl $1 | grep "var JSVariables" | python3 -c "import sys; line=sys.stdin.read(); line=line[line.find('{'):-2]; import json; j=json.loads(line); print(j['artifactUrl'])" | wget -i - -O android-ndk-ci-linux-x86_64.zip
diff --git a/contrib/android/make_barcode_scanner.sh b/contrib/android/make_barcode_scanner.sh
index 31f7f83..7c3f70e 100755
--- a/contrib/android/make_barcode_scanner.sh
+++ b/contrib/android/make_barcode_scanner.sh
@@ -65,6 +65,7 @@ else
info "Building zxing-cpp for $ZXING_CPP_BUILD_ID..."
ZXING_CPP_DIR="$BUILDDIR/zxing-cpp"
clone_or_update_repo "$ZXING_CPP_REPO" "$ZXING_CPP_COMMIT_HASH" "$ZXING_CPP_DIR"
+ apply_patch "${CONTRIB_ANDROID}/barcode_16kb.patch" "$ZXING_CPP_DIR"
cd "$ZXING_CPP_DIR/wrappers/aar"
chmod +x gradlew
diff --git a/contrib/build_tools_util.sh b/contrib/build_tools_util.sh
index aab00ef..0ca8d42 100755
--- a/contrib/build_tools_util.sh
+++ b/contrib/build_tools_util.sh
@@ -72,6 +72,24 @@ clone_or_update_repo() {
fi
}
+apply_patch() {
+ local patch=$1
+ local path=$2
+
+ if [ -z "$patch" ] || [ -z "$path" ]; then
+ fail "apply_patch: invalid arguments: patch='$patch', path='$path'"
+ fi
+
+ if [ -d "$path" ]; then
+ info "Patching: $patch"
+ cd "$path"
+ patch -p1 <"$patch"
+ cd -
+ else
+ fail "apply_patch: path='$path' not found"
+ fi
+}
+
# https://github.com/travis-ci/travis-build/blob/master/lib/travis/build/templates/header.sh
function retry() {
local result=0
Why this scored 19/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.