@@ -273,7 +273,11 @@ export async function injectSystemCertificate(
273273 mkdir -p -m 700 /data/local/tmp/htk-ca-copy
274274
275275 # Copy out the existing certificates
276- cp /system/etc/security/cacerts/* /data/local/tmp/htk-ca-copy/
276+ if [ -d "/apex/com.android.conscrypt/cacerts" ]; then
277+ cp /apex/com.android.conscrypt/cacerts/* /data/local/tmp/htk-ca-copy/
278+ else
279+ cp /system/etc/security/cacerts/* /data/local/tmp/htk-ca-copy/
280+ fi
277281
278282 # Create the in-memory mount on top of the system certs folder
279283 mount -t tmpfs tmpfs /system/etc/security/cacerts
@@ -289,6 +293,50 @@ export async function injectSystemCertificate(
289293 chmod 644 /system/etc/security/cacerts/*
290294 chcon u:object_r:system_file:s0 /system/etc/security/cacerts/*
291295
296+ echo 'System cacerts setup completed'
297+
298+ # Deal with the APEX overrides in Android 14+, which need injecting into each namespace:
299+ if [ -d "/apex/com.android.conscrypt/cacerts" ]; then
300+ echo 'Injecting certificates into APEX cacerts'
301+
302+ # When the APEX manages cacerts, we need to mount them at that path too. We can't do
303+ # this globally as APEX mounts are namespaced per process, so we need to inject a
304+ # bind mount for this directory into every mount namespace.
305+
306+ # First we get the Zygote process(es), which launch each app
307+ ZYGOTE_PID=$(pidof zygote || true)
308+ ZYGOTE64_PID=$(pidof zygote64 || true)
309+ # N.b. some devices appear to have both!
310+
311+ # Apps inherit the Zygote's mounts at startup, so we inject here to ensure all newly
312+ # started apps will see these certs straight away:
313+ for Z_PID in "$ZYGOTE_PID $ZYGOTE64_PID"; do
314+ # We use 'echo' below to trim spaces
315+ nsenter --mount=/proc/$(echo $Z_PID)/ns/mnt -- \
316+ /bin/mount --bind /system/etc/security/cacerts /apex/com.android.conscrypt/cacerts
317+ done
318+
319+ echo 'Zygote APEX certificates remounted'
320+
321+ # Then we inject the mount into all already running apps, so they see these certs immediately.
322+
323+ # Get the PID of every process whose parent is one of the Zygotes:
324+ APP_PIDS=$(
325+ echo "$ZYGOTE_PID $ZYGOTE64_PID" | \
326+ xargs -n1 ps -o 'PID' -P | \
327+ grep -v PID
328+ )
329+
330+ # Inject into the mount namespace of each of those apps:
331+ for PID in $APP_PIDS; do
332+ nsenter --mount=/proc/$PID/ns/mnt -- \
333+ /bin/mount --bind /system/etc/security/cacerts /apex/com.android.conscrypt/cacerts &
334+ done
335+ wait # Launched in parallel - wait for completion here
336+
337+ echo "APEX certificates remounted for $(echo $APP_PIDS | wc -w) apps"
338+ fi
339+
292340 # Delete the temp cert directory & this script itself
293341 rm -r /data/local/tmp/htk-ca-copy
294342 rm ${ injectionScriptPath }
0 commit comments