Unify Magisk configuration
Introduce monogisk tool
This commit is contained in:
parent
8d6f3c2450
commit
e710848345
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
|
out/
|
||||||
obj/
|
obj/
|
||||||
libs/
|
libs/
|
||||||
*.zip
|
*.zip
|
||||||
|
355
build.py
355
build.py
@ -38,23 +38,36 @@ import shutil
|
|||||||
import lzma
|
import lzma
|
||||||
import base64
|
import base64
|
||||||
|
|
||||||
def silentremove(file):
|
def mv(source, target):
|
||||||
|
print('mv: {} -> {}'.format(source, target))
|
||||||
|
shutil.move(source, target)
|
||||||
|
|
||||||
|
def cp(source, target):
|
||||||
|
print('cp: {} -> {}'.format(source, target))
|
||||||
|
shutil.copyfile(source, target)
|
||||||
|
|
||||||
|
def rm(file):
|
||||||
try:
|
try:
|
||||||
os.remove(file)
|
os.remove(file)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
if e.errno != errno.ENOENT:
|
if e.errno != errno.ENOENT:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
def mkdir(path, mode=0o777):
|
||||||
|
try:
|
||||||
|
os.mkdir(path, mode)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def mkdir_p(path, mode=0o777):
|
||||||
|
os.makedirs(path, mode, exist_ok=True)
|
||||||
|
|
||||||
def zip_with_msg(zipfile, source, target):
|
def zip_with_msg(zipfile, source, target):
|
||||||
if not os.path.exists(source):
|
if not os.path.exists(source):
|
||||||
error('{} does not exist! Try build \'binary\' and \'apk\' before zipping!'.format(source))
|
error('{} does not exist! Try build \'binary\' and \'apk\' before zipping!'.format(source))
|
||||||
print('zip: {} -> {}'.format(source, target))
|
print('zip: {} -> {}'.format(source, target))
|
||||||
zipfile.write(source, target)
|
zipfile.write(source, target)
|
||||||
|
|
||||||
def cp(source, target):
|
|
||||||
print('cp: {} -> {}'.format(source, target))
|
|
||||||
shutil.copyfile(source, target)
|
|
||||||
|
|
||||||
def build_all(args):
|
def build_all(args):
|
||||||
build_binary(args)
|
build_binary(args)
|
||||||
build_apk(args)
|
build_apk(args)
|
||||||
@ -67,13 +80,40 @@ def build_binary(args):
|
|||||||
# Force update Android.mk timestamp to trigger recompilation
|
# Force update Android.mk timestamp to trigger recompilation
|
||||||
os.utime(os.path.join('jni', 'Android.mk'))
|
os.utime(os.path.join('jni', 'Android.mk'))
|
||||||
|
|
||||||
ndk_build = os.path.join(os.environ['ANDROID_HOME'], 'ndk-bundle', 'ndk-build')
|
|
||||||
debug_flag = '' if args.release else '-DMAGISK_DEBUG'
|
debug_flag = '' if args.release else '-DMAGISK_DEBUG'
|
||||||
proc = subprocess.run('{} APP_CFLAGS=\"-DMAGISK_VERSION=\\\"{}\\\" -DMAGISK_VER_CODE={} {}\" -j{}'.format(
|
cflag = 'APP_CFLAGS=\"-DMAGISK_VERSION=\\\"{}\\\" -DMAGISK_VER_CODE={} {}\"'.format(args.versionString, args.versionCode, debug_flag)
|
||||||
ndk_build, args.versionString, args.versionCode, debug_flag, multiprocessing.cpu_count()), shell=True)
|
|
||||||
|
ndk_build = os.path.join(os.environ['ANDROID_HOME'], 'ndk-bundle', 'ndk-build')
|
||||||
|
# Prebuild
|
||||||
|
proc = subprocess.run('PRECOMPILE=true {} {} -j{}'.format(ndk_build, cflag, multiprocessing.cpu_count()), shell=True)
|
||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
error('Build Magisk binary failed!')
|
error('Build Magisk binary failed!')
|
||||||
|
|
||||||
|
print('')
|
||||||
|
for arch in ['arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64']:
|
||||||
|
mkdir_p(os.path.join('out', arch))
|
||||||
|
with open(os.path.join('out', arch, 'dump.h'), 'w') as dump:
|
||||||
|
dump.write('#include "stdlib.h"\n')
|
||||||
|
for binary in ['magisk', 'magiskinit']:
|
||||||
|
mv(os.path.join('libs', arch, binary), os.path.join('out', arch, binary))
|
||||||
|
with open(os.path.join('out', arch, binary), 'rb') as bin:
|
||||||
|
dump.write('const uint8_t {}_dump[] = "'.format(binary))
|
||||||
|
dump.write(''.join("\\x{:02X}".format(c) for c in lzma.compress(bin.read(), preset=9)))
|
||||||
|
dump.write('";\n')
|
||||||
|
print('')
|
||||||
|
|
||||||
|
proc = subprocess.run('{} {} -j{}'.format(ndk_build, cflag, multiprocessing.cpu_count()), shell=True)
|
||||||
|
if proc.returncode != 0:
|
||||||
|
error('Build Magisk binary failed!')
|
||||||
|
|
||||||
|
print('')
|
||||||
|
for arch in ['arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64']:
|
||||||
|
for binary in ['monogisk', 'magiskboot', 'b64xz', 'busybox']:
|
||||||
|
try:
|
||||||
|
mv(os.path.join('libs', arch, binary), os.path.join('out', arch, binary))
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
def build_apk(args):
|
def build_apk(args):
|
||||||
header('* Building Magisk Manager')
|
header('* Building Magisk Manager')
|
||||||
|
|
||||||
@ -104,8 +144,8 @@ def build_apk(args):
|
|||||||
# Find the latest build tools
|
# Find the latest build tools
|
||||||
build_tool = sorted(os.listdir(os.path.join(os.environ['ANDROID_HOME'], 'build-tools')))[-1]
|
build_tool = sorted(os.listdir(os.path.join(os.environ['ANDROID_HOME'], 'build-tools')))[-1]
|
||||||
|
|
||||||
silentremove(aligned)
|
rm(aligned)
|
||||||
silentremove(release)
|
rm(release)
|
||||||
|
|
||||||
proc = subprocess.run([
|
proc = subprocess.run([
|
||||||
os.path.join(os.environ['ANDROID_HOME'], 'build-tools', build_tool, 'zipalign'),
|
os.path.join(os.environ['ANDROID_HOME'], 'build-tools', build_tool, 'zipalign'),
|
||||||
@ -129,13 +169,24 @@ def build_apk(args):
|
|||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
error('Release sign Magisk Manager failed!')
|
error('Release sign Magisk Manager failed!')
|
||||||
|
|
||||||
silentremove(unsigned)
|
rm(unsigned)
|
||||||
silentremove(aligned)
|
rm(aligned)
|
||||||
|
|
||||||
|
mkdir(os.path.join('..', 'out'))
|
||||||
|
target = os.path.join('..', 'out', 'app-release.apk')
|
||||||
|
print('')
|
||||||
|
mv(release, target)
|
||||||
else:
|
else:
|
||||||
proc = subprocess.run('{} app:assembleDebug'.format(os.path.join('.', 'gradlew')), shell=True)
|
proc = subprocess.run('{} app:assembleDebug'.format(os.path.join('.', 'gradlew')), shell=True)
|
||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
error('Build Magisk Manager failed!')
|
error('Build Magisk Manager failed!')
|
||||||
|
|
||||||
|
source = os.path.join('app', 'build', 'outputs', 'apk', 'debug', 'app-debug.apk')
|
||||||
|
mkdir(os.path.join('..', 'out'))
|
||||||
|
target = os.path.join('..', 'out', 'app-debug.apk')
|
||||||
|
print('')
|
||||||
|
mv(source, target)
|
||||||
|
|
||||||
# Return to upper directory
|
# Return to upper directory
|
||||||
os.chdir('..')
|
os.chdir('..')
|
||||||
|
|
||||||
@ -145,11 +196,137 @@ def build_snet(args):
|
|||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
error('Build snet extention failed!')
|
error('Build snet extention failed!')
|
||||||
source = os.path.join('snet', 'build', 'outputs', 'apk', 'release', 'snet-release-unsigned.apk')
|
source = os.path.join('snet', 'build', 'outputs', 'apk', 'release', 'snet-release-unsigned.apk')
|
||||||
target = os.path.join('..', 'snet.apk')
|
mkdir(os.path.join('..', 'out'))
|
||||||
|
target = os.path.join('..', 'out', 'snet.apk')
|
||||||
print('')
|
print('')
|
||||||
cp(source, target)
|
mv(source, target)
|
||||||
os.chdir('..')
|
os.chdir('..')
|
||||||
|
|
||||||
|
def gen_update_binary():
|
||||||
|
update_bin = []
|
||||||
|
binary = os.path.join('out', 'armeabi-v7a', 'b64xz')
|
||||||
|
if not os.path.exists(binary):
|
||||||
|
error('Please build \'binary\' before zipping!')
|
||||||
|
with open(binary, 'rb') as b64xz:
|
||||||
|
update_bin.append('#! /sbin/sh\nEX_ARM=\'')
|
||||||
|
update_bin.append(''.join("\\x{:02X}".format(c) for c in b64xz.read()))
|
||||||
|
binary = os.path.join('out', 'x86', 'b64xz')
|
||||||
|
with open(binary, 'rb') as b64xz:
|
||||||
|
update_bin.append('\'\nEX_X86=\'')
|
||||||
|
update_bin.append(''.join("\\x{:02X}".format(c) for c in b64xz.read()))
|
||||||
|
binary = os.path.join('out', 'armeabi-v7a', 'busybox')
|
||||||
|
with open(binary, 'rb') as busybox:
|
||||||
|
update_bin.append('\'\nBB_ARM=')
|
||||||
|
update_bin.append(base64.b64encode(lzma.compress(busybox.read(), preset=9)).decode('ascii'))
|
||||||
|
binary = os.path.join('out', 'x86', 'busybox')
|
||||||
|
with open(binary, 'rb') as busybox:
|
||||||
|
update_bin.append('\nBB_X86=')
|
||||||
|
update_bin.append(base64.b64encode(lzma.compress(busybox.read(), preset=9)).decode('ascii'))
|
||||||
|
update_bin.append('\n')
|
||||||
|
with open(os.path.join('scripts', 'update_binary.sh'), 'r') as script:
|
||||||
|
update_bin.append(script.read())
|
||||||
|
return ''.join(update_bin)
|
||||||
|
|
||||||
|
def zip_main(args):
|
||||||
|
header('* Packing Flashable Zip')
|
||||||
|
|
||||||
|
with zipfile.ZipFile('tmp_unsigned.zip', 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=False) as zipf:
|
||||||
|
# META-INF
|
||||||
|
# update-binary
|
||||||
|
target = os.path.join('META-INF', 'com', 'google', 'android', 'update-binary')
|
||||||
|
print('zip: ' + target)
|
||||||
|
zipf.writestr(target, gen_update_binary())
|
||||||
|
# updater-script
|
||||||
|
source = os.path.join('scripts', 'flash_script.sh')
|
||||||
|
target = os.path.join('META-INF', 'com', 'google', 'android', 'updater-script')
|
||||||
|
zip_with_msg(zipf, source, target)
|
||||||
|
|
||||||
|
# Binaries
|
||||||
|
for lib_dir, zip_dir in [('arm64-v8a', 'arm64'), ('armeabi-v7a', 'arm'), ('x86', 'x86'), ('x86_64', 'x64')]:
|
||||||
|
for binary in ['monogisk', 'magiskboot']:
|
||||||
|
source = os.path.join('out', lib_dir, binary)
|
||||||
|
target = os.path.join(zip_dir, binary)
|
||||||
|
zip_with_msg(zipf, source, target)
|
||||||
|
|
||||||
|
# APK
|
||||||
|
source = os.path.join('out', 'app-release.apk' if args.release else 'app-debug.apk')
|
||||||
|
target = os.path.join('common', 'magisk.apk')
|
||||||
|
zip_with_msg(zipf, source, target)
|
||||||
|
|
||||||
|
# Scripts
|
||||||
|
# boot_patch.sh
|
||||||
|
source = os.path.join('scripts', 'boot_patch.sh')
|
||||||
|
target = os.path.join('common', 'boot_patch.sh')
|
||||||
|
zip_with_msg(zipf, source, target)
|
||||||
|
# util_functions.sh
|
||||||
|
source = os.path.join('scripts', 'util_functions.sh')
|
||||||
|
with open(source, 'r') as script:
|
||||||
|
# Add version info util_functions.sh
|
||||||
|
util_func = script.read().replace(
|
||||||
|
'MAGISK_VERSION_STUB', 'MAGISK_VER="{}"\nMAGISK_VER_CODE={}'.format(args.versionString, args.versionCode))
|
||||||
|
target = os.path.join('common', 'util_functions.sh')
|
||||||
|
print('zip: ' + source + ' -> ' + target)
|
||||||
|
zipf.writestr(target, util_func)
|
||||||
|
# addon.d.sh
|
||||||
|
source = os.path.join('scripts', 'addon.d.sh')
|
||||||
|
target = os.path.join('addon.d', '99-magisk.sh')
|
||||||
|
zip_with_msg(zipf, source, target)
|
||||||
|
|
||||||
|
# Prebuilts
|
||||||
|
for chromeos in ['futility', 'kernel_data_key.vbprivk', 'kernel.keyblock']:
|
||||||
|
source = os.path.join('chromeos', chromeos)
|
||||||
|
zip_with_msg(zipf, source, source)
|
||||||
|
|
||||||
|
# End of zipping
|
||||||
|
|
||||||
|
output = os.path.join('out', 'Magisk-v{}.zip'.format(args.versionString))
|
||||||
|
sign_adjust_zip('tmp_unsigned.zip', output)
|
||||||
|
|
||||||
|
def zip_uninstaller(args):
|
||||||
|
header('* Packing Uninstaller Zip')
|
||||||
|
|
||||||
|
with zipfile.ZipFile('tmp_unsigned.zip', 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=False) as zipf:
|
||||||
|
# META-INF
|
||||||
|
# update-binary
|
||||||
|
target = os.path.join('META-INF', 'com', 'google', 'android', 'update-binary')
|
||||||
|
print('zip: ' + target)
|
||||||
|
zipf.writestr(target, gen_update_binary())
|
||||||
|
# updater-script
|
||||||
|
source = os.path.join('scripts', 'uninstaller_loader.sh')
|
||||||
|
target = os.path.join('META-INF', 'com', 'google', 'android', 'updater-script')
|
||||||
|
zip_with_msg(zipf, source, target)
|
||||||
|
|
||||||
|
# Binaries
|
||||||
|
for lib_dir, zip_dir in [('arm64-v8a', 'arm64'), ('armeabi-v7a', 'arm'), ('x86', 'x86'), ('x86_64', 'x64')]:
|
||||||
|
source = os.path.join('out', lib_dir, 'magiskboot')
|
||||||
|
target = os.path.join(zip_dir, 'magiskboot')
|
||||||
|
zip_with_msg(zipf, source, target)
|
||||||
|
|
||||||
|
source = os.path.join('scripts', 'magisk_uninstaller.sh')
|
||||||
|
target = 'magisk_uninstaller.sh'
|
||||||
|
zip_with_msg(zipf, source, target)
|
||||||
|
|
||||||
|
# Scripts
|
||||||
|
# util_functions.sh
|
||||||
|
source = os.path.join('scripts', 'util_functions.sh')
|
||||||
|
with open(source, 'r') as script:
|
||||||
|
# Remove the stub
|
||||||
|
util_func = script.read().replace(
|
||||||
|
'MAGISK_VERSION_STUB', '')
|
||||||
|
target = os.path.join('util_functions.sh')
|
||||||
|
print('zip: ' + source + ' -> ' + target)
|
||||||
|
zipf.writestr(target, util_func)
|
||||||
|
|
||||||
|
# Prebuilts
|
||||||
|
for chromeos in ['futility', 'kernel_data_key.vbprivk', 'kernel.keyblock']:
|
||||||
|
source = os.path.join('chromeos', chromeos)
|
||||||
|
zip_with_msg(zipf, source, source)
|
||||||
|
|
||||||
|
# End of zipping
|
||||||
|
|
||||||
|
output = os.path.join('out', 'Magisk-uninstaller-{}.zip'.format(datetime.datetime.now().strftime('%Y%m%d')))
|
||||||
|
sign_adjust_zip('tmp_unsigned.zip', output)
|
||||||
|
|
||||||
def sign_adjust_zip(unsigned, output):
|
def sign_adjust_zip(unsigned, output):
|
||||||
signer_name = 'zipsigner-1.0.jar'
|
signer_name = 'zipsigner-1.0.jar'
|
||||||
jarsigner = os.path.join('java', 'crypto', 'build', 'libs', signer_name)
|
jarsigner = os.path.join('java', 'crypto', 'build', 'libs', signer_name)
|
||||||
@ -191,142 +368,9 @@ def sign_adjust_zip(unsigned, output):
|
|||||||
error('Second sign flashable zip failed!')
|
error('Second sign flashable zip failed!')
|
||||||
|
|
||||||
# Cleanup
|
# Cleanup
|
||||||
silentremove(unsigned)
|
rm(unsigned)
|
||||||
silentremove('tmp_signed.zip')
|
rm('tmp_signed.zip')
|
||||||
silentremove('tmp_adjusted.zip')
|
rm('tmp_adjusted.zip')
|
||||||
|
|
||||||
def gen_update_binary():
|
|
||||||
update_bin = []
|
|
||||||
binary = os.path.join('libs', 'armeabi-v7a', 'b64xz')
|
|
||||||
if not os.path.exists(binary):
|
|
||||||
error('Please build \'binary\' before zipping!')
|
|
||||||
with open(binary, 'rb') as b64xz:
|
|
||||||
update_bin.append('#! /sbin/sh\nEX_ARM=\'')
|
|
||||||
update_bin.append(''.join("\\x{:02X}".format(c) for c in b64xz.read()))
|
|
||||||
binary = os.path.join('libs', 'x86', 'b64xz')
|
|
||||||
with open(binary, 'rb') as b64xz:
|
|
||||||
update_bin.append('\'\nEX_X86=\'')
|
|
||||||
update_bin.append(''.join("\\x{:02X}".format(c) for c in b64xz.read()))
|
|
||||||
binary = os.path.join('libs', 'armeabi-v7a', 'busybox')
|
|
||||||
with open(binary, 'rb') as busybox:
|
|
||||||
update_bin.append('\'\nBB_ARM=')
|
|
||||||
update_bin.append(base64.b64encode(lzma.compress(busybox.read())).decode('ascii'))
|
|
||||||
binary = os.path.join('libs', 'x86', 'busybox')
|
|
||||||
with open(binary, 'rb') as busybox:
|
|
||||||
update_bin.append('\nBB_X86=')
|
|
||||||
update_bin.append(base64.b64encode(lzma.compress(busybox.read())).decode('ascii'))
|
|
||||||
update_bin.append('\n')
|
|
||||||
with open(os.path.join('scripts', 'update_binary.sh'), 'r') as script:
|
|
||||||
update_bin.append(script.read())
|
|
||||||
return ''.join(update_bin)
|
|
||||||
|
|
||||||
def zip_main(args):
|
|
||||||
header('* Packing Flashable Zip')
|
|
||||||
|
|
||||||
with zipfile.ZipFile('tmp_unsigned.zip', 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=False) as zipf:
|
|
||||||
# META-INF
|
|
||||||
# update-binary
|
|
||||||
target = os.path.join('META-INF', 'com', 'google', 'android', 'update-binary')
|
|
||||||
print('zip: ' + target)
|
|
||||||
zipf.writestr(target, gen_update_binary())
|
|
||||||
# updater-script
|
|
||||||
source = os.path.join('scripts', 'flash_script.sh')
|
|
||||||
target = os.path.join('META-INF', 'com', 'google', 'android', 'updater-script')
|
|
||||||
zip_with_msg(zipf, source, target)
|
|
||||||
|
|
||||||
# Binaries
|
|
||||||
for lib_dir, zip_dir in [('arm64-v8a', 'arm64'), ('armeabi-v7a', 'arm'), ('x86', 'x86'), ('x86_64', 'x64')]:
|
|
||||||
for binary in ['magisk', 'magiskboot']:
|
|
||||||
source = os.path.join('libs', lib_dir, binary)
|
|
||||||
target = os.path.join(zip_dir, binary)
|
|
||||||
zip_with_msg(zipf, source, target)
|
|
||||||
source = os.path.join('libs', 'arm64-v8a', 'magiskinit')
|
|
||||||
target = os.path.join('arm64', 'magiskinit')
|
|
||||||
zip_with_msg(zipf, source, target)
|
|
||||||
|
|
||||||
# APK
|
|
||||||
source = os.path.join('java', 'app', 'build', 'outputs', 'apk',
|
|
||||||
'release' if args.release else 'debug', 'app-release.apk' if args.release else 'app-debug.apk')
|
|
||||||
target = os.path.join('common', 'magisk.apk')
|
|
||||||
zip_with_msg(zipf, source, target)
|
|
||||||
|
|
||||||
# Scripts
|
|
||||||
# boot_patch.sh
|
|
||||||
source = os.path.join('scripts', 'boot_patch.sh')
|
|
||||||
target = os.path.join('common', 'boot_patch.sh')
|
|
||||||
zip_with_msg(zipf, source, target)
|
|
||||||
# util_functions.sh
|
|
||||||
source = os.path.join('scripts', 'util_functions.sh')
|
|
||||||
with open(source, 'r') as script:
|
|
||||||
# Add version info util_functions.sh
|
|
||||||
util_func = script.read().replace(
|
|
||||||
'MAGISK_VERSION_STUB', 'MAGISK_VER="{}"\nMAGISK_VER_CODE={}'.format(args.versionString, args.versionCode))
|
|
||||||
target = os.path.join('common', 'util_functions.sh')
|
|
||||||
print('zip: ' + source + ' -> ' + target)
|
|
||||||
zipf.writestr(target, util_func)
|
|
||||||
# addon.d.sh
|
|
||||||
source = os.path.join('scripts', 'addon.d.sh')
|
|
||||||
target = os.path.join('addon.d', '99-magisk.sh')
|
|
||||||
zip_with_msg(zipf, source, target)
|
|
||||||
# init.magisk.rc
|
|
||||||
source = os.path.join('scripts', 'init.magisk.rc')
|
|
||||||
target = os.path.join('common', 'init.magisk.rc')
|
|
||||||
zip_with_msg(zipf, source, target)
|
|
||||||
|
|
||||||
# Prebuilts
|
|
||||||
for chromeos in ['futility', 'kernel_data_key.vbprivk', 'kernel.keyblock']:
|
|
||||||
source = os.path.join('chromeos', chromeos)
|
|
||||||
zip_with_msg(zipf, source, source)
|
|
||||||
|
|
||||||
# End of zipping
|
|
||||||
|
|
||||||
output = 'Magisk-v{}.zip'.format(args.versionString)
|
|
||||||
sign_adjust_zip('tmp_unsigned.zip', output)
|
|
||||||
|
|
||||||
def zip_uninstaller(args):
|
|
||||||
header('* Packing Uninstaller Zip')
|
|
||||||
|
|
||||||
with zipfile.ZipFile('tmp_unsigned.zip', 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=False) as zipf:
|
|
||||||
# META-INF
|
|
||||||
# update-binary
|
|
||||||
target = os.path.join('META-INF', 'com', 'google', 'android', 'update-binary')
|
|
||||||
print('zip: ' + target)
|
|
||||||
zipf.writestr(target, gen_update_binary())
|
|
||||||
# updater-script
|
|
||||||
source = os.path.join('scripts', 'uninstaller_loader.sh')
|
|
||||||
target = os.path.join('META-INF', 'com', 'google', 'android', 'updater-script')
|
|
||||||
zip_with_msg(zipf, source, target)
|
|
||||||
|
|
||||||
# Binaries
|
|
||||||
for lib_dir, zip_dir in [('arm64-v8a', 'arm64'), ('armeabi-v7a', 'arm'), ('x86', 'x86'), ('x86_64', 'x64')]:
|
|
||||||
source = os.path.join('libs', lib_dir, 'magiskboot')
|
|
||||||
target = os.path.join(zip_dir, 'magiskboot')
|
|
||||||
zip_with_msg(zipf, source, target)
|
|
||||||
|
|
||||||
source = os.path.join('scripts', 'magisk_uninstaller.sh')
|
|
||||||
target = 'magisk_uninstaller.sh'
|
|
||||||
zip_with_msg(zipf, source, target)
|
|
||||||
|
|
||||||
# Scripts
|
|
||||||
# util_functions.sh
|
|
||||||
source = os.path.join('scripts', 'util_functions.sh')
|
|
||||||
with open(source, 'r') as script:
|
|
||||||
# Remove the stub
|
|
||||||
util_func = script.read().replace(
|
|
||||||
'MAGISK_VERSION_STUB', '')
|
|
||||||
target = os.path.join('util_functions.sh')
|
|
||||||
print('zip: ' + source + ' -> ' + target)
|
|
||||||
zipf.writestr(target, util_func)
|
|
||||||
|
|
||||||
# Prebuilts
|
|
||||||
for chromeos in ['futility', 'kernel_data_key.vbprivk', 'kernel.keyblock']:
|
|
||||||
source = os.path.join('chromeos', chromeos)
|
|
||||||
zip_with_msg(zipf, source, source)
|
|
||||||
|
|
||||||
# End of zipping
|
|
||||||
|
|
||||||
output = 'Magisk-uninstaller-{}.zip'.format(datetime.datetime.now().strftime('%Y%m%d'))
|
|
||||||
sign_adjust_zip('tmp_unsigned.zip', output)
|
|
||||||
|
|
||||||
def cleanup(args):
|
def cleanup(args):
|
||||||
if len(args.target) == 0:
|
if len(args.target) == 0:
|
||||||
@ -335,20 +379,23 @@ def cleanup(args):
|
|||||||
if 'binary' in args.target:
|
if 'binary' in args.target:
|
||||||
header('* Cleaning binaries')
|
header('* Cleaning binaries')
|
||||||
subprocess.run(os.path.join(os.environ['ANDROID_HOME'], 'ndk-bundle', 'ndk-build') + ' clean', shell=True)
|
subprocess.run(os.path.join(os.environ['ANDROID_HOME'], 'ndk-bundle', 'ndk-build') + ' clean', shell=True)
|
||||||
|
for arch in ['arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64']:
|
||||||
|
shutil.rmtree(os.path.join('out', arch), ignore_errors=True)
|
||||||
|
|
||||||
if 'java' in args.target:
|
if 'java' in args.target:
|
||||||
header('* Cleaning java')
|
header('* Cleaning java')
|
||||||
os.chdir('java')
|
os.chdir('java')
|
||||||
subprocess.run('{} clean'.format(os.path.join('.', 'gradlew')), shell=True)
|
subprocess.run('{} clean'.format(os.path.join('.', 'gradlew')), shell=True)
|
||||||
os.chdir('..')
|
os.chdir('..')
|
||||||
silentremove('snet.apk')
|
for f in os.listdir('out'):
|
||||||
|
if '.apk' in f:
|
||||||
|
rm(os.path.join('out', f))
|
||||||
|
|
||||||
if 'zip' in args.target:
|
if 'zip' in args.target:
|
||||||
header('* Cleaning zip files')
|
header('* Cleaning zip files')
|
||||||
for f in os.listdir('.'):
|
for f in os.listdir('out'):
|
||||||
if '.zip' in f:
|
if '.zip' in f:
|
||||||
print('rm {}'.format(f))
|
rm(os.path.join('out', f))
|
||||||
silentremove(f)
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description='Magisk build script')
|
parser = argparse.ArgumentParser(description='Magisk build script')
|
||||||
parser.add_argument('--release', action='store_true', help='compile Magisk for release')
|
parser.add_argument('--release', action='store_true', help='compile Magisk for release')
|
||||||
|
2
java
2
java
@ -1 +1 @@
|
|||||||
Subproject commit fdd700f3e5c2f9d7688d2434d4dbee8c12524411
|
Subproject commit 99c74b31be15a239fdffe4a727d2d83feb52b8bb
|
@ -14,17 +14,17 @@ LIBFDT := $(EXT_PATH)/dtc/libfdt
|
|||||||
# Binaries
|
# Binaries
|
||||||
########################
|
########################
|
||||||
|
|
||||||
|
ifdef PRECOMPILE
|
||||||
|
|
||||||
# magisk main binary
|
# magisk main binary
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
LOCAL_MODULE := magisk
|
LOCAL_MODULE := magisk
|
||||||
LOCAL_STATIC_LIBRARIES := libsepol
|
|
||||||
LOCAL_SHARED_LIBRARIES := libsqlite libselinux
|
LOCAL_SHARED_LIBRARIES := libsqlite libselinux
|
||||||
|
|
||||||
LOCAL_C_INCLUDES := \
|
LOCAL_C_INCLUDES := \
|
||||||
jni/include \
|
jni/include \
|
||||||
jni/external \
|
jni/external \
|
||||||
$(LIBSELINUX) \
|
$(LIBSELINUX)
|
||||||
$(LIBSEPOL)
|
|
||||||
|
|
||||||
LOCAL_SRC_FILES := \
|
LOCAL_SRC_FILES := \
|
||||||
daemon/magisk.c \
|
daemon/magisk.c \
|
||||||
@ -41,10 +41,6 @@ LOCAL_SRC_FILES := \
|
|||||||
magiskhide/magiskhide.c \
|
magiskhide/magiskhide.c \
|
||||||
magiskhide/proc_monitor.c \
|
magiskhide/proc_monitor.c \
|
||||||
magiskhide/hide_utils.c \
|
magiskhide/hide_utils.c \
|
||||||
magiskpolicy/magiskpolicy.c \
|
|
||||||
magiskpolicy/rules.c \
|
|
||||||
magiskpolicy/sepolicy.c \
|
|
||||||
magiskpolicy/api.c \
|
|
||||||
resetprop/resetprop.cpp \
|
resetprop/resetprop.cpp \
|
||||||
resetprop/system_properties.cpp \
|
resetprop/system_properties.cpp \
|
||||||
su/su.c \
|
su/su.c \
|
||||||
@ -59,6 +55,37 @@ LOCAL_CPPFLAGS := -std=c++11
|
|||||||
LOCAL_LDLIBS := -llog
|
LOCAL_LDLIBS := -llog
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
|
# magiskinit
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := magiskinit
|
||||||
|
LOCAL_STATIC_LIBRARIES := libsepol
|
||||||
|
LOCAL_C_INCLUDES := jni/include $(LIBSEPOL)
|
||||||
|
LOCAL_SRC_FILES := \
|
||||||
|
init/magiskinit.c \
|
||||||
|
utils/vector.c \
|
||||||
|
utils/file.c \
|
||||||
|
utils/xwrap.c \
|
||||||
|
magiskpolicy/api.c \
|
||||||
|
magiskpolicy/magiskpolicy.c \
|
||||||
|
magiskpolicy/rules.c \
|
||||||
|
magiskpolicy/sepolicy.c
|
||||||
|
|
||||||
|
LOCAL_CFLAGS := -DNO_SELINUX
|
||||||
|
LOCAL_LDFLAGS := -static
|
||||||
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
|
# precompile
|
||||||
|
else
|
||||||
|
|
||||||
|
# monogisk
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_MODULE := monogisk
|
||||||
|
LOCAL_STATIC_LIBRARIES := liblzma
|
||||||
|
LOCAL_C_INCLUDES := jni/include out/$(TARGET_ARCH_ABI) $(LIBLZMA)
|
||||||
|
LOCAL_SRC_FILES := init/monogisk.c
|
||||||
|
LOCAL_LDFLAGS := -static
|
||||||
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
# magiskboot
|
# magiskboot
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
LOCAL_MODULE := magiskboot
|
LOCAL_MODULE := magiskboot
|
||||||
@ -81,29 +108,13 @@ LOCAL_SRC_FILES := \
|
|||||||
magiskboot/types.c \
|
magiskboot/types.c \
|
||||||
magiskboot/dtb.c \
|
magiskboot/dtb.c \
|
||||||
utils/xwrap.c \
|
utils/xwrap.c \
|
||||||
|
utils/file.c \
|
||||||
utils/vector.c
|
utils/vector.c
|
||||||
|
|
||||||
|
LOCAL_CFLAGS := -DNO_SELINUX
|
||||||
LOCAL_LDLIBS := -lz
|
LOCAL_LDLIBS := -lz
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
# magiskinit
|
|
||||||
ifeq ($(TARGET_ARCH_ABI), arm64-v8a)
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
LOCAL_MODULE := magiskinit
|
|
||||||
LOCAL_STATIC_LIBRARIES := libsepol
|
|
||||||
LOCAL_C_INCLUDES := jni/include $(LIBSEPOL)
|
|
||||||
LOCAL_SRC_FILES := \
|
|
||||||
magiskinit.c \
|
|
||||||
magiskboot/boot_utils.c \
|
|
||||||
utils/file.c \
|
|
||||||
utils/xwrap.c \
|
|
||||||
magiskpolicy/rules.c \
|
|
||||||
magiskpolicy/sepolicy.c \
|
|
||||||
magiskpolicy/api.c
|
|
||||||
LOCAL_CFLAGS := -DNO_SELINUX
|
|
||||||
LOCAL_LDFLAGS := -static
|
|
||||||
include $(BUILD_EXECUTABLE)
|
|
||||||
endif
|
|
||||||
|
|
||||||
# 32-bit static binaries
|
# 32-bit static binaries
|
||||||
ifneq ($(TARGET_ARCH_ABI), x86_64)
|
ifneq ($(TARGET_ARCH_ABI), x86_64)
|
||||||
ifneq ($(TARGET_ARCH_ABI), arm64-v8a)
|
ifneq ($(TARGET_ARCH_ABI), arm64-v8a)
|
||||||
@ -120,6 +131,9 @@ include jni/external/busybox/Android.mk
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Precompile
|
||||||
|
endif
|
||||||
|
|
||||||
########################
|
########################
|
||||||
# Externals
|
# Externals
|
||||||
########################
|
########################
|
||||||
|
@ -568,7 +568,7 @@ void fix_filecon() {
|
|||||||
****************/
|
****************/
|
||||||
|
|
||||||
static void unblock_boot_process() {
|
static void unblock_boot_process() {
|
||||||
close(xopen(UNBLOCKFILE, O_RDONLY | O_CREAT));
|
close(xopen(UNBLOCKFILE, O_RDONLY | O_CREAT, 0));
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -743,7 +743,8 @@ void late_start(int client) {
|
|||||||
if (buf2 == NULL) buf2 = xmalloc(PATH_MAX);
|
if (buf2 == NULL) buf2 = xmalloc(PATH_MAX);
|
||||||
|
|
||||||
// Wait till the full patch is done
|
// Wait till the full patch is done
|
||||||
pthread_join(sepol_patch, NULL);
|
while (access(PATCHDONE, F_OK) == -1)
|
||||||
|
usleep(500); /* Wait 0.5ms */
|
||||||
|
|
||||||
// Run scripts after full patch, most reliable way to run scripts
|
// Run scripts after full patch, most reliable way to run scripts
|
||||||
LOGI("* Running service.d scripts\n");
|
LOGI("* Running service.d scripts\n");
|
||||||
|
@ -103,16 +103,6 @@ static int setup_socket(struct sockaddr_un *sun) {
|
|||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *large_sepol_patch(void *args) {
|
|
||||||
LOGD("sepol: Starting large patch thread\n");
|
|
||||||
// Patch su to everything
|
|
||||||
sepol_allow("su", ALL, ALL, ALL);
|
|
||||||
dump_policydb(SELINUX_LOAD);
|
|
||||||
LOGD("sepol: Large patch done\n");
|
|
||||||
destroy_policydb();
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *start_magisk_hide(void *args) {
|
static void *start_magisk_hide(void *args) {
|
||||||
launch_magiskhide(-1);
|
launch_magiskhide(-1);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -137,11 +127,6 @@ void start_daemon() {
|
|||||||
xdup2(fd, STDERR_FILENO);
|
xdup2(fd, STDERR_FILENO);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
// Patch selinux with medium patch before we do anything
|
|
||||||
load_policydb(SELINUX_POLICY);
|
|
||||||
sepol_med_rules();
|
|
||||||
dump_policydb(SELINUX_LOAD);
|
|
||||||
|
|
||||||
struct sockaddr_un sun;
|
struct sockaddr_un sun;
|
||||||
fd = setup_socket(&sun);
|
fd = setup_socket(&sun);
|
||||||
|
|
||||||
@ -159,9 +144,6 @@ void start_daemon() {
|
|||||||
// Start the log monitor
|
// Start the log monitor
|
||||||
monitor_logs();
|
monitor_logs();
|
||||||
|
|
||||||
// Continue the larger patch in another thread, we will join later
|
|
||||||
xpthread_create(&sepol_patch, NULL, large_sepol_patch, NULL);
|
|
||||||
|
|
||||||
LOGI("Magisk v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") daemon started\n");
|
LOGI("Magisk v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") daemon started\n");
|
||||||
|
|
||||||
// Change process name
|
// Change process name
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "magisk.h"
|
#include "magisk.h"
|
||||||
@ -12,10 +13,10 @@
|
|||||||
char *argv0;
|
char *argv0;
|
||||||
|
|
||||||
char *applet[] =
|
char *applet[] =
|
||||||
{ "su", "resetprop", "magiskpolicy", "supolicy", "magiskhide", NULL };
|
{ "su", "resetprop", "magiskhide", NULL };
|
||||||
|
|
||||||
int (*applet_main[]) (int, char *[]) =
|
int (*applet_main[]) (int, char *[]) =
|
||||||
{ su_client_main, resetprop_main, magiskpolicy_main, magiskpolicy_main, magiskhide_main, NULL };
|
{ su_client_main, resetprop_main, magiskhide_main, NULL };
|
||||||
|
|
||||||
int create_links(const char *bin, const char *path) {
|
int create_links(const char *bin, const char *path) {
|
||||||
char self[PATH_MAX], linkpath[PATH_MAX];
|
char self[PATH_MAX], linkpath[PATH_MAX];
|
||||||
@ -56,7 +57,7 @@ static void usage() {
|
|||||||
" --clone-attr SRC DEST clone permission, owner, and selinux context\n"
|
" --clone-attr SRC DEST clone permission, owner, and selinux context\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Supported init services:\n"
|
"Supported init services:\n"
|
||||||
" daemon post-fs, post-fs-data, service\n"
|
" daemon, post-fs, post-fs-data, service\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Supported applets:\n"
|
"Supported applets:\n"
|
||||||
, argv0, argv0);
|
, argv0, argv0);
|
||||||
@ -69,10 +70,7 @@ static void usage() {
|
|||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
argv0 = argv[0];
|
argv0 = argv[0];
|
||||||
char * arg = strrchr(argv[0], '/');
|
if (strcmp(basename(argv[0]), "magisk") == 0) {
|
||||||
if (arg) ++arg;
|
|
||||||
else arg = argv[0];
|
|
||||||
if (strcmp(arg, "magisk") == 0) {
|
|
||||||
if (argc < 2) usage();
|
if (argc < 2) usage();
|
||||||
if (strcmp(argv[1], "-c") == 0) {
|
if (strcmp(argv[1], "-c") == 0) {
|
||||||
printf("%s\n", MAGISK_VER_STR);
|
printf("%s\n", MAGISK_VER_STR);
|
||||||
@ -168,16 +166,15 @@ int main(int argc, char *argv[]) {
|
|||||||
// It's calling applets
|
// It's calling applets
|
||||||
--argc;
|
--argc;
|
||||||
++argv;
|
++argv;
|
||||||
arg = argv[0];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Applets
|
// Applets
|
||||||
for (int i = 0; applet[i]; ++i) {
|
for (int i = 0; applet[i]; ++i) {
|
||||||
if (strcmp(arg, applet[i]) == 0)
|
if (strcmp(basename(argv[0]), applet[i]) == 0)
|
||||||
return (*applet_main[i])(argc, argv);
|
return (*applet_main[i])(argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "%s: applet not found\n", arg);
|
fprintf(stderr, "%s: applet not found\n", basename(argv[0]));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,9 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define str(a) #a
|
||||||
|
#define xstr(a) str(a)
|
||||||
|
|
||||||
#ifdef IS_DAEMON
|
#ifdef IS_DAEMON
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
@ -6,9 +6,6 @@
|
|||||||
|
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
|
|
||||||
#define str(a) #a
|
|
||||||
#define xstr(a) str(a)
|
|
||||||
|
|
||||||
#define MAGISK_VER_STR xstr(MAGISK_VERSION) ":MAGISK"
|
#define MAGISK_VER_STR xstr(MAGISK_VERSION) ":MAGISK"
|
||||||
#define REQUESTOR_DAEMON_PATH "\0MAGISK"
|
#define REQUESTOR_DAEMON_PATH "\0MAGISK"
|
||||||
|
|
||||||
@ -20,6 +17,7 @@
|
|||||||
#define LASTLOG "/cache/last_magisk.log"
|
#define LASTLOG "/cache/last_magisk.log"
|
||||||
#define DEBUG_LOG "/data/magisk_debug.log"
|
#define DEBUG_LOG "/data/magisk_debug.log"
|
||||||
#define UNBLOCKFILE "/dev/.magisk.unblock"
|
#define UNBLOCKFILE "/dev/.magisk.unblock"
|
||||||
|
#define PATCHDONE "/dev/.magisk.patch.done"
|
||||||
#define DISABLEFILE "/cache/.disable_magisk"
|
#define DISABLEFILE "/cache/.disable_magisk"
|
||||||
#define UNINSTALLER "/cache/magisk_uninstaller.sh"
|
#define UNINSTALLER "/cache/magisk_uninstaller.sh"
|
||||||
#define CACHEMOUNT "/cache/magisk_mount"
|
#define CACHEMOUNT "/cache/magisk_mount"
|
||||||
|
45
jni/include/magiskrc.h
Normal file
45
jni/include/magiskrc.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
const char magiskrc[] =
|
||||||
|
|
||||||
|
// Triggers
|
||||||
|
|
||||||
|
"on post-fs\n"
|
||||||
|
" start logd\n"
|
||||||
|
" start magisk_daemon\n"
|
||||||
|
" wait /dev/.magisk.unblock 5\n"
|
||||||
|
" rm /dev/.magisk.unblock\n"
|
||||||
|
" start magisk_pfs\n"
|
||||||
|
" wait /dev/.magisk.unblock 10\n"
|
||||||
|
"\n"
|
||||||
|
|
||||||
|
"on post-fs-data\n"
|
||||||
|
" load_persist_props\n"
|
||||||
|
" rm /dev/.magisk.unblock\n"
|
||||||
|
" start magisk_pfsd\n"
|
||||||
|
" wait /dev/.magisk.unblock 10\n"
|
||||||
|
"\n"
|
||||||
|
|
||||||
|
// Services
|
||||||
|
|
||||||
|
"service magisk_daemon /sbin/magisk --daemon\n"
|
||||||
|
" user root\n"
|
||||||
|
" seclabel u:r:su:s0\n"
|
||||||
|
"\n"
|
||||||
|
|
||||||
|
"service magisk_pfs /sbin/magisk --post-fs\n"
|
||||||
|
" user root\n"
|
||||||
|
" seclabel u:r:su:s0\n"
|
||||||
|
" oneshot\n"
|
||||||
|
"\n"
|
||||||
|
|
||||||
|
"service magisk_pfsd /sbin/magisk --post-fs-data\n"
|
||||||
|
" user root\n"
|
||||||
|
" seclabel u:r:su:s0\n"
|
||||||
|
" oneshot\n"
|
||||||
|
"\n"
|
||||||
|
|
||||||
|
"service magisk_service /sbin/magisk --service\n"
|
||||||
|
" class late_start\n"
|
||||||
|
" user root\n"
|
||||||
|
" seclabel u:r:su:s0\n"
|
||||||
|
" oneshot\n"
|
||||||
|
;
|
@ -116,6 +116,8 @@ int fsetattr(int fd, struct file_attr *a);
|
|||||||
void fclone_attr(const int sourcefd, const int targetfd);
|
void fclone_attr(const int sourcefd, const int targetfd);
|
||||||
void clone_attr(const char *source, const char *target);
|
void clone_attr(const char *source, const char *target);
|
||||||
void restorecon(int dirfd, int force);
|
void restorecon(int dirfd, int force);
|
||||||
|
void mmap_ro(const char *filename, void **buf, size_t *size);
|
||||||
|
void mmap_rw(const char *filename, void **buf, size_t *size);
|
||||||
|
|
||||||
// img.c
|
// img.c
|
||||||
|
|
||||||
|
364
jni/init/magiskinit.c
Normal file
364
jni/init/magiskinit.c
Normal file
@ -0,0 +1,364 @@
|
|||||||
|
/* magiskinit.c - Pre-init Magisk support
|
||||||
|
*
|
||||||
|
* This code has to be compiled statically to work properly.
|
||||||
|
*
|
||||||
|
* This binary will be extracted from monogisk, and dos all pre-init operations to setup
|
||||||
|
* a Magisk environment. The tool modifies rootfs on the fly, providing fundamental support
|
||||||
|
* such as init, init.rc, and sepolicy patching. Magiskinit is also responsible to construct
|
||||||
|
* a proper rootfs on skip_initramfs devices.
|
||||||
|
* On skip_initramfs devices, it will parse kernel cmdline, mount sysfs, parse through
|
||||||
|
* uevent files to make the system (or vendor if available) block device node, then copy
|
||||||
|
* rootfs files from system. The "overlay" folder is constructed by monogisk,
|
||||||
|
* which contains additional files extracted from the tool. These files will be moved to /.
|
||||||
|
* This tool will be replaced with the real init to continue the boot process, but hardlinks are
|
||||||
|
* preserved as it also provides CLI for sepolicy patching (magiskpolicy)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/mount.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/sendfile.h>
|
||||||
|
#include <sys/sysmacros.h>
|
||||||
|
|
||||||
|
#include <cil/cil.h>
|
||||||
|
|
||||||
|
#include "magisk.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "magiskpolicy.h"
|
||||||
|
|
||||||
|
struct cmdline {
|
||||||
|
int skip_initramfs;
|
||||||
|
char slot[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct device {
|
||||||
|
dev_t major;
|
||||||
|
dev_t minor;
|
||||||
|
char devname[32];
|
||||||
|
char partname[32];
|
||||||
|
char path[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
extern policydb_t *policydb;
|
||||||
|
|
||||||
|
static void parse_cmdline(struct cmdline *cmd) {
|
||||||
|
char *tok;
|
||||||
|
char buffer[4096];
|
||||||
|
mkdir("/proc", 0555);
|
||||||
|
mount("proc", "/proc", "proc", 0, NULL);
|
||||||
|
int fd = open("/proc/cmdline", O_RDONLY | O_CLOEXEC);
|
||||||
|
ssize_t size = read(fd, buffer, sizeof(buffer));
|
||||||
|
buffer[size] = '\0';
|
||||||
|
close(fd);
|
||||||
|
umount("/proc");
|
||||||
|
tok = strtok(buffer, " ");
|
||||||
|
cmd->skip_initramfs = 0;
|
||||||
|
cmd->slot[0] = '\0';
|
||||||
|
while (tok != NULL) {
|
||||||
|
if (strncmp(tok, "androidboot.slot_suffix", 23) == 0) {
|
||||||
|
sscanf(tok, "androidboot.slot_suffix=%s", cmd->slot);
|
||||||
|
} else if (strcmp(tok, "skip_initramfs") == 0) {
|
||||||
|
cmd->skip_initramfs = 1;
|
||||||
|
}
|
||||||
|
tok = strtok(NULL, " ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void parse_device(struct device *dev, char *uevent) {
|
||||||
|
char *tok;
|
||||||
|
tok = strtok(uevent, "\n");
|
||||||
|
while (tok != NULL) {
|
||||||
|
if (strncmp(tok, "MAJOR", 5) == 0) {
|
||||||
|
sscanf(tok, "MAJOR=%ld", (long*) &dev->major);
|
||||||
|
} else if (strncmp(tok, "MINOR", 5) == 0) {
|
||||||
|
sscanf(tok, "MINOR=%ld", (long*) &dev->minor);
|
||||||
|
} else if (strncmp(tok, "DEVNAME", 7) == 0) {
|
||||||
|
sscanf(tok, "DEVNAME=%s", dev->devname);
|
||||||
|
} else if (strncmp(tok, "PARTNAME", 8) == 0) {
|
||||||
|
sscanf(tok, "PARTNAME=%s", dev->partname);
|
||||||
|
}
|
||||||
|
tok = strtok(NULL, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int setup_block(struct device *dev, const char *partname) {
|
||||||
|
char buffer[1024], path[128];
|
||||||
|
struct dirent *entry;
|
||||||
|
DIR *dir = opendir("/sys/dev/block");
|
||||||
|
if (dir == NULL)
|
||||||
|
return 1;
|
||||||
|
int found = 0;
|
||||||
|
while ((entry = readdir(dir))) {
|
||||||
|
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
||||||
|
continue;
|
||||||
|
snprintf(path, sizeof(path), "/sys/dev/block/%s/uevent", entry->d_name);
|
||||||
|
int fd = open(path, O_RDONLY | O_CLOEXEC);
|
||||||
|
ssize_t size = read(fd, buffer, sizeof(buffer));
|
||||||
|
buffer[size] = '\0';
|
||||||
|
close(fd);
|
||||||
|
parse_device(dev, buffer);
|
||||||
|
if (strcmp(dev->partname, partname) == 0) {
|
||||||
|
snprintf(dev->path, sizeof(dev->path), "/dev/block/%s", dev->devname);
|
||||||
|
found = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
mkdir("/dev", 0755);
|
||||||
|
mkdir("/dev/block", 0755);
|
||||||
|
mknod(dev->path, S_IFBLK | 0600, makedev(dev->major, dev->minor));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *patch_init_rc(char *data, uint32_t *size) {
|
||||||
|
int injected = 0;
|
||||||
|
char *new_data = malloc(*size + 23);
|
||||||
|
char *old_data = data;
|
||||||
|
uint32_t pos = 0;
|
||||||
|
|
||||||
|
for (char *tok = strsep(&old_data, "\n"); tok; tok = strsep(&old_data, "\n")) {
|
||||||
|
if (!injected && strncmp(tok, "import", 6) == 0) {
|
||||||
|
if (strstr(tok, "init.magisk.rc")) {
|
||||||
|
injected = 1;
|
||||||
|
} else {
|
||||||
|
strcpy(new_data + pos, "import /init.magisk.rc\n");
|
||||||
|
pos += 23;
|
||||||
|
injected = 1;
|
||||||
|
}
|
||||||
|
} else if (strstr(tok, "selinux.reload_policy")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Copy the line
|
||||||
|
strcpy(new_data + pos, tok);
|
||||||
|
pos += strlen(tok);
|
||||||
|
new_data[pos++] = '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
*size = pos;
|
||||||
|
return new_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void patch_ramdisk() {
|
||||||
|
void *addr;
|
||||||
|
size_t size;
|
||||||
|
mmap_rw("/init", &addr, &size);
|
||||||
|
for (int i = 0; i < size; ++i) {
|
||||||
|
if (memcmp(addr + i, "/system/etc/selinux/plat_sepolicy.cil", 37) == 0) {
|
||||||
|
memcpy(addr + i, "/system/etc/selinux/plat_sepolicy.xxx", 37);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
munmap(addr, size);
|
||||||
|
|
||||||
|
mmap_rw("/init.rc", &addr, &size);
|
||||||
|
uint32_t new_size = size;
|
||||||
|
void *init_rc = patch_init_rc(addr, &new_size);
|
||||||
|
munmap(addr, size);
|
||||||
|
|
||||||
|
int fd = open("/init.rc", O_WRONLY | O_TRUNC | O_CLOEXEC);
|
||||||
|
write(fd, init_rc, new_size);
|
||||||
|
close(fd);
|
||||||
|
free(init_rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int strend(const char *s1, const char *s2) {
|
||||||
|
int l1 = strlen(s1);
|
||||||
|
int l2 = strlen(s2);
|
||||||
|
return strcmp(s1 + l1 - l2, s2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int compile_cil() {
|
||||||
|
DIR *dir;
|
||||||
|
struct dirent *entry;
|
||||||
|
char path[128];
|
||||||
|
|
||||||
|
struct cil_db *db = NULL;
|
||||||
|
sepol_policydb_t *pdb = NULL;
|
||||||
|
void *addr;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
cil_db_init(&db);
|
||||||
|
cil_set_mls(db, 1);
|
||||||
|
cil_set_target_platform(db, SEPOL_TARGET_SELINUX);
|
||||||
|
cil_set_policy_version(db, POLICYDB_VERSION_XPERMS_IOCTL);
|
||||||
|
cil_set_attrs_expand_generated(db, 0);
|
||||||
|
|
||||||
|
// plat
|
||||||
|
mmap_ro("/system/etc/selinux/plat_sepolicy.cil", &addr, &size);
|
||||||
|
cil_add_file(db, "/system/etc/selinux/plat_sepolicy.cil", addr, size);
|
||||||
|
munmap(addr, size);
|
||||||
|
|
||||||
|
// mapping
|
||||||
|
char plat[10];
|
||||||
|
int fd = open("/vendor/etc/selinux/plat_sepolicy_vers.txt", O_RDONLY | O_CLOEXEC);
|
||||||
|
if (fd > 0) {
|
||||||
|
plat[read(fd, plat, sizeof(plat)) - 1] = '\0';
|
||||||
|
snprintf(path, sizeof(path), "/system/etc/selinux/mapping/%s.cil", plat);
|
||||||
|
mmap_ro(path, &addr, &size);
|
||||||
|
cil_add_file(db, path, addr, size);
|
||||||
|
munmap(addr, size);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
dir = opendir("/vendor/etc/selinux");
|
||||||
|
while ((entry = readdir(dir))) {
|
||||||
|
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
||||||
|
continue;
|
||||||
|
if (strend(entry->d_name, ".cil") == 0) {
|
||||||
|
snprintf(path, sizeof(path), "/vendor/etc/selinux/%s", entry->d_name);
|
||||||
|
mmap_ro(path, &addr, &size);
|
||||||
|
cil_add_file(db, path, addr, size);
|
||||||
|
munmap(addr, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
|
||||||
|
cil_compile(db);
|
||||||
|
cil_build_policydb(db, &pdb);
|
||||||
|
cil_db_destroy(&db);
|
||||||
|
|
||||||
|
policydb = &pdb->p;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int verify_precompiled() {
|
||||||
|
DIR *dir;
|
||||||
|
struct dirent *entry;
|
||||||
|
int fd;
|
||||||
|
char sys_sha[70], ven_sha[70];
|
||||||
|
|
||||||
|
dir = opendir("/vendor/etc/selinux");
|
||||||
|
while ((entry = readdir(dir))) {
|
||||||
|
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
||||||
|
continue;
|
||||||
|
if (strend(entry->d_name, ".sha256") == 0) {
|
||||||
|
fd = openat(dirfd(dir), entry->d_name, O_RDONLY | O_CLOEXEC);
|
||||||
|
ven_sha[read(fd, ven_sha, sizeof(ven_sha))] = '\0';
|
||||||
|
close(fd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
dir = opendir("/system/etc/selinux");
|
||||||
|
while ((entry = readdir(dir))) {
|
||||||
|
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
||||||
|
continue;
|
||||||
|
if (strend(entry->d_name, ".sha256") == 0) {
|
||||||
|
fd = openat(dirfd(dir), entry->d_name, O_RDONLY | O_CLOEXEC);
|
||||||
|
sys_sha[read(fd, sys_sha, sizeof(sys_sha))] = '\0';
|
||||||
|
close(fd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
return strcmp(sys_sha, ven_sha);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void patch_sepolicy() {
|
||||||
|
if (access("/sepolicy", R_OK) == 0) {
|
||||||
|
load_policydb("/sepolicy");
|
||||||
|
} else if (access("/vendor/etc/selinux/precompiled_sepolicy", R_OK) == 0
|
||||||
|
&& verify_precompiled() == 0) {
|
||||||
|
load_policydb("/vendor/etc/selinux/precompiled_sepolicy");
|
||||||
|
} else if (access("/system/etc/selinux/plat_sepolicy.cil", R_OK) == 0) {
|
||||||
|
compile_cil();
|
||||||
|
}
|
||||||
|
|
||||||
|
sepol_med_rules();
|
||||||
|
dump_policydb("/sepolicy");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
if (strcmp(basename(argv[0]), "magiskpolicy") == 0 || strcmp(basename(argv[0]), "supolicy") == 0)
|
||||||
|
return magiskpolicy_main(argc, argv);
|
||||||
|
if (argc > 1 && (strcmp(argv[1], "magiskpolicy") == 0 || strcmp(argv[1], "supolicy") == 0))
|
||||||
|
return magiskpolicy_main(argc - 1, argv + 1);
|
||||||
|
|
||||||
|
umask(0);
|
||||||
|
|
||||||
|
struct cmdline cmd;
|
||||||
|
parse_cmdline(&cmd);
|
||||||
|
|
||||||
|
int root = open("/", O_RDONLY | O_CLOEXEC);
|
||||||
|
|
||||||
|
if (cmd.skip_initramfs) {
|
||||||
|
// Exclude overlay folder
|
||||||
|
excl_list = (char *[]) { "overlay", ".backup", NULL };
|
||||||
|
// Clear rootfs
|
||||||
|
frm_rf(root);
|
||||||
|
|
||||||
|
mkdir("/sys", 0755);
|
||||||
|
mount("sysfs", "/sys", "sysfs", 0, NULL);
|
||||||
|
|
||||||
|
char partname[32];
|
||||||
|
snprintf(partname, sizeof(partname), "system%s", cmd.slot);
|
||||||
|
|
||||||
|
struct device dev;
|
||||||
|
setup_block(&dev, partname);
|
||||||
|
|
||||||
|
mkdir("/system_root", 0755);
|
||||||
|
mount(dev.path, "/system_root", "ext4", MS_RDONLY, NULL);
|
||||||
|
int system_root = open("/system_root", O_RDONLY | O_CLOEXEC);
|
||||||
|
|
||||||
|
// Exclude system folder
|
||||||
|
excl_list = (char *[]) { "system", NULL };
|
||||||
|
clone_dir(system_root, root);
|
||||||
|
mkdir("/system", 0755);
|
||||||
|
mount("/system_root/system", "/system", NULL, MS_BIND, NULL);
|
||||||
|
|
||||||
|
snprintf(partname, sizeof(partname), "vendor%s", cmd.slot);
|
||||||
|
|
||||||
|
// We need to mount independent vendor partition
|
||||||
|
if (setup_block(&dev, partname) == 0)
|
||||||
|
mount(dev.path, "/vendor", "ext4", MS_RDONLY, NULL);
|
||||||
|
|
||||||
|
close(system_root);
|
||||||
|
} else {
|
||||||
|
// Revert original init binary
|
||||||
|
unlink("/init");
|
||||||
|
link("/.backup/init", "/init");
|
||||||
|
}
|
||||||
|
|
||||||
|
int overlay = open("/overlay", O_RDONLY | O_CLOEXEC);
|
||||||
|
mv_dir(overlay, root);
|
||||||
|
|
||||||
|
patch_ramdisk();
|
||||||
|
patch_sepolicy();
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
rmdir("/overlay");
|
||||||
|
umount("/vendor");
|
||||||
|
close(overlay);
|
||||||
|
close(root);
|
||||||
|
|
||||||
|
if (fork() == 0) {
|
||||||
|
// Fork a new process for full patch
|
||||||
|
setsid();
|
||||||
|
sepol_allow("su", ALL, ALL, ALL);
|
||||||
|
while (access(SELINUX_LOAD, W_OK) == -1) {
|
||||||
|
usleep(500); /* Wait 0.5ms */
|
||||||
|
}
|
||||||
|
dump_policydb(SELINUX_LOAD);
|
||||||
|
close(open(PATCHDONE, O_RDONLY | O_CREAT, 0));
|
||||||
|
destroy_policydb();
|
||||||
|
} else {
|
||||||
|
// Finally, give control back!
|
||||||
|
execv("/init", argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
121
jni/init/monogisk.c
Normal file
121
jni/init/monogisk.c
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
/* monogisk.c - Monolithic binary hosting Magisk binaries
|
||||||
|
*
|
||||||
|
* This code has to be compiled statically to work properly.
|
||||||
|
*
|
||||||
|
* To unify Magisk support for both legacy "normal" devices and new skip_initramfs devices,
|
||||||
|
* this tool is born. Magisk binary compilation is split into two parts - first part contains
|
||||||
|
* "magisk" and "magiskinit". The python build script will load these 2 binaries and compress
|
||||||
|
* them with lzma2, dumping the results into "dump.h". Monogisk is simply just a static lzma
|
||||||
|
* extractor embedded with binary blobs, with a few additional operations to construct an
|
||||||
|
* environment for "magiskinit" to handle the rest of the work.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <lzma.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "dump.h"
|
||||||
|
#include "magiskrc.h"
|
||||||
|
|
||||||
|
#define str(a) #a
|
||||||
|
#define xstr(a) str(a)
|
||||||
|
#define BUFSIZE 0x100000
|
||||||
|
|
||||||
|
lzma_stream strm = LZMA_STREAM_INIT;
|
||||||
|
|
||||||
|
static void usage() {
|
||||||
|
const char usage[] =
|
||||||
|
"Monogisk v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") (by topjohnwu)\n"
|
||||||
|
"A monolithic binary used as /init to add Magisk support\n"
|
||||||
|
"\n"
|
||||||
|
"Usage:\n"
|
||||||
|
" monogisk -x <binary> <out>\n"
|
||||||
|
" extract \"magisk\", \"magiskinit\", or \"magiskrc\"\n"
|
||||||
|
" /init\n"
|
||||||
|
" Startup the system with Magisk support\n"
|
||||||
|
"\n";
|
||||||
|
write(STDERR_FILENO, usage, sizeof(usage));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int unxz(lzma_stream *strm, const void *buf, size_t size, int fd) {
|
||||||
|
lzma_ret ret = 0;
|
||||||
|
uint8_t out[BUFSIZE];
|
||||||
|
strm->next_in = buf;
|
||||||
|
strm->avail_in = size;
|
||||||
|
do {
|
||||||
|
strm->next_out = out;
|
||||||
|
strm->avail_out = sizeof(out);
|
||||||
|
ret = lzma_code(strm, LZMA_RUN);
|
||||||
|
write(fd, out, sizeof(out) - strm->avail_out);
|
||||||
|
} while (strm->avail_out == 0 && ret == LZMA_OK);
|
||||||
|
|
||||||
|
if (ret != LZMA_OK && ret != LZMA_STREAM_END)
|
||||||
|
write(STDERR_FILENO, "LZMA error!\n", 13);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dump_magisk(const char *path, mode_t mode) {
|
||||||
|
if (lzma_auto_decoder(&strm, UINT64_MAX, 0) != LZMA_OK)
|
||||||
|
return 1;
|
||||||
|
unlink(path);
|
||||||
|
int fd = creat(path, mode);
|
||||||
|
int ret = unxz(&strm, magisk_dump, sizeof(magisk_dump), fd);
|
||||||
|
close(fd);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dump_magiskinit(const char *path, mode_t mode) {
|
||||||
|
if (lzma_auto_decoder(&strm, UINT64_MAX, 0) != LZMA_OK)
|
||||||
|
return 1;
|
||||||
|
unlink(path);
|
||||||
|
int fd = creat(path, mode);
|
||||||
|
int ret = unxz(&strm, magiskinit_dump, sizeof(magiskinit_dump), fd);
|
||||||
|
close(fd);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dump_magiskrc(const char *path, mode_t mode) {
|
||||||
|
unlink(path);
|
||||||
|
int fd = creat(path, mode);
|
||||||
|
write(fd, magiskrc, sizeof(magiskrc));
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int init_main(int argc, char *argv[]) {
|
||||||
|
dump_magiskinit("/init", 0750);
|
||||||
|
mkdir("/overlay", 0);
|
||||||
|
dump_magiskrc("/overlay/init.magisk.rc", 0750);
|
||||||
|
mkdir("/overlay/sbin", 0755);
|
||||||
|
dump_magisk("/overlay/sbin/magisk", 0755);
|
||||||
|
mkdir("/overlay/root", 0755);
|
||||||
|
link("/init", "/overlay/root/magiskpolicy");
|
||||||
|
link("/init", "/overlay/root/supolicy");
|
||||||
|
execv("/init", argv);
|
||||||
|
return 1; /* Should not happen */
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
umask(0);
|
||||||
|
|
||||||
|
if (argc == 1)
|
||||||
|
return init_main(argc, argv);
|
||||||
|
|
||||||
|
if (argc < 4)
|
||||||
|
usage();
|
||||||
|
|
||||||
|
if (strcmp(argv[2], "magisk") == 0)
|
||||||
|
dump_magisk(argv[3], 0755);
|
||||||
|
else if (strcmp(argv[2], "magiskinit") == 0)
|
||||||
|
dump_magiskinit(argv[3], 0755);
|
||||||
|
else
|
||||||
|
usage();
|
||||||
|
|
||||||
|
lzma_end(&strm);
|
||||||
|
return 0;
|
||||||
|
}
|
@ -1,25 +1,8 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/mman.h>
|
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
void mmap_ro(const char *filename, void **buf, size_t *size) {
|
|
||||||
int fd = xopen(filename, O_RDONLY);
|
|
||||||
*size = lseek(fd, 0, SEEK_END);
|
|
||||||
lseek(fd, 0, SEEK_SET);
|
|
||||||
*buf = *size > 0 ? xmmap(NULL, *size, PROT_READ, MAP_SHARED, fd, 0) : NULL;
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void mmap_rw(const char *filename, void **buf, size_t *size) {
|
|
||||||
int fd = xopen(filename, O_RDWR);
|
|
||||||
*size = lseek(fd, 0, SEEK_END);
|
|
||||||
lseek(fd, 0, SEEK_SET);
|
|
||||||
*buf = *size > 0 ? xmmap(NULL, *size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0) : NULL;
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_zero(int fd, size_t size) {
|
void write_zero(int fd, size_t size) {
|
||||||
size_t pos = lseek(fd, 0, SEEK_CUR);
|
size_t pos = lseek(fd, 0, SEEK_CUR);
|
||||||
ftruncate(fd, pos + size);
|
ftruncate(fd, pos + size);
|
||||||
@ -51,35 +34,6 @@ int open_new(const char *filename) {
|
|||||||
return xopen(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
return xopen(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *patch_init_rc(char *data, uint32_t *size) {
|
|
||||||
int injected = 0;
|
|
||||||
char *new_data = xmalloc(*size + 23);
|
|
||||||
char *old_data = data;
|
|
||||||
uint32_t pos = 0;
|
|
||||||
|
|
||||||
for (char *tok = strsep(&old_data, "\n"); tok; tok = strsep(&old_data, "\n")) {
|
|
||||||
if (!injected && strncmp(tok, "import", 6) == 0) {
|
|
||||||
if (strstr(tok, "init.magisk.rc")) {
|
|
||||||
injected = 1;
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Inject [import /init.magisk.rc] to [init.rc]\n");
|
|
||||||
strcpy(new_data + pos, "import /init.magisk.rc\n");
|
|
||||||
pos += 23;
|
|
||||||
injected = 1;
|
|
||||||
}
|
|
||||||
} else if (strstr(tok, "selinux.reload_policy")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Copy the line
|
|
||||||
strcpy(new_data + pos, tok);
|
|
||||||
pos += strlen(tok);
|
|
||||||
new_data[pos++] = '\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
*size = pos;
|
|
||||||
return new_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
int check_verity_pattern(const char *s) {
|
int check_verity_pattern(const char *s) {
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
if (s[0] == ',') ++pos;
|
if (s[0] == ',') ++pos;
|
||||||
|
@ -186,7 +186,7 @@ static void cpio_test(struct vector *v) {
|
|||||||
int ret = STOCK_BOOT;
|
int ret = STOCK_BOOT;
|
||||||
cpio_entry *f;
|
cpio_entry *f;
|
||||||
const char *OTHER_LIST[] = { "sbin/launch_daemonsu.sh", "sbin/su", "init.xposed.rc", "boot/sbin/launch_daemonsu.sh", NULL };
|
const char *OTHER_LIST[] = { "sbin/launch_daemonsu.sh", "sbin/su", "init.xposed.rc", "boot/sbin/launch_daemonsu.sh", NULL };
|
||||||
const char *MAGISK_LIST[] = { "init.magisk.rc", "overlay/init.magisk.rc", NULL };
|
const char *MAGISK_LIST[] = { ".backup/.magisk", "init.magisk.rc", "overlay/init.magisk.rc", NULL };
|
||||||
vec_for_each(v, f) {
|
vec_for_each(v, f) {
|
||||||
for (int i = 0; OTHER_LIST[i]; ++i) {
|
for (int i = 0; OTHER_LIST[i]; ++i) {
|
||||||
if (strcmp(f->filename, OTHER_LIST[i]) == 0) {
|
if (strcmp(f->filename, OTHER_LIST[i]) == 0) {
|
||||||
@ -208,11 +208,6 @@ static void cpio_patch(struct vector *v, int keepverity, int keepforceencrypt) {
|
|||||||
cpio_entry *f;
|
cpio_entry *f;
|
||||||
int skip, write;
|
int skip, write;
|
||||||
vec_for_each(v, f) {
|
vec_for_each(v, f) {
|
||||||
if (strcmp(f->filename, "init.rc") == 0) {
|
|
||||||
void *new_data = patch_init_rc(f->data, &f->filesize);
|
|
||||||
free(f->data);
|
|
||||||
f->data = new_data;
|
|
||||||
} else {
|
|
||||||
if (!keepverity) {
|
if (!keepverity) {
|
||||||
if (strstr(f->filename, "fstab") != NULL && S_ISREG(f->mode)) {
|
if (strstr(f->filename, "fstab") != NULL && S_ISREG(f->mode)) {
|
||||||
write = 0;
|
write = 0;
|
||||||
@ -246,7 +241,6 @@ static void cpio_patch(struct vector *v, int keepverity, int keepforceencrypt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cpio_extract(const char *entry, const char *filename, struct vector *v) {
|
static void cpio_extract(const char *entry, const char *filename, struct vector *v) {
|
||||||
@ -265,19 +259,35 @@ static void cpio_extract(const char *entry, const char *filename, struct vector
|
|||||||
LOGE("Cannot find the file entry [%s]\n", entry);
|
LOGE("Cannot find the file entry [%s]\n", entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cpio_backup(const char *orig, struct vector *v) {
|
static void cpio_backup(const char *orig, const char *sha1, struct vector *v) {
|
||||||
struct vector o_body, *o = &o_body, bak;
|
struct vector o_body, *o = &o_body, bak;
|
||||||
cpio_entry *m, *n, *dir, *rem;
|
cpio_entry *m, *n, *rem, *cksm;
|
||||||
char buf[PATH_MAX];
|
char buf[PATH_MAX];
|
||||||
int res, doBak;
|
int res, doBak;
|
||||||
|
|
||||||
dir = xcalloc(sizeof(*dir), 1);
|
if (sha1) cksm = xcalloc(sizeof(*cksm), 1);
|
||||||
rem = xcalloc(sizeof(*rem), 1);
|
|
||||||
vec_init(o);
|
vec_init(o);
|
||||||
vec_init(&bak);
|
vec_init(&bak);
|
||||||
// First push back the directory and the rmlist
|
|
||||||
vec_push_back(&bak, dir);
|
m = xcalloc(sizeof(*m), 1);
|
||||||
|
m->filename = strdup(".backup");
|
||||||
|
m->namesize = strlen(m->filename) + 1;
|
||||||
|
m->mode = S_IFDIR;
|
||||||
|
vec_push_back(&bak, m);
|
||||||
|
|
||||||
|
m = xcalloc(sizeof(*m), 1);
|
||||||
|
m->filename = strdup(".backup/.magisk");
|
||||||
|
m->namesize = strlen(m->filename) + 1;
|
||||||
|
m->mode = S_IFREG;
|
||||||
|
vec_push_back(&bak, m);
|
||||||
|
|
||||||
|
rem = xcalloc(sizeof(*rem), 1);
|
||||||
|
rem->filename = strdup(".backup/.rmlist");
|
||||||
|
rem->namesize = strlen(rem->filename) + 1;
|
||||||
|
rem->mode = S_IFREG;
|
||||||
vec_push_back(&bak, rem);
|
vec_push_back(&bak, rem);
|
||||||
|
|
||||||
|
if (sha1) vec_push_back(&bak, cksm);
|
||||||
parse_cpio(orig, o);
|
parse_cpio(orig, o);
|
||||||
// Remove possible backups in original ramdisk
|
// Remove possible backups in original ramdisk
|
||||||
cpio_rm(1, ".backup", o);
|
cpio_rm(1, ".backup", o);
|
||||||
@ -287,13 +297,14 @@ static void cpio_backup(const char *orig, struct vector *v) {
|
|||||||
vec_sort(v, cpio_cmp);
|
vec_sort(v, cpio_cmp);
|
||||||
vec_sort(o, cpio_cmp);
|
vec_sort(o, cpio_cmp);
|
||||||
|
|
||||||
// Init the directory and rmlist
|
if (sha1) {
|
||||||
dir->filename = strdup(".backup");
|
fprintf(stderr, "Save SHA1: [%s] -> [.backup/.sha1]\n", sha1);
|
||||||
dir->namesize = strlen(dir->filename) + 1;
|
cksm->filename = strdup(".backup/.sha1");
|
||||||
dir->mode = S_IFDIR;
|
cksm->namesize = strlen(cksm->filename) + 1;
|
||||||
rem->filename = strdup(".backup/.rmlist");
|
cksm->mode = S_IFREG;
|
||||||
rem->namesize = strlen(rem->filename) + 1;
|
cksm->data = strdup(sha1);
|
||||||
rem->mode = S_IFREG;
|
cksm->filesize = strlen(sha1) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Start comparing
|
// Start comparing
|
||||||
size_t i = 0, j = 0;
|
size_t i = 0, j = 0;
|
||||||
@ -349,12 +360,8 @@ static void cpio_backup(const char *orig, struct vector *v) {
|
|||||||
vec_push_back(v, m);
|
vec_push_back(v, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't include if empty
|
if (rem->filesize == 0)
|
||||||
if (rem->filesize == 0) {
|
|
||||||
rem->remove = 1;
|
rem->remove = 1;
|
||||||
if (bak.size == 2)
|
|
||||||
dir->remove = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
cpio_vec_destroy(o);
|
cpio_vec_destroy(o);
|
||||||
@ -367,12 +374,14 @@ static int cpio_restore(struct vector *v) {
|
|||||||
if (strstr(f->filename, ".backup") != NULL) {
|
if (strstr(f->filename, ".backup") != NULL) {
|
||||||
ret = 0;
|
ret = 0;
|
||||||
f->remove = 1;
|
f->remove = 1;
|
||||||
if (strcmp(f->filename, ".backup") == 0) continue;
|
if (f->filename[7] == '\0') continue;
|
||||||
|
if (f->filename[8] == '.') {
|
||||||
if (strcmp(f->filename, ".backup/.rmlist") == 0) {
|
if (strcmp(f->filename, ".backup/.rmlist") == 0) {
|
||||||
for (int pos = 0; pos < f->filesize; pos += strlen(f->data + pos) + 1)
|
for (int pos = 0; pos < f->filesize; pos += strlen(f->data + pos) + 1)
|
||||||
cpio_rm(0, f->data + pos, v);
|
cpio_rm(0, f->data + pos, v);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
n = xcalloc(sizeof(*n), 1);
|
n = xcalloc(sizeof(*n), 1);
|
||||||
memcpy(n, f, sizeof(*f));
|
memcpy(n, f, sizeof(*f));
|
||||||
n->namesize -= 8;
|
n->namesize -= 8;
|
||||||
@ -380,10 +389,11 @@ static int cpio_restore(struct vector *v) {
|
|||||||
n->data = f->data;
|
n->data = f->data;
|
||||||
f->data = NULL;
|
f->data = NULL;
|
||||||
n->remove = 0;
|
n->remove = 0;
|
||||||
fprintf(stderr, "Restoring [%s] -> [%s]\n", f->filename, n->filename);
|
fprintf(stderr, "Restore [%s] -> [%s]\n", f->filename, n->filename);
|
||||||
cpio_vec_insert(v, n);
|
cpio_vec_insert(v, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Some known stuff we can remove
|
// Some known stuff we can remove
|
||||||
cpio_rm(0, "sbin/magic_mask.sh", v);
|
cpio_rm(0, "sbin/magic_mask.sh", v);
|
||||||
cpio_rm(0, "init.magisk.rc", v);
|
cpio_rm(0, "init.magisk.rc", v);
|
||||||
@ -406,6 +416,8 @@ static void cpio_stocksha1(struct vector *v) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (strcmp(f->filename, ".backup/.sha1") == 0) {
|
||||||
|
printf("%s\n", f->data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -443,7 +455,7 @@ int cpio_commands(const char *command, int argc, char *argv[]) {
|
|||||||
cmd = RESTORE;
|
cmd = RESTORE;
|
||||||
} else if (strcmp(command, "stocksha1") == 0) {
|
} else if (strcmp(command, "stocksha1") == 0) {
|
||||||
cmd = STOCKSHA1;
|
cmd = STOCKSHA1;
|
||||||
} else if (argc == 1 && strcmp(command, "backup") == 0) {
|
} else if (argc >= 1 && strcmp(command, "backup") == 0) {
|
||||||
cmd = BACKUP;
|
cmd = BACKUP;
|
||||||
} else if (argc > 0 && strcmp(command, "rm") == 0) {
|
} else if (argc > 0 && strcmp(command, "rm") == 0) {
|
||||||
cmd = RM;
|
cmd = RM;
|
||||||
@ -479,7 +491,7 @@ int cpio_commands(const char *command, int argc, char *argv[]) {
|
|||||||
cpio_stocksha1(&v);
|
cpio_stocksha1(&v);
|
||||||
return 0;
|
return 0;
|
||||||
case BACKUP:
|
case BACKUP:
|
||||||
cpio_backup(argv[0], &v);
|
cpio_backup(argv[0], argc > 1 ? argv[1] : NULL, &v);
|
||||||
case RM:
|
case RM:
|
||||||
cpio_rm(recursive, argv[0], &v);
|
cpio_rm(recursive, argv[0], &v);
|
||||||
break;
|
break;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "logging.h"
|
||||||
#include "bootimg.h"
|
#include "bootimg.h"
|
||||||
|
|
||||||
#define KERNEL_FILE "kernel"
|
#define KERNEL_FILE "kernel"
|
||||||
@ -12,9 +13,6 @@
|
|||||||
#define DTB_FILE "dtb"
|
#define DTB_FILE "dtb"
|
||||||
#define NEW_BOOT "new-boot.img"
|
#define NEW_BOOT "new-boot.img"
|
||||||
|
|
||||||
#define str(a) #a
|
|
||||||
#define xstr(a) str(a)
|
|
||||||
|
|
||||||
// Main entries
|
// Main entries
|
||||||
void unpack(const char *image);
|
void unpack(const char *image);
|
||||||
void repack(const char* orig_image, const char* out_image);
|
void repack(const char* orig_image, const char* out_image);
|
||||||
@ -36,13 +34,10 @@ long long comp(file_t type, int to, const void *from, size_t size);
|
|||||||
long long decomp(file_t type, int to, const void *from, size_t size);
|
long long decomp(file_t type, int to, const void *from, size_t size);
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
extern void mmap_ro(const char *filename, void **buf, size_t *size);
|
|
||||||
extern void mmap_rw(const char *filename, void **buf, size_t *size);
|
|
||||||
extern void write_zero(int fd, size_t size);
|
extern void write_zero(int fd, size_t size);
|
||||||
extern void mem_align(size_t *pos, size_t align);
|
extern void mem_align(size_t *pos, size_t align);
|
||||||
extern void file_align(int fd, size_t align, int out);
|
extern void file_align(int fd, size_t align, int out);
|
||||||
extern int open_new(const char *filename);
|
extern int open_new(const char *filename);
|
||||||
extern void *patch_init_rc(char *data, uint32_t *size);
|
|
||||||
extern int check_verity_pattern(const char *s);
|
extern int check_verity_pattern(const char *s);
|
||||||
extern int check_encryption_pattern(const char *s);
|
extern int check_encryption_pattern(const char *s);
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
||||||
#include "magiskboot.h"
|
#include "magiskboot.h"
|
||||||
|
#include "utils.h"
|
||||||
#include "sha1.h"
|
#include "sha1.h"
|
||||||
|
|
||||||
/********************
|
/********************
|
||||||
@ -47,8 +48,9 @@ static void usage(char *arg0) {
|
|||||||
" Return value: 0/stock 1/Magisk 2/other (e.g. phh, SuperSU)\n"
|
" Return value: 0/stock 1/Magisk 2/other (e.g. phh, SuperSU)\n"
|
||||||
" -patch <KEEPVERITY> <KEEPFORCEENCRYPT>\n"
|
" -patch <KEEPVERITY> <KEEPFORCEENCRYPT>\n"
|
||||||
" Patch cpio for Magisk. KEEP**** are true/false values\n"
|
" Patch cpio for Magisk. KEEP**** are true/false values\n"
|
||||||
" -backup <origcpio>\n"
|
" -backup <origcpio> [SHA1]\n"
|
||||||
" Create ramdisk backups into <incpio> from <origcpio>\n"
|
" Create ramdisk backups into <incpio> from <origcpio>\n"
|
||||||
|
" SHA1 of stock boot image is optional\n"
|
||||||
" -restore\n"
|
" -restore\n"
|
||||||
" Restore ramdisk from ramdisk backup within <incpio>\n"
|
" Restore ramdisk from ramdisk backup within <incpio>\n"
|
||||||
" -stocksha1\n"
|
" -stocksha1\n"
|
||||||
|
311
jni/magiskinit.c
311
jni/magiskinit.c
@ -1,311 +0,0 @@
|
|||||||
/* magiskinit.c - Workaround for skip_initramfs devices
|
|
||||||
*
|
|
||||||
* This code has to be compiled statically to work properly.
|
|
||||||
*
|
|
||||||
* Magiskinit will mount sysfs, parse through uevent files to make the system block device,
|
|
||||||
* then it'll mount the system partition and clone rootfs except files under /system.
|
|
||||||
* Folders placed in "overlay" will then be overlayed to the root.
|
|
||||||
* Lastly, before giving control back to the real init, it'll patch the root files,
|
|
||||||
* extract (or compile if needed) sepolicy and patch it to load Magisk.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/mount.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <sys/sendfile.h>
|
|
||||||
#include <sys/sysmacros.h>
|
|
||||||
|
|
||||||
#include <cil/cil.h>
|
|
||||||
|
|
||||||
#include "utils.h"
|
|
||||||
#include "magiskpolicy.h"
|
|
||||||
|
|
||||||
struct cmdline {
|
|
||||||
int skip_initramfs;
|
|
||||||
char slot[3];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct device {
|
|
||||||
dev_t major;
|
|
||||||
dev_t minor;
|
|
||||||
char devname[32];
|
|
||||||
char partname[32];
|
|
||||||
char path[64];
|
|
||||||
};
|
|
||||||
|
|
||||||
extern policydb_t *policydb;
|
|
||||||
|
|
||||||
extern void mmap_ro(const char *filename, void **buf, size_t *size);
|
|
||||||
extern void mmap_rw(const char *filename, void **buf, size_t *size);
|
|
||||||
extern void *patch_init_rc(char *data, uint32_t *size);
|
|
||||||
|
|
||||||
static void parse_cmdline(struct cmdline *cmd) {
|
|
||||||
char *tok;
|
|
||||||
char buffer[4096];
|
|
||||||
mkdir("/proc", 0555);
|
|
||||||
mount("proc", "/proc", "proc", 0, NULL);
|
|
||||||
int fd = open("/proc/cmdline", O_RDONLY | O_CLOEXEC);
|
|
||||||
ssize_t size = read(fd, buffer, sizeof(buffer));
|
|
||||||
buffer[size] = '\0';
|
|
||||||
close(fd);
|
|
||||||
umount("/proc");
|
|
||||||
tok = strtok(buffer, " ");
|
|
||||||
cmd->skip_initramfs = 0;
|
|
||||||
cmd->slot[0] = '\0';
|
|
||||||
while (tok != NULL) {
|
|
||||||
if (strncmp(tok, "androidboot.slot_suffix", 23) == 0) {
|
|
||||||
sscanf(tok, "androidboot.slot_suffix=%s", cmd->slot);
|
|
||||||
} else if (strcmp(tok, "skip_initramfs") == 0) {
|
|
||||||
cmd->skip_initramfs = 1;
|
|
||||||
}
|
|
||||||
tok = strtok(NULL, " ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void parse_device(struct device *dev, char *uevent) {
|
|
||||||
char *tok;
|
|
||||||
tok = strtok(uevent, "\n");
|
|
||||||
while (tok != NULL) {
|
|
||||||
if (strncmp(tok, "MAJOR", 5) == 0) {
|
|
||||||
sscanf(tok, "MAJOR=%ld", (long*) &dev->major);
|
|
||||||
} else if (strncmp(tok, "MINOR", 5) == 0) {
|
|
||||||
sscanf(tok, "MINOR=%ld", (long*) &dev->minor);
|
|
||||||
} else if (strncmp(tok, "DEVNAME", 7) == 0) {
|
|
||||||
sscanf(tok, "DEVNAME=%s", dev->devname);
|
|
||||||
} else if (strncmp(tok, "PARTNAME", 8) == 0) {
|
|
||||||
sscanf(tok, "PARTNAME=%s", dev->partname);
|
|
||||||
}
|
|
||||||
tok = strtok(NULL, "\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int setup_block(struct device *dev, const char *partname) {
|
|
||||||
char buffer[1024], path[128];
|
|
||||||
struct dirent *entry;
|
|
||||||
DIR *dir = opendir("/sys/dev/block");
|
|
||||||
if (dir == NULL)
|
|
||||||
return 1;
|
|
||||||
int found = 0;
|
|
||||||
while ((entry = readdir(dir))) {
|
|
||||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
|
||||||
continue;
|
|
||||||
snprintf(path, sizeof(path), "/sys/dev/block/%s/uevent", entry->d_name);
|
|
||||||
int fd = open(path, O_RDONLY | O_CLOEXEC);
|
|
||||||
ssize_t size = read(fd, buffer, sizeof(buffer));
|
|
||||||
buffer[size] = '\0';
|
|
||||||
close(fd);
|
|
||||||
parse_device(dev, buffer);
|
|
||||||
if (strcmp(dev->partname, partname) == 0) {
|
|
||||||
snprintf(dev->path, sizeof(dev->path), "/dev/block/%s", dev->devname);
|
|
||||||
found = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
closedir(dir);
|
|
||||||
|
|
||||||
if (!found)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
mkdir("/dev", 0755);
|
|
||||||
mkdir("/dev/block", 0755);
|
|
||||||
mknod(dev->path, S_IFBLK | 0600, makedev(dev->major, dev->minor));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void patch_ramdisk() {
|
|
||||||
void *addr;
|
|
||||||
size_t size;
|
|
||||||
mmap_rw("/init", &addr, &size);
|
|
||||||
for (int i = 0; i < size; ++i) {
|
|
||||||
if (memcmp(addr + i, "/system/etc/selinux/plat_sepolicy.cil", 37) == 0) {
|
|
||||||
memcpy(addr + i, "/system/etc/selinux/plat_sepolicy.xxx", 37);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
munmap(addr, size);
|
|
||||||
mmap_rw("/init.rc", &addr, &size);
|
|
||||||
uint32_t new_size = size;
|
|
||||||
void *init_rc = patch_init_rc(addr, &new_size);
|
|
||||||
munmap(addr, size);
|
|
||||||
int fd = open("/init.rc", O_WRONLY | O_TRUNC | O_CLOEXEC);
|
|
||||||
write(fd, init_rc, new_size);
|
|
||||||
close(fd);
|
|
||||||
free(init_rc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int strend(const char *s1, const char *s2) {
|
|
||||||
int l1 = strlen(s1);
|
|
||||||
int l2 = strlen(s2);
|
|
||||||
return strcmp(s1 + l1 - l2, s2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void patch_sepolicy() {
|
|
||||||
DIR *dir;
|
|
||||||
struct dirent *entry;
|
|
||||||
char *sepolicy = NULL, path[128];
|
|
||||||
if (access("/system_root/sepolicy", R_OK) == 0)
|
|
||||||
sepolicy = "/system_root/sepolicy";
|
|
||||||
if (sepolicy == NULL && access("/vendor/etc/selinux/precompiled_sepolicy", R_OK) == 0) {
|
|
||||||
void *sys_sha = NULL, *ven_sha = NULL;
|
|
||||||
size_t sys_size = 0, ven_size = 0;
|
|
||||||
if ((dir = opendir("/vendor/etc/selinux")) == NULL)
|
|
||||||
goto check_done;
|
|
||||||
while ((entry = readdir(dir))) {
|
|
||||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
|
||||||
continue;
|
|
||||||
if (strend(entry->d_name, ".sha256") == 0) {
|
|
||||||
snprintf(path, sizeof(path), "/vendor/etc/selinux/%s", entry->d_name);
|
|
||||||
mmap_ro(path, &ven_sha, &ven_size);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
closedir(dir);
|
|
||||||
if ((dir = opendir("/system/etc/selinux")) == NULL)
|
|
||||||
goto check_done;
|
|
||||||
while ((entry = readdir(dir))) {
|
|
||||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
|
||||||
continue;
|
|
||||||
if (strend(entry->d_name, ".sha256") == 0) {
|
|
||||||
snprintf(path, sizeof(path), "/system/etc/selinux/%s", entry->d_name);
|
|
||||||
mmap_ro(path, &sys_sha, &sys_size);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
closedir(dir);
|
|
||||||
if (sys_size == ven_size && memcmp(sys_sha, ven_sha, sys_size) == 0)
|
|
||||||
sepolicy = "/vendor/etc/selinux/precompiled_sepolicy";
|
|
||||||
munmap(sys_sha, sys_size);
|
|
||||||
munmap(ven_sha, ven_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
check_done:
|
|
||||||
|
|
||||||
if (sepolicy) {
|
|
||||||
load_policydb(sepolicy);
|
|
||||||
} else {
|
|
||||||
// Compile cil
|
|
||||||
struct cil_db *db = NULL;
|
|
||||||
sepol_policydb_t *pdb = NULL;
|
|
||||||
void *addr;
|
|
||||||
size_t size;
|
|
||||||
|
|
||||||
cil_db_init(&db);
|
|
||||||
cil_set_mls(db, 1);
|
|
||||||
cil_set_target_platform(db, SEPOL_TARGET_SELINUX);
|
|
||||||
cil_set_policy_version(db, POLICYDB_VERSION_XPERMS_IOCTL);
|
|
||||||
cil_set_attrs_expand_generated(db, 0);
|
|
||||||
|
|
||||||
mmap_ro("/system/etc/selinux/plat_sepolicy.cil", &addr, &size);
|
|
||||||
cil_add_file(db, "/system/etc/selinux/plat_sepolicy.cil", addr, size);
|
|
||||||
munmap(addr, size);
|
|
||||||
|
|
||||||
dir = opendir("/system/etc/selinux/mapping");
|
|
||||||
while ((entry = readdir(dir))) {
|
|
||||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
|
||||||
continue;
|
|
||||||
if (strend(entry->d_name, ".cil") == 0) {
|
|
||||||
snprintf(path, sizeof(path), "/system/etc/selinux/mapping/%s", entry->d_name);
|
|
||||||
mmap_ro(path, &addr, &size);
|
|
||||||
cil_add_file(db, path, addr, size);
|
|
||||||
munmap(addr, size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
closedir(dir);
|
|
||||||
|
|
||||||
dir = opendir("/vendor/etc/selinux");
|
|
||||||
while ((entry = readdir(dir))) {
|
|
||||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
|
||||||
continue;
|
|
||||||
if (strend(entry->d_name, ".cil") == 0) {
|
|
||||||
snprintf(path, sizeof(path), "/vendor/etc/selinux/%s", entry->d_name);
|
|
||||||
mmap_ro(path, &addr, &size);
|
|
||||||
cil_add_file(db, path, addr, size);
|
|
||||||
munmap(addr, size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
closedir(dir);
|
|
||||||
|
|
||||||
cil_compile(db);
|
|
||||||
cil_build_policydb(db, &pdb);
|
|
||||||
cil_db_destroy(&db);
|
|
||||||
|
|
||||||
policydb = &pdb->p;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Magisk patches
|
|
||||||
sepol_min_rules();
|
|
||||||
dump_policydb("/sepolicy");
|
|
||||||
destroy_policydb();
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
umask(0);
|
|
||||||
|
|
||||||
struct cmdline cmd;
|
|
||||||
parse_cmdline(&cmd);
|
|
||||||
|
|
||||||
if (cmd.skip_initramfs) {
|
|
||||||
// Normal boot mode
|
|
||||||
// Clear rootfs
|
|
||||||
int root = open("/", O_RDONLY | O_CLOEXEC);
|
|
||||||
|
|
||||||
// Exclude overlay folder
|
|
||||||
excl_list = (char *[]) { "overlay", NULL };
|
|
||||||
frm_rf(root);
|
|
||||||
|
|
||||||
mkdir("/sys", 0755);
|
|
||||||
mount("sysfs", "/sys", "sysfs", 0, NULL);
|
|
||||||
|
|
||||||
char partname[32];
|
|
||||||
snprintf(partname, sizeof(partname), "system%s", cmd.slot);
|
|
||||||
|
|
||||||
struct device dev;
|
|
||||||
setup_block(&dev, partname);
|
|
||||||
|
|
||||||
mkdir("/system_root", 0755);
|
|
||||||
mount(dev.path, "/system_root", "ext4", MS_RDONLY, NULL);
|
|
||||||
int system_root = open("/system_root", O_RDONLY | O_CLOEXEC);
|
|
||||||
|
|
||||||
// Exclude system folder
|
|
||||||
excl_list = (char *[]) { "system", NULL };
|
|
||||||
clone_dir(system_root, root);
|
|
||||||
mkdir("/system", 0755);
|
|
||||||
mount("/system_root/system", "/system", NULL, MS_BIND, NULL);
|
|
||||||
|
|
||||||
int overlay = open("/overlay", O_RDONLY | O_CLOEXEC);
|
|
||||||
if (overlay > 0)
|
|
||||||
mv_dir(overlay, root);
|
|
||||||
|
|
||||||
snprintf(partname, sizeof(partname), "vendor%s", cmd.slot);
|
|
||||||
|
|
||||||
// We need to mount independent vendor partition
|
|
||||||
if (setup_block(&dev, partname) == 0)
|
|
||||||
mount(dev.path, "/vendor", "ext4", MS_RDONLY, NULL);
|
|
||||||
|
|
||||||
patch_ramdisk();
|
|
||||||
patch_sepolicy();
|
|
||||||
|
|
||||||
close(root);
|
|
||||||
close(system_root);
|
|
||||||
close(overlay);
|
|
||||||
rmdir("/overlay");
|
|
||||||
umount("/vendor");
|
|
||||||
} else {
|
|
||||||
// Recovery mode
|
|
||||||
// Revert original init binary
|
|
||||||
unlink("/init");
|
|
||||||
rename("/.backup/init", "/init");
|
|
||||||
}
|
|
||||||
|
|
||||||
execv("/init", argv);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1 +1 @@
|
|||||||
Subproject commit 3c6a170138cacb1f817c65181bd6e3ef15cfca9e
|
Subproject commit 9e96824161ddf1d6af516f44cad4d0e904a7abed
|
@ -5,6 +5,7 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/sendfile.h>
|
#include <sys/sendfile.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
#ifndef NO_SELINUX
|
#ifndef NO_SELINUX
|
||||||
#include <selinux/selinux.h>
|
#include <selinux/selinux.h>
|
||||||
@ -52,6 +53,8 @@ int mkdir_p(const char *pathname, mode_t mode) {
|
|||||||
|
|
||||||
void rm_rf(const char *path) {
|
void rm_rf(const char *path) {
|
||||||
int fd = xopen(path, O_RDONLY | O_CLOEXEC);
|
int fd = xopen(path, O_RDONLY | O_CLOEXEC);
|
||||||
|
if (fd < 0)
|
||||||
|
return;
|
||||||
frm_rf(fd);
|
frm_rf(fd);
|
||||||
close(fd);
|
close(fd);
|
||||||
rmdir(path);
|
rmdir(path);
|
||||||
@ -294,6 +297,22 @@ void fclone_attr(const int sourcefd, const int targetfd) {
|
|||||||
fsetattr(targetfd, &a);
|
fsetattr(targetfd, &a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mmap_ro(const char *filename, void **buf, size_t *size) {
|
||||||
|
int fd = xopen(filename, O_RDONLY);
|
||||||
|
*size = lseek(fd, 0, SEEK_END);
|
||||||
|
lseek(fd, 0, SEEK_SET);
|
||||||
|
*buf = *size > 0 ? xmmap(NULL, *size, PROT_READ, MAP_SHARED, fd, 0) : NULL;
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mmap_rw(const char *filename, void **buf, size_t *size) {
|
||||||
|
int fd = xopen(filename, O_RDWR);
|
||||||
|
*size = lseek(fd, 0, SEEK_END);
|
||||||
|
lseek(fd, 0, SEEK_SET);
|
||||||
|
*buf = *size > 0 ? xmmap(NULL, *size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0) : NULL;
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef NO_SELINUX
|
#ifndef NO_SELINUX
|
||||||
|
|
||||||
#define UNLABEL_CON "u:object_r:unlabeled:s0"
|
#define UNLABEL_CON "u:object_r:unlabeled:s0"
|
||||||
|
@ -11,18 +11,15 @@
|
|||||||
# boot_patch.sh script A script to patch boot. Expect path to boot image as parameter.
|
# boot_patch.sh script A script to patch boot. Expect path to boot image as parameter.
|
||||||
# (this file) The script will use binaries and files in its same directory
|
# (this file) The script will use binaries and files in its same directory
|
||||||
# to complete the patching process
|
# to complete the patching process
|
||||||
# magisk binary The main binary for all Magisk operations.
|
# monogisk binary The monolithic binary to replace /init
|
||||||
# It is also used to patch the sepolicy in the ramdisk.
|
|
||||||
# magiskboot binary A tool to unpack boot image, decompress ramdisk, extract ramdisk
|
# magiskboot binary A tool to unpack boot image, decompress ramdisk, extract ramdisk
|
||||||
# , and patch the ramdisk for Magisk support
|
# , and patch the ramdisk for Magisk support
|
||||||
# init.magisk.rc script A new line will be added to init.rc to import this script.
|
|
||||||
# All magisk entrypoints are defined here
|
|
||||||
# chromeos folder This folder should store all the utilities and keys to sign
|
# chromeos folder This folder should store all the utilities and keys to sign
|
||||||
# (optional) a chromeos device, used in the tablet Pixel C
|
# (optional) a chromeos device, used in the tablet Pixel C
|
||||||
#
|
#
|
||||||
# If the script is not running as root, then the input boot image should be a stock image
|
# If the script is not running as root, then the input boot image should be a stock image
|
||||||
# or have a backup included in ramdisk internally, since we cannot access the stock boot
|
# or have a backup included in ramdisk internally, since we cannot access the stock boot
|
||||||
# image placed under /data we've created when previously installing
|
# image placed under /data we've created when previously installed
|
||||||
#
|
#
|
||||||
##########################################################################################
|
##########################################################################################
|
||||||
##########################################################################################
|
##########################################################################################
|
||||||
@ -47,21 +44,6 @@ basename_wrap() {
|
|||||||
echo ${1##*/}
|
echo ${1##*/}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --cpio-add <incpio> <mode> <entry> <infile>
|
|
||||||
cpio_add() {
|
|
||||||
./magiskboot --cpio-add ramdisk.cpio $1 $2 $3
|
|
||||||
}
|
|
||||||
|
|
||||||
# --cpio-extract <incpio> <entry> <outfile>
|
|
||||||
cpio_extract() {
|
|
||||||
./magiskboot --cpio-extract ramdisk.cpio $1 $2
|
|
||||||
}
|
|
||||||
|
|
||||||
# --cpio-mkdir <incpio> <mode> <entry>
|
|
||||||
cpio_mkdir() {
|
|
||||||
./magiskboot --cpio-mkdir ramdisk.cpio $1 $2
|
|
||||||
}
|
|
||||||
|
|
||||||
##########################################################################################
|
##########################################################################################
|
||||||
# Initialization
|
# Initialization
|
||||||
##########################################################################################
|
##########################################################################################
|
||||||
@ -85,6 +67,9 @@ BOOTIMAGE="$1"
|
|||||||
|
|
||||||
chmod -R 755 .
|
chmod -R 755 .
|
||||||
|
|
||||||
|
# Extract magisk if doesn't exist
|
||||||
|
[ -e magisk ] || ./monogisk -x magisk magisk
|
||||||
|
|
||||||
##########################################################################################
|
##########################################################################################
|
||||||
# Unpack
|
# Unpack
|
||||||
##########################################################################################
|
##########################################################################################
|
||||||
@ -172,33 +157,11 @@ esac
|
|||||||
|
|
||||||
ui_print "- Patching ramdisk"
|
ui_print "- Patching ramdisk"
|
||||||
|
|
||||||
if [ ! -z $SHA1 ]; then
|
./magiskboot --cpio-add ramdisk.cpio 750 init monogisk
|
||||||
cp init.magisk.rc init.magisk.rc.bak
|
./magiskboot --cpio-patch ramdisk.cpio $KEEPVERITY $KEEPFORCEENCRYPT
|
||||||
echo "# STOCKSHA1=$SHA1" >> init.magisk.rc
|
|
||||||
fi
|
|
||||||
|
|
||||||
if $SKIP_INITRAMFS; then
|
|
||||||
cpio_add 750 init magiskinit
|
|
||||||
cpio_mkdir 000 overlay
|
|
||||||
cpio_add 750 overlay/init.magisk.rc init.magisk.rc
|
|
||||||
cpio_mkdir 750 overlay/sbin
|
|
||||||
cpio_add 755 overlay/sbin/magisk magisk
|
|
||||||
else
|
|
||||||
./magiskboot --cpio-patch ramdisk.cpio $KEEPVERITY $KEEPFORCEENCRYPT
|
|
||||||
|
|
||||||
cpio_extract sepolicy sepolicy
|
|
||||||
./magisk magiskpolicy --load sepolicy --save sepolicy --minimal
|
|
||||||
cpio_add 644 sepolicy sepolicy
|
|
||||||
rm -f sepolicy
|
|
||||||
|
|
||||||
cpio_add 750 init.magisk.rc init.magisk.rc
|
|
||||||
cpio_add 755 sbin/magisk magisk
|
|
||||||
fi
|
|
||||||
|
|
||||||
mv init.magisk.rc.bak init.magisk.rc 2>/dev/null
|
|
||||||
|
|
||||||
# Create ramdisk backups
|
# Create ramdisk backups
|
||||||
./magiskboot --cpio-backup ramdisk.cpio ramdisk.cpio.orig
|
./magiskboot --cpio-backup ramdisk.cpio ramdisk.cpio.orig $SHA1
|
||||||
|
|
||||||
if ! $KEEPVERITY && [ -f dtb ]; then
|
if ! $KEEPVERITY && [ -f dtb ]; then
|
||||||
./magiskboot --dtb-patch dtb && ui_print "- Patching fstab in dtb to remove dm-verity"
|
./magiskboot --dtb-patch dtb && ui_print "- Patching fstab in dtb to remove dm-verity"
|
||||||
@ -218,7 +181,7 @@ rm -f ramdisk.cpio.orig
|
|||||||
A1020054011440B93FA00F7140020054010840B93FA00F71E0010054001840B91FA00F7181010054
|
A1020054011440B93FA00F7140020054010840B93FA00F71E0010054001840B91FA00F7181010054
|
||||||
|
|
||||||
# skip_initramfs -> want_initramfs
|
# skip_initramfs -> want_initramfs
|
||||||
$SKIP_INITRAMFS && ./magiskboot --hexpatch kernel \
|
./magiskboot --hexpatch kernel \
|
||||||
736B69705F696E697472616D6673 \
|
736B69705F696E697472616D6673 \
|
||||||
77616E745F696E697472616D6673
|
77616E745F696E697472616D6673
|
||||||
|
|
||||||
|
@ -79,18 +79,12 @@ ui_print "- Constructing environment"
|
|||||||
|
|
||||||
is_mounted /data && MAGISKBIN=/data/magisk || MAGISKBIN=/cache/data_bin
|
is_mounted /data && MAGISKBIN=/data/magisk || MAGISKBIN=/cache/data_bin
|
||||||
|
|
||||||
if $BOOTMODE; then
|
|
||||||
# Cleanup binary mirrors
|
|
||||||
umount -l /dev/magisk/mirror/bin 2>/dev/null
|
|
||||||
rm -rf /dev/magisk/mirror/bin 2>/dev/null
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Save our stock boot image dump before removing it
|
# Save our stock boot image dump before removing it
|
||||||
mv /data/magisk/stock_boot* /data 2>/dev/null
|
mv /data/magisk/stock_boot* /data 2>/dev/null
|
||||||
|
|
||||||
# Copy required files
|
# Copy required files
|
||||||
rm -rf $MAGISKBIN 2>/dev/null
|
rm -rf $MAGISKBIN/* 2>/dev/null
|
||||||
mkdir -p $MAGISKBIN
|
mkdir -p $MAGISKBIN 2>/dev/null
|
||||||
cp -af $BINDIR/. $COMMONDIR/. $CHROMEDIR $TMPDIR/bin/busybox $MAGISKBIN
|
cp -af $BINDIR/. $COMMONDIR/. $CHROMEDIR $TMPDIR/bin/busybox $MAGISKBIN
|
||||||
chmod -R 755 $MAGISKBIN
|
chmod -R 755 $MAGISKBIN
|
||||||
|
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
# Triggers
|
|
||||||
|
|
||||||
on post-fs
|
|
||||||
start logd
|
|
||||||
start magisk_daemon
|
|
||||||
wait /dev/.magisk.unblock 5
|
|
||||||
rm /dev/.magisk.unblock
|
|
||||||
start magisk_pfs
|
|
||||||
wait /dev/.magisk.unblock 10
|
|
||||||
|
|
||||||
on post-fs-data
|
|
||||||
load_persist_props
|
|
||||||
rm /dev/.magisk.unblock
|
|
||||||
start magisk_pfsd
|
|
||||||
wait /dev/.magisk.unblock 10
|
|
||||||
|
|
||||||
# Services
|
|
||||||
|
|
||||||
# Self recoverable service
|
|
||||||
service magisk_daemon /sbin/magisk --daemon
|
|
||||||
user root
|
|
||||||
seclabel u:r:su:s0
|
|
||||||
|
|
||||||
# launch post-fs script
|
|
||||||
service magisk_pfs /sbin/magisk --post-fs
|
|
||||||
user root
|
|
||||||
seclabel u:r:su:s0
|
|
||||||
oneshot
|
|
||||||
|
|
||||||
# launch post-fs-data script
|
|
||||||
service magisk_pfsd /sbin/magisk --post-fs-data
|
|
||||||
user root
|
|
||||||
seclabel u:r:su:s0
|
|
||||||
oneshot
|
|
||||||
|
|
||||||
# launch late_start script
|
|
||||||
service magisk_service /sbin/magisk --service
|
|
||||||
class late_start
|
|
||||||
user root
|
|
||||||
seclabel u:r:su:s0
|
|
||||||
oneshot
|
|
Loading…
x
Reference in New Issue
Block a user