Magisk/scripts/magic_mask.sh

528 lines
15 KiB
Bash
Raw Permalink Normal View History

2016-09-14 10:31:13 +08:00
#!/system/bin/sh
LOGFILE=/cache/magisk.log
2017-02-05 23:40:50 +08:00
DISABLEFILE=/cache/.disable_magisk
2017-02-06 03:22:37 +08:00
UNINSTALLER=/cache/magisk_uninstaller.sh
2016-09-14 10:31:13 +08:00
IMG=/data/magisk.img
WHITELIST="/system/bin"
2016-09-14 10:31:13 +08:00
MOUNTPOINT=/magisk
2016-10-06 17:53:52 +08:00
COREDIR=$MOUNTPOINT/.core
2016-09-14 10:31:13 +08:00
TMPDIR=/dev/magisk
DUMMDIR=$TMPDIR/dummy
MIRRDIR=$TMPDIR/mirror
MOUNTINFO=$TMPDIR/mnt
2016-09-14 10:31:13 +08:00
# Use the included busybox for maximum compatibility and reliable results
# e.g. we rely on the option "-c" for cp (reserve contexts), and -exec for find
2017-02-04 18:44:07 +08:00
TOOLPATH=/dev/busybox
2016-11-05 02:38:02 +08:00
BINPATH=/data/magisk
2017-02-04 18:44:07 +08:00
OLDPATH=$PATH
export PATH=$TOOLPATH:$OLDPATH
APPDIR=/data/data/com.topjohnwu.magisk/files
2016-11-29 04:16:01 +08:00
2016-11-13 16:58:43 +08:00
# Default permissions
umask 022
2016-09-14 10:31:13 +08:00
log_print() {
2016-11-01 04:21:43 +08:00
echo "$1"
echo "$1" >> $LOGFILE
2016-09-14 10:31:13 +08:00
log -p i -t Magisk "$1"
}
mktouch() {
mkdir -p "${1%/*}" 2>/dev/null
2016-09-14 10:31:13 +08:00
if [ -z "$2" ]; then
2016-11-14 04:30:05 +08:00
touch "$1" 2>/dev/null
2016-09-14 10:31:13 +08:00
else
2016-11-14 04:30:05 +08:00
echo "$2" > "$1" 2>/dev/null
2016-09-14 10:31:13 +08:00
fi
}
2017-01-01 19:45:06 +08:00
in_list() {
for i in $2; do
[ "$1" = "$i" ] && return 0
done
return 1
}
2016-09-14 10:31:13 +08:00
unblock() {
2016-10-03 04:34:50 +08:00
touch /dev/.magisk.unblock
2017-02-05 00:37:30 +08:00
chcon u:object_r:device:s0 /dev/.magisk.unblock
2016-09-14 10:31:13 +08:00
exit
}
run_scripts() {
2016-10-06 17:53:52 +08:00
BASE=$MOUNTPOINT
2016-09-14 10:31:13 +08:00
for MOD in $BASE/* ; do
if [ ! -f $MOD/disable ]; then
if [ -f $MOD/$1.sh ]; then
2016-09-14 10:31:13 +08:00
chmod 755 $MOD/$1.sh
chcon u:object_r:system_file:s0 $MOD/$1.sh
2016-09-14 10:31:13 +08:00
log_print "$1: $MOD/$1.sh"
sh $MOD/$1.sh
2016-09-14 10:31:13 +08:00
fi
fi
done
2017-02-06 00:13:25 +08:00
for SCRIPT in $COREDIR/${1}.d/* ; do
if [ -f "$SCRIPT" ]; then
chmod 755 $SCRIPT
chcon u:object_r:system_file:s0 $SCRIPT
log_print "${1}.d: $SCRIPT"
sh $SCRIPT
fi
done
2016-09-14 10:31:13 +08:00
}
loopsetup() {
LOOPDEVICE=
for DEV in `ls /dev/block/loop*`; do
if losetup $DEV $1; then
2016-09-14 10:31:13 +08:00
LOOPDEVICE=$DEV
break
fi
done
}
target_size_check() {
e2fsck -p -f "$1"
2016-09-14 10:31:13 +08:00
curBlocks=`e2fsck -n $1 2>/dev/null | cut -d, -f3 | cut -d\ -f2`;
curUsedM=$((`echo "$curBlocks" | cut -d/ -f1` * 4 / 1024));
curSizeM=$((`echo "$curBlocks" | cut -d/ -f2` * 4 / 1024));
curFreeM=$((curSizeM - curUsedM));
}
travel() {
2017-01-02 17:48:34 +08:00
# Ignore /system/vendor, we will handle it differently
[ "$1" = "system/vendor" ] && return
cd "$TRAVEL_ROOT/$1"
if [ -f .replace ]; then
rm -rf "$MOUNTINFO/$1"
mktouch "$MOUNTINFO/$1" "$TRAVEL_ROOT"
2016-09-14 10:31:13 +08:00
else
for ITEM in * ; do
2017-02-05 01:36:07 +08:00
# This means it an empty folder (shouldn't happen, but better to be safe)
[ "$ITEM" = "*" ] && return;
# Target not found or target/file is a symlink
if [ ! -e "/$1/$ITEM" -o -L "/$1/$ITEM" -o -L "$ITEM" ]; then
# If we are in a higher level, delete the lower levels
2017-02-05 01:36:07 +08:00
rm -rf "$MOUNTINFO/dummy/$1" 2>/dev/null
# Mount the dummy parent
mktouch "$MOUNTINFO/dummy/$1"
if [ -d "$ITEM" ]; then
# Create new dummy directory and mount it
mkdir -p "$DUMMDIR/$1/$ITEM"
mktouch "$MOUNTINFO/$1/$ITEM" "$TRAVEL_ROOT"
elif [ -L "$ITEM" ]; then
2017-02-05 01:36:07 +08:00
# Copy symlinks
mkdir -p "$DUMMDIR/$1" 2>/dev/null
cp -afc "$ITEM" $"DUMMDIR/$1/$ITEM"
2016-09-14 10:31:13 +08:00
else
# Create new dummy file and mount it
mktouch "$DUMMDIR/$1/$ITEM"
mktouch "$MOUNTINFO/$1/$ITEM" "$TRAVEL_ROOT"
2016-09-14 10:31:13 +08:00
fi
else
if [ -d "$ITEM" ]; then
# It's an directory, travel deeper
(travel "$1/$ITEM")
elif [ ! -L "$ITEM" ]; then
# Mount this file
mktouch "$MOUNTINFO/$1/$ITEM" "$TRAVEL_ROOT"
fi
2016-09-14 10:31:13 +08:00
fi
done
fi
}
2016-09-14 10:31:13 +08:00
clone_dummy() {
2017-01-02 17:48:34 +08:00
LINK=false
in_list "$1" "$WHITELIST" && LINK=true
2017-01-01 19:45:06 +08:00
for ITEM in $MIRRDIR$1/* ; do
REAL="${ITEM#$MIRRDIR}"
if [ -d "$MOUNTINFO$REAL" ]; then
2016-12-08 21:31:34 +08:00
# Need to clone deeper
mkdir -p "$DUMMDIR$REAL"
(clone_dummy "$REAL")
2017-02-05 01:36:07 +08:00
elif [ ! -f "$DUMMDIR$REAL" ]; then
# It's not the file to be added/replaced, clone it
if [ -L "$ITEM" ]; then
# Copy original symlink
cp -afc "$ITEM" "$DUMMDIR$REAL"
else
if $LINK && [ ! -e "$MOUNTINFO$REAL" ]; then
ln -s "$MIRRDIR$REAL" "$DUMMDIR$REAL"
2016-11-29 04:16:01 +08:00
else
if [ -d "$ITEM" ]; then
mkdir -p "$DUMMDIR$REAL"
2017-01-01 19:45:06 +08:00
else
mktouch "$DUMMDIR$REAL"
2017-01-01 19:45:06 +08:00
fi
[ ! -e "$MOUNTINFO$REAL" ] && mktouch "$MOUNTINFO/mirror$REAL"
2016-11-29 04:16:01 +08:00
fi
2016-09-14 10:31:13 +08:00
fi
fi
done
2016-09-14 10:31:13 +08:00
}
bind_mount() {
if [ -e "$1" -a -e "$2" ]; then
mount -o bind "$1" "$2"
if [ $? -eq 0 ]; then
2016-10-06 17:53:52 +08:00
log_print "Mount: $1"
else
log_print "Mount Fail: $1"
fi
2016-09-14 10:31:13 +08:00
fi
}
merge_image() {
if [ -f $1 ]; then
2016-09-14 10:31:13 +08:00
log_print "$1 found"
if [ -f $IMG ]; then
2016-09-14 10:31:13 +08:00
log_print "$IMG found, attempt to merge"
# Handle large images
target_size_check $1
MERGEUSED=$curUsedM
target_size_check $IMG
if [ "$MERGEUSED" -gt "$curFreeM" ]; then
NEWDATASIZE=$((((MERGEUSED + curUsedM) / 32 + 2) * 32))
log_print "Expanding $IMG to ${NEWDATASIZE}M..."
resize2fs $IMG ${NEWDATASIZE}M
fi
# Start merging
mkdir /cache/data_img
mkdir /cache/merge_img
# setup loop devices
loopsetup $IMG
LOOPDATA=$LOOPDEVICE
log_print "$LOOPDATA $IMG"
loopsetup $1
LOOPMERGE=$LOOPDEVICE
log_print "$LOOPMERGE $1"
if [ ! -z $LOOPDATA -a ! -z $LOOPMERGE ]; then
# if loop devices have been setup, mount images
OK=false
mount -t ext4 -o rw,noatime $LOOPDATA /cache/data_img && \
mount -t ext4 -o rw,noatime $LOOPMERGE /cache/merge_img && \
OK=true
if $OK; then
# Merge (will reserve selinux contexts)
cd /cache/merge_img
for MOD in *; do
if [ "$MOD" != "lost+found" ]; then
log_print "Merging: $MOD"
rm -rf /cache/data_img/$MOD
fi
done
cp -afc . /cache/data_img
log_print "Merge complete"
cd /
2016-09-14 10:31:13 +08:00
fi
umount /cache/data_img
umount /cache/merge_img
2016-09-14 10:31:13 +08:00
fi
2016-11-14 04:30:05 +08:00
losetup -d $LOOPDATA
losetup -d $LOOPMERGE
2016-09-14 10:31:13 +08:00
rmdir /cache/data_img
rmdir /cache/merge_img
else
log_print "Moving $1 to $IMG "
mv $1 $IMG
fi
rm -f $1
fi
}
case $1 in
post-fs )
mv $LOGFILE /cache/last_magisk.log
touch $LOGFILE
chmod 644 $LOGFILE
# No more cache mods!
# Only for multirom!
2016-09-14 10:31:13 +08:00
2016-11-09 05:17:14 +08:00
log_print "** Magisk post-fs mode running..."
# Cleanup legacy stuffs...
2016-11-07 23:57:21 +08:00
rm -rf /cache/magisk /cache/magisk_merge /cache/magiskhide.log
2016-11-05 02:38:02 +08:00
2017-02-06 03:22:37 +08:00
[ -f $DISABLEFILE -o -f $UNINSTALLER ] && unblock
2017-02-05 23:40:50 +08:00
if [ -d /cache/magisk_mount ]; then
log_print "* Mounting cache files"
2016-11-13 21:02:35 +08:00
find /cache/magisk_mount -type f 2>/dev/null | while read ITEM ; do
chmod 644 "$ITEM"
chcon u:object_r:system_file:s0 "$ITEM"
TARGET="${ITEM#/cache/magisk_mount}"
bind_mount "$ITEM" "$TARGET"
2016-11-09 05:17:14 +08:00
done
fi
2016-09-14 10:31:13 +08:00
unblock
;;
post-fs-data )
# /data not mounted yet
2017-01-01 19:45:06 +08:00
! mount | grep " /data " >/dev/null && unblock
mount | grep " /data " | grep "tmpfs" >/dev/null && unblock
2016-09-14 10:31:13 +08:00
# Don't run twice
2016-11-05 02:38:02 +08:00
if [ "`getprop magisk.restart_pfsd`" != "1" ]; then
2016-09-14 10:31:13 +08:00
2016-11-01 04:21:43 +08:00
log_print "** Magisk post-fs-data mode running..."
2016-10-03 04:34:50 +08:00
# Cache support
2017-02-01 06:02:43 +08:00
mv /cache/stock_boot.img /data/stock_boot.img 2>/dev/null
mv /cache/magisk.apk /data/magisk.apk 2>/dev/null
mv /cache/custom_ramdisk_patch.sh /data/custom_ramdisk_patch.sh 2>/dev/null
2017-02-04 18:44:07 +08:00
if [ -d /cache/data_bin ]; then
rm -rf $BINPATH
2016-11-05 02:38:02 +08:00
mv /cache/data_bin $BINPATH
2016-09-14 10:31:13 +08:00
fi
2017-02-04 18:44:07 +08:00
chmod -R 755 $BINPATH
chown -R 0.0 $BINPATH
2017-02-01 06:02:43 +08:00
# Live patch sepolicy
$BINPATH/sepolicy-inject --live
2016-09-14 10:31:13 +08:00
2017-02-06 03:22:37 +08:00
if [ -f $UNINSTALLER ]; then
touch /dev/.magisk.unblock
chcon u:object_r:device:s0 /dev/.magisk.unblock
BOOTMODE=true sh $UNINSTALLER
exit
fi
# Set up environment
2017-02-04 18:44:07 +08:00
mkdir -p $TOOLPATH
$BINPATH/busybox --install -s $TOOLPATH
ln -s $BINPATH/busybox $TOOLPATH/busybox
# Prevent issues
rm -f $TOOLPATH/su $TOOLPATH/sh $TOOLPATH/reboot
chmod -R 755 $TOOLPATH
chown -R 0.0 $TOOLPATH
find $BINPATH $TOOLPATH -exec chcon -h u:object_r:system_file:s0 {} \;
2016-09-14 10:31:13 +08:00
2016-11-29 04:16:01 +08:00
# Multirom functions should go here, not available right now
MULTIROM=false
# Image merging
chmod 644 $IMG /cache/magisk.img /data/magisk_merge.img 2>/dev/null
merge_image /cache/magisk.img
merge_image /data/magisk_merge.img
2016-09-14 10:31:13 +08:00
# Mount magisk.img
[ ! -d $MOUNTPOINT ] && mkdir -p $MOUNTPOINT
if ! mount | grep $MOUNTPOINT; then
loopsetup $IMG
[ ! -z $LOOPDEVICE ] && mount -t ext4 -o rw,noatime $LOOPDEVICE $MOUNTPOINT
if [ $? -ne 0 ]; then
log_print "magisk.img mount failed, nothing to do :("
unblock
fi
2016-09-14 10:31:13 +08:00
fi
# Remove empty directories, legacy paths, symlinks, old temporary images
2016-11-14 04:30:05 +08:00
find $MOUNTPOINT -type d -depth ! -path "*core*" -exec rmdir {} \; 2>/dev/null
2017-02-05 23:40:50 +08:00
rm -rf $MOUNTPOINT/zzsupersu $MOUNTPOINT/phh $COREDIR/bin $COREDIR/dummy $COREDIR/mirror \
$COREDIR/busybox /data/magisk/*.img /data/busybox 2>/dev/null
2016-09-14 10:31:13 +08:00
2017-02-01 06:02:43 +08:00
# Remove modules that are labeled to be removed
for MOD in $MOUNTPOINT/* ; do
2017-01-01 19:45:06 +08:00
rm -f $MOD/system/placeholder 2>/dev/null
if [ -f $MOD/remove ]; then
log_print "Remove module: $MOD"
rm -rf $MOD
fi
done
# Unmount, shrink, remount
if umount $MOUNTPOINT; then
losetup -d $LOOPDEVICE 2>/dev/null
target_size_check $IMG
NEWDATASIZE=$(((curUsedM / 32 + 2) * 32))
if [ "$curSizeM" -gt "$NEWDATASIZE" ]; then
log_print "Shrinking $IMG to ${NEWDATASIZE}M..."
resize2fs $IMG ${NEWDATASIZE}M
fi
loopsetup $IMG
[ ! -z $LOOPDEVICE ] && mount -t ext4 -o rw,noatime $LOOPDEVICE $MOUNTPOINT
if [ $? -ne 0 ]; then
log_print "magisk.img mount failed, nothing to do :("
unblock
fi
fi
2016-09-14 10:31:13 +08:00
2017-02-01 06:02:43 +08:00
# Start MagiskSU if no SuperSU
2017-02-04 18:44:07 +08:00
export PATH=$OLDPATH
2017-02-01 06:02:43 +08:00
[ ! -f /sbin/launch_daemonsu.sh ] && sh $COREDIR/su/magisksu.sh
2017-02-04 18:44:07 +08:00
export PATH=$TOOLPATH:$OLDPATH
2017-02-05 23:40:50 +08:00
[ -f $DISABLEFILE ] && unblock
2016-09-14 10:31:13 +08:00
2017-02-01 06:02:43 +08:00
log_print "* Preparing modules"
2017-01-02 02:00:53 +08:00
mkdir -p $DUMMDIR
mkdir -p $MIRRDIR/system
2016-09-14 10:31:13 +08:00
2017-01-01 19:45:06 +08:00
# Remove crap folder
rm -rf $MOUNTPOINT/lost+found
2017-01-02 17:48:34 +08:00
# Link vendor if not exist
if [ ! -e /vendor ]; then
mount -o rw,remount rootfs /
ln -s /system/vendor /vendor
mount -o ro,remount rootfs /
fi
# Travel through all mods
for MOD in $MOUNTPOINT/* ; do
if [ -f $MOD/auto_mount -a -d $MOD/system -a ! -f $MOD/disable ]; then
TRAVEL_ROOT=$MOD
(travel system)
2017-01-02 17:48:34 +08:00
rm -f $MOD/vendor 2>/dev/null
if [ -d $MOD/system/vendor ]; then
ln -s $MOD/system/vendor $MOD/vendor
(travel vendor)
fi
fi
done
2016-11-14 04:30:05 +08:00
# Proper permissions for generated items
find $TMPDIR -exec chcon -h u:object_r:system_file:s0 {} \;
2016-11-14 04:30:05 +08:00
# linker(64), t*box required for bin
if [ -f $MOUNTINFO/dummy/system/bin ]; then
cp -afc /system/bin/linker* /system/bin/t*box $DUMMDIR/system/bin/
2016-11-14 04:30:05 +08:00
fi
# Start doing tasks
# Stage 1
log_print "* Stage 1: Mount system and vendor mirrors"
SYSTEMBLOCK=`mount | grep " /system " | awk '{print $1}'`
mkdir -p $MIRRDIR/system
mount -o ro $SYSTEMBLOCK $MIRRDIR/system
if [ `mount | grep -c " /vendor "` -ne 0 ]; then
VENDORBLOCK=`mount | grep " /vendor " | awk '{print $1}'`
mkdir -p $MIRRDIR/vendor
mount -o ro $VENDORBLOCK $MIRRDIR/vendor
else
ln -s $MIRRDIR/system/vendor $MIRRDIR/vendor
fi
2017-01-01 19:45:06 +08:00
2017-01-02 17:48:34 +08:00
# Since mirrors always exist, we load libraries and binaries from mirrors
2017-01-01 19:45:06 +08:00
export LD_LIBRARY_PATH=$MIRRDIR/system/lib:$MIRRDIR/vendor/lib
2017-01-02 17:48:34 +08:00
[ -d $MIRRDIR/system/lib64 ] && export LD_LIBRARY_PATH=$MIRRDIR/system/lib64:$MIRRDIR/vendor/lib64
# Stage 2
log_print "* Stage 2: Mount dummy skeletons"
2017-01-02 17:48:34 +08:00
# Move /system/vendor to /vendor for consistency
mv -f $MOUNTINFO/dummy/system/vendor $MOUNTINFO/dummy/vendor 2>/dev/null
mv -f $DUMMDIR/system/vendor $DUMMDIR/vendor 2>/dev/null
2016-11-14 04:30:05 +08:00
find $MOUNTINFO/dummy -type f 2>/dev/null | while read ITEM ; do
TARGET="${ITEM#$MOUNTINFO/dummy}"
ORIG="$DUMMDIR$TARGET"
(clone_dummy "$TARGET")
bind_mount "$ORIG" "$TARGET"
done
2017-01-02 17:48:34 +08:00
# Check if the dummy /system/bin is empty, it shouldn't
[ -e $DUMMDIR/system/bin -a ! -e $DUMMDIR/system/bin/sh ] && clone_dummy /system/bin
2017-01-02 17:48:34 +08:00
# Stage 3
log_print "* Stage 3: Mount module items"
find $MOUNTINFO/system $MOUNTINFO/vendor -type f 2>/dev/null | while read ITEM ; do
TARGET="${ITEM#$MOUNTINFO}"
ORIG="`cat "$ITEM"`$TARGET"
bind_mount "$ORIG" "$TARGET"
2017-01-02 17:48:34 +08:00
done
# Stage 4
2017-02-06 00:13:25 +08:00
log_print "* Stage 4: Execute scripts"
run_scripts post-fs-data
# Stage 5
log_print "* Stage 5: Mount mirrored items back to dummy"
find $MOUNTINFO/mirror -type f 2>/dev/null | while read ITEM ; do
TARGET="${ITEM#$MOUNTINFO/mirror}"
ORIG="$MIRRDIR$TARGET"
bind_mount "$ORIG" "$TARGET"
done
# Bind hosts for Adblock apps
if [ -f $COREDIR/hosts ]; then
log_print "* Enabling systemless hosts file support"
2016-11-09 05:17:14 +08:00
bind_mount $COREDIR/hosts /system/etc/hosts
fi
if [ -f /data/magisk.apk ]; then
if [ -z `ls /data/app | grep com.topjohnwu.magisk` ]; then
mkdir /data/app/com.topjohnwu.magisk-1
cp /data/magisk.apk /data/app/com.topjohnwu.magisk-1/base.apk
chown 1000.1000 /data/app/com.topjohnwu.magisk-1
chown 1000.1000 /data/app/com.topjohnwu.magisk-1/base.apk
chmod 755 /data/app/com.topjohnwu.magisk-1
chmod 644 /data/app/com.topjohnwu.magisk-1/base.apk
chcon u:object_r:apk_data_file:s0 /data/app/com.topjohnwu.magisk-1
chcon u:object_r:apk_data_file:s0 /data/app/com.topjohnwu.magisk-1/base.apk
fi
rm -f /data/magisk.apk 2>/dev/null
fi
2017-02-05 00:37:30 +08:00
for MOD in $MOUNTPOINT/* ; do
# Read in defined system props
if [ -f $MOD/system.prop ]; then
log_print "* Reading props from $MOD/system.prop"
/data/magisk/resetprop --file $MOD/system.prop
fi
done
# Expose busybox
[ "`getprop persist.magisk.busybox`" = "1" ] && sh /sbin/magic_mask.sh mount_busybox
2016-11-05 02:38:02 +08:00
# Restart post-fs-data if necessary (multirom)
$MULTIROM && setprop magisk.restart_pfsd 1
fi
2016-09-14 10:31:13 +08:00
unblock
;;
2017-02-04 18:44:07 +08:00
mount_busybox )
log_print "* Enabling BusyBox"
cp -afc /system/xbin/. $TOOLPATH
umount /system/xbin 2>/dev/null
bind_mount $TOOLPATH /system/xbin
;;
2016-09-14 10:31:13 +08:00
service )
2016-10-03 04:34:50 +08:00
# Version info
MAGISK_VERSION_STUB
2016-11-01 04:21:43 +08:00
log_print "** Magisk late_start service mode running..."
2017-02-05 23:40:50 +08:00
if [ -f $DISABLEFILE ]; then
setprop ro.magisk.disable 1
exit
fi
2016-09-14 10:31:13 +08:00
run_scripts service
;;
esac