From 1e3586621b982f90bd50a2a7113be78455fe4153 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Thu, 8 Dec 2016 00:50:52 -0800 Subject: [PATCH] Magic Mount Total Re-factor Part 2 1. It seems that many part of the system is upset about symlinks, revert to bind mounts 2. New system and vendor mirror implementation found, no need to copy anything 3. Thanks to the new mirror implementation, adding new items to /system and /vendor is now possible 4. Re-written some coding style --- .gitignore | 2 +- scripts/magic_mask.sh | 373 ++++++++++++++++-------------------------- 2 files changed, 138 insertions(+), 237 deletions(-) diff --git a/.gitignore b/.gitignore index b69749855..270fa6a43 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,7 @@ uninstaller/arm/* uninstaller/arm64/* uninstaller/x86/* uninstaller/x64/* -zipsigntools/zipadjust +ziptools/zipadjust # Generated scripts zip_static/common/magic_mask.sh diff --git a/scripts/magic_mask.sh b/scripts/magic_mask.sh index 427533bc7..b201afcb5 100644 --- a/scripts/magic_mask.sh +++ b/scripts/magic_mask.sh @@ -47,8 +47,8 @@ unblock() { run_scripts() { BASE=$MOUNTPOINT for MOD in $BASE/* ; do - if [ ! -f "$MOD/disable" ]; then - if [ -f "$MOD/$1.sh" ]; then + if [ ! -f $MOD/disable ]; then + if [ -f $MOD/$1.sh ]; then chmod 755 $MOD/$1.sh chcon "u:object_r:system_file:s0" "$MOD/$1.sh" log_print "$1: $MOD/$1.sh" @@ -60,8 +60,8 @@ run_scripts() { loopsetup() { LOOPDEVICE= - for DEV in $(ls /dev/block/loop*); do - if [ `losetup $DEV $1 >/dev/null 2>&1; echo $?` -eq 0 ]; then + for DEV in `ls /dev/block/loop*`; do + if losetup $DEV $1; then LOOPDEVICE=$DEV break fi @@ -77,44 +77,39 @@ target_size_check() { } travel() { - cd "$TRAVEL_ROOT/$1" - if [ -f ".replace" ]; then - rm -rf "$MOUNTINFO/$1" - mktouch "$MOUNTINFO/$1" "$TRAVEL_ROOT" + cd $TRAVEL_ROOT/$1 + if [ -f .replace ]; then + rm -rf $MOUNTINFO/$1 + mktouch $MOUNTINFO/$1 $TRAVEL_ROOT else for ITEM in * ; do - if [ ! -e "/$1/$ITEM" ]; then + if [ ! -e /$1/$ITEM ]; then # New item found - if [ "$1" = "system" ]; then - # We cannot add new items to /system root, delete it - rm -rf "$ITEM" - else - # If we are in a higher level, delete the lower levels - rm -rf "$MOUNTINFO/dummy/$1" - # Mount the dummy parent - mktouch "$MOUNTINFO/dummy/$1" + # If we are in a higher level, delete the lower levels + rm -rf $MOUNTINFO/dummy/$1 + # 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 - # Symlinks are small, copy them - mkdir -p "$DUMMDIR/$1" 2>/dev/null - cp -afc "$ITEM" "$DUMMDIR/$1/$ITEM" - else - # Create new dummy file and mount it - mktouch "$DUMMDIR/$1/$ITEM" - mktouch "$MOUNTINFO/$1/$ITEM" "$TRAVEL_ROOT" - fi + 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 + # Symlinks are small, copy them + mkdir -p $DUMMDIR/$1 2>/dev/null + cp -afc $ITEM $DUMMDIR/$1/$ITEM + else + # Create new dummy file and mount it + mktouch $DUMMDIR/$1/$ITEM + mktouch $MOUNTINFO/$1/$ITEM $TRAVEL_ROOT fi else - if [ -d "$ITEM" ]; then + if [ -d $ITEM ]; then # It's an directory, travel deeper - (travel "$1/$ITEM") - elif [ ! -L "$ITEM" ]; then + (travel $1/$ITEM) + elif [ ! -L $ITEM ]; then # Mount this file - mktouch "$MOUNTINFO/$1/$ITEM" "$TRAVEL_ROOT" + mktouch $MOUNTINFO/$1/$ITEM $TRAVEL_ROOT fi fi done @@ -122,55 +117,33 @@ travel() { } clone_dummy() { - for ITEM in $1/* ; do - if [ ! -e "$TRAVEL_ROOT$ITEM" ]; then - if [ ! -d "$MOUNTINFO$ITEM" ]; then - if [ -L "$ITEM" ]; then - # Copy original symlink - cp -afc "$ITEM" "$TRAVEL_ROOT$ITEM" - else - # Link to mirror item - ln -s "$MIRRDIR$ITEM" "$TRAVEL_ROOT$ITEM" - fi + for ITEM in $MIRRDIR$1/* ; do + REAL=${ITEM#$MIRRDIR} + if [ ! -e $MOUNTINFO$REAL ]; then + if [ -L $ITEM ]; then + # Copy original symlink + cp -afc $ITEM $DUMMDIR$REAL else - # Need to clone a skeleton - (clone_dummy "$ITEM") + if [ -d $ITEM ]; then + mkdir -p $DUMMDIR$REAL + else + mktouch $DUMMDIR$REAL + fi + # Mount the mirror + mktouch $MOUNTINFO/mirror$REAL fi - elif [ -d "$TRAVEL_ROOT$ITEM" ]; then - # Need to clone a skeleton - (clone_dummy "$ITEM") + elif [ -d $MOUNTINFO$REAL ]; then + # Need to clone deeper + mkdir -p $DUMMDIR$REAL + (clone_dummy $REAL) fi done } -make_copy_image() { - TARGETSIZE=$2 - if [ -z $TARGETSIZE ]; then - TARGETSIZE=`du -s $1 | awk '{print $1}'` - TARGETSIZE=$((($TARGETSIZE / 10240 + 2) * 10240)) - fi - TARGETIMG=/data/magisk/${1//\//_}.img - make_ext4fs -l ${TARGETSIZE}K -a $1 $TARGETIMG - loopsetup $TARGETIMG - mkdir -p $MIRRDIR/copy$1 - mount -t ext4 -o rw,noatime $LOOPDEVICE $MIRRDIR/copy$1 - return $? -} - -mount_copy_image() { - TARGETIMG=/data/magisk/${1//\//_}.img - umount $MIRRDIR/copy$1 - rm -rf $MIRRDIR/copy - losetup -d $LOOPDEVICE 2>/dev/null - loopsetup $TARGETIMG - mount -t ext4 -o rw,noatime $LOOPDEVICE $1 - return $? -} - bind_mount() { - if [ -e "$1" -a -e "$2" ]; then + if [ -e $1 -a -e $2 ]; then mount -o bind $1 $2 - if [ "$?" -eq "0" ]; then + if [ $? -eq 0 ]; then log_print "Mount: $1" else log_print "Mount Fail: $1" @@ -179,9 +152,9 @@ bind_mount() { } merge_image() { - if [ -f "$1" ]; then + if [ -f $1 ]; then log_print "$1 found" - if [ -f "$IMG" ]; then + if [ -f $IMG ]; then log_print "$IMG found, attempt to merge" # Handle large images @@ -207,36 +180,29 @@ merge_image() { LOOPMERGE=$LOOPDEVICE log_print "$LOOPMERGE $1" - if [ ! -z "$LOOPDATA" ]; then - if [ ! -z "$LOOPMERGE" ]; then - # if loop devices have been setup, mount images - OK=true + 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 [ `mount -t ext4 -o rw,noatime $LOOPDATA /cache/data_img >/dev/null 2>&1; echo $?` -ne 0 ]; then - OK=false - fi - - if [ `mount -t ext4 -o rw,noatime $LOOPMERGE /cache/merge_img >/dev/null 2>&1; echo $?` -ne 0 ]; then - OK=false - fi - - 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 / - fi - - umount /cache/data_img - umount /cache/merge_img + 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 / fi + + umount /cache/data_img + umount /cache/merge_img fi losetup -d $LOOPDATA @@ -263,16 +229,16 @@ case $1 in log_print "** Magisk post-fs mode running..." - # Cleanup previous version stuffs... + # Cleanup legacy stuffs... rm -rf /cache/magisk /cache/magisk_merge /cache/magiskhide.log - if [ -d "/cache/magisk_mount" ]; then + if [ -d /cache/magisk_mount ]; then log_print "* Mounting cache files" 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" + chmod 644 $ITEM + chcon "u:object_r:system_file:s0" $ITEM + TARGET=${ITEM#/cache/magisk_mount} + bind_mount $ITEM $TARGET done fi @@ -280,15 +246,9 @@ case $1 in ;; post-fs-data ) - if [ `mount | grep " /data " >/dev/null 2>&1; echo $?` -ne 0 ]; then - # /data not mounted yet, we will be called again later - unblock - fi - - if [ `mount | grep " /data " | grep "tmpfs" >/dev/null 2>&1; echo $?` -eq 0 ]; then - # /data not mounted yet, we will be called again later - unblock - fi + # /data not mounted yet + ! mount | grep " /data " && unblock + mount | grep " /data " | grep "tmpfs" && unblock # Don't run twice if [ "`getprop magisk.restart_pfsd`" != "1" ]; then @@ -326,32 +286,29 @@ case $1 in # Mount magisk.img [ ! -d $MOUNTPOINT ] && mkdir -p $MOUNTPOINT - if [ `cat /proc/mounts | grep $MOUNTPOINT >/dev/null 2>&1; echo $?` -ne 0 ]; then + if ! mount | grep $MOUNTPOINT; then loopsetup $IMG - if [ ! -z "$LOOPDEVICE" ]; then - mount -t ext4 -o rw,noatime $LOOPDEVICE $MOUNTPOINT + [ ! -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 - if [ `cat /proc/mounts | grep $MOUNTPOINT >/dev/null 2>&1; echo $?` -ne 0 ]; then - log_print "magisk.img mount failed, nothing to do :(" - unblock - fi - # Remove empty directories, legacy paths, symlinks, old temporary images find $MOUNTPOINT -type d -depth ! -path "*core*" -exec rmdir {} \; 2>/dev/null rm -rf $COREDIR/bin $COREDIR/dummy $COREDIR/mirror /data/magisk/*.img # Remove modules that is labeled to be removed for MOD in $MOUNTPOINT/* ; do - if [ -f "$MOD/remove" ] || [ "$MOD" = "zzsupersu" ]; then + if [ -f $MOD/remove ] || [ $MOD = zzsupersu ]; then log_print "Remove module: $MOD" rm -rf $MOD fi done # Unmount, shrink, remount - if [ `umount $MOUNTPOINT >/dev/null 2>&1; echo $?` -eq 0 ]; then + if umount $MOUNTPOINT; then losetup -d $LOOPDEVICE target_size_check $IMG NEWDATASIZE=$(((curUsedM / 32 + 2) * 32)) @@ -360,10 +317,8 @@ case $1 in resize2fs $IMG ${NEWDATASIZE}M fi loopsetup $IMG - if [ ! -z "$LOOPDEVICE" ]; then - mount -t ext4 -o rw,noatime $LOOPDEVICE $MOUNTPOINT - fi - if [ `cat /proc/mounts | grep $MOUNTPOINT >/dev/null 2>&1; echo $?` -ne 0 ]; then + [ ! -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 @@ -376,7 +331,7 @@ case $1 in # Travel through all mods for MOD in $MOUNTPOINT/* ; do - if [ -f "$MOD/auto_mount" -a -d "$MOD/system" -a ! -f "$MOD/disable" ]; then + if [ -f $MOD/auto_mount -a -d $MOD/system -a ! -f $MOD/disable ]; then TRAVEL_ROOT=$MOD (travel system) fi @@ -386,130 +341,80 @@ case $1 in find $TMPDIR -exec chcon -h "u:object_r:system_file:s0" {} \; # linker(64), t*box required for bin - if [ -f "$MOUNTINFO/dummy/system/bin" ]; then + if [ -f $MOUNTINFO/dummy/system/bin ]; then cp -afc /system/bin/linker* /system/bin/t*box $DUMMDIR/system/bin/ fi - BACKUPLIBS=false + DISABLEHIDE=false - # Libraries are full of issues, copy a full clone to data - - # lib - if [ -f "$MOUNTINFO/dummy/system/lib" ]; then - BACKUPLIBS=true - make_copy_image /system/lib - cp -afc /system/lib/. $MIRRDIR/copy/system/lib - cp -afc $DUMMDIR/system/lib/. $MIRRDIR/copy/system/lib - mount_copy_image /system/lib - rm -f $MOUNTINFO/dummy/system/lib - fi - - # lib64 - if [ -f "$MOUNTINFO/dummy/system/lib64" ]; then - BACKUPLIBS=true - make_copy_image /system/lib64 - cp -afc /system/lib64/. $MIRRDIR/copy/system/lib64 - cp -afc $DUMMDIR/system/lib64/. $MIRRDIR/copy/system/lib64 - mount_copy_image /system/lib64 - rm -f $MOUNTINFO/dummy/system/lib64 - fi - - # Whole vendor - if [ -f "$MOUNTINFO/dummy/system/vendor" ]; then - BACKUPLIBS=true - LIBSIZE=`du -s /vendor/lib | awk '{print $1}'` - if [ -d /vendor/lib64 ]; then - LIB64SIZE=`du -s /vendor/lib64 | awk '{print $1}'` - VENDORLIBSIZE=$(((($LIBSIZE + $LIB64SIZE) / 10240 + 2) * 10240)) - else - VENDORLIBSIZE=$((($LIBSIZE / 10240 + 2) * 10240)) - fi - make_copy_image /vendor $VENDORLIBSIZE - - # Copy lib/lib64 - mkdir -p $MIRRDIR/copy/vendor/lib - cp -afc /vendor/lib/. $MIRRDIR/copy/vendor/lib - cp -afc $DUMMDIR/system/vendor/lib/. $MIRRDIR/copy/vendor/lib 2>/dev/null - if [ -d /vendor/lib64 ]; then - mkdir -p $MIRRDIR/copy/vendor/lib64 - cp -afc /vendor/lib64/. $MIRRDIR/copy/vendor/lib64 - cp -afc $DUMMDIR/system/vendor/lib64/. $MIRRDIR/copy/vendor/lib64 2>/dev/null - fi - - cp -afc $DUMMDIR/system/vendor/. $MIRRDIR/copy/vendor - - TRAVEL_ROOT=$MIRRDIR/copy - (clone_dummy /vendor) - # Create vendor mirror - if [ `mount | grep -c "on /vendor type"` -ne 0 ]; then - VENDORBLOCK=`mount | grep "on /vendor type" | awk '{print $1}'` - mkdir -p $MIRRDIR/vendor - mount -o ro $VENDORBLOCK $MIRRDIR/vendor - else - ln -s $MIRRDIR/system/vendor $MIRRDIR/vendor - fi - mount_copy_image /vendor - rm -f $MOUNTINFO/dummy/system/vendor - fi - - # vendor lib - if [ -f "$MOUNTINFO/dummy/system/vendor/lib" ]; then - BACKUPLIBS=true - make_copy_image /system/vendor/lib - cp -afc /system/vendor/lib/. $MIRRDIR/copy/system/vendor/lib - cp -afc $DUMMDIR/system/vendor/lib/. $MIRRDIR/copy/system/vendor/lib - mount_copy_image /system/vendor/lib - rm -f $MOUNTINFO/dummy/system/vendor/lib - fi - - # vendor lib64 - if [ -f "$MOUNTINFO/dummy/system/vendor/lib64" ]; then - BACKUPLIBS=true - make_copy_image /system/vendor/lib64 - cp -afc /system/vendor/lib64/. $MIRRDIR/copy/system/vendor/lib64 - cp -afc $DUMMDIR/system/vendor/lib64/. $MIRRDIR/copy/system/vendor/lib64 - mount_copy_image /system/vendor/lib64 - rm -f $MOUNTINFO/dummy/system/vendor/lib64 - fi + for i in /system /system/lib /system/lib64 /system/vendor /system/vendor/lib /system/vendor/lib64; do + [ -f $MOUNTINFO/dummy$1 ] && DISABLEHIDE=true && break + done # Crash prevention!! - $BACKUPLIBS && rm -f $COREDIR/magiskhide/enable 2>/dev/null + $DISABLEHIDE && rm -f $COREDIR/magiskhide/enable 2>/dev/null # Remove crap folder rm -rf $MOUNTPOINT/lost+found # Start doing tasks - + # Stage 1 - TRAVEL_ROOT=$DUMMDIR - log_print "* Bind mount dummy system" - 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 + 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 + # Since mirrors always exist, we load libraries from mirrors + LD_LIBRARY_PATH=$MIRRDIR/system/lib:$MIRRDIR/vendor/lib + [ -d /system/lib64 ] LD_LIBRARY_PATH=$MIRRDIR/system/lib64:$MIRRDIR/vendor/lib64 # Stage 2 - log_print "* Bind mount module items" + log_print "* Stage 2: Mount dummy skeletons" + # Move dummy /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 + 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 + + # Stage 3 + log_print "* Stage 3: Mount module items" find $MOUNTINFO/system -type f 2>/dev/null | while read ITEM ; do TARGET=${ITEM#$MOUNTINFO} ORIG=`cat $ITEM`$TARGET bind_mount $ORIG $TARGET - rm -f $DUMMDIR${TARGET%/*}/.dummy 2>/dev/null done - # Run scripts + # Stage 4 + log_print "* Stage 4: Execute module 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 + if [ -f $COREDIR/hosts ]; then log_print "* Enabling systemless hosts file support" bind_mount $COREDIR/hosts /system/etc/hosts fi # Expose busybox - if [ -f "$COREDIR/busybox/enable" ]; then + if [ -f $COREDIR/busybox/enable ]; then log_print "* Enabling BusyBox" cp -afc /data/busybox/. $COREDIR/busybox cp -afc /system/xbin/. $COREDIR/busybox @@ -518,10 +423,6 @@ case $1 in bind_mount $COREDIR/busybox /system/xbin fi - # Stage 3 - log_print "* Bind mount system mirror" - bind_mount /system $MIRRDIR/system - # Restart post-fs-data if necessary (multirom) $MULTIROM && setprop magisk.restart_pfsd 1 @@ -536,7 +437,7 @@ case $1 in run_scripts service # Magisk Hide - if [ -f "$COREDIR/magiskhide/enable" ]; then + if [ -f $COREDIR/magiskhide/enable ]; then log_print "* Removing tampered read-only system props" VERIFYBOOT=`getprop ro.boot.verifiedbootstate`