Stop embedding magisk in magiskinit

This commit is contained in:
topjohnwu 2021-01-18 04:25:26 -08:00
parent 42278f12ff
commit 5a71998b4e
11 changed files with 140 additions and 136 deletions

View File

@ -65,6 +65,16 @@ abstract class MagiskInstallImpl : KoinComponent {
logs = NOPList.getInstance() logs = NOPList.getInstance()
} }
companion object {
private val ABI_MAP = TreeMap<String, String>()
init {
ABI_MAP["armeabi-v7a"] = "arm"
ABI_MAP["arm64-v8a"] = "arm64"
ABI_MAP["x86"] = "x86"
ABI_MAP["x86_64"] = "x64"
}
}
protected constructor(zip: Uri, out: MutableList<String>, err: MutableList<String>) { protected constructor(zip: Uri, out: MutableList<String>, err: MutableList<String>) {
console = out console = out
logs = err logs = err
@ -103,44 +113,52 @@ abstract class MagiskInstallImpl : KoinComponent {
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
private fun extractZip(): Boolean { private fun extractZip(): Boolean {
val arch = if (Build.VERSION.SDK_INT >= 21) { val arch: String
val abis = listOf(*Build.SUPPORTED_ABIS) val arch32: String
if (abis.contains("x86")) "x86" else "arm" if (Build.VERSION.SDK_INT >= 21) {
arch = ABI_MAP[Build.SUPPORTED_ABIS[0]]!!
arch32 = ABI_MAP[Build.SUPPORTED_32_BIT_ABIS[0]]!!
} else { } else {
if (Build.CPU_ABI == "x86") "x86" else "arm" arch = ABI_MAP[Build.CPU_ABI]!!
arch32 = arch
} }
console.add("- Device platform: " + Build.CPU_ABI) console.add("- Device platform: $arch")
console.add("- Magisk Manager: ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})") console.add("- Magisk Manager: ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})")
console.add("- Install target: ${Info.remote.magisk.version} (${Info.remote.magisk.versionCode})") console.add("- Install target: ${Info.remote.magisk.version} (${Info.remote.magisk.versionCode})")
fun newFile(name: String): File {
return if (installDir is SuFile)
SuFile(installDir, name)
else
File(installDir, name)
}
try { try {
ZipInputStream(zipUri.inputStream().buffered()).use { zi -> ZipInputStream(zipUri.inputStream().buffered()).use { zi ->
lateinit var ze: ZipEntry lateinit var ze: ZipEntry
while (zi.nextEntry?.let { ze = it } != null) { while (zi.nextEntry?.let { ze = it } != null) {
if (ze.isDirectory) if (ze.isDirectory)
continue continue
var name: String? = null var name: String? = null
val names = arrayOf("$arch/", "common/", "META-INF/com/google/android/update-binary")
for (n in names) { if (ze.name.startsWith("chromeos/")) {
ze.name.run { name = ze.name
if (startsWith(n)) { } else {
name = substring(lastIndexOf('/') + 1) for (n in listOf("$arch32/", "common/", "META-INF/com/google/android/update-binary")) {
if (ze.name.startsWith(n)) {
name = ze.name.substring(ze.name.lastIndexOf('/') + 1)
break
} }
} }
name ?: continue
break
} }
if (name == null && ze.name.startsWith("chromeos/"))
name = ze.name name ?: continue
name?.also {
val dest = if (installDir is SuFile) val dest = newFile(name)
SuFile(installDir, it) dest.parentFile!!.mkdirs()
else SuFileOutputStream(dest).use { s -> zi.copyTo(s) }
File(installDir, it)
dest.parentFile!!.mkdirs()
SuFileOutputStream(dest).use { s -> zi.copyTo(s) }
} ?: continue
} }
} }
} catch (e: IOException) { } catch (e: IOException) {
@ -149,9 +167,9 @@ abstract class MagiskInstallImpl : KoinComponent {
return false return false
} }
val init64 = SuFile.open(installDir, "magiskinit64") val init64 = newFile("magiskinit64")
if (Build.VERSION.SDK_INT >= 21 && Build.SUPPORTED_64_BIT_ABIS.isNotEmpty()) { if (init64.exists() && arch != arch32) {
init64.renameTo(SuFile.open(installDir, "magiskinit")) init64.renameTo(newFile("magiskinit"))
} else { } else {
init64.delete() init64.delete()
} }
@ -324,9 +342,12 @@ abstract class MagiskInstallImpl : KoinComponent {
return false return false
} }
if (!("KEEPFORCEENCRYPT=${Config.keepEnc} KEEPVERITY=${Config.keepVerity} " + val FLAGS =
"RECOVERYMODE=${Config.recovery} sh update-binary " + "KEEPFORCEENCRYPT=${Config.keepEnc} " +
"sh boot_patch.sh $srcBoot").sh().isSuccess) { "KEEPVERITY=${Config.keepVerity} " +
"RECOVERYMODE=${Config.recovery}"
if (!("$FLAGS sh update-binary sh boot_patch.sh $srcBoot").sh().isSuccess) {
return false return false
} }

View File

@ -7,7 +7,7 @@ run_delay() {
} }
env_check() { env_check() {
for file in busybox magisk magiskboot magiskinit util_functions.sh boot_patch.sh; do for file in busybox magiskboot magiskinit util_functions.sh boot_patch.sh; do
[ -f $MAGISKBIN/$file ] || return 1 [ -f $MAGISKBIN/$file ] || return 1
done done
return 0 return 0

View File

@ -287,18 +287,6 @@ def run_ndk_build(flags):
def dump_bin_headers(): def dump_bin_headers():
for arch in archs:
bin_file = op.join('native', 'out', arch, 'magisk')
if not op.exists(bin_file):
error('Build "magisk" before building "magiskinit"')
with open(op.join('native', 'out', arch, 'binaries_arch.h'), 'w') as out:
with open(bin_file, 'rb') as src:
binary_dump(src, out, 'magisk_xz')
for arch, arch32 in list(zip(arch64, archs)):
bin_file = op.join('native', 'out', arch, 'magisk')
with open(op.join('native', 'out', arch32, 'binaries_arch64.h'), 'w') as out:
with open(bin_file, 'rb') as src:
binary_dump(src, out, 'magisk_xz')
stub = op.join(config['outdir'], 'stub-release.apk') stub = op.join(config['outdir'], 'stub-release.apk')
if not op.exists(stub): if not op.exists(stub):
error('Build stub APK before building "magiskinit"') error('Build stub APK before building "magiskinit"')
@ -347,26 +335,31 @@ def build_binary(args):
run_ndk_build('B_MAGISK=1 B_64BIT=1') run_ndk_build('B_MAGISK=1 B_64BIT=1')
clean_elf() clean_elf()
if 'magiskinit' in args.target:
dump_bin_headers()
run_ndk_build('B_INIT=1')
run_ndk_build('B_INIT64=1')
if 'magiskpolicy' in args.target:
run_ndk_build('B_POLICY=1')
if 'resetprop' in args.target:
run_ndk_build('B_PROP=1')
if 'magiskboot' in args.target:
run_ndk_build('B_BOOT=1')
if 'busybox' in args.target:
run_ndk_build('B_BB=1')
if 'test' in args.target: if 'test' in args.target:
run_ndk_build('B_TEST=1 B_64BIT=1') run_ndk_build('B_TEST=1 B_64BIT=1')
# 32-bit only targets can be built in one command
flag = ''
if 'magiskinit' in args.target:
dump_bin_headers()
flag += ' B_INIT=1'
if 'magiskpolicy' in args.target:
flag += ' B_POLICY=1'
if 'resetprop' in args.target:
flag += ' B_PROP=1'
if 'magiskboot' in args.target:
flag += ' B_BOOT=1'
if 'busybox' in args.target:
flag += ' B_BB=1'
if flag:
run_ndk_build(flag)
def build_apk(args, module): def build_apk(args, module):
build_type = 'Release' if args.release or module == 'stub' else 'Debug' build_type = 'Release' if args.release or module == 'stub' else 'Debug'
@ -440,12 +433,17 @@ def zip_main(args):
zip_with_msg(zipf, source, target) zip_with_msg(zipf, source, target)
# Binaries # Binaries
for lib_dir, zip_dir in [('armeabi-v7a', 'arm'), ('x86', 'x86')]: for lib_dir, zip_dir in zip(archs, ('arm', 'x86')):
for binary in ['magiskinit', 'magiskinit64', 'magiskboot']: for binary in ['magiskinit', 'magiskboot', 'magisk']:
source = op.join('native', 'out', lib_dir, binary) source = op.join('native', 'out', lib_dir, binary)
target = op.join(zip_dir, binary) target = op.join(zip_dir, 'magisk32' if binary == 'magisk' else binary)
zip_with_msg(zipf, source, target) zip_with_msg(zipf, source, target)
for lib_dir, zip_dir in zip(arch64, ('arm', 'x86')):
source = op.join('native', 'out', lib_dir, 'magisk')
target = op.join(zip_dir, 'magisk64')
zip_with_msg(zipf, source, target)
# APK # APK
source = op.join( source = op.join(
config['outdir'], 'app-release.apk' if args.release else 'app-debug.apk') config['outdir'], 'app-release.apk' if args.release else 'app-debug.apk')

View File

@ -54,21 +54,10 @@ endif
include $(CLEAR_VARS) include $(CLEAR_VARS)
ifdef B_INIT ifdef B_INIT
LOCAL_MODULE := magiskinit LOCAL_MODULE := magiskinit
BB_INIT := 1
else ifdef B_INIT64
LOCAL_MODULE := magiskinit64
LOCAL_CPPFLAGS += -DUSE_64BIT
BB_INIT := 1
endif
ifdef BB_INIT
LOCAL_STATIC_LIBRARIES := libsepol libxz libutils LOCAL_STATIC_LIBRARIES := libsepol libxz libutils
LOCAL_C_INCLUDES := \ LOCAL_C_INCLUDES := jni/include out
jni/include \
out \
out/$(TARGET_ARCH_ABI)
LOCAL_SRC_FILES := \ LOCAL_SRC_FILES := \
init/init.cpp \ init/init.cpp \

View File

@ -10,12 +10,6 @@
#include <utils.hpp> #include <utils.hpp>
#include "binaries.h" #include "binaries.h"
#ifdef USE_64BIT
#include "binaries_arch64.h"
#else
#include "binaries_arch.h"
#endif
#include "init.hpp" #include "init.hpp"
using namespace std; using namespace std;
@ -26,7 +20,7 @@ using namespace std;
constexpr int (*init_applet_main[])(int, char *[]) = constexpr int (*init_applet_main[])(int, char *[]) =
{ magiskpolicy_main, magiskpolicy_main, nullptr }; { magiskpolicy_main, magiskpolicy_main, nullptr };
static bool unxz(int fd, const uint8_t *buf, size_t size) { bool unxz(int fd, const uint8_t *buf, size_t size) {
uint8_t out[8192]; uint8_t out[8192];
xz_crc32_init(); xz_crc32_init();
struct xz_dec *dec = xz_dec_init(XZ_DYNALLOC, 1 << 26); struct xz_dec *dec = xz_dec_init(XZ_DYNALLOC, 1 << 26);
@ -49,16 +43,6 @@ static bool unxz(int fd, const uint8_t *buf, size_t size) {
return true; return true;
} }
int dump_magisk(const char *path, mode_t mode) {
int fd = xopen(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode);
if (fd < 0)
return 1;
if (!unxz(fd, magisk_xz, sizeof(magisk_xz)))
return 1;
close(fd);
return 0;
}
static int dump_manager(const char *path, mode_t mode) { static int dump_manager(const char *path, mode_t mode) {
int fd = xopen(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode); int fd = xopen(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode);
if (fd < 0) if (fd < 0)
@ -147,10 +131,9 @@ int main(int argc, char *argv[]) {
#endif #endif
if (argc > 1 && argv[1] == "-x"sv) { if (argc > 1 && argv[1] == "-x"sv) {
if (argv[2] == "magisk"sv) if (argc > 2 && argv[2] == "manager"sv)
return dump_magisk(argv[3], 0755);
else if (argv[2] == "manager"sv)
return dump_manager(argv[3], 0644); return dump_manager(argv[3], 0644);
return 1;
} }
if (getpid() != 1) if (getpid() != 1)
@ -166,18 +149,16 @@ int main(int argc, char *argv[]) {
// This will also mount /sys and /proc // This will also mount /sys and /proc
load_kernel_info(&cmd); load_kernel_info(&cmd);
if (cmd.skip_initramfs) { if (cmd.skip_initramfs)
init = new SARInit(argv, &cmd); init = new SARInit(argv, &cmd);
} else { else if (cmd.force_normal_boot)
if (cmd.force_normal_boot) init = new FirstStageInit(argv, &cmd);
init = new FirstStageInit(argv, &cmd); else if (access("/sbin/recovery", F_OK) == 0 || access("/system/bin/recovery", F_OK) == 0)
else if (access("/sbin/recovery", F_OK) == 0 || access("/system/bin/recovery", F_OK) == 0) init = new RecoveryInit(argv, &cmd);
init = new RecoveryInit(argv, &cmd); else if (check_two_stage())
else if (check_two_stage()) init = new FirstStageInit(argv, &cmd);
init = new FirstStageInit(argv, &cmd); else
else init = new RootFSInit(argv, &cmd);
init = new RootFSInit(argv, &cmd);
}
} }
// Run the main routine // Run the main routine

View File

@ -31,9 +31,9 @@ struct fstab_entry {
extern std::vector<std::string> mount_list; extern std::vector<std::string> mount_list;
bool unxz(int fd, const uint8_t *buf, size_t size);
void load_kernel_info(cmdline *cmd); void load_kernel_info(cmdline *cmd);
bool check_two_stage(); bool check_two_stage();
int dump_magisk(const char *path, mode_t mode);
void setup_klog(); void setup_klog();
/*************** /***************

View File

@ -378,13 +378,6 @@ void BaseInit::exec_init() {
exit(1); exit(1);
} }
static void patch_socket_name(const char *path) {
char rstr[16];
gen_rand_str(rstr, sizeof(rstr));
auto bin = mmap_data::rw(path);
bin.patch({ make_pair(MAIN_SOCKET, rstr) });
}
void MagiskInit::setup_tmp(const char *path) { void MagiskInit::setup_tmp(const char *path) {
LOGD("Setup Magisk tmp at %s\n", path); LOGD("Setup Magisk tmp at %s\n", path);
xmount("tmpfs", path, "tmpfs", 0, "mode=755"); xmount("tmpfs", path, "tmpfs", 0, "mode=755");
@ -401,8 +394,8 @@ void MagiskInit::setup_tmp(const char *path) {
fd = xopen("magiskinit", O_WRONLY | O_CREAT, 0755); fd = xopen("magiskinit", O_WRONLY | O_CREAT, 0755);
xwrite(fd, self.buf, self.sz); xwrite(fd, self.buf, self.sz);
close(fd); close(fd);
dump_magisk("magisk", 0755);
patch_socket_name("magisk"); // The magisk binary will be handled later
// Create applet symlinks // Create applet symlinks
for (int i = 0; applet_names[i]; ++i) for (int i = 0; applet_names[i]; ++i)

View File

@ -174,6 +174,13 @@ static void magic_mount(const string &sdir, const string &ddir = "") {
} }
} }
static void patch_socket_name(const char *path) {
char rstr[16];
gen_rand_str(rstr, sizeof(rstr));
auto bin = mmap_data::rw(path);
bin.patch({ make_pair(MAIN_SOCKET, rstr) });
}
#define ROOTMIR MIRRDIR "/system_root" #define ROOTMIR MIRRDIR "/system_root"
#define MONOPOLICY "/sepolicy" #define MONOPOLICY "/sepolicy"
#define NEW_INITRC "/system/etc/init/hw/init.rc" #define NEW_INITRC "/system/etc/init/hw/init.rc"
@ -280,9 +287,19 @@ void SARBase::patch_rootdir() {
patch_init_rc(NEW_INITRC, ROOTOVL NEW_INITRC, tmp_dir.data()); patch_init_rc(NEW_INITRC, ROOTOVL NEW_INITRC, tmp_dir.data());
} }
// Extract magisk
{
auto magisk = mmap_data::ro("magisk.xz");
unlink("magisk.xz");
int fd = xopen("magisk", O_WRONLY | O_CREAT, 0755);
unxz(fd, magisk.buf, magisk.sz);
close(fd);
patch_socket_name("magisk");
}
// Mount rootdir // Mount rootdir
magic_mount(ROOTOVL); magic_mount(ROOTOVL);
int dest = xopen(ROOTMNT, O_WRONLY | O_CREAT | O_CLOEXEC, 0); int dest = xopen(ROOTMNT, O_WRONLY | O_CREAT, 0);
write(dest, magic_mount_list.data(), magic_mount_list.length()); write(dest, magic_mount_list.data(), magic_mount_list.length());
close(dest); close(dest);
@ -335,15 +352,23 @@ void MagiskProxy::start() {
// Backup stuffs before removing them // Backup stuffs before removing them
self = mmap_data::ro("/sbin/magisk"); self = mmap_data::ro("/sbin/magisk");
config = mmap_data::ro("/.backup/.magisk"); config = mmap_data::ro("/.backup/.magisk");
auto magisk = mmap_data::ro("/sbin/magisk.xz");
char custom_rules_dir[64]; char custom_rules_dir[64];
custom_rules_dir[0] = '\0'; custom_rules_dir[0] = '\0';
xreadlink(TMP_RULESDIR, custom_rules_dir, sizeof(custom_rules_dir)); xreadlink(TMP_RULESDIR, custom_rules_dir, sizeof(custom_rules_dir));
unlink("/sbin/magisk"); unlink("/sbin/magisk");
unlink("/sbin/magisk.xz");
rm_rf("/.backup"); rm_rf("/.backup");
setup_tmp("/sbin"); setup_tmp("/sbin");
// Extract magisk
int fd = xopen("/sbin/magisk", O_WRONLY | O_CREAT, 0755);
unxz(fd, magisk.buf, magisk.sz);
close(fd);
patch_socket_name("/sbin/magisk");
// Create symlinks pointing back to /root // Create symlinks pointing back to /root
recreate_sbin("/root", false); recreate_sbin("/root", false);

View File

@ -53,6 +53,8 @@ if [ -z $SOURCEDMODE ]; then
cd "`getdir "${BASH_SOURCE:-$0}"`" cd "`getdir "${BASH_SOURCE:-$0}"`"
# Load utility functions # Load utility functions
. ./util_functions.sh . ./util_functions.sh
# Detect version and architecture
api_level_arch_detect
fi fi
BOOTIMAGE="$1" BOOTIMAGE="$1"
@ -67,9 +69,6 @@ export KEEPFORCEENCRYPT
chmod -R 755 . chmod -R 755 .
# Extract magisk if doesn't exist
[ -e magisk ] || ./magiskinit -x magisk magisk
######### #########
# Unpack # Unpack
######### #########
@ -135,14 +134,24 @@ echo "KEEPFORCEENCRYPT=$KEEPFORCEENCRYPT" >> config
echo "RECOVERYMODE=$RECOVERYMODE" >> config echo "RECOVERYMODE=$RECOVERYMODE" >> config
[ ! -z $SHA1 ] && echo "SHA1=$SHA1" >> config [ ! -z $SHA1 ] && echo "SHA1=$SHA1" >> config
# Compress to save precious ramdisk space
if $IS64BIT; then
./magiskboot compress=xz magisk64 magisk.xz
else
./magiskboot compress=xz magisk32 magisk.xz
fi
./magiskboot cpio ramdisk.cpio \ ./magiskboot cpio ramdisk.cpio \
"add 750 init magiskinit" \ "add 750 init magiskinit" \
"mkdir 0750 overlay.d" \
"mkdir 0750 overlay.d/sbin" \
"add 750 overlay.d/sbin/magisk.xz magisk.xz" \
"patch" \ "patch" \
"backup ramdisk.cpio.orig" \ "backup ramdisk.cpio.orig" \
"mkdir 000 .backup" \ "mkdir 000 .backup" \
"add 000 .backup/.magisk config" "add 000 .backup/.magisk config"
rm -f ramdisk.cpio.orig config rm -f ramdisk.cpio.orig config magisk.xz
################# #################
# Binary Patches # Binary Patches

View File

@ -28,14 +28,8 @@ mount_sbin() {
if [ ! -f /system/build.prop ]; then if [ ! -f /system/build.prop ]; then
# Running on PC # Running on PC
cd "`dirname "$0"`/.." cd "$(dirname "$0")/.."
adb push native/out/x86/busybox scripts/emulator.sh /data/local/tmp adb push native/out/x86/busybox scripts/emulator.sh native/out/x86/magiskinit native/out/x86_64/magisk /data/local/tmp
emu_arch=`adb shell uname -m`
if [ "$emu_arch" = "x86_64" ]; then
adb push native/out/x86/magiskinit64 /data/local/tmp/magiskinit
else
adb push native/out/x86/magiskinit /data/local/tmp
fi
adb shell sh /data/local/tmp/emulator.sh adb shell sh /data/local/tmp/emulator.sh
exit 0 exit 0
fi fi
@ -43,7 +37,7 @@ fi
cd /data/local/tmp cd /data/local/tmp
chmod 777 busybox chmod 777 busybox
chmod 777 magiskinit chmod 777 magiskinit
./magiskinit -x magisk magisk chmod 777 magisk
if [ -z "$FIRST_STAGE" ]; then if [ -z "$FIRST_STAGE" ]; then
export FIRST_STAGE=1 export FIRST_STAGE=1
@ -113,7 +107,7 @@ else
fi fi
# Magisk stuffs # Magisk stuffs
./magiskinit -x magisk $BINDIR/magisk cp -af ./magisk $BINDIR/magisk
chmod 755 $BINDIR/magisk chmod 755 $BINDIR/magisk
ln -s ./magisk $BINDIR/su ln -s ./magisk $BINDIR/su
ln -s ./magisk $BINDIR/resetprop ln -s ./magisk $BINDIR/resetprop

View File

@ -445,12 +445,6 @@ install_magisk() {
$BOOTSIGNED && ui_print "- Boot image is signed with AVB 1.0" $BOOTSIGNED && ui_print "- Boot image is signed with AVB 1.0"
fi fi
if $IS64BIT; then
mv -f magiskinit64 magiskinit 2>/dev/null
else
rm -f magiskinit64
fi
# Source the boot patcher # Source the boot patcher
SOURCEDMODE=true SOURCEDMODE=true
. ./boot_patch.sh "$BOOTIMAGE" . ./boot_patch.sh "$BOOTIMAGE"