Merge Magisk install zip into Magisk Manager

Distribute Magisk directly with Magisk Manager APK. The APK will
contain all required binaries and scripts for installation and
uninstallation. App versions will now align with Magisk releases.

Extra effort is spent to make the APK itself also a flashable zip that
can be used in custom recoveries, so those still prefer to install
Magisk with recoveries will not be affected with this change.

As a bonus, this makes the whole installation and uninstallation
process 100% offline. The existing Magisk Manager was not really
functional without an Internet connection, as the installation process
was highly tied to zips hosted on the server.

An additional bonus: since all binaries are now shipped as "native
libraries" of the APK, we can finally bump the target SDK version
higher than 28. The target SDK version was stuck at 28 for a long time
because newer SELinux restricts running executables from internal
storage. More details can be found here: https://github.com/termux/termux-app/issues/1072
The target SDK bump will be addressed in a future commit.

Co-authored with @vvb2060
This commit is contained in:
topjohnwu
2021-01-22 02:28:53 -08:00
parent 61d52991f1
commit ec8fffe61c
37 changed files with 784 additions and 1025 deletions

View File

@ -1,8 +1,7 @@
#!/system/bin/sh
###########################################################################################
#
#######################################################################################
# Magisk Boot Image Patcher
# by topjohnwu
#######################################################################################
#
# Usage: boot_patch.sh <bootimage>
#
@ -14,16 +13,17 @@
# File name Type Description
#
# boot_patch.sh script A script to patch boot image for Magisk.
# (this file) The script will use binaries and files in its same directory
# to complete the patching process
# util_functions.sh script A script which hosts all functions required for this script
# to work properly
# magiskinit binary The binary to replace /init; magisk binary embedded
# (this file) The script will use files in its same
# directory to complete the patching process
# util_functions.sh script A script which hosts all functions required
# for this script to work properly
# magiskinit binary The binary to replace /init
# magisk(32/64) binary The magisk binaries
# magiskboot binary A tool to manipulate boot images
# chromeos folder This folder includes all the utilities and keys to sign
# (optional) chromeos boot images. Currently only used for Pixel C
# chromeos folder This folder includes the utility and keys to sign
# (optional) chromeos boot images. Only used for Pixel C.
#
###########################################################################################
#######################################################################################
############
# Functions
@ -50,7 +50,7 @@ getdir() {
if [ -z $SOURCEDMODE ]; then
# Switch to the location of the script file
cd "`getdir "${BASH_SOURCE:-$0}"`"
cd "$(getdir "${BASH_SOURCE:-$0}")"
# Load utility functions
. ./util_functions.sh
# Check if 64-bit
@ -106,14 +106,14 @@ fi
case $((STATUS & 3)) in
0 ) # Stock boot
ui_print "- Stock boot image detected"
SHA1=`./magiskboot sha1 "$BOOTIMAGE" 2>/dev/null`
SHA1=$(./magiskboot sha1 "$BOOTIMAGE" 2>/dev/null)
cat $BOOTIMAGE > stock_boot.img
cp -af ramdisk.cpio ramdisk.cpio.orig 2>/dev/null
;;
1 ) # Magisk patched
ui_print "- Magisk patched boot image detected"
# Find SHA1 of stock boot image
[ -z $SHA1 ] && SHA1=`./magiskboot cpio ramdisk.cpio sha1 2>/dev/null`
[ -z $SHA1 ] && SHA1=$(./magiskboot cpio ramdisk.cpio sha1 2>/dev/null)
./magiskboot cpio ramdisk.cpio restore
cp -af ramdisk.cpio ramdisk.cpio.orig
;;

View File

@ -1,31 +1,26 @@
#MAGISK
############################################
#
# Magisk Flash Script (updater-script)
# by topjohnwu
#
############################################
##############
# Preparation
##############
COMMONDIR=$INSTALLER/common
APK=$COMMONDIR/magisk.apk
CHROMEDIR=$INSTALLER/chromeos
# Default permissions
umask 022
OUTFD=$2
ZIP=$3
APK="$3"
COMMONDIR=$INSTALLER/assets
CHROMEDIR=$INSTALLER/assets/chromeos
if [ ! -f $COMMONDIR/util_functions.sh ]; then
echo "! Unable to extract zip file!"
exit 1
fi
# Load utility fuctions
# Load utility functions
. $COMMONDIR/util_functions.sh
setup_flashable
@ -57,7 +52,11 @@ api_level_arch_detect
ui_print "- Device platform: $ARCH"
BINDIR=$INSTALLER/$ARCH32
BINDIR=$INSTALLER/lib/$ARCH32
[ ! -d "$BINDIR" ] && BINDIR=$INSTALLER/lib/armeabi-v7a
cd $BINDIR
for file in lib*.so; do mv "$file" "${file:3:${#file}-6}"; done
cd /
chmod -R 755 $CHROMEDIR $BINDIR
# Check if system root is installed and remove
@ -72,24 +71,22 @@ ui_print "- Constructing environment"
# Copy required files
rm -rf $MAGISKBIN/* 2>/dev/null
mkdir -p $MAGISKBIN 2>/dev/null
cp -af $BINDIR/. $COMMONDIR/. $CHROMEDIR $BBBIN $MAGISKBIN
cp -af $BINDIR/. $COMMONDIR/. $BBBIN $MAGISKBIN
chmod -R 755 $MAGISKBIN
# addon.d
if [ -d /system/addon.d ]; then
ui_print "- Adding addon.d survival script"
blockdev --setrw /dev/block/mapper/system$SLOT 2>/dev/null
mount -o rw,remount /system
mount -o rw,remount /system || mount -o rw,remount /
ADDOND=/system/addon.d/99-magisk.sh
cp -af $COMMONDIR/addon.d.sh $ADDOND
chmod 755 $ADDOND
fi
$BOOTMODE || recovery_actions
#####################
# Boot/DTBO Patching
#####################
##################
# Image Patching
##################
install_magisk

View File

@ -1,72 +1,75 @@
#MAGISK
############################################
#
# Magisk Uninstaller
# by topjohnwu
#
# Magisk Uninstaller (updater-script)
############################################
##############
# Preparation
##############
# This path should work in any cases
TMPDIR=/dev/tmp
INSTALLER=$TMPDIR/install
CHROMEDIR=$INSTALLER/chromeos
# Default permissions
umask 022
OUTFD=$2
ZIP=$3
APK="$3"
COMMONDIR=$INSTALLER/assets
CHROMEDIR=$INSTALLER/assets/chromeos
if [ ! -f $INSTALLER/util_functions.sh ]; then
if [ ! -f $COMMONDIR/util_functions.sh ]; then
echo "! Unable to extract zip file!"
exit 1
fi
# Load utility functions
. $INSTALLER/util_functions.sh
. $COMMONDIR/util_functions.sh
setup_flashable
print_title "Magisk Uninstaller"
############
# Detection
############
if echo $MAGISK_VER | grep -q '\.'; then
PRETTY_VER=$MAGISK_VER
else
PRETTY_VER="$MAGISK_VER($MAGISK_VER_CODE)"
fi
print_title "Magisk $PRETTY_VER Uninstaller"
is_mounted /data || mount /data || abort "! Unable to mount /data, please uninstall with Magisk Manager"
mount_partitions
check_data
$DATA_DE || abort "! Cannot access /data, please uninstall with Magisk Manager"
if ! $BOOTMODE; then
# Mounting stuffs in recovery (best effort)
mount_name metadata /metadata
mount_name "cache cac" /cache
mount_name persist /persist
fi
mount_partitions
get_flags
find_boot_image
[ -z $BOOTIMAGE ] && abort "! Unable to detect target image"
ui_print "- Target image: $BOOTIMAGE"
# Detect version and architecture
api_level_arch_detect
ui_print "- Device platform: $ARCH"
MAGISKBIN=$INSTALLER/$ARCH32
mv $CHROMEDIR $MAGISKBIN
chmod -R 755 $MAGISKBIN
check_data
$DATA_DE || abort "! Cannot access /data, please uninstall with Magisk Manager"
$BOOTMODE || recovery_actions
run_migrations
BINDIR=$INSTALLER/lib/$ARCH32
[ ! -d "$BINDIR" ] && BINDIR=$INSTALLER/lib/armeabi-v7a
cd $BINDIR
for file in lib*.so; do mv "$file" "${file:3:${#file}-6}"; done
cd /
chmod -R 755 $CHROMEDIR $BINDIR
cp -af $CHROMEDIR/. $BINDIR/chromeos
############
# Uninstall
############
get_flags
find_boot_image
[ -e $BOOTIMAGE ] || abort "! Unable to detect boot image"
ui_print "- Found target image: $BOOTIMAGE"
[ -z $DTBOIMAGE ] || ui_print "- Found dtbo image: $DTBOIMAGE"
cd $MAGISKBIN
cd $BINDIR
CHROMEOS=false
@ -108,14 +111,14 @@ case $((STATUS & 3)) in
1 ) # Magisk patched
ui_print "- Magisk patched image detected"
# Find SHA1 of stock boot image
SHA1=`./magiskboot cpio ramdisk.cpio sha1 2>/dev/null`
SHA1=$(./magiskboot cpio ramdisk.cpio sha1 2>/dev/null)
BACKUPDIR=/data/magisk_backup_$SHA1
if [ -d $BACKUPDIR ]; then
ui_print "- Restoring stock boot image"
flash_image $BACKUPDIR/boot.img.gz $BOOTIMAGE
for name in dtb dtbo dtbs; do
[ -f $BACKUPDIR/${name}.img.gz ] || continue
IMAGE=`find_block $name$SLOT`
IMAGE=$(find_block $name$SLOT)
[ -z $IMAGE ] && continue
ui_print "- Restoring stock $name image"
flash_image $BACKUPDIR/${name}.img.gz $IMAGE
@ -124,7 +127,7 @@ case $((STATUS & 3)) in
ui_print "! Boot image backup unavailable"
ui_print "- Restoring ramdisk with internal backup"
./magiskboot cpio ramdisk.cpio restore
if ! ./magiskboot cpio ramdisk.cpio "exists init.rc"; then
if ! ./magiskboot cpio ramdisk.cpio "exists init"; then
# A only system-as-root
rm -f ramdisk.cpio
fi
@ -148,10 +151,11 @@ rm -rf \
/data/adb/post-fs-data.d /data/adb/service.d /data/adb/modules* \
/data/unencrypted/magisk /metadata/magisk /persist/magisk /mnt/vendor/persist/magisk
if [ -f /system/addon.d/99-magisk.sh ]; then
ADDOND=/system/addon.d/99-magisk.sh
if [ -f $ADDOND ]; then
blockdev --setrw /dev/block/mapper/system$SLOT 2>/dev/null
mount -o rw,remount /system || mount -o rw,remount /
rm -f /system/addon.d/99-magisk.sh
rm -f $ADDOND
fi
cd /
@ -163,7 +167,10 @@ if $BOOTMODE; then
ui_print "********************************************"
(sleep 8; /system/bin/reboot)&
else
rm -rf /data/data/*magisk* /data/user*/*/*magisk* /data/app/*magisk* /data/app/*/*magisk*
ui_print "********************************************"
ui_print " Magisk Manager will not be uninstalled"
ui_print " Please uninstall it manually after reboot"
ui_print "********************************************"
recovery_cleanup
ui_print "- Done"
fi

View File

@ -1,37 +1,18 @@
#!/sbin/sh
X86_CNT=__X86_CNT__
extract_bb() {
touch "$BBBIN"
chmod 755 "$BBBIN"
dd if="$0" of="$BBBIN" bs=1024 skip=1 count=$X86_CNT
"$BBBIN" >/dev/null 2>&1 || dd if="$0" of="$BBBIN" bs=1024 skip=$(($X86_CNT + 1))
}
setup_bb() {
mkdir -p $TMPDIR 2>/dev/null
BBBIN=$TMPDIR/busybox
extract_bb
}
export BBBIN
case "$1" in
"extract"|"-x")
BBBIN=./busybox
[ -z "$2" ] || BBBIN="$2"
extract_bb
;;
"sh")
TMPDIR=.
setup_bb
shift
exec ./busybox sh -o standalone "$@"
;;
*)
TMPDIR=/dev/tmp
rm -rf $TMPDIR 2>/dev/null
setup_bb
export INSTALLER=$TMPDIR/install
$BBBIN mkdir -p $INSTALLER
$BBBIN unzip -o "$3" -d $INSTALLER >&2
exec $BBBIN sh -o standalone $INSTALLER/META-INF/com/google/android/updater-script "$@"
;;
esac
exit
TMPDIR=/dev/tmp
rm -rf $TMPDIR
mkdir -p $TMPDIR 2>/dev/null
export BBBIN=$TMPDIR/busybox
unzip -o "$3" lib/x86/libbusybox.so lib/armeabi-v7a/libbusybox.so -d $TMPDIR >&2
chmod -R 755 $TMPDIR/lib
mv -f $TMPDIR/lib/x86/libbusybox.so $BBBIN
$BBBIN >/dev/null 2>&1 || mv -f $TMPDIR/lib/armeabi-v7a/libbusybox.so $BBBIN
$BBBIN rm -rf $TMPDIR/lib
export INSTALLER=$TMPDIR/install
$BBBIN mkdir -p $INSTALLER
$BBBIN unzip -o "$3" "assets/*" "lib/*" "META-INF/com/google/*" -x "lib/*/libbusybox.so" -d $INSTALLER >&2
export ASH_STANDALONE=1
exec $BBBIN sh "$INSTALLER/META-INF/com/google/android/updater-script" "$@"

View File

@ -1,8 +1,5 @@
############################################
#
# Magisk General Utility Functions
# by topjohnwu
#
############################################
#MAGISK_VERSION_STUB
@ -33,7 +30,7 @@ grep_prop() {
shift
local FILES=$@
[ -z "$FILES" ] && FILES='/system/build.prop'
cat $FILES | dos2unix | sed -n "$REGEX" 2>/dev/null | head -n 1
cat $FILES 2>/dev/null | dos2unix | sed -n "$REGEX" | head -n 1
}
getvar() {
@ -42,11 +39,11 @@ getvar() {
local PROPPATH='/data/.magisk /cache/.magisk'
[ -n $MAGISKTMP ] && PROPPATH="$MAGISKTMP/config $PROPPATH"
VALUE=$(grep_prop $VARNAME $PROPPATH)
[ ! -z $VALUE ] && eval $VARNAME=\$VALUE
[ -n $VALUE ] && eval $VARNAME=\$VALUE
}
is_mounted() {
grep -q " `readlink -f $1` " /proc/mounts 2>/dev/null
grep -q " $(readlink -f $1) " /proc/mounts 2>/dev/null
return $?
}
@ -96,6 +93,7 @@ setup_flashable() {
fi
done
fi
recovery_actions
}
ensure_bb() {
@ -309,51 +307,57 @@ mount_apex() {
$BOOTMODE || [ ! -d /system/apex ] && return
local APEX DEST
setup_mntpoint /apex
mount -t tmpfs tmpfs /apex -o mode=755
local PATTERN='s/.*"name":[^"]*"\([^"]*\).*/\1/p'
for APEX in /system/apex/*; do
DEST=/apex/$(basename $APEX .apex)
[ "$DEST" == /apex/com.android.runtime.release ] && DEST=/apex/com.android.runtime
mkdir -p $DEST 2>/dev/null
if [ -f $APEX ]; then
# APEX APKs, extract and loop mount
unzip -qo $APEX apex_payload.img -d /apex
loop_setup apex_payload.img
DEST=/apex/$(unzip -qp $APEX apex_manifest.pb | strings | head -n 1)
[ -z $DEST ] && DEST=/apex/$(unzip -qp $APEX apex_manifest.json | sed -n $PATTERN)
[ -z $DEST ] && continue
mkdir -p $DEST
loop_setup /apex/apex_payload.img
if [ ! -z $LOOPDEV ]; then
ui_print "- Mounting $DEST"
mount -t ext4 -o ro,noatime $LOOPDEV $DEST
fi
rm -f apex_payload.img
rm -f /apex/apex_payload.img
elif [ -d $APEX ]; then
# APEX folders, bind mount directory
if [ -f $APEX/apex_manifest.json ]; then
DEST=/apex/$(sed -n $PATTERN $APEX/apex_manifest.json)
elif [ -f $APEX/apex_manifest.pb ]; then
DEST=/apex/$(strings apex_manifest.pb | head -n 1)
else
continue
fi
mkdir -p $DEST
ui_print "- Mounting $DEST"
mount -o bind $APEX $DEST
fi
done
export ANDROID_RUNTIME_ROOT=/apex/com.android.runtime
export ANDROID_TZDATA_ROOT=/apex/com.android.tzdata
local APEXRJPATH=/apex/com.android.runtime/javalib
local SYSFRAME=/system/framework
export BOOTCLASSPATH=\
$APEXRJPATH/core-oj.jar:$APEXRJPATH/core-libart.jar:$APEXRJPATH/okhttp.jar:\
$APEXRJPATH/bouncycastle.jar:$APEXRJPATH/apache-xml.jar:$SYSFRAME/framework.jar:\
$SYSFRAME/ext.jar:$SYSFRAME/telephony-common.jar:$SYSFRAME/voip-common.jar:\
$SYSFRAME/ims-common.jar:$SYSFRAME/android.test.base.jar:$SYSFRAME/telephony-ext.jar:\
/apex/com.android.conscrypt/javalib/conscrypt.jar:\
/apex/com.android.media/javalib/updatable-media.jar
export ANDROID_ART_ROOT=/apex/com.android.art
export ANDROID_I18N_ROOT=/apex/com.android.i18n
local APEXJARS=$(find /apex -name '*.jar' | sort | tr '\n' ':')
local FWK=/system/framework
export BOOTCLASSPATH=${APEXJARS}\
$FWK/framework.jar:$FWK/ext.jar:$FWK/telephony-common.jar:\
$FWK/voip-common.jar:$FWK/ims-common.jar:$FWK/telephony-ext.jar
}
umount_apex() {
[ -d /apex ] || return
local DEST SRC
for DEST in /apex/*; do
[ "$DEST" = '/apex/*' ] && break
SRC=$(grep $DEST /proc/mounts | awk '{ print $1 }')
umount -l $DEST
# Detach loop device just in case
losetup -d $SRC 2>/dev/null
umount -l /apex
for loop in /dev/block/loop*; do
losetup -d $loop 2>/dev/null
done
rm -rf /apex
unset ANDROID_RUNTIME_ROOT
unset ANDROID_TZDATA_ROOT
unset ANDROID_ART_ROOT
unset ANDROID_I18N_ROOT
unset BOOTCLASSPATH
}
@ -389,7 +393,7 @@ find_boot_image() {
BOOTIMAGE=
if $RECOVERYMODE; then
BOOTIMAGE=`find_block recovery_ramdisk$SLOT recovery$SLOT sos`
elif [ ! -z $SLOT ]; then
elif [ -n $SLOT ]; then
BOOTIMAGE=`find_block ramdisk$SLOT recovery_ramdisk$SLOT boot$SLOT`
else
BOOTIMAGE=`find_block ramdisk recovery_ramdisk kern-a android_boot kernel bootimg boot lnx boot_a`
@ -402,7 +406,7 @@ find_boot_image() {
flash_image() {
case "$1" in
*.gz) CMD1="$MAGISKBIN/magiskboot decompress '$1' - 2>/dev/null";;
*.gz) CMD1="gzip -d < '$1' 2>/dev/null";;
*) CMD1="cat '$1'";;
esac
if $BOOTSIGNED; then