Compare commits

...

574 Commits
v8 ... v16.2

Author SHA1 Message Date
topjohnwu
e8a44646b8 Update Magisk Manager 2018-03-18 12:34:07 +08:00
topjohnwu
ae97d011ae Change MagiskHide state if logd is disabled 2018-03-18 12:17:10 +08:00
imswebra
1b7657a374 tips.md Grammar Fix 2018-03-18 12:16:57 +08:00
topjohnwu
5665e04014 Force using system binaries 2018-03-17 21:42:42 +08:00
topjohnwu
bb70385a42 Update Magisk Manager 2018-03-11 08:37:13 +08:00
topjohnwu
9855877b03 Update rules for Android P 2018-03-11 08:36:20 +08:00
topjohnwu
76c9188fae Android P renamed nonplat_properties 2018-03-11 02:53:57 +08:00
topjohnwu
e4e5269836 Android P have no make_ext4fs, use mke2fs as fallback 2018-03-11 02:52:24 +08:00
topjohnwu
9e737df534 Update high compression mode detection logic 2018-03-10 15:55:55 +08:00
Shaka Huang
0b3192c4d5 Check dtb even if kernel is not available
By the flow of unpacking boot image of Chrome OS there will be no kernel file but an dtb image. In that case the dtb image won’t be added when repacking boot image.

Signed-off-by: Shaka Huang <shakalaca@gmail.com>
2018-03-03 20:57:55 +08:00
Shaka Huang
968e6237bd Fix error parsing MTK boot.img
Should be copy & paste error:

1. boot->r_fmt should be re-checked instead of boot->k_fmt once MTK header was found in ramdisk.

2. ramdisk_size should be restored instead of kernel_size when uncompressed ramdisk was found.

3. Correct header of ramdisk

Signed-off-by: Shaka Huang <shakalaca@gmail.com>
2018-03-03 20:57:37 +08:00
worstperson
d780b5a0e4 Add support for the Nook Tablet, Acclaim
Also changed occurences of NOOK with NOOKHD
2018-03-03 20:55:44 +08:00
worstperson
3e48427eaf Add support for the new NOOK_MAGIC
The new cmdline value that's been in use since Marshmallow
2018-03-03 20:55:44 +08:00
worstperson
31360c34ed Set NOOK_PRE_HEADER_SZ from 0xFFFFF to 0x100000
All applicable Nook HD/HD+ roms are using this offset
2018-03-03 20:55:44 +08:00
topjohnwu
e9624e2304 Update submodules 2018-02-22 02:49:54 +08:00
topjohnwu
9c6e64f47d Workaround compiler optimization bug 2018-02-21 14:44:24 +08:00
topjohnwu
0afa601551 Fix F2FS manager crashing 2018-02-20 05:15:06 +08:00
topjohnwu
a94fa81195 Support non skip_initramfs device with slot suffix 2018-02-14 00:57:52 +08:00
topjohnwu
6119c24720 Bump Magisk Manager version 2018-02-13 08:04:47 +08:00
topjohnwu
7da205f4c8 Round sizes to nearest integer 2018-02-12 04:56:50 +08:00
topjohnwu
754fafcfe9 Check logd before logging 2018-02-12 02:48:15 +08:00
topjohnwu
bd7766b17e Prevent small memory leak 2018-02-11 21:55:57 +08:00
Andrew Gunnerson
70b7d73453 utils/cpio.c: Fix off-by-one error in cpio_vec_insert
Previously, if `cpio_vec_insert()` needed to replace a file and the file
already exists as the first entry, then a duplicate entry would get
created.

This fixes the bug I reported at:
https://forum.xda-developers.com/showpost.php?p=75449768&postcount=22647

Signed-off-by: Andrew Gunnerson <andrewgunnerson@gmail.com>
2018-02-11 18:50:42 +08:00
Andrew Gunnerson
5ad4702a5b utils/file.c: NULL terminate all files read into memory
Some functions, like `patch_init_rc()`, treat buffers read into memory
as a string instead of a byte buffer. Since the buffers weren't
NULL-terminated, this resulted in out-of-bounds reads and caused crashes
in certain conditions.

THis commit updates fd_full_read() to always NULL-terminate the buffers
so that they can be treated as strings when working with text files.

Signed-off-by: Andrew Gunnerson <andrewgunnerson@gmail.com>
2018-02-11 18:50:42 +08:00
topjohnwu
40b6fe03c2 Tweak enum 2018-02-11 18:50:42 +08:00
topjohnwu
49ecba2476 Obfuscate filenames to prevent detection
Because why not
2018-02-11 04:04:47 +08:00
topjohnwu
ebd509d92d Obfuscate socket name to prevent detection
Because why not
2018-02-11 03:59:54 +08:00
topjohnwu
7193374a7e Better Windows support 2018-02-10 19:54:58 +08:00
topjohnwu
6728445542 Support separate ramdisk images 2018-02-10 03:34:13 +08:00
topjohnwu
10ed299c78 Detect recovery on FBE devices with no DE access 2018-02-10 03:31:00 +08:00
topjohnwu
32b124913e Change busybox config 2018-02-06 05:52:25 +08:00
topjohnwu
599ae95251 Support moving files across filesystems 2018-02-02 04:47:16 +08:00
topjohnwu
d1be34c34a Support sepolicy_debug 2018-02-02 04:17:13 +08:00
topjohnwu
bc2cac90fe Hardlink files recursively 2018-02-02 03:22:38 +08:00
topjohnwu
28350e3ad9 Support Nook Green Loader 2018-01-30 05:56:59 +08:00
topjohnwu
f48e6c93b8 Support Tegra blobs 2018-01-30 05:20:18 +08:00
topjohnwu
7cfc24d68f Add DHTB header support 2018-01-29 22:16:02 +08:00
topjohnwu
a58d3ea04d Use libmincrypt 2018-01-29 15:34:05 +08:00
topjohnwu
dfee9954e0 Small refactor of magiskboot 2018-01-29 03:12:35 +08:00
topjohnwu
eed86c760f Add support to PXA devices
Close #340
2018-01-29 02:44:30 +08:00
topjohnwu
c471bb6f67 Update external sources 2018-01-29 02:41:39 +08:00
topjohnwu
518c2b0f95 Update README 2018-01-28 04:44:46 +08:00
topjohnwu
328fc44194 Rename module core to native 2018-01-27 09:11:28 +08:00
topjohnwu
b6f735a8f6 Rename module 2018-01-27 08:34:40 +08:00
topjohnwu
deae08fc4b Port zipadjust to Java 2018-01-27 08:25:34 +08:00
topjohnwu
c61135ee7b Embed testkeys into jar 2018-01-27 00:19:35 +08:00
topjohnwu
97cf15007f Update crypto 2018-01-23 05:06:34 +08:00
topjohnwu
e8302dfbe2 Update Magisk Manager 2018-01-13 06:28:22 +08:00
topjohnwu
558f95cf7e Improve APK installation and add logging 2018-01-13 06:28:07 +08:00
topjohnwu
18f6ead891 Fix alignment when boot image has head offset 2018-01-13 06:28:07 +08:00
topjohnwu
10bd25be52 Suppress harmless error logs 2018-01-12 00:23:38 +08:00
topjohnwu
65511845d2 Fix APK installation on some devices
Close #367. Android 6.0 and before doesn't like the new path
2018-01-11 20:57:05 +08:00
topjohnwu
1c743839ea Add MS_SILENT to xmount and cleanup function wraps 2018-01-11 03:06:20 +08:00
topjohnwu
bcae9dec41 Fix a bug when only one script will run 2018-01-11 02:48:15 +08:00
Shaka Huang
482c9af41f Fix segmentation fault
When both keepverity and keepforceencrypt are false, ‘e’ will be freed after removing ‘verity_key’ and segmentation fault might happened in strstr(e->filename, “fstab”)

Signed-off-by: Shaka Huang <shakalaca@gmail.com>
2018-01-11 02:08:52 +08:00
topjohnwu
2bf2e7461f Update diagram URL 2018-01-09 06:50:03 +08:00
topjohnwu
7d1082b1cb Fix magiskhide in graph 2018-01-09 06:48:58 +08:00
topjohnwu
0dbae83aec Update diagram URL 2018-01-09 06:08:54 +08:00
topjohnwu
f927c1b997 Update procedure diagram 2018-01-09 06:07:12 +08:00
topjohnwu
89ec7dad2b Update documentation to v15.2 2018-01-08 22:33:55 +08:00
topjohnwu
4fd61345af Happy New Year 2018-01-02 01:27:20 +08:00
topjohnwu
66cca24453 Samsung need more rules :) 2018-01-02 00:11:26 +08:00
topjohnwu
e733484fab Some devices don't like all log buffers 2018-01-01 23:58:13 +08:00
topjohnwu
e5c3183025 Update scripts 2018-01-01 16:46:28 +08:00
topjohnwu
930c82316a Slightly change logging style 2017-12-31 21:54:39 +08:00
Shaka Huang
3dc22db265 Support loading split sepolicy on non skip_initramfs devices
For certain device (e.g ZenFone 4 ZE554KL) there’s no sepolicy under rootfs and no a/b partition (implies no vendor partition) Magisk will failed to patch SELinux policy database and the system won’t boot up.

In order to cope with this configuration the status of loading policy db needs to be checked, once it failed we have to mount the system partition and do patch_sepolicy() again.

Signed-off-by: Shaka Huang <shakalaca@gmail.com>
2017-12-31 21:30:56 +08:00
topjohnwu
d8c51cb286 Update sepolicy handling 2017-12-31 19:32:04 +08:00
topjohnwu
2f79d0c3b3 Fix segfault while patching dtb 2017-12-31 19:30:56 +08:00
topjohnwu
d8bb3af06b Miscellaneous 2017-12-29 04:25:30 +08:00
topjohnwu
e139e8777b Fix faulty magiskboot ramdisk patch code 2017-12-29 04:25:03 +08:00
topjohnwu
d52d7cfbd9 Update magiskpolicy 2017-12-26 04:24:48 +08:00
topjohnwu
4f74a259e3 Update Magisk Manager 2017-12-26 04:00:01 +08:00
topjohnwu
74da6e1dc0 Support new 1500 template 2017-12-26 03:23:58 +08:00
topjohnwu
84ffdf0ed5 Eliminate a possbility to cause segfault 2017-12-25 05:21:40 +08:00
topjohnwu
022b18c8ce Properly detect /data status 2017-12-25 05:21:40 +08:00
topjohnwu
b92b1dcddb cil: Allow redeclare types[attributes] and disable neverallow 2017-12-25 05:21:40 +08:00
topjohnwu
1472dbb291 Add cache magisk image merging support 2017-12-22 16:10:38 +08:00
topjohnwu
d58a8dc868 Update Magisk Manager 2017-12-22 06:44:22 +08:00
topjohnwu
e94be0b70e Prevent creating 128M images
make_ext4fs will fail creating 128M ext4 images, LOL WTF? Change it to 132M to fix this issue
2017-12-22 02:39:44 +08:00
topjohnwu
f6ae7e1bf1 Allow su to work when manager uninstalled 2017-12-22 00:30:08 +08:00
topjohnwu
f7b4935677 Add recommend KEEPVERITY and KEEPFORCEENCRYPT flags 2017-12-21 15:42:03 +08:00
topjohnwu
a3c49de6a5 Refactor magiskboot 2017-12-21 03:36:18 +08:00
topjohnwu
e8dd1b292f Update snet 2017-12-19 15:51:01 +08:00
topjohnwu
d21264d01b Let magiskinit directly spawn new magisk_daemon process 2017-12-19 14:27:54 +08:00
topjohnwu
b0567eadfd Reduce effort and memory of log monitor 2017-12-18 18:17:37 +08:00
topjohnwu
5fc2058336 Show version code when report client 2017-12-18 16:00:44 +08:00
topjohnwu
d0567d29d2 Update su to match Linux's implementation 2017-12-18 15:46:18 +08:00
topjohnwu
4db0ad32f0 Fix install scripts 2017-12-18 03:08:53 +08:00
topjohnwu
d065040321 Fix magiskinit invincible mode and logcat monitor 2017-12-18 02:51:27 +08:00
topjohnwu
17f0fea3fc Fix unreleased resource in rootfs 2017-12-16 04:42:16 +08:00
topjohnwu
8ca1e43533 Move all /data files into /data/adb 2017-12-16 04:42:16 +08:00
topjohnwu
bd01c314dc Change database location 2017-12-12 03:04:55 +08:00
topjohnwu
e404476609 Fix logs on decrypted /data 2017-12-07 23:25:43 +08:00
topjohnwu
942c870981 Properly handle KEEPVERITY and HIGHCOMP 2017-12-07 04:20:27 +08:00
topjohnwu
baff9256c5 Dynamic patch verity and forceencrypt flag 2017-12-07 03:21:13 +08:00
topjohnwu
b4c0a255fc Separate pattern logic 2017-12-07 01:30:48 +08:00
topjohnwu
9f6a27c20d Add high compression ramdisk support 2017-12-06 12:51:16 +08:00
topjohnwu
742dc137ed More fail proof to magiskinit 2017-12-05 21:05:20 +08:00
topjohnwu
39a6bd33ce Fix critical bug 2017-12-05 05:32:15 +08:00
topjohnwu
4672a5fad6 Add cpio extract all feature 2017-12-05 03:32:37 +08:00
topjohnwu
e649b0a2df Update README.md 2017-12-04 22:59:29 +08:00
topjohnwu
fd8dbe3eff Greatly reduce Gradle sync time and frequency 2017-12-04 22:21:19 +08:00
topjohnwu
bb97cc594d Cleanup and small fixes 2017-12-04 18:05:07 +08:00
topjohnwu
70a322263e Fix Android Studio gradle sync 2017-12-04 15:32:18 +08:00
topjohnwu
c6f144d482 Update README.md 2017-12-04 15:21:06 +08:00
topjohnwu
3709489b3a Massive project restructure 2017-12-04 15:16:41 +08:00
topjohnwu
145ef32e28 Tidy up external 2017-12-04 03:37:00 +08:00
topjohnwu
2212800a23 Add symlink feature to cpio 2017-12-04 03:37:00 +08:00
topjohnwu
2e25431bb6 Generalize cpio functions 2017-12-04 03:37:00 +08:00
topjohnwu
32c8e7522f More precise logging configuration 2017-12-01 17:38:57 +08:00
topjohnwu
a5e4f3cc6b Separate cpio logic from MagiskBoot 2017-12-01 17:17:24 +08:00
topjohnwu
a30777bd9f Fix bug in compiling split cil 2017-12-01 03:33:25 +08:00
topjohnwu
e989195a68 Update magiskpolicy 2017-11-30 20:57:40 +08:00
topjohnwu
997d58932e Adjust daemon initialization 2017-11-28 04:43:46 +08:00
topjohnwu
b4015f877f New invincible implementation 2017-11-28 03:42:48 +08:00
topjohnwu
d15fff95b9 Use inotify to monitor files 2017-11-27 15:37:28 +08:00
topjohnwu
687e3b13ea Bump Magisk Manager version 2017-11-23 23:56:17 +08:00
topjohnwu
8c6bb383b7 Add support to build with NDK r10e 2017-11-23 23:55:33 +08:00
topjohnwu
bc592c1d13 Fix bootloops on some devices 2017-11-23 18:38:12 +08:00
topjohnwu
968bd8be67 Update Magisk Manager 2017-11-23 01:33:33 +08:00
topjohnwu
d8b8adb88c Fix is_mounted function 2017-11-22 22:22:29 +08:00
topjohnwu
f42d820891 Several small tweaks 2017-11-22 16:12:08 +08:00
topjohnwu
bc21a1fb71 Update internal paths 2017-11-22 16:04:24 +08:00
topjohnwu
3bc31374ac Fix issue of touch command on Android 5.0 2017-11-20 04:13:51 +08:00
topjohnwu
858e7bae2b More precise size for mmap 2017-11-20 03:40:37 +08:00
Patryk Szalanski
8c02d120a2 Fix missing includes for ndk r16 2017-11-17 02:54:16 +08:00
topjohnwu
07e353f4ff Fix typo when handling MTK 2017-11-16 22:26:28 +08:00
topjohnwu
bb33d9e600 Use real tmp files 2017-11-15 05:48:31 +08:00
topjohnwu
68eb0bdec9 Allow specific signal to specific threads 2017-11-15 05:48:31 +08:00
topjohnwu
32ee8e462c Properly and fully support dtbo patching 2017-11-15 05:48:31 +08:00
topjohnwu
e79aa54b70 Proper Windows building support 2017-11-12 04:17:56 +08:00
topjohnwu
9a95652034 Simplify compress code 2017-11-12 04:08:52 +08:00
topjohnwu
912c188b53 Add dtbo.img patch support 2017-11-11 01:33:50 +08:00
topjohnwu
e9d0f615ba Add dtb test command 2017-11-11 01:30:33 +08:00
topjohnwu
9136573596 Add stdin/stdout support 2017-11-10 20:25:41 +08:00
topjohnwu
2487ec94e6 Add support to remove avb verity 2017-11-10 03:45:06 +08:00
topjohnwu
811489f157 Small reorganization 2017-11-10 01:51:41 +08:00
topjohnwu
b438cc9335 Remove unnecessary monogisk 2017-11-10 00:54:54 +08:00
topjohnwu
1d3d30fa45 Get potential slot info 2017-11-09 03:05:25 +08:00
topjohnwu
72b5985398 Prevent race condition on /magisk symlink 2017-11-09 03:05:01 +08:00
topjohnwu
2db60e0a6b Add Pixel 2 XL support 2017-11-06 22:33:41 +08:00
topjohnwu
e710848345 Unify Magisk configuration
Introduce monogisk tool
2017-11-06 06:22:45 +08:00
topjohnwu
8d6f3c2450 Fix build error on release builds 2017-11-02 14:48:22 +08:00
topjohnwu
f863d127e7 Fix Xiaomi A1 support 2017-11-01 22:49:06 +08:00
topjohnwu
a831110816 Add boot signing to installation 2017-10-31 17:05:24 +08:00
topjohnwu
e97bdb53f4 Adjust java paths 2017-10-30 03:45:50 +08:00
topjohnwu
fe1439fbac Support changing su requester package name 2017-10-28 16:20:31 +08:00
topjohnwu
2bc30e5c22 Hide /magisk 2017-10-28 16:12:01 +08:00
topjohnwu
7244c02a0d Small adjustments 2017-10-28 16:11:01 +08:00
topjohnwu
6c229ffa68 Update external sources 2017-10-19 00:46:39 +08:00
topjohnwu
cdc5d983f3 Bump MagiskManager version 2017-10-15 03:21:33 +08:00
topjohnwu
96688e4dac Fix proper Lollipop selinux support 2017-10-14 22:37:02 +08:00
topjohnwu
28a945fee9 Fix SEGFAULT in magisk log dumper 2017-10-14 21:10:52 +08:00
topjohnwu
c7e777255a Reduce unnecessary stack memory allocation 2017-10-14 21:10:51 +08:00
topjohnwu
2dd4cf040e Prevent multiple process clashes to start daemon 2017-10-14 21:10:51 +08:00
topjohnwu
d1b9eca5eb Fix bug that cause boot delay 2017-10-14 00:19:13 +08:00
topjohnwu
594a67fe28 Cleanup and add more xwraps 2017-10-14 00:08:12 +08:00
topjohnwu
cddeaffada Remove err_handler 2017-10-13 22:26:42 +08:00
topjohnwu
2a8898e7c3 Fix lz4 legacy on LG zImages 2017-10-13 00:18:40 +08:00
topjohnwu
ce3f3b09b4 Brute force resizeimg for Crapsung device :) 2017-10-12 14:32:40 +08:00
topjohnwu
fe4b3df7e9 Fix selinux context on Magisk files 2017-10-12 14:32:40 +08:00
topjohnwu
25bdbcf526 Add new file operations 2017-10-12 14:32:40 +08:00
topjohnwu
df7eaa5598 Reduce update-binary size 2017-10-11 02:26:43 +08:00
topjohnwu
bb7099376b Improve daemon startup and log management 2017-10-11 02:26:28 +08:00
topjohnwu
0327fd9710 Restart MagiskHide if daemon restarted 2017-10-10 19:49:15 +08:00
topjohnwu
e645c6e465 Refactor resetprop 2017-10-10 02:04:50 +08:00
topjohnwu
78a3d36ccc Allow devices without separate vendor partition 2017-10-09 21:53:50 +08:00
topjohnwu
3942858ccd Introduce a single general purpose logcat monitor 2017-10-09 05:39:40 +08:00
topjohnwu
03c8d716cc Introduce Invincible Mode: Self recover service 2017-10-08 22:00:22 +08:00
topjohnwu
60181c4fcb MagiskManager -> java 2017-10-07 22:48:16 +08:00
topjohnwu
c215447405 Fix Pixel C installation 2017-10-07 22:08:10 +08:00
topjohnwu
89330b89d8 Clone attributes to new tmpfs mountpoint 2017-09-29 01:07:28 +08:00
topjohnwu
a8f3718ed0 Bump MagiskManager version 2017-09-28 05:50:18 +08:00
topjohnwu
a78ba44709 Always create core directories 2017-09-28 05:50:06 +08:00
topjohnwu
ff110e3513 Update docs 2017-09-28 05:39:10 +08:00
topjohnwu
cfae6c63b5 Remove sepolicy-inject alias 2017-09-28 01:01:46 +08:00
topjohnwu
dbfe49c56f Unlock blocks before flashing boot image 2017-09-28 00:54:01 +08:00
topjohnwu
98e21f9f5b Update uninstaller 2017-09-27 15:26:21 +08:00
topjohnwu
83af0497e4 Don't use dummy directory; directly use tmpfs 2017-09-27 04:36:01 +08:00
topjohnwu
6ce37b44db Improve logging 2017-09-27 04:36:01 +08:00
topjohnwu
9cb1cf756f Update scripts 2017-09-26 20:21:43 +08:00
topjohnwu
ffa005e4ab Don't patch FBE flags 2017-09-26 02:04:07 +08:00
topjohnwu
af102e47f1 Fix a small bug in deleteprop 2017-09-25 17:47:30 +08:00
topjohnwu
73064a816d Fix ramdisk patches 2017-09-25 13:44:00 +08:00
topjohnwu
9b4ae8fcc5 Adjust scripts 2017-09-16 03:48:58 +08:00
topjohnwu
a1a2c52409 Patch sepolicy at boot time 2017-09-16 01:32:09 +08:00
topjohnwu
9a0b26e0b0 Proper FBE support 2017-09-15 18:05:42 +08:00
topjohnwu
b805b96e16 Read SHA1 from overlay ramdisk 2017-09-15 18:03:56 +08:00
topjohnwu
590e7f7724 Proper support for Magisk Manager installation 2017-09-15 18:02:25 +08:00
Shaka Huang
4d61e5e319 Fix error generating binary for x86
fix typo

Signed-off-by: Shaka Huang <shakalaca@gmail.com>
2017-09-14 14:33:37 -05:00
topjohnwu
8c8a63ebfb Use external functions in init
Don't reinvent the wheel
2017-09-15 03:22:23 +08:00
topjohnwu
e5e34797a8 Patch fstab from dtb 2017-09-15 02:52:53 +08:00
topjohnwu
8516ebe6f5 Add libfdt 2017-09-15 02:52:53 +08:00
topjohnwu
9f6205f47f Refactor ramdisk pattern patches 2017-09-15 02:52:53 +08:00
topjohnwu
8b2ec23a89 Re-organize MagiskBoot 2017-09-15 02:52:53 +08:00
topjohnwu
1816ca6b02 Seperate logging to another header 2017-09-15 02:52:53 +08:00
topjohnwu
7394ff9346 Rename cpio_file -> cpio_entry 2017-09-15 02:52:53 +08:00
topjohnwu
bb5a6a1c28 Re-organize folders 2017-09-14 01:57:53 +08:00
topjohnwu
b614b06736 Search for dtb only if not existed 2017-09-14 01:57:44 +08:00
topjohnwu
7a376c9efc Adjust the daemon for Pixel support 2017-09-14 01:57:44 +08:00
topjohnwu
518f3d229f Slight adjustments to scripts 2017-09-13 15:51:45 +08:00
topjohnwu
46c91f923d Update scripts to support Pixel (XL) 2017-09-13 04:08:50 +08:00
topjohnwu
3a2262dfb3 Use backup init if booted as recovery 2017-09-13 04:08:50 +08:00
topjohnwu
ff7c38f8e9 Add runtime ramdisk patch support 2017-09-13 04:08:50 +08:00
topjohnwu
4229ba364f Update lz4 to v1.8.0 2017-09-13 04:08:50 +08:00
topjohnwu
ba8e7a211a Use default preferences from lz4 cli 2017-09-13 04:08:50 +08:00
topjohnwu
6b41653a32 Add kernel decompression and appended dtb support 2017-09-13 04:08:50 +08:00
topjohnwu
59c1125e72 Refactor MagiskBoot compression methods 2017-09-13 04:08:50 +08:00
topjohnwu
b536046720 MagiskBoot refactor 2017-09-13 04:08:50 +08:00
topjohnwu
619b805894 Add secilc 2017-09-13 04:08:50 +08:00
topjohnwu
8662537883 Add ramdisk overlay to magiskinit 2017-09-13 04:08:50 +08:00
topjohnwu
717890395b Introduce magiskinit for Pixel (XL) 2017-09-13 04:08:50 +08:00
topjohnwu
b7b4164f4f Add cpio-mv action 2017-09-13 04:08:44 +08:00
topjohnwu
7e65296470 Small improvement to cpio 2017-09-13 04:08:44 +08:00
topjohnwu
cd5f5d702f Fix stock image dump not stored correctly 2017-09-13 04:08:44 +08:00
topjohnwu
44b93e7cc4 Bump Magisk Manager version 2017-09-06 23:33:46 +08:00
topjohnwu
0eb79e5acd Update scripts 2017-09-06 23:33:46 +08:00
topjohnwu
eceba26894 Make MagiskHide work without magisk.img 2017-09-06 02:25:40 +08:00
topjohnwu
0bf404f75e Bump busybox to 1.27.2 2017-09-05 21:45:13 +08:00
topjohnwu
cd8dd65a65 chcon on Android 5.0 doesn't support -h options 2017-09-05 21:44:53 +08:00
topjohnwu
50c56f8b50 Simplify flash scripts 2017-09-05 21:44:22 +08:00
topjohnwu
9e9f8ca8f3 Restore cwd 2017-09-02 23:28:17 +08:00
topjohnwu
f63af0601c Support Magisk Manager boot image file patch 2017-08-31 03:08:09 +08:00
topjohnwu
189c671ce2 Rewrite environment setup 2017-08-31 02:20:06 +08:00
topjohnwu
bb39a01361 Minor adjust magiskpolicy 2017-08-28 02:14:14 +08:00
topjohnwu
764999704a Collect va_list before fork 2017-08-27 02:17:37 +08:00
topjohnwu
ecfa4aafc1 Fix clone_attr 2017-08-26 23:19:56 +08:00
topjohnwu
a1e33c4d2f Build everything ourselves 2017-08-24 12:14:17 +08:00
topjohnwu
7f8ba74dac Add hide Magisk Manager feature 2017-08-22 03:02:08 +08:00
topjohnwu
e3df62d812 Refactor several utility functions 2017-08-20 21:36:32 +08:00
topjohnwu
1913125881 Update README.MD 2017-08-20 15:03:26 +08:00
topjohnwu
e8e58f3fed Adjust run_command 2017-08-19 19:27:51 +08:00
topjohnwu
1ca9ec384b Fix typo in cloning attribute 2017-08-19 18:59:06 +08:00
topjohnwu
9522255e3a Proper magisk manual injection support 2017-08-17 03:46:01 +08:00
topjohnwu
2a22fa694e Fix removing modules from images 2017-08-17 02:19:14 +08:00
topjohnwu
1591f5a0ca Update magiskpolicy help message 2017-08-17 00:58:02 +08:00
topjohnwu
3bc4e9a724 Finalize docs 2017-08-17 00:41:50 +08:00
topjohnwu
f7a6bb0723 Add more details and tips 2017-08-15 10:13:19 +08:00
topjohnwu
e9c17a3ef7 Add bootstages docs 2017-08-15 02:27:07 +08:00
topjohnwu
29bb5840b5 Fix duplicate in applets.md 2017-08-15 01:38:22 +08:00
topjohnwu
c9d8d860f6 Update diagram link 2017-08-15 01:32:24 +08:00
topjohnwu
cc18096882 Update docs 2017-08-15 01:28:45 +08:00
topjohnwu
15f2a664d1 Update help messages 2017-08-15 01:25:54 +08:00
topjohnwu
70b4f62ddc Update links 2017-08-14 03:54:05 +08:00
topjohnwu
e1023fdfaf Fix typo in procedure chart 2017-08-14 03:52:37 +08:00
topjohnwu
5e9648387a Merge module and repo docs 2017-08-14 03:46:23 +08:00
topjohnwu
2ba8b4df67 Complete module.md 2017-08-14 03:25:11 +08:00
topjohnwu
3a084c5d7b Add docs 2017-08-14 02:41:27 +08:00
topjohnwu
f7200e39c3 Bump MagiskManager version 2017-08-13 01:50:36 +08:00
topjohnwu
a7dfc20967 Adjust several operation orders 2017-08-13 01:15:18 +08:00
topjohnwu
6eb7c0b5d6 Add new util functions for new template version 2017-08-12 23:15:39 +08:00
topjohnwu
0b3c078aeb Fix README.MD 2017-08-12 19:17:06 +08:00
topjohnwu
750872cc37 Add boot actions 2017-08-12 17:03:31 +08:00
topjohnwu
29895ff474 Fix multiuser in user independent mode 2017-08-12 01:09:20 +08:00
topjohnwu
44adccc147 Add magisk binary mirror 2017-08-11 17:43:36 +08:00
topjohnwu
2a7e2c70b5 Extract functions 2017-08-11 14:53:24 +08:00
topjohnwu
8d431b6762 Remove IS_VENDOR flag (not needed) 2017-08-11 14:53:17 +08:00
topjohnwu
273849c0c8 Reorganize functions 2017-08-11 11:07:58 +08:00
topjohnwu
5cc14405c7 Combine image related functions 2017-08-10 17:26:37 +08:00
topjohnwu
f0cfd60e62 Fix multiuser 2017-08-07 00:32:04 +08:00
topjohnwu
d6547f0701 Fix installer options not read properly 2017-08-04 23:49:22 +08:00
topjohnwu
3b68905037 Swap buffer to fix module scripts 2017-08-03 18:07:34 +08:00
topjohnwu
eae611c54d Add b64xz to handle busybox decode/decompress in scripts 2017-08-02 18:25:24 +08:00
topjohnwu
b37bad35c2 Fuse busybox into update-binary and remove from Magisk Manager APK 2017-08-02 02:22:33 +08:00
topjohnwu
5fab15fee5 Add busybox into PATH for scripts 2017-08-01 15:34:16 +08:00
topjohnwu
10c8ea17aa Fix debug message 2017-08-01 01:24:27 +08:00
topjohnwu
7058c8ff5a Force main binaries recompile everytime 2017-07-31 23:52:50 +08:00
topjohnwu
64e85da59f Merge Android.mk 2017-07-31 23:47:50 +08:00
topjohnwu
f79fad64aa Fix several script issues 2017-07-31 23:31:40 +08:00
topjohnwu
cb70eebb08 Update scripts 2017-07-31 03:03:52 +08:00
topjohnwu
edaf8787d1 Provide external files to Magisk Manager with build script 2017-07-31 00:59:41 +08:00
topjohnwu
24164c8580 Add busybox to source 2017-07-30 20:14:12 +08:00
topjohnwu
9fca7011aa Move headers 2017-07-30 18:15:00 +08:00
topjohnwu
b13eb3fd40 Force start logd ASAP 2017-07-25 05:33:25 +08:00
topjohnwu
b7986a351c Overcome some quirks in Android Lollipop 2017-07-25 05:33:25 +08:00
topjohnwu
ce87591c62 Fix unable to get SHA1 value issue 2017-07-25 02:40:26 +08:00
topjohnwu
25c289ad3e Fix typo in uninstaller 2017-07-19 03:24:07 +08:00
topjohnwu
8c5f11b7dd Update Magisk Manager 2017-07-19 02:34:23 +08:00
topjohnwu
7f7dda9ec2 Update uninstaller 2017-07-19 02:22:07 +08:00
topjohnwu
9c1005ff0c Update to Google CTS (2017.7.17) 2017-07-19 02:22:07 +08:00
topjohnwu
5b36b4472c Update and add new resetprop features 2017-07-19 02:22:07 +08:00
topjohnwu
a3fcc64aaa MagiskBoot log to stderr 2017-07-18 11:53:28 +08:00
topjohnwu
f3078bc903 Update MagiskSU 2017-07-16 23:39:27 +08:00
topjohnwu
6072744f7e Prevent logcat monitors crashing 2017-07-16 23:39:27 +08:00
topjohnwu
a87ad35a50 Check Android version before actually doing anything
Close #233
2017-07-14 01:13:49 +08:00
topjohnwu
cf56d7e4ed Let core-only mode run hosts and magiskhide 2017-07-14 00:54:43 +08:00
topjohnwu
e33a5eb307 Set proper selinux context for /sbin re-link 2017-07-14 00:51:42 +08:00
topjohnwu
e5b704eb32 Several cleanups 2017-07-13 23:42:01 +08:00
topjohnwu
56457bd325 Fix lzma compressed ramdisk
Fix issue #222
2017-07-13 10:22:55 +08:00
topjohnwu
bdbb3c6657 Eliminate a potential segfault in magiskpolicy
Huge props to @jenslody for finding out the issue!
Fix #278
2017-07-13 10:13:14 +08:00
topjohnwu
c4d7001489 Fix Pixel C flashing errors
Use return values instead of creating a file to indicate a chromeos image
Fix #264
2017-07-13 02:14:10 +08:00
topjohnwu
c07bac9a63 Bump MagiskManager version 2017-07-11 01:54:26 +08:00
topjohnwu
d27d04783f Add version info into util_functions 2017-07-11 01:54:11 +08:00
topjohnwu
58de5a7ec7 Prevent a slight chance to crash 2017-07-11 01:53:45 +08:00
topjohnwu
504a9b4746 MagiskHide refactor 2017-07-10 23:41:21 +08:00
topjohnwu
cccb5a3e08 Update comments 2017-07-10 22:48:14 +08:00
topjohnwu
d75fa62cab Adjust run_command function 2017-07-10 22:29:53 +08:00
topjohnwu
3d43c3c5bc Update scripts 2017-07-10 00:17:34 +08:00
topjohnwu
b570b363d9 Cleanup file descriptors and add more info 2017-07-08 23:51:58 +08:00
topjohnwu
b9968aa1e6 Add mount-master option to su 2017-07-08 01:13:12 +08:00
topjohnwu
c0d77808f6 Update selinux from upstream 2017-07-07 23:08:18 +08:00
topjohnwu
9679492c28 Match resetprop files with AOSP 2017-07-07 22:29:55 +08:00
topjohnwu
f3b68e6543 Seperate external shared libraries 2017-07-07 22:11:00 +08:00
topjohnwu
0dcfaaf5ff Adjust hide policies 2017-07-07 17:52:25 +08:00
topjohnwu
ba513dcb9a Use sqlite stub 2017-07-07 17:14:37 +08:00
topjohnwu
ebabc60477 Update Magisk Manager 2017-07-03 01:19:15 +08:00
topjohnwu
cf565d0145 Add mount ns kernel support detection 2017-07-03 01:19:15 +08:00
topjohnwu
52a23e7904 Add more props for hiding 2017-07-03 01:19:15 +08:00
topjohnwu
9e22b80714 Update unmounting policies 2017-07-03 01:19:15 +08:00
topjohnwu
7eed9c4a6d Several improvements 2017-07-03 01:19:15 +08:00
topjohnwu
bf42fce17e Update boot patch method and scripts 2017-07-03 01:19:15 +08:00
topjohnwu
9d421226a7 Update list implementation 2017-07-03 01:15:11 +08:00
topjohnwu
7b9be8369e Enable magiskhide by default 2017-07-01 15:45:22 +08:00
topjohnwu
7cf4b819ae Several small tweaks 2017-07-01 14:05:54 +08:00
topjohnwu
9e1aea33c3 Improve xmkdir 2017-06-30 23:22:51 +08:00
topjohnwu
8767a88854 Check/fix ext4 image before mounting 2017-06-30 23:22:26 +08:00
topjohnwu
47c0084641 Fix cache mount bug 2017-06-30 21:49:35 +08:00
topjohnwu
54e6a790cf Update Magisk Manager 2017-06-24 23:46:44 +09:00
topjohnwu
2a86bc8695 Update scripts 2017-06-24 23:39:24 +09:00
topjohnwu
04538372c6 Add more image commands 2017-06-24 23:37:45 +09:00
topjohnwu
9430ed66cd Add addon.d survival script 2017-06-19 00:15:44 +08:00
topjohnwu
96f8efc27a Several small fixes 2017-06-16 15:27:28 +08:00
topjohnwu
a90e8b6112 Only use binaries/libs in /system 2017-06-16 04:09:36 +08:00
topjohnwu
561c1fb798 Update MagiskManager 2017-06-16 04:07:45 +08:00
topjohnwu
806fec7017 Add new rules to unmount 2017-06-15 18:32:24 +08:00
topjohnwu
b3da28eade Don't compile shell.c for sqlite 2017-06-14 03:29:59 +08:00
topjohnwu
166f6412c2 Fix a flaw in mounting logic 2017-06-14 00:55:41 +08:00
topjohnwu
1e877808bc Fix link errors for flash scripts 2017-06-13 00:46:20 +08:00
topjohnwu
1777d9f751 Magic Mount algorithm massive bug fix 2017-06-12 03:29:01 +08:00
topjohnwu
309b99eac0 Always init for resetprop 2017-06-11 20:22:10 +08:00
topjohnwu
a5aa1b3917 Don't use system and collect logs 2017-06-11 20:20:24 +08:00
topjohnwu
aced0632ec Improve image merging 2017-06-11 16:51:44 +08:00
topjohnwu
4e801788d7 Fix shared library linking error 2017-06-11 01:40:08 +08:00
topjohnwu
0b4baad78b Add mount namespace mode 2017-06-08 22:56:21 +08:00
topjohnwu
201e32d4c4 Fix daemon crashes in encrypted /data 2017-06-08 19:15:51 +08:00
topjohnwu
0980cb6eb5 Proper handle version string 2017-06-08 05:21:51 +08:00
topjohnwu
f75d23363b Update Magisk Manager 2017-06-08 05:21:27 +08:00
topjohnwu
6c0ba66f17 Add excessive logging for debug mode 2017-06-08 03:25:15 +08:00
topjohnwu
f32ce7392e Update sepolicy rules 2017-06-08 03:02:01 +08:00
topjohnwu
8bf382adad Apparently, not every device uses emmc 2017-06-07 11:32:35 +08:00
topjohnwu
541ba357bb Fix prop issues 2017-06-07 11:26:58 +08:00
topjohnwu
b6578b52e3 Update README.MD 2017-06-04 02:55:12 +08:00
topjohnwu
fb01c43ece Add Linux compatibility 2017-06-04 01:39:52 +08:00
topjohnwu
b9a012c6e3 Fix execution in Magisk binary for uninstallation 2017-06-04 00:35:45 +08:00
topjohnwu
17684ed8a8 Fix uninstaller and build with 'all' 2017-06-04 00:04:58 +08:00
topjohnwu
1b6b3b2cd5 Build in debug mode by default 2017-06-03 22:04:22 +08:00
topjohnwu
acd8567586 Adjust for Windows builds 2017-06-03 22:00:22 +08:00
topjohnwu
e780c76c93 Massive build script refactor 2017-06-03 20:31:02 +08:00
topjohnwu
532c6caddf Fix typo in cpio check 2017-06-03 18:52:02 +08:00
topjohnwu
ef8d9be633 More improvements and fixes 2017-06-03 05:52:49 +08:00
topjohnwu
2cdbcc5666 Add more checks for other patches 2017-06-03 05:08:52 +08:00
topjohnwu
c282a8f328 Loop for every for logging 2017-06-03 04:31:01 +08:00
topjohnwu
b9eab39541 Add ext4 img helper commands 2017-06-03 03:58:26 +08:00
topjohnwu
20903784a4 Support file based encryption and several small updates 2017-06-03 02:28:51 +08:00
topjohnwu
3ec9ff7467 Update MagiskSU 2017-06-01 03:20:51 +08:00
topjohnwu
17d3a87b1f Prevent resetprop function signature duplicate with libc 2017-05-30 23:34:39 +08:00
topjohnwu
14c5c60863 Improve excessive rapid root access performance 2017-05-29 18:56:00 +08:00
topjohnwu
70a80090c4 Improve multiuser su support 2017-05-28 01:33:58 +08:00
topjohnwu
b6cb5d09cb Add multiuser support 2017-05-27 02:43:55 +08:00
topjohnwu
69cfde4516 Add new function for vector (future proof) 2017-05-26 23:03:54 +08:00
topjohnwu
bdc83da098 Fix bug in magic mount 2017-05-26 23:03:54 +08:00
topjohnwu
f872a122a9 Preserve at least 32M free size 2017-05-26 23:03:45 +08:00
topjohnwu
aa92e4cbd0 Fix stupid bug in MagiskHide 2017-05-12 15:28:15 +08:00
topjohnwu
e603877a17 Install Magisk Manager APK with pm (Android O Compat.) 2017-05-09 01:16:58 +08:00
topjohnwu
bb96477779 Improve Magic Mount with proper precedence 2017-05-09 01:09:32 +08:00
topjohnwu
543ee79720 Prevent su logging tons of errors 2017-05-08 11:50:52 +08:00
topjohnwu
ea8cd98361 Cleanup file descriptors 2017-05-08 03:11:14 +08:00
topjohnwu
58849f28a8 Add daemon response code 2017-05-05 16:13:26 +08:00
topjohnwu
d66c284bed Fix several small issues 2017-05-05 04:39:09 +08:00
topjohnwu
693848280b Add systemless hosts support 2017-05-04 03:05:37 +08:00
topjohnwu
396afaa181 Improve magiskhide stability 2017-05-04 02:58:37 +08:00
topjohnwu
05ed29133b Finish post-fs simple mount 2017-05-04 02:39:53 +08:00
topjohnwu
a31c1e8084 post-fs-data mode done 2017-05-04 01:22:56 +08:00
topjohnwu
21891230f2 Typo fix 2017-05-02 05:00:01 +08:00
topjohnwu
47da76c5a5 Stupid bug, critical fix 2017-05-02 04:57:14 +08:00
topjohnwu
6017ff2318 Close files, cleanup resourses 2017-05-02 04:55:55 +08:00
topjohnwu
e16d604d0d Implement Magic Mount 2017-05-01 01:58:52 +08:00
topjohnwu
d3d5703f3f Reduce duplicate code for MagiskBoot 2017-04-28 21:53:44 +08:00
topjohnwu
62fe92d922 Update credits 2017-04-28 03:36:16 +08:00
topjohnwu
512e7be74f Add version info 2017-04-28 03:26:48 +08:00
topjohnwu
727abbea8f Cleanup magiskboot 2017-04-28 03:24:30 +08:00
topjohnwu
76f81ece62 Fix verbose output 2017-04-28 01:45:57 +08:00
topjohnwu
495654f9ff Small tweaks 2017-04-24 21:43:30 +08:00
topjohnwu
95fec2100e Use GPL v3 license and update copyright messages 2017-04-22 17:12:54 +08:00
topjohnwu
623a879797 Update scripts 2017-04-22 17:12:54 +08:00
topjohnwu
4c96d23f48 Some minor updates 2017-04-22 17:12:54 +08:00
topjohnwu
9bc8f6e9d7 Add common script support 2017-04-22 17:12:54 +08:00
topjohnwu
e00e6509ee Add error code for magiskhide 2017-04-22 17:12:54 +08:00
topjohnwu
be5739508b Isolate root daemon from requests 2017-04-22 17:12:54 +08:00
topjohnwu
38c867ea94 Some fixes 2017-04-22 17:12:54 +08:00
topjohnwu
2a985ce6c0 Add magiskhide list management 2017-04-22 17:12:54 +08:00
topjohnwu
e4f3fb36f3 Update build scripts 2017-04-22 17:12:54 +08:00
topjohnwu
b2f8792873 Add more Android O selinux stuff 2017-04-22 17:12:54 +08:00
topjohnwu
2065133e2d Update policy rules for Android O 2017-04-22 17:12:54 +08:00
topjohnwu
86da87f254 Update build script and tools 2017-04-22 17:12:54 +08:00
topjohnwu
102a7f8723 Change flags 2017-04-22 17:12:54 +08:00
topjohnwu
e9afc15719 Fix magiskhide daemon enable/disable 2017-04-22 17:12:54 +08:00
topjohnwu
08527dde9b Auto start magiskhide 2017-04-22 17:12:54 +08:00
topjohnwu
d9c3a3c9a9 Remove su_device auto transit 2017-04-22 17:12:54 +08:00
topjohnwu
fe89f9e55e Update to newer functions in resetprop 2017-04-22 17:12:54 +08:00
topjohnwu
73802aabac Fix compile issue when using NDK Unified Headers 2017-04-22 17:12:54 +08:00
topjohnwu
bc66733289 Add Android O sepolicy patches 2017-04-22 17:12:54 +08:00
topjohnwu
f4c93b2251 Update resetprop for Android O support
Updated to upstream https://android.googlesource.com/platform/bionic.git
2017-04-22 17:12:54 +08:00
topjohnwu
c079c598f2 Update scripts, MagiskSU now works fine 2017-04-22 17:12:54 +08:00
topjohnwu
8a2f0063d4 Improve magiskhide process/thread management 2017-04-22 17:12:54 +08:00
topjohnwu
dfe4b33f2f Integrate sepolicy patching with MagiskSU fixed 2017-04-22 17:12:54 +08:00
topjohnwu
2f7cfa7ab2 Link binaries when daemon started 2017-04-22 17:12:54 +08:00
topjohnwu
bdcb813ee6 Add block rw support 2017-04-22 17:12:54 +08:00
topjohnwu
f0751007f3 Update main function 2017-04-22 17:12:54 +08:00
topjohnwu
6ad993704c Integrate MagiskSU into Magisk daemon 2017-04-22 17:12:54 +08:00
topjohnwu
796c3009c7 Refactor resetprop 2017-04-22 17:12:54 +08:00
topjohnwu
144ff5e716 Integrate MagiskHide into Magisk Daemon 2017-04-22 17:12:54 +08:00
topjohnwu
054a1e5ea4 Add magisk daemon 2017-04-22 17:12:54 +08:00
topjohnwu
a223f6056e Add zygote namespace detection 2017-04-22 17:12:54 +08:00
topjohnwu
a1fd7704e0 Fix vector bug 2017-04-22 17:12:54 +08:00
topjohnwu
b94227efc9 Add process searching 2017-04-22 17:12:54 +08:00
topjohnwu
3a7e782c07 Remove separate binary support for tools rely on daemon 2017-04-22 17:12:54 +08:00
topjohnwu
8f6b33d790 Rewrite magiskhide 2017-04-22 17:12:54 +08:00
topjohnwu
f476daa041 Change parts of library to shared
libsqlite and libselinux are shipped with Android systems
We build them here for the compiler to link against it,
we actually use the one in /system/lib(64)
2017-04-22 17:12:54 +08:00
topjohnwu
acfde9458d Merge magiskpolicy, magiskhide, resetprop, magisksu 2017-04-22 17:12:54 +08:00
topjohnwu
82e969627a Start unifying with log monitor 2017-04-22 17:12:54 +08:00
topjohnwu
40766b3375 Do not use psuedo permissive, hide instead 2017-04-03 23:28:18 +08:00
topjohnwu
d274e45587 Fix SuperSU installation 2017-03-31 06:25:22 +08:00
topjohnwu
0a0eb3f710 Update policy rules 2017-03-31 02:54:39 +08:00
topjohnwu
81d054a525 Adjust scripts 2017-03-31 02:54:39 +08:00
topjohnwu
2e185f4ec9 Add core props support 2017-03-30 02:47:40 +08:00
topjohnwu
67f347f880 Live patch policy in service mode 2017-03-30 02:29:10 +08:00
topjohnwu
81542fc6a8 Fix MTK header support 2017-03-29 04:35:35 +08:00
topjohnwu
5aced279d6 Add legacy lz4 mode support 2017-03-29 04:35:35 +08:00
topjohnwu
3f016f785f Handle selinux for Samsung in binary 2017-03-29 02:23:10 +08:00
topjohnwu
a6427d081e Fix typo 2017-03-29 02:22:33 +08:00
topjohnwu
8c7fbe20f9 Daemons cannot run in /data on Samsung, move to magisk.img 2017-03-27 07:23:53 +08:00
Deiki-kun
469aba8ed0 Magisk Hide enable/disable scripts fix 2017-03-27 05:51:23 +08:00
topjohnwu
6e8e4ad5da Fix compile warnings 2017-03-26 23:40:34 +08:00
Jan Christian Grünhage
2f33d654e4 Fix Markdown headings 2017-03-26 21:49:24 +08:00
Jasmin Hassan
760b6385f1 list_monitor: use IN_CLOSE_WRITE instead of IN_MODIFY 2017-03-26 21:49:11 +08:00
Jasmin Hassan
91527500f9 proc_monitor: Support newer kernels am_proc_start format 2017-03-26 21:49:11 +08:00
Jasmin Hassan
e87d989ca3 Fix proccess monitor for lsskernel 6.0.1 (3.8UX) 2017-03-26 21:49:11 +08:00
topjohnwu
64d61bae08 Start MagiskHide even if disabled (MagiskSU only mode) 2017-03-26 21:47:54 +08:00
topjohnwu
9862265465 Add Samsung RKP hexpatch back 2017-03-26 21:44:44 +08:00
topjohnwu
624b7616d0 Another freakin stupid typo 2017-03-21 05:15:13 +08:00
topjohnwu
d53f33bed8 I shall test Samsung before release... 2017-03-21 04:25:49 +08:00
topjohnwu
02e039d792 Small fixes 2017-03-20 05:03:52 +08:00
topjohnwu
9f9333315e Update build script and remove redundant file 2017-03-19 05:02:20 +08:00
topjohnwu
0d10b812fe Handle MagiskSU and MagiskHide differently 2017-03-19 05:00:12 +08:00
topjohnwu
b4fe4f3d10 Rename sepolicy-inject 2017-03-18 17:26:30 +08:00
topjohnwu
ba93fcbda0 Prevent multirom crashes 2017-03-18 16:57:29 +08:00
topjohnwu
88d19a4ca4 Several fixes 2017-03-18 16:57:04 +08:00
topjohnwu
af7b9ea898 Update to MagiskSU 8 2017-03-16 06:58:43 +08:00
topjohnwu
09cd0468cf Stop after reading TRAILER!!! 2017-03-16 06:46:32 +08:00
topjohnwu
529aa754f5 Update scripts 2017-03-15 19:32:25 +08:00
topjohnwu
3c7e865555 The long awaited vendor mount fix 2017-03-15 03:43:28 +08:00
topjohnwu
7877ac0c3b Well, /dev/zero cannot be used like that... 2017-03-13 05:05:51 +08:00
topjohnwu
1442e29d0e Update size in MTK headers 2017-03-13 04:27:56 +08:00
topjohnwu
9a7e9b736e Typo 2017-03-13 04:17:39 +08:00
topjohnwu
c421e45fa0 Small improvements and bug fixes 2017-03-12 19:22:15 +08:00
topjohnwu
8833d21ac3 Update scripts for MagiskBoot 2017-03-12 18:21:50 +08:00
topjohnwu
1a3c522c94 Various improvements for Magisk installation 2017-03-12 18:12:16 +08:00
topjohnwu
c55aa92d4f Update build script 2017-03-12 01:24:30 +08:00
topjohnwu
212a303347 Add auto cpio backup and restore 2017-03-10 07:52:59 +08:00
topjohnwu
3f3568d8af More cpio features 2017-03-10 04:15:37 +08:00
topjohnwu
1e3bcfc8cd Add basic cpio features 2017-03-08 00:54:23 +08:00
topjohnwu
a4ce9f6f05 Add compress, decompress, cleanup command 2017-03-05 01:51:13 +08:00
topjohnwu
65dc99744e Use our own zlib for static link and ZLIB_CONST flag 2017-03-04 21:18:24 +08:00
topjohnwu
c6d4740b0c Separate utility functions 2017-03-04 21:16:59 +08:00
topjohnwu
9f91c8b59d Improvements 2017-03-04 00:04:15 +08:00
topjohnwu
2b3b087c29 Add bzip2 support 2017-03-02 05:23:31 +08:00
topjohnwu
e08d46aa76 Add lz4 support 2017-03-02 04:12:47 +08:00
topjohnwu
feccc97a14 Fix typo 2017-03-01 00:50:56 +08:00
topjohnwu
77eec3d21d Support legacy lzma 2017-03-01 00:47:59 +08:00
topjohnwu
ecaafd1b70 Fix header when repack from ELF 2017-03-01 00:15:38 +08:00
topjohnwu
0d51997e46 Add xz support 2017-02-28 21:56:13 +08:00
topjohnwu
463cbceb07 Cleanup Android.mk 2017-02-28 17:53:04 +08:00
topjohnwu
1437c5c63f Add ndk-compression with liblzma 2017-02-28 17:24:27 +08:00
topjohnwu
52f1d50902 Project restructure 2017-02-28 16:59:21 +08:00
topjohnwu
a839cb787e Rename bootimgtool to magiskboot 2017-02-28 05:43:49 +08:00
topjohnwu
f621fb2060 Add gzip native support 2017-02-28 05:40:27 +08:00
topjohnwu
2ccd8b8838 Cleanup hexpatch 2017-02-25 03:50:26 +08:00
topjohnwu
7ef0746c52 Add ELF support 2017-02-25 03:29:12 +08:00
topjohnwu
6f609f0dd7 Several improvements 2017-02-24 15:53:17 +08:00
topjohnwu
ee2a30470a Boot IMG tools complete re-write
Fix #27, Fix #35, Fix #68, Fix #70, Fix #71, Fix #72, Fix #75, Fix #87
2017-02-24 07:45:48 +08:00
topjohnwu
e11fb2c09e Fix compile errors 2017-02-20 11:55:32 +08:00
topjohnwu
c6e9270590 Add busybox to uninstaller and bug fixes 2017-02-14 07:13:36 +08:00
topjohnwu
3e2e171407 Update su 2017-02-14 06:41:52 +08:00
topjohnwu
332f531a10 Move binaries to seperate folder 2017-02-14 06:39:10 +08:00
Drgravy
bae2c9bc63 fix LG bump support for uninstaller 2017-02-14 03:39:53 +08:00
Drgravy
5ac68f8df8 fix up bump support for LG g2/g3 devices 2017-02-14 03:39:53 +08:00
topjohnwu
06d3b94804 Several improvements 2017-02-07 07:50:55 +08:00
topjohnwu
e7c314fefc Add sepolicy-inject back to PATH 2017-02-06 07:20:01 +08:00
topjohnwu
faab79b41a Update uninstaller 2017-02-06 07:20:01 +08:00
topjohnwu
14204c9bfc Busybox path changed; stock one is enough for detection 2017-02-06 00:14:03 +08:00
topjohnwu
45dbd4464b Add general purpose script execution 2017-02-06 00:13:25 +08:00
topjohnwu
472255924a Auto switch to pseudo enforced if permissive 2017-02-05 23:43:01 +08:00
topjohnwu
6d3ac2aa55 Check before enable/disable 2017-02-05 23:42:57 +08:00
topjohnwu
9ad03994d1 Handle disabling 2017-02-05 23:40:50 +08:00
topjohnwu
35228f80b8 Several minor fixes 2017-02-05 01:45:53 +08:00
topjohnwu
69ded881c6 Treat symlinks as new files 2017-02-05 01:36:07 +08:00
topjohnwu
d9bce45db4 Fix props not loading correctly 2017-02-05 00:37:30 +08:00
topjohnwu
5e92b4faa9 Update binaries 2017-02-04 18:59:52 +08:00
topjohnwu
db501822ef Update busybox handling 2017-02-04 18:44:07 +08:00
topjohnwu
ef9948a967 Move MagiskHide initialization to Magisk Manager 2017-02-01 23:22:26 +08:00
topjohnwu
298f09402f Introduce MagiskSU 2017-02-01 06:08:59 +08:00
topjohnwu
d4149d4b7a Update native parts 2017-02-01 06:03:05 +08:00
topjohnwu
3315228a90 Properly handle loading prop files
1. Add new trigger "load_magisk_props_action" in init.magisk.rc
2. Patch init*.rc with new trigger
3. Update resetprop to handle prop value with spaces
4. Handle the case when modules contains file/folder names with spaces
2017-01-09 02:23:00 +08:00
topjohnwu
f72205c401 Fix binary outdated complain 2017-01-03 09:37:45 +08:00
topjohnwu
11862bbaee Remove apps from whitelist, causes issues 2017-01-03 09:37:03 +08:00
topjohnwu
8d846993ee Load system.prop; longer waiting time 2017-01-03 01:55:19 +08:00
topjohnwu
1f84626278 Handle /cache/su.img 2017-01-02 17:48:50 +08:00
topjohnwu
b4cfe6e9c0 Proper vendor support 2017-01-02 17:48:34 +08:00
topjohnwu
94a861e318 Update uninstaller 2017-01-02 03:35:30 +08:00
topjohnwu
1421e775d2 Remove system root 2017-01-02 03:00:03 +08:00
topjohnwu
f8eab72c7a Install Magisk Manager stub if not installed 2017-01-02 02:31:59 +08:00
topjohnwu
2afd2f0d3b More SuperSU support 2017-01-02 02:00:53 +08:00
topjohnwu
2b72f40cec Upgrade phh su 2017-01-02 01:28:24 +08:00
topjohnwu
ff5c0d6361 MagiskHide small fix 2017-01-01 20:31:08 +08:00
topjohnwu
198b14e5fc Fixed various Magic Mount bugs 2017-01-01 19:45:06 +08:00
topjohnwu
f9fea265cf Small updates for MagiskHide 2017-01-01 18:54:13 +08:00
topjohnwu
668601ca23 Separate all binaries and makefile 2016-12-31 02:44:24 +08:00
topjohnwu
99406f2099 Separate all Android.mk files 2016-12-30 06:06:19 +08:00
topjohnwu
632b3cb9ae Higher priority; compare whole string instead substr 2016-12-30 06:05:33 +08:00
topjohnwu
0bf04c04f9 Final fix for MagiskHide, all is well! 2016-12-29 23:25:11 +08:00
topjohnwu
dc29018ec0 Reduce wait interval and various bug fixes 2016-12-28 15:28:42 +08:00
topjohnwu
b6412afe96 Fix Magisk Hide losing root issue
This is the issue that has been haunting since day 1. Root and mounted files randomly disappears, and only an reboot can fix it.
The issue is that Zygote requires some time to isolate the mount namespace for the children it forks (read: most processes), so in rare cases such as the CPU is on heavy load, or CPU is in deep sleep, it takes longer than usual to finish the mount namespace isolation. Magisk Hide kicks in before the isolation is done, and it will switch to Zygote's namespace and do the unmounting. All children will then lose the mounted files, which includes root.
The solution is to first find the namespace id of Zygote, and wait a small period of time and retry if the namespace isn't isolated yet.
2016-12-28 04:02:35 +08:00
topjohnwu
4e88186903 Move /sbin binaries to new location for root
Finally fix #12
2016-12-22 20:03:35 +08:00
Paulo d'Castro
f387378b69 Bump support 2016-12-22 20:02:29 +08:00
Paulo d'Castro
f894e6b4ea Uninstaller bump support 2016-12-22 20:02:29 +08:00
topjohnwu
e33f5996f3 Disable MagiskHide when SuperSU detected 2016-12-18 22:50:27 +08:00
topjohnwu
8f7f1ff7dd Fix boot image backup overwrites when upgrade 2016-12-18 22:45:31 +08:00
topjohnwu
54a0e52e05 Minor script fix 2016-12-18 19:05:18 +08:00
topjohnwu
b2431b982f Prettify code 2016-12-11 05:10:48 +08:00
topjohnwu
8d6d619eed Fork once only
Right now there are three threads (process)
1. Main thread in parent: monitor logcat
2. Second thread in parent: monitor hidelist
3. Children: switch namespace and unmounts
2016-12-11 04:56:01 +08:00
topjohnwu
70e332b9e8 MagiskHide small update 2016-12-11 03:41:29 +08:00
topjohnwu
0a53c42a8a Improve phh su installation 2016-12-10 23:48:24 +08:00
topjohnwu
0ccc92dc1e Minor restructure 2016-12-09 15:57:10 +08:00
topjohnwu
c9157cc13b Fix bug in clone dummy 2016-12-08 21:31:34 +08:00
topjohnwu
2b1270381d Install phh su if no SuperSU detected 2016-12-08 01:50:10 -08:00
topjohnwu
cdb8ee3946 Fix #19 uninstaller issues 2016-12-08 01:24:27 -08:00
topjohnwu
1e3586621b Magic Mount Total Re-factor Part 2
1. It seems that many part of the system is upset about symlinks, revert to bind mounts
2. New system and vendor mirror implementation found, no need to copy anything
3. Thanks to the new mirror implementation, adding new items to /system and /vendor is now possible
4. Re-written some coding style
2016-12-08 00:58:22 -08:00
topjohnwu
c07e9ac29d Magic Mount total re-factor
1. Remove stage 4 bind which mount files back, use symlinks instead
2. libs do not support symlink, make a copy to data if needed
3. Proper support for adding new files into /system/vendor on devices with separate vendor partition
2016-12-07 01:45:09 +08:00
topjohnwu
6e3bb48574 Add su binary into Magisk 2016-12-06 04:49:35 +08:00
topjohnwu
16d7ae62bd Move selinux submodule 2016-12-06 03:09:15 +08:00
topjohnwu
eea3cb32a5 Add Windows build scripts and fix script bugs 2016-12-06 02:45:51 +08:00
topjohnwu
670fe8590c Various fixes
Fixes #13 and #17
2016-11-29 04:19:36 +08:00
topjohnwu
30c048723c Update installer 2016-11-15 04:46:01 +08:00
topjohnwu
85dc669ddf Mount magisk.img with option suid
Should fix #12, hope so :)
2016-11-14 11:00:56 +08:00
topjohnwu
397c1a1c2b Magisk Hide won't play well with dummy lib 2016-11-14 05:02:57 +08:00
topjohnwu
f1d3e35aac Proper support for special mounts 2016-11-14 04:30:05 +08:00
topjohnwu
0e69201f05 Remove UID check, not reliable.... 2016-11-14 04:27:43 +08:00
topjohnwu
f8fdaf5c1f Initialize is not needed 2016-11-13 21:22:04 +08:00
topjohnwu
1f3b81338c Fix Moto DTB issue 2016-11-13 21:03:00 +08:00
topjohnwu
5921d3a42a Update scripts 2016-11-13 21:02:35 +08:00
topjohnwu
dbbc85719e MagiskHide: Unmount cache mounts and check UID 2016-11-13 19:27:01 +08:00
topjohnwu
0ddb6c3f10 Various small changes 2016-11-13 16:58:43 +08:00
topjohnwu
e13281726c Add bootanim, host, busybox 2016-11-09 05:17:14 +08:00
topjohnwu
0ddf4355a1 Update build.sh 2016-11-09 05:16:03 +08:00
topjohnwu
7c8a3ca1a8 Revert to 1.25.0 as 1.25.1 is faulty 2016-11-09 04:41:34 +08:00
topjohnwu
3068738a70 MagiskHide small tweak 2016-11-07 23:57:21 +08:00
topjohnwu
cfa0d8b7c0 gitmodule typo fix 2016-11-06 05:00:58 +08:00
topjohnwu
7ac41652f7 Brand new dummy cloning: No bugs and faster 2016-11-06 04:47:54 +08:00
topjohnwu
24a510bc2e Kill process after remove from list 2016-11-06 02:43:57 +08:00
topjohnwu
0498540439 Magisk Hide: Unmount dummy skeleton 2016-11-06 02:09:14 +08:00
topjohnwu
da94c2e1e5 Update build.sh to detect failures 2016-11-06 01:33:55 +08:00
topjohnwu
bcdd74514f Adjust scripts for resetprop 2016-11-05 02:38:10 +08:00
topjohnwu
1d0c36a0ab Add resetprop to Magisk 2016-11-05 02:38:10 +08:00
topjohnwu
a34ea8f131 Magisk Hide Massive Update 2016-11-01 04:21:43 +08:00
topjohnwu
7fbfa6a52b Remove custom patch script in uninstaller 2016-10-30 20:09:32 +08:00
topjohnwu
799ef3380d Update build script 2016-10-30 19:32:36 +08:00
topjohnwu
d5087858ca Add build scripts
Building through the build script will compile all binaries, and generate a properly signed zip
Should work on linux and macOS environments
2016-10-30 19:11:26 +08:00
Pierre-Hugues Husson
d9fc5650b8 Oops, MTK rootfs/recovery detection had wrong offset 2016-10-30 06:57:50 +08:00
topjohnwu
9ea028f5ab Various updates, prepare for Multirom support 2016-10-30 06:50:06 +08:00
topjohnwu
aa309087fd Update flash script 2016-10-30 06:50:06 +08:00
topjohnwu
57bdd9d3bf Update busybox to 1.25.1 2016-10-30 06:11:48 +08:00
topjohnwu
dc9871fe5b Update binaries 2016-10-30 06:11:22 +08:00
topjohnwu
3255ca3ea4 Remove unnecessary statics 2016-10-30 06:08:23 +08:00
167 changed files with 29885 additions and 2005 deletions

18
.gitattributes vendored Normal file
View File

@@ -0,0 +1,18 @@
# Set the default behavior, in case people don't have core.autocrlf set.
* text eol=lf
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
# *.c text
# *.h text
# Declare files that will always have CRLF line endings on checkout.
*.cmd text eol=crlf
*.bat text eol=crlf
# Denote all files that are truly binary and should not be modified.
chromeos/** binary
*.jar binary
*.exe binary
*.apk binary
*.png binary

17
.gitignore vendored
View File

@@ -1,3 +1,16 @@
obj
libs
out
*.zip
*.jks
*.apk
# Built binaries
ziptools/zipadjust
# Android Studio / Gradle
*.iml
.gradle
/local.properties
/.idea
/build
/captures
.externalNativeBuild

31
.gitmodules vendored
View File

@@ -1,6 +1,27 @@
[submodule "selinux"]
path = selinux
url = https://github.com/topjohnwu/selinux
[submodule "jni/sepolicy-inject"]
path = jni/sepolicy-inject
url = https://github.com/topjohnwu/sepolicy-inject
path = native/jni/external/selinux
url = https://github.com/topjohnwu/selinux.git
[submodule "su"]
path = native/jni/su
url = https://github.com/topjohnwu/MagiskSU.git
[submodule "magiskpolicy"]
path = native/jni/magiskpolicy
url = https://github.com/topjohnwu/magiskpolicy.git
[submodule "MagiskManager"]
path = app
url = https://github.com/topjohnwu/MagiskManager.git
[submodule "busybox"]
path = native/jni/external/busybox
url = https://github.com/topjohnwu/ndk-busybox.git
[submodule "dtc"]
path = native/jni/external/dtc
url = https://github.com/dgibson/dtc
[submodule "lz4"]
path = native/jni/external/lz4
url = https://github.com/lz4/lz4.git
[submodule "bzip2"]
path = native/jni/external/bzip2
url = https://github.com/nemequ/bzip2.git
[submodule "xz"]
path = native/jni/external/xz
url = https://github.com/xz-mirror/xz.git

674
LICENSE Normal file
View File

@@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
{one line to give the program's name and a brief idea of what it does.}
Copyright (C) {year} {name of author}
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
{project} Copyright (C) {year} {fullname}
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

View File

@@ -1,3 +1,79 @@
# Magisk
Static binaries included:
* Busybox: http://forum.xda-developers.com/android/software-hacking/tool-busybox-flashable-archs-t3348543
## How to build Magisk
#### Building has been tested on 3 major platforms: macOS, Ubuntu, Windows 10
### Environment Requirements
1. Python 3.5+: run `build.py` script
2. Java Development Kit (JDK) 8: Compile Magisk Manager and sign zips
3. Latest Android SDK: `ANDROID_HOME` environment variable should point to the Android SDK folder
4. Android NDK: Install NDK along with SDK (`$ANDROID_HOME/ndk-bundle`), or specify custom path `ANDROID_NDK`
5. (Windows Only) Python package Colorama: Install with `pip install colorama`, used for ANSI color codes
### Instructions and Notes
1. Magisk can be built with the latest NDK (r16 as of writing), however binaries released officially will be built with NDK r10e due to ELF incompatibilities with the binaries built from the newer NDKs.
2. The easiest way to setup the environment is by importing the folder as an Android Studio project. The IDE will download required components and construct the environment for you. You still have to set the `ANDROID_HOME` environment variable to point to the SDK path.
3. Run `build.py` with argument `-h` to see the built-in help message. The `-h` option also works for each supported actions, e.g. `./build.py binary -h`
4. Build everything with `build.py`, don't directly call `gradlew` or `ndk-build`, since most requires special setup / dependencies.
5. By default, `build.py` will build binaries and Magisk Manager in debug mode. If you want to build Magisk Manager in release mode (through the flag `--release`), you will need to place a Java Keystore file at `release_signature.jks` to sign Magisk Manager's APK. For more information, check out [Google's Official Documentation](https://developer.android.com/studio/publish/app-signing.html#signing-manually).
## License
```
Magisk, including all git submodules are free software:
you can redistribute it and/or modify it under the terms of the
GNU General Public License as published by the Free Software Foundation,
either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
```
## Credits
**MagiskManager** (`app`)
* Copyright 2016-2018, John Wu (@topjohnwu)
* All contributors and translators on Github
**MagiskSU** (`native/jni/su`)
* Copyright 2016-2018, John Wu (@topjohnwu)
* Copyright 2015, Pierre-Hugues Husson (phh@phh.me)
* Copyright 2013, Koushik Dutta (@koush)
* Copyright 2010, Adam Shanks (@ChainsDD)
* Copyright 2008, Zinx Verituse (@zinxv)
**MagiskPolicy** (`native/jni/magiskpolicy`)
* Copyright 2016-2018, John Wu (@topjohnwu)
* Copyright 2015, Pierre-Hugues Husson (phh@phh.me)
* Copyright 2015, Joshua Brindle (@joshua_brindle)
**MagiskHide** (`native/jni/magiskhide`)
* Copyright 2016-2018, John Wu (@topjohnwu)
* Copyright 2016, Pierre-Hugues Husson (phh@phh.me)
**resetprop** (`native/jni/resetprop`)
* Copyright 2016-2018 John Wu (@topjohnwu)
* Copyright 2016 nkk71 (nkk71x@gmail.com)
**External Dependencies** (`native/jni/external`)
* Makefile for busybox, generated by [ndk-busybox-kitchen](https://github.com/topjohnwu/ndk-busybox-kitchen)
* Each dependencies has its own license/copyright information in each subdirectory.
All of them are either GPL or GPL compatible.
**Others Not Mentioned**
* Copyright 2016-2018, John Wu (@topjohnwu)

1
app Submodule

Submodule app added at 0c782edf21

27
build.gradle Normal file
View File

@@ -0,0 +1,27 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}

402
build.py Executable file
View File

@@ -0,0 +1,402 @@
#!/usr/bin/env python3
import sys
import os
import subprocess
if os.name == 'nt':
from colorama import init
init()
def error(str):
print('\n' + '\033[41m' + str + '\033[0m' + '\n')
sys.exit(1)
def header(str):
print('\n' + '\033[44m' + str + '\033[0m' + '\n')
# Environment checks
if not sys.version_info >= (3, 5):
error('Requires Python >= 3.5')
if 'ANDROID_HOME' not in os.environ:
error('Please add Android SDK path to ANDROID_HOME environment variable!')
try:
subprocess.run(['java', '-version'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
except FileNotFoundError:
error('Please install Java and make sure \'java\' is available in PATH')
import argparse
import multiprocessing
import zipfile
import datetime
import errno
import shutil
import lzma
import base64
import tempfile
if 'ANDROID_NDK' in os.environ:
ndk_build = os.path.join(os.environ['ANDROID_NDK'], 'ndk-build')
else:
ndk_build = os.path.join(os.environ['ANDROID_HOME'], 'ndk-bundle', 'ndk-build')
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:
os.remove(file)
except OSError as e:
if e.errno != errno.ENOENT:
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):
if not os.path.exists(source):
error('{} does not exist! Try build \'binary\' and \'apk\' before zipping!'.format(source))
print('zip: {} -> {}'.format(source, target))
zipfile.write(source, target)
def build_all(args):
build_binary(args)
build_apk(args)
zip_main(args)
zip_uninstaller(args)
build_snet(args)
def build_binary(args):
header('* Building Magisk binaries')
# Force update logging.h timestamp to trigger recompilation
os.utime(os.path.join('native', 'jni', 'include', 'logging.h'))
debug_flag = '' if args.release else '-DMAGISK_DEBUG'
cflag = 'MAGISK_FLAGS=\"-DMAGISK_VERSION=\\\"{}\\\" -DMAGISK_VER_CODE={} {}\"'.format(args.versionString, args.versionCode, debug_flag)
# Prebuild
proc = subprocess.run('{} -C native PRECOMPILE=true {} -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']:
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')
mv(os.path.join('native', 'libs', arch, 'magisk'), os.path.join('out', arch, 'magisk'))
with open(os.path.join('out', arch, 'magisk'), 'rb') as bin:
dump.write('const uint8_t magisk_dump[] = "')
dump.write(''.join("\\x{:02X}".format(c) for c in lzma.compress(bin.read(), preset=9)))
dump.write('";\n')
print('')
proc = subprocess.run('{} -C native {} -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 ['magiskinit', 'magiskboot', 'b64xz', 'busybox']:
try:
mv(os.path.join('native', 'libs', arch, binary), os.path.join('out', arch, binary))
except:
pass
def build_apk(args):
header('* Building Magisk Manager')
mkdir(os.path.join('app', 'src', 'main', 'assets'))
for script in ['magisk_uninstaller.sh', 'util_functions.sh']:
source = os.path.join('scripts', script)
target = os.path.join('app', 'src', 'main', 'assets', script)
cp(source, target)
if args.release:
if not os.path.exists('release_signature.jks'):
error('Please generate a java keystore and place it in \'release_signature.jks\'')
proc = subprocess.run('{} app:assembleRelease'.format(os.path.join('.', 'gradlew')), shell=True)
if proc.returncode != 0:
error('Build Magisk Manager failed!')
unsigned = os.path.join('app', 'build', 'outputs', 'apk', 'release', 'app-release-unsigned.apk')
aligned = os.path.join('app', 'build', 'outputs', 'apk', 'release', 'app-release-aligned.apk')
release = os.path.join('app', 'build', 'outputs', 'apk', 'release', 'app-release.apk')
# Find the latest build tools
build_tool = sorted(os.listdir(os.path.join(os.environ['ANDROID_HOME'], 'build-tools')))[-1]
rm(aligned)
rm(release)
proc = subprocess.run([
os.path.join(os.environ['ANDROID_HOME'], 'build-tools', build_tool, 'zipalign'),
'-v', '-p', '4', unsigned, aligned], stdout=subprocess.DEVNULL)
if proc.returncode != 0:
error('Zipalign Magisk Manager failed!')
# Find apksigner.jar
apksigner = ''
for root, dirs, files in os.walk(os.path.join(os.environ['ANDROID_HOME'], 'build-tools', build_tool)):
if 'apksigner.jar' in files:
apksigner = os.path.join(root, 'apksigner.jar')
break
if not apksigner:
error('Cannot find apksigner.jar in Android SDK build tools')
proc = subprocess.run('java -jar {} sign --ks {} --out {} {}'.format(
apksigner, 'release_signature.jks', release, aligned), shell=True)
if proc.returncode != 0:
error('Release sign Magisk Manager failed!')
rm(unsigned)
rm(aligned)
mkdir('out')
target = os.path.join('out', 'app-release.apk')
print('')
mv(release, target)
else:
proc = subprocess.run('{} app:assembleDebug'.format(os.path.join('.', 'gradlew')), shell=True)
if proc.returncode != 0:
error('Build Magisk Manager failed!')
source = os.path.join('app', 'build', 'outputs', 'apk', 'debug', 'app-debug.apk')
mkdir('out')
target = os.path.join('out', 'app-debug.apk')
print('')
mv(source, target)
def build_snet(args):
proc = subprocess.run('{} snet:assembleRelease'.format(os.path.join('.', 'gradlew')), shell=True)
if proc.returncode != 0:
error('Build snet extention failed!')
source = os.path.join('snet', 'build', 'outputs', 'apk', 'release', 'snet-release-unsigned.apk')
mkdir('out')
target = os.path.join('out', 'snet.apk')
print('')
mv(source, target)
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')
unsigned = tempfile.mkstemp()[1]
with zipfile.ZipFile(unsigned, '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 ['magiskinit', '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(unsigned, output)
def zip_uninstaller(args):
header('* Packing Uninstaller Zip')
unsigned = tempfile.mkstemp()[1]
with zipfile.ZipFile(unsigned, '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
target = os.path.join('util_functions.sh')
print('zip: ' + source + ' -> ' + target)
zipf.writestr(target, script.read())
# 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(unsigned, output)
def sign_adjust_zip(unsigned, output):
signer_name = 'zipsigner-2.1.jar'
jarsigner = os.path.join('utils', 'build', 'libs', signer_name)
if not os.path.exists(jarsigner):
header('* Building ' + signer_name)
proc = subprocess.run('{} utils:shadowJar'.format(os.path.join('.', 'gradlew')), shell=True)
if proc.returncode != 0:
error('Build {} failed!'.format(signer_name))
header('* Signing Zip')
signed = tempfile.mkstemp()[1]
proc = subprocess.run(['java', '-jar', jarsigner, unsigned, output])
if proc.returncode != 0:
error('Signing zip failed!')
def cleanup(args):
if len(args.target) == 0:
args.target = ['binary', 'java', 'zip']
if 'binary' in args.target:
header('* Cleaning binaries')
subprocess.run(ndk_build + ' -C native PRECOMPILE=true clean', shell=True)
subprocess.run(ndk_build + ' -C native 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:
header('* Cleaning java')
subprocess.run('{} app:clean snet:clean utils:clean'.format(os.path.join('.', 'gradlew')), shell=True)
for f in os.listdir('out'):
if '.apk' in f:
rm(os.path.join('out', f))
if 'zip' in args.target:
header('* Cleaning zip files')
for f in os.listdir('out'):
if '.zip' in f:
rm(os.path.join('out', f))
parser = argparse.ArgumentParser(description='Magisk build script')
parser.add_argument('--release', action='store_true', help='compile Magisk for release')
subparsers = parser.add_subparsers(title='actions')
all_parser = subparsers.add_parser('all', help='build everything and create flashable zip with uninstaller')
all_parser.add_argument('versionString')
all_parser.add_argument('versionCode', type=int)
all_parser.set_defaults(func=build_all)
binary_parser = subparsers.add_parser('binary', help='build Magisk binaries')
binary_parser.add_argument('versionString')
binary_parser.add_argument('versionCode', type=int)
binary_parser.set_defaults(func=build_binary)
apk_parser = subparsers.add_parser('apk', help='build Magisk Manager APK')
apk_parser.set_defaults(func=build_apk)
snet_parser = subparsers.add_parser('snet', help='build snet extention for Magisk Manager')
snet_parser.set_defaults(func=build_snet)
zip_parser = subparsers.add_parser('zip', help='zip and sign Magisk into a flashable zip')
zip_parser.add_argument('versionString')
zip_parser.add_argument('versionCode', type=int)
zip_parser.set_defaults(func=zip_main)
uninstaller_parser = subparsers.add_parser('uninstaller', help='create flashable uninstaller')
uninstaller_parser.set_defaults(func=zip_uninstaller)
clean_parser = subparsers.add_parser('clean', help='clean [target...] targets: binary java zip')
clean_parser.add_argument('target', nargs='*')
clean_parser.set_defaults(func=cleanup)
if len(sys.argv) == 1:
parser.print_help()
sys.exit(1)
args = parser.parse_args()
args.func(args)

36
docs/README.MD Normal file
View File

@@ -0,0 +1,36 @@
# Magisk Documentations
(Updated on 2018.1.8) ([Changelog](changelog.md))
## Table of Contents
- [Introduction](#introduction)
- [Tips and Tricks](tips.md)
- [OTA Installation Tips](tips.md#ota-installation-tips)
The following are for developers
- [Procedure Diagram](https://cdn.rawgit.com/topjohnwu/Magisk/7d1082b1cb91db90ed0a29d8b092723fc3d69c58/docs/procedures.html)
- [Magisk Details](details.md)
- [Boot Stages](details.md#boot-stages)
- [Magic Mount Details](details.md#magic-mount-details)
- [Simple Mount Details](details.md#simple-mount-details)
- [Available Tools](tools.md)
- [magiskboot](tools.md#magiskboot)
- [magiskinit](tools.md#magiskinit)
- [magiskpolicy](tools.md#magiskpolicy)
- [magisk](tools.md#magisk)
- [su](tools.md#su)
- [resetprop](tools.md#resetprop)
- [magiskhide](tools.md#magiskhide)
- [Modules](modules.md)
- [Modules and Templates](modules.md#magisk-module-format)
- [Submit Modules to Repo](https://github.com/topjohnwu/Magisk_Repo_Submissions)
- [Tips and Tricks](tips.md)
- [Remove Files](tips.md#remove-files)
- [Remove Folders](tips.md#remove-folders)
## Introduction
Magisk is a suite of open source tools for devices running Android version higher than 5.0 Lollipop (API 21). It establishes an environment which covers most stuffs you need for Android customization, such as root, boot scripts, SELinux patches, AVB2.0 / dm-verity / forceencrypt patches etc..
Furthermore, Magisk provides a **Systemless Interface** to alter the system (or vendor) arbitrarily while the actual partitions stay completely intact, all of which accomplished by only patching the boot image. With its systemless nature along with several other hacks, Magisk can hide modifications from nearly any existing system integrity verifications, one of the main target is to hide from [Google's SafetyNet API](https://developer.android.com/training/safetynet/index.html).

8
docs/changelog.md Normal file
View File

@@ -0,0 +1,8 @@
# Changelog
- 2017.8.16
- Initial version for Magisk v13.5
- 2017.9.28
- Update applets info to Magisk v14.1
- Add OTA tips
- 2017.1.8
- Update to Magisk v15.2

59
docs/details.md Normal file
View File

@@ -0,0 +1,59 @@
## Boot Stages
If you are working on complicated projects, you shall need more control to the whole process. Magisk can run scripts in different boot stages, so you can fine tune exactly what you want to do. It's recommended to read this documentation along with the procedure graph.
- post-fs mode
- **This stage is BLOCKING. Boot process will NOT continue until everything is done, or 10 seconds has passed**
- Happens after most partitions are mounted. `/data` might not be available since `vold` is not started yet
- Magisk will bind mount files under `/cache/magisk_mount/system` and `/cache/magisk_mount/vendor`
- It is only **Simple Mount**, which means it will replace existing files, but cannot add/remove files.
- This part is mostly deprecated (reasons in details)
- post-fs-data mode
- **This stage is BLOCKING. Boot process will NOT continue until everything is done, or 10 seconds has passed**
- Happens after `/data` is ready (including the case when `/data` is encrypted)
- Happens before Zygote and system servers are started (which means pretty much everything)
- `/data/adb/magisk.img` will be merged, trimmed, and mounted to `MOUNTPOINT=/sbin/.core/img`
- Magisk will run scripts under `$MOUNTPOINT/.core/post-fs-data.d`
- Magisk will run scripts: `$MOUNTPOINT/$MODID/post-fs-data.sh` (placed in each module directory)
- Magisk will finally **Magisk Mount** module files
- late_start service mode
- **This stage is NON-BLOCKING, it will run in parallel with other processes**
- Happens when class late_start is triggered
- The daemon will wait for the full `sepolicy` patch before running this stage, so SELinux is guaranteed to be fully patched
- Put time consuming scripts here. Boot process will get stuck if it took too long to finish your tasks in `post-fs-data`
- **It is recommended to run all scripts in this stage**, unless your scripts requires doing stuffs before Zygote is started
- Magisk will run scripts under `$MOUNTPOINT/.core/service.d`
- Magisk will run scripts: `$MOUNTPOINT/$MODID/service.sh` (placed in each module directory)
## Magic Mount Details
### Terminology
- **Item**: A folder, file, or symbolic link
- **Leaf**: An item that is on the very end of a directory structure tree. It can be either a file or symbolic link
- **`$MODPATH`**: A variable to represent the path of a module folder
- **Source item**: An item under `$MODPATH/system`, for example, `$MODPATH/system/bin/app_process32` is a source item
- **Existing item**: An item in the actual filesystem, for example, `/system/bin/app_process32` is an existing item
- **Target item**: The corresponding item of a source item. For example, the target item of `$MODPATH/system/bin/app_process32` is `/system/bin/app_process32`
Note: A target item **does not** imply it is an existing item. A target item might not exist in the actual filesystem
### Policies
- For a source leaf: if its target item is also an existing item, the existing item will be replaced with the source leaf
- For a source leaf: if its target item is not an existing item, the source leaf will be added to the path of its target item
- For any existing item that's not a target item, it will stay intact
Above is the rule of thumb. Basically it means that Magic Mount merges the two folders, `$MODPATH/system` into `/system`. A simpler way to understand is to think as the items is dirty copied from `$MODPATH/system` into `/system`.
However, an addition rule will override the above policies:
- For a source folder containing the file `.replace`, the source folder will be treated as if it is a leaf. That is, the items within the target folder will be completely discarded, and the target folder will be replaced with the source folder.
Directories containing a file named `.replace` will **NOT** be merged, instead it directly replaces the target directory. A simpler way to understand is to think as if it wipes the target folder, and then copies the whole folder to the target path.
### Notes
- If you want to replace files in `/vendor`, please place it under `$MODPATH/system/vendor`. Magisk will handle both cases, whether the vendor partition is separated or not under-the-hood, developers don't need to bother.
- Sometimes, completely replacing a folder is inevitable. For example you want to replace `/system/priv-app/SystemUI` in your stock rom. In stock roms, system apps usually comes with pre-optimized files. If your replacement `SystemUI.apk` is deodexed (which is most likely the case), you would want to replace the whole `/system/priv-app/SystemUI` to make sure the folder only contains the modified `SystemUI.apk` without the pre-optimized files.
- If you are using the [Magisk Module Template](https://github.com/topjohnwu/magisk-module-template), you can create a list of folders you want to replace in the file `config.sh`. The installation scripts will handle the creation of `.replace` files into the listed folders for you.
## Simple Mount Details
(Note: this part is mostly deprecated, since starting with devices using A/B partitions, there is no longer a dedicated partition for cache because OTAs are applied live at boot. Instead, `/cache` now points to `/data/cache`, which means `post-fs` mode does not have access to `/cache` anymore)
Some files require to be mounted much earlier in the boot process, currently known are bootanimation and some libs (most users won't change them). You can simply place your modified files into the corresponding path under `/cache/magisk_mount`. For example, you want to replace `/system/media/bootanimation.zip`, copy your new boot animation zip to `/cache/magisk_mount/system/media/bootanimation.zip`, and Magisk will mount your files in the next reboot. Magisk will **clone all the attributes from the target file**, which includes selinux context, permission mode, owner, group. This means you don't need to worry about the metadata for files placed under `/cache/magisk_mount`: just copy the file to the correct place, reboot then you're done!

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 KiB

BIN
docs/images/flashfire.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 KiB

BIN
docs/images/ota_step2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
docs/images/restore_img.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

49
docs/modules.md Normal file
View File

@@ -0,0 +1,49 @@
# Magisk Modules
## Magisk Module Format
A Magisk module is a folder placed in the root folder in `magisk.img`, which has a structure as described below:
```
$MOUNTPOINT
├── .
├── .
├── $MODID <--- The ID of the module, should match with module.prop
│   ├── auto_mount <--- If this file exists, auto mount is enabled
│   ├── disable <--- If this file exists, the module is disabled
│   ├── module.prop <--- This files stores the identity and properties of the module
│   ├── post-fs-data.sh <--- This script will be executed in post-fs-data
│   ├── remove <--- If this file exists, the module will be removed next reboot
│   ├── service.sh <--- This script will be executed in late_start service
│   ├── system.prop <--- This file will be loaded as system props
│   ├── system <--- If auto mount is enabled, Magisk will "Magic Mount" this folder
│   │   ├── .
│   │   ├── .
│   │   └── .
│   ├── vendor <--- Auto generated. A symlink to $MODID/system/vendor
│   ├── . <--- Any other files/folders are allowed
│   └── .
├── another_module
│   ├── .
│   └── .
├── .
├── .
```
You are not required to use my Magisk Module Template to create a module. As long as you place files with the structure above, it will be recognized as a module.
## Magisk Module Template
The **Magisk Module Template** is hosted **[here](https://github.com/topjohnwu/magisk-module-template)**.
It is a template to create a flashable zip to install Magisk Modules. It is designed to be simple to use so that anyone can create their own modules easily. The template itself contains minimal scripting for installation; most of the functions are located externally in [util_functions.sh](https://github.com/topjohnwu/Magisk/blob/master/scripts/util_functions.sh), which will be installed along with Magisk, and can be upgraded through a Magisk upgrade without the need of a template update.
Here are some files you would want to know:
- `config.sh`: A simple script used as a configuration file. It is the place to configure which features your module needs/disables. A detailed instructions on how to use the template is also written in this file.
- `module.prop`: This file contains your module's indentity and properties, including name and versions etc.. This file will be used to identify your module on an actual device and in the [Magisk Modules Repo](https://github.com/Magisk-Modules-Repo)
- `common/*`: Boot stage scripts and `system.prop`
- `META-INF/com/google/android/update-binary`: The actual installation script. Modify this file for advanced custom behavior
And here are some notes to be aware of:
- The template depends on external Magisk scripts, please specify the correct `minMagisk` value in `module.prop` with the template version your module is based on, or the minimum Magisk version your module is tested on.
- **Windows users please check here!!** The line endings of all text files should be in the **Unix format**. Please use advanced text editors like Sublime, Atom, Notepad++ etc. to edit **ALL** text files, **NEVER** use Windows Notepad.
- In `module.prop`, `version` can be an arbitrary string, so any fancy version name (e.g. `ultra-beta-v1.1.1.1`) is allowed. However, `versionCode` **MUST** be an integer. The value is used for version comparison.
- Make sure your module ID **does not contain any spaces**.

11
docs/procedures.html Normal file

File diff suppressed because one or more lines are too long

53
docs/tips.md Normal file
View File

@@ -0,0 +1,53 @@
# Tips and Tricks
## OTA Installation Tips
Magisk does modifications systemless-ly, which means applying official OTAs is much simpler. Here I provide a few tutorials for several different kind of devices to apply OTAs and preserve Magisk after the installation if possible.
**This tutorial is only for Magisk v14.1+**
**NOTE: In order to apply OTAs, you HAVE to make sure you haven't modified `/system` (and `/vendor` if available) in anyway, even remounting the partition to rw will tamper block verification!!**
#### Prerequisites
1. Please disable *Automatic system updates* in developer options, so it won't install OTAs without your acknowledgement.
<img src="images/disable_auto_ota.png" width="250">
1. When an OTA is available, please go to Magisk Manager → Uninstall → Restore Images. **Do not reboot immediately or you will have Magisk uninstalled.** This will restore your boot (or dtbo if available) back to 100% untouched stock images in order to pass verifications. **This step is required before doing any of the following steps written below!**
<img src="images/restore_img.png" width="250">
#### Devices with A/B Partitions
(Includes Pixel family)
Due to the fact that these devices have two separate partitions and the OTA installation happens live when the system is still running, these devices have the best support: the out-of-the-box OTA installation works seamlessly and Magisk will be preserved after the installation.
1. After restoring stock boot image, apply OTAs as you normally would (Settings → System → System Updates)
1. Once the installation passed step 1 and starting step 2, go to Magisk Manager → Install → Install to Second Slot. This will install Magisk into the second boot image slot, which is the updated slot.
<img src="images/ota_step2.png" width="250"> <img src="images/install_second_slot.png" width="250">
1. Let the OTA finish its job. After a reboot, the bootloader will switch to the updated system. Magisk should still be installed since we already patched the new boot image.
#### Devices with FlashFire Support
(Includes Pixel family, Nexus family, Samsung devices)
(If you are using a device with A/B partitions, I **strongly** recommend you to use the method stated above since it uses the stock OTA installation mechanism and will always work under any circumstances)
The [FlashFire](https://play.google.com/store/apps/details?id=eu.chainfire.flash) app developed by Chainfire is a great app to apply OTAs and preserve root at the same time. However, whether it supports your device/system combination depends on the application itself, and support may also change in the future. If you face any issues, please directly [report to Chainfire](https://forum.xda-developers.com/general/paid-software/flashfire-t3075433).
1. After restoring the stock boot image, download the OTA (Settings → System → System Updates), **do not press reboot to install.**
1. Open FlashFire, it should detect your OTA zip. Select OK in the popup dialog to let it do its setup.
1. Please use the options shown in the screenshot below. The key point is to disable EverRoot (or it will install SuperSU), and add a new action to flash Magisk zip **after** the OTA update.zip (the update.zip is auto generated in the previous step).
<img src="images/flashfire.png" width="250">
1. Press the big **Flash** button, after a few minutes it should reboot updated with Magisk installed.
#### Other Devices - General Case
Unfortunately, there are no real good ways to apply OTAs on all devices. Also, the tutorial provided below will not preserve Magisk - you will have to manually re-root your device after the upgrade, and this will require PC access. Here I share my personal experience with HTC U11.
1. To properly install OTAs, you should have your stock recovery installed on your device. If you have custom recovery installed, you can restore it from your previous backup, or dumps found online, or factory images provided by OEMs.
If you decide to start by installing Magisk without touching your recovery partition, you have a few choices, either way you will end up with a Magisk rooted device, but recovery remain stock untouched:
- If supported, use `fastboot boot <recovery_img>` to boot the custom recovery and install Magisk.
- If you have a copy of your stock boot image dump, install Magisk by patching boot image via Magisk Manager, and manually flash it through download mode / fastboot mode / Odin
1. Once your device have stock recovery and stock boot image restored, download the OTA. Optionally, once you downloaded the OTA update zip, you can find a way to copy the zip out since you are still rooted. Personally I will extract the stock boot image and recovery image from the OTA zip for future usage (to patch via Magisk Manager or restore stock recovery etc.)
1. Apply and reboot your device. This will use the official stock OTA installation mechanism of your device to upgrade your system.
1. Once it's done you will be left with an upgraded, 100% stock, un-rooted device. You will have to manually flash Magisk back. Consider using the methods stated in step 1. to flash Magisk without touching the recovery partition if you want to receive stock OTAs frequently.
## Remove Files
How to remove a file systemless-ly? To actually make the file **disappear** is complicated (possible, not worth the effort). **Replacing it with a dummy file should be good enough**! Create an empty file with the same name and place it in the same path within a module, it shall replace your target file with a dummy file.
## Remove Folders
Same as mentioned above, actually making the folder to **disappear** is not worth the effort. **Replacing it with an empty folder should be good enough**! A handy trick for module developers using [Magisk Module Template](https://github.com/topjohnwu/magisk-module-template) is to add the folder you want to remove into the `REPLACE` list within `config.sh`. If your module doesn't provide a correspond folder, it will create an empty folder, and automatically add `.replace` into the empty folder so the dummy folder will properly replace the one in `/system`.

287
docs/tools.md Normal file
View File

@@ -0,0 +1,287 @@
## Available Tools
Magisk comes with a lot of tools for installation, programs running as a daemon, and utilities for developers. This documentation covers 3 binaries, and many more tools are available as applets. The relation between tools are shown below:
```
magiskboot /* binary */
magiskinit /* binary */
magiskpolicy -> magiskinit
supolicy -> magiskinit /* alias of magiskpolicy */
magisk /* binary */
magiskhide -> magisk
resetprop -> magisk
su -> magisk
```
### magiskboot
A tool to unpack / repack boot images, parse and patch cpio and dtbs, hex patch binaries, compress / decompress with multiple algorithms. It is used to install Magisk into boot images.
`magiskboot` natively supports (which means it does not call external tools) all popular compression methods including `gzip` (used everywhere for compressing kernel and ramdisk), `lz4` (used to compress kernel in modern devices like Pixel), `lz4_legacy` (legacy LZ4 block format with special metadata used [only on LG](https://events.static.linuxfound.org/sites/events/files/lcjpcojp13_klee.pdf) to compress kernel), `lzma` (LZMA1 algorithm natively supported in Linux kernel, used in some custom kernel to compress ramdisk), `xz` (LZMA2 algorithm, very high compression rate, used in Magisk for high compression mode and storing binaries), and `bzip2` (used in desktop Linux boot images to create bzImage, haven't seen on Android yet).
The concept of `magiskboot` is to keep the images as intact as possible. For unpacking, it extracts the large chunks of data (kernel, ramdisk, second, dtb, extra etc.) and decompress them if possible. When repacking a boot image, the original boot image has to be provided so it can use the original headers (including MTK specific headers) with only changing the necessary entries such as the data chunk sizes, and re-compress all data with the original compression method. The same concept also applies to CPIO patching: it does not extract all files, modify in file system, archive all files back to cpio as usually done to create Linux `initramfs`, instead we do modifications directly in the cpio level in memory without involving any data extraction.
Command help message:
```
Usage: magiskboot <action> [args...]
Supported actions:
--parse <bootimg>
Parse <bootimg> only, do not unpack. Return values:
0:OK 1:error 2:insufficient boot partition size
3:chromeos 4:ELF32 5:ELF64
--unpack <bootimg>
Unpack <bootimg> to kernel, ramdisk.cpio, (second), (dtb), (extra) into
the current directory. Return value is the same as --parse
--repack <origbootimg> [outbootimg]
Repack kernel, ramdisk.cpio[.ext], second, dtb... from current directory
to [outbootimg], or new-boot.img if not specified.
It will compress ramdisk.cpio with the same method used in <origbootimg>,
or attempt to find ramdisk.cpio.[ext], and repack directly with the
compressed ramdisk file
--hexpatch <file> <hexpattern1> <hexpattern2>
Search <hexpattern1> in <file>, and replace with <hexpattern2>
--cpio <incpio> [commands...]
Do cpio commands to <incpio> (modifications are done directly)
Each command is a single argument, use quotes if necessary
Supported commands:
rm [-r] ENTRY
Remove ENTRY, specify [-r] to remove recursively
mkdir MODE ENTRY
Create directory ENTRY in permissions MODE
ln TARGET ENTRY
Create a symlink to TARGET with the name ENTRY
mv SOURCE DEST
Move SOURCE to DEST
add MODE ENTRY INFILE
Add INFILE as ENTRY in permissions MODE; replaces ENTRY if exists
extract [ENTRY OUT]
Extract ENTRY to OUT, or extract all entries to current directory
test
Test the current cpio's patch status. Return value:
0:stock 1:Magisk 2:other (phh, SuperSU, Xposed)
patch KEEPVERITY KEEPFORCEENCRYPT
Ramdisk patches. KEEP**** are boolean values
backup ORIG [SHA1]
Create ramdisk backups from ORIG
SHA1 of stock boot image is optional
restore
Restore ramdisk from ramdisk backup stored within incpio
magisk ORIG HIGHCOMP KEEPVERITY KEEPFORCEENCRYPT [SHA1]
Do Magisk patches and backups all in one step
Create ramdisk backups from ORIG
HIGHCOMP, KEEP**** are boolean values
SHA1 of stock boot image is optional
sha1
Print stock boot SHA1 if previously stored
--dtb-<cmd> <dtb>
Do dtb related cmds to <dtb> (modifications are done directly)
Supported commands:
dump
Dump all contents from dtb for debugging
test
Check if fstab has verity/avb flags. Return value:
0:no flags 1:flag exists
patch
Search for fstab and remove verity/avb
--compress[=method] <infile> [outfile]
Compress <infile> with [method] (default: gzip), optionally to [outfile]
<infile>/[outfile] can be '-' to be STDIN/STDOUT
Supported methods: gzip xz lzma bzip2 lz4 lz4_legacy
--decompress <infile> [outfile]
Detect method and decompress <infile>, optionally to [outfile]
<infile>/[outfile] can be '-' to be STDIN/STDOUT
Supported methods: gzip xz lzma bzip2 lz4 lz4_legacy
--sha1 <file>
Print the SHA1 checksum for <file>
--cleanup
Cleanup the current working directory
```
### magiskinit
This tool is created to unify Magisk support for both legacy "normal" devices and new `skip_initramfs` devices. The compiled binary will replace `init` in the ramdisk, so things could be done even before `init` is started.
`magiskinit` is responsible for constructing a proper rootfs on devices which the actual rootfs is placed in the system partition instead of ramdisk in `boot.img`, such as the Pixel familiy and most Treble enabled devices, or I like to call it `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. For normal "traditional" devices, it will simply swap `init` back to the original one and continue on to the next stage.
With a proper rootfs, `magiskinit` goes on and does all pre-init operations to setup a Magisk environment. It patches rootfs on the fly, providing fundamental support such as patching `init`, `init.rc`, run preliminary `sepolicy` patches, and extracts `magisk` and `init.magisk.rc` (these two files are embedded into `magiskinit`). Once all is done, it will spawn another process (`magiskinit_daemon`) to asynchronously run a full `sepolicy` patch, then starts monitoring the main Magisk daemon to make sure it is always running (a.k.a invincible mode); at the same time, it will execute the original `init` to hand the boot process back.
### magiskpolicy
(This tool is aliased to `supolicy` for compatibility with SuperSU's sepolicy tool)
This tool is an applet of `magiskinit`: once `magiskinit` had finished its mission in the pre-init stage, it will preserve an entry point for `magiskpolicy`. This tool could be used for advanced developers messing with `sepolicy`, a compiled binary containing SELinux rules. Normally Linux server admins directly modifies the SELinux policy sources (`*.te`) and recompile the `sepolicy` binary, but here we directly patch the binary file since we don't have access to the sources.
All processes spawned from the Magisk daemon, including root shells and all its forks, are running in the context `u:r:su:s0`. Magisk splits the built in patches into 2 parts: preliminary and full
- The preliminary patch should allow all Magisk internal procedures to run properly (can be done manually by the `--magisk` option). It also contains quite a few additional patches so most scripts can run in the daemon before the full patch is done
- The full patch adds the rule `allow su * * *` on top of the preliminary rules. This is done because stock Samsung ROMs do not support permissive; adding this rule makes the domain effectively permissive. Due to the concern of greatly increasing the boot time, the Magisk daemon will not wait for this patch to finish until the boot stage `late_start` triggers. What this means is that **only `late_start` service mode is guaranteed to run in a fully patched environment**. For non-Samsung devices it doesn't matter because `u:r:su:s0` is permissive anyways, but for full compatibility, it is **highly recommended to run boot scripts in `late_start` service mode**.
Command help message:
```
Usage: magiskpolicy [--options...] [policystatements...]
Options:
--live directly apply patched policy live
--magisk built-in rules for a Magisk selinux environment
--load FILE load policies from <infile>
--save FILE save policies to <outfile>
If no input file is specified, it will load from current policies
If neither --live nor --save is specified, nothing will happen
One policy statement should be treated as one parameter;
this means a full policy statement should be enclosed in quotes;
multiple policy statements can be provided in a single command
The statements has a format of "<action> [args...]"
Use '*' in args to represent every possible match.
Collections wrapped in curly brackets can also be used as args.
Supported policy statements:
Type 1:
"<action> source-class target-class permission-class permission"
Action: allow, deny, auditallow, auditdeny
Type 2:
"<action> source-class target-class permission-class ioctl range"
Action: allowxperm, auditallowxperm, dontauditxperm
Type 3:
"<action> class"
Action: create, permissive, enforcing
Type 4:
"attradd class attribute"
Type 5:
"typetrans source-class target-class permission-class default-class (optional: object-name)"
Notes:
- typetrans does not support the all match '*' syntax
- permission-class cannot be collections
- source-class and target-class can also be attributes
Example: allow { source1 source2 } { target1 target2 } permission-class *
Will be expanded to:
allow source1 target1 permission-class { all-permissions }
allow source1 target2 permission-class { all-permissions }
allow source2 target1 permission-class { all-permissions }
allow source2 target2 permission-class { all-permissions }
```
### magisk
The magisk binary contains all the magic of Magisk, providing all the features Magisk has to offer. When called with the name `magisk`, it works as an utility tool with many helper functions, and also the entry point for `init` to start Magisk services. These helper functions are extensively used by the [Magisk Module Template](https://github.com/topjohnwu/magisk-module-template) and Magisk Manager.
Command help message:
```
Usage: magisk [applet [arguments]...]
or: magisk [options]...
Options:
-c print current binary version
-v print running daemon version
-V print running daemon version code
--list list all available applets
--install [SOURCE] DIR symlink all applets to DIR. SOURCE is optional
--createimg IMG SIZE create ext4 image. SIZE is interpreted in MB
--imgsize IMG report ext4 image used/total size
--resizeimg IMG SIZE resize ext4 image. SIZE is interpreted in MB
--mountimg IMG PATH mount IMG to PATH and prints the loop device
--umountimg PATH LOOP unmount PATH and delete LOOP device
--[init service] start init service
--unlock-blocks set BLKROSET flag to OFF for all block devices
--restorecon fix selinux context on Magisk files and folders
--clone-attr SRC DEST clone permission, owner, and selinux context
Supported init services:
daemon, post-fs, post-fs-data, service
Supported applets:
su, resetprop, magiskhide
```
### su
An applet of `magisk`, the MagiskSU entry point, the good old `su` command.
Command help message:
```
Usage: su [options] [-] [user [argument...]]
Options:
-c, --command COMMAND pass COMMAND to the invoked shell
-h, --help display this help message and exit
-, -l, --login pretend the shell to be a login shell
-m, -p,
--preserve-environment preserve the entire environment
-s, --shell SHELL use SHELL instead of the default /system/bin/sh
-v, --version display version number and exit
-V display version code and exit,
this is used almost exclusively by Superuser.apk
-mm, -M,
--mount-master run in the global mount namespace,
use if you need to publicly apply mounts
```
Note: even though the `-Z, --context` option is not listed above, it actually still exists for compatibility with apps using SuperSU. However MagiskSU will silently ignore the option since it's no more relevant.
### resetprop
An applet of `magisk`, an advanced system property manipulation utility. Here's some background knowledge:
System properties are stored in a hybrid trie/binary tree data structure in memory. These properties are allowed to be read by many processes (natively via `libcutils`, in shells via the `getprop` command); however, only the `init` process have direct write access to the memory of property data. `init` provides a `property_service` to accept property update requests and acts as a gatekeeper, doing things such as preventing **read-only** props to be overridden and storing **persist** props to non-volatile storages. In addition, property triggers registered in `*.rc` scripts are also handled here.
`resetprop` is created by pulling out the portion of source code managing properties from AOSP and try to mimic what `init` is doing. With some hackery the result is that we have direct access to the data structure, bypassing the need to go through `property_service` to gain arbitrary control. Here is a small implementation detail: the data structure and the stack-like memory allocation method does not support removing props (they are **designed NOT** to be removed); prop deletion is accomplished by detaching the target node from the tree structure, making it effectively invisible. As we cannot reclaim the memory allocated to store the property, this wastes a few bytes of memory but it shouldn't be a big deal unless you are adding and deleting hundreds of thousands of props over and over again.
Due to the fact that we bypassed `property_service`, there are a few things developer should to be aware of:
- `on property:foo=bar` triggers registered in `*.rc` scripts will not be triggered when props are changed. This could be a good thing or a bad thing, depending on what behavior you expect. The default behavior of `resetprop` matches the original `setprop`, which **WILL** trigger events (implemented by deleting the prop and set the props via `property_service`), but there is a flag (`-n`) to disable it if you need this special behavior.
- persist props are stored both in memory and in `/data/property`. By default, deleting props will **NOT** remove it from persistent storage, meaning the prop will be restored after the next reboot; reading props will **NOT** read from persistent storage, as this is the behavior of normal `getprop`. With the flag `-p` enabled, deleting props will remove the prop **BOTH** in memory and `/data/property`; props will be read from **BOTH** in memory and persistent storage.
Command help message:
```
Usage: resetprop [flags] [options...]
Options:
-h, --help show this message
(no arguments) print all properties
NAME get property
NAME VALUE set property entry NAME with VALUE
--file FILE load props from FILE
--delete NAME delete property
Flags:
-v print verbose output to stderr
-n set properties without init triggers
only affects setprop
-p access actual persist storage
only affects getprop and deleteprop
```
### magiskhide
An applet of `magisk`, the CLI to control MagiskHide. Use this tool to communicate with the daemon to change MagiskHide settings.
Command help message:
```
Usage: magiskhide [--options [arguments...] ]
Options:
--enable Start magiskhide
--disable Stop magiskhide
--add PROCESS Add PROCESS to the hide list
--rm PROCESS Remove PROCESS from the hide list
--ls Print out the current hide list
```

22
gradle.properties Normal file
View File

@@ -0,0 +1,22 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
org.gradle.jvmargs=-Xmx2560m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
org.gradle.parallel=true
# When set to true the Gradle daemon is used to run the build. For local developer builds this is our favorite property.
# The developer environment is optimized for speed and feedback so we nearly always run Gradle jobs with the daemon.
org.gradle.daemon=true

BIN
gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,6 @@
#Mon Dec 04 11:24:34 CST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip

160
gradlew vendored Executable file
View File

@@ -0,0 +1,160 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

90
gradlew.bat vendored Normal file
View File

@@ -0,0 +1,90 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@@ -1,35 +0,0 @@
my_path := $(call my-dir)
LOCAL_PATH := $(my_path)
include $(CLEAR_VARS)
LOCAL_MODULE := magiskhide
LOCAL_MODULE_TAGS := optional
LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_LDFLAGS := -static
LOCAL_STATIC_LIBRARIES := libc libcutils
LOCAL_SRC_FILES := magiskhide.c
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_MODULE := bootimgtools
LOCAL_MODULE_TAGS := optional
LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_LDFLAGS := -static
LOCAL_STATIC_LIBRARIES := libc libcutils
LOCAL_SRC_FILES := bootimgtools.c extract.c repack.c hexpatch.c
LOCAL_CFLAGS += -std=gnu11
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_MODULE := sepolicy-inject
LOCAL_MODULE_TAGS := optional
LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_LDFLAGS := -static
LOCAL_STATIC_LIBRARIES := libc libcutils libsepol
LOCAL_SRC_FILES := sepolicy-inject/sepolicy-inject.c sepolicy-inject/builtin_rules.c
LOCAL_C_INCLUDES := selinux/libsepol/include/
LOCAL_CFLAGS += -std=gnu11
include $(BUILD_EXECUTABLE)
include selinux/libsepol/Android.mk

View File

@@ -1,3 +0,0 @@
APP_ABI := x86 armeabi
APP_PIE = true
APP_PLATFORM := android-21

View File

@@ -1,45 +0,0 @@
#include <getopt.h>
#include <stdio.h>
#include "bootimgtools.h"
/********************
Patch Boot Image
*********************/
int usage(char *arg0) {
fprintf(stderr, "Boot Image Unpack/Repack Tool\n");
fprintf(stderr, "%s --extract <bootimage>\n", arg0);
fprintf(stderr, " Unpack <bootimage> into current directory\n\n");
fprintf(stderr, "%s --repack <bootimage>\n", arg0);
fprintf(stderr, " Repack kernel, dt, ramdisk... from current directory to new-image.img\n <bootimage> is the image you've just unpacked\n\n");
fprintf(stderr, "%s --hexpatch <bootimage> <hexpattern1> <hexpattern2>\n", arg0);
fprintf(stderr, " Search <hexpattern1> in <bootimage>, and replace with <hexpattern2>\n\n");
return 1;
}
int main(int argc, char *argv[])
{
char ch;
struct option long_options[] = {
{"extract", required_argument, NULL, 'e'},
{"repack", required_argument, NULL, 'r'},
{"hexpatch", required_argument, NULL, 'p'},
{NULL, 0, NULL, 0}
};
while ((ch = getopt_long(argc, argv, "e:r:p:", long_options, NULL)) != -1) {
switch (ch) {
case 'e':
return extract(optarg);
case 'r':
return repack(optarg);
case 'p':
if (argc < 5) return usage(argv[0]);
optind += 2;
return hexpatch(argv[optind - 3], argv[optind - 2], argv[optind - 1]);
default:
return usage(argv[0]);
}
}
return 0;
}

View File

@@ -1,90 +0,0 @@
/* tools/mkbootimg/bootimg.h
**
** Copyright 2007, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#include <stdint.h>
#ifndef _BOOT_IMAGE_H_
#define _BOOT_IMAGE_H_
typedef struct boot_img_hdr boot_img_hdr;
#define BOOT_MAGIC "ANDROID!"
#define BOOT_MAGIC_SIZE 8
#define BOOT_NAME_SIZE 16
#define BOOT_ARGS_SIZE 512
#define BOOT_EXTRA_ARGS_SIZE 1024
struct boot_img_hdr
{
uint8_t magic[BOOT_MAGIC_SIZE];
uint32_t kernel_size; /* size in bytes */
uint32_t kernel_addr; /* physical load addr */
uint32_t ramdisk_size; /* size in bytes */
uint32_t ramdisk_addr; /* physical load addr */
uint32_t second_size; /* size in bytes */
uint32_t second_addr; /* physical load addr */
uint32_t tags_addr; /* physical addr for kernel tags */
uint32_t page_size; /* flash page size we assume */
uint32_t unused[2]; /* future expansion: should be 0 */
uint8_t name[BOOT_NAME_SIZE]; /* asciiz product name */
uint8_t cmdline[BOOT_ARGS_SIZE];
uint32_t id[8]; /* timestamp / checksum / sha1 / etc */
/* Supplemental command line data; kept here to maintain
* binary compatibility with older versions of mkbootimg */
uint8_t extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
} __attribute__((packed));
/*
** +-----------------+
** | boot header | 1 page
** +-----------------+
** | kernel | n pages
** +-----------------+
** | ramdisk | m pages
** +-----------------+
** | second stage | o pages
** +-----------------+
**
** n = (kernel_size + page_size - 1) / page_size
** m = (ramdisk_size + page_size - 1) / page_size
** o = (second_size + page_size - 1) / page_size
**
** 0. all entities are page_size aligned in flash
** 1. kernel and ramdisk are required (size != 0)
** 2. second is optional (second_size == 0 -> no second)
** 3. load each element (kernel, ramdisk, second) at
** the specified physical address (kernel_addr, etc)
** 4. prepare tags at tag_addr. kernel_args[] is
** appended to the kernel commandline in the tags.
** 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr
** 6. if second_size != 0: jump to second_addr
** else: jump to kernel_addr
*/
int extract(char *image);
int repack(char *image);
int hexpatch(char *image, char *from, char *to);
#endif

View File

@@ -1,148 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/sendfile.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <assert.h>
#include <string.h>
#include "bootimgtools.h"
void dump(uint8_t *ptr, size_t size, char* filename) {
unlink(filename);
int ofd = open(filename, O_WRONLY|O_CREAT, 0644);
assert(ofd >= 0);
int ret = write(ofd, ptr, size);
assert(ret == size);
close(ofd);
}
//TODO: Search for other header types
void dump_ramdisk(uint8_t *ptr, size_t size) {
//GZip header
if(memcmp(ptr, "\x1f\x8b\x08\x00", 4) == 0) {
dump(ptr, size, "ramdisk.gz");
//MTK header
} else if(memcmp(ptr, "\x88\x16\x88\x58", 4) == 0) {
if(memcmp(ptr+4, "RECOVERY", 8)==0) {
dump(ptr, 0, "ramdisk-mtk-recovery");
} else if(memcmp(ptr+4, "ROOTFS\0\0", 8)==0) {
dump(ptr, 0, "ramdisk-mtk-boot");
} else {
exit(1);
}
dump(ptr, 0, "ramdisk-mtk"); //Create an mtk flag
dump_ramdisk(ptr+512, size-512);
} else {
//Since our first aim is to extract/repack ramdisk
//Stop if we can't find it
//Still dump it for debug purposes
dump(ptr, size, "ramdisk");
fprintf(stderr, "Unknown ramdisk type\n");
abort();
}
}
void search_security_hdr(uint8_t *buf, size_t size) {
if(memcmp(buf, "CHROMEOS", 8) == 0) {
dump(buf, 0, "chromeos");
return;
}
}
int search_security(uint8_t *buf, size_t size, int pos) {
//Rockchip signature
if(memcmp(buf+1024, "SIGN", 4) == 0) {
//Rockchip signature AT LEAST means the bootloader will check the crc
dump(buf, 0, "rkcrc"); //Create an flag to tell it
//And it's possible there is a security too
return 1;
}
//If we didn't parse the whole file, it is highly likely there is a boot signature
if(pos < size) {
return 1;
}
return 0;
}
/*
* TODO:
* - At the moment we dump kernel + ramdisk + second + DT, it's likely we only want ramdisk
* - Error-handling via assert() is perhaps not the best
*/
int extract(char *image) {
int fd = open(image, O_RDONLY);
off_t size = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
uint8_t *orig = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
uint8_t *base = orig;
assert(base);
search_security_hdr(base, size);
//We're searching for the header in the whole file, we could stop earlier.
//At least HTC and nVidia have a signature header
while(base<(orig+size)) {
if(memcmp(base, BOOT_MAGIC, BOOT_MAGIC_SIZE) == 0)
break;
//We're searching every 256bytes, is it ok?
base += 256;
}
assert(base < (orig+size));
struct boot_img_hdr *hdr = (struct boot_img_hdr*) base;
assert(
hdr->page_size == 2048 ||
hdr->page_size == 4096 ||
hdr->page_size == 16384
);
long pos = hdr->page_size;
dump(base+pos, hdr->kernel_size, "kernel");
pos += hdr->kernel_size + hdr->page_size-1;
pos &= ~(hdr->page_size-1L);
dump_ramdisk(base+pos, hdr->ramdisk_size);
pos += hdr->ramdisk_size + hdr->page_size-1;
pos &= ~(hdr->page_size-1L);
if(hdr->second_size) {
assert( (pos+hdr->second_size) <= size);
dump(base+pos, hdr->second_size, "second");
pos += hdr->second_size + hdr->page_size-1;
pos &= ~(hdr->page_size-1L);
}
//This is non-standard, so we triple check
if( hdr->unused[0] &&
pos < size &&
(pos+hdr->unused[0]) <= size) {
if(memcmp(base+pos, "QCDT", 4) == 0 ||
memcmp(base+pos, "SPRD", 4) == 0 ||
memcmp(base+pos, "DTBH", 4) == 0
) {
dump(base+pos, hdr->unused[0], "dt");
pos += hdr->unused[0] + hdr->page_size-1;
pos &= ~(hdr->page_size-1L);
}
}
//If we think we find some security-related infos in the boot.img
//create a "secure" flag to warn the user it is dangerous
if(search_security(base, size, pos)) {
dump(base, 0, "secure");
}
munmap(orig, size);
close(fd);
return 0;
}

View File

@@ -1,66 +0,0 @@
#include <getopt.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include "bootimgtools.h"
int hex2int(char c) {
int first = c / 16 - 3;
int second = c % 16;
int result = first * 10 + second;
if(result > 9) result--;
return result;
}
int hex2ascii(char c, char d) {
int high = hex2int(c) * 16;
int low = hex2int(d);
return high+low;
}
void hexstr2str(char *hex, char *str) {
char buf = 0;
for(int i = 0, length = strlen(hex); i < length; ++i){
if(i % 2){
str[i / 2] = hex2ascii(buf, hex[i]);
} else{
buf = hex[i];
}
}
}
int hexpatch(char * image, char *from, char *to) {
int fd = open(image, O_RDWR), patternsize = strlen(from) / 2, patchsize = strlen(to) / 2;
off_t filesize = lseek(fd, 0, SEEK_END);
char *file, *pattern, *patch, *start;
file = malloc(sizeof (char) * filesize);
pattern = malloc(sizeof (char) * patternsize);
patch = malloc(sizeof (char) * patchsize);
lseek(fd, 0, SEEK_SET);
read(fd, file, filesize);
hexstr2str(from, pattern);
hexstr2str(to, patch);
for (off_t i = 0; i < filesize;) {
int j;
for (j = 0; j < patternsize; ++j) {
if(file[i + j] != pattern[j]) break;
}
if (j == patternsize) {
fprintf(stderr, "Pattern %s found!\nPatching to %s\n", from, to);
lseek(fd, i, SEEK_SET);
write(fd, patch, patchsize);
}
if(j == 0) j = 1;
i += j;
}
free(file);
free(pattern);
free(patch);
close(fd);
return 0;
}

View File

@@ -1,165 +0,0 @@
typedef unsigned short int sa_family_t;
//Linux includes
#define _LINUX_TIME_H
#define _GNU_SOURCE
#include <sys/types.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/connector.h>
#include <linux/cn_proc.h>
#include <linux/netlink.h>
#include <linux/fs.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <asm/unistd.h>
#include <sys/mount.h>
char **file_to_str_arr(FILE *fp, int *size) {
int allocated = 16;
char *line = NULL, **array;
size_t len = 0;
ssize_t read;
array = (char **) malloc(sizeof(char*) * allocated);
*size = 0;
while ((read = getline(&line, &len, fp)) != -1) {
if (*size >= allocated) {
// Double our allocation and re-allocate
allocated *= 2;
array = (char **) realloc(array, sizeof(char*) * allocated);
}
// Remove end newline
if (line[read - 1] == '\n') {
line[read - 1] = '\0';
}
array[*size] = line;
line = NULL;
++(*size);
}
return array;
}
//WARNING: Calling this will change our current namespace
//We don't care because we don't want to run from here anyway
int hideMagisk(int pid) {
char *path = NULL;
asprintf(&path, "/proc/%d/ns/mnt", pid);
int fd = open(path, O_RDONLY);
if(fd == -1) return 2;
int res = syscall(SYS_setns, fd, 0);
if(res == -1) return 3;
free(path);
path = NULL;
asprintf(&path, "/proc/%d/mounts", pid);
FILE *mount_fp = fopen(path, "r");
if (mount_fp == NULL) {
fprintf(stderr, "Error opening mount list!\n");
return 1;
}
free(path);
int mount_size;
char **mount_list = file_to_str_arr(mount_fp, &mount_size), mountpoint[256], *sbstr;
fclose(mount_fp);
int i, unmount = 0;
for(i = mount_size - 1; i >= 0; --i) {
if((strstr(mount_list[i], "/dev/block/loop") != NULL)) {
sscanf(mount_list[i], "%256s %256s", mountpoint, mountpoint);
if (strstr(mountpoint, "/.core/dummy") != NULL)
unmount = 0;
else
unmount = 1;
} else if ((sbstr = strstr(mount_list[i], "/.core/dummy")) != NULL) {
sscanf(sbstr, "/.core/dummy%256s", mountpoint);
unmount = 1;
}
if(unmount) {
unmount = 0;
res = umount2(mountpoint, MNT_DETACH);
if (res != -1) printf("Unmounted: %s\n", mountpoint);
else printf("Failed: %s\n", mountpoint);
}
free(mount_list[i]);
}
// Free memory
free(mount_list);
return 0;
}
int main(int argc, char **argv, char **envp) {
if (argc != 2) {
fprintf(stderr, "%s <process/package name list>\n", argv[0]);
return 1;
}
int i, hide_size;
char **hide_list;
FILE *hide_fp = fopen(argv[1], "r");
if (hide_fp == NULL) {
fprintf(stderr, "Error opening hide list\n");
return 1;
}
hide_list = file_to_str_arr(hide_fp, &hide_size);
fclose(hide_fp);
printf("Get process / package name from config:\n");
for(i = 0; i < hide_size; i++)
printf("%s\n", hide_list[i]);
printf("\n");
char buffer[512];
FILE *p = popen("while true;do logcat -b events -v raw -s am_proc_start;sleep 1;done", "r");
while(!feof(p)) {
//Format of am_proc_start is (as of Android 5.1 and 6.0)
//UserID, pid, unix uid, processName, hostingType, hostingName
fgets(buffer, sizeof(buffer), p);
{
char *pos = buffer;
while(1) {
pos = strchr(pos, ',');
if(pos == NULL)
break;
pos[0] = ' ';
}
}
int user, pid, uid;
char processName[256], hostingType[16], hostingName[256];
int ret = sscanf(buffer, "[%d %d %d %256s %16s %256s]",
&user, &pid, &uid,
processName, hostingType, hostingName);
if(ret != 6) {
continue;
}
for (i = 0; i < hide_size; ++i) {
if(strstr(processName, hide_list[i]) != NULL) {
printf("Disabling for process = %s, PID = %d, UID = %d\n", processName, pid, uid);
hideMagisk(pid);
break;
}
}
}
pclose(p);
// Free memory
for(i = 0; i < hide_size; ++i)
free(hide_list[i]);
free(hide_list);
return 0;
}

View File

@@ -1,144 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/sendfile.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <assert.h>
#include <string.h>
#include "bootimgtools.h"
off_t file_size(char *filename) {
struct stat st;
if(stat(filename, &st))
exit(1);
return st.st_size;
}
int append_file(int ofd, char *filename, off_t pos) {
lseek(ofd, pos, SEEK_SET);
int fd = open(filename, O_RDONLY);
int size = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
sendfile(ofd, fd, NULL, size);
close(fd);
return size;
}
int append_ramdisk(int ofd, off_t pos) {
if(access("ramdisk-mtk", R_OK) == 0) {
char buf[512];
off_t size = file_size("ramdisk.gz");
memcpy(buf, "\x88\x16\x88\x58", 4);
uint32_t v = size;
memcpy(buf+4, &v, sizeof(v)); //Should convert to LE
//TODO: RECOVERY OR ROOTFS?
char str[32];
memset(str, 0, sizeof(str));
if(access("ramdisk-mtk-boot", R_OK)==0) {
strcpy(str, "ROOTFS");
} else if(access("ramdisk-mtk-recovery", R_OK)==0) {
strcpy(str, "RECOVERY");
} else {
exit(1);
}
memcpy(buf+8, str, sizeof(str));
memset(buf+8+sizeof(str), 0xff, 512-8-sizeof(str));
pwrite(ofd, buf, sizeof(buf), pos);
return append_file(ofd, "ramdisk.gz", pos + 512) + 512;
} else if(access("ramdisk.gz", R_OK) == 0) {
return append_file(ofd, "ramdisk.gz", pos);
} else {
return append_file(ofd, "ramdisk", pos);
}
}
void post_process(struct boot_img_hdr *hdr, int ofd, int pos) {
if(access("rkcrc", R_OK) == 0) {
fprintf(stderr, "Rockchip CRCs not supported yet\n");
exit(1);
}
//Round up the file size
ftruncate(ofd, pos);
}
int repack(char *image) {
//TODO: Merge with extract.c?
//{
int ifd = open(image, O_RDONLY);
off_t isize = lseek(ifd, 0, SEEK_END);
lseek(ifd, 0, SEEK_SET);
uint8_t *iorig = mmap(NULL, isize, PROT_READ, MAP_SHARED, ifd, 0);
uint8_t *ibase = iorig;
assert(ibase);
while(ibase<(iorig+isize)) {
if(memcmp(ibase, BOOT_MAGIC, BOOT_MAGIC_SIZE) == 0)
break;
ibase += 256;
}
assert(ibase < (iorig+isize));
//}
//
struct boot_img_hdr *ihdr = (struct boot_img_hdr*) ibase;
assert(
ihdr->page_size == 2048 ||
ihdr->page_size == 4096 ||
ihdr->page_size == 16384
);
unlink("new-boot.img");
int ofd = open("new-boot.img", O_RDWR|O_CREAT, 0644);
ftruncate(ofd, ihdr->page_size);
//Write back original header, we'll change it later
write(ofd, ihdr, sizeof(*ihdr));
struct boot_img_hdr *hdr = mmap(NULL, sizeof(*ihdr), PROT_READ|PROT_WRITE, MAP_SHARED, ofd, 0);
//First set everything to zero, so we know where we are at.
hdr->kernel_size = 0;
hdr->ramdisk_size = 0;
hdr->second_size = 0;
hdr->unused[0] = 0;
memset(hdr->id, 0, sizeof(hdr->id)); //Setting id to 0 might be wrong?
int pos = hdr->page_size;
int size = 0;
size = append_file(ofd, "kernel", pos);
pos += size + hdr->page_size - 1;
pos &= ~(hdr->page_size-1);
hdr->kernel_size = size;
size = append_ramdisk(ofd, pos);
pos += size + hdr->page_size - 1;
pos &= ~(hdr->page_size-1);
hdr->ramdisk_size = size;
if(access("second", R_OK) == 0) {
size = append_file(ofd, "second", pos);
pos += size + hdr->page_size - 1;
pos &= ~(hdr->page_size-1);
hdr->second_size = size;
}
if(access("dt", R_OK) == 0) {
size = append_file(ofd, "dt", pos);
pos += size + hdr->page_size - 1;
pos &= ~(hdr->page_size-1);
hdr->unused[0] = size;
}
post_process(hdr, ofd, pos);
munmap(hdr, sizeof(*ihdr));
close(ofd);
return 0;
}

3
native/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
/build
obj
libs

20
native/build.gradle Normal file
View File

@@ -0,0 +1,20 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion 27
externalNativeBuild {
ndkBuild {
path 'jni/Android.mk'
}
}
defaultConfig {
externalNativeBuild {
ndkBuild {
// Passes an optional argument to ndk-build.
arguments "GRADLE=true"
}
}
}
}

137
native/jni/Android.mk Normal file
View File

@@ -0,0 +1,137 @@
LOCAL_PATH := $(call my-dir)
# Some handy paths
EXT_PATH := jni/external
SE_PATH := $(EXT_PATH)/selinux
LIBSELINUX := $(SE_PATH)/libselinux/include
LIBSEPOL := $(SE_PATH)/libsepol/include $(SE_PATH)/libsepol/cil/include
LIBLZMA := $(EXT_PATH)/xz/src/liblzma/api
LIBLZ4 := $(EXT_PATH)/lz4/lib
LIBBZ2 := $(EXT_PATH)/bzip2
LIBFDT := $(EXT_PATH)/dtc/libfdt
UTIL_SRC := utils/cpio.c \
utils/file.c \
utils/img.c \
utils/list.c \
utils/misc.c \
utils/pattern.c \
utils/vector.c \
utils/xwrap.c
########################
# Binaries
########################
ifneq "$(or $(PRECOMPILE), $(GRADLE))" ""
# magisk main binary
include $(CLEAR_VARS)
LOCAL_MODULE := magisk
LOCAL_SHARED_LIBRARIES := libsqlite libselinux
LOCAL_C_INCLUDES := \
jni/include \
$(EXT_PATH)/include \
$(LIBSELINUX)
LOCAL_SRC_FILES := \
core/magisk.c \
core/daemon.c \
core/log_monitor.c \
core/bootstages.c \
core/socket.c \
magiskhide/magiskhide.c \
magiskhide/proc_monitor.c \
magiskhide/hide_utils.c \
resetprop/resetprop.cpp \
resetprop/system_properties.cpp \
su/su.c \
su/activity.c \
su/db.c \
su/pts.c \
su/su_daemon.c \
su/su_socket.c \
$(UTIL_SRC)
LOCAL_CFLAGS := -DIS_DAEMON -DSELINUX
LOCAL_LDLIBS := -llog
include $(BUILD_EXECUTABLE)
endif
ifndef PRECOMPILE
# magiskinit
include $(CLEAR_VARS)
LOCAL_MODULE := magiskinit
LOCAL_STATIC_LIBRARIES := libsepol liblzma
LOCAL_C_INCLUDES := \
jni/include \
jni/magiskpolicy \
../out/$(TARGET_ARCH_ABI) \
$(LIBSEPOL) \
$(LIBLZMA)
LOCAL_SRC_FILES := \
core/magiskinit.c \
core/socket.c \
magiskpolicy/api.c \
magiskpolicy/magiskpolicy.c \
magiskpolicy/rules.c \
magiskpolicy/sepolicy.c \
$(UTIL_SRC)
LOCAL_LDFLAGS := -static
include $(BUILD_EXECUTABLE)
# magiskboot
include $(CLEAR_VARS)
LOCAL_MODULE := magiskboot
LOCAL_STATIC_LIBRARIES := libmincrypt liblzma liblz4 libbz2 libfdt
LOCAL_C_INCLUDES := \
jni/include \
$(EXT_PATH)/include \
$(LIBLZMA) \
$(LIBLZ4) \
$(LIBBZ2) \
$(LIBFDT)
LOCAL_SRC_FILES := \
magiskboot/main.c \
magiskboot/bootimg.c \
magiskboot/hexpatch.c \
magiskboot/compress.c \
magiskboot/format.c \
magiskboot/dtb.c \
magiskboot/ramdisk.c \
$(UTIL_SRC)
LOCAL_CFLAGS := -DXWRAP_EXIT
LOCAL_LDLIBS := -lz
include $(BUILD_EXECUTABLE)
# 32-bit static binaries
ifndef GRADLE # Do not run gradle sync on these binaries
ifneq ($(TARGET_ARCH_ABI), x86_64)
ifneq ($(TARGET_ARCH_ABI), arm64-v8a)
# b64xz
include $(CLEAR_VARS)
LOCAL_MODULE := b64xz
LOCAL_STATIC_LIBRARIES := liblzma
LOCAL_C_INCLUDES := $(LIBLZMA)
LOCAL_SRC_FILES := b64xz.c
LOCAL_LDFLAGS := -static
include $(BUILD_EXECUTABLE)
# Busybox
include jni/external/busybox/Android.mk
endif
endif
endif
# Precompile
endif
########################
# Externals
########################
include jni/external/Android.mk

View File

@@ -0,0 +1,5 @@
APP_ABI := x86 x86_64 armeabi-v7a arm64-v8a
APP_PLATFORM := android-21
APP_CFLAGS := $(MAGISK_FLAGS) -std=gnu99
APP_CPPFLAGS := -std=c++11
APP_SHORT_COMMANDS := true

83
native/jni/b64xz.c Normal file
View File

@@ -0,0 +1,83 @@
/* b64xz.c - Base64-XZ Extractor
*
* This program expects data from stdin. The data should be compressed with xz and
* then encoded into base64 format. What b64xz does is basically the reverse of the
* mentioned process: decode base64 to uint8_ts, decompress xz, then dump to stdout
*
* The compiled binary will be hex-dumped into update-binary
* Busybox will be xz-compressed, base64 encoded and dumped into update-binary
* This program is to recover busybox for Magisk installation environment
*
* I intentionally removed stdio. This will result in a smaller binary size because
* all I/O are handled by system calls (read/write) instead of libc wrappers
*/
#include <unistd.h>
#include <lzma.h>
#define BUFSIZE 8192
static const char trans_tbl[] =
"|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq";
static void decodeblock(uint8_t* in, uint8_t* out) {
out[0] = (uint8_t)(in[0] << 2 | in[1] >> 4);
out[1] = (uint8_t)(in[1] << 4 | in[2] >> 2);
out[2] = (uint8_t)(((in[2] << 6) & 0xc0) | in[3]);
}
static int unxz(lzma_stream *strm, void *buf, size_t size) {
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(STDOUT_FILENO, 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;
}
int main(int argc, char const* argv[]) {
if (argc > 1)
return 0;
uint8_t in[4], buf[BUFSIZE];
int len = 0, pos = 0;
char c;
// Setup lzma stream
lzma_stream strm = LZMA_STREAM_INIT;
if (lzma_auto_decoder(&strm, UINT64_MAX, 0) != LZMA_OK) {
write(STDERR_FILENO, "Unable to init lzma stream\n", 28);
return 1;
}
while (read(STDIN_FILENO, &c, sizeof(c)) == 1) {
c = ((c < 43 || c > 122) ? -1 : (trans_tbl[c - 43] == '$' ? -1 : trans_tbl[c - 43] - 62));
if (c >= 0)
in[len++] = c;
if (len < 4)
continue;
len = 0;
decodeblock(in, buf + pos);
pos += 3;
if (pos > sizeof(buf) - 3) {
// Buffer is full, unxz
if (unxz(&strm, buf, pos))
return 1;
pos = 0;
}
}
if (pos) {
if (unxz(&strm, buf, pos))
return 1;
}
lzma_end(&strm);
return 0;
}

View File

@@ -0,0 +1,683 @@
/* bootstages.c - Core bootstage operations
*
* All bootstage operations, including simple mount in post-fs,
* magisk mount in post-fs-data, various image handling, script
* execution, load modules, install Magisk Manager etc.
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <dirent.h>
#include <sys/mount.h>
#include <sys/wait.h>
#include <selinux/selinux.h>
#include "magisk.h"
#include "utils.h"
#include "daemon.h"
#include "resetprop.h"
static char *buf, *buf2;
static struct vector module_list;
extern char **environ;
/******************
* Node structure *
******************/
// Precedence: MODULE > SKEL > INTER > DUMMY
#define IS_DUMMY 0x01 /* mount from mirror */
#define IS_INTER 0x02 /* intermediate node */
#define IS_SKEL 0x04 /* mount from skeleton */
#define IS_MODULE 0x08 /* mount from module */
#define IS_DIR(n) (n->type == DT_DIR)
#define IS_LNK(n) (n->type == DT_LNK)
#define IS_REG(n) (n->type == DT_REG)
struct node_entry {
const char *module; /* Only used when status & IS_MODULE */
char *name;
uint8_t type;
uint8_t status;
struct node_entry *parent;
struct vector *children;
};
static void concat_path(struct node_entry *node) {
if (node->parent)
concat_path(node->parent);
size_t len = strlen(buf);
buf[len] = '/';
strcpy(buf + len + 1, node->name);
}
static char *get_full_path(struct node_entry *node) {
buf[0] = '\0';
concat_path(node);
return strdup(buf);
}
// Free the node
static void destroy_node(struct node_entry *node) {
free(node->name);
vec_destroy(node->children);
free(node->children);
free(node);
}
// Free the node and all children recursively
static void destroy_subtree(struct node_entry *node) {
// Never free parent, since it shall be freed by themselves
struct node_entry *e;
vec_for_each(node->children, e) {
destroy_subtree(e);
}
destroy_node(node);
}
// Return the child
static struct node_entry *insert_child(struct node_entry *p, struct node_entry *c) {
c->parent = p;
if (p->children == NULL) {
p->children = xmalloc(sizeof(struct vector));
vec_init(p->children);
}
struct node_entry *e;
vec_for_each(p->children, e) {
if (strcmp(e->name, c->name) == 0) {
// Exist duplicate
if (c->status > e->status) {
// Precedence is higher, replace with new node
destroy_subtree(e);
vec_cur(p->children) = c;
return c;
} else {
// Free the new entry, return old
destroy_node(c);
return e;
}
}
}
// New entry, push back
vec_push_back(p->children, c);
return c;
}
/***********
* setenvs *
***********/
static void bb_setenv(struct vector *v) {
for (int i = 0; environ[i]; ++i) {
if (strncmp(environ[i], "PATH=", 5) == 0) {
snprintf(buf, PATH_MAX, "PATH=%s:%s", BBPATH, strchr(environ[i], '=') + 1);
vec_push_back(v, strdup(buf));
} else {
vec_push_back(v, strdup(environ[i]));
}
}
vec_push_back(v, NULL);
}
static void pm_setenv(struct vector *v) {
for (int i = 0; environ[i]; ++i) {
if (strncmp(environ[i], "CLASSPATH=", 10) != 0)
vec_push_back(v, strdup(environ[i]));
}
vec_push_back(v, strdup("CLASSPATH=/system/framework/pm.jar"));
vec_push_back(v, NULL);
}
/***********
* Scripts *
***********/
static void exec_common_script(const char* stage) {
DIR *dir;
struct dirent *entry;
snprintf(buf2, PATH_MAX, "%s/%s.d", COREDIR, stage);
if (!(dir = xopendir(buf2)))
return;
while ((entry = xreaddir(dir))) {
if (entry->d_type == DT_REG) {
snprintf(buf2, PATH_MAX, "%s/%s.d/%s", COREDIR, stage, entry->d_name);
if (access(buf2, X_OK) == -1)
continue;
LOGI("%s.d: exec [%s]\n", stage, entry->d_name);
int pid = exec_command(0, NULL, bb_setenv, "sh", buf2, NULL);
if (pid != -1)
waitpid(pid, NULL, 0);
}
}
closedir(dir);
}
static void exec_module_script(const char* stage) {
char *module;
vec_for_each(&module_list, module) {
snprintf(buf2, PATH_MAX, "%s/%s/%s.sh", MOUNTPOINT, module, stage);
snprintf(buf, PATH_MAX, "%s/%s/disable", MOUNTPOINT, module);
if (access(buf2, F_OK) == -1 || access(buf, F_OK) == 0)
continue;
LOGI("%s: exec [%s.sh]\n", module, stage);
int pid = exec_command(0, NULL, bb_setenv, "sh", buf2, NULL);
if (pid != -1)
waitpid(pid, NULL, 0);
}
}
/***************
* Magic Mount *
***************/
static void construct_tree(const char *module, struct node_entry *parent) {
DIR *dir;
struct dirent *entry;
struct node_entry *node;
char *parent_path = get_full_path(parent);
snprintf(buf, PATH_MAX, "%s/%s%s", MOUNTPOINT, module, parent_path);
if (!(dir = xopendir(buf)))
goto cleanup;
while ((entry = xreaddir(dir))) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue;
// Create new node
node = xcalloc(sizeof(*node), 1);
node->module = module;
node->name = strdup(entry->d_name);
node->type = entry->d_type;
snprintf(buf, PATH_MAX, "%s/%s", parent_path, node->name);
/*
* Clone the parent in the following condition:
* 1. File in module is a symlink
* 2. Target file do not exist
* 3. Target file is a symlink, but not /system/vendor
*/
int clone = 0;
if (IS_LNK(node) || access(buf, F_OK) == -1) {
clone = 1;
} else if (parent->parent != NULL || strcmp(node->name, "vendor") != 0) {
struct stat s;
xstat(buf, &s);
if (S_ISLNK(s.st_mode))
clone = 1;
}
if (clone) {
// Mark the parent folder as a skeleton
parent->status |= IS_SKEL; /* This will not overwrite if parent is module */
node->status = IS_MODULE;
} else if (IS_DIR(node)) {
// Check if marked as replace
snprintf(buf2, PATH_MAX, "%s/%s%s/.replace", MOUNTPOINT, module, buf);
if (access(buf2, F_OK) == 0) {
// Replace everything, mark as leaf
node->status = IS_MODULE;
} else {
// This will be an intermediate node
node->status = IS_INTER;
}
} else if (IS_REG(node)) {
// This is a leaf, mark as target
node->status = IS_MODULE;
}
node = insert_child(parent, node);
if (node->status & (IS_SKEL | IS_INTER)) {
// Intermediate folder, travel deeper
construct_tree(module, node);
}
}
closedir(dir);
cleanup:
free(parent_path);
}
static void clone_skeleton(struct node_entry *node) {
DIR *dir;
struct dirent *entry;
struct node_entry *dummy, *child;
// Clone the structure
char *full_path = get_full_path(node);
snprintf(buf, PATH_MAX, "%s%s", MIRRDIR, full_path);
if (!(dir = xopendir(buf)))
goto cleanup;
while ((entry = xreaddir(dir))) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue;
// Create dummy node
dummy = xcalloc(sizeof(*dummy), 1);
dummy->name = strdup(entry->d_name);
dummy->type = entry->d_type;
dummy->status = IS_DUMMY;
insert_child(node, dummy);
}
closedir(dir);
if (node->status & IS_SKEL) {
struct stat s;
char *con;
xstat(full_path, &s);
getfilecon(full_path, &con);
LOGI("mnt_tmpfs : %s\n", full_path);
xmount("tmpfs", full_path, "tmpfs", 0, NULL);
chmod(full_path, s.st_mode & 0777);
chown(full_path, s.st_uid, s.st_gid);
setfilecon(full_path, con);
free(con);
}
vec_for_each(node->children, child) {
snprintf(buf, PATH_MAX, "%s/%s", full_path, child->name);
// Create the dummy file/directory
if (IS_DIR(child))
xmkdir(buf, 0755);
else if (IS_REG(child))
close(creat(buf, 0644));
// Links will be handled later
if (child->parent->parent == NULL && strcmp(child->name, "vendor") == 0) {
if (IS_LNK(child)) {
cp_afc(MIRRDIR "/system/vendor", "/system/vendor");
LOGI("creat_link: %s <- %s\n", "/system/vendor", MIRRDIR "/system/vendor");
}
// Skip
continue;
} else if (child->status & IS_MODULE) {
// Mount from module file to dummy file
snprintf(buf2, PATH_MAX, "%s/%s%s/%s", MOUNTPOINT, child->module, full_path, child->name);
} else if (child->status & (IS_SKEL | IS_INTER)) {
// It's an intermediate folder, recursive clone
clone_skeleton(child);
continue;
} else if (child->status & IS_DUMMY) {
// Mount from mirror to dummy file
snprintf(buf2, PATH_MAX, "%s%s/%s", MIRRDIR, full_path, child->name);
}
if (IS_LNK(child)) {
// Copy symlinks directly
cp_afc(buf2, buf);
#ifdef MAGISK_DEBUG
LOGI("creat_link: %s <- %s\n",buf, buf2);
#else
LOGI("creat_link: %s\n", buf);
#endif
} else {
snprintf(buf, PATH_MAX, "%s/%s", full_path, child->name);
bind_mount(buf2, buf);
}
}
cleanup:
free(full_path);
}
static void magic_mount(struct node_entry *node) {
char *real_path;
struct node_entry *child;
if (node->status & IS_MODULE) {
// The real deal, mount module item
real_path = get_full_path(node);
snprintf(buf, PATH_MAX, "%s/%s%s", MOUNTPOINT, node->module, real_path);
bind_mount(buf, real_path);
free(real_path);
} else if (node->status & IS_SKEL) {
// The node is labeled to be cloned with skeleton, lets do it
clone_skeleton(node);
} else if (node->status & IS_INTER) {
// It's an intermediate node, travel deeper
vec_for_each(node->children, child)
magic_mount(child);
}
// The only thing goes here should be vendor placeholder
// There should be no dummies, so don't need to handle it here
}
/****************
* Simple Mount *
****************/
static void simple_mount(const char *path) {
DIR *dir;
struct dirent *entry;
snprintf(buf, PATH_MAX, "%s%s", CACHEMOUNT, path);
if (!(dir = opendir(buf)))
return;
while ((entry = xreaddir(dir))) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue;
// Target file path
snprintf(buf2, PATH_MAX, "%s/%s", path, entry->d_name);
// Only mount existing file
if (access(buf2, F_OK) == -1)
continue;
if (entry->d_type == DT_DIR) {
char *new_path = strdup(buf2);
simple_mount(new_path);
free(new_path);
} else if (entry->d_type == DT_REG) {
// Actual file path
snprintf(buf, PATH_MAX, "%s%s", CACHEMOUNT, buf2);
// Clone all attributes
clone_attr(buf2, buf);
// Finally, mount the file
bind_mount(buf, buf2);
}
}
closedir(dir);
}
/*****************
* Miscellaneous *
*****************/
#define alt_img ((char *[]) \
{ "/cache/magisk.img", "/data/magisk_merge.img", "/data/adb/magisk_merge.img", NULL })
static int prepare_img() {
// Merge images
for (int i = 0; alt_img[i]; ++i) {
if (merge_img(alt_img[i], MAINIMG)) {
LOGE("Image merge %s -> " MAINIMG " failed!\n", alt_img[i]);
return 1;
}
}
if (access(MAINIMG, F_OK) == -1) {
if (create_img(MAINIMG, 64))
return 1;
}
LOGI("* Mounting " MAINIMG "\n");
// Mounting magisk image
char *magiskloop = mount_image(MAINIMG, MOUNTPOINT);
if (magiskloop == NULL)
return 1;
xmkdir(COREDIR, 0755);
xmkdir(COREDIR "/post-fs-data.d", 0755);
xmkdir(COREDIR "/service.d", 0755);
xmkdir(COREDIR "/props", 0755);
DIR *dir = xopendir(MOUNTPOINT);
struct dirent *entry;
while ((entry = xreaddir(dir))) {
if (entry->d_type == DT_DIR) {
if (strcmp(entry->d_name, ".") == 0 ||
strcmp(entry->d_name, "..") == 0 ||
strcmp(entry->d_name, ".core") == 0 ||
strcmp(entry->d_name, "lost+found") == 0)
continue;
snprintf(buf, PATH_MAX, "%s/%s/remove", MOUNTPOINT, entry->d_name);
if (access(buf, F_OK) == 0) {
snprintf(buf, PATH_MAX, "%s/%s", MOUNTPOINT, entry->d_name);
rm_rf(buf);
continue;
}
snprintf(buf, PATH_MAX, "%s/%s/disable", MOUNTPOINT, entry->d_name);
if (access(buf, F_OK) == 0)
continue;
vec_push_back(&module_list, strdup(entry->d_name));
}
}
closedir(dir);
// Trim image
umount_image(MOUNTPOINT, magiskloop);
free(magiskloop);
trim_img(MAINIMG);
// Remount them back :)
magiskloop = mount_image(MAINIMG, MOUNTPOINT);
free(magiskloop);
// Fix file selinux contexts
fix_filecon();
return 0;
}
void fix_filecon() {
int dirfd = xopen(MOUNTPOINT, O_RDONLY | O_CLOEXEC);
restorecon(dirfd, 0);
close(dirfd);
}
/****************
* Entry points *
****************/
static void unblock_boot_process() {
close(xopen(UNBLOCKFILE, O_RDONLY | O_CREAT, 0));
pthread_exit(NULL);
}
void post_fs(int client) {
LOGI("** post-fs mode running\n");
// ack
write_int(client, 0);
close(client);
// Uninstall or core only mode
if (access(UNINSTALLER, F_OK) == 0 || access(DISABLEFILE, F_OK) == 0)
goto unblock;
// Allocate buffer
buf = xmalloc(PATH_MAX);
buf2 = xmalloc(PATH_MAX);
simple_mount("/system");
simple_mount("/vendor");
unblock:
unblock_boot_process();
}
void post_fs_data(int client) {
// ack
write_int(client, 0);
close(client);
if (!is_daemon_init && !check_data())
goto unblock;
// Start the debug log
start_debug_full_log();
LOGI("** post-fs-data mode running\n");
// Allocate buffer
if (buf == NULL) buf = xmalloc(PATH_MAX);
if (buf2 == NULL) buf2 = xmalloc(PATH_MAX);
vec_init(&module_list);
// Initialize
if (!is_daemon_init)
daemon_init();
// uninstaller
if (access(UNINSTALLER, F_OK) == 0) {
close(open(UNBLOCKFILE, O_RDONLY | O_CREAT));
setenv("BOOTMODE", "true", 1);
exec_command(0, NULL, bb_setenv, "sh", UNINSTALLER, NULL);
return;
}
// Merge, trim, mount magisk.img, which will also travel through the modules
// After this, it will create the module list
if (prepare_img())
goto core_only; // Mounting fails, we can only do core only stuffs
// Run common scripts
LOGI("* Running post-fs-data.d scripts\n");
exec_common_script("post-fs-data");
// Core only mode
if (access(DISABLEFILE, F_OK) == 0)
goto core_only;
// Execute module scripts
LOGI("* Running module post-fs-data scripts\n");
exec_module_script("post-fs-data");
char *module;
struct node_entry *sys_root, *ven_root = NULL, *child;
// Create the system root entry
sys_root = xcalloc(sizeof(*sys_root), 1);
sys_root->name = strdup("system");
sys_root->status = IS_INTER;
int has_modules = 0;
LOGI("* Loading modules\n");
vec_for_each(&module_list, module) {
// Read props
snprintf(buf, PATH_MAX, "%s/%s/system.prop", MOUNTPOINT, module);
if (access(buf, F_OK) == 0) {
LOGI("%s: loading [system.prop]\n", module);
read_prop_file(buf, 0);
}
// Check whether enable auto_mount
snprintf(buf, PATH_MAX, "%s/%s/auto_mount", MOUNTPOINT, module);
if (access(buf, F_OK) == -1)
continue;
// Double check whether the system folder exists
snprintf(buf, PATH_MAX, "%s/%s/system", MOUNTPOINT, module);
if (access(buf, F_OK) == -1)
continue;
// Construct structure
has_modules = 1;
LOGI("%s: constructing magic mount structure\n", module);
// If /system/vendor exists in module, create a link outside
snprintf(buf, PATH_MAX, "%s/%s/system/vendor", MOUNTPOINT, module);
if (access(buf, F_OK) == 0) {
snprintf(buf2, PATH_MAX, "%s/%s/vendor", MOUNTPOINT, module);
unlink(buf2);
xsymlink(buf, buf2);
}
construct_tree(module, sys_root);
}
if (has_modules) {
// Extract the vendor node out of system tree and swap with placeholder
vec_for_each(sys_root->children, child) {
if (strcmp(child->name, "vendor") == 0) {
ven_root = child;
child = xcalloc(sizeof(*child), 1);
child->type = seperate_vendor ? DT_LNK : DT_DIR;
child->parent = ven_root->parent;
child->name = strdup("vendor");
child->status = 0;
// Swap!
vec_cur(sys_root->children) = child;
ven_root->parent = NULL;
break;
}
}
// Magic!!
magic_mount(sys_root);
if (ven_root) magic_mount(ven_root);
}
// Cleanup memory
destroy_subtree(sys_root);
if (ven_root) destroy_subtree(ven_root);
core_only:
// Systemless hosts
if (access(HOSTSFILE, F_OK) == 0) {
LOGI("* Enabling systemless hosts file support");
bind_mount(HOSTSFILE, "/system/etc/hosts");
}
auto_start_magiskhide();
unblock:
unblock_boot_process();
}
void late_start(int client) {
LOGI("** late_start service mode running\n");
// ack
write_int(client, 0);
close(client);
// Allocate buffer
if (buf == NULL) buf = xmalloc(PATH_MAX);
if (buf2 == NULL) buf2 = xmalloc(PATH_MAX);
// Wait till the full patch is done
wait_till_exists(PATCHDONE);
unlink(PATCHDONE);
// Run scripts after full patch, most reliable way to run scripts
LOGI("* Running service.d scripts\n");
exec_common_script("service");
// Core only mode
if (access(DISABLEFILE, F_OK) == 0)
goto core_only;
LOGI("* Running module service scripts\n");
exec_module_script("service");
core_only:
// Install Magisk Manager if exists
if (access(MANAGERAPK, F_OK) == 0) {
rename(MANAGERAPK, "/data/magisk.apk");
setfilecon("/data/magisk.apk", "u:object_r:su_file:s0");
while (1) {
sleep(5);
int apk_res = -1, pid;
pid = exec_command(1, &apk_res, pm_setenv,
"app_process",
"/system/bin", "com.android.commands.pm.Pm",
"install", "-r", "/data/magisk.apk", NULL);
if (pid != -1) {
int err = 0;
while (fdgets(buf, PATH_MAX, apk_res) > 0) {
LOGD("apk_install: %s", buf);
err |= strstr(buf, "Error:") != NULL;
}
waitpid(pid, NULL, 0);
close(apk_res);
// Keep trying until pm is started
if (err)
continue;
break;
}
}
unlink("/data/magisk.apk");
}
// All boot stage done, cleanup everything
free(buf);
free(buf2);
buf = buf2 = NULL;
vec_deep_destroy(&module_list);
stop_debug_full_log();
}

321
native/jni/core/daemon.c Normal file
View File

@@ -0,0 +1,321 @@
/* daemon.c - Magisk Daemon
*
* Start the daemon and wait for requests
* Connect the daemon and send requests through sockets
*/
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <pthread.h>
#include <signal.h>
#include <sys/un.h>
#include <sys/types.h>
#include <sys/mount.h>
#include <selinux/selinux.h>
#include "magisk.h"
#include "utils.h"
#include "daemon.h"
#include "resetprop.h"
int is_daemon_init = 0, seperate_vendor = 0;
static void *request_handler(void *args) {
int client = *((int *) args);
free(args);
int req = read_int(client);
struct ucred credential;
get_client_cred(client, &credential);
switch (req) {
case LAUNCH_MAGISKHIDE:
case STOP_MAGISKHIDE:
case ADD_HIDELIST:
case RM_HIDELIST:
case LS_HIDELIST:
case POST_FS:
case POST_FS_DATA:
case LATE_START:
if (credential.uid != 0) {
write_int(client, ROOT_REQUIRED);
close(client);
return NULL;
}
default:
break;
}
switch (req) {
case LAUNCH_MAGISKHIDE:
launch_magiskhide(client);
break;
case STOP_MAGISKHIDE:
stop_magiskhide(client);
break;
case ADD_HIDELIST:
add_hide_list(client);
break;
case RM_HIDELIST:
rm_hide_list(client);
break;
case LS_HIDELIST:
ls_hide_list(client);
break;
case SUPERUSER:
su_daemon_receiver(client, &credential);
break;
case CHECK_VERSION:
write_string(client, MAGISK_VER_STR);
close(client);
break;
case CHECK_VERSION_CODE:
write_int(client, MAGISK_VER_CODE);
close(client);
break;
case POST_FS:
post_fs(client);
break;
case POST_FS_DATA:
post_fs_data(client);
break;
case LATE_START:
late_start(client);
break;
default:
break;
}
return NULL;
}
static void *start_magisk_hide(void *args) {
launch_magiskhide(-1);
return NULL;
}
void auto_start_magiskhide() {
char *hide_prop = getprop2(MAGISKHIDE_PROP, 1);
if (hide_prop == NULL || strcmp(hide_prop, "0") != 0) {
pthread_t thread;
xpthread_create(&thread, NULL, start_magisk_hide, NULL);
pthread_detach(thread);
}
free(hide_prop);
}
void daemon_init() {
is_daemon_init = 1;
// Magisk binaries
char *bin_path = NULL;
if (access("/cache/data_bin", F_OK) == 0)
bin_path = "/cache/data_bin";
else if (access("/data/data/com.topjohnwu.magisk/install", F_OK) == 0)
bin_path = "/data/data/com.topjohnwu.magisk/install";
else if (access("/data/user_de/0/com.topjohnwu.magisk/install", F_OK) == 0)
bin_path = "/data/user_de/0/com.topjohnwu.magisk/install";
if (bin_path) {
rm_rf(DATABIN);
cp_afc(bin_path, DATABIN);
rm_rf(bin_path);
}
// Migration
rm_rf("/data/magisk");
unlink("/data/magisk.img");
unlink("/data/magisk_debug.log");
chmod("/data/adb", 0700);
LOGI("* Creating /sbin overlay");
DIR *dir;
struct dirent *entry;
int root, sbin;
char buf[PATH_MAX], buf2[PATH_MAX];
char magisk_name[10], init_name[10];
// Setup links under /sbin
xmount(NULL, "/", NULL, MS_REMOUNT, NULL);
xmkdir("/root", 0755);
chmod("/root", 0755);
root = xopen("/root", O_RDONLY | O_CLOEXEC);
sbin = xopen("/sbin", O_RDONLY | O_CLOEXEC);
link_dir(sbin, root);
unlink("/sbin/magisk");
close(sbin);
xmount("tmpfs", "/sbin", "tmpfs", 0, NULL);
chmod("/sbin", 0755);
setfilecon("/sbin", "u:object_r:rootfs:s0");
dir = xfdopendir(root);
while((entry = xreaddir(dir))) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue;
snprintf(buf, PATH_MAX, "/root/%s", entry->d_name);
snprintf(buf2, PATH_MAX, "/sbin/%s", entry->d_name);
xsymlink(buf, buf2);
}
gen_rand_str(magisk_name, sizeof(magisk_name));
snprintf(buf, PATH_MAX, "/root/%s", magisk_name);
unlink("/sbin/magisk");
rename("/root/magisk", buf);
xsymlink(buf, "/sbin/magisk");
for (int i = 0; applet[i]; ++i) {
snprintf(buf2, PATH_MAX, "/sbin/%s", applet[i]);
xsymlink(buf, buf2);
}
gen_rand_str(init_name, sizeof(init_name));
snprintf(buf, PATH_MAX, "/root/%s", init_name);
unlink("/sbin/magiskinit");
rename("/root/magiskinit", buf);
for (int i = 0; init_applet[i]; ++i) {
snprintf(buf2, PATH_MAX, "/sbin/%s", init_applet[i]);
xsymlink(buf, buf2);
}
close(root);
// Backward compatibility
xsymlink(DATABIN, "/data/magisk");
xsymlink(MAINIMG, "/data/magisk.img");
xsymlink(MOUNTPOINT, "/magisk");
xmount(NULL, "/", NULL, MS_REMOUNT | MS_RDONLY, NULL);
LOGI("* Mounting mirrors");
struct vector mounts;
vec_init(&mounts);
file_to_vector("/proc/mounts", &mounts);
char *line;
int skip_initramfs = 0;
// Check whether skip_initramfs device
vec_for_each(&mounts, line) {
if (strstr(line, " /system_root ")) {
xmkdirs(MIRRDIR "/system", 0755);
bind_mount("/system_root/system", MIRRDIR "/system");
skip_initramfs = 1;
break;
}
}
vec_for_each(&mounts, line) {
if (!skip_initramfs && strstr(line, " /system ")) {
sscanf(line, "%s", buf);
xmkdirs(MIRRDIR "/system", 0755);
xmount(buf, MIRRDIR "/system", "ext4", MS_RDONLY, NULL);
#ifdef MAGISK_DEBUG
LOGI("mount: %s <- %s\n", MIRRDIR "/system", buf);
#else
LOGI("mount: %s\n", MIRRDIR "/system");
#endif
} else if (strstr(line, " /vendor ")) {
seperate_vendor = 1;
sscanf(line, "%s", buf);
xmkdirs(MIRRDIR "/vendor", 0755);
xmount(buf, MIRRDIR "/vendor", "ext4", MS_RDONLY, NULL);
#ifdef MAGISK_DEBUG
LOGI("mount: %s <- %s\n", MIRRDIR "/vendor", buf);
#else
LOGI("mount: %s\n", MIRRDIR "/vendor");
#endif
}
free(line);
}
vec_destroy(&mounts);
if (!seperate_vendor) {
xsymlink(MIRRDIR "/system/vendor", MIRRDIR "/vendor");
#ifdef MAGISK_DEBUG
LOGI("link: %s <- %s\n", MIRRDIR "/vendor", MIRRDIR "/system/vendor");
#else
LOGI("link: %s\n", MIRRDIR "/vendor");
#endif
}
xmkdirs(MIRRDIR "/bin", 0755);
bind_mount(DATABIN, MIRRDIR "/bin");
LOGI("* Setting up internal busybox");
xmkdirs(BBPATH, 0755);
exec_command_sync(MIRRDIR "/bin/busybox", "--install", "-s", BBPATH, NULL);
xsymlink(MIRRDIR "/bin/busybox", BBPATH "/busybox");
}
void start_daemon() {
setsid();
setcon("u:r:su:s0");
umask(0);
int fd = xopen("/dev/null", O_RDWR | O_CLOEXEC);
xdup2(fd, STDIN_FILENO);
xdup2(fd, STDOUT_FILENO);
xdup2(fd, STDERR_FILENO);
close(fd);
// Block user signals
sigset_t block_set;
sigemptyset(&block_set);
sigaddset(&block_set, SIGUSR1);
sigaddset(&block_set, SIGUSR2);
pthread_sigmask(SIG_SETMASK, &block_set, NULL);
struct sockaddr_un sun;
fd = setup_socket(&sun);
if (xbind(fd, (struct sockaddr*) &sun, sizeof(sun)))
exit(1);
xlisten(fd, 10);
// Start the log monitor
monitor_logs();
if ((is_daemon_init = (access(MAGISKTMP, F_OK) == 0))) {
// Restart stuffs if the daemon is restarted
exec_command_sync("logcat", "-b", "all", "-c", NULL);
auto_start_magiskhide();
start_debug_log();
} else if (check_data()) {
daemon_init();
}
LOGI("Magisk v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") daemon started\n");
// Change process name
strcpy(argv0, "magisk_daemon");
// Unlock all blocks for rw
unlock_blocks();
// Loop forever to listen for requests
while(1) {
int *client = xmalloc(sizeof(int));
*client = xaccept4(fd, NULL, NULL, SOCK_CLOEXEC);
pthread_t thread;
xpthread_create(&thread, NULL, request_handler, client);
// Detach the thread, we will never join it
pthread_detach(thread);
}
}
/* Connect the daemon, and return a socketfd */
int connect_daemon() {
struct sockaddr_un sun;
int fd = setup_socket(&sun);
if (connect(fd, (struct sockaddr*) &sun, sizeof(sun))) {
// If we cannot access the daemon, we start a daemon in the child process if possible
if (getuid() != UID_ROOT || getgid() != UID_ROOT) {
fprintf(stderr, "No daemon is currently running!\n");
exit(1);
}
if (xfork() == 0) {
LOGD("client: connect fail, try launching new daemon process\n");
close(fd);
start_daemon();
}
while (connect(fd, (struct sockaddr*) &sun, sizeof(sun)))
usleep(10000);
}
return fd;
}

View File

@@ -0,0 +1,211 @@
/* log_monitor.c - New thread to monitor logcat
*
* A universal logcat monitor for many usages. Add listeners to the list,
* and the pointer of the new log line will be sent through pipes to trigger
* asynchronous events without polling
*/
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/wait.h>
#include "magisk.h"
#include "utils.h"
#include "resetprop.h"
extern int is_daemon_init;
int logd = 0;
static int am_proc_start_filter(const char *log) {
return strstr(log, "am_proc_start") != NULL;
}
static int magisk_log_filter(const char *log) {
char *ss;
return (ss = strstr(log, " Magisk")) && (ss[-1] != 'D') && (ss[-1] != 'V');
}
static int magisk_debug_log_filter(const char *log) {
return strstr(log, "Magisk") != NULL;
}
struct log_listener log_events[] = {
{ /* HIDE_EVENT */
.fd = -1,
.filter = am_proc_start_filter
},
{ /* LOG_EVENT */
.fd = -1,
.filter = magisk_log_filter
},
{ /* DEBUG_EVENT */
.fd = -1,
.filter = magisk_debug_log_filter
}
};
#ifdef MAGISK_DEBUG
static int debug_log_pid = -1, debug_log_fd = -1;
#endif
static void check_logd() {
char *prop = getprop("init.svc.logd");
if (prop != NULL) {
free(prop);
logd = 1;
} else {
LOGD("log_monitor: logd not started, disable logging");
logd = 0;
}
}
static void *logger_thread(void *args) {
int log_fd = -1, log_pid;
char line[4096];
LOGD("log_monitor: logger start");
while (1) {
if (!logd) {
// Disable all services
for (int i = 0; i < (sizeof(log_events) / sizeof(struct log_listener)); ++i) {
close(log_events[i].fd);
log_events[i].fd = -1;
}
return NULL;
}
// Start logcat
log_pid = exec_command(0, &log_fd, NULL, "logcat", "-b", "events", "-b", "main", "-v", "threadtime", "-s", "am_proc_start", "-s", "Magisk", NULL);
while (fdgets(line, sizeof(line), log_fd)) {
for (int i = 0; i < (sizeof(log_events) / sizeof(struct log_listener)); ++i) {
if (log_events[i].fd > 0 && log_events[i].filter(line)) {
char *s = strdup(line);
xwrite(log_events[i].fd, &s, sizeof(s));
}
}
if (kill(log_pid, 0))
break;
}
// Cleanup
close(log_fd);
log_fd = -1;
kill(log_pid, SIGTERM);
waitpid(log_pid, NULL, 0);
// Clear buffer before restart
exec_command_sync("logcat", "-b", "events", "-b", "main", "-c", NULL);
check_logd();
}
// Should never be here, but well...
return NULL;
}
static void *magisk_log_thread(void *args) {
// Buffer logs before we have data access
struct vector logs;
vec_init(&logs);
int pipefd[2];
if (xpipe2(pipefd, O_CLOEXEC) == -1)
return NULL;
// Register our listener
log_events[LOG_EVENT].fd = pipefd[1];
LOGD("log_monitor: magisk log dumper start");
FILE *log = NULL;
for (char *line; xxread(pipefd[0], &line, sizeof(line)) > 0; free(line)) {
if (!is_daemon_init) {
vec_push_back(&logs, strdup(line));
} else {
if (log == NULL) {
// Dump buffered logs to file
log = xfopen(LOGFILE, "w");
setbuf(log, NULL);
char *tmp;
vec_for_each(&logs, tmp) {
fprintf(log, "%s", tmp);
free(tmp);
}
vec_destroy(&logs);
}
fprintf(log, "%s", line);
}
}
return NULL;
}
static void *debug_magisk_log_thread(void *args) {
FILE *log = xfopen(DEBUG_LOG, "a");
setbuf(log, NULL);
int pipefd[2];
if (xpipe2(pipefd, O_CLOEXEC) == -1)
return NULL;
LOGD("log_monitor: debug log dumper start");
// Register our listener
log_events[DEBUG_EVENT].fd = pipefd[1];
for (char *line; xxread(pipefd[0], &line, sizeof(line)) > 0; free(line))
fprintf(log, "%s", line);
return NULL;
}
/* Start new threads to monitor logcat and dump to logfile */
void monitor_logs() {
pthread_t thread;
check_logd();
if (logd) {
// Start log file dumper before monitor
xpthread_create(&thread, NULL, magisk_log_thread, NULL);
pthread_detach(thread);
// Start logcat monitor
xpthread_create(&thread, NULL, logger_thread, NULL);
pthread_detach(thread);
}
}
void start_debug_full_log() {
#ifdef MAGISK_DEBUG
if (logd) {
// Log everything initially
debug_log_fd = xopen(DEBUG_LOG, O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC, 0644);
debug_log_pid = exec_command(0, &debug_log_fd, NULL, "logcat", "-v", "threadtime", NULL);
close(debug_log_fd);
}
#endif
}
void stop_debug_full_log() {
#ifdef MAGISK_DEBUG
// Stop recording the boot logcat after every boot task is done
if (debug_log_pid > 0) {
kill(debug_log_pid, SIGTERM);
waitpid(debug_log_pid, NULL, 0);
// Start debug thread
start_debug_log();
}
#endif
}
void start_debug_log() {
#ifdef MAGISK_DEBUG
if (logd) {
pthread_t thread;
// Start debug thread
xpthread_create(&thread, NULL, debug_magisk_log_thread, NULL);
pthread_detach(thread);
}
#endif
}

177
native/jni/core/magisk.c Normal file
View File

@@ -0,0 +1,177 @@
/* main.c - The multicall entry point
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <libgen.h>
#include "utils.h"
#include "magisk.h"
#include "daemon.h"
char *argv0;
int (*applet_main[]) (int, char *[]) = { su_client_main, resetprop_main, magiskhide_main, NULL };
int create_links(const char *bin, const char *path) {
char self[PATH_MAX], linkpath[PATH_MAX];
if (bin == NULL) {
xreadlink("/proc/self/exe", self, sizeof(self));
bin = self;
}
int ret = 0;
for (int i = 0; applet[i]; ++i) {
snprintf(linkpath, sizeof(linkpath), "%s/%s", path, applet[i]);
unlink(linkpath);
ret |= symlink(bin, linkpath);
}
return ret;
}
static void usage() {
fprintf(stderr,
"Magisk v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") (by topjohnwu) multi-call binary\n"
"\n"
"Usage: %s [applet [arguments]...]\n"
" or: %s [options]...\n"
"\n"
"Options:\n"
" -c print current binary version\n"
" -v print running daemon version\n"
" -V print running daemon version code\n"
" --list list all available applets\n"
" --install [SOURCE] DIR symlink all applets to DIR. SOURCE is optional\n"
" --createimg IMG SIZE create ext4 image. SIZE is interpreted in MB\n"
" --imgsize IMG report ext4 image used/total size\n"
" --resizeimg IMG SIZE resize ext4 image. SIZE is interpreted in MB\n"
" --mountimg IMG PATH mount IMG to PATH and prints the loop device\n"
" --umountimg PATH LOOP unmount PATH and delete LOOP device\n"
" --[init service] start init service\n"
" --unlock-blocks set BLKROSET flag to OFF for all block devices\n"
" --restorecon fix selinux context on Magisk files and folders\n"
" --clone-attr SRC DEST clone permission, owner, and selinux context\n"
"\n"
"Supported init services:\n"
" daemon, post-fs, post-fs-data, service\n"
"\n"
"Supported applets:\n"
, argv0, argv0);
for (int i = 0; applet[i]; ++i)
fprintf(stderr, i ? ", %s" : " %s", applet[i]);
fprintf(stderr, "\n\n");
exit(1);
}
int main(int argc, char *argv[]) {
argv0 = argv[0];
if (strcmp(basename(argv[0]), "magisk") == 0) {
if (argc < 2) usage();
if (strcmp(argv[1], "-c") == 0) {
printf("%s (%d)\n", MAGISK_VER_STR, MAGISK_VER_CODE);
return 0;
} else if (strcmp(argv[1], "-v") == 0) {
int fd = connect_daemon();
write_int(fd, CHECK_VERSION);
char *v = read_string(fd);
printf("%s\n", v);
free(v);
return 0;
} else if (strcmp(argv[1], "-V") == 0) {
int fd = connect_daemon();
write_int(fd, CHECK_VERSION_CODE);
printf("%d\n", read_int(fd));
return 0;
} else if (strcmp(argv[1], "--install") == 0) {
if (argc < 3) usage();
if (argc == 3) return create_links(NULL, argv[2]);
else return create_links(argv[2], argv[3]);
} else if (strcmp(argv[1], "--list") == 0) {
for (int i = 0; applet[i]; ++i)
printf("%s\n", applet[i]);
return 0;
} else if (strcmp(argv[1], "--createimg") == 0) {
if (argc < 4) usage();
int size;
sscanf(argv[3], "%d", &size);
return create_img(argv[2], size);
} else if (strcmp(argv[1], "--imgsize") == 0) {
if (argc < 3) usage();
int used, total;
if (get_img_size(argv[2], &used, &total)) {
fprintf(stderr, "Cannot check %s size\n", argv[2]);
return 1;
}
printf("%d %d\n", used, total);
return 0;
} else if (strcmp(argv[1], "--resizeimg") == 0) {
if (argc < 4) usage();
int used, total, size;
sscanf(argv[3], "%d", &size);
if (get_img_size(argv[2], &used, &total)) {
fprintf(stderr, "Cannot check %s size\n", argv[2]);
return 1;
}
if (size <= used) {
fprintf(stderr, "Cannot resize smaller than %dM\n", used);
return 1;
}
return resize_img(argv[2], size);
} else if (strcmp(argv[1], "--mountimg") == 0) {
if (argc < 4) usage();
char *loop = mount_image(argv[2], argv[3]);
if (loop == NULL) {
fprintf(stderr, "Cannot mount image!\n");
return 1;
} else {
printf("%s\n", loop);
free(loop);
return 0;
}
} else if (strcmp(argv[1], "--umountimg") == 0) {
if (argc < 4) usage();
umount_image(argv[2], argv[3]);
return 0;
} else if (strcmp(argv[1], "--unlock-blocks") == 0) {
unlock_blocks();
return 0;
} else if (strcmp(argv[1], "--restorecon") == 0) {
fix_filecon();
return 0;
} else if (strcmp(argv[1], "--clone-attr") == 0) {
if (argc < 4) usage();
clone_attr(argv[2], argv[3]);
return 0;
} else if (strcmp(argv[1], "--daemon") == 0) {
if (xfork() == 0)
start_daemon();
return 0;
} else if (strcmp(argv[1], "--post-fs") == 0) {
int fd = connect_daemon();
write_int(fd, POST_FS);
return read_int(fd);
} else if (strcmp(argv[1], "--post-fs-data") == 0) {
int fd = connect_daemon();
write_int(fd, POST_FS_DATA);
return read_int(fd);
} else if (strcmp(argv[1], "--service") == 0) {
int fd = connect_daemon();
write_int(fd, LATE_START);
return read_int(fd);
} else {
// It's calling applets
--argc;
++argv;
}
}
// Applets
for (int i = 0; applet[i]; ++i) {
if (strcmp(basename(argv[0]), applet[i]) == 0)
return (*applet_main[i])(argc, argv);
}
fprintf(stderr, "%s: applet not found\n", basename(argv[0]));
return 1;
}

View File

@@ -0,0 +1,543 @@
/* magiskinit.c - Pre-init Magisk support
*
* This code has to be compiled statically to work properly.
*
* To unify Magisk support for both legacy "normal" devices and new skip_initramfs devices,
* magisk binary compilation is split into two parts - first part only compiles "magisk".
* The python build script will load the magisk main binary and compress with lzma2, dumping
* the results into "dump.h". The "magisk" binary is embedded into this binary, and will
* get extracted to the overlay folder along with init.magisk.rc.
*
* This tool does all pre-init operations to setup a Magisk environment, which pathces rootfs
* on the fly, providing fundamental support such as init, init.rc, and sepolicy patching.
*
* Magiskinit is also responsible for constructing 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.
*
* 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)
*/
#define _GNU_SOURCE
#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 <lzma.h>
#include <cil/cil.h>
#include "dump.h"
#include "magiskrc.h"
#include "utils.h"
#include "magiskpolicy.h"
#include "daemon.h"
#include "cpio.h"
#include "magisk.h"
#ifdef MAGISK_DEBUG
#define VLOG(fmt, ...) printf(fmt, __VA_ARGS__)
#else
#define VLOG(fmt, ...)
#endif
extern policydb_t *policydb;
int (*init_applet_main[]) (int, char *[]) = { magiskpolicy_main, magiskpolicy_main, NULL };
static char RAND_SOCKET_NAME[sizeof(SOCKET_NAME)];
static int SOCKET_OFF = -1;
struct cmdline {
char skip_initramfs;
char slot[3];
};
struct device {
dev_t major;
dev_t minor;
char devname[32];
char partname[32];
char path[64];
};
static void parse_cmdline(struct cmdline *cmd) {
// cleanup
memset(cmd, 0, sizeof(&cmd));
char cmdline[4096];
mkdir("/proc", 0555);
xmount("proc", "/proc", "proc", 0, NULL);
int fd = open("/proc/cmdline", O_RDONLY | O_CLOEXEC);
cmdline[read(fd, cmdline, sizeof(cmdline))] = '\0';
close(fd);
umount("/proc");
for (char *tok = strtok(cmdline, " "); tok; tok = strtok(NULL, " ")) {
if (strncmp(tok, "androidboot.slot_suffix", 23) == 0) {
sscanf(tok, "androidboot.slot_suffix=%s", cmd->slot);
} else if (strncmp(tok, "androidboot.slot", 16) == 0) {
cmd->slot[0] = '_';
sscanf(tok, "androidboot.slot=%c", cmd->slot + 1);
} else if (strcmp(tok, "skip_initramfs") == 0) {
cmd->skip_initramfs = 1;
}
}
VLOG("cmdline: skip_initramfs[%d] slot[%s]\n", cmd->skip_initramfs, cmd->slot);
}
static void parse_device(struct device *dev, char *uevent) {
dev->partname[0] = '\0';
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");
}
VLOG("%s [%s] (%u, %u)\n", dev->devname, dev->partname, (unsigned) dev->major, (unsigned) dev->minor);
}
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, SPLIT_PLAT_CIL, sizeof(SPLIT_PLAT_CIL) - 1) == 0) {
memcpy(addr + i + sizeof(SPLIT_PLAT_CIL) - 4, "xxx", 3);
break;
}
}
munmap(addr, size);
full_read("/init.rc", &addr, &size);
patch_init_rc(&addr, &size);
int fd = creat("/init.rc", 0750);
write(fd, addr, size);
close(fd);
free(addr);
}
static int strend(const char *s1, const char *s2) {
size_t l1 = strlen(s1);
size_t 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_multiple_decls(db, 1);
cil_set_disable_neverallow(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(SPLIT_PLAT_CIL, &addr, &size);
VLOG("cil_add[%s]\n", SPLIT_PLAT_CIL);
cil_add_file(db, SPLIT_PLAT_CIL, addr, size);
munmap(addr, size);
// mapping
char plat[10];
int fd = open(SPLIT_NONPLAT_VER, O_RDONLY | O_CLOEXEC);
plat[read(fd, plat, sizeof(plat)) - 1] = '\0';
snprintf(path, sizeof(path), SPLIT_PLAT_MAPPING, plat);
mmap_ro(path, &addr, &size);
VLOG("cil_add[%s]\n", path);
cil_add_file(db, path, addr, size);
munmap(addr, size);
close(fd);
// nonplat
dir = opendir(NONPLAT_POLICY_DIR);
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), NONPLAT_POLICY_DIR "%s", entry->d_name);
mmap_ro(path, &addr, &size);
VLOG("cil_add[%s]\n", path);
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];
// init the strings with different value
sys_sha[0] = 0;
ven_sha[0] = 1;
dir = opendir(NONPLAT_POLICY_DIR);
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)) - 1] = '\0';
close(fd);
break;
}
}
closedir(dir);
dir = opendir(PLAT_POLICY_DIR);
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)) - 1] = '\0';
close(fd);
break;
}
}
closedir(dir);
VLOG("sys_sha[%s]\nven_sha[%s]\n", sys_sha, ven_sha);
return strcmp(sys_sha, ven_sha) == 0;
}
static int patch_sepolicy() {
if (access("/sepolicy", R_OK) == 0)
load_policydb("/sepolicy");
else if (access(SPLIT_PRECOMPILE, R_OK) == 0 && verify_precompiled())
load_policydb(SPLIT_PRECOMPILE);
else if (access(SPLIT_PLAT_CIL, R_OK) == 0)
compile_cil();
else
return 1;
sepol_magisk_rules();
dump_policydb("/sepolicy");
// Remove the stupid debug sepolicy and use our own
if (access("/sepolicy_debug", F_OK) == 0) {
unlink("/sepolicy_debug");
link("/sepolicy", "/sepolicy_debug");
}
return 0;
}
#define BUFSIZE (1 << 20)
static int unxz(const void *buf, size_t size, int fd) {
lzma_stream strm = LZMA_STREAM_INIT;
if (lzma_auto_decoder(&strm, UINT64_MAX, 0) != LZMA_OK)
return 1;
lzma_ret ret;
void *out = malloc(BUFSIZE);
strm.next_in = buf;
strm.avail_in = size;
do {
strm.next_out = out;
strm.avail_out = BUFSIZE;
ret = lzma_code(&strm, LZMA_RUN);
write(fd, out, BUFSIZE - strm.avail_out);
} while (strm.avail_out == 0 && ret == LZMA_OK);
free(out);
lzma_end(&strm);
if (ret != LZMA_OK && ret != LZMA_STREAM_END)
return 1;
return 0;
}
static int dump_magisk(const char *path, mode_t mode) {
unlink(path);
int fd = creat(path, mode);
int ret = unxz(magisk_dump, sizeof(magisk_dump), fd);
close(fd);
return ret;
}
static int dump_magiskrc(const char *path, mode_t mode) {
int fd = creat(path, mode);
write(fd, magiskrc, sizeof(magiskrc));
close(fd);
return 0;
}
static void patch_socket_name(const char *path) {
void *buf;
size_t size;
mmap_rw(path, &buf, &size);
if (SOCKET_OFF < 0) {
for (int i = 0; i < size; ++i) {
if (memcmp(buf + i, socket_name, sizeof(SOCKET_NAME)) == 0) {
SOCKET_OFF = i;
break;
}
}
}
gen_rand_str(RAND_SOCKET_NAME, sizeof(SOCKET_NAME));
memcpy(buf + SOCKET_OFF, RAND_SOCKET_NAME, sizeof(SOCKET_NAME));
munmap(buf, size);
}
static void magisk_init_daemon() {
setsid();
// Full patch
sepol_allow("su", ALL, ALL, ALL);
// Wait till init cold boot done
while (access("/dev/.coldboot_done", F_OK))
usleep(1);
int null = open("/dev/null", O_RDWR | O_CLOEXEC);
dup3(null, STDIN_FILENO, O_CLOEXEC);
dup3(null, STDOUT_FILENO, O_CLOEXEC);
dup3(null, STDERR_FILENO, O_CLOEXEC);
if (null > STDERR_FILENO)
close(null);
// Transit our context to su (mimic setcon)
int fd, crap;
fd = open("/proc/self/attr/current", O_WRONLY);
write(fd, "u:r:su:s0", 9);
close(fd);
// Dump full patch to kernel
dump_policydb(SELINUX_LOAD);
close(creat(PATCHDONE, 0));
destroy_policydb();
// Keep Magisk daemon always alive
while (1) {
struct sockaddr_un sun;
fd = setup_socket(&sun);
memcpy(sun.sun_path + 1, RAND_SOCKET_NAME, sizeof(SOCKET_NAME));
while (connect(fd, (struct sockaddr*) &sun, sizeof(sun)))
usleep(10000); /* Wait 10 ms after each try */
/* Should hold forever */
read(fd, &crap, sizeof(crap));
/* If things went here, it means the other side of the socket is closed
* We restart the daemon again */
close(fd);
if (fork_dont_care() == 0) {
execv("/sbin/magisk", (char *[]) { "magisk", "--daemon", NULL } );
exit(1);
}
}
}
int main(int argc, char *argv[]) {
umask(0);
for (int i = 0; init_applet[i]; ++i) {
if (strcmp(basename(argv[0]), init_applet[i]) == 0)
return (*init_applet_main[i])(argc, argv);
}
if (argc > 1 && strcmp(argv[1], "-x") == 0) {
if (strcmp(argv[2], "magisk") == 0)
return dump_magisk(argv[3], 0755);
else if (strcmp(argv[2], "magiskrc") == 0)
return dump_magiskrc(argv[3], 0755);
}
// Prevent file descriptor confusion
mknod("/null", S_IFCHR | 0666, makedev(1, 3));
int null = open("/null", O_RDWR | O_CLOEXEC);
unlink("/null");
dup3(null, STDIN_FILENO, O_CLOEXEC);
dup3(null, STDOUT_FILENO, O_CLOEXEC);
dup3(null, STDERR_FILENO, O_CLOEXEC);
if (null > STDERR_FILENO)
close(null);
// Extract and link files
mkdir("/overlay", 0000);
dump_magiskrc("/overlay/init.magisk.rc", 0750);
mkdir("/overlay/sbin", 0755);
dump_magisk("/overlay/sbin/magisk", 0755);
patch_socket_name("/overlay/sbin/magisk");
mkdir("/overlay/root", 0755);
link("/init", "/overlay/root/magiskinit");
struct cmdline cmd;
parse_cmdline(&cmd);
/* ***********
* Initialize
* ***********/
int root = open("/", O_RDONLY | O_CLOEXEC);
if (cmd.skip_initramfs) {
// Clear rootfs
excl_list = (char *[]) { "overlay", ".backup", NULL };
frm_rf(root);
} else if (access("/ramdisk.cpio.xz", R_OK) == 0) {
// High compression mode
void *addr;
size_t size;
mmap_ro("/ramdisk.cpio.xz", &addr, &size);
int fd = creat("/ramdisk.cpio", 0);
unxz(addr, size, fd);
munmap(addr, size);
close(fd);
struct vector v;
vec_init(&v);
parse_cpio(&v, "/ramdisk.cpio");
excl_list = (char *[]) { "overlay", ".backup", NULL };
frm_rf(root);
chdir("/");
cpio_extract_all(&v);
cpio_vec_destroy(&v);
} else {
// Revert original init binary
unlink("/init");
link("/.backup/init", "/init");
}
/* ************
* Early Mount
* ************/
// If skip_initramfs or using split policies, we need early mount
if (cmd.skip_initramfs || access("/sepolicy", R_OK) != 0) {
char partname[32];
struct device dev;
// Mount sysfs
mkdir("/sys", 0755);
xmount("sysfs", "/sys", "sysfs", 0, NULL);
// Mount system
snprintf(partname, sizeof(partname), "system%s", cmd.slot);
setup_block(&dev, partname);
if (cmd.skip_initramfs) {
mkdir("/system_root", 0755);
xmount(dev.path, "/system_root", "ext4", MS_RDONLY, NULL);
int system_root = open("/system_root", O_RDONLY | O_CLOEXEC);
// Clone rootfs except /system
excl_list = (char *[]) { "system", NULL };
clone_dir(system_root, root);
close(system_root);
mkdir("/system", 0755);
xmount("/system_root/system", "/system", NULL, MS_BIND, NULL);
} else {
xmount(dev.path, "/system", "ext4", MS_RDONLY, NULL);
}
// Mount vendor
snprintf(partname, sizeof(partname), "vendor%s", cmd.slot);
if (setup_block(&dev, partname) == 0)
xmount(dev.path, "/vendor", "ext4", MS_RDONLY, NULL);
}
/* *************
* Patch rootfs
* *************/
// Only patch rootfs if not intended to run in recovery
if (access("/etc/recovery.fstab", F_OK) != 0) {
int overlay = open("/overlay", O_RDONLY | O_CLOEXEC);
mv_dir(overlay, root);
close(overlay);
rmdir("/overlay");
patch_ramdisk();
patch_sepolicy();
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
if (fork_dont_care() == 0) {
strcpy(argv[0], "magiskinit");
close(root);
magisk_init_daemon();
}
}
// Clean up
close(root);
if (!cmd.skip_initramfs)
umount("/system");
umount("/vendor");
// Finally, give control back!
execv("/init", argv);
}

155
native/jni/core/socket.c Normal file
View File

@@ -0,0 +1,155 @@
/* socket.c - All socket related operations
*/
#include <fcntl.h>
#include "daemon.h"
#include "logging.h"
#include "utils.h"
#include "magisk.h"
char socket_name[] = SOCKET_NAME;
/* Setup the address and return socket fd */
int setup_socket(struct sockaddr_un *sun) {
int fd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
memset(sun, 0, sizeof(*sun));
sun->sun_family = AF_LOCAL;
sun->sun_path[0] = '\0';
memcpy(sun->sun_path + 1, socket_name, sizeof(SOCKET_NAME));
return fd;
}
/*
* Receive a file descriptor from a Unix socket.
* Contributed by @mkasick
*
* Returns the file descriptor on success, or -1 if a file
* descriptor was not actually included in the message
*
* On error the function terminates by calling exit(-1)
*/
int recv_fd(int sockfd) {
// Need to receive data from the message, otherwise don't care about it.
char iovbuf;
struct iovec iov = {
.iov_base = &iovbuf,
.iov_len = 1,
};
char cmsgbuf[CMSG_SPACE(sizeof(int))];
struct msghdr msg = {
.msg_iov = &iov,
.msg_iovlen = 1,
.msg_control = cmsgbuf,
.msg_controllen = sizeof(cmsgbuf),
};
xrecvmsg(sockfd, &msg, MSG_WAITALL);
// Was a control message actually sent?
switch (msg.msg_controllen) {
case 0:
// No, so the file descriptor was closed and won't be used.
return -1;
case sizeof(cmsgbuf):
// Yes, grab the file descriptor from it.
break;
default:
goto error;
}
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
if (cmsg == NULL ||
cmsg->cmsg_len != CMSG_LEN(sizeof(int)) ||
cmsg->cmsg_level != SOL_SOCKET ||
cmsg->cmsg_type != SCM_RIGHTS) {
error:
LOGE("unable to read fd");
exit(-1);
}
return *(int *)CMSG_DATA(cmsg);
}
/*
* Send a file descriptor through a Unix socket.
* Contributed by @mkasick
*
* On error the function terminates by calling exit(-1)
*
* fd may be -1, in which case the dummy data is sent,
* but no control message with the FD is sent.
*/
void send_fd(int sockfd, int fd) {
// Need to send some data in the message, this will do.
struct iovec iov = {
.iov_base = "",
.iov_len = 1,
};
struct msghdr msg = {
.msg_iov = &iov,
.msg_iovlen = 1,
};
char cmsgbuf[CMSG_SPACE(sizeof(int))];
if (fd != -1) {
// Is the file descriptor actually open?
if (fcntl(fd, F_GETFD) == -1) {
if (errno != EBADF) {
PLOGE("unable to send fd");
}
// It's closed, don't send a control message or sendmsg will EBADF.
} else {
// It's open, send the file descriptor in a control message.
msg.msg_control = cmsgbuf;
msg.msg_controllen = sizeof(cmsgbuf);
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
*(int *)CMSG_DATA(cmsg) = fd;
}
}
xsendmsg(sockfd, &msg, 0);
}
int read_int(int fd) {
int val;
xxread(fd, &val, sizeof(int));
return val;
}
void write_int(int fd, int val) {
if (fd < 0) return;
xwrite(fd, &val, sizeof(int));
}
char* read_string(int fd) {
int len = read_int(fd);
if (len > PATH_MAX || len < 0) {
LOGE("invalid string length %d", len);
exit(1);
}
char* val = xmalloc(sizeof(char) * (len + 1));
xxread(fd, val, len);
val[len] = '\0';
return val;
}
void write_string(int fd, const char* val) {
if (fd < 0) return;
int len = strlen(val);
write_int(fd, len);
xwrite(fd, val, len);
}

172
native/jni/external/Android.mk vendored Normal file
View File

@@ -0,0 +1,172 @@
LOCAL_PATH:= $(call my-dir)
# libsqlite.so (stub)
include $(CLEAR_VARS)
LOCAL_MODULE:= libsqlite
LOCAL_C_INCLUDES := $(EXT_PATH)/include
LOCAL_SRC_FILES := stubs/sqlite3_stub.c
include $(BUILD_SHARED_LIBRARY)
# libselinux.so (stub)
include $(CLEAR_VARS)
LOCAL_MODULE:= libselinux
LOCAL_C_INCLUDES := $(LIBSELINUX)
LOCAL_SRC_FILES := stubs/selinux_stub.c
include $(BUILD_SHARED_LIBRARY)
# libmincrypt.a
include $(CLEAR_VARS)
LOCAL_MODULE:= libmincrypt
LOCAL_C_INCLUDES := $(EXT_PATH)/include
LOCAL_SRC_FILES := \
mincrypt/dsa_sig.c \
mincrypt/p256.c \
mincrypt/p256_ec.c \
mincrypt/p256_ecdsa.c \
mincrypt/rsa.c \
mincrypt/sha.c \
mincrypt/sha256.c
include $(BUILD_STATIC_LIBRARY)
# libfdt.a
include $(CLEAR_VARS)
LOCAL_MODULE:= libfdt
LOCAL_C_INCLUDES := $(LIBFDT)
LOCAL_SRC_FILES := \
dtc/libfdt/fdt.c \
dtc/libfdt/fdt_addresses.c \
dtc/libfdt/fdt_empty_tree.c \
dtc/libfdt/fdt_overlay.c \
dtc/libfdt/fdt_ro.c \
dtc/libfdt/fdt_rw.c \
dtc/libfdt/fdt_strerror.c \
dtc/libfdt/fdt_sw.c \
dtc/libfdt/fdt_wip.c
include $(BUILD_STATIC_LIBRARY)
# liblz4.a
include $(CLEAR_VARS)
LOCAL_MODULE := liblz4
LOCAL_C_INCLUDES += $(LIBLZ4)
LOCAL_SRC_FILES := \
lz4/lib/lz4.c \
lz4/lib/lz4frame.c \
lz4/lib/lz4hc.c \
lz4/lib/xxhash.c
include $(BUILD_STATIC_LIBRARY)
# libbz2.a
include $(CLEAR_VARS)
LOCAL_MODULE := libbz2
LOCAL_C_INCLUDES += $(LIBBZ2)
LOCAL_SRC_FILES := \
bzip2/blocksort.c \
bzip2/huffman.c \
bzip2/crctable.c \
bzip2/randtable.c \
bzip2/compress.c \
bzip2/decompress.c \
bzip2/bzlib.c
include $(BUILD_STATIC_LIBRARY)
# liblzma.a
include $(CLEAR_VARS)
LOCAL_MODULE := liblzma
LOCAL_C_INCLUDES += \
$(EXT_PATH)/include/xz_config \
$(EXT_PATH)/xz/src/common \
$(EXT_PATH)/xz/src/liblzma/api \
$(EXT_PATH)/xz/src/liblzma/check \
$(EXT_PATH)/xz/src/liblzma/common \
$(EXT_PATH)/xz/src/liblzma/delta \
$(EXT_PATH)/xz/src/liblzma/lz \
$(EXT_PATH)/xz/src/liblzma/lzma \
$(EXT_PATH)/xz/src/liblzma/rangecoder \
$(EXT_PATH)/xz/src/liblzma/simple \
$(EXT_PATH)/xz/src/liblzma
LOCAL_SRC_FILES := \
xz/src/common/tuklib_cpucores.c \
xz/src/common/tuklib_exit.c \
xz/src/common/tuklib_mbstr_fw.c \
xz/src/common/tuklib_mbstr_width.c \
xz/src/common/tuklib_open_stdxxx.c \
xz/src/common/tuklib_physmem.c \
xz/src/common/tuklib_progname.c \
xz/src/liblzma/check/check.c \
xz/src/liblzma/check/crc32_fast.c \
xz/src/liblzma/check/crc32_table.c \
xz/src/liblzma/check/crc64_fast.c \
xz/src/liblzma/check/crc64_table.c \
xz/src/liblzma/check/sha256.c \
xz/src/liblzma/common/alone_decoder.c \
xz/src/liblzma/common/alone_encoder.c \
xz/src/liblzma/common/auto_decoder.c \
xz/src/liblzma/common/block_buffer_decoder.c \
xz/src/liblzma/common/block_buffer_encoder.c \
xz/src/liblzma/common/block_decoder.c \
xz/src/liblzma/common/block_encoder.c \
xz/src/liblzma/common/block_header_decoder.c \
xz/src/liblzma/common/block_header_encoder.c \
xz/src/liblzma/common/block_util.c \
xz/src/liblzma/common/common.c \
xz/src/liblzma/common/easy_buffer_encoder.c \
xz/src/liblzma/common/easy_decoder_memusage.c \
xz/src/liblzma/common/easy_encoder.c \
xz/src/liblzma/common/easy_encoder_memusage.c \
xz/src/liblzma/common/easy_preset.c \
xz/src/liblzma/common/filter_buffer_decoder.c \
xz/src/liblzma/common/filter_buffer_encoder.c \
xz/src/liblzma/common/filter_common.c \
xz/src/liblzma/common/filter_decoder.c \
xz/src/liblzma/common/filter_encoder.c \
xz/src/liblzma/common/filter_flags_decoder.c \
xz/src/liblzma/common/filter_flags_encoder.c \
xz/src/liblzma/common/hardware_cputhreads.c \
xz/src/liblzma/common/hardware_physmem.c \
xz/src/liblzma/common/index.c \
xz/src/liblzma/common/index_decoder.c \
xz/src/liblzma/common/index_encoder.c \
xz/src/liblzma/common/index_hash.c \
xz/src/liblzma/common/outqueue.c \
xz/src/liblzma/common/stream_buffer_decoder.c \
xz/src/liblzma/common/stream_buffer_encoder.c \
xz/src/liblzma/common/stream_decoder.c \
xz/src/liblzma/common/stream_encoder.c \
xz/src/liblzma/common/stream_encoder_mt.c \
xz/src/liblzma/common/stream_flags_common.c \
xz/src/liblzma/common/stream_flags_decoder.c \
xz/src/liblzma/common/stream_flags_encoder.c \
xz/src/liblzma/common/vli_decoder.c \
xz/src/liblzma/common/vli_encoder.c \
xz/src/liblzma/common/vli_size.c \
xz/src/liblzma/delta/delta_common.c \
xz/src/liblzma/delta/delta_decoder.c \
xz/src/liblzma/delta/delta_encoder.c \
xz/src/liblzma/lz/lz_decoder.c \
xz/src/liblzma/lz/lz_encoder.c \
xz/src/liblzma/lz/lz_encoder_mf.c \
xz/src/liblzma/lzma/fastpos_table.c \
xz/src/liblzma/lzma/fastpos_tablegen.c \
xz/src/liblzma/lzma/lzma2_decoder.c \
xz/src/liblzma/lzma/lzma2_encoder.c \
xz/src/liblzma/lzma/lzma_decoder.c \
xz/src/liblzma/lzma/lzma_encoder.c \
xz/src/liblzma/lzma/lzma_encoder_optimum_fast.c \
xz/src/liblzma/lzma/lzma_encoder_optimum_normal.c \
xz/src/liblzma/lzma/lzma_encoder_presets.c \
xz/src/liblzma/rangecoder/price_table.c \
xz/src/liblzma/rangecoder/price_tablegen.c \
xz/src/liblzma/simple/arm.c \
xz/src/liblzma/simple/armthumb.c \
xz/src/liblzma/simple/ia64.c \
xz/src/liblzma/simple/powerpc.c \
xz/src/liblzma/simple/simple_coder.c \
xz/src/liblzma/simple/simple_decoder.c \
xz/src/liblzma/simple/simple_encoder.c \
xz/src/liblzma/simple/sparc.c \
xz/src/liblzma/simple/x86.c
LOCAL_CFLAGS += -DHAVE_CONFIG_H -std=c99
include $(BUILD_STATIC_LIBRARY)
# libsepol.a
include $(SE_PATH)/libsepol/Android.mk

1
native/jni/external/busybox vendored Submodule

1
native/jni/external/bzip2 vendored Submodule

1
native/jni/external/dtc vendored Submodule

Submodule native/jni/external/dtc added at e54388015a

View File

@@ -0,0 +1,43 @@
/*
* Copyright 2013 The Android Open Source Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Google Inc. nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_DSA_SIG_H_
#define SYSTEM_CORE_INCLUDE_MINCRYPT_DSA_SIG_H_
#include "mincrypt/p256.h"
#ifdef __cplusplus
extern "C" {
#endif
// Returns 0 if input sig is not a valid ASN.1 sequence
int dsa_sig_unpack(unsigned char* sig, int sig_len, p256_int* r_int, p256_int* s_int);
#ifdef __cplusplus
}
#endif
#endif /* SYSTEM_CORE_INCLUDE_MINCRYPT_DSA_SIG_H_ */

View File

@@ -0,0 +1,63 @@
/*
* Copyright 2007 The Android Open Source Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Google Inc. nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_HASH_INTERNAL_H_
#define SYSTEM_CORE_INCLUDE_MINCRYPT_HASH_INTERNAL_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
struct HASH_CTX; // forward decl
typedef struct HASH_VTAB {
void (* const init)(struct HASH_CTX*);
void (* const update)(struct HASH_CTX*, const void*, int);
const uint8_t* (* const final)(struct HASH_CTX*);
const uint8_t* (* const hash)(const void*, int, uint8_t*);
int size;
} HASH_VTAB;
typedef struct HASH_CTX {
const HASH_VTAB * f;
uint64_t count;
uint8_t buf[64];
uint32_t state[8]; // upto SHA2
} HASH_CTX;
#define HASH_init(ctx) (ctx)->f->init(ctx)
#define HASH_update(ctx, data, len) (ctx)->f->update(ctx, data, len)
#define HASH_final(ctx) (ctx)->f->final(ctx)
#define HASH_hash(data, len, digest) (ctx)->f->hash(data, len, digest)
#define HASH_size(ctx) (ctx)->f->size
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // SYSTEM_CORE_INCLUDE_MINCRYPT_HASH_INTERNAL_H_

View File

@@ -0,0 +1,162 @@
/*
* Copyright 2013 The Android Open Source Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Google Inc. nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_LITE_P256_H_
#define SYSTEM_CORE_INCLUDE_MINCRYPT_LITE_P256_H_
// Collection of routines manipulating 256 bit unsigned integers.
// Just enough to implement ecdsa-p256 and related algorithms.
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define P256_BITSPERDIGIT 32
#define P256_NDIGITS 8
#define P256_NBYTES 32
typedef int p256_err;
typedef uint32_t p256_digit;
typedef int32_t p256_sdigit;
typedef uint64_t p256_ddigit;
typedef int64_t p256_sddigit;
// Defining p256_int as struct to leverage struct assigment.
typedef struct {
p256_digit a[P256_NDIGITS];
} p256_int;
extern const p256_int SECP256r1_n; // Curve order
extern const p256_int SECP256r1_p; // Curve prime
extern const p256_int SECP256r1_b; // Curve param
// Initialize a p256_int to zero.
void p256_init(p256_int* a);
// Clear a p256_int to zero.
void p256_clear(p256_int* a);
// Return bit. Index 0 is least significant.
int p256_get_bit(const p256_int* a, int index);
// b := a % MOD
void p256_mod(
const p256_int* MOD,
const p256_int* a,
p256_int* b);
// c := a * (top_b | b) % MOD
void p256_modmul(
const p256_int* MOD,
const p256_int* a,
const p256_digit top_b,
const p256_int* b,
p256_int* c);
// b := 1 / a % MOD
// MOD best be SECP256r1_n
void p256_modinv(
const p256_int* MOD,
const p256_int* a,
p256_int* b);
// b := 1 / a % MOD
// MOD best be SECP256r1_n
// Faster than p256_modinv()
void p256_modinv_vartime(
const p256_int* MOD,
const p256_int* a,
p256_int* b);
// b := a << (n % P256_BITSPERDIGIT)
// Returns the bits shifted out of most significant digit.
p256_digit p256_shl(const p256_int* a, int n, p256_int* b);
// b := a >> (n % P256_BITSPERDIGIT)
void p256_shr(const p256_int* a, int n, p256_int* b);
int p256_is_zero(const p256_int* a);
int p256_is_odd(const p256_int* a);
int p256_is_even(const p256_int* a);
// Returns -1, 0 or 1.
int p256_cmp(const p256_int* a, const p256_int *b);
// c: = a - b
// Returns -1 on borrow.
int p256_sub(const p256_int* a, const p256_int* b, p256_int* c);
// c := a + b
// Returns 1 on carry.
int p256_add(const p256_int* a, const p256_int* b, p256_int* c);
// c := a + (single digit)b
// Returns carry 1 on carry.
int p256_add_d(const p256_int* a, p256_digit b, p256_int* c);
// ec routines.
// {out_x,out_y} := nG
void p256_base_point_mul(const p256_int *n,
p256_int *out_x,
p256_int *out_y);
// {out_x,out_y} := n{in_x,in_y}
void p256_point_mul(const p256_int *n,
const p256_int *in_x,
const p256_int *in_y,
p256_int *out_x,
p256_int *out_y);
// {out_x,out_y} := n1G + n2{in_x,in_y}
void p256_points_mul_vartime(
const p256_int *n1, const p256_int *n2,
const p256_int *in_x, const p256_int *in_y,
p256_int *out_x, p256_int *out_y);
// Return whether point {x,y} is on curve.
int p256_is_valid_point(const p256_int* x, const p256_int* y);
// Outputs big-endian binary form. No leading zero skips.
void p256_to_bin(const p256_int* src, uint8_t dst[P256_NBYTES]);
// Reads from big-endian binary form,
// thus pre-pad with leading zeros if short.
void p256_from_bin(const uint8_t src[P256_NBYTES], p256_int* dst);
#define P256_DIGITS(x) ((x)->a)
#define P256_DIGIT(x,y) ((x)->a[y])
#define P256_ZERO {{0}}
#define P256_ONE {{1}}
#ifdef __cplusplus
}
#endif
#endif // SYSTEM_CORE_INCLUDE_MINCRYPT_LITE_P256_H_

View File

@@ -0,0 +1,53 @@
/*
* Copyright 2013 The Android Open Source Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Google Inc. nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_P256_ECDSA_H_
#define SYSTEM_CORE_INCLUDE_MINCRYPT_P256_ECDSA_H_
// Using current directory as relative include path here since
// this code typically gets lifted into a variety of build systems
// and directory structures.
#include "p256.h"
#ifdef __cplusplus
extern "C" {
#endif
// Returns 0 if {r,s} is not a signature on message for
// public key {key_x,key_y}.
//
// Note: message is a p256_int.
// Convert from a binary string using p256_from_bin().
int p256_ecdsa_verify(const p256_int* key_x,
const p256_int* key_y,
const p256_int* message,
const p256_int* r, const p256_int* s);
#ifdef __cplusplus
}
#endif
#endif // SYSTEM_CORE_INCLUDE_MINCRYPT_P256_ECDSA_H_

View File

@@ -0,0 +1,58 @@
/* rsa.h
**
** Copyright 2008, The Android Open Source Project
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of Google Inc. nor the names of its contributors may
** be used to endorse or promote products derived from this software
** without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_RSA_H_
#define SYSTEM_CORE_INCLUDE_MINCRYPT_RSA_H_
#include <inttypes.h>
#ifdef __cplusplus
extern "C" {
#endif
#define RSANUMBYTES 256 /* 2048 bit key length */
#define RSANUMWORDS (RSANUMBYTES / sizeof(uint32_t))
typedef struct RSAPublicKey {
int len; /* Length of n[] in number of uint32_t */
uint32_t n0inv; /* -1 / n[0] mod 2^32 */
uint32_t n[RSANUMWORDS]; /* modulus as little endian array */
uint32_t rr[RSANUMWORDS]; /* R^2 as little endian array */
int exponent; /* 3 or 65537 */
} RSAPublicKey;
int RSA_verify(const RSAPublicKey *key,
const uint8_t* signature,
const int len,
const uint8_t* hash,
const int hash_len);
#ifdef __cplusplus
}
#endif
#endif // SYSTEM_CORE_INCLUDE_MINCRYPT_RSA_H_

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2005 The Android Open Source Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Google Inc. nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_SHA1_H_
#define SYSTEM_CORE_INCLUDE_MINCRYPT_SHA1_H_
#include <stdint.h>
#include "hash-internal.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
typedef HASH_CTX SHA_CTX;
void SHA_init(SHA_CTX* ctx);
void SHA_update(SHA_CTX* ctx, const void* data, int len);
const uint8_t* SHA_final(SHA_CTX* ctx);
// Convenience method. Returns digest address.
// NOTE: *digest needs to hold SHA_DIGEST_SIZE bytes.
const uint8_t* SHA_hash(const void* data, int len, uint8_t* digest);
#define SHA_DIGEST_SIZE 20
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // SYSTEM_CORE_INCLUDE_MINCRYPT_SHA1_H_

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2011 The Android Open Source Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Google Inc. nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_SHA256_H_
#define SYSTEM_CORE_INCLUDE_MINCRYPT_SHA256_H_
#include <stdint.h>
#include "hash-internal.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
typedef HASH_CTX SHA256_CTX;
void SHA256_init(SHA256_CTX* ctx);
void SHA256_update(SHA256_CTX* ctx, const void* data, int len);
const uint8_t* SHA256_final(SHA256_CTX* ctx);
// Convenience method. Returns digest address.
const uint8_t* SHA256_hash(const void* data, int len, uint8_t* digest);
#define SHA256_DIGEST_SIZE 32
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // SYSTEM_CORE_INCLUDE_MINCRYPT_SHA256_H_

44
native/jni/external/include/sha1.h vendored Normal file
View File

@@ -0,0 +1,44 @@
#ifndef SHA1_H
#define SHA1_H
/*
SHA-1 in C
By Steve Reid <steve@edmweb.com>
100% Public Domain
*/
#include "stdint.h"
typedef struct
{
uint32_t state[5];
uint32_t count[2];
unsigned char buffer[64];
} SHA1_CTX;
void SHA1Transform(
uint32_t state[5],
const unsigned char buffer[64]
);
void SHA1Init(
SHA1_CTX * context
);
void SHA1Update(
SHA1_CTX * context,
const unsigned char *data,
uint32_t len
);
void SHA1Final(
unsigned char digest[20],
SHA1_CTX * context
);
void SHA1(
char *hash_out,
const char *str,
int len);
#endif /* SHA1_H */

10491
native/jni/external/include/sqlite3.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,498 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define if building universal (internal helper macro) */
/* #undef AC_APPLE_UNIVERSAL_BUILD */
/* How many MiB of RAM to assume if the real amount cannot be determined. */
#define ASSUME_RAM 128
/* Define to 1 if translation of program messages to the user's native
language is requested. */
/* #undef ENABLE_NLS */
/* Define to 1 if bswap_16 is available. */
#define HAVE_BSWAP_16 1
/* Define to 1 if bswap_32 is available. */
#define HAVE_BSWAP_32 1
/* Define to 1 if bswap_64 is available. */
#define HAVE_BSWAP_64 1
/* Define to 1 if you have the <byteswap.h> header file. */
#define HAVE_BYTESWAP_H 1
/* Define to 1 if Capsicum is available. */
/* #undef HAVE_CAPSICUM */
/* Define to 1 if the system has the type `CC_SHA256_CTX'. */
/* #undef HAVE_CC_SHA256_CTX */
/* Define to 1 if you have the `CC_SHA256_Init' function. */
/* #undef HAVE_CC_SHA256_INIT */
/* Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the
CoreFoundation framework. */
/* #undef HAVE_CFLOCALECOPYCURRENT */
/* Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in
the CoreFoundation framework. */
/* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */
/* Define to 1 if crc32 integrity check is enabled. */
#define HAVE_CHECK_CRC32 1
/* Define to 1 if crc64 integrity check is enabled. */
#define HAVE_CHECK_CRC64 1
/* Define to 1 if sha256 integrity check is enabled. */
#define HAVE_CHECK_SHA256 1
/* Define to 1 if you have the `clock_gettime' function. */
#define HAVE_CLOCK_GETTIME 1
/* Define to 1 if you have the <CommonCrypto/CommonDigest.h> header file. */
/* #undef HAVE_COMMONCRYPTO_COMMONDIGEST_H */
/* Define if the GNU dcgettext() function is already present or preinstalled.
*/
/* #undef HAVE_DCGETTEXT */
/* Define to 1 if you have the declaration of `CLOCK_MONOTONIC', and to 0 if
you don't. */
#define HAVE_DECL_CLOCK_MONOTONIC 1
/* Define to 1 if you have the declaration of `program_invocation_name', and
to 0 if you don't. */
#define HAVE_DECL_PROGRAM_INVOCATION_NAME 0
/* Define to 1 if any of HAVE_DECODER_foo have been defined. */
#define HAVE_DECODERS 1
/* Define to 1 if arm decoder is enabled. */
#define HAVE_DECODER_ARM 1
/* Define to 1 if armthumb decoder is enabled. */
#define HAVE_DECODER_ARMTHUMB 1
/* Define to 1 if delta decoder is enabled. */
#define HAVE_DECODER_DELTA 1
/* Define to 1 if ia64 decoder is enabled. */
#define HAVE_DECODER_IA64 1
/* Define to 1 if lzma1 decoder is enabled. */
#define HAVE_DECODER_LZMA1 1
/* Define to 1 if lzma2 decoder is enabled. */
#define HAVE_DECODER_LZMA2 1
/* Define to 1 if powerpc decoder is enabled. */
#define HAVE_DECODER_POWERPC 1
/* Define to 1 if sparc decoder is enabled. */
#define HAVE_DECODER_SPARC 1
/* Define to 1 if x86 decoder is enabled. */
#define HAVE_DECODER_X86 1
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define to 1 if any of HAVE_ENCODER_foo have been defined. */
#define HAVE_ENCODERS 1
/* Define to 1 if arm encoder is enabled. */
#define HAVE_ENCODER_ARM 1
/* Define to 1 if armthumb encoder is enabled. */
#define HAVE_ENCODER_ARMTHUMB 1
/* Define to 1 if delta encoder is enabled. */
#define HAVE_ENCODER_DELTA 1
/* Define to 1 if ia64 encoder is enabled. */
#define HAVE_ENCODER_IA64 1
/* Define to 1 if lzma1 encoder is enabled. */
#define HAVE_ENCODER_LZMA1 1
/* Define to 1 if lzma2 encoder is enabled. */
#define HAVE_ENCODER_LZMA2 1
/* Define to 1 if powerpc encoder is enabled. */
#define HAVE_ENCODER_POWERPC 1
/* Define to 1 if sparc encoder is enabled. */
#define HAVE_ENCODER_SPARC 1
/* Define to 1 if x86 encoder is enabled. */
#define HAVE_ENCODER_X86 1
/* Define to 1 if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
/* Define to 1 if you have the `futimens' function. */
#define HAVE_FUTIMENS 1
/* Define to 1 if you have the `futimes' function. */
/* #undef HAVE_FUTIMES */
/* Define to 1 if you have the `futimesat' function. */
/* #undef HAVE_FUTIMESAT */
/* Define to 1 if you have the <getopt.h> header file. */
#define HAVE_GETOPT_H 1
/* Define to 1 if you have the `getopt_long' function. */
#define HAVE_GETOPT_LONG 1
/* Define if the GNU gettext() function is already present or preinstalled. */
/* #undef HAVE_GETTEXT */
/* Define if you have the iconv() function and it works. */
/* #undef HAVE_ICONV */
/* Define to 1 if you have the <immintrin.h> header file. */
/* #undef HAVE_IMMINTRIN_H */
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the <limits.h> header file. */
#define HAVE_LIMITS_H 1
/* Define to 1 if mbrtowc and mbstate_t are properly declared. */
#define HAVE_MBRTOWC 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 to enable bt2 match finder. */
#define HAVE_MF_BT2 1
/* Define to 1 to enable bt3 match finder. */
#define HAVE_MF_BT3 1
/* Define to 1 to enable bt4 match finder. */
#define HAVE_MF_BT4 1
/* Define to 1 to enable hc3 match finder. */
#define HAVE_MF_HC3 1
/* Define to 1 to enable hc4 match finder. */
#define HAVE_MF_HC4 1
/* Define to 1 if you have the <minix/sha2.h> header file. */
/* #undef HAVE_MINIX_SHA2_H */
/* Define to 1 if getopt.h declares extern int optreset. */
#define HAVE_OPTRESET 1
/* Define to 1 if you have the `posix_fadvise' function. */
#define HAVE_POSIX_FADVISE 1
/* Define to 1 if you have the `pthread_condattr_setclock' function. */
#define HAVE_PTHREAD_CONDATTR_SETCLOCK 1
/* Have PTHREAD_PRIO_INHERIT. */
/* #undef HAVE_PTHREAD_PRIO_INHERIT */
/* Define to 1 if you have the `SHA256Init' function. */
/* #undef HAVE_SHA256INIT */
/* Define to 1 if the system has the type `SHA256_CTX'. */
/* #undef HAVE_SHA256_CTX */
/* Define to 1 if you have the <sha256.h> header file. */
/* #undef HAVE_SHA256_H */
/* Define to 1 if you have the `SHA256_Init' function. */
/* #undef HAVE_SHA256_INIT */
/* Define to 1 if the system has the type `SHA2_CTX'. */
/* #undef HAVE_SHA2_CTX */
/* Define to 1 if you have the <sha2.h> header file. */
/* #undef HAVE_SHA2_H */
/* Define to 1 if optimizing for size. */
/* #undef HAVE_SMALL */
/* Define to 1 if stdbool.h conforms to C99. */
#define HAVE_STDBOOL_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if `st_atimensec' is a member of `struct stat'. */
#define HAVE_STRUCT_STAT_ST_ATIMENSEC 1
/* Define to 1 if `st_atimespec.tv_nsec' is a member of `struct stat'. */
/* #undef HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC */
/* Define to 1 if `st_atim.st__tim.tv_nsec' is a member of `struct stat'. */
/* #undef HAVE_STRUCT_STAT_ST_ATIM_ST__TIM_TV_NSEC */
/* Define to 1 if `st_atim.tv_nsec' is a member of `struct stat'. */
/* #undef HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC */
/* Define to 1 if `st_uatime' is a member of `struct stat'. */
/* #undef HAVE_STRUCT_STAT_ST_UATIME */
/* Define to 1 if you have the <sys/byteorder.h> header file. */
/* #undef HAVE_SYS_BYTEORDER_H */
/* Define to 1 if you have the <sys/capsicum.h> header file. */
/* #undef HAVE_SYS_CAPSICUM_H */
/* Define to 1 if you have the <sys/endian.h> header file. */
/* #undef HAVE_SYS_ENDIAN_H */
/* Define to 1 if you have the <sys/param.h> header file. */
#define HAVE_SYS_PARAM_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/time.h> header file. */
#define HAVE_SYS_TIME_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if the system has the type `uintptr_t'. */
#define HAVE_UINTPTR_T 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if you have the `utime' function. */
/* #undef HAVE_UTIME */
/* Define to 1 if you have the `utimes' function. */
/* #undef HAVE_UTIMES */
/* Define to 1 or 0, depending whether the compiler supports simple visibility
declarations. */
#define HAVE_VISIBILITY 1
/* Define to 1 if you have the `wcwidth' function. */
#define HAVE_WCWIDTH 1
/* Define to 1 if the system has the type `_Bool'. */
#define HAVE__BOOL 1
/* Define to 1 if _mm_movemask_epi8 is available. */
/* #undef HAVE__MM_MOVEMASK_EPI8 */
/* Define to the sub-directory where libtool stores uninstalled libraries. */
#define LT_OBJDIR ".libs/"
/* Define to 1 when using POSIX threads (pthreads). */
#define MYTHREAD_POSIX 1
/* Define to 1 when using Windows Vista compatible threads. This uses features
that are not available on Windows XP. */
/* #undef MYTHREAD_VISTA */
/* Define to 1 when using Windows 95 (and thus XP) compatible threads. This
avoids use of features that were added in Windows Vista. */
/* #undef MYTHREAD_WIN95 */
/* Define to 1 to disable debugging code. */
#define NDEBUG 1
/* Name of package */
#define PACKAGE "xz"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "lasse.collin@tukaani.org"
/* Define to the full name of this package. */
#define PACKAGE_NAME "XZ Utils"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "XZ Utils 5.3.0alpha"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "xz"
/* Define to the home page for this package. */
#define PACKAGE_URL "http://tukaani.org/xz/"
/* Define to the version of this package. */
#define PACKAGE_VERSION "5.3.0alpha"
/* Define to necessary symbol if this constant uses a non-standard name on
your system. */
/* #undef PTHREAD_CREATE_JOINABLE */
/* The size of `size_t', as computed by sizeof. */
#define SIZEOF_SIZE_T 4
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define to 1 if the number of available CPU cores can be detected with
cpuset(2). */
/* #undef TUKLIB_CPUCORES_CPUSET */
/* Define to 1 if the number of available CPU cores can be detected with
pstat_getdynamic(). */
/* #undef TUKLIB_CPUCORES_PSTAT_GETDYNAMIC */
/* Define to 1 if the number of available CPU cores can be detected with
sysconf(_SC_NPROCESSORS_ONLN) or sysconf(_SC_NPROC_ONLN). */
#define TUKLIB_CPUCORES_SYSCONF 1
/* Define to 1 if the number of available CPU cores can be detected with
sysctl(). */
/* #undef TUKLIB_CPUCORES_SYSCTL */
/* Define to 1 if the system supports fast unaligned access to 16-bit and
32-bit integers. */
/* #undef TUKLIB_FAST_UNALIGNED_ACCESS */
/* Define to 1 if the amount of physical memory can be detected with
_system_configuration.physmem. */
/* #undef TUKLIB_PHYSMEM_AIX */
/* Define to 1 if the amount of physical memory can be detected with
getinvent_r(). */
/* #undef TUKLIB_PHYSMEM_GETINVENT_R */
/* Define to 1 if the amount of physical memory can be detected with
getsysinfo(). */
/* #undef TUKLIB_PHYSMEM_GETSYSINFO */
/* Define to 1 if the amount of physical memory can be detected with
pstat_getstatic(). */
/* #undef TUKLIB_PHYSMEM_PSTAT_GETSTATIC */
/* Define to 1 if the amount of physical memory can be detected with
sysconf(_SC_PAGESIZE) and sysconf(_SC_PHYS_PAGES). */
#define TUKLIB_PHYSMEM_SYSCONF 1
/* Define to 1 if the amount of physical memory can be detected with sysctl().
*/
/* #undef TUKLIB_PHYSMEM_SYSCTL */
/* Define to 1 if the amount of physical memory can be detected with Linux
sysinfo(). */
/* #undef TUKLIB_PHYSMEM_SYSINFO */
/* Enable extensions on AIX 3, Interix. */
#ifndef _ALL_SOURCE
# define _ALL_SOURCE 1
#endif
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
# define _GNU_SOURCE 1
#endif
/* Enable threading extensions on Solaris. */
#ifndef _POSIX_PTHREAD_SEMANTICS
# define _POSIX_PTHREAD_SEMANTICS 1
#endif
/* Enable extensions on HP NonStop. */
#ifndef _TANDEM_SOURCE
# define _TANDEM_SOURCE 1
#endif
/* Enable general extensions on Solaris. */
#ifndef __EXTENSIONS__
# define __EXTENSIONS__ 1
#endif
/* Version number of package */
#define VERSION "5.3.0alpha"
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
/* # undef WORDS_BIGENDIAN */
# endif
#endif
/* Enable large inode numbers on Mac OS X 10.5. */
#ifndef _DARWIN_USE_64_BIT_INODE
# define _DARWIN_USE_64_BIT_INODE 1
#endif
/* Number of bits in a file offset, on hosts where this is settable. */
/* #undef _FILE_OFFSET_BITS */
/* Define for large files, on AIX-style hosts. */
/* #undef _LARGE_FILES */
/* Define to 1 if on MINIX. */
/* #undef _MINIX */
/* Define to 2 if the system does not provide POSIX.1 features except with
this defined. */
/* #undef _POSIX_1_SOURCE */
/* Define to 1 if you need to in order for `stat' and other things to work. */
/* #undef _POSIX_SOURCE */
/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
#define below would cause a syntax error. */
/* #undef _UINT32_T */
/* Define for Solaris 2.5.1 so the uint64_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
#define below would cause a syntax error. */
/* #undef _UINT64_T */
/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
#define below would cause a syntax error. */
/* #undef _UINT8_T */
/* Define to rpl_ if the getopt replacement functions and variables should be
used. */
/* #undef __GETOPT_PREFIX */
/* Define to the type of a signed integer type of width exactly 32 bits if
such a type exists and the standard includes do not define it. */
/* #undef int32_t */
/* Define to the type of a signed integer type of width exactly 64 bits if
such a type exists and the standard includes do not define it. */
/* #undef int64_t */
/* Define to the type of an unsigned integer type of width exactly 16 bits if
such a type exists and the standard includes do not define it. */
/* #undef uint16_t */
/* Define to the type of an unsigned integer type of width exactly 32 bits if
such a type exists and the standard includes do not define it. */
/* #undef uint32_t */
/* Define to the type of an unsigned integer type of width exactly 64 bits if
such a type exists and the standard includes do not define it. */
/* #undef uint64_t */
/* Define to the type of an unsigned integer type of width exactly 8 bits if
such a type exists and the standard includes do not define it. */
/* #undef uint8_t */
/* Define to the type of an unsigned integer type wide enough to hold a
pointer, if such a type exists, and if the system does not define it. */
/* #undef uintptr_t */

1
native/jni/external/lz4 vendored Submodule

Submodule native/jni/external/lz4 added at dfed9fa1d7

126
native/jni/external/mincrypt/dsa_sig.c vendored Normal file
View File

@@ -0,0 +1,126 @@
/*
* Copyright 2013 The Android Open Source Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Google Inc. nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <string.h>
#include "mincrypt/dsa_sig.h"
#include "mincrypt/p256.h"
/**
* Trims off the leading zero bytes and copy it to a buffer aligning it to the end.
*/
static inline int trim_to_p256_bytes(unsigned char dst[P256_NBYTES], unsigned char *src,
int src_len) {
int dst_offset;
while (*src == '\0' && src_len > 0) {
src++;
src_len--;
}
if (src_len > P256_NBYTES || src_len < 1) {
return 0;
}
dst_offset = P256_NBYTES - src_len;
memset(dst, 0, dst_offset);
memcpy(dst + dst_offset, src, src_len);
return 1;
}
/**
* Unpacks the ASN.1 DSA signature sequence.
*/
int dsa_sig_unpack(unsigned char* sig, int sig_len, p256_int* r_int, p256_int* s_int) {
/*
* Structure is:
* 0x30 0xNN SEQUENCE + s_length
* 0x02 0xNN INTEGER + r_length
* 0xAA 0xBB .. r_length bytes of "r" (offset 4)
* 0x02 0xNN INTEGER + s_length
* 0xMM 0xNN .. s_length bytes of "s" (offset 6 + r_len)
*/
int seq_len;
unsigned char r_bytes[P256_NBYTES];
unsigned char s_bytes[P256_NBYTES];
int r_len;
int s_len;
memset(r_bytes, 0, sizeof(r_bytes));
memset(s_bytes, 0, sizeof(s_bytes));
/*
* Must have at least:
* 2 bytes sequence header and length
* 2 bytes R integer header and length
* 1 byte of R
* 2 bytes S integer header and length
* 1 byte of S
*
* 8 bytes total
*/
if (sig_len < 8 || sig[0] != 0x30 || sig[2] != 0x02) {
return 0;
}
seq_len = sig[1];
if ((seq_len <= 0) || (seq_len + 2 != sig_len)) {
return 0;
}
r_len = sig[3];
/*
* Must have at least:
* 2 bytes for R header and length
* 2 bytes S integer header and length
* 1 byte of S
*/
if ((r_len < 1) || (r_len > seq_len - 5) || (sig[4 + r_len] != 0x02)) {
return 0;
}
s_len = sig[5 + r_len];
/**
* Must have:
* 2 bytes for R header and length
* r_len bytes for R
* 2 bytes S integer header and length
*/
if ((s_len < 1) || (s_len != seq_len - 4 - r_len)) {
return 0;
}
/*
* ASN.1 encoded integers are zero-padded for positive integers. Make sure we have
* a correctly-sized buffer and that the resulting integer isn't too large.
*/
if (!trim_to_p256_bytes(r_bytes, &sig[4], r_len)
|| !trim_to_p256_bytes(s_bytes, &sig[6 + r_len], s_len)) {
return 0;
}
p256_from_bin(r_bytes, r_int);
p256_from_bin(s_bytes, s_int);
return 1;
}

373
native/jni/external/mincrypt/p256.c vendored Normal file
View File

@@ -0,0 +1,373 @@
/*
* Copyright 2013 The Android Open Source Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Google Inc. nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// This is an implementation of the P256 elliptic curve group. It's written to
// be portable 32-bit, although it's still constant-time.
//
// WARNING: Implementing these functions in a constant-time manner is far from
// obvious. Be careful when touching this code.
//
// See http://www.imperialviolet.org/2010/12/04/ecc.html ([1]) for background.
#include <assert.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "mincrypt/p256.h"
const p256_int SECP256r1_n = // curve order
{{0xfc632551, 0xf3b9cac2, 0xa7179e84, 0xbce6faad, -1, -1, 0, -1}};
const p256_int SECP256r1_p = // curve field size
{{-1, -1, -1, 0, 0, 0, 1, -1 }};
const p256_int SECP256r1_b = // curve b
{{0x27d2604b, 0x3bce3c3e, 0xcc53b0f6, 0x651d06b0,
0x769886bc, 0xb3ebbd55, 0xaa3a93e7, 0x5ac635d8}};
void p256_init(p256_int* a) {
memset(a, 0, sizeof(*a));
}
void p256_clear(p256_int* a) { p256_init(a); }
int p256_get_bit(const p256_int* scalar, int bit) {
return (P256_DIGIT(scalar, bit / P256_BITSPERDIGIT)
>> (bit & (P256_BITSPERDIGIT - 1))) & 1;
}
int p256_is_zero(const p256_int* a) {
int i, result = 0;
for (i = 0; i < P256_NDIGITS; ++i) result |= P256_DIGIT(a, i);
return !result;
}
// top, c[] += a[] * b
// Returns new top
static p256_digit mulAdd(const p256_int* a,
p256_digit b,
p256_digit top,
p256_digit* c) {
int i;
p256_ddigit carry = 0;
for (i = 0; i < P256_NDIGITS; ++i) {
carry += *c;
carry += (p256_ddigit)P256_DIGIT(a, i) * b;
*c++ = (p256_digit)carry;
carry >>= P256_BITSPERDIGIT;
}
return top + (p256_digit)carry;
}
// top, c[] -= top_a, a[]
static p256_digit subTop(p256_digit top_a,
const p256_digit* a,
p256_digit top_c,
p256_digit* c) {
int i;
p256_sddigit borrow = 0;
for (i = 0; i < P256_NDIGITS; ++i) {
borrow += *c;
borrow -= *a++;
*c++ = (p256_digit)borrow;
borrow >>= P256_BITSPERDIGIT;
}
borrow += top_c;
borrow -= top_a;
top_c = (p256_digit)borrow;
assert((borrow >> P256_BITSPERDIGIT) == 0);
return top_c;
}
// top, c[] -= MOD[] & mask (0 or -1)
// returns new top.
static p256_digit subM(const p256_int* MOD,
p256_digit top,
p256_digit* c,
p256_digit mask) {
int i;
p256_sddigit borrow = 0;
for (i = 0; i < P256_NDIGITS; ++i) {
borrow += *c;
borrow -= P256_DIGIT(MOD, i) & mask;
*c++ = (p256_digit)borrow;
borrow >>= P256_BITSPERDIGIT;
}
return top + (p256_digit)borrow;
}
// top, c[] += MOD[] & mask (0 or -1)
// returns new top.
static p256_digit addM(const p256_int* MOD,
p256_digit top,
p256_digit* c,
p256_digit mask) {
int i;
p256_ddigit carry = 0;
for (i = 0; i < P256_NDIGITS; ++i) {
carry += *c;
carry += P256_DIGIT(MOD, i) & mask;
*c++ = (p256_digit)carry;
carry >>= P256_BITSPERDIGIT;
}
return top + (p256_digit)carry;
}
// c = a * b mod MOD. c can be a and/or b.
void p256_modmul(const p256_int* MOD,
const p256_int* a,
const p256_digit top_b,
const p256_int* b,
p256_int* c) {
p256_digit tmp[P256_NDIGITS * 2 + 1] = { 0 };
p256_digit top = 0;
int i;
// Multiply/add into tmp.
for (i = 0; i < P256_NDIGITS; ++i) {
if (i) tmp[i + P256_NDIGITS - 1] = top;
top = mulAdd(a, P256_DIGIT(b, i), 0, tmp + i);
}
// Multiply/add top digit
tmp[i + P256_NDIGITS - 1] = top;
top = mulAdd(a, top_b, 0, tmp + i);
// Reduce tmp, digit by digit.
for (; i >= 0; --i) {
p256_digit reducer[P256_NDIGITS] = { 0 };
p256_digit top_reducer;
// top can be any value at this point.
// Guestimate reducer as top * MOD, since msw of MOD is -1.
top_reducer = mulAdd(MOD, top, 0, reducer);
// Subtract reducer from top | tmp.
top = subTop(top_reducer, reducer, top, tmp + i);
// top is now either 0 or 1. Make it 0, fixed-timing.
assert(top <= 1);
top = subM(MOD, top, tmp + i, ~(top - 1));
assert(top == 0);
// We have now reduced the top digit off tmp. Fetch new top digit.
top = tmp[i + P256_NDIGITS - 1];
}
// tmp might still be larger than MOD, yet same bit length.
// Make sure it is less, fixed-timing.
addM(MOD, 0, tmp, subM(MOD, 0, tmp, -1));
memcpy(c, tmp, P256_NBYTES);
}
int p256_is_odd(const p256_int* a) { return P256_DIGIT(a, 0) & 1; }
int p256_is_even(const p256_int* a) { return !(P256_DIGIT(a, 0) & 1); }
p256_digit p256_shl(const p256_int* a, int n, p256_int* b) {
int i;
p256_digit top = P256_DIGIT(a, P256_NDIGITS - 1);
n %= P256_BITSPERDIGIT;
for (i = P256_NDIGITS - 1; i > 0; --i) {
p256_digit accu = (P256_DIGIT(a, i) << n);
accu |= (P256_DIGIT(a, i - 1) >> (P256_BITSPERDIGIT - n));
P256_DIGIT(b, i) = accu;
}
P256_DIGIT(b, i) = (P256_DIGIT(a, i) << n);
top = (p256_digit)((((p256_ddigit)top) << n) >> P256_BITSPERDIGIT);
return top;
}
void p256_shr(const p256_int* a, int n, p256_int* b) {
int i;
n %= P256_BITSPERDIGIT;
for (i = 0; i < P256_NDIGITS - 1; ++i) {
p256_digit accu = (P256_DIGIT(a, i) >> n);
accu |= (P256_DIGIT(a, i + 1) << (P256_BITSPERDIGIT - n));
P256_DIGIT(b, i) = accu;
}
P256_DIGIT(b, i) = (P256_DIGIT(a, i) >> n);
}
static void p256_shr1(const p256_int* a, int highbit, p256_int* b) {
int i;
for (i = 0; i < P256_NDIGITS - 1; ++i) {
p256_digit accu = (P256_DIGIT(a, i) >> 1);
accu |= (P256_DIGIT(a, i + 1) << (P256_BITSPERDIGIT - 1));
P256_DIGIT(b, i) = accu;
}
P256_DIGIT(b, i) = (P256_DIGIT(a, i) >> 1) |
(highbit << (P256_BITSPERDIGIT - 1));
}
// Return -1, 0, 1 for a < b, a == b or a > b respectively.
int p256_cmp(const p256_int* a, const p256_int* b) {
int i;
p256_sddigit borrow = 0;
p256_digit notzero = 0;
for (i = 0; i < P256_NDIGITS; ++i) {
borrow += (p256_sddigit)P256_DIGIT(a, i) - P256_DIGIT(b, i);
// Track whether any result digit is ever not zero.
// Relies on !!(non-zero) evaluating to 1, e.g., !!(-1) evaluating to 1.
notzero |= !!((p256_digit)borrow);
borrow >>= P256_BITSPERDIGIT;
}
return (int)borrow | notzero;
}
// c = a - b. Returns borrow: 0 or -1.
int p256_sub(const p256_int* a, const p256_int* b, p256_int* c) {
int i;
p256_sddigit borrow = 0;
for (i = 0; i < P256_NDIGITS; ++i) {
borrow += (p256_sddigit)P256_DIGIT(a, i) - P256_DIGIT(b, i);
if (c) P256_DIGIT(c, i) = (p256_digit)borrow;
borrow >>= P256_BITSPERDIGIT;
}
return (int)borrow;
}
// c = a + b. Returns carry: 0 or 1.
int p256_add(const p256_int* a, const p256_int* b, p256_int* c) {
int i;
p256_ddigit carry = 0;
for (i = 0; i < P256_NDIGITS; ++i) {
carry += (p256_ddigit)P256_DIGIT(a, i) + P256_DIGIT(b, i);
if (c) P256_DIGIT(c, i) = (p256_digit)carry;
carry >>= P256_BITSPERDIGIT;
}
return (int)carry;
}
// b = a + d. Returns carry, 0 or 1.
int p256_add_d(const p256_int* a, p256_digit d, p256_int* b) {
int i;
p256_ddigit carry = d;
for (i = 0; i < P256_NDIGITS; ++i) {
carry += (p256_ddigit)P256_DIGIT(a, i);
if (b) P256_DIGIT(b, i) = (p256_digit)carry;
carry >>= P256_BITSPERDIGIT;
}
return (int)carry;
}
// b = 1/a mod MOD, binary euclid.
void p256_modinv_vartime(const p256_int* MOD,
const p256_int* a,
p256_int* b) {
p256_int R = P256_ZERO;
p256_int S = P256_ONE;
p256_int U = *MOD;
p256_int V = *a;
for (;;) {
if (p256_is_even(&U)) {
p256_shr1(&U, 0, &U);
if (p256_is_even(&R)) {
p256_shr1(&R, 0, &R);
} else {
// R = (R+MOD)/2
p256_shr1(&R, p256_add(&R, MOD, &R), &R);
}
} else if (p256_is_even(&V)) {
p256_shr1(&V, 0, &V);
if (p256_is_even(&S)) {
p256_shr1(&S, 0, &S);
} else {
// S = (S+MOD)/2
p256_shr1(&S, p256_add(&S, MOD, &S) , &S);
}
} else { // U,V both odd.
if (!p256_sub(&V, &U, NULL)) {
p256_sub(&V, &U, &V);
if (p256_sub(&S, &R, &S)) p256_add(&S, MOD, &S);
if (p256_is_zero(&V)) break; // done.
} else {
p256_sub(&U, &V, &U);
if (p256_sub(&R, &S, &R)) p256_add(&R, MOD, &R);
}
}
}
p256_mod(MOD, &R, b);
}
void p256_mod(const p256_int* MOD,
const p256_int* in,
p256_int* out) {
if (out != in) *out = *in;
addM(MOD, 0, P256_DIGITS(out), subM(MOD, 0, P256_DIGITS(out), -1));
}
// Verify y^2 == x^3 - 3x + b mod p
// and 0 < x < p and 0 < y < p
int p256_is_valid_point(const p256_int* x, const p256_int* y) {
p256_int y2, x3;
if (p256_cmp(&SECP256r1_p, x) <= 0 ||
p256_cmp(&SECP256r1_p, y) <= 0 ||
p256_is_zero(x) ||
p256_is_zero(y)) return 0;
p256_modmul(&SECP256r1_p, y, 0, y, &y2); // y^2
p256_modmul(&SECP256r1_p, x, 0, x, &x3); // x^2
p256_modmul(&SECP256r1_p, x, 0, &x3, &x3); // x^3
if (p256_sub(&x3, x, &x3)) p256_add(&x3, &SECP256r1_p, &x3); // x^3 - x
if (p256_sub(&x3, x, &x3)) p256_add(&x3, &SECP256r1_p, &x3); // x^3 - 2x
if (p256_sub(&x3, x, &x3)) p256_add(&x3, &SECP256r1_p, &x3); // x^3 - 3x
if (p256_add(&x3, &SECP256r1_b, &x3)) // x^3 - 3x + b
p256_sub(&x3, &SECP256r1_p, &x3);
return p256_cmp(&y2, &x3) == 0;
}
void p256_from_bin(const uint8_t src[P256_NBYTES], p256_int* dst) {
int i;
const uint8_t* p = &src[0];
for (i = P256_NDIGITS - 1; i >= 0; --i) {
P256_DIGIT(dst, i) =
(p[0] << 24) |
(p[1] << 16) |
(p[2] << 8) |
p[3];
p += 4;
}
}

1279
native/jni/external/mincrypt/p256_ec.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2013 The Android Open Source Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Google Inc. nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <string.h>
#include "mincrypt/p256_ecdsa.h"
#include "mincrypt/p256.h"
int p256_ecdsa_verify(const p256_int* key_x, const p256_int* key_y,
const p256_int* message,
const p256_int* r, const p256_int* s) {
p256_int u, v;
// Check public key.
if (!p256_is_valid_point(key_x, key_y)) return 0;
// Check r and s are != 0 % n.
p256_mod(&SECP256r1_n, r, &u);
p256_mod(&SECP256r1_n, s, &v);
if (p256_is_zero(&u) || p256_is_zero(&v)) return 0;
p256_modinv_vartime(&SECP256r1_n, s, &v);
p256_modmul(&SECP256r1_n, message, 0, &v, &u); // message / s % n
p256_modmul(&SECP256r1_n, r, 0, &v, &v); // r / s % n
p256_points_mul_vartime(&u, &v,
key_x, key_y,
&u, &v);
p256_mod(&SECP256r1_n, &u, &u); // (x coord % p) % n
return p256_cmp(r, &u) == 0;
}

308
native/jni/external/mincrypt/rsa.c vendored Normal file
View File

@@ -0,0 +1,308 @@
/* rsa.c
**
** Copyright 2012, The Android Open Source Project
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of Google Inc. nor the names of its contributors may
** be used to endorse or promote products derived from this software
** without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "mincrypt/rsa.h"
#include "mincrypt/sha.h"
#include "mincrypt/sha256.h"
// a[] -= mod
static void subM(const RSAPublicKey* key,
uint32_t* a) {
int64_t A = 0;
int i;
for (i = 0; i < key->len; ++i) {
A += (uint64_t)a[i] - key->n[i];
a[i] = (uint32_t)A;
A >>= 32;
}
}
// return a[] >= mod
static int geM(const RSAPublicKey* key,
const uint32_t* a) {
int i;
for (i = key->len; i;) {
--i;
if (a[i] < key->n[i]) return 0;
if (a[i] > key->n[i]) return 1;
}
return 1; // equal
}
// montgomery c[] += a * b[] / R % mod
static void montMulAdd(const RSAPublicKey* key,
uint32_t* c,
const uint32_t a,
const uint32_t* b) {
uint64_t A = (uint64_t)a * b[0] + c[0];
uint32_t d0 = (uint32_t)A * key->n0inv;
uint64_t B = (uint64_t)d0 * key->n[0] + (uint32_t)A;
int i;
for (i = 1; i < key->len; ++i) {
A = (A >> 32) + (uint64_t)a * b[i] + c[i];
B = (B >> 32) + (uint64_t)d0 * key->n[i] + (uint32_t)A;
c[i - 1] = (uint32_t)B;
}
A = (A >> 32) + (B >> 32);
c[i - 1] = (uint32_t)A;
if (A >> 32) {
subM(key, c);
}
}
// montgomery c[] = a[] * b[] / R % mod
static void montMul(const RSAPublicKey* key,
uint32_t* c,
const uint32_t* a,
const uint32_t* b) {
int i;
for (i = 0; i < key->len; ++i) {
c[i] = 0;
}
for (i = 0; i < key->len; ++i) {
montMulAdd(key, c, a[i], b);
}
}
// In-place public exponentiation.
// Input and output big-endian byte array in inout.
static void modpow(const RSAPublicKey* key,
uint8_t* inout) {
uint32_t a[RSANUMWORDS];
uint32_t aR[RSANUMWORDS];
uint32_t aaR[RSANUMWORDS];
uint32_t* aaa = 0;
int i;
// Convert from big endian byte array to little endian word array.
for (i = 0; i < key->len; ++i) {
uint32_t tmp =
(inout[((key->len - 1 - i) * 4) + 0] << 24) |
(inout[((key->len - 1 - i) * 4) + 1] << 16) |
(inout[((key->len - 1 - i) * 4) + 2] << 8) |
(inout[((key->len - 1 - i) * 4) + 3] << 0);
a[i] = tmp;
}
if (key->exponent == 65537) {
aaa = aaR; // Re-use location.
montMul(key, aR, a, key->rr); // aR = a * RR / R mod M
for (i = 0; i < 16; i += 2) {
montMul(key, aaR, aR, aR); // aaR = aR * aR / R mod M
montMul(key, aR, aaR, aaR); // aR = aaR * aaR / R mod M
}
montMul(key, aaa, aR, a); // aaa = aR * a / R mod M
} else if (key->exponent == 3) {
aaa = aR; // Re-use location.
montMul(key, aR, a, key->rr); /* aR = a * RR / R mod M */
montMul(key, aaR, aR, aR); /* aaR = aR * aR / R mod M */
montMul(key, aaa, aaR, a); /* aaa = aaR * a / R mod M */
}
// Make sure aaa < mod; aaa is at most 1x mod too large.
if (geM(key, aaa)) {
subM(key, aaa);
}
// Convert to bigendian byte array
for (i = key->len - 1; i >= 0; --i) {
uint32_t tmp = aaa[i];
*inout++ = tmp >> 24;
*inout++ = tmp >> 16;
*inout++ = tmp >> 8;
*inout++ = tmp >> 0;
}
}
// Expected PKCS1.5 signature padding bytes, for a keytool RSA signature.
// Has the 0-length optional parameter encoded in the ASN1 (as opposed to the
// other flavor which omits the optional parameter entirely). This code does not
// accept signatures without the optional parameter.
/*
static const uint8_t sha_padding[RSANUMBYTES] = {
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x21, 0x30,
0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a,
0x05, 0x00, 0x04, 0x14,
// 20 bytes of hash go here.
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
*/
// SHA-1 of PKCS1.5 signature sha_padding for 2048 bit, as above.
// At the location of the bytes of the hash all 00 are hashed.
static const uint8_t kExpectedPadShaRsa2048[SHA_DIGEST_SIZE] = {
0xdc, 0xbd, 0xbe, 0x42, 0xd5, 0xf5, 0xa7, 0x2e,
0x6e, 0xfc, 0xf5, 0x5d, 0xaf, 0x9d, 0xea, 0x68,
0x7c, 0xfb, 0xf1, 0x67
};
/*
static const uint8_t sha256_padding[RSANUMBYTES] = {
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x31, 0x30,
0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20,
// 32 bytes of hash go here.
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};
*/
// SHA-256 of PKCS1.5 signature sha256_padding for 2048 bit, as above.
// At the location of the bytes of the hash all 00 are hashed.
static const uint8_t kExpectedPadSha256Rsa2048[SHA256_DIGEST_SIZE] = {
0xab, 0x28, 0x8d, 0x8a, 0xd7, 0xd9, 0x59, 0x92,
0xba, 0xcc, 0xf8, 0x67, 0x20, 0xe1, 0x15, 0x2e,
0x39, 0x8d, 0x80, 0x36, 0xd6, 0x6f, 0xf0, 0xfd,
0x90, 0xe8, 0x7d, 0x8b, 0xe1, 0x7c, 0x87, 0x59,
};
// Verify a 2048-bit RSA PKCS1.5 signature against an expected hash.
// Both e=3 and e=65537 are supported. hash_len may be
// SHA_DIGEST_SIZE (== 20) to indicate a SHA-1 hash, or
// SHA256_DIGEST_SIZE (== 32) to indicate a SHA-256 hash. No other
// values are supported.
//
// Returns 1 on successful verification, 0 on failure.
int RSA_verify(const RSAPublicKey *key,
const uint8_t *signature,
const int len,
const uint8_t *hash,
const int hash_len) {
uint8_t buf[RSANUMBYTES];
int i;
const uint8_t* padding_hash;
if (key->len != RSANUMWORDS) {
return 0; // Wrong key passed in.
}
if (len != sizeof(buf)) {
return 0; // Wrong input length.
}
if (hash_len != SHA_DIGEST_SIZE &&
hash_len != SHA256_DIGEST_SIZE) {
return 0; // Unsupported hash.
}
if (key->exponent != 3 && key->exponent != 65537) {
return 0; // Unsupported exponent.
}
for (i = 0; i < len; ++i) { // Copy input to local workspace.
buf[i] = signature[i];
}
modpow(key, buf); // In-place exponentiation.
// Xor sha portion, so it all becomes 00 iff equal.
for (i = len - hash_len; i < len; ++i) {
buf[i] ^= *hash++;
}
// Hash resulting buf, in-place.
switch (hash_len) {
case SHA_DIGEST_SIZE:
padding_hash = kExpectedPadShaRsa2048;
SHA_hash(buf, len, buf);
break;
case SHA256_DIGEST_SIZE:
padding_hash = kExpectedPadSha256Rsa2048;
SHA256_hash(buf, len, buf);
break;
default:
return 0;
}
// Compare against expected hash value.
for (i = 0; i < hash_len; ++i) {
if (buf[i] != padding_hash[i]) {
return 0;
}
}
return 1; // All checked out OK.
}

155
native/jni/external/mincrypt/sha.c vendored Normal file
View File

@@ -0,0 +1,155 @@
/* sha.c
**
** Copyright 2013, The Android Open Source Project
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of Google Inc. nor the names of its contributors may
** be used to endorse or promote products derived from this software
** without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Optimized for minimal code size.
#include "mincrypt/sha.h"
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#define rol(bits, value) (((value) << (bits)) | ((value) >> (32 - (bits))))
static void SHA1_Transform(SHA_CTX* ctx) {
uint32_t W[80];
uint32_t A, B, C, D, E;
uint8_t* p = ctx->buf;
int t;
for(t = 0; t < 16; ++t) {
uint32_t tmp = *p++ << 24;
tmp |= *p++ << 16;
tmp |= *p++ << 8;
tmp |= *p++;
W[t] = tmp;
}
for(; t < 80; t++) {
W[t] = rol(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
for(t = 0; t < 80; t++) {
uint32_t tmp = rol(5,A) + E + W[t];
if (t < 20)
tmp += (D^(B&(C^D))) + 0x5A827999;
else if ( t < 40)
tmp += (B^C^D) + 0x6ED9EBA1;
else if ( t < 60)
tmp += ((B&C)|(D&(B|C))) + 0x8F1BBCDC;
else
tmp += (B^C^D) + 0xCA62C1D6;
E = D;
D = C;
C = rol(30,B);
B = A;
A = tmp;
}
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
}
static const HASH_VTAB SHA_VTAB = {
SHA_init,
SHA_update,
SHA_final,
SHA_hash,
SHA_DIGEST_SIZE
};
void SHA_init(SHA_CTX* ctx) {
ctx->f = &SHA_VTAB;
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
ctx->state[4] = 0xC3D2E1F0;
ctx->count = 0;
}
void SHA_update(SHA_CTX* ctx, const void* data, int len) {
int i = (int) (ctx->count & 63);
const uint8_t* p = (const uint8_t*)data;
ctx->count += len;
while (len--) {
ctx->buf[i++] = *p++;
if (i == 64) {
SHA1_Transform(ctx);
i = 0;
}
}
}
const uint8_t* SHA_final(SHA_CTX* ctx) {
uint8_t *p = ctx->buf;
uint64_t cnt = ctx->count * 8;
int i;
SHA_update(ctx, (uint8_t*)"\x80", 1);
while ((ctx->count & 63) != 56) {
SHA_update(ctx, (uint8_t*)"\0", 1);
}
for (i = 0; i < 8; ++i) {
uint8_t tmp = (uint8_t) (cnt >> ((7 - i) * 8));
SHA_update(ctx, &tmp, 1);
}
for (i = 0; i < 5; i++) {
uint32_t tmp = ctx->state[i];
*p++ = tmp >> 24;
*p++ = tmp >> 16;
*p++ = tmp >> 8;
*p++ = tmp >> 0;
}
return ctx->buf;
}
/* Convenience function */
const uint8_t* SHA_hash(const void* data, int len, uint8_t* digest) {
SHA_CTX ctx;
SHA_init(&ctx);
SHA_update(&ctx, data, len);
memcpy(digest, SHA_final(&ctx), SHA_DIGEST_SIZE);
return digest;
}

184
native/jni/external/mincrypt/sha256.c vendored Normal file
View File

@@ -0,0 +1,184 @@
/* sha256.c
**
** Copyright 2013, The Android Open Source Project
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of Google Inc. nor the names of its contributors may
** be used to endorse or promote products derived from this software
** without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Optimized for minimal code size.
#include "mincrypt/sha256.h"
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#define ror(value, bits) (((value) >> (bits)) | ((value) << (32 - (bits))))
#define shr(value, bits) ((value) >> (bits))
static const uint32_t K[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 };
static void SHA256_Transform(SHA256_CTX* ctx) {
uint32_t W[64];
uint32_t A, B, C, D, E, F, G, H;
uint8_t* p = ctx->buf;
int t;
for(t = 0; t < 16; ++t) {
uint32_t tmp = *p++ << 24;
tmp |= *p++ << 16;
tmp |= *p++ << 8;
tmp |= *p++;
W[t] = tmp;
}
for(; t < 64; t++) {
uint32_t s0 = ror(W[t-15], 7) ^ ror(W[t-15], 18) ^ shr(W[t-15], 3);
uint32_t s1 = ror(W[t-2], 17) ^ ror(W[t-2], 19) ^ shr(W[t-2], 10);
W[t] = W[t-16] + s0 + W[t-7] + s1;
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
F = ctx->state[5];
G = ctx->state[6];
H = ctx->state[7];
for(t = 0; t < 64; t++) {
uint32_t s0 = ror(A, 2) ^ ror(A, 13) ^ ror(A, 22);
uint32_t maj = (A & B) ^ (A & C) ^ (B & C);
uint32_t t2 = s0 + maj;
uint32_t s1 = ror(E, 6) ^ ror(E, 11) ^ ror(E, 25);
uint32_t ch = (E & F) ^ ((~E) & G);
uint32_t t1 = H + s1 + ch + K[t] + W[t];
H = G;
G = F;
F = E;
E = D + t1;
D = C;
C = B;
B = A;
A = t1 + t2;
}
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
ctx->state[5] += F;
ctx->state[6] += G;
ctx->state[7] += H;
}
static const HASH_VTAB SHA256_VTAB = {
SHA256_init,
SHA256_update,
SHA256_final,
SHA256_hash,
SHA256_DIGEST_SIZE
};
void SHA256_init(SHA256_CTX* ctx) {
ctx->f = &SHA256_VTAB;
ctx->state[0] = 0x6a09e667;
ctx->state[1] = 0xbb67ae85;
ctx->state[2] = 0x3c6ef372;
ctx->state[3] = 0xa54ff53a;
ctx->state[4] = 0x510e527f;
ctx->state[5] = 0x9b05688c;
ctx->state[6] = 0x1f83d9ab;
ctx->state[7] = 0x5be0cd19;
ctx->count = 0;
}
void SHA256_update(SHA256_CTX* ctx, const void* data, int len) {
int i = (int) (ctx->count & 63);
const uint8_t* p = (const uint8_t*)data;
ctx->count += len;
while (len--) {
ctx->buf[i++] = *p++;
if (i == 64) {
SHA256_Transform(ctx);
i = 0;
}
}
}
const uint8_t* SHA256_final(SHA256_CTX* ctx) {
uint8_t *p = ctx->buf;
uint64_t cnt = ctx->count * 8;
int i;
SHA256_update(ctx, (uint8_t*)"\x80", 1);
while ((ctx->count & 63) != 56) {
SHA256_update(ctx, (uint8_t*)"\0", 1);
}
for (i = 0; i < 8; ++i) {
uint8_t tmp = (uint8_t) (cnt >> ((7 - i) * 8));
SHA256_update(ctx, &tmp, 1);
}
for (i = 0; i < 8; i++) {
uint32_t tmp = ctx->state[i];
*p++ = tmp >> 24;
*p++ = tmp >> 16;
*p++ = tmp >> 8;
*p++ = tmp >> 0;
}
return ctx->buf;
}
/* Convenience function */
const uint8_t* SHA256_hash(const void* data, int len, uint8_t* digest) {
SHA256_CTX ctx;
SHA256_init(&ctx);
SHA256_update(&ctx, data, len);
memcpy(digest, SHA256_final(&ctx), SHA256_DIGEST_SIZE);
return digest;
}

1
native/jni/external/selinux vendored Submodule

356
native/jni/external/stubs/selinux_stub.c vendored Normal file
View File

@@ -0,0 +1,356 @@
#include <stdbool.h>
#include <selinux/avc.h>
#include <selinux/context.h>
#include <selinux/get_context_list.h>
#include <selinux/get_default_type.h>
#include <selinux/label.h>
#include <selinux/restorecon.h>
#include <selinux/selinux.h>
int is_selinux_enabled(void) { return 0; }
int is_selinux_mls_enabled(void) { return 0; }
void freecon(char * con) { }
void freeconary(char ** con) { }
int getcon(char ** con) { return 0; }
int getcon_raw(char ** con) { return 0; }
int setcon(const char * con) { return 0; }
int setcon_raw(const char * con) { return 0; }
int getpidcon(pid_t pid, char ** con) { return 0; }
int getpidcon_raw(pid_t pid, char ** con) { return 0; }
int getprevcon(char ** con) { return 0; }
int getprevcon_raw(char ** con) { return 0; }
int getexeccon(char ** con) { return 0; }
int getexeccon_raw(char ** con) { return 0; }
int setexeccon(const char * con) { return 0; }
int setexeccon_raw(const char * con) { return 0; }
int getfscreatecon(char ** con) { return 0; }
int getfscreatecon_raw(char ** con) { return 0; }
int setfscreatecon(const char * context) { return 0; }
int setfscreatecon_raw(const char * context) { return 0; }
int getkeycreatecon(char ** con) { return 0; }
int getkeycreatecon_raw(char ** con) { return 0; }
int setkeycreatecon(const char * context) { return 0; }
int setkeycreatecon_raw(const char * context) { return 0; }
int getsockcreatecon(char ** con) { return 0; }
int getsockcreatecon_raw(char ** con) { return 0; }
int setsockcreatecon(const char * context) { return 0; }
int setsockcreatecon_raw(const char * context) { return 0; }
int getfilecon(const char *path, char ** con) { return 0; }
int getfilecon_raw(const char *path, char ** con) { return 0; }
int lgetfilecon(const char *path, char ** con) { return 0; }
int lgetfilecon_raw(const char *path, char ** con) { return 0; }
int fgetfilecon(int fd, char ** con) { return 0; }
int fgetfilecon_raw(int fd, char ** con) { return 0; }
int setfilecon(const char *path, const char * con) { return 0; }
int setfilecon_raw(const char *path, const char * con) { return 0; }
int lsetfilecon(const char *path, const char * con) { return 0; }
int lsetfilecon_raw(const char *path, const char * con) { return 0; }
int fsetfilecon(int fd, const char * con) { return 0; }
int fsetfilecon_raw(int fd, const char * con) { return 0; }
int getpeercon(int fd, char ** con) { return 0; }
int getpeercon_raw(int fd, char ** con) { return 0; }
void selinux_set_callback(int type, union selinux_callback cb) { }
int security_compute_av(const char * scon,
const char * tcon,
security_class_t tclass,
access_vector_t requested,
struct av_decision *avd) { return 0; }
int security_compute_av_raw(const char * scon,
const char * tcon,
security_class_t tclass,
access_vector_t requested,
struct av_decision *avd) { return 0; }
int security_compute_av_flags(const char * scon,
const char * tcon,
security_class_t tclass,
access_vector_t requested,
struct av_decision *avd) { return 0; }
int security_compute_av_flags_raw(const char * scon,
const char * tcon,
security_class_t tclass,
access_vector_t requested,
struct av_decision *avd) { return 0; }
int security_compute_create(const char * scon,
const char * tcon,
security_class_t tclass,
char ** newcon) { return 0; }
int security_compute_create_raw(const char * scon,
const char * tcon,
security_class_t tclass,
char ** newcon) { return 0; }
int security_compute_create_name(const char * scon,
const char * tcon,
security_class_t tclass,
const char *objname,
char ** newcon) { return 0; }
int security_compute_create_name_raw(const char * scon,
const char * tcon,
security_class_t tclass,
const char *objname,
char ** newcon) { return 0; }
int security_compute_relabel(const char * scon,
const char * tcon,
security_class_t tclass,
char ** newcon) { return 0; }
int security_compute_relabel_raw(const char * scon,
const char * tcon,
security_class_t tclass,
char ** newcon) { return 0; }
int security_compute_member(const char * scon,
const char * tcon,
security_class_t tclass,
char ** newcon) { return 0; }
int security_compute_member_raw(const char * scon,
const char * tcon,
security_class_t tclass,
char ** newcon) { return 0; }
int security_compute_user(const char * scon,
const char *username,
char *** con) { return 0; }
int security_compute_user_raw(const char * scon,
const char *username,
char *** con) { return 0; }
int security_load_policy(void *data, size_t len) { return 0; }
int security_get_initial_context(const char *name,
char ** con) { return 0; }
int security_get_initial_context_raw(const char *name,
char ** con) { return 0; }
int selinux_mkload_policy(int preservebools) { return 0; }
int selinux_init_load_policy(int *enforce) { return 0; }
int security_set_boolean_list(size_t boolcnt,
SELboolean * boollist, int permanent) { return 0; }
int security_load_booleans(char *path) { return 0; }
int security_check_context(const char * con) { return 0; }
int security_check_context_raw(const char * con) { return 0; }
int security_canonicalize_context(const char * con,
char ** canoncon) { return 0; }
int security_canonicalize_context_raw(const char * con,
char ** canoncon) { return 0; }
int security_getenforce(void) { return 0; }
int security_setenforce(int value) { return 0; }
int security_deny_unknown(void) { return 0; }
int security_disable(void) { return 0; }
int security_policyvers(void) { return 0; }
int security_get_boolean_names(char ***names, int *len) { return 0; }
int security_get_boolean_pending(const char *name) { return 0; }
int security_get_boolean_active(const char *name) { return 0; }
int security_set_boolean(const char *name, int value) { return 0; }
int security_commit_booleans(void) { return 0; }
int selinux_set_mapping(struct security_class_mapping *map) { return 0; }
security_class_t mode_to_security_class(mode_t mode) { return 0; }
security_class_t string_to_security_class(const char *name) { return 0; }
const char *security_class_to_string(security_class_t cls) { return 0; }
const char *security_av_perm_to_string(security_class_t tclass,
access_vector_t perm) { return 0; }
access_vector_t string_to_av_perm(security_class_t tclass,
const char *name) { return 0; }
int security_av_string(security_class_t tclass,
access_vector_t av, char **result) { return 0; }
void print_access_vector(security_class_t tclass, access_vector_t av) { }
void set_matchpathcon_printf(void (*f) (const char *fmt, ...)) { }
void set_matchpathcon_invalidcon(int (*f) (const char *path,
unsigned lineno,
char *context)) { }
void set_matchpathcon_canoncon(int (*f) (const char *path,
unsigned lineno,
char **context)) { }
void set_matchpathcon_flags(unsigned int flags) { }
int matchpathcon_init(const char *path) { return 0; }
int matchpathcon_init_prefix(const char *path, const char *prefix) { return 0; }
void matchpathcon_fini(void) { }
int realpath_not_final(const char *name, char *resolved_path) { return 0; }
int matchpathcon(const char *path,
mode_t mode, char ** con) { return 0; }
int matchpathcon_index(const char *path,
mode_t mode, char ** con) { return 0; }
int matchpathcon_filespec_add(ino_t ino, int specind, const char *file) { return 0; }
void matchpathcon_filespec_destroy(void) { }
void matchpathcon_filespec_eval(void) { }
void matchpathcon_checkmatches(char *str) { }
int matchmediacon(const char *media, char ** con) { return 0; }
int selinux_getenforcemode(int *enforce) { return 0; }
char *selinux_boolean_sub(const char *boolean_name) { return 0; }
int selinux_getpolicytype(char **policytype) { return 0; }
const char *selinux_policy_root(void) { return 0; }
int selinux_set_policy_root(const char *rootpath) { return 0; }
const char *selinux_current_policy_path(void) { return 0; }
const char *selinux_binary_policy_path(void) { return 0; }
const char *selinux_failsafe_context_path(void) { return 0; }
const char *selinux_removable_context_path(void) { return 0; }
const char *selinux_default_context_path(void) { return 0; }
const char *selinux_user_contexts_path(void) { return 0; }
const char *selinux_file_context_path(void) { return 0; }
const char *selinux_file_context_homedir_path(void) { return 0; }
const char *selinux_file_context_local_path(void) { return 0; }
const char *selinux_file_context_subs_path(void) { return 0; }
const char *selinux_file_context_subs_dist_path(void) { return 0; }
const char *selinux_homedir_context_path(void) { return 0; }
const char *selinux_media_context_path(void) { return 0; }
const char *selinux_virtual_domain_context_path(void) { return 0; }
const char *selinux_virtual_image_context_path(void) { return 0; }
const char *selinux_lxc_contexts_path(void) { return 0; }
const char *selinux_x_context_path(void) { return 0; }
const char *selinux_sepgsql_context_path(void) { return 0; }
const char *selinux_openrc_contexts_path(void) { return 0; }
const char *selinux_openssh_contexts_path(void) { return 0; }
const char *selinux_snapperd_contexts_path(void) { return 0; }
const char *selinux_systemd_contexts_path(void) { return 0; }
const char *selinux_contexts_path(void) { return 0; }
const char *selinux_securetty_types_path(void) { return 0; }
const char *selinux_booleans_subs_path(void) { return 0; }
const char *selinux_booleans_path(void) { return 0; }
const char *selinux_customizable_types_path(void) { return 0; }
const char *selinux_users_path(void) { return 0; }
const char *selinux_usersconf_path(void) { return 0; }
const char *selinux_translations_path(void) { return 0; }
const char *selinux_colors_path(void) { return 0; }
const char *selinux_netfilter_context_path(void) { return 0; }
const char *selinux_path(void) { return 0; }
int selinux_check_access(const char * scon, const char * tcon, const char *tclass, const char *perm, void *auditdata) { return 0; }
int selinux_check_passwd_access(access_vector_t requested) { return 0; }
int checkPasswdAccess(access_vector_t requested) { return 0; }
int selinux_check_securetty_context(const char * tty_context) { return 0; }
void set_selinuxmnt(const char *mnt) { }
int selinuxfs_exists(void) { return 0; }
void fini_selinuxmnt(void) {}
int setexecfilecon(const char *filename, const char *fallback_type) { return 0; }
#ifndef DISABLE_RPM
int rpm_execcon(unsigned int verified,
const char *filename,
char *const argv[], char *const envp[]) { return 0; }
#endif
int is_context_customizable(const char * scontext) { return 0; }
int selinux_trans_to_raw_context(const char * trans,
char ** rawp) { return 0; }
int selinux_raw_to_trans_context(const char * raw,
char ** transp) { return 0; }
int selinux_raw_context_to_color(const char * raw,
char **color_str) { return 0; }
int getseuserbyname(const char *linuxuser, char **seuser, char **level) { return 0; }
int getseuser(const char *username, const char *service,
char **r_seuser, char **r_level) { return 0; }
int selinux_file_context_cmp(const char * a,
const char * b) { return 0; }
int selinux_file_context_verify(const char *path, mode_t mode) { return 0; }
int selinux_lsetfilecon_default(const char *path) { return 0; }
void selinux_reset_config(void) { }
int avc_sid_to_context(security_id_t sid, char ** ctx) { return 0; }
int avc_sid_to_context_raw(security_id_t sid, char ** ctx) { return 0; }
int avc_context_to_sid(const char * ctx, security_id_t * sid) { return 0; }
int avc_context_to_sid_raw(const char * ctx, security_id_t * sid) { return 0; }
int sidget(security_id_t sid) { return 0; }
int sidput(security_id_t sid) { return 0; }
int avc_get_initial_sid(const char *name, security_id_t * sid) { return 0; }
int avc_init(const char *msgprefix,
const struct avc_memory_callback *mem_callbacks,
const struct avc_log_callback *log_callbacks,
const struct avc_thread_callback *thread_callbacks,
const struct avc_lock_callback *lock_callbacks) { return 0; }
int avc_open(struct selinux_opt *opts, unsigned nopts) { return 0; }
void avc_cleanup(void) { }
int avc_reset(void) { return 0; }
void avc_destroy(void) { }
int avc_has_perm_noaudit(security_id_t ssid,
security_id_t tsid,
security_class_t tclass,
access_vector_t requested,
struct avc_entry_ref *aeref, struct av_decision *avd) { return 0; }
int avc_has_perm(security_id_t ssid, security_id_t tsid,
security_class_t tclass, access_vector_t requested,
struct avc_entry_ref *aeref, void *auditdata) { return 0; }
void avc_audit(security_id_t ssid, security_id_t tsid,
security_class_t tclass, access_vector_t requested,
struct av_decision *avd, int result, void *auditdata) { }
int avc_compute_create(security_id_t ssid,
security_id_t tsid,
security_class_t tclass, security_id_t * newsid) { return 0; }
int avc_compute_member(security_id_t ssid,
security_id_t tsid,
security_class_t tclass, security_id_t * newsid) { return 0; }
int avc_add_callback(int (*callback)
(uint32_t event, security_id_t ssid,
security_id_t tsid, security_class_t tclass,
access_vector_t perms,
access_vector_t * out_retained),
uint32_t events, security_id_t ssid,
security_id_t tsid, security_class_t tclass,
access_vector_t perms) { return 0; }
void avc_cache_stats(struct avc_cache_stats *stats) { }
void avc_av_stats(void) { }
void avc_sid_stats(void) { }
int avc_netlink_open(int blocking) { return 0; }
void avc_netlink_loop(void) { }
void avc_netlink_close(void) { }
int avc_netlink_acquire_fd(void) { return 0; }
void avc_netlink_release_fd(void) { }
int avc_netlink_check_nb(void) { return 0; }
int selinux_status_open(int fallback) { return 0; }
void selinux_status_close(void) { }
int selinux_status_updated(void) { return 0; }
int selinux_status_getenforce(void) { return 0; }
int selinux_status_policyload(void) { return 0; }
int selinux_status_deny_unknown(void) { return 0; }
context_t context_new(const char *s) { return 0; }
char *context_str(context_t c) { return 0; }
void context_free(context_t c) { }
const char *context_type_get(context_t c) { return 0; }
const char *context_range_get(context_t c) { return 0; }
const char *context_role_get(context_t c) { return 0; }
const char *context_user_get(context_t c) { return 0; }
int context_type_set(context_t c, const char *s) { return 0; }
int context_range_set(context_t c, const char *s) { return 0; }
int context_role_set(context_t c, const char *s) { return 0; }
int context_user_set(context_t c, const char *s) { return 0; }
int get_ordered_context_list(const char *user,
char * fromcon,
char *** list) { return 0; }
int get_ordered_context_list_with_level(const char *user,
const char *level,
char * fromcon,
char *** list) { return 0; }
int get_default_context(const char *user,
char * fromcon,
char ** newcon) { return 0; }
int get_default_context_with_level(const char *user,
const char *level,
char * fromcon,
char ** newcon) { return 0; }
int get_default_context_with_role(const char *user,
const char *role,
char * fromcon,
char ** newcon) { return 0; }
int get_default_context_with_rolelevel(const char *user,
const char *role,
const char *level,
char * fromcon,
char ** newcon) { return 0; }
int query_user_context(char ** list,
char ** newcon) { return 0; }
int manual_user_enter_context(const char *user,
char ** newcon) { return 0; }
const char *selinux_default_type_path(void) { return 0; }
int get_default_type(const char *role, char **type) { return 0; }
struct selabel_handle *selabel_open(unsigned int backend,
const struct selinux_opt *opts,
unsigned nopts) { return 0; }
void selabel_close(struct selabel_handle *handle) { }
int selabel_lookup(struct selabel_handle *handle, char **con,
const char *key, int type) { return 0; }
int selabel_lookup_raw(struct selabel_handle *handle, char **con,
const char *key, int type) { return 0; }
bool selabel_partial_match(struct selabel_handle *handle, const char *key) { return 0; }
int selabel_lookup_best_match(struct selabel_handle *rec, char **con,
const char *key, const char **aliases, int type) { return 0; }
int selabel_lookup_best_match_raw(struct selabel_handle *rec, char **con,
const char *key, const char **aliases, int type) { return 0; }
int selabel_digest(struct selabel_handle *rec,
unsigned char **digest, size_t *digest_len,
char ***specfiles, size_t *num_specfiles) { return 0; }
void selabel_stats(struct selabel_handle *handle) { }
int selinux_restorecon(const char *pathname,
unsigned int restorecon_flags) { return 0; }
struct selabel_handle *selinux_restorecon_default_handle(void) { return 0; }
void selinux_restorecon_set_exclude_list(const char **exclude_list) { }
int selinux_restorecon_set_alt_rootpath(const char *alt_rootpath) { return 0; }
int selinux_restorecon_xattr(const char *pathname,
unsigned int xattr_flags,
struct dir_xattr ***xattr_list) { return 0; }

676
native/jni/external/stubs/sqlite3_stub.c vendored Normal file
View File

@@ -0,0 +1,676 @@
#include "sqlite3.h"
SQLITE_API const char *sqlite3_libversion(void) { return 0; }
SQLITE_API const char *sqlite3_sourceid(void) { return 0; }
SQLITE_API int sqlite3_libversion_number(void) { return 0; }
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
SQLITE_API int sqlite3_compileoption_used(const char *zOptName) { return 0; }
SQLITE_API const char *sqlite3_compileoption_get(int N) { return 0; }
#endif
SQLITE_API int sqlite3_threadsafe(void) { return 0; }
SQLITE_API int sqlite3_close(sqlite3 *db) { return 0; }
SQLITE_API int sqlite3_close_v2(sqlite3 *db) { return 0; }
SQLITE_API int sqlite3_exec(
sqlite3 *db,
const char *sql,
int (*callback)(void*,int,char**,char**),
void *v,
char **errmsg
) { return 0; }
SQLITE_API int sqlite3_initialize(void) { return 0; }
SQLITE_API int sqlite3_shutdown(void) { return 0; }
SQLITE_API int sqlite3_os_init(void) { return 0; }
SQLITE_API int sqlite3_os_end(void) { return 0; }
SQLITE_API int sqlite3_config(int i, ...) { return 0; }
SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...) { return 0; }
SQLITE_API int sqlite3_extended_result_codes(sqlite3 *db, int onoff) { return 0; }
SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3 *db) { return 0; }
SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3 *db,sqlite3_int64 i) { }
SQLITE_API int sqlite3_changes(sqlite3 *db) { return 0; }
SQLITE_API int sqlite3_total_changes(sqlite3 *db) { return 0; }
SQLITE_API void sqlite3_interrupt(sqlite3 *db) { }
SQLITE_API int sqlite3_complete(const char *sql) { return 0; }
SQLITE_API int sqlite3_complete16(const void *sql) { return 0; }
SQLITE_API int sqlite3_busy_handler(sqlite3 *db, int(*f) (void *v,int i), void* v) { return 0; }
SQLITE_API int sqlite3_busy_timeout(sqlite3 *db, int ms) { return 0; }
SQLITE_API int sqlite3_get_table(
sqlite3 *db,
const char *zSql,
char ***pazResult,
int *pnRow,
int *pnColumn,
char **pzErrmsg
) { return 0; }
SQLITE_API void sqlite3_free_table(char **result) { }
SQLITE_API char *sqlite3_mprintf(const char* s,...) { return 0; }
SQLITE_API char *sqlite3_vmprintf(const char* s, va_list v) { return 0; }
SQLITE_API char *sqlite3_snprintf(int i, char* s, const char* st, ...) { return 0; }
SQLITE_API char *sqlite3_vsnprintf(int i, char* s, const char* st, va_list v) { return 0; }
SQLITE_API void *sqlite3_malloc(int i) { return 0; }
SQLITE_API void *sqlite3_malloc64(sqlite3_uint64 i) { return 0; }
SQLITE_API void *sqlite3_realloc(void* v, int i) { return 0; }
SQLITE_API void *sqlite3_realloc64(void* v, sqlite3_uint64 i) { return 0; }
SQLITE_API void sqlite3_free(void* v) { }
SQLITE_API sqlite3_uint64 sqlite3_msize(void* v) { return 0; }
SQLITE_API sqlite3_int64 sqlite3_memory_used(void) { return 0; }
SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag) { return 0; }
SQLITE_API void sqlite3_randomness(int N, void *P) { }
SQLITE_API int sqlite3_set_authorizer(
sqlite3 *db,
int (*xAuth)(void *v,int i,const char*,const char*,const char*,const char*),
void *pUserData
) { return 0; }
SQLITE_API SQLITE_DEPRECATED void *sqlite3_trace(sqlite3 *db,
void(*xTrace)(void *v,const char*), void* v) { return 0; }
SQLITE_API SQLITE_DEPRECATED void *sqlite3_profile(sqlite3 *db,
void(*xProfile)(void *v,const char*,sqlite3_uint64), void* v) { return 0; }
SQLITE_API int sqlite3_trace_v2(
sqlite3 *db,
unsigned uMask,
int(*xCallback)(unsigned,void *v,void *vv,void*),
void *pCtx
) { return 0; }
SQLITE_API void sqlite3_progress_handler(sqlite3 *db, int i, int(*f)(void*), void* v) { }
SQLITE_API int sqlite3_open(
const char *filename,
sqlite3 **ppDb
) { return 0; }
SQLITE_API int sqlite3_open16(
const void *filename,
sqlite3 **ppDb
) { return 0; }
SQLITE_API int sqlite3_open_v2(
const char *filename,
sqlite3 **ppDb,
int flags,
const char *zVfs
) { return 0; }
SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam) { return 0; }
SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault) { return 0; }
SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char* s, const char* st, sqlite3_int64 i) { return 0; }
SQLITE_API int sqlite3_errcode(sqlite3 *db) { return 0; }
SQLITE_API int sqlite3_extended_errcode(sqlite3 *db) { return 0; }
SQLITE_API const char *sqlite3_errmsg(sqlite3 *db) { return 0; }
SQLITE_API const void *sqlite3_errmsg16(sqlite3 *db) { return 0; }
SQLITE_API const char *sqlite3_errstr(int i) { return 0; }
SQLITE_API int sqlite3_limit(sqlite3 *db, int id, int newVal) { return 0; }
SQLITE_API int sqlite3_prepare(
sqlite3 *db,
const char *zSql,
int nByte,
sqlite3_stmt **ppStmt,
const char **pzTail
) { return 0; }
SQLITE_API int sqlite3_prepare_v2(
sqlite3 *db,
const char *zSql,
int nByte,
sqlite3_stmt **ppStmt,
const char **pzTail
) { return 0; }
SQLITE_API int sqlite3_prepare16(
sqlite3 *db,
const void *zSql,
int nByte,
sqlite3_stmt **ppStmt,
const void **pzTail
) { return 0; }
SQLITE_API int sqlite3_prepare16_v2(
sqlite3 *db,
const void *zSql,
int nByte,
sqlite3_stmt **ppStmt,
const void **pzTail
) { return 0; }
SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt) { return 0; }
SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt) { return 0; }
SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt) { return 0; }
SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt* s) { return 0; }
SQLITE_API int sqlite3_bind_blob(sqlite3_stmt* s, int i, const void*v, int n, void(*f)(void*)) { return 0; }
SQLITE_API int sqlite3_bind_blob64(sqlite3_stmt* s, int i, const void *v, sqlite3_uint64 ii,
void(*f)(void*)) { return 0; }
SQLITE_API int sqlite3_bind_double(sqlite3_stmt* s, int i, double d) { return 0; }
SQLITE_API int sqlite3_bind_int(sqlite3_stmt* s, int i, int ii) { return 0; }
SQLITE_API int sqlite3_bind_int64(sqlite3_stmt* s, int i, sqlite3_int64 ii) { return 0; }
SQLITE_API int sqlite3_bind_null(sqlite3_stmt* s, int i) { return 0; }
SQLITE_API int sqlite3_bind_text(sqlite3_stmt* s,int i,const char* str, int ii, void(*f)(void*)) { return 0; }
SQLITE_API int sqlite3_bind_text16(sqlite3_stmt* s, int i, const void *v, int ii, void(*f)(void*)) { return 0; }
SQLITE_API int sqlite3_bind_text64(sqlite3_stmt* s, int i, const char* str, sqlite3_uint64 ii,
void(*f)(void*), unsigned char encoding) { return 0; }
SQLITE_API int sqlite3_bind_value(sqlite3_stmt* s, int i, const sqlite3_value* v) { return 0; }
SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt* s, int i, int n) { return 0; }
SQLITE_API int sqlite3_bind_zeroblob64(sqlite3_stmt* s, int i, sqlite3_uint64 ii) { return 0; }
SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt* s) { return 0; }
SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt* s, int i) { return 0; }
SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt* s, const char *zName) { return 0; }
SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt* s) { return 0; }
SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt) { return 0; }
SQLITE_API const char *sqlite3_column_name(sqlite3_stmt* s, int N) { return 0; }
SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt* s, int N) { return 0; }
SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt* s,int i) { return 0; }
SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt* s,int i){ return 0; }
SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt* s,int i) { return 0; }
SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt* s,int i) { return 0; }
SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt* s,int i) { return 0; }
SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt* s,int i) { return 0; }
SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt* s,int i) { return 0; }
SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt* s,int i) { return 0; }
SQLITE_API int sqlite3_step(sqlite3_stmt* s) { return 0; }
SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt) { return 0; }
SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt* s, int iCol) { return 0; }
SQLITE_API int sqlite3_column_bytes(sqlite3_stmt* s, int iCol) { return 0; }
SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt* s, int iCol) { return 0; }
SQLITE_API double sqlite3_column_double(sqlite3_stmt* s, int iCol) { return 0; }
SQLITE_API int sqlite3_column_int(sqlite3_stmt* s, int iCol) { return 0; }
SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt* s, int iCol) { return 0; }
SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt* s, int iCol) { return 0; }
SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt* s, int iCol) { return 0; }
SQLITE_API int sqlite3_column_type(sqlite3_stmt* s, int iCol) { return 0; }
SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt* s, int iCol) { return 0; }
SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt) { return 0; }
SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt) { return 0; }
SQLITE_API int sqlite3_create_function(
sqlite3 *db,
const char *zFunctionName,
int nArg,
int eTextRep,
void *pApp,
void (*xFunc)(sqlite3_context* c,int i,sqlite3_value**),
void (*xStep)(sqlite3_context* c,int i,sqlite3_value**),
void (*xFinal)(sqlite3_context* c)
) { return 0; }
SQLITE_API int sqlite3_create_function16(
sqlite3 *db,
const void *zFunctionName,
int nArg,
int eTextRep,
void *pApp,
void (*xFunc)(sqlite3_context* c,int i,sqlite3_value**),
void (*xStep)(sqlite3_context* c,int i,sqlite3_value**),
void (*xFinal)(sqlite3_context* c)
) { return 0; }
SQLITE_API int sqlite3_create_function_v2(
sqlite3 *db,
const char *zFunctionName,
int nArg,
int eTextRep,
void *pApp,
void (*xFunc)(sqlite3_context* c,int i,sqlite3_value**),
void (*xStep)(sqlite3_context* c,int i,sqlite3_value**),
void (*xFinal)(sqlite3_context* c),
void(*xDestroy)(void*)
) { return 0; }
#ifndef SQLITE_OMIT_DEPRECATED
SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context* c) { return 0; }
SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt* s) { return 0; }
SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt* s, sqlite3_stmt* ss) { return 0; }
SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void) { return 0; }
SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void) { }
SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*f)(void *v,sqlite3_int64,int),
void *v,sqlite3_int64 i) { return 0; }
#endif
SQLITE_API const void *sqlite3_value_blob(sqlite3_value* v) { return 0; }
SQLITE_API int sqlite3_value_bytes(sqlite3_value* v) { return 0; }
SQLITE_API int sqlite3_value_bytes16(sqlite3_value* v) { return 0; }
SQLITE_API double sqlite3_value_double(sqlite3_value* v) { return 0; }
SQLITE_API int sqlite3_value_int(sqlite3_value* v) { return 0; }
SQLITE_API sqlite3_int64 sqlite3_value_int64(sqlite3_value* v) { return 0; }
SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value* v) { return 0; }
SQLITE_API const void *sqlite3_value_text16(sqlite3_value* v) { return 0; }
SQLITE_API const void *sqlite3_value_text16le(sqlite3_value* v) { return 0; }
SQLITE_API const void *sqlite3_value_text16be(sqlite3_value* v) { return 0; }
SQLITE_API int sqlite3_value_type(sqlite3_value* v) { return 0; }
SQLITE_API int sqlite3_value_numeric_type(sqlite3_value* v) { return 0; }
SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value* v) { return 0; }
SQLITE_API sqlite3_value *sqlite3_value_dup(const sqlite3_value* v) { return 0; }
SQLITE_API void sqlite3_value_free(sqlite3_value* v) { }
SQLITE_API void *sqlite3_aggregate_context(sqlite3_context* c, int nBytes) { return 0; }
SQLITE_API void *sqlite3_user_data(sqlite3_context* c) { return 0; }
SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context* c) { return 0; }
SQLITE_API void *sqlite3_get_auxdata(sqlite3_context* c, int N) { return 0; }
SQLITE_API void sqlite3_set_auxdata(sqlite3_context* c, int N, void *v, void (*f)(void*)) { }
SQLITE_API void sqlite3_result_blob(sqlite3_context* c, const void *v, int i, void(*f)(void*)) { }
SQLITE_API void sqlite3_result_blob64(sqlite3_context* c,const void *v,
sqlite3_uint64 i,void(*f)(void*)) { }
SQLITE_API void sqlite3_result_double(sqlite3_context* c, double d) { }
SQLITE_API void sqlite3_result_error(sqlite3_context* c, const char* s, int i) { }
SQLITE_API void sqlite3_result_error16(sqlite3_context* c, const void *v, int i) { }
SQLITE_API void sqlite3_result_error_toobig(sqlite3_context* c) { }
SQLITE_API void sqlite3_result_error_nomem(sqlite3_context* c) { }
SQLITE_API void sqlite3_result_error_code(sqlite3_context* c, int i) { }
SQLITE_API void sqlite3_result_int(sqlite3_context* c, int i) { }
SQLITE_API void sqlite3_result_int64(sqlite3_context* c, sqlite3_int64 i) { }
SQLITE_API void sqlite3_result_null(sqlite3_context* c) { }
SQLITE_API void sqlite3_result_text(sqlite3_context* c, const char* s, int i, void(*f)(void*)) { }
SQLITE_API void sqlite3_result_text64(sqlite3_context* c, const char* s, sqlite3_uint64 i,
void(*f)(void*), unsigned char encoding) { }
SQLITE_API void sqlite3_result_text16(sqlite3_context* c, const void *v, int i, void(*f)(void*)) { }
SQLITE_API void sqlite3_result_text16le(sqlite3_context* c, const void *v, int i,void(*f)(void*)) { }
SQLITE_API void sqlite3_result_text16be(sqlite3_context* c, const void *v, int i,void(*f)(void*)) { }
SQLITE_API void sqlite3_result_value(sqlite3_context* c, sqlite3_value* v) { }
SQLITE_API void sqlite3_result_zeroblob(sqlite3_context* c, int n) { }
SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context* c, sqlite3_uint64 n) { return 0; }
SQLITE_API void sqlite3_result_subtype(sqlite3_context* c,unsigned int i) { }
SQLITE_API int sqlite3_create_collation(
sqlite3 *db,
const char *zName,
int eTextRep,
void *pArg,
int(*xCompare)(void *,int,const void *,int,const void*)
) { return 0; }
SQLITE_API int sqlite3_create_collation_v2(
sqlite3 *db,
const char *zName,
int eTextRep,
void *pArg,
int(*xCompare)(void *,int,const void*,int,const void*),
void(*xDestroy)(void*)
) { return 0; }
SQLITE_API int sqlite3_create_collation16(
sqlite3 *db,
const void *zName,
int eTextRep,
void *pArg,
int(*xCompare)(void *,int,const void *,int,const void*)
) { return 0; }
SQLITE_API int sqlite3_collation_needed(
sqlite3 *db,
void *v,
void(*f)(void *v,sqlite3 *db,int eTextRep,const char*)
) { return 0; }
SQLITE_API int sqlite3_collation_needed16(
sqlite3 *db,
void *v,
void(*f)(void *v,sqlite3 *db,int eTextRep,const void*)
) { return 0; }
#ifdef SQLITE_HAS_CODEC
SQLITE_API int sqlite3_key(
sqlite3 *db,
const void *pKey, int nKey
) { return 0; }
SQLITE_API int sqlite3_key_v2(
sqlite3 *db,
const char *zDbName,
const void *pKey, int nKey
) { return 0; }
SQLITE_API int sqlite3_rekey(
sqlite3 *db,
const void *pKey, int nKey
) { return 0; }
SQLITE_API int sqlite3_rekey_v2(
sqlite3 *db,
const char *zDbName,
const void *pKey, int nKey
) { return 0; }
SQLITE_API void sqlite3_activate_see(
const char *zPassPhrase
) { return 0; }
#endif
#ifdef SQLITE_ENABLE_CEROD
SQLITE_API void sqlite3_activate_cerod(
const char *zPassPhrase
) { return 0; }
#endif
SQLITE_API int sqlite3_sleep(int i) { return 0; }
SQLITE_API int sqlite3_get_autocommit(sqlite3 *db) { return 0; }
SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt *s) { return 0; }
SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName) { return 0; }
SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName) { return 0; }
SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt) { return 0; }
SQLITE_API void *sqlite3_commit_hook(sqlite3 *db, int(*f)(void*), void *v) { return 0; }
SQLITE_API void *sqlite3_rollback_hook(sqlite3 *db, void(*f)(void *), void *v) { return 0; }
SQLITE_API void *sqlite3_update_hook(
sqlite3 *db,
void(*f)(void *,int ,char const *,char const *,sqlite3_int64),
void *v
) { return 0; }
SQLITE_API int sqlite3_enable_shared_cache(int i) { return 0; }
SQLITE_API int sqlite3_release_memory(int i) { return 0; }
SQLITE_API int sqlite3_db_release_memory(sqlite3 *db) { return 0; }
SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N) { return 0; }
SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N) { }
SQLITE_API int sqlite3_table_column_metadata(
sqlite3 *db,
const char *zDbName,
const char *zTableName,
const char *zColumnName,
char const **pzDataType,
char const **pzCollSeq,
int *pNotNull,
int *pPrimaryKey,
int *pAutoinc
) { return 0; }
SQLITE_API int sqlite3_load_extension(
sqlite3 *db,
const char *zFile,
const char *zProc,
char **pzErrMsg
) { return 0; }
SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff) { return 0; }
SQLITE_API int sqlite3_auto_extension(void(*xEntryPoint)(void)) { return 0; }
SQLITE_API int sqlite3_cancel_auto_extension(void(*xEntryPoint)(void)) { return 0; }
SQLITE_API void sqlite3_reset_auto_extension(void) { }
SQLITE_API int sqlite3_create_module(
sqlite3 *db,
const char *zName,
const sqlite3_module *p,
void *pClientData
) { return 0; }
SQLITE_API int sqlite3_create_module_v2(
sqlite3 *db,
const char *zName,
const sqlite3_module *p,
void *pClientData,
void(*xDestroy)(void*)
) { return 0; }
SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zSQL) { return 0; }
SQLITE_API int sqlite3_overload_function(sqlite3 *db, const char *zFuncName, int nArg) { return 0; }
SQLITE_API int sqlite3_blob_open(
sqlite3 *db,
const char *zDb,
const char *zTable,
const char *zColumn,
sqlite3_int64 iRow,
int flags,
sqlite3_blob **ppBlob
) { return 0; }
SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *b, sqlite3_int64 i) { return 0; }
SQLITE_API int sqlite3_blob_close(sqlite3_blob *b) { return 0; }
SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *b) { return 0; }
SQLITE_API int sqlite3_blob_read(sqlite3_blob *b, void *Z, int N, int iOffset) { return 0; }
SQLITE_API int sqlite3_blob_write(sqlite3_blob *b, const void *z, int n, int iOffset) { return 0; }
SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName) { return 0; }
SQLITE_API int sqlite3_vfs_register(sqlite3_vfs *v, int makeDflt) { return 0; }
SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs *v) { return 0; }
SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int i) { return 0; }
SQLITE_API void sqlite3_mutex_free(sqlite3_mutex *m) { }
SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex *m) { }
SQLITE_API int sqlite3_mutex_try(sqlite3_mutex *m) { return 0; }
SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex *m) { }
#ifndef NDEBUG
SQLITE_API int sqlite3_mutex_held(sqlite3_mutex *m) { return 0; }
SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *m) { return 0; }
#endif
SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3* db) { return 0; }
SQLITE_API int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void* v) { return 0; }
SQLITE_API int sqlite3_test_control(int op, ...) { return 0; }
SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag) { return 0; }
SQLITE_API int sqlite3_status64(
int op,
sqlite3_int64 *pCurrent,
sqlite3_int64 *pHighwater,
int resetFlag
) { return 0; }
SQLITE_API int sqlite3_db_status(sqlite3 *db, int op, int *pCur, int *pHiwtr, int resetFlg) { return 0; }
SQLITE_API int sqlite3_stmt_status(sqlite3_stmt* s, int op,int resetFlg) { return 0; }
SQLITE_API sqlite3_backup *sqlite3_backup_init(
sqlite3 *pDest,
const char *zDestName,
sqlite3 *pSource,
const char *zSourceName
) { return 0; }
SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage) { return 0; }
SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p) { return 0; }
SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p) { return 0; }
SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p) { return 0; }
SQLITE_API int sqlite3_unlock_notify(
sqlite3 *pBlocked,
void (*xNotify)(void **apArg, int nArg),
void *pNotifyArg
) { return 0; }
SQLITE_API int sqlite3_stricmp(const char *s, const char *ss) { return 0; }
SQLITE_API int sqlite3_strnicmp(const char *s, const char *ss, int i) { return 0; }
SQLITE_API int sqlite3_strglob(const char *zGlob, const char *zStr) { return 0; }
SQLITE_API int sqlite3_strlike(const char *zGlob, const char *zStr, unsigned int cEsc) { return 0; }
SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...) { }
SQLITE_API void *sqlite3_wal_hook(
sqlite3 *db,
int(*f)(void *,sqlite3 *db,const char*,int i),
void *v
) { return 0; }
SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N) { return 0; }
SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb) { return 0; }
SQLITE_API int sqlite3_wal_checkpoint_v2(
sqlite3 *db,
const char *zDb,
int eMode,
int *pnLog,
int *pnCkpt
) { return 0; }
#define SQLITE_CHECKPOINT_PASSIVE 0
#define SQLITE_CHECKPOINT_FULL 1
#define SQLITE_CHECKPOINT_RESTART 2
#define SQLITE_CHECKPOINT_TRUNCATE 3
SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...) { return 0; }
#define SQLITE_VTAB_CONSTRAINT_SUPPORT 1
SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *db) { return 0; }
#define SQLITE_ROLLBACK 1
#define SQLITE_FAIL 3
#define SQLITE_REPLACE 5
#define SQLITE_SCANSTAT_NLOOP 0
#define SQLITE_SCANSTAT_NVISIT 1
#define SQLITE_SCANSTAT_EST 2
#define SQLITE_SCANSTAT_NAME 3
#define SQLITE_SCANSTAT_EXPLAIN 4
#define SQLITE_SCANSTAT_SELECTID 5
SQLITE_API int sqlite3_stmt_scanstatus(
sqlite3_stmt *pStmt,
int idx,
int iScanStatusOp,
void *pOut
) { return 0; }
SQLITE_API void sqlite3_stmt_scanstatus_reset(sqlite3_stmt *s) { }
SQLITE_API int sqlite3_db_cacheflush(sqlite3* db) { return 0; }
#if defined(SQLITE_ENABLE_PREUPDATE_HOOK)
SQLITE_API void *sqlite3_preupdate_hook(
sqlite3 *db,
void(*xPreUpdate)(
void *pCtx,
sqlite3 *db,
int op,
char const *zDb,
char const *zName,
sqlite3_int64 iKey1,
sqlite3_int64 iKey2
),
void*
) { return 0; }
SQLITE_API int sqlite3_preupdate_old(sqlite3 *, int i, sqlite3_value **) { return 0; }
SQLITE_API int sqlite3_preupdate_count(sqlite3 *) { return 0; }
SQLITE_API int sqlite3_preupdate_depth(sqlite3 *) { return 0; }
SQLITE_API int sqlite3_preupdate_new(sqlite3 *, int i, sqlite3_value **) { return 0; }
#endif
SQLITE_API int sqlite3_system_errno(sqlite3 *db) { return 0; }
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get(
sqlite3 *db,
const char *zSchema,
sqlite3_snapshot **ppSnapshot
) { return 0; }
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open(
sqlite3 *db,
const char *zSchema,
sqlite3_snapshot *pSnapshot
) { return 0; }
SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot* s) { }
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp(
sqlite3_snapshot *p1,
sqlite3_snapshot *p2
) { return 0; }
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb) { return 0; }
SQLITE_API int sqlite3_rtree_geometry_callback(
sqlite3 *db,
const char *zGeom,
int (*xGeom)(sqlite3_rtree_geometry*, int i, sqlite3_rtree_dbl*,int*),
void *pContext
) { return 0; }
SQLITE_API int sqlite3_rtree_query_callback(
sqlite3 *db,
const char *zQueryFunc,
int (*xQueryFunc)(sqlite3_rtree_query_info*),
void *pContext,
void (*xDestructor)(void*)
) { return 0; }
typedef struct sqlite3_session sqlite3_session;
typedef struct sqlite3_changeset_iter sqlite3_changeset_iter;
SQLITE_API int sqlite3session_create(
sqlite3 *db,
const char *zDb,
sqlite3_session **ppSession
) { return 0; }
SQLITE_API void sqlite3session_delete(sqlite3_session *pSession) { }
SQLITE_API int sqlite3session_enable(sqlite3_session *pSession, int bEnable) { return 0; }
SQLITE_API int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect) { return 0; }
SQLITE_API int sqlite3session_attach(
sqlite3_session *pSession,
const char *zTab
) { return 0; }
SQLITE_API void sqlite3session_table_filter(
sqlite3_session *pSession,
int(*xFilter)(
void *pCtx,
const char *zTab
),
void *pCtx
) { }
SQLITE_API int sqlite3session_changeset(
sqlite3_session *pSession,
int *pnChangeset,
void **ppChangeset
) { return 0; }
SQLITE_API int sqlite3session_diff(
sqlite3_session *pSession,
const char *zFromDb,
const char *zTbl,
char **pzErrMsg
) { return 0; }
SQLITE_API int sqlite3session_patchset(
sqlite3_session *pSession,
int *pnPatchset,
void **ppPatchset
) { return 0; }
SQLITE_API int sqlite3session_isempty(sqlite3_session *pSession) { return 0; }
SQLITE_API int sqlite3changeset_start(
sqlite3_changeset_iter **pp,
int nChangeset,
void *pChangeset
) { return 0; }
SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *pIter) { return 0; }
SQLITE_API int sqlite3changeset_op(
sqlite3_changeset_iter *pIter,
const char **pzTab,
int *pnCol,
int *pOp,
int *pbIndirect
) { return 0; }
SQLITE_API int sqlite3changeset_pk(
sqlite3_changeset_iter *pIter,
unsigned char **pabPK,
int *pnCol
) { return 0; }
SQLITE_API int sqlite3changeset_old(
sqlite3_changeset_iter *pIter,
int iVal,
sqlite3_value **ppValue
) { return 0; }
SQLITE_API int sqlite3changeset_new(
sqlite3_changeset_iter *pIter,
int iVal,
sqlite3_value **ppValue
) { return 0; }
SQLITE_API int sqlite3changeset_conflict(
sqlite3_changeset_iter *pIter,
int iVal,
sqlite3_value **ppValue
) { return 0; }
SQLITE_API int sqlite3changeset_fk_conflicts(
sqlite3_changeset_iter *pIter,
int *pnOut
) { return 0; }
SQLITE_API int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter) { return 0; }
SQLITE_API int sqlite3changeset_invert(
int nIn, const void *pIn,
int *pnOut, void **ppOut
) { return 0; }
SQLITE_API int sqlite3changeset_concat(
int nA,
void *pA,
int nB,
void *pB,
int *pnOut,
void **ppOut
) { return 0; }
typedef struct sqlite3_changegroup sqlite3_changegroup;
int sqlite3changegroup_new(sqlite3_changegroup **pp) { return 0; }
int sqlite3changegroup_add(sqlite3_changegroup *c, int nData, void *pData) { return 0; }
int sqlite3changegroup_output(
sqlite3_changegroup *c,
int *pnData,
void **ppData
) { return 0; }
void sqlite3changegroup_delete(sqlite3_changegroup *c) { }
SQLITE_API int sqlite3changeset_apply(
sqlite3 *db,
int nChangeset,
void *pChangeset,
int(*xFilter)(
void *pCtx,
const char *zTab
),
int(*xConflict)(
void *pCtx,
int eConflict,
sqlite3_changeset_iter *p
),
void *pCtx
) { return 0; }
SQLITE_API int sqlite3changeset_apply_strm(
sqlite3 *db,
int (*xInput)(void *pIn, void *pData, int *pnData),
void *pIn,
int(*xFilter)(
void *pCtx,
const char *zTab
),
int(*xConflict)(
void *pCtx,
int eConflict,
sqlite3_changeset_iter *p
),
void *pCtx
) { return 0; }
SQLITE_API int sqlite3changeset_concat_strm(
int (*xInputA)(void *pIn, void *pData, int *pnData),
void *pInA,
int (*xInputB)(void *pIn, void *pData, int *pnData),
void *pInB,
int (*xOutput)(void *pOut, const void *pData, int nData),
void *pOut
) { return 0; }
SQLITE_API int sqlite3changeset_invert_strm(
int (*xInput)(void *pIn, void *pData, int *pnData),
void *pIn,
int (*xOutput)(void *pOut, const void *pData, int nData),
void *pOut
) { return 0; }
SQLITE_API int sqlite3changeset_start_strm(
sqlite3_changeset_iter **pp,
int (*xInput)(void *pIn, void *pData, int *pnData),
void *pIn
) { return 0; }
SQLITE_API int sqlite3session_changeset_strm(
sqlite3_session *pSession,
int (*xOutput)(void *pOut, const void *pData, int nData),
void *pOut
) { return 0; }
SQLITE_API int sqlite3session_patchset_strm(
sqlite3_session *pSession,
int (*xOutput)(void *pOut, const void *pData, int nData),
void *pOut
) { return 0; }
int sqlite3changegroup_add_strm(sqlite3_changegroup *c,
int (*xInput)(void *pIn, void *pData, int *pnData),
void *pIn
) { return 0; }
int sqlite3changegroup_output_strm(sqlite3_changegroup *c,
int (*xOutput)(void *pOut, const void *pData, int nData),
void *pOut
) { return 0; }

1
native/jni/external/xz vendored Submodule

Submodule native/jni/external/xz added at 3d566cd519

60
native/jni/include/cpio.h Normal file
View File

@@ -0,0 +1,60 @@
#ifndef _CPIO_H_
#define _CPIO_H_
#include <stdint.h>
#include "vector.h"
typedef struct cpio_entry {
// uint32_t ino;
uint32_t mode;
uint32_t uid;
uint32_t gid;
// uint32_t nlink;
// uint32_t mtime;
uint32_t filesize;
// uint32_t devmajor;
// uint32_t devminor;
// uint32_t rdevmajor;
// uint32_t rdevminor;
// uint32_t namesize;
// uint32_t check;
char *filename;
void *data;
int remove;
} cpio_entry;
typedef struct cpio_newc_header {
char magic[6];
char ino[8];
char mode[8];
char uid[8];
char gid[8];
char nlink[8];
char mtime[8];
char filesize[8];
char devmajor[8];
char devminor[8];
char rdevmajor[8];
char rdevminor[8];
char namesize[8];
char check[8];
} cpio_newc_header;
// Basic cpio functions
void cpio_free(cpio_entry *e);
int cpio_find(struct vector *v, const char *entry);
int cpio_cmp(const void *a, const void *b);
void parse_cpio(struct vector *v, const char *filename);
void dump_cpio(struct vector *v, const char *filename);
void cpio_vec_insert(struct vector *v, cpio_entry *n);
void cpio_vec_destroy(struct vector *v);
void cpio_rm(struct vector *v, int recursive, const char *entry);
void cpio_mkdir(struct vector *v, mode_t mode, const char *entry);
void cpio_ln(struct vector *v, const char *target, const char *entry);
void cpio_add(struct vector *v, mode_t mode, const char *entry, const char *filename);
int cpio_mv(struct vector *v, const char *from, const char *to);
int cpio_extract(struct vector *v, const char *entry, const char *filename);
void cpio_extract_all(struct vector *v);
#endif

View File

@@ -0,0 +1,83 @@
/* daemon.h - Utility functions for daemon-client communication
*/
#ifndef _DAEMON_H_
#define _DAEMON_H_
#include <pthread.h>
#include <sys/un.h>
#include <sys/socket.h>
extern int is_daemon_init, seperate_vendor;
// Commands require connecting to daemon
enum {
DO_NOTHING = 0,
SUPERUSER,
CHECK_VERSION,
CHECK_VERSION_CODE,
POST_FS,
POST_FS_DATA,
LATE_START,
LAUNCH_MAGISKHIDE,
STOP_MAGISKHIDE,
ADD_HIDELIST,
RM_HIDELIST,
LS_HIDELIST
};
// Return codes for daemon
enum {
DAEMON_ERROR = -1,
DAEMON_SUCCESS = 0,
ROOT_REQUIRED,
LOGD_DISABLED,
HIDE_IS_ENABLED,
HIDE_NOT_ENABLED,
HIDE_ITEM_EXIST,
HIDE_ITEM_NOT_EXIST,
};
// daemon.c
void start_daemon();
int connect_daemon();
void auto_start_magiskhide();
void daemon_init();
// socket.c
int setup_socket(struct sockaddr_un *sun);
int recv_fd(int sockfd);
void send_fd(int sockfd, int fd);
int read_int(int fd);
void write_int(int fd, int val);
char* read_string(int fd);
void write_string(int fd, const char* val);
/***************
* Boot Stages *
***************/
void post_fs(int client);
void post_fs_data(int client);
void late_start(int client);
void fix_filecon();
/**************
* MagiskHide *
**************/
void launch_magiskhide(int client);
void stop_magiskhide(int client);
void add_hide_list(int client);
void rm_hide_list(int client);
void ls_hide_list(int client);
/*************
* Superuser *
*************/
void su_daemon_receiver(int client, struct ucred *credential);
#endif

43
native/jni/include/list.h Normal file
View File

@@ -0,0 +1,43 @@
/* list.h - Double link list implementation
*/
#ifndef _LIST_H_
#define _LIST_H_
#include <stddef.h>
struct list_head {
struct list_head *next;
struct list_head *prev;
};
void init_list_head(struct list_head *head);
void list_insert(struct list_head *pos, struct list_head *node);
void list_insert_end(struct list_head *head, struct list_head *node);
struct list_head *list_pop(struct list_head *pos);
struct list_head *list_pop_end(struct list_head *head);
#define list_entry(pos, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (pos); \
(type *)( (char *)__mptr - offsetof(type,member) );})
#define list_for_each(ptr, head, type, member) \
ptr = list_entry((head)->next, type, member); \
for (struct list_head *__ = (head)->next; __ != (head); __ = __->next, ptr = list_entry(__, type, member))
#define list_for_each_r(ptr, head, type, member) \
ptr = list_entry((head)->prev, type, member); \
for (struct list_head *__ = (head)->prev; __ != (head); __ = __->prev, ptr = list_entry(__, type, member))
#define list_destory(head, type, member, func) ({ \
struct list_head *node = head->next; \
while(node != head) { \
node = node->next; \
if (func) func(list_entry(node->prev, line_list, pos)); \
free(list_entry(node->prev, line_list, pos)); \
} \
head->next = head; \
head->prev = head; \
})
#endif

View File

@@ -0,0 +1,87 @@
/* logging.h - Error handling and logging
*/
#ifndef _LOGGING_H_
#define _LOGGING_H_
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#define str(a) #a
#define xstr(a) str(a)
/**************
* No logging *
**************/
#define LOGD(...)
#define LOGI(...)
#define LOGW(...)
#define LOGE(...)
#define PLOGE(...)
/******************
* Daemon logging *
******************/
#ifdef IS_DAEMON
#undef LOGI
#undef LOGW
#undef LOGE
#undef PLOGE
#include <pthread.h>
#include <android/log.h>
#define LOG_TAG "Magisk"
#ifdef MAGISK_DEBUG
#undef LOGD
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#endif
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define PLOGE(fmt, args...) LOGE(fmt " failed with %d: %s", ##args, errno, strerror(errno))
enum {
HIDE_EVENT,
LOG_EVENT,
DEBUG_EVENT
};
struct log_listener {
int fd;
int (*filter) (const char*);
};
extern struct log_listener log_events[];
extern int logd;
void monitor_logs();
void start_debug_full_log();
void stop_debug_full_log();
void start_debug_log();
#endif
/********************
* Tools Log & Exit *
********************/
#ifdef XWRAP_EXIT
#undef LOGE
#undef PLOGE
#include <stdio.h>
#define LOGE(...) { fprintf(stderr, __VA_ARGS__); exit(1); }
#define PLOGE(fmt, args...) { fprintf(stderr, fmt " failed with %d: %s\n\n", ##args, errno, strerror(errno)); exit(1); }
#endif
#endif // _LOGGING_H_

View File

@@ -0,0 +1,75 @@
/* magisk.h - Top header
*/
#ifndef _MAGISK_H_
#define _MAGISK_H_
#include "logging.h"
#define MAGISK_VER_STR xstr(MAGISK_VERSION) ":MAGISK"
#define SOCKET_NAME "d30138f2310a9fb9c54a3e0c21f58591"
#ifndef ARG_MAX
#define ARG_MAX 4096
#endif
#define LOGFILE "/cache/magisk.log"
#define DEBUG_LOG "/data/adb/magisk_debug.log"
#define UNBLOCKFILE "/dev/.magisk.unblock"
#define PATCHDONE "/dev/.magisk.patch.done"
#define DISABLEFILE "/cache/.disable_magisk"
#define UNINSTALLER "/cache/magisk_uninstaller.sh"
#define CACHEMOUNT "/cache/magisk_mount"
#define MAGISKTMP "/sbin/.core"
#define MIRRDIR MAGISKTMP "/mirror"
#define BBPATH MAGISKTMP "/busybox"
#define MOUNTPOINT MAGISKTMP "/img"
#define COREDIR MOUNTPOINT "/.core"
#define HOSTSFILE COREDIR "/hosts"
#define HIDELIST COREDIR "/hidelist"
#define MAINIMG "/data/adb/magisk.img"
#define DATABIN "/data/adb/magisk"
#define MANAGERAPK DATABIN "/magisk.apk"
#define MAGISKRC "/init.magisk.rc"
// selinuxfs paths
#define SELINUX_PATH "/sys/fs/selinux/"
#define SELINUX_ENFORCE SELINUX_PATH "enforce"
#define SELINUX_POLICY SELINUX_PATH "policy"
#define SELINUX_LOAD SELINUX_PATH "load"
// split policy paths
#define PLAT_POLICY_DIR "/system/etc/selinux/"
#define NONPLAT_POLICY_DIR "/vendor/etc/selinux/"
#define SPLIT_PLAT_CIL PLAT_POLICY_DIR "plat_sepolicy.cil"
#define SPLIT_PLAT_MAPPING PLAT_POLICY_DIR "mapping/%s.cil"
#define SPLIT_PRECOMPILE NONPLAT_POLICY_DIR "precompiled_sepolicy"
#define SPLIT_NONPLAT_VER NONPLAT_POLICY_DIR "plat_sepolicy_vers.txt"
#define MAGISKHIDE_PROP "persist.magisk.hide"
extern char *argv0; /* For changing process name */
#define applet ((char *[]) { "su", "resetprop", "magiskhide", NULL })
#define init_applet ((char *[]) { "magiskpolicy", "supolicy", NULL })
extern int (*applet_main[]) (int, char *[]), (*init_applet_main[]) (int, char *[]);
extern char socket_name[]; /* Workaround compiler bug pre NDK r13 */
int create_links(const char *bin, const char *path);
// Multi-call entrypoints
int magiskhide_main(int argc, char *argv[]);
int magiskpolicy_main(int argc, char *argv[]);
int su_client_main(int argc, char *argv[]);
#ifdef __cplusplus
extern "C" {
#endif
int resetprop_main(int argc, char *argv[]);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,44 @@
const char magiskrc[] =
// Triggers
"on post-fs\n"
" start logd\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"
" rm /dev/.magisk.unblock\n"
"\n"
// Services
"service magisk_daemon /sbin/magisk --daemon\n"
" user root\n"
" seclabel u:r:su:s0\n"
" oneshot\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"
;

View File

@@ -0,0 +1,25 @@
/* resetprop.h - API for resetprop
*/
#ifndef _RESETPROP_H_
#define _RESETPROP_H_
#ifdef __cplusplus
extern "C" {
#endif
int prop_exist(const char *name);
int setprop(const char *name, const char *value);
int setprop2(const char *name, const char *value, const int trigger);
char *getprop(const char *name);
char *getprop2(const char *name, int persist);
int deleteprop(const char *name);
int deleteprop2(const char *name, const int persist);
int read_prop_file(const char* filename, const int trigger);
void getprop_all(void (*callback)(const char*, const char*));
#ifdef __cplusplus
}
#endif
#endif

154
native/jni/include/utils.h Normal file
View File

@@ -0,0 +1,154 @@
/* util.h - Header for all utility functions
*/
#ifndef _UTILS_H_
#define _UTILS_H_
#include <stdio.h>
#include <dirent.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include "vector.h"
#define UID_SHELL (get_shell_uid())
#define UID_ROOT 0
#define UID_SYSTEM (get_system_uid())
#define UID_RADIO (get_radio_uid())
// xwrap.c
FILE *xfopen(const char *pathname, const char *mode);
FILE *xfdopen(int fd, const char *mode);
#define GET_MACRO(_1, _2, _3, NAME, ...) NAME
#define xopen(...) GET_MACRO(__VA_ARGS__, xopen3, xopen2)(__VA_ARGS__)
int xopen2(const char *pathname, int flags);
int xopen3(const char *pathname, int flags, mode_t mode);
int xopenat(int dirfd, const char *pathname, int flags);
ssize_t xwrite(int fd, const void *buf, size_t count);
ssize_t xread(int fd, void *buf, size_t count);
ssize_t xxread(int fd, void *buf, size_t count);
int xpipe2(int pipefd[2], int flags);
int xsetns(int fd, int nstype);
DIR *xopendir(const char *name);
DIR *xfdopendir(int fd);
struct dirent *xreaddir(DIR *dirp);
pid_t xsetsid();
int xsocket(int domain, int type, int protocol);
int xbind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
int xconnect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
int xlisten(int sockfd, int backlog);
int xaccept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
void *xmalloc(size_t size);
void *xcalloc(size_t nmemb, size_t size);
void *xrealloc(void *ptr, size_t size);
ssize_t xsendmsg(int sockfd, const struct msghdr *msg, int flags);
ssize_t xrecvmsg(int sockfd, struct msghdr *msg, int flags);
int xpthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
int xsocketpair(int domain, int type, int protocol, int sv[2]);
int xstat(const char *pathname, struct stat *buf);
int xlstat(const char *pathname, struct stat *buf);
int xdup2(int oldfd, int newfd);
ssize_t xreadlink(const char *pathname, char *buf, size_t bufsiz);
ssize_t xreadlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz);
int xsymlink(const char *target, const char *linkpath);
int xmount(const char *source, const char *target,
const char *filesystemtype, unsigned long mountflags,
const void *data);
int xumount(const char *target);
int xumount2(const char *target, int flags);
int xrename(const char *oldpath, const char *newpath);
int xmkdir(const char *pathname, mode_t mode);
int xmkdirs(const char *pathname, mode_t mode);
int xmkdirat(int dirfd, const char *pathname, mode_t mode);
void *xmmap(void *addr, size_t length, int prot, int flags,
int fd, off_t offset);
ssize_t xsendfile(int out_fd, int in_fd, off_t *offset, size_t count);
pid_t xfork();
// misc.c
#define quit_signals ((int []) { SIGALRM, SIGABRT, SIGHUP, SIGPIPE, SIGQUIT, SIGTERM, SIGINT, 0 })
unsigned get_shell_uid();
unsigned get_system_uid();
unsigned get_radio_uid();
int check_data();
int file_to_vector(const char* filename, struct vector *v);
int vector_to_file(const char* filename, struct vector *v);
ssize_t fdgets(char *buf, size_t size, int fd);
void ps(void (*func)(int));
void ps_filter_proc_name(const char *filter, void (*func)(int));
void unlock_blocks();
void setup_sighandlers(void (*handler)(int));
int exec_command(int err, int *fd, void (*setupenv)(struct vector*), const char *argv0, ...);
int exec_command_sync(char *const argv0, ...);
int bind_mount(const char *from, const char *to);
void get_client_cred(int fd, struct ucred *cred);
int switch_mnt_ns(int pid);
int fork_dont_care();
void wait_till_exists(const char *target);
void gen_rand_str(char *buf, int len);
// file.c
#define align(p, a) (((p) + (a) - 1) / (a) * (a))
#define align_off(p, a) (align(p, a) - (p))
extern char **excl_list;
struct file_attr {
struct stat st;
char con[128];
};
int fd_getpath(int fd, char *path, size_t size);
int mkdirs(const char *pathname, mode_t mode);
void in_order_walk(int dirfd, void (*callback)(int, struct dirent*));
void rm_rf(const char *path);
void frm_rf(int dirfd);
void mv_f(const char *source, const char *destination);
void mv_dir(int src, int dest);
void cp_afc(const char *source, const char *destination);
void link_dir(int src, int dest);
void clone_dir(int src, int dest);
int getattr(const char *path, struct file_attr *a);
int getattrat(int dirfd, const char *pathname, struct file_attr *a);
int fgetattr(int fd, struct file_attr *a);
int setattr(const char *path, struct file_attr *a);
int setattrat(int dirfd, const char *pathname, struct file_attr *a);
int fsetattr(int fd, struct file_attr *a);
void fclone_attr(const int sourcefd, const int targetfd);
void clone_attr(const char *source, const char *target);
void restorecon(int dirfd, int force);
int mmap_ro(const char *filename, void **buf, size_t *size);
int mmap_rw(const char *filename, void **buf, size_t *size);
void fd_full_read(int fd, void **buf, size_t *size);
void full_read(const char *filename, void **buf, size_t *size);
void full_read_at(int dirfd, const char *filename, void **buf, size_t *size);
void stream_full_read(int fd, void **buf, size_t *size);
void write_zero(int fd, size_t size);
// img.c
#define round_size(a) ((((a) / 32) + 2) * 32)
#define SOURCE_TMP "/dev/source"
#define TARGET_TMP "/dev/target"
int create_img(const char *img, int size);
int get_img_size(const char *img, int *used, int *total);
int resize_img(const char *img, int size);
char *mount_image(const char *img, const char *target);
void umount_image(const char *target, const char *device);
int merge_img(const char *source, const char *target);
void trim_img(const char *img);
// pattern.c
void patch_init_rc(void **buf, size_t *size);
int patch_verity(void **buf, uint32_t *size, int patch);
void patch_encryption(void **buf, uint32_t *size);
#endif

View File

@@ -0,0 +1,37 @@
/* vector.h - A simple vector implementation in c
*/
#ifndef _VECTOR_H_
#define _VECTOR_H_
#include <sys/types.h>
struct vector {
unsigned size;
unsigned cap;
void **data;
};
void vec_init(struct vector *v);
void vec_push_back(struct vector *v, void *p);
void *vec_pop_back(struct vector *v);
void vec_sort(struct vector *v, int (*compar)(const void *, const void *));
void vec_destroy(struct vector *v);
void vec_deep_destroy(struct vector *v);
struct vector *vec_dup(struct vector *v);
#define vec_size(v) (v)->size
#define vec_cap(v) (v)->cap
#define vec_entry(v) (v)->data
/* Usage: vec_for_each(vector *v, void *e) */
#define vec_for_each(v, e) \
e = v ? (v)->data[0] : NULL; \
for (int _ = 0; v && _ < (v)->size; ++_, e = (v)->data[_])
#define vec_for_each_r(v, e) \
e = (v && (v)->size > 0) ? (v)->data[(v)->size - 1] : NULL; \
for (int _ = ((int) (v)->size) - 1; v && _ >= 0; --_, e = (v)->data[_])
#define vec_cur(v) vec_entry(v)[_]
#endif

View File

@@ -0,0 +1,431 @@
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "bootimg.h"
#include "magiskboot.h"
#include "utils.h"
#include "logging.h"
#include "mincrypt/sha.h"
#include "mincrypt/sha256.h"
#define INSUF_BLOCK_RET 2
#define CHROMEOS_RET 3
#define ELF32_RET 4
#define ELF64_RET 5
// Macros to determine header on-the-go
#define lheader(b, e, o) \
((b)->flags & PXA_FLAG) ? \
(((struct pxa_boot_img_hdr*) (b)->hdr)->e o) : \
(((struct boot_img_hdr*) (b)->hdr)->e o)
#define header(b, e) (lheader(b, e,))
static void dump(void *buf, size_t size, const char *filename) {
if (size == 0)
return;
int fd = creat(filename, 0644);
xwrite(fd, buf, size);
close(fd);
}
static size_t restore(const char *filename, int fd) {
int ifd = xopen(filename, O_RDONLY);
size_t size = lseek(ifd, 0, SEEK_END);
lseek(ifd, 0, SEEK_SET);
xsendfile(fd, ifd, NULL, size);
close(ifd);
return size;
}
static void restore_buf(int fd, const void *buf, size_t size) {
xwrite(fd, buf, size);
}
static void print_hdr(const boot_img *boot) {
fprintf(stderr, "KERNEL [%u]\n", header(boot, kernel_size));
fprintf(stderr, "RAMDISK [%u]\n", header(boot, ramdisk_size));
fprintf(stderr, "SECOND [%u]\n", header(boot, second_size));
fprintf(stderr, "EXTRA [%u]\n", header(boot, extra_size));
fprintf(stderr, "PAGESIZE [%u]\n", header(boot, page_size));
if (!(boot->flags & PXA_FLAG)) {
uint32_t os_version = ((boot_img_hdr*) boot->hdr)->os_version;
if (os_version) {
int a,b,c,y,m = 0;
int version, patch_level;
version = os_version >> 11;
patch_level = os_version & 0x7ff;
a = (version >> 14) & 0x7f;
b = (version >> 7) & 0x7f;
c = version & 0x7f;
fprintf(stderr, "OS_VERSION [%d.%d.%d]\n", a, b, c);
y = (patch_level >> 4) + 2000;
m = patch_level & 0xf;
fprintf(stderr, "PATCH_LEVEL [%d-%02d]\n", y, m);
}
}
fprintf(stderr, "NAME [%s]\n", header(boot, name));
fprintf(stderr, "CMDLINE [%s]\n", header(boot, cmdline));
fprintf(stderr, "CHECKSUM [");
for (int i = 0; i < ((boot->flags & SHA256_FLAG) ? SHA256_DIGEST_SIZE : SHA_DIGEST_SIZE); ++i)
fprintf(stderr, "%02x", header(boot, id)[i]);
fprintf(stderr, "]\n");
}
static void clean_boot(boot_img *boot) {
munmap(boot->map_addr, boot->map_size);
free(boot->hdr);
free(boot->k_hdr);
free(boot->r_hdr);
free(boot->b_hdr);
memset(boot, 0, sizeof(*boot));
}
#define pos_align() pos = align(pos, header(boot, page_size))
int parse_img(const char *image, boot_img *boot) {
memset(boot, 0, sizeof(*boot));
int is_blk = mmap_ro(image, &boot->map_addr, &boot->map_size);
// Parse image
fprintf(stderr, "Parsing boot image: [%s]\n", image);
for (void *head = boot->map_addr; head < boot->map_addr + boot->map_size; ++head) {
size_t pos = 0;
switch (check_fmt(head, boot->map_size)) {
case CHROMEOS:
// The caller should know it's chromeos, as it needs additional signing
boot->flags |= CHROMEOS_FLAG;
continue;
case DHTB:
boot->flags |= DHTB_FLAG;
boot->flags |= SEANDROID_FLAG;
fprintf(stderr, "DHTB_HDR\n");
continue;
case ELF32:
exit(ELF32_RET);
case ELF64:
exit(ELF64_RET);
case BLOB:
boot->flags |= BLOB_FLAG;
fprintf(stderr, "TEGRA_BLOB\n");
boot->b_hdr = malloc(sizeof(blob_hdr));
memcpy(boot->b_hdr, head, sizeof(blob_hdr));
continue;
case AOSP:
// Read the header
if (((boot_img_hdr*) head)->page_size >= 0x02000000) {
boot->flags |= PXA_FLAG;
fprintf(stderr, "PXA_BOOT_HDR\n");
boot->hdr = malloc(sizeof(pxa_boot_img_hdr));
memcpy(boot->hdr, head, sizeof(pxa_boot_img_hdr));
} else if (memcmp(((boot_img_hdr*) head)->cmdline, NOOKHD_MAGIC, 12) == 0
|| memcmp(((boot_img_hdr*) head)->cmdline, NOOKHD_NEW_MAGIC, 26) == 0) {
boot->flags |= NOOKHD_FLAG;
fprintf(stderr, "NOOKHD_GREEN_LOADER\n");
head += NOOKHD_PRE_HEADER_SZ - 1;
continue;
} else if (memcmp(((boot_img_hdr*) head)->name, ACCLAIM_MAGIC, 10) == 0) {
boot->flags |= ACCLAIM_FLAG;
fprintf(stderr, "ACCLAIM_BAUWKSBOOT\n");
head += ACCLAIM_PRE_HEADER_SZ - 1;
continue;
} else {
boot->hdr = malloc(sizeof(boot_img_hdr));
memcpy(boot->hdr, head, sizeof(boot_img_hdr));
}
pos += header(boot, page_size);
for (int i = SHA_DIGEST_SIZE; i < SHA256_DIGEST_SIZE; ++i) {
if (header(boot, id)[i]) {
boot->flags |= SHA256_FLAG;
break;
}
}
print_hdr(boot);
boot->kernel = head + pos;
pos += header(boot, kernel_size);
pos_align();
boot->ramdisk = head + pos;
pos += header(boot, ramdisk_size);
pos_align();
boot->second = head + pos;
pos += header(boot, second_size);
pos_align();
boot->extra = head + pos;
pos += header(boot, extra_size);
pos_align();
if (pos < boot->map_size) {
boot->tail = head + pos;
boot->tail_size = boot->map_size - pos;
}
// Check tail info, currently only for LG Bump and Samsung SEANDROIDENFORCE
if (boot->tail_size >= 16 && memcmp(boot->tail, SEANDROID_MAGIC, 16) == 0) {
boot->flags |= SEANDROID_FLAG;
} else if (boot->tail_size >= 16 && memcmp(boot->tail, LG_BUMP_MAGIC, 16) == 0) {
boot->flags |= LG_BUMP_FLAG;
}
// Search for dtb in kernel
for (uint32_t i = 0; i < header(boot, kernel_size); ++i) {
if (memcmp(boot->kernel + i, DTB_MAGIC, 4) == 0) {
boot->dtb = boot->kernel + i;
boot->dt_size = header(boot, kernel_size) - i;
lheader(boot, kernel_size, = i);
fprintf(stderr, "DTB [%u]\n", boot->dt_size);
break;
}
}
boot->k_fmt = check_fmt(boot->kernel, header(boot, kernel_size));
boot->r_fmt = check_fmt(boot->ramdisk, header(boot, ramdisk_size));
// Check MTK
if (boot->k_fmt == MTK) {
fprintf(stderr, "MTK_KERNEL_HDR\n");
boot->flags |= MTK_KERNEL;
boot->k_hdr = malloc(sizeof(mtk_hdr));
memcpy(boot->k_hdr, boot->kernel, sizeof(mtk_hdr));
fprintf(stderr, "KERNEL [%u]\n", boot->k_hdr->size);
fprintf(stderr, "NAME [%s]\n", boot->k_hdr->name);
boot->kernel += 512;
lheader(boot, kernel_size, -= 512);
boot->k_fmt = check_fmt(boot->kernel, header(boot, kernel_size));
}
if (boot->r_fmt == MTK) {
fprintf(stderr, "MTK_RAMDISK_HDR\n");
boot->flags |= MTK_RAMDISK;
boot->r_hdr = malloc(sizeof(mtk_hdr));
memcpy(boot->r_hdr, boot->ramdisk, sizeof(mtk_hdr));
fprintf(stderr, "RAMDISK [%u]\n", boot->r_hdr->size);
fprintf(stderr, "NAME [%s]\n", boot->r_hdr->name);
boot->ramdisk += 512;
lheader(boot, ramdisk_size, -= 512);
boot->r_fmt = check_fmt(boot->ramdisk, header(boot, ramdisk_size));
}
char fmt[16];
get_fmt_name(boot->k_fmt, fmt);
fprintf(stderr, "KERNEL_FMT [%s]\n", fmt);
get_fmt_name(boot->r_fmt, fmt);
fprintf(stderr, "RAMDISK_FMT [%s]\n", fmt);
return boot->flags & CHROMEOS_FLAG ? CHROMEOS_RET :
((is_blk && boot->tail_size < 500 * 1024) ? INSUF_BLOCK_RET : 0);
default:
continue;
}
}
LOGE("No boot image magic found!\n");
}
int unpack(const char *image) {
boot_img boot;
int ret = parse_img(image, &boot);
int fd;
// Dump kernel
if (COMPRESSED(boot.k_fmt)) {
fd = creat(KERNEL_FILE, 0644);
decomp(boot.k_fmt, fd, boot.kernel, header(&boot, kernel_size));
close(fd);
} else {
dump(boot.kernel, header(&boot, kernel_size), KERNEL_FILE);
}
// Dump dtb
dump(boot.dtb, boot.dt_size, DTB_FILE);
// Dump ramdisk
if (COMPRESSED(boot.r_fmt)) {
fd = creat(RAMDISK_FILE, 0644);
decomp(boot.r_fmt, fd, boot.ramdisk, header(&boot, ramdisk_size));
close(fd);
} else {
dump(boot.ramdisk, header(&boot, ramdisk_size), RAMDISK_FILE);
}
// Dump second
dump(boot.second, header(&boot, second_size), SECOND_FILE);
// Dump extra
dump(boot.extra, header(&boot, extra_size), EXTRA_FILE);
clean_boot(&boot);
return ret;
}
#define file_align() write_zero(fd, align_off(lseek(fd, 0, SEEK_CUR) - header_off, header(&boot, page_size)))
void repack(const char* orig_image, const char* out_image) {
boot_img boot;
off_t header_off, kernel_off, ramdisk_off, second_off, extra_off;
// Parse original image
parse_img(orig_image, &boot);
// Reset all sizes
lheader(&boot, kernel_size, = 0);
lheader(&boot, ramdisk_size, = 0);
lheader(&boot, second_size, = 0);
lheader(&boot, extra_size, = 0);
boot.dt_size = 0;
fprintf(stderr, "Repack to boot image: [%s]\n", out_image);
// Create new image
int fd = creat(out_image, 0644);
if (boot.flags & DHTB_FLAG) {
// Skip DHTB header
write_zero(fd, 512);
} else if (boot.flags & BLOB_FLAG) {
// Skip blob header
write_zero(fd, sizeof(blob_hdr));
} else if (boot.flags & NOOKHD_FLAG) {
restore_buf(fd, boot.map_addr, NOOKHD_PRE_HEADER_SZ);
} else if (boot.flags & ACCLAIM_FLAG) {
restore_buf(fd, boot.map_addr, ACCLAIM_PRE_HEADER_SZ);
}
// Skip a page for header
header_off = lseek(fd, 0, SEEK_CUR);
write_zero(fd, header(&boot, page_size));
// kernel
kernel_off = lseek(fd, 0, SEEK_CUR);
if (boot.flags & MTK_KERNEL) {
// Skip MTK header
write_zero(fd, 512);
}
if (access(KERNEL_FILE, R_OK) == 0) {
if (COMPRESSED(boot.k_fmt)) {
size_t raw_size;
void *kernel_raw;
mmap_ro(KERNEL_FILE, &kernel_raw, &raw_size);
lheader(&boot, kernel_size, = comp(boot.k_fmt, fd, kernel_raw, raw_size));
munmap(kernel_raw, raw_size);
} else {
lheader(&boot, kernel_size, = restore(KERNEL_FILE, fd));
}
}
// dtb
if (access(DTB_FILE, R_OK) == 0) {
lheader(&boot, kernel_size, += restore(DTB_FILE, fd));
}
file_align();
// ramdisk
ramdisk_off = lseek(fd, 0, SEEK_CUR);
if (boot.flags & MTK_RAMDISK) {
// Skip MTK header
write_zero(fd, 512);
}
if (access(RAMDISK_FILE, R_OK) == 0) {
if (COMPRESSED(boot.r_fmt)) {
size_t cpio_size;
void *cpio;
mmap_ro(RAMDISK_FILE, &cpio, &cpio_size);
lheader(&boot, ramdisk_size, = comp(boot.r_fmt, fd, cpio, cpio_size));
munmap(cpio, cpio_size);
} else {
lheader(&boot, ramdisk_size, = restore(RAMDISK_FILE, fd));
}
file_align();
}
// second
second_off = lseek(fd, 0, SEEK_CUR);
if (access(SECOND_FILE, R_OK) == 0) {
lheader(&boot, second_size, = restore(SECOND_FILE, fd));
file_align();
}
// extra
extra_off = lseek(fd, 0, SEEK_CUR);
if (access(EXTRA_FILE, R_OK) == 0) {
lheader(&boot, extra_size, = restore(EXTRA_FILE, fd));
file_align();
}
// Append tail info
if (boot.flags & SEANDROID_FLAG) {
restore_buf(fd, SEANDROID_MAGIC "\xFF\xFF\xFF\xFF", 20);
}
if (boot.flags & LG_BUMP_FLAG) {
restore_buf(fd, LG_BUMP_MAGIC, 16);
}
close(fd);
// Map output image as rw
munmap(boot.map_addr, boot.map_size);
mmap_rw(out_image, &boot.map_addr, &boot.map_size);
// MTK headers
if (boot.flags & MTK_KERNEL) {
boot.k_hdr->size = header(&boot, kernel_size);
lheader(&boot, kernel_size, += 512);
memcpy(boot.map_addr + kernel_off, boot.k_hdr, sizeof(mtk_hdr));
}
if (boot.flags & MTK_RAMDISK) {
boot.r_hdr->size = header(&boot, ramdisk_size);
lheader(&boot, ramdisk_size, += 512);
memcpy(boot.map_addr + ramdisk_off, boot.r_hdr, sizeof(mtk_hdr));
}
// Update checksum
HASH_CTX ctx;
(boot.flags & SHA256_FLAG) ? SHA256_init(&ctx) : SHA_init(&ctx);
uint32_t size = header(&boot, kernel_size);
HASH_update(&ctx, boot.map_addr + kernel_off, size);
HASH_update(&ctx, &size, sizeof(size));
size = header(&boot, ramdisk_size);
HASH_update(&ctx, boot.map_addr + ramdisk_off, size);
HASH_update(&ctx, &size, sizeof(size));
size = header(&boot, second_size);
HASH_update(&ctx, boot.map_addr + second_off, size);
HASH_update(&ctx, &size, sizeof(size));
size = header(&boot, extra_size);
if (size) {
HASH_update(&ctx, boot.map_addr + extra_off, size);
HASH_update(&ctx, &size, sizeof(size));
}
memset(header(&boot, id), 0, 32);
memcpy(header(&boot, id), HASH_final(&ctx),
(boot.flags & SHA256_FLAG) ? SHA256_DIGEST_SIZE : SHA_DIGEST_SIZE);
// Print new image info
print_hdr(&boot);
// Main header
memcpy(boot.map_addr + header_off, boot.hdr,
(boot.flags & PXA_FLAG) ? sizeof(pxa_boot_img_hdr) : sizeof(boot_img_hdr));
if (boot.flags & DHTB_FLAG) {
// DHTB header
dhtb_hdr *hdr = boot.map_addr;
memcpy(hdr, DHTB_MAGIC, 8);
hdr->size = boot.map_size - 512;
SHA256_hash(boot.map_addr + 512, hdr->size, hdr->checksum);
} else if (boot.flags & BLOB_FLAG) {
// Blob headers
boot.b_hdr->size = boot.map_size - sizeof(blob_hdr);
memcpy(boot.map_addr, boot.b_hdr, sizeof(blob_hdr));
}
clean_boot(&boot);
}

View File

@@ -0,0 +1,169 @@
#include <stdint.h>
#include "format.h"
#ifndef _BOOT_IMAGE_H_
#define _BOOT_IMAGE_H_
typedef struct boot_img_hdr {
char magic[8];
uint32_t kernel_size; /* size in bytes */
uint32_t kernel_addr; /* physical load addr */
uint32_t ramdisk_size; /* size in bytes */
uint32_t ramdisk_addr; /* physical load addr */
uint32_t second_size; /* size in bytes */
uint32_t second_addr; /* physical load addr */
uint32_t tags_addr; /* physical addr for kernel tags */
uint32_t page_size; /* flash page size we assume */
uint32_t extra_size; /* extra blob size in bytes */
/* operating system version and security patch level; for
* version "A.B.C" and patch level "Y-M-D":
* ver = A << 14 | B << 7 | C (7 bits for each of A, B, C)
* lvl = ((Y - 2000) & 127) << 4 | M (7 bits for Y, 4 bits for M)
* os_version = ver << 11 | lvl */
uint32_t os_version;
char name[16]; /* asciiz product name */
char cmdline[512];
char id[32]; /* timestamp / checksum / sha1 / etc */
/* Supplemental command line data; kept here to maintain
* binary compatibility with older versions of mkbootimg */
char extra_cmdline[1024];
} __attribute__((packed)) boot_img_hdr ;
typedef struct pxa_boot_img_hdr {
char magic[8];
uint32_t kernel_size; /* size in bytes */
uint32_t kernel_addr; /* physical load addr */
uint32_t ramdisk_size; /* size in bytes */
uint32_t ramdisk_addr; /* physical load addr */
uint32_t second_size; /* size in bytes */
uint32_t second_addr; /* physical load addr */
uint32_t extra_size; /* extra blob size in bytes */
uint32_t unknown; /* unknown value */
uint32_t tags_addr; /* physical addr for kernel tags */
uint32_t page_size; /* flash page size we assume */
char name[24]; /* asciiz product name */
char cmdline[512];
char id[32]; /* timestamp / checksum / sha1 / etc */
/* Supplemental command line data; kept here to maintain
* binary compatibility with older versions of mkbootimg */
char extra_cmdline[1024];
} __attribute__((packed)) pxa_boot_img_hdr;
/*
** +-----------------+
** | boot header | 1 page
** +-----------------+
** | kernel | n pages
** +-----------------+
** | ramdisk | m pages
** +-----------------+
** | second stage | o pages
** +-----------------+
** | extra blob | p pages
** +-----------------+
**
** n = (kernel_size + page_size - 1) / page_size
** m = (ramdisk_size + page_size - 1) / page_size
** o = (second_size + page_size - 1) / page_size
** p = (extra_size + page_size - 1) / page_size
**
** 0. all entities are page_size aligned in flash
** 1. kernel and ramdisk are required (size != 0)
** 2. second is optional (second_size == 0 -> no second)
** 3. load each element (kernel, ramdisk, second) at
** the specified physical address (kernel_addr, etc)
** 4. prepare tags at tag_addr. kernel_args[] is
** appended to the kernel commandline in the tags.
** 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr
** 6. if second_size != 0: jump to second_addr
** else: jump to kernel_addr
*/
typedef struct mtk_hdr {
uint32_t magic; /* MTK magic */
uint32_t size; /* Size of the content */
char name[32]; /* The type of the header */
} __attribute__((packed)) mtk_hdr;
typedef struct dhtb_hdr {
char magic[8]; /* DHTB magic */
char checksum[40]; /* Payload SHA256, whole image + SEANDROIDENFORCE + 0xFFFFFFFF */
uint32_t size; /* Payload size, whole image + SEANDROIDENFORCE + 0xFFFFFFFF */
} __attribute__((packed)) dhtb_hdr;
typedef struct blob_hdr {
char secure_magic[20]; /* "-SIGNED-BY-SIGNBLOB-" */
uint32_t datalen; /* 0x00000000 */
uint32_t signature; /* 0x00000000 */
char magic[16]; /* "MSM-RADIO-UPDATE" */
uint32_t hdr_version; /* 0x00010000 */
uint32_t hdr_size; /* Size of header */
uint32_t part_offset; /* Same as size */
uint32_t num_parts; /* Number of partitions */
uint32_t unknown[7]; /* All 0x00000000 */
char name[4]; /* Name of partition */
uint32_t offset; /* offset in blob where this partition starts */
uint32_t size; /* Size of data */
uint32_t version; /* 0x00000001 */
} __attribute__((packed)) blob_hdr;
// Flags
#define MTK_KERNEL 0x0001
#define MTK_RAMDISK 0x0002
#define CHROMEOS_FLAG 0x0004
#define PXA_FLAG 0x0008
#define DHTB_FLAG 0x0010
#define SEANDROID_FLAG 0x0020
#define LG_BUMP_FLAG 0x0040
#define SHA256_FLAG 0x0080
#define BLOB_FLAG 0x0100
#define NOOKHD_FLAG 0x0200
#define ACCLAIM_FLAG 0x0400
typedef struct boot_img {
// Memory map of the whole image
void *map_addr;
size_t map_size;
// Headers
void *hdr; /* Either boot_img_hdr or pxa_boot_img_hdr */
mtk_hdr *k_hdr; /* MTK kernel header */
mtk_hdr *r_hdr; /* MTK ramdisk header */
blob_hdr *b_hdr; /* Tegra blob header */
// Flags to indicate the state of current boot image
uint16_t flags;
// The format of kernel and ramdisk
format_t k_fmt;
format_t r_fmt;
// Pointer to dtb that is appended after kernel
void *dtb;
uint32_t dt_size;
// Pointer to end of image
void *tail;
size_t tail_size;
// Pointers to blocks defined in header
void *kernel;
void *ramdisk;
void *second;
void *extra;
} boot_img;
#endif

View File

@@ -0,0 +1,512 @@
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <zlib.h>
#include <lzma.h>
#include <lz4.h>
#include <lz4frame.h>
#include <lz4hc.h>
#include <bzlib.h>
#include "magiskboot.h"
#include "logging.h"
#include "utils.h"
#define CHUNK 0x40000
// Mode: 0 = decode; 1 = encode
size_t gzip(int mode, int fd, const void *buf, size_t size) {
size_t ret = 0, have, total = 0;
z_stream strm;
unsigned char out[CHUNK];
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
switch(mode) {
case 0:
ret = inflateInit2(&strm, 15 | 16);
break;
case 1:
ret = deflateInit2(&strm, 9, Z_DEFLATED, 15 | 16, 8, Z_DEFAULT_STRATEGY);
break;
}
if (ret != Z_OK)
LOGE("Unable to init zlib stream\n");
strm.next_in = (void *) buf;
strm.avail_in = size;
do {
strm.avail_out = CHUNK;
strm.next_out = out;
switch(mode) {
case 0:
ret = inflate(&strm, Z_FINISH);
break;
case 1:
ret = deflate(&strm, Z_FINISH);
break;
}
if (ret == Z_STREAM_ERROR)
LOGE("Error when running gzip\n");
have = CHUNK - strm.avail_out;
total += xwrite(fd, out, have);
} while (strm.avail_out == 0);
switch(mode) {
case 0:
inflateEnd(&strm);
break;
case 1:
deflateEnd(&strm);
break;
}
return total;
}
// Mode: 0 = decode xz/lzma; 1 = encode xz; 2 = encode lzma
size_t lzma(int mode, int fd, const void *buf, size_t size) {
size_t have, total = 0;
lzma_ret ret = 0;
lzma_stream strm = LZMA_STREAM_INIT;
lzma_options_lzma opt;
unsigned char out[CHUNK];
// Initialize preset
lzma_lzma_preset(&opt, 9);
lzma_filter filters[] = {
{ .id = LZMA_FILTER_LZMA2, .options = &opt },
{ .id = LZMA_VLI_UNKNOWN, .options = NULL },
};
switch(mode) {
case 0:
ret = lzma_auto_decoder(&strm, UINT64_MAX, 0);
break;
case 1:
ret = lzma_stream_encoder(&strm, filters, LZMA_CHECK_CRC32);
break;
case 2:
ret = lzma_alone_encoder(&strm, &opt);
break;
}
if (ret != LZMA_OK)
LOGE("Unable to init lzma stream\n");
strm.next_in = buf;
strm.avail_in = size;
do {
strm.avail_out = CHUNK;
strm.next_out = out;
ret = lzma_code(&strm, LZMA_FINISH);
if (ret != LZMA_OK && ret != LZMA_STREAM_END)
LOGE("LZMA error %d!\n", ret);
have = CHUNK - strm.avail_out;
total += xwrite(fd, out, have);
} while (strm.avail_out == 0);
lzma_end(&strm);
return total;
}
// Mode: 0 = decode; 1 = encode
size_t lz4(int mode, int fd, const void *buf, size_t size) {
LZ4F_decompressionContext_t dctx;
LZ4F_compressionContext_t cctx;
LZ4F_frameInfo_t info;
size_t blockSize, outCapacity, avail_in, ret = 0, pos = 0, total = 0;
size_t have, read;
void *out = NULL;
// Initialize context
switch(mode) {
case 0:
ret = LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION);
break;
case 1:
ret = LZ4F_createCompressionContext(&cctx, LZ4F_VERSION);
break;
}
if (LZ4F_isError(ret))
LOGE("Context creation error: %s\n", LZ4F_getErrorName(ret));
// Allocate out buffer
blockSize = 1 << 22;
switch(mode) {
case 0:
// Read header
read = blockSize;
ret = LZ4F_getFrameInfo(dctx, &info, buf, &read);
if (LZ4F_isError(ret))
LOGE("LZ4F_getFrameInfo error: %s\n", LZ4F_getErrorName(ret));
switch (info.blockSizeID) {
case LZ4F_default:
case LZ4F_max64KB: outCapacity = 1 << 16; break;
case LZ4F_max256KB: outCapacity = 1 << 18; break;
case LZ4F_max1MB: outCapacity = 1 << 20; break;
case LZ4F_max4MB: outCapacity = 1 << 22; break;
default:
LOGE("Impossible unless more block sizes are allowed\n");
}
pos += read;
break;
case 1:
outCapacity = LZ4F_compressFrameBound(blockSize, NULL);
break;
}
out = xmalloc(outCapacity);
// Write header
if (mode == 1) {
LZ4F_preferences_t prefs;
memset(&prefs, 0, sizeof(prefs));
prefs.autoFlush = 1;
prefs.compressionLevel = 9;
prefs.frameInfo.blockMode = 1;
prefs.frameInfo.blockSizeID = 7;
prefs.frameInfo.contentChecksumFlag = 1;
have = ret = LZ4F_compressBegin(cctx, out, size, &prefs);
if (LZ4F_isError(ret))
LOGE("Failed to start compression: error %s\n", LZ4F_getErrorName(ret));
total += xwrite(fd, out, have);
}
do {
if (pos + blockSize >= size) {
avail_in = size - pos;
} else {
avail_in = blockSize;
}
do {
switch(mode) {
case 0:
have = outCapacity;
read = avail_in;
ret = LZ4F_decompress(dctx, out, &have, buf + pos, &read, NULL);
break;
case 1:
read = avail_in;
have = ret = LZ4F_compressUpdate(cctx, out, outCapacity, buf + pos, avail_in, NULL);
break;
}
if (LZ4F_isError(ret))
LOGE("LZ4 coding error: %s\n", LZ4F_getErrorName(ret));
total += xwrite(fd, out, have);
// Update status
pos += read;
avail_in -= read;
} while(avail_in != 0 && ret != 0);
} while(pos < size && ret != 0);
switch(mode) {
case 0:
LZ4F_freeDecompressionContext(dctx);
break;
case 1:
have = ret = LZ4F_compressEnd(cctx, out, outCapacity, NULL);
if (LZ4F_isError(ret))
LOGE("Failed to end compression: error %s\n", LZ4F_getErrorName(ret));
total += xwrite(fd, out, have);
LZ4F_freeCompressionContext(cctx);
break;
}
free(out);
return total;
}
// Mode: 0 = decode; 1 = encode
size_t bzip2(int mode, int fd, const void* buf, size_t size) {
size_t ret = 0, have, total = 0;
bz_stream strm;
char out[CHUNK];
strm.bzalloc = NULL;
strm.bzfree = NULL;
strm.opaque = NULL;
switch(mode) {
case 0:
ret = BZ2_bzDecompressInit(&strm, 0, 0);
break;
case 1:
ret = BZ2_bzCompressInit(&strm, 9, 0, 0);
break;
}
if (ret != BZ_OK)
LOGE("Unable to init bzlib stream\n");
strm.next_in = (void *) buf;
strm.avail_in = size;
do {
strm.avail_out = CHUNK;
strm.next_out = out;
switch(mode) {
case 0:
ret = BZ2_bzDecompress(&strm);
break;
case 1:
ret = BZ2_bzCompress(&strm, BZ_FINISH);
break;
}
have = CHUNK - strm.avail_out;
total += xwrite(fd, out, have);
} while (strm.avail_out == 0);
switch(mode) {
case 0:
BZ2_bzDecompressEnd(&strm);
break;
case 1:
BZ2_bzCompressEnd(&strm);
break;
}
return total;
}
#define LZ4_LEGACY_BLOCKSIZE 0x800000
// Mode: 0 = decode; 1 = encode
size_t lz4_legacy(int mode, int fd, const void* buf, size_t size) {
size_t pos = 0;
int have;
char *out;
unsigned block_size, insize, total = 0;
switch(mode) {
case 0:
out = xmalloc(LZ4_LEGACY_BLOCKSIZE);
// Skip magic
pos += 4;
break;
case 1:
out = xmalloc(LZ4_COMPRESSBOUND(LZ4_LEGACY_BLOCKSIZE));
// Write magic
total += xwrite(fd, "\x02\x21\x4c\x18", 4);
break;
}
do {
switch(mode) {
case 0:
// Read block size
block_size = *(unsigned *)(buf + pos);
pos += 4;
if (block_size > LZ4_COMPRESSBOUND(LZ4_LEGACY_BLOCKSIZE))
goto done;
have = LZ4_decompress_safe(buf + pos, out, block_size, LZ4_LEGACY_BLOCKSIZE);
if (have < 0)
LOGE("Cannot decode lz4_legacy block\n");
pos += block_size;
break;
case 1:
if (pos + LZ4_LEGACY_BLOCKSIZE >= size)
insize = size - pos;
else
insize = LZ4_LEGACY_BLOCKSIZE;
have = LZ4_compress_HC(buf + pos, out, insize, LZ4_COMPRESSBOUND(LZ4_LEGACY_BLOCKSIZE), 9);
if (have == 0)
LOGE("lz4_legacy compression error\n");
pos += insize;
// Write block size
total += xwrite(fd, &have, sizeof(have));
break;
}
// Write main data
total += xwrite(fd, out, have);
} while(pos < size);
done:
if (mode == 1) {
// Append original size to output
unsigned uncomp = size;
xwrite(fd, &uncomp, sizeof(uncomp));
}
free(out);
return total;
}
long long decomp(format_t type, int to, const void *from, size_t size) {
switch (type) {
case GZIP:
return gzip(0, to, from, size);
case XZ:
return lzma(0, to, from, size);
case LZMA:
return lzma(0, to, from, size);
case BZIP2:
return bzip2(0, to, from, size);
case LZ4:
return lz4(0, to, from, size);
case LZ4_LEGACY:
return lz4_legacy(0, to, from, size);
default:
// Unsupported
return -1;
}
}
long long comp(format_t type, int to, const void *from, size_t size) {
switch (type) {
case GZIP:
return gzip(1, to, from, size);
case XZ:
return lzma(1, to, from, size);
case LZMA:
return lzma(2, to, from, size);
case BZIP2:
return bzip2(1, to, from, size);
case LZ4:
return lz4(1, to, from, size);
case LZ4_LEGACY:
return lz4_legacy(1, to, from, size);
default:
// Unsupported
return -1;
}
}
/*
* Below are utility functions for commandline
*/
void decomp_file(char *from, const char *to) {
int strip = 1;
void *file;
size_t size = 0;
if (strcmp(from, "-") == 0)
stream_full_read(STDIN_FILENO, &file, &size);
else
mmap_ro(from, &file, &size);
format_t type = check_fmt(file, size);
char *ext;
ext = strrchr(from, '.');
if (to == NULL)
to = from;
if (ext != NULL) {
// Strip out a matched file extension
switch (type) {
case GZIP:
if (strcmp(ext, ".gz") != 0)
strip = 0;
break;
case XZ:
if (strcmp(ext, ".xz") != 0)
strip = 0;
break;
case LZMA:
if (strcmp(ext, ".lzma") != 0)
strip = 0;
break;
case BZIP2:
if (strcmp(ext, ".bz2") != 0)
strip = 0;
break;
case LZ4_LEGACY:
case LZ4:
if (strcmp(ext, ".lz4") != 0)
strip = 0;
break;
default:
LOGE("Provided file \'%s\' is not a supported archive format\n", from);
}
if (strip)
*ext = '\0';
}
int fd;
if (strcmp(to, "-") == 0) {
fd = STDOUT_FILENO;
} else {
fd = creat(to, 0644);
fprintf(stderr, "Decompressing to [%s]\n", to);
}
decomp(type, fd, file, size);
close(fd);
if (to == from && ext != NULL) {
*ext = '.';
unlink(from);
}
if (strcmp(from, "-") == 0)
free(file);
else
munmap(file, size);
}
void comp_file(const char *method, const char *from, const char *to) {
format_t type;
char *ext, dest[PATH_MAX];
if (strcmp(method, "gzip") == 0) {
type = GZIP;
ext = "gz";
} else if (strcmp(method, "xz") == 0) {
type = XZ;
ext = "xz";
} else if (strcmp(method, "lzma") == 0) {
type = LZMA;
ext = "lzma";
} else if (strcmp(method, "lz4") == 0) {
type = LZ4;
ext = "lz4";
} else if (strcmp(method, "lz4_legacy") == 0) {
type = LZ4_LEGACY;
ext = "lz4";
} else if (strcmp(method, "bzip2") == 0) {
type = BZIP2;
ext = "bz2";
} else {
fprintf(stderr, "Only support following methods: ");
for (int i = 0; SUP_LIST[i]; ++i)
fprintf(stderr, "%s ", SUP_LIST[i]);
fprintf(stderr, "\n");
exit(1);
}
void *file;
size_t size;
if (strcmp(from, "-") == 0)
stream_full_read(STDIN_FILENO, &file, &size);
else
mmap_ro(from, &file, &size);
if (to == NULL) {
if (strcmp(from, "-") == 0)
strcpy(dest, "-");
else
snprintf(dest, sizeof(dest), "%s.%s", from, ext);
} else
strcpy(dest, to);
int fd;
if (strcmp(dest, "-") == 0) {
fd = STDOUT_FILENO;
} else {
fd = creat(dest, 0644);
fprintf(stderr, "Compressing to [%s]\n", dest);
}
comp(type, fd, file, size);
close(fd);
if (strcmp(from, "-") == 0)
free(file);
else
munmap(file, size);
if (to == NULL)
unlink(from);
}

111
native/jni/magiskboot/dtb.c Normal file
View File

@@ -0,0 +1,111 @@
#include <libfdt.h>
#include <unistd.h>
#include <sys/mman.h>
#include "magiskboot.h"
#include "utils.h"
static void print_props(const void *fdt, int node, int depth) {
int prop;
fdt_for_each_property_offset(prop, fdt, node) {
for (int i = 0; i < depth; ++i) printf(" ");
printf(" ");
int size;
const char *name;
const char *value = fdt_getprop_by_offset(fdt, prop, &name, &size);
printf("[%s]: [%s]\n", name, value);
}
}
static void print_subnode(const void *fdt, int parent, int depth) {
int node;
fdt_for_each_subnode(node, fdt, parent) {
for (int i = 0; i < depth; ++i) printf(" ");
printf("#%d: %s\n", node, fdt_get_name(fdt, node, NULL));
print_props(fdt, node, depth);
print_subnode(fdt, node, depth + 1);
}
}
static int find_fstab(const void *fdt, int parent) {
int node, fstab;
fdt_for_each_subnode(node, fdt, parent) {
if (strcmp(fdt_get_name(fdt, node, NULL), "fstab") == 0)
return node;
fstab = find_fstab(fdt, node);
if (fstab != -1)
return fstab;
}
return -1;
}
static void dtb_dump(const char *file) {
size_t size ;
void *dtb, *fdt;
fprintf(stderr, "Loading dtbs from [%s]\n", file);
mmap_ro(file, &dtb, &size);
// Loop through all the dtbs
int dtb_num = 0;
for (int i = 0; i < size; ++i) {
if (memcmp(dtb + i, DTB_MAGIC, 4) == 0) {
fdt = dtb + i;
fprintf(stderr, "Dumping dtb.%04d\n", dtb_num++);
print_subnode(fdt, 0, 0);
}
}
fprintf(stderr, "\n");
munmap(dtb, size);
exit(0);
}
static void dtb_patch(const char *file, int patch) {
size_t size ;
void *dtb, *fdt;
fprintf(stderr, "Loading dtbs from [%s]\n", file);
if (patch)
mmap_rw(file, &dtb, &size);
else
mmap_ro(file, &dtb, &size);
// Loop through all the dtbs
int dtb_num = 0, found = 0;
for (int i = 0; i < size; ++i) {
if (memcmp(dtb + i, DTB_MAGIC, 4) == 0) {
fdt = dtb + i;
int fstab = find_fstab(fdt, 0);
if (fstab > 0) {
fprintf(stderr, "Found fstab in dtb.%04d\n", dtb_num++);
int block;
fdt_for_each_subnode(block, fdt, fstab) {
fprintf(stderr, "Found block [%s] in fstab\n", fdt_get_name(fdt, block, NULL));
uint32_t value_size;
void *value = (void *) fdt_getprop(fdt, block, "fsmgr_flags", &value_size);
if (patch) {
void *dup = xmalloc(value_size);
memcpy(dup, value, value_size);
memset(value, 0, value_size);
found |= patch_verity(&dup, &value_size, 1);
memcpy(value, dup, value_size);
free(dup);
} else {
found |= patch_verity(&value, &value_size, 0);
}
}
}
}
}
munmap(dtb, size);
exit(!found);
}
int dtb_commands(const char *cmd, int argc, char *argv[]) {
if (argc == 0) return 1;
if (strcmp(cmd, "dump") == 0)
dtb_dump(argv[0]);
else if (strcmp(cmd, "patch") == 0)
dtb_patch(argv[0], 1);
else if (strcmp(cmd, "test") == 0)
dtb_patch(argv[0], 0);
return 0;
}

View File

@@ -0,0 +1,85 @@
#include <string.h>
#include "bootimg.h"
#include "format.h"
#define MATCH(s) (len >= (sizeof(s) - 1) && memcmp(buf, s, sizeof(s) - 1) == 0)
format_t check_fmt(const void *buf, size_t len) {
if (MATCH(CHROMEOS_MAGIC)) {
return CHROMEOS;
} else if (MATCH(BOOT_MAGIC)) {
return AOSP;
} else if (MATCH(ELF32_MAGIC)) {
return ELF32;
} else if (MATCH(ELF64_MAGIC)) {
return ELF64;
} else if (MATCH(GZIP_MAGIC)) {
return GZIP;
} else if (MATCH(LZOP_MAGIC)) {
return LZOP;
} else if (MATCH(XZ_MAGIC)) {
return XZ;
} else if (len >= 13 && memcmp(buf, "\x5d\x00\x00", 3) == 0
&& (((char *)buf)[12] == '\xff' || ((char *)buf)[12] == '\x00')) {
return LZMA;
} else if (MATCH(BZIP_MAGIC)) {
return BZIP2;
} else if (MATCH(LZ4_MAGIC)) {
return LZ4;
} else if (MATCH(LZ4_LEG_MAGIC)) {
return LZ4_LEGACY;
} else if (MATCH(MTK_MAGIC)) {
return MTK;
} else if (MATCH(DTB_MAGIC)) {
return DTB;
} else if (MATCH(DHTB_MAGIC)) {
return DHTB;
} else if (MATCH(TEGRABLOB_MAGIC)) {
return BLOB;
} else {
return UNKNOWN;
}
}
void get_fmt_name(format_t fmt, char *name) {
char *s;
switch (fmt) {
case CHROMEOS:
s = "chromeos";
break;
case AOSP:
s = "aosp";
break;
case GZIP:
s = "gzip";
break;
case LZOP:
s = "lzop";
break;
case XZ:
s = "xz";
break;
case LZMA:
s = "lzma";
break;
case BZIP2:
s = "bzip2";
break;
case LZ4:
s = "lz4";
break;
case LZ4_LEGACY:
s = "lz4_legacy";
break;
case MTK:
s = "mtk";
break;
case DTB:
s = "dtb";
break;
default:
s = "raw";
}
strcpy(name, s);
}

View File

@@ -0,0 +1,53 @@
#ifndef _FORMAT_H_
#define _FORMAT_H_
typedef enum {
UNKNOWN,
CHROMEOS,
AOSP,
ELF32,
ELF64,
GZIP,
LZOP,
XZ,
LZMA,
BZIP2,
LZ4,
LZ4_LEGACY,
MTK,
DTB,
DHTB,
BLOB
} format_t;
#define COMPRESSED(fmt) (fmt >= GZIP && fmt <= LZ4_LEGACY)
#define BOOT_MAGIC "ANDROID!"
#define CHROMEOS_MAGIC "CHROMEOS"
#define ELF32_MAGIC "\x7f""ELF\x01"
#define ELF64_MAGIC "\x7f""ELF\x02"
#define GZIP_MAGIC "\x1f\x8b\x08\x00"
#define LZOP_MAGIC "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a"
#define XZ_MAGIC "\xfd""7zXZ\x00"
#define BZIP_MAGIC "BZh"
#define LZ4_MAGIC "\x04\x22\x4d\x18"
#define LZ4_LEG_MAGIC "\x02\x21\x4c\x18"
#define MTK_MAGIC "\x88\x16\x88\x58"
#define DTB_MAGIC "\xd0\x0d\xfe\xed"
#define LG_BUMP_MAGIC "\x41\xa9\xe4\x67\x74\x4d\x1d\x1b\xa4\x29\xf2\xec\xea\x65\x52\x79"
#define DHTB_MAGIC "\x44\x48\x54\x42\x01\x00\x00\x00"
#define SEANDROID_MAGIC "SEANDROIDENFORCE"
#define TEGRABLOB_MAGIC "-SIGNED-BY-SIGNBLOB-"
#define NOOKHD_MAGIC "Green Loader"
#define NOOKHD_NEW_MAGIC "eMMC boot.img+secondloader"
#define NOOKHD_PRE_HEADER_SZ 1048576
#define ACCLAIM_MAGIC "BauwksBoot"
#define ACCLAIM_PRE_HEADER_SZ 262144
#define SUP_LIST ((char *[]) { "gzip", "xz", "lzma", "bzip2", "lz4", "lz4_legacy", NULL })
#define SUP_EXT_LIST ((char *[]) { "gz", "xz", "lzma", "bz2", "lz4", "lz4", NULL })
format_t check_fmt(const void *buf, size_t len);
void get_fmt_name(format_t fmt, char *name);
#endif

View File

@@ -0,0 +1,38 @@
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <sys/mman.h>
#include "magiskboot.h"
#include "utils.h"
static void hex2byte(const char *hex, unsigned char *str) {
char high, low;
for (int i = 0, length = strlen(hex); i < length; i += 2) {
high = toupper(hex[i]) - '0';
low = toupper(hex[i + 1]) - '0';
str[i / 2] = ((high > 9 ? high - 7 : high) << 4) + (low > 9 ? low - 7 : low);
}
}
void hexpatch(const char *image, const char *from, const char *to) {
int patternsize = strlen(from) / 2, patchsize = strlen(to) / 2;
size_t filesize;
void *file, *pattern, *patch;
mmap_rw(image, &file, &filesize);
pattern = xmalloc(patternsize);
patch = xmalloc(patchsize);
hex2byte(from, pattern);
hex2byte(to, patch);
for (size_t i = 0; filesize > 0 && i < filesize - patternsize; ++i) {
if (memcmp(file + i, pattern, patternsize) == 0) {
fprintf(stderr, "Patch @ %08X [%s]->[%s]\n", (unsigned) i, from, to);
memset(file + i, 0, patternsize);
memcpy(file + i, patch, patchsize);
i += patternsize - 1;
}
}
munmap(file, filesize);
free(pattern);
free(patch);
}

View File

@@ -0,0 +1,35 @@
#ifndef _MAGISKBOOT_H_
#define _MAGISKBOOT_H_
#include <sys/types.h>
#include "logging.h"
#include "bootimg.h"
#define KERNEL_FILE "kernel"
#define RAMDISK_FILE "ramdisk.cpio"
#define SECOND_FILE "second"
#define EXTRA_FILE "extra"
#define DTB_FILE "dtb"
#define NEW_BOOT "new-boot.img"
// Main entries
int unpack(const char *image);
void repack(const char* orig_image, const char* out_image);
void hexpatch(const char *image, const char *from, const char *to);
int parse_img(const char *image, boot_img *boot);
int cpio_commands(int argc, char *argv[]);
void comp_file(const char *method, const char *from, const char *to);
void decomp_file(char *from, const char *to);
int dtb_commands(const char *cmd, int argc, char *argv[]);
// Compressions
size_t gzip(int mode, int fd, const void *buf, size_t size);
size_t lzma(int mode, int fd, const void *buf, size_t size);
size_t lz4(int mode, int fd, const void *buf, size_t size);
size_t bzip2(int mode, int fd, const void *buf, size_t size);
size_t lz4_legacy(int mode, int fd, const void *buf, size_t size);
long long comp(format_t type, int to, const void *from, size_t size);
long long decomp(format_t type, int to, const void *from, size_t size);
#endif

View File

@@ -0,0 +1,168 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include "magiskboot.h"
#include "utils.h"
#include "mincrypt/sha.h"
/********************
Patch Boot Image
*********************/
static void usage(char *arg0) {
fprintf(stderr,
"Usage: %s <action> [args...]\n"
"\n"
"Supported actions:\n"
" --parse <bootimg>\n"
" Parse <bootimg> only, do not unpack. Return values: \n"
" 0:OK 1:error 2:insufficient boot partition size\n"
" 3:chromeos 4:ELF32 5:ELF64\n"
"\n"
" --unpack <bootimg>\n"
" Unpack <bootimg> to kernel, ramdisk.cpio, (second), (dtb), (extra) into\n"
" the current directory. Return value is the same as --parse\n"
"\n"
" --repack <origbootimg> [outbootimg]\n"
" Repack kernel, ramdisk.cpio[.ext], second, dtb... from current directory\n"
" to [outbootimg], or new-boot.img if not specified.\n"
" It will compress ramdisk.cpio with the same method used in <origbootimg>,\n"
" or attempt to find ramdisk.cpio.[ext], and repack directly with the\n"
" compressed ramdisk file\n"
"\n"
" --hexpatch <file> <hexpattern1> <hexpattern2>\n"
" Search <hexpattern1> in <file>, and replace with <hexpattern2>\n"
"\n"
" --cpio <incpio> [commands...]\n"
" Do cpio commands to <incpio> (modifications are done directly)\n"
" Each command is a single argument, use quotes if necessary\n"
" Supported commands:\n"
" rm [-r] ENTRY\n"
" Remove ENTRY, specify [-r] to remove recursively\n"
" mkdir MODE ENTRY\n"
" Create directory ENTRY in permissions MODE\n"
" ln TARGET ENTRY\n"
" Create a symlink to TARGET with the name ENTRY\n"
" mv SOURCE DEST\n"
" Move SOURCE to DEST\n"
" add MODE ENTRY INFILE\n"
" Add INFILE as ENTRY in permissions MODE; replaces ENTRY if exists\n"
" extract [ENTRY OUT]\n"
" Extract ENTRY to OUT, or extract all entries to current directory\n"
" test\n"
" Test the current cpio's patch status\n"
" Return value: 0/stock 1/Magisk 2/other (phh, SuperSU, Xposed)\n"
" patch KEEPVERITY KEEPFORCEENCRYPT\n"
" Ramdisk patches. KEEP**** are boolean values\n"
" backup ORIG [SHA1]\n"
" Create ramdisk backups from ORIG\n"
" SHA1 of stock boot image is optional\n"
" restore\n"
" Restore ramdisk from ramdisk backup stored within incpio\n"
" magisk ORIG HIGHCOMP KEEPVERITY KEEPFORCEENCRYPT [SHA1]\n"
" Do Magisk patches and backups all in one step\n"
" Create ramdisk backups from ORIG\n"
" HIGHCOMP, KEEP**** are boolean values\n"
" SHA1 of stock boot image is optional\n"
" sha1\n"
" Print stock boot SHA1 if previously stored\n"
"\n"
" --dtb-<cmd> <dtb>\n"
" Do dtb related cmds to <dtb> (modifications are done directly)\n"
" Supported commands:\n"
" dump\n"
" Dump all contents from dtb for debugging\n"
" test\n"
" Check if fstab has verity/avb flags\n"
" Return value: 0/no flags 1/flag exists\n"
" patch\n"
" Search for fstab and remove verity/avb\n"
"\n"
" --compress[=method] <infile> [outfile]\n"
" Compress <infile> with [method] (default: gzip), optionally to [outfile]\n"
" <infile>/[outfile] can be '-' to be STDIN/STDOUT\n"
" Supported methods: "
, arg0);
for (int i = 0; SUP_LIST[i]; ++i)
fprintf(stderr, "%s ", SUP_LIST[i]);
fprintf(stderr,
"\n\n"
" --decompress <infile> [outfile]\n"
" Detect method and decompress <infile>, optionally to [outfile]\n"
" <infile>/[outfile] can be '-' to be STDIN/STDOUT\n"
" Supported methods: ");
for (int i = 0; SUP_LIST[i]; ++i)
fprintf(stderr, "%s ", SUP_LIST[i]);
fprintf(stderr,
"\n\n"
" --sha1 <file>\n"
" Print the SHA1 checksum for <file>\n"
"\n"
" --cleanup\n"
" Cleanup the current working directory\n"
"\n");
exit(1);
}
int main(int argc, char *argv[]) {
fprintf(stderr, "MagiskBoot v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") (by topjohnwu) - Boot Image Modification Tool\n");
umask(0);
if (argc > 1 && strcmp(argv[1], "--cleanup") == 0) {
fprintf(stderr, "Cleaning up...\n");
char name[PATH_MAX];
unlink(KERNEL_FILE);
unlink(RAMDISK_FILE);
unlink(RAMDISK_FILE ".raw");
unlink(SECOND_FILE);
unlink(DTB_FILE);
unlink(EXTRA_FILE);
for (int i = 0; SUP_EXT_LIST[i]; ++i) {
sprintf(name, "%s.%s", RAMDISK_FILE, SUP_EXT_LIST[i]);
unlink(name);
}
} else if (argc > 2 && strcmp(argv[1], "--sha1") == 0) {
uint8_t sha1[SHA_DIGEST_SIZE];
void *buf;
size_t size;
mmap_ro(argv[2], &buf, &size);
SHA_hash(buf, size, sha1);
for (int i = 0; i < SHA_DIGEST_SIZE; ++i)
printf("%02x", sha1[i]);
printf("\n");
munmap(buf, size);
} else if (argc > 2 && strcmp(argv[1], "--parse") == 0) {
boot_img boot;
return parse_img(argv[2], &boot);
} else if (argc > 2 && strcmp(argv[1], "--unpack") == 0) {
return unpack(argv[2]);
} else if (argc > 2 && strcmp(argv[1], "--repack") == 0) {
repack(argv[2], argc > 3 ? argv[3] : NEW_BOOT);
} else if (argc > 2 && strcmp(argv[1], "--decompress") == 0) {
decomp_file(argv[2], argc > 3 ? argv[3] : NULL);
} else if (argc > 2 && strncmp(argv[1], "--compress", 10) == 0) {
char *method;
method = strchr(argv[1], '=');
if (method == NULL) method = "gzip";
else method++;
comp_file(method, argv[2], argc > 3 ? argv[3] : NULL);
} else if (argc > 4 && strcmp(argv[1], "--hexpatch") == 0) {
hexpatch(argv[2], argv[3], argv[4]);
} else if (argc > 2 && strcmp(argv[1], "--cpio") == 0) {
if (cpio_commands(argc - 2, argv + 2)) usage(argv[0]);
} else if (argc > 2 && strncmp(argv[1], "--dtb", 5) == 0) {
char *cmd = argv[1] + 5;
if (*cmd == '\0') usage(argv[0]);
else ++cmd;
if (dtb_commands(cmd, argc - 2, argv + 2))
usage(argv[0]);
} else {
usage(argv[0]);
}
return 0;
}

View File

@@ -0,0 +1,339 @@
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <utils.h>
#include <sys/mman.h>
#include <fcntl.h>
#include "magiskboot.h"
#include "cpio.h"
static void cpio_patch(struct vector *v, int keepverity, int keepforceencrypt) {
fprintf(stderr, "Patch with flag KEEPVERITY=[%s] KEEPFORCEENCRYPT=[%s]\n",
keepverity ? "true" : "false", keepforceencrypt ? "true" : "false");
cpio_entry *e;
vec_for_each(v, e) {
if (!e) continue;
if (!keepverity) {
if (strncmp(e->filename, ".backup", 7) && strstr(e->filename, "fstab") && S_ISREG(e->mode)) {
patch_verity(&e->data, &e->filesize, 1);
} else if (strcmp(e->filename, "verity_key") == 0) {
fprintf(stderr, "Remove [verity_key]\n");
cpio_free(e);
vec_cur(v) = NULL;
continue;
}
}
if (!keepforceencrypt) {
if (strstr(e->filename, "fstab") != NULL && S_ISREG(e->mode)) {
patch_encryption(&e->data, &e->filesize);
}
}
}
}
#define STOCK_BOOT 0x0
#define MAGISK_PATCH 0x1
#define HIGH_COMPRESS 0x2
#define OTHER_PATCH 0x3
static int cpio_test(struct vector *v) {
const char *OTHER_LIST[] = { "sbin/launch_daemonsu.sh", "sbin/su", "init.xposed.rc", "boot/sbin/launch_daemonsu.sh", NULL };
const char *MAGISK_LIST[] = { ".backup/.magisk", "init.magisk.rc", "overlay/init.magisk.rc", NULL };
for (int i = 0; OTHER_LIST[i]; ++i)
if (cpio_find(v, OTHER_LIST[i]) >= 0)
return OTHER_PATCH;
if (cpio_find(v, "ramdisk.cpio.xz") >= 0)
return HIGH_COMPRESS;
for (int i = 0; MAGISK_LIST[i]; ++i)
if (cpio_find(v, MAGISK_LIST[i]) >= 0)
return MAGISK_PATCH;
return STOCK_BOOT;
}
static char *cpio_sha1(struct vector *v) {
cpio_entry *e;
char sha1[41];
vec_for_each(v, e) {
if (!e) continue;
if (strcmp(e->filename, "init.magisk.rc") == 0
|| strcmp(e->filename, "overlay/init.magisk.rc") == 0) {
for (void *pos = e->data; pos < e->data + e->filesize; pos = strchr(pos + 1, '\n') + 1) {
if (memcmp(pos, "# STOCKSHA1=", 12) == 0) {
pos += 12;
memcpy(sha1, pos, 40);
sha1[40] = '\0';
return strdup(sha1);
}
}
} else if (strcmp(e->filename, ".backup/.sha1") == 0) {
return e->data;
}
}
return NULL;
}
static void cpio_backup(struct vector *v, struct vector *bak, const char *orig, const char *sha1) {
struct vector o_body, *o = &o_body;
cpio_entry *m, *n, *rem, *cksm;
char buf[PATH_MAX];
int res, backup;
m = xcalloc(sizeof(*m), 1);
m->filename = strdup(".backup");
m->mode = S_IFDIR;
vec_push_back(bak, m);
rem = xcalloc(sizeof(*rem), 1);
rem->filename = strdup(".backup/.rmlist");
rem->mode = S_IFREG;
if (sha1) {
fprintf(stderr, "Save SHA1: [%s] -> [.backup/.sha1]\n", sha1);
cksm = xcalloc(sizeof(*cksm), 1);
vec_push_back(bak, cksm);
cksm->filename = strdup(".backup/.sha1");
cksm->mode = S_IFREG;
cksm->data = strdup(sha1);
cksm->filesize = strlen(sha1) + 1;
}
vec_init(o);
parse_cpio(o, orig);
// Remove possible backups in original ramdisk
cpio_rm(o, 1, ".backup");
cpio_rm(v, 1, ".backup");
// Sort both vectors before comparing
vec_sort(o, cpio_cmp);
vec_sort(v, cpio_cmp);
// Start comparing
size_t i = 0, j = 0;
while(i != vec_size(o) || j != vec_size(v)) {
backup = 0;
if (i != vec_size(o) && j != vec_size(v)) {
m = vec_entry(o)[i];
n = vec_entry(v)[j];
res = strcmp(m->filename, n->filename);
} else if (i == vec_size(o)) {
n = vec_entry(v)[j];
res = 1;
} else if (j == vec_size(v)) {
m = vec_entry(o)[i];
res = -1;
}
if (res < 0) {
// Something is missing in new ramdisk, backup!
++i;
backup = 1;
fprintf(stderr, "Backup missing entry: ");
} else if (res == 0) {
++i; ++j;
if (m->filesize == n->filesize && memcmp(m->data, n->data, m->filesize) == 0)
continue;
// Not the same!
backup = 1;
fprintf(stderr, "Backup mismatch entry: ");
} else {
// Something new in ramdisk, record in rem
++j;
rem->data = xrealloc(rem->data, rem->filesize + strlen(n->filename) + 1);
memcpy(rem->data + rem->filesize, n->filename, strlen(n->filename) + 1);
rem->filesize += strlen(n->filename) + 1;
fprintf(stderr, "Record new entry: [%s] -> [.backup/.rmlist]\n", n->filename);
}
if (backup) {
sprintf(buf, ".backup/%s", m->filename);
fprintf(stderr, "[%s] -> [%s]\n", m->filename, buf);
free(m->filename);
m->filename = strdup(buf);
vec_push_back(bak, m);
// NULL the original entry, so it won't be freed
vec_entry(o)[i - 1] = NULL;
}
}
if (rem->filesize)
vec_push_back(bak, rem);
else
cpio_free(rem);
// Cleanup
cpio_vec_destroy(o);
}
static void cpio_restore(struct vector *v) {
cpio_entry *e;
vec_for_each(v, e) {
if (!e) continue;
if (strncmp(e->filename, ".backup", 7) == 0) {
if (e->filename[7] == '\0') continue;
if (e->filename[8] == '.') {
if (strcmp(e->filename, ".backup/.rmlist") == 0) {
for (int pos = 0; pos < e->filesize; pos += strlen(e->data + pos) + 1)
cpio_rm(v, 0, e->data + pos);
}
continue;
} else {
fprintf(stderr, "Restore [%s] -> [%s]\n", e->filename, e->filename + 8);
vec_cur(v) = NULL;
char *new_name = strdup(e->filename + 8);
free(e->filename);
e->filename = new_name;
cpio_vec_insert(v, e);
}
}
}
// Some known stuff we can remove
cpio_rm(v, 1, ".backup");
cpio_rm(v, 1, "overlay");
cpio_rm(v, 0, "sbin/magic_mask.sh");
cpio_rm(v, 0, "init.magisk.rc");
cpio_rm(v, 0, "magisk");
cpio_rm(v, 0, "ramdisk-recovery.xz");
}
static void restore_high_compress(struct vector *v, const char *incpio) {
// Check if the ramdisk is in high compression mode
if (cpio_extract(v, "ramdisk.cpio.xz", incpio) == 0) {
void *xz;
size_t size;
full_read(incpio, &xz, &size);
int fd = creat(incpio, 0644);
lzma(0, fd, xz, size);
close(fd);
free(xz);
cpio_rm(v, 0, "ramdisk.cpio.xz");
cpio_rm(v, 0, "init");
struct vector vv;
vec_init(&vv);
parse_cpio(&vv, incpio);
cpio_entry *e;
vec_for_each(&vv, e)
vec_push_back(v, e);
vec_destroy(&vv);
}
}
static void enable_high_compress(struct vector *v, struct vector *b, const char *incpio) {
cpio_entry *init, *magiskinit;
// Swap magiskinit with original init
int i = cpio_find(b, ".backup/init"), j = cpio_find(v, "init");
init = vec_entry(b)[i];
magiskinit = vec_entry(v)[j];
free(init->filename);
init->filename = strdup("init");
vec_entry(v)[j] = init;
vec_entry(b)[i] = NULL;
dump_cpio(v, incpio);
cpio_vec_destroy(v);
void *cpio;
size_t size;
full_read(incpio, &cpio, &size);
int fd = creat(incpio, 0644);
lzma(1, fd, cpio, size);
close(fd);
free(cpio);
vec_init(v);
vec_push_back(v, magiskinit);
cpio_add(v, 0, "ramdisk.cpio.xz", incpio);
}
int cpio_commands(int argc, char *argv[]) {
char *incpio = argv[0];
++argv;
--argc;
struct vector v;
vec_init(&v);
parse_cpio(&v, incpio);
int cmdc;
char *cmdv[6];
while (argc) {
cmdc = 0;
for (char *tok = strtok(argv[0], " "); tok; tok = strtok(NULL, " "))
cmdv[cmdc++] = tok;
if (strcmp(cmdv[0], "test") == 0) {
exit(cpio_test(&v));
} else if (strcmp(cmdv[0], "restore") == 0) {
restore_high_compress(&v, incpio);
cpio_restore(&v);
} else if (strcmp(cmdv[0], "sha1") == 0) {
char *sha1 = cpio_sha1(&v);
if (sha1)
printf("%s\n", sha1);
return 0;
} else if (cmdc >= 2 && strcmp(cmdv[0], "backup") == 0) {
struct vector back;
vec_init(&back);
cpio_backup(&v, &back, cmdv[1], cmdc > 2 ? cmdv[2] : NULL);
cpio_entry *e;
vec_for_each(&back, e)
if (e) vec_push_back(&v, e);
vec_destroy(&back);
} else if (cmdc >= 5 && strcmp(cmdv[0], "magisk") == 0) {
cpio_patch(&v, strcmp(cmdv[3], "true") == 0, strcmp(cmdv[4], "true") == 0);
struct vector back;
vec_init(&back);
cpio_backup(&v, &back, cmdv[1], cmdc > 5 ? cmdv[5] : NULL);
cpio_entry *e;
e = xcalloc(sizeof(*e), 1);
e->filename = strdup(".backup/.magisk");
e->mode = S_IFREG;
e->data = xmalloc(50);
snprintf(e->data, 50, "KEEPVERITY=%s\nKEEPFORCEENCRYPT=%s\n", cmdv[3], cmdv[4]);
e->filesize = strlen(e->data) + 1;
vec_push_back(&back, e);
// Enable high compression mode
if (strcmp(cmdv[2], "true") == 0)
enable_high_compress(&v, &back, incpio);
vec_for_each(&back, e)
if (e) vec_push_back(&v, e);
vec_destroy(&back);
} else if (cmdc >= 2 && strcmp(cmdv[0], "rm") == 0) {
int recur = cmdc > 2 && strcmp(cmdv[1], "-r") == 0;
cpio_rm(&v, recur, cmdv[1 + recur]);
} else if (cmdc == 3 && strcmp(cmdv[0], "mv") == 0) {
cpio_mv(&v, cmdv[1], cmdv[2]);
} else if (cmdc == 3 && strcmp(cmdv[0], "patch") == 0) {
cpio_patch(&v, strcmp(cmdv[1], "true") == 0, strcmp(cmdv[2], "true") == 0);
} else if (strcmp(cmdv[0], "extract") == 0) {
if (cmdc == 3) {
return cpio_extract(&v, cmdv[1], cmdv[2]);
} else {
cpio_extract_all(&v);
return 0;
}
} else if (cmdc == 3 && strcmp(cmdv[0], "mkdir") == 0) {
cpio_mkdir(&v, strtoul(cmdv[1], NULL, 8), cmdv[2]);
} else if (cmdc == 3 && strcmp(cmdv[0], "ln") == 0) {
cpio_ln(&v, cmdv[1], cmdv[2]);
} else if (cmdc == 4 && strcmp(cmdv[0], "add") == 0) {
cpio_add(&v, strtoul(cmdv[1], NULL, 8), cmdv[2], cmdv[3]);
} else {
return 1;
}
--argc;
++argv;
}
dump_cpio(&v, incpio);
cpio_vec_destroy(&v);
return 0;
}

View File

@@ -0,0 +1,213 @@
/* hide_utils.c - Some utility functions for MagiskHide
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <selinux/selinux.h>
#include "magisk.h"
#include "utils.h"
#include "resetprop.h"
#include "magiskhide.h"
#include "daemon.h"
static char *prop_key[] =
{ "ro.boot.verifiedbootstate", "ro.boot.flash.locked", "ro.boot.veritymode", "ro.boot.warranty_bit", "ro.warranty_bit",
"ro.debuggable", "ro.secure", "ro.build.type", "ro.build.tags", "ro.build.selinux", NULL };
static char *prop_value[] =
{ "green", "1", "enforcing", "0", "0", "0", "1", "user", "release-keys", "0", NULL };
static int mocked = 0;
void manage_selinux() {
if (mocked) return;
char val[1];
int fd = xopen(SELINUX_ENFORCE, O_RDONLY);
xxread(fd, val, 1);
close(fd);
// Permissive
if (val[0] == '0') {
LOGI("hide_daemon: Permissive detected, hide the state\n");
chmod(SELINUX_ENFORCE, 0640);
chmod(SELINUX_POLICY, 0440);
mocked = 1;
}
}
void hide_sensitive_props() {
LOGI("hide_utils: Hiding sensitive props\n");
// Hide all sensitive props
char *value;
for (int i = 0; prop_key[i]; ++i) {
value = getprop(prop_key[i]);
if (value) {
if (strcmp(value, prop_value[i]) != 0)
setprop2(prop_key[i], prop_value[i], 0);
free(value);
}
}
}
static void rm_magisk_prop(const char *name, const char *value) {
if (strstr(name, "magisk")) {
deleteprop2(name, 0);
}
}
void clean_magisk_props() {
LOGD("hide_utils: Cleaning magisk props\n");
getprop_all(rm_magisk_prop);
}
int add_list(char *proc) {
if (!hideEnabled) {
free(proc);
return HIDE_NOT_ENABLED;
}
char *line;
struct vector *new_list = xmalloc(sizeof(*new_list));
if (new_list == NULL)
return DAEMON_ERROR;
vec_init(new_list);
vec_for_each(hide_list, line) {
// They should be unique
if (strcmp(line, proc) == 0) {
free(proc);
vec_destroy(new_list);
free(new_list);
return HIDE_ITEM_EXIST;
}
vec_push_back(new_list, line);
}
vec_push_back(new_list, proc);
LOGI("hide_list add: [%s]\n", proc);
ps_filter_proc_name(proc, kill_proc);
// Critical region
pthread_mutex_lock(&hide_lock);
vec_destroy(hide_list);
free(hide_list);
hide_list = new_list;
pthread_mutex_unlock(&hide_lock);
pthread_mutex_lock(&file_lock);
vector_to_file(HIDELIST, hide_list); // Do not complain if file not found
pthread_mutex_unlock(&file_lock);
return DAEMON_SUCCESS;
}
int rm_list(char *proc) {
if (!hideEnabled) {
free(proc);
return HIDE_NOT_ENABLED;
}
int ret = DAEMON_ERROR;
char *line;
int do_rm = 0;
struct vector *new_list = xmalloc(sizeof(*new_list));
if (new_list == NULL)
goto error;
vec_init(new_list);
vec_for_each(hide_list, line) {
if (strcmp(line, proc) == 0) {
free(proc);
proc = line;
do_rm = 1;
continue;
}
vec_push_back(new_list, line);
}
if (do_rm) {
LOGI("hide_list rm: [%s]\n", proc);
ps_filter_proc_name(proc, kill_proc);
// Critical region
pthread_mutex_lock(&hide_lock);
vec_destroy(hide_list);
free(hide_list);
hide_list = new_list;
pthread_mutex_unlock(&hide_lock);
ret = DAEMON_SUCCESS;
pthread_mutex_lock(&file_lock);
vector_to_file(HIDELIST, hide_list); // Do not complain if file not found
pthread_mutex_unlock(&file_lock);
} else {
ret = HIDE_ITEM_NOT_EXIST;
vec_destroy(new_list);
free(new_list);
}
error:
free(proc);
return ret;
}
int init_list() {
LOGD("hide_list: initialize...\n");
if ((hide_list = xmalloc(sizeof(*hide_list))) == NULL)
return 1;
vec_init(hide_list);
// Might error if file doesn't exist, no need to report
file_to_vector(HIDELIST, hide_list);
char *line;
vec_for_each(hide_list, line) {
LOGI("hide_list: [%s]\n", line);
ps_filter_proc_name(line, kill_proc);
}
return 0;
}
int destroy_list() {
char *line;
vec_for_each(hide_list, line) {
ps_filter_proc_name(line, kill_proc);
}
vec_deep_destroy(hide_list);
free(hide_list);
hide_list = NULL;
return 0;
}
void add_hide_list(int client) {
char *proc = read_string(client);
// ack
write_int(client, add_list(proc));
close(client);
}
void rm_hide_list(int client) {
char *proc = read_string(client);
// ack
write_int(client, rm_list(proc));
close(client);
}
void ls_hide_list(int client) {
if (!hideEnabled) {
write_int(client, HIDE_NOT_ENABLED);
return;
}
write_int(client, DAEMON_SUCCESS);
write_int(client, vec_size(hide_list));
char *s;
vec_for_each(hide_list, s) {
write_string(client, s);
}
close(client);
}

View File

@@ -0,0 +1,182 @@
/* magiskhide.c - initialize the environment for Magiskhide
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
#include "magisk.h"
#include "utils.h"
#include "magiskhide.h"
#include "daemon.h"
#include "resetprop.h"
struct vector *hide_list = NULL;
int hideEnabled = 0;
static pthread_t proc_monitor_thread;
pthread_mutex_t hide_lock, file_lock;
void kill_proc(int pid) {
kill(pid, SIGTERM);
}
static void usage(char *arg0) {
fprintf(stderr,
"MagiskHide v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") (by topjohnwu) - Hide Magisk!\n\n"
"Usage: %s [--options [arguments...] ]\n\n"
"Options:\n"
" --enable Start magiskhide\n"
" --disable Stop magiskhide\n"
" --add PROCESS Add PROCESS to the hide list\n"
" --rm PROCESS Remove PROCESS from the hide list\n"
" --ls Print out the current hide list\n"
, arg0);
exit(1);
}
void launch_magiskhide(int client) {
if (hideEnabled) {
if (client > 0) {
write_int(client, HIDE_IS_ENABLED);
close(client);
}
return;
}
if (!logd) {
if (client > 0) {
write_int(client, LOGD_DISABLED);
close(client);
}
setprop(MAGISKHIDE_PROP, "0");
// Remove without actually removing persist props
deleteprop2(MAGISKHIDE_PROP, 0);
return;
}
hideEnabled = 1;
LOGI("* Starting MagiskHide\n");
deleteprop2(MAGISKHIDE_PROP, 1);
hide_sensitive_props();
// Initialize the mutex lock
pthread_mutex_init(&hide_lock, NULL);
pthread_mutex_init(&file_lock, NULL);
// Initialize the hide list
if (init_list())
goto error;
// Add SafetyNet by default
add_list(strdup("com.google.android.gms.unstable"));
if (client > 0) {
write_int(client, DAEMON_SUCCESS);
close(client);
}
// Get thread reference
proc_monitor_thread = pthread_self();
// Start monitoring
proc_monitor();
return;
error:
hideEnabled = 0;
if (client > 0) {
write_int(client, DAEMON_ERROR);
close(client);
}
return;
}
void stop_magiskhide(int client) {
if (!hideEnabled) {
write_int(client, HIDE_NOT_ENABLED);
close(client);
return;
}
LOGI("* Stopping MagiskHide\n");
hideEnabled = 0;
setprop(MAGISKHIDE_PROP, "0");
// Remove without actually removing persist props
deleteprop2(MAGISKHIDE_PROP, 0);
pthread_kill(proc_monitor_thread, TERM_THREAD);
write_int(client, DAEMON_SUCCESS);
close(client);
}
int magiskhide_main(int argc, char *argv[]) {
if (argc < 2) {
usage(argv[0]);
}
int req = DO_NOTHING;
if (strcmp(argv[1], "--enable") == 0) {
req = LAUNCH_MAGISKHIDE;
} else if (strcmp(argv[1], "--disable") == 0) {
req = STOP_MAGISKHIDE;
} else if (strcmp(argv[1], "--add") == 0 && argc > 2) {
req = ADD_HIDELIST;
} else if (strcmp(argv[1], "--rm") == 0 && argc > 2) {
req = RM_HIDELIST;
} else if (strcmp(argv[1], "--ls") == 0) {
req = LS_HIDELIST;
} else {
usage(argv[0]);
}
int fd = connect_daemon();
write_int(fd, req);
if (req == ADD_HIDELIST || req == RM_HIDELIST) {
write_string(fd, argv[2]);
}
int code = read_int(fd);
switch (code) {
case DAEMON_SUCCESS:
break;
case ROOT_REQUIRED:
fprintf(stderr, "Root is required for this operation\n");
return code;
case LOGD_DISABLED:
fprintf(stderr, "Logd is not running, cannot run logcat\n");
return (code);
case HIDE_NOT_ENABLED:
fprintf(stderr, "Magisk hide is not enabled yet\n");
return code;
case HIDE_IS_ENABLED:
fprintf(stderr, "Magisk hide is already enabled\n");
return code;
case HIDE_ITEM_EXIST:
fprintf(stderr, "Process [%s] already exists in hide list\n", argv[2]);
return code;
case HIDE_ITEM_NOT_EXIST:
fprintf(stderr, "Process [%s] does not exist in hide list\n", argv[2]);
return code;
case DAEMON_ERROR:
default:
fprintf(stderr, "Error occured in daemon...\n");
return code;
}
if (req == LS_HIDELIST) {
int argc = read_int(fd);
for (int i = 0; i < argc; ++i) {
char *s = read_string(fd);
printf("%s\n", s);
free(s);
}
}
close(fd);
return 0;
}

View File

@@ -0,0 +1,30 @@
#ifndef MAGISK_HIDE_H
#define MAGISK_HIDE_H
#include <pthread.h>
#define TERM_THREAD SIGUSR1
#define HIDE_DONE SIGUSR2
// Kill process
void kill_proc(int pid);
// Process monitor
void proc_monitor();
// Utility functions
void manage_selinux();
void hide_sensitive_props();
void clean_magisk_props();
// List managements
int add_list(char *proc);
int rm_list(char *proc);
int init_list();
int destroy_list();
extern int hideEnabled;
extern struct vector *hide_list;
extern pthread_mutex_t hide_lock, file_lock;
#endif

View File

@@ -0,0 +1,265 @@
/* proc_monitor.c - Monitor am_proc_start events and unmount
*
* We monitor the logcat am_proc_start events. When a target starts up,
* we pause it ASAP, and fork a new process to join its mount namespace
* and do all the unmounting/mocking
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/mount.h>
#include "magisk.h"
#include "utils.h"
#include "magiskhide.h"
static char init_ns[32], zygote_ns[2][32], cache_block[256];
static int hide_queue = 0, zygote_num, has_cache = 1, pipefd[2] = { -1, -1 };
// Workaround for the lack of pthread_cancel
static void term_thread(int sig) {
LOGD("proc_monitor: running cleanup\n");
destroy_list();
hideEnabled = 0;
// Unregister listener
log_events[HIDE_EVENT].fd = -1;
close(pipefd[0]);
close(pipefd[1]);
pipefd[0] = pipefd[1] = -1;
pthread_mutex_destroy(&hide_lock);
pthread_mutex_destroy(&file_lock);
LOGD("proc_monitor: terminating...\n");
pthread_exit(NULL);
}
static void hide_done(int sig) {
--hide_queue;
if (hide_queue == 0) {
xmount(NULL, "/", NULL, MS_REMOUNT, NULL);
xsymlink(DATABIN, "/data/magisk");
xsymlink(MAINIMG, "/data/magisk.img");
xsymlink(MOUNTPOINT, "/magisk");
xmount(NULL, "/", NULL, MS_REMOUNT | MS_RDONLY, NULL);
}
}
static int read_namespace(const int pid, char* target, const size_t size) {
char path[32];
snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
if (access(path, R_OK) == -1)
return 1;
xreadlink(path, target, size);
return 0;
}
static void store_zygote_ns(int pid) {
if (zygote_num == 2) return;
do {
usleep(500);
read_namespace(pid, zygote_ns[zygote_num], 32);
} while (strcmp(zygote_ns[zygote_num], init_ns) == 0);
++zygote_num;
}
static void lazy_unmount(const char* mountpoint) {
if (umount2(mountpoint, MNT_DETACH) != -1)
LOGD("hide_daemon: Unmounted (%s)\n", mountpoint);
}
static void hide_daemon(int pid, int ppid) {
LOGD("hide_daemon: start unmount for pid=[%d]\n", pid);
strcpy(argv0, "hide_daemon");
char *line, buffer[PATH_MAX];
struct vector mount_list;
manage_selinux();
clean_magisk_props();
if (switch_mnt_ns(pid))
goto exit;
snprintf(buffer, sizeof(buffer), "/proc/%d/mounts", pid);
vec_init(&mount_list);
file_to_vector(buffer, &mount_list);
// Find the cache block name if not found yet
if (has_cache && cache_block[0] == '\0') {
vec_for_each(&mount_list, line) {
if (strstr(line, " /cache ")) {
sscanf(line, "%256s", cache_block);
break;
}
}
if (strlen(cache_block) == 0)
has_cache = 0;
}
// Unmout cache mounts
if (has_cache) {
vec_for_each(&mount_list, line) {
if (strstr(line, cache_block) && (strstr(line, " /system/") || strstr(line, " /vendor/"))) {
sscanf(line, "%*s %4096s", buffer);
lazy_unmount(buffer);
}
}
}
// Unmount dummy skeletons, /sbin links
vec_for_each(&mount_list, line) {
if (strstr(line, "tmpfs /system") || strstr(line, "tmpfs /vendor") || strstr(line, "tmpfs /sbin")) {
sscanf(line, "%*s %4096s", buffer);
lazy_unmount(buffer);
}
free(line);
}
vec_destroy(&mount_list);
// Re-read mount infos
snprintf(buffer, sizeof(buffer), "/proc/%d/mounts", pid);
vec_init(&mount_list);
file_to_vector(buffer, &mount_list);
// Unmount any loop mounts
vec_for_each(&mount_list, line) {
if (strstr(line, "/dev/block/loop")) {
sscanf(line, "%*s %4096s", buffer);
lazy_unmount(buffer);
}
free(line);
}
exit:
// Send resume signal
kill(pid, SIGCONT);
// Free up memory
vec_destroy(&mount_list);
// Wait a while and link it back
sleep(10);
kill(ppid, HIDE_DONE);
_exit(0);
}
void proc_monitor() {
// Unblock user signals
sigset_t block_set;
sigemptyset(&block_set);
sigaddset(&block_set, TERM_THREAD);
sigaddset(&block_set, HIDE_DONE);
pthread_sigmask(SIG_UNBLOCK, &block_set, NULL);
// Register the cancel signal
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = term_thread;
sigaction(TERM_THREAD, &act, NULL);
act.sa_handler = hide_done;
sigaction(HIDE_DONE, &act, NULL);
cache_block[0] = '\0';
// Get the mount namespace of init
if (read_namespace(1, init_ns, 32)) {
LOGE("proc_monitor: Your kernel doesn't support mount namespace :(\n");
term_thread(TERM_THREAD);
}
LOGI("proc_monitor: init ns=%s\n", init_ns);
// Get the mount namespace of zygote
zygote_num = 0;
while(!zygote_num) {
// Check zygote every 10 ms
usleep(10000);
ps_filter_proc_name("zygote", store_zygote_ns);
}
ps_filter_proc_name("zygote64", store_zygote_ns);
switch(zygote_num) {
case 1:
LOGI("proc_monitor: zygote ns=%s\n", zygote_ns[0]);
break;
case 2:
LOGI("proc_monitor: zygote ns=%s zygote64 ns=%s\n", zygote_ns[0], zygote_ns[1]);
break;
}
// Register our listener to logcat monitor
xpipe2(pipefd, O_CLOEXEC);
log_events[HIDE_EVENT].fd = pipefd[1];
for (char *log, *line;; free(log)) {
if (read(pipefd[0], &log, sizeof(log)) != sizeof(log)) {
/* It might be interrupted */
log = NULL;
continue;
}
char *ss = strchr(log, '[');
int pid, ret, comma = 0;
char *pos = ss, processName[256], ns[32];
while(1) {
pos = strchr(pos, ',');
if(pos == NULL)
break;
pos[0] = ' ';
++comma;
}
if (comma == 6)
ret = sscanf(ss, "[%*d %d %*d %*d %256s", &pid, processName);
else
ret = sscanf(ss, "[%*d %d %*d %256s", &pid, processName);
if(ret != 2)
continue;
// Critical region
pthread_mutex_lock(&hide_lock);
vec_for_each(hide_list, line) {
if (strcmp(processName, line) == 0) {
while(1) {
ret = 1;
for (int i = 0; i < zygote_num; ++i) {
read_namespace(pid, ns, sizeof(ns));
if (strcmp(ns, zygote_ns[i]) == 0) {
usleep(50);
ret = 0;
break;
}
}
if (ret) break;
}
// Send pause signal ASAP
if (kill(pid, SIGSTOP) == -1) continue;
LOGI("proc_monitor: %s (PID=%d ns=%s)\n", processName, pid, ns);
xmount(NULL, "/", NULL, MS_REMOUNT, NULL);
unlink("/magisk");
unlink("/data/magisk");
unlink("/data/magisk.img");
unlink(MAGISKRC);
xmount(NULL, "/", NULL, MS_REMOUNT | MS_RDONLY, NULL);
++hide_queue;
/*
* The setns system call do not support multithread processes
* We have to fork a new process, setns, then do the unmounts
*/
int selfpid = getpid();
if (fork_dont_care() == 0)
hide_daemon(pid, selfpid);
break;
}
}
pthread_mutex_unlock(&hide_lock);
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ERRNO_RESTORER_H
#define ERRNO_RESTORER_H
#include <errno.h>
#include "bionic_macros.h"
class ErrnoRestorer {
public:
explicit ErrnoRestorer() : saved_errno_(errno) {
}
~ErrnoRestorer() {
errno = saved_errno_;
}
void override(int new_errno) {
saved_errno_ = new_errno;
}
private:
int saved_errno_;
DISALLOW_COPY_AND_ASSIGN(ErrnoRestorer);
};
#endif // ERRNO_RESTORER_H

Some files were not shown because too many files have changed in this diff Show More