Compare commits

..

437 Commits
v11.6 ... v16.1

Author SHA1 Message Date
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
193 changed files with 29359 additions and 8149 deletions

4
.gitattributes vendored
View File

@@ -8,9 +8,11 @@
# 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.
binaries/** binary
chromeos/** binary
*.jar binary
*.exe binary
*.apk binary
*.png binary

30
.gitignore vendored
View File

@@ -1,22 +1,16 @@
obj/
libs/
out
*.zip
*.jks
*.apk
# Copied binaries
zip_static/arm/*
zip_static/arm64/*
zip_static/x86/*
zip_static/x64/*
zip_static/chromeos/*
uninstaller/arm/*
uninstaller/arm64/*
uninstaller/x86/*
uninstaller/x64/*
uninstaller/chromeos/*
# Built binaries
ziptools/zipadjust
# Generated scripts
uninstaller/common/
zip_static/common/*.sh
zip_static/common/*.rc
zip_static/META-INF/com/google/android/update-binary
# Android Studio / Gradle
*.iml
.gradle
/local.properties
/.idea
/build
/captures
.externalNativeBuild

33
.gitmodules vendored
View File

@@ -1,12 +1,27 @@
[submodule "jni/selinux"]
path = jni/selinux
[submodule "selinux"]
path = native/jni/external/selinux
url = https://github.com/topjohnwu/selinux.git
[submodule "jni/su"]
path = jni/su
[submodule "su"]
path = native/jni/su
url = https://github.com/topjohnwu/MagiskSU.git
[submodule "jni/ndk-compression"]
path = jni/ndk-compression
url = https://github.com/topjohnwu/ndk-compression.git
[submodule "jni/magiskpolicy"]
path = jni/magiskpolicy
[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,11 +1,79 @@
# Magisk
###Static binaries included:
* Busybox: http://forum.xda-developers.com/android/software-hacking/tool-busybox-flashable-archs-t3348543
###How to build Magisk
1. Download and install NDK
2. Add the NDK directory into PATH
To check if the PATH is set correctly, try calling `which ndk-build` (`where ndk-build` on Windows) and see if it shows the NDK directory
3. Unix-like users (e.g. Linux & MacOS) please execute `build.sh` through shell
Windows users please execute `build.cmd` through cmd
4. The scripts will show you further details
## 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 d5408d1f09

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

182
build.cmd
View File

@@ -1,182 +0,0 @@
@ECHO OFF
SETLOCAL ENABLEEXTENSIONS
SET me=%~nx0
SET parent=%~dp0
SET tab=
SET OK=
CD %parent%
call :%~1 "%~2"
IF NOT DEFINED OK CALL :usage
EXIT /B %ERRORLEVEL%
:usage
ECHO %me% all ^<version name^>
ECHO %tab%Build binaries, zip, and sign Magisk
ECHO %tab%This is equlivant to first ^<build^>, then ^<zip^>
ECHO %me% clean
ECHO %tab%Cleanup compiled / generated files
ECHO %me% build
ECHO %tab%Build the binaries with ndk
ECHO %me% zip ^<version name^>
ECHO %tab%Zip and sign Magisk
ECHO %me% uninstaller
ECHO %tab%Zip and sign the uninstaller
EXIT /B 1
:all
SET OK=y
IF [%~1] == [] (
CALL :error "Missing version number"
CALL :usage
EXIT /B %ERRORLEVEL%
)
CALL :build
CALL :zip "%~1"
EXIT /B %ERRORLEVEL%
:build
SET OK=y
ECHO ************************
ECHO * Building binaries
ECHO ************************
FOR /F "tokens=* USEBACKQ" %%F IN (`where ndk-build`) DO (
IF [%%F] == [] (
CALL :error "Please add ndk-build to PATH!"
EXIT /B 1
)
)
CALL ndk-build -j4 || CALL :error "Magisk binary tools build failed...."
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
ECHO ************************
ECHO * Copying binaries
ECHO ************************
CALL :mkcp libs\armeabi-v7a\* zip_static\arm
CALL :mkcp libs\arm64-v8a\* zip_static\arm64
CALL :mkcp libs\x86\* zip_static\x86
CALL :mkcp libs\x86_64\* zip_static\x64
CALL :mkcp libs\armeabi-v7a\magiskboot uninstaller\arm
CALL :mkcp libs\arm64-v8a\magiskboot uninstaller\arm64
CALL :mkcp libs\x86\magiskboot uninstaller\x86
CALL :mkcp libs\x86_64\magiskboot uninstaller\x64
EXIT /B %ERRORLEVEL%
:clean
SET OK=y
ECHO ************************
ECHO * Cleaning up
ECHO ************************
CALL ndk-build clean
2>NUL RMDIR /S /Q zip_static\arm
2>NUL RMDIR /S /Q zip_static\arm64
2>NUL RMDIR /S /Q zip_static\x86
2>NUL RMDIR /S /Q zip_static\x64
2>NUL RMDIR /S /Q zip_static\chromeos
2>NUL DEL zip_static\META-INF\com\google\android\update-binary
2>NUL DEL zip_static\common\*.sh
2>NUL DEL zip_static\common\*.rc
2>NUL RMDIR /S /Q uninstaller\common
2>NUL RMDIR /S /Q uninstaller\arm
2>NUL RMDIR /S /Q uninstaller\arm64
2>NUL RMDIR /S /Q uninstaller\x86
2>NUL RMDIR /S /Q uninstaller\x64
2>NUL RMDIR /S /Q uninstaller\chromeos
EXIT /B 0
:zip
SET OK=y
IF [%~1] == [] (
CALL :error "Missing version number"
CALL :usage
EXIT /B %ERRORLEVEL%
)
IF NOT EXIST "zip_static\arm\magiskboot" CALL :error "Missing binaries! Please run '%me% build' before zipping!"
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
ECHO ************************
ECHO * Adding version info
ECHO ************************
powershell.exe -nologo -noprofile -command "(gc -Raw scripts\flash_script.sh) -replace 'MAGISK_VERSION_STUB', 'Magisk v%~1 Boot Image Patcher' | sc zip_static\META-INF\com\google\android\update-binary"
powershell.exe -nologo -noprofile -command "(gc -Raw scripts\magic_mask.sh) -replace 'MAGISK_VERSION_STUB', 'setprop magisk.version \"%~1\"' | sc zip_static\common\magic_mask.sh"
ECHO ************************
ECHO * Copying Files
ECHO ************************
COPY /Y scripts\ramdisk_patch.sh zip_static\common\ramdisk_patch.sh
COPY /Y scripts\init.magisk.rc zip_static\common\init.magisk.rc
COPY /Y binaries\busybox-arm zip_static\arm\busybox
COPY /Y binaries\busybox-arm64 zip_static\arm64\busybox
COPY /Y binaries\busybox-x86 zip_static\x86\busybox
COPY /Y binaries\busybox-x64 zip_static\x64\busybox
CALL :mkcp binaries\chromeos zip_static\chromeos
ECHO ************************
ECHO * Zipping Magisk v%~1
ECHO ************************
CD zip_static
2>NUL DEL "..\Magisk-v%~1.zip"
..\ziptools\win_bin\zip "..\Magisk-v%~1.zip" -r .
CD ..\
CALL :sign_zip "Magisk-v%~1.zip"
EXIT /B %ERRORLEVEL%
:uninstaller
SET OK=y
IF NOT EXIST "uninstaller\arm\magiskboot" CALL :error "Missing binaries! Please run '%me% build' before zipping!"
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
ECHO ************************
ECHO * Copying Files
ECHO ************************
CALL :mkcp scripts\magisk_uninstaller.sh uninstaller\common
COPY /Y binaries\busybox-arm uninstaller\arm\busybox
COPY /Y binaries\busybox-arm64 uninstaller\arm64\busybox
COPY /Y binaries\busybox-x86 uninstaller\x86\busybox
COPY /Y binaries\busybox-x64 uninstaller\x64\busybox
CALL :mkcp binaries\chromeos uninstaller\chromeos
ECHO ************************
ECHO * Zipping uninstaller
ECHO ************************
FOR /F "tokens=* USEBACKQ" %%F IN (`ziptools\win_bin\date "+%%Y%%m%%d"`) DO (set timestamp=%%F)
CD uninstaller
2>NUL DEL "../Magisk-uninstaller-%timestamp%.zip"
..\ziptools\win_bin\zip "../Magisk-uninstaller-%timestamp%.zip" -r .
CD ..\
CALL :sign_zip "Magisk-uninstaller-%timestamp%.zip"
EXIT /B %ERRORLEVEL%
:sign_zip
IF NOT EXIST "ziptools\win_bin\zipadjust.exe" (
ECHO ************************
ECHO * Compiling ZipAdjust
ECHO ************************
gcc -o ziptools\win_bin\zipadjust ziptools\src\*.c -lz || CALL :error "ZipAdjust Build failed...."
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
)
SET basename="%~1"
SET basename="%basename:.zip=%"
ECHO ************************
ECHO * First sign %~1
ECHO ************************
java -jar "ziptools\signapk.jar" "ziptools\test.certificate.x509.pem" "ziptools\test.key.pk8" "%~1" "%basename:"=%-firstsign.zip"
ECHO ************************
ECHO * Adjusting %~1
ECHO ************************
ziptools\win_bin\zipadjust "%basename:"=%-firstsign.zip" "%basename:"=%-adjusted.zip"
ECHO ************************
ECHO * Final sign %~1
ECHO ************************
java -jar "ziptools\minsignapk.jar" "ziptools\test.certificate.x509.pem" "ziptools\test.key.pk8" "%basename:"=%-adjusted.zip" "%basename:"=%-signed.zip"
MOVE /Y "%basename:"=%-signed.zip" "%~1"
DEL "%basename:"=%-adjusted.zip" "%basename:"=%-firstsign.zip"
EXIT /B %ERRORLEVEL%
:mkcp
2>NUL MKDIR "%~2"
2>NUL COPY /Y "%~1" "%~2"
EXIT /B 0
:error
ECHO.
ECHO ! %~1
ECHO.
EXIT /B 1

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)

172
build.sh
View File

@@ -1,172 +0,0 @@
#!/bin/bash
usage() {
echo "$0 all <version name>"
echo -e "\tBuild binaries, zip, and sign Magisk"
echo -e "\tThis is equlivant to first <build>, then <zip>"
echo "$0 clean"
echo -e "\tCleanup compiled / generated files"
echo "$0 build"
echo -e "\tBuild the binaries with ndk"
echo "$0 zip <version name>"
echo -e "\tZip and sign Magisk"
echo "$0 uninstaller"
echo -e "\tZip and sign the uninstaller"
exit 1
}
cleanup() {
echo "************************"
echo "* Cleaning up"
echo "************************"
ndk-build clean 2>/dev/null
rm -rfv zip_static/arm
rm -rfv zip_static/arm64
rm -rfv zip_static/x86
rm -rfv zip_static/x64
rm -rfv zip_static/chromeos
rm -rfv zip_static/META-INF/com/google/android/update-binary
rm -rfv zip_static/common/*.sh
rm -rfv zip_static/common/*.rc
rm -rfv uninstaller/common
rm -rfv uninstaller/arm
rm -rfv uninstaller/arm64
rm -rfv uninstaller/x86
rm -rfv uninstaller/x64
rm -rfv uninstaller/chromeos
}
mkcp() {
[ ! -d "$2" ] && mkdir -p "$2"
cp -afv $1 $2
}
error() {
echo -e "\n! $1\n"
exit 1
}
build_bin() {
echo "************************"
echo "* Building binaries"
echo "************************"
[ -z `which ndk-build` ] && error "Please add ndk-build to PATH!"
ndk-build -j4 || error "Magisk binary tools build failed...."
echo "************************"
echo "* Copying binaries"
echo "************************"
mkcp "libs/armeabi-v7a/*" zip_static/arm
mkcp libs/armeabi-v7a/magiskboot uninstaller/arm
mkcp "libs/arm64-v8a/*" zip_static/arm64
mkcp libs/arm64-v8a/magiskboot uninstaller/arm64
mkcp "libs/x86/*" zip_static/x86
mkcp libs/x86/magiskboot uninstaller/x86
mkcp "libs/x86_64/*" zip_static/x64
mkcp libs/x86_64/magiskboot uninstaller/x64
}
zip_package() {
[ ! -f "zip_static/arm/magiskboot" ] && error "Missing binaries!! Please run '$0 build' before zipping"
echo "************************"
echo "* Adding version info"
echo "************************"
sed "s/MAGISK_VERSION_STUB/Magisk v$1 Boot Image Patcher/g" scripts/flash_script.sh > zip_static/META-INF/com/google/android/update-binary
sed "s/MAGISK_VERSION_STUB/setprop magisk.version \"$1\"/g" scripts/magic_mask.sh > zip_static/common/magic_mask.sh
echo "************************"
echo "* Copying files"
echo "************************"
cp -afv scripts/ramdisk_patch.sh zip_static/common/ramdisk_patch.sh
cp -afv scripts/init.magisk.rc zip_static/common/init.magisk.rc
cp -afv binaries/busybox-arm zip_static/arm/busybox
cp -afv binaries/busybox-arm64 zip_static/arm64/busybox
cp -afv binaries/busybox-x86 zip_static/x86/busybox
cp -afv binaries/busybox-x64 zip_static/x64/busybox
cp -afv binaries/chromeos/. zip_static/chromeos
echo "************************"
echo "* Zipping Magisk v$1"
echo "************************"
cd zip_static
find . -type f -exec chmod 644 {} \;
find . -type d -exec chmod 755 {} \;
rm -rf "../Magisk-v$1.zip"
zip "../Magisk-v$1.zip" -r .
cd ../
sign_zip "Magisk-v$1.zip"
}
zip_uninstaller() {
[ ! -f "uninstaller/arm/magiskboot" ] && error "Missing binaries!! Please run '$0 build' before zipping"
echo "************************"
echo "* Copying files"
echo "************************"
mkcp scripts/magisk_uninstaller.sh uninstaller/common
cp -afv binaries/busybox-arm uninstaller/arm/busybox
cp -afv binaries/busybox-arm64 uninstaller/arm64/busybox
cp -afv binaries/busybox-x86 uninstaller/x86/busybox
cp -afv binaries/busybox-x64 uninstaller/x64/busybox
cp -afv binaries/chromeos/. zip_static/chromeos
echo "************************"
echo "* Zipping uninstaller"
echo "************************"
mkcp scripts/magisk_uninstaller.sh uninstaller/common
cd uninstaller
find . -type f -exec chmod 644 {} \;
find . -type d -exec chmod 755 {} \;
TIMESTAMP=`date "+%Y%m%d"`
rm -rf "../Magisk-uninstaller-$TIMESTAMP.zip"
zip "../Magisk-uninstaller-$TIMESTAMP.zip" -r .
cd ../
sign_zip "Magisk-uninstaller-$TIMESTAMP.zip"
}
sign_zip() {
if [ ! -f "ziptools/zipadjust" ]; then
echo "************************"
echo "* Compiling ZipAdjust"
echo "************************"
gcc -o ziptools/zipadjust ziptools/src/*.c -lz || error "ZipAdjust Build failed...."
chmod 755 ziptools/zipadjust
fi
echo "************************"
echo "* First sign $1"
echo "************************"
java -jar "ziptools/signapk.jar" "ziptools/test.certificate.x509.pem" "ziptools/test.key.pk8" "$1" "${1%.*}-firstsign.zip"
echo "************************"
echo "* Adjusting $1"
echo "************************"
ziptools/zipadjust "${1%.*}-firstsign.zip" "${1%.*}-adjusted.zip"
echo "************************"
echo "* Final sign $1"
echo "************************"
java -jar "ziptools/minsignapk.jar" "ziptools/test.certificate.x509.pem" "ziptools/test.key.pk8" "${1%.*}-adjusted.zip" "${1%.*}-signed.zip"
mv "${1%.*}-signed.zip" "$1"
rm "${1%.*}-adjusted.zip" "${1%.*}-firstsign.zip"
}
DIR="$(cd "$(dirname "$0")"; pwd)"
cd "$DIR"
case $1 in
"all" )
[ -z "$2" ] && echo -e "! Missing version number\n" && usage
build_bin
zip_package $2
;;
"clean" )
cleanup
;;
"build" )
build_bin
;;
"zip" )
[ -z "$2" ] && echo -e "! Missing version number\n" && usage
zip_package $2
;;
"uninstaller" )
zip_uninstaller
;;
* )
usage
;;
esac

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 do 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,7 +0,0 @@
LOCAL_PATH := $(call my-dir)
include jni/magiskboot/Android.mk
include jni/magiskhide/Android.mk
include jni/resetprop/Android.mk
include jni/magiskpolicy/Android.mk
include jni/su/Android.mk

View File

@@ -1,3 +0,0 @@
APP_ABI := x86 x86_64 armeabi-v7a arm64-v8a
APP_PLATFORM := android-21
APP_CPPFLAGS += -std=c++11

View File

@@ -1,19 +0,0 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := magiskboot
LOCAL_STATIC_LIBRARIES := libz liblzma liblz4 libbz2
LOCAL_C_INCLUDES := \
jni/ndk-compression/zlib/ \
jni/ndk-compression/xz/src/liblzma/api/ \
jni/ndk-compression/lz4/lib/ \
jni/ndk-compression/bzip2/
LOCAL_SRC_FILES := main.c unpack.c repack.c hexpatch.c parseimg.c compress.c utils.c cpio.c sha1.c
LOCAL_CFLAGS += -DZLIB_CONST
include $(BUILD_EXECUTABLE)
include jni/ndk-compression/zlib/Android.mk
include jni/ndk-compression/xz/src/liblzma/Android.mk
include jni/ndk-compression/lz4/lib/Android.mk
include jni/ndk-compression/bzip2/Android.mk

View File

@@ -1,102 +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 dt_size; /* device tree 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;
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
** +-----------------+
** | device tree | 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 = (dt_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 {
uint8_t magic[4]; /* MTK magic */
uint32_t size; /* Size of the content */
uint8_t name[32]; /* The type of the header */
} mtk_hdr;
#endif

View File

@@ -1,479 +0,0 @@
#include <zlib.h>
#include <lzma.h>
#include <lz4frame.h>
#include <bzlib.h>
#include "magiskboot.h"
static void write_file(const int fd, const void *buf, const size_t size, const char *filename) {
if (write(fd, buf, size) != size)
error(1, "Error in writing %s", filename);
}
static void report(const int mode, const char* filename) {
switch(mode) {
case 0:
printf("Decompressing to [%s]\n\n", filename);
break;
default:
printf("Compressing to [%s]\n\n", filename);
break;
}
}
// Mode: 0 = decode; 1 = encode
void gzip(int mode, const char* filename, const unsigned char* buf, size_t size) {
size_t ret = 0, flush, have, pos = 0;
z_stream strm;
unsigned char out[CHUNK];
report(mode, filename);
int fd = open_new(filename);
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
switch(mode) {
case 0:
ret = inflateInit2(&strm, windowBits | ZLIB_GZIP);
break;
case 1:
ret = deflateInit2(&strm, 9, Z_DEFLATED, windowBits | ZLIB_GZIP, memLevel, Z_DEFAULT_STRATEGY);
break;
default:
error(1, "Unsupported gzip mode!");
}
if (ret != Z_OK)
error(1, "Unable to init zlib stream");
do {
strm.next_in = buf + pos;
if (pos + CHUNK >= size) {
strm.avail_in = size - pos;
flush = Z_FINISH;
} else {
strm.avail_in = CHUNK;
flush = Z_NO_FLUSH;
}
pos += strm.avail_in;
do {
strm.avail_out = CHUNK;
strm.next_out = out;
switch(mode) {
case 0:
ret = inflate(&strm, flush);
break;
case 1:
ret = deflate(&strm, flush);
break;
}
if (ret == Z_STREAM_ERROR)
error(1, "Error when running gzip");
have = CHUNK - strm.avail_out;
write_file(fd, out, have, filename);
} while (strm.avail_out == 0);
} while(pos < size);
switch(mode) {
case 0:
inflateEnd(&strm);
break;
case 1:
deflateEnd(&strm);
break;
}
close(fd);
}
// Mode: 0 = decode xz/lzma; 1 = encode xz; 2 = encode lzma
void lzma(int mode, const char* filename, const unsigned char* buf, size_t size) {
size_t have, pos = 0;
lzma_ret ret = 0;
lzma_stream strm = LZMA_STREAM_INIT;
lzma_options_lzma opt;
lzma_action action;
unsigned char out[BUFSIZ];
report(mode, filename);
int fd = open_new(filename);
// Initialize preset
lzma_lzma_preset(&opt, LZMA_PRESET_DEFAULT);
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_CRC64);
break;
case 2:
ret = lzma_alone_encoder(&strm, &opt);
break;
default:
error(1, "Unsupported lzma mode!");
}
if (ret != LZMA_OK)
error(1, "Unable to init lzma stream");
do {
strm.next_in = buf + pos;
if (pos + BUFSIZ >= size) {
strm.avail_in = size - pos;
action = LZMA_FINISH;
} else {
strm.avail_in = BUFSIZ;
action = LZMA_RUN;
}
pos += strm.avail_in;
do {
strm.avail_out = BUFSIZ;
strm.next_out = out;
ret = lzma_code(&strm, action);
have = BUFSIZ - strm.avail_out;
write_file(fd, out, have, filename);
} while (strm.avail_out == 0 && ret == LZMA_OK);
if (ret != LZMA_OK && ret != LZMA_STREAM_END)
error(1, "LZMA error %d!", ret);
} while (pos < size);
lzma_end(&strm);
}
// Mode: 0 = decode; 1 = encode
void lz4(int mode, const char* filename, const unsigned char* buf, size_t size) {
LZ4F_decompressionContext_t dctx;
LZ4F_compressionContext_t cctx;
LZ4F_frameInfo_t info;
size_t outCapacity, avail_in, ret = 0, pos = 0;
size_t have, read;
unsigned char *out = NULL;
report(mode, filename);
int fd = open_new(filename);
// Initialize context
switch(mode) {
case 0:
ret = LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION);
break;
case 1:
ret = LZ4F_createCompressionContext(&cctx, LZ4F_VERSION);
break;
default:
error(1, "Unsupported lz4 mode!");
}
if (LZ4F_isError(ret))
error(1, "Context creation error: %s\n", LZ4F_getErrorName(ret));
// Allocate out buffer
switch(mode) {
case 0:
// Read header
read = CHUNK;
ret = LZ4F_getFrameInfo(dctx, &info, buf, &read);
if (LZ4F_isError(ret))
error(1, "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:
error(1, "Impossible unless more block sizes are allowed\n");
}
pos += read;
break;
case 1:
outCapacity = LZ4F_compressBound(CHUNK, NULL) + LZ4_HEADER_SIZE + LZ4_FOOTER_SIZE;
break;
}
out = malloc(outCapacity);
if (!out)
error(1, "LZ4 malloc error!");
// Write header
if (mode == 1) {
have = ret = LZ4F_compressBegin(cctx, out, size, NULL);
if (LZ4F_isError(ret))
error(1, "Failed to start compression: error %s\n", LZ4F_getErrorName(ret));
write_file(fd, out, have, filename);
}
do {
if (pos + CHUNK >= size) {
avail_in = size - pos;
} else {
avail_in = CHUNK;
}
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))
error(1, "LZ4 coding error: %s\n", LZ4F_getErrorName(ret));
write_file(fd, out, have, filename);
// 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))
error(1, "Failed to end compression: error %s\n", LZ4F_getErrorName(ret));
write_file(fd, out, have, filename);
LZ4F_freeCompressionContext(cctx);
break;
}
free(out);
}
// Mode: 0 = decode; 1 = encode
void bzip2(int mode, const char* filename, const unsigned char* buf, size_t size) {
size_t ret = 0, action, have, pos = 0;
bz_stream strm;
char out[CHUNK];
report(mode, filename);
int fd = open_new(filename);
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;
default:
error(1, "Unsupported bzip2 mode!");
}
if (ret != BZ_OK)
error(1, "Unable to init bzlib stream");
do {
strm.next_in = (char *) buf + pos;
if (pos + CHUNK >= size) {
strm.avail_in = size - pos;
action = BZ_FINISH;
} else {
strm.avail_in = CHUNK;
action = BZ_RUN;
}
pos += strm.avail_in;
do {
strm.avail_out = CHUNK;
strm.next_out = out;
switch(mode) {
case 0:
ret = BZ2_bzDecompress(&strm);
break;
case 1:
ret = BZ2_bzCompress(&strm, action);
break;
}
have = CHUNK - strm.avail_out;
write_file(fd, out, have, filename);
} while (strm.avail_out == 0);
} while(pos < size);
switch(mode) {
case 0:
BZ2_bzDecompressEnd(&strm);
break;
case 1:
BZ2_bzCompressEnd(&strm);
break;
}
close(fd);
}
int decomp(file_t type, const char *to, const unsigned char *from, size_t size) {
switch (type) {
case GZIP:
gzip(0, to, from, size);
break;
case XZ:
lzma(0, to, from, size);
break;
case LZMA:
lzma(0, to, from, size);
break;
case BZIP2:
bzip2(0, to, from, size);
break;
case LZ4:
lz4(0, to, from, size);
break;
default:
// Unsupported
return 1;
}
return 0;
}
// Output will be to.ext
int comp(file_t type, const char *to, const unsigned char *from, size_t size) {
char name[PATH_MAX];
const char *ext = strrchr(to, '.');
if (ext == NULL) ext = to;
strcpy(name, to);
switch (type) {
case GZIP:
if (strcmp(ext, ".gz") != 0)
sprintf(name, "%s.%s", to, "gz");
gzip(1, name, from, size);
break;
case XZ:
if (strcmp(ext, ".xz") != 0)
sprintf(name, "%s.%s", to, "xz");
lzma(1, name, from, size);
break;
case LZMA:
if (strcmp(ext, ".lzma") != 0)
sprintf(name, "%s.%s", to, "lzma");
lzma(2, name, from, size);
break;
case BZIP2:
if (strcmp(ext, ".bz2") != 0)
sprintf(name, "%s.%s", to, "bz2");
bzip2(1, name, from, size);
break;
case LZ4:
if (strcmp(ext, ".lz4") != 0)
sprintf(name, "%s.%s", to, "lz4");
lz4(1, name, from, size);
break;
default:
// Unsupported
return 1;
}
return 0;
}
void decomp_file(char *from, const char *to) {
int ok = 1;
unsigned char *file;
size_t size;
mmap_ro(from, &file, &size);
file_t type = check_type(file);
char *ext;
ext = strrchr(from, '.');
if (ext == NULL)
error(1, "Bad filename extention");
// File type and extension should match
switch (type) {
case GZIP:
if (strcmp(ext, ".gz") != 0)
ok = 0;
break;
case XZ:
if (strcmp(ext, ".xz") != 0)
ok = 0;
break;
case LZMA:
if (strcmp(ext, ".lzma") != 0)
ok = 0;
break;
case BZIP2:
if (strcmp(ext, ".bz2") != 0)
ok = 0;
break;
case LZ4:
if (strcmp(ext, ".lz4") != 0)
ok = 0;
break;
default:
error(1, "Provided file \'%s\' is not a supported archive format", from);
}
if (ok) {
// If all match, strip out the suffix
if (!to) {
*ext = '\0';
to = from;
}
decomp(type, to, file, size);
if (to == from) {
*ext = '.';
unlink(from);
}
} else {
error(1, "Bad filename extention \'%s\'", ext);
}
munmap(file, size);
}
void comp_file(const char *method, const char *from, const char *to) {
file_t type;
if (strcmp(method, "gzip") == 0) {
type = GZIP;
} else if (strcmp(method, "xz") == 0) {
type = XZ;
} else if (strcmp(method, "lzma") == 0) {
type = LZMA;
} else if (strcmp(method, "lz4") == 0) {
type = LZ4;
} else if (strcmp(method, "bzip2") == 0) {
type = BZIP2;
} else {
error(1, "Only support following methods: " SUP_LIST);
}
unsigned char *file;
size_t size;
mmap_ro(from, &file, &size);
if (!to)
to = from;
comp(type, to, file, size);
munmap(file, size);
if (to == from)
unlink(from);
}

View File

@@ -1,480 +0,0 @@
#include "magiskboot.h"
#include "cpio.h"
static uint32_t x8u(char *hex) {
uint32_t val, inpos = 8, outpos;
char pattern[6];
while (*hex == '0') {
hex++;
if (!--inpos) return 0;
}
// Because scanf gratuitously treats %*X differently than printf does.
sprintf(pattern, "%%%dx%%n", inpos);
sscanf(hex, pattern, &val, &outpos);
if (inpos != outpos) error(1, "bad cpio header");
return val;
}
static void cpio_free(cpio_file *f) {
if (f) {
free(f->filename);
free(f->data);
free(f);
}
}
static void cpio_vec_insert(vector *v, cpio_file *n) {
cpio_file *f, *t;
int shift = 0;
// Insert in alphabet order
vec_for_each(v, f) {
if (shift) {
vec_entry(v)[_i] = t;
t = f;
continue;
}
t = f;
if (strcmp(f->filename, n->filename) == 0) {
// Replace, then all is done
cpio_free(f);
vec_entry(v)[_i] = n;
return;
} else if (strcmp(f->filename, n->filename) > 0) {
// Insert, then start shifting
vec_entry(v)[_i] = n;
t = f;
shift = 1;
}
}
if (shift)
vec_push_back(v, t);
else
vec_push_back(v, n);
}
static int cpio_compare(const void *a, const void *b) {
return strcmp((*(cpio_file **) a)->filename, (*(cpio_file **) b)->filename);
}
// Parse cpio file to a vector of cpio_file
static void parse_cpio(const char *filename, vector *v) {
printf("Loading cpio: [%s]\n\n", filename);
int fd = open(filename, O_RDONLY);
if (fd < 0)
error(1, "Cannot open %s", filename);
cpio_newc_header header;
cpio_file *f;
while(read(fd, &header, 110) == 110) {
f = calloc(sizeof(*f), 1);
// f->ino = x8u(header.ino);
f->mode = x8u(header.mode);
f->uid = x8u(header.uid);
f->gid = x8u(header.gid);
// f->nlink = x8u(header.nlink);
// f->mtime = x8u(header.mtime);
f->filesize = x8u(header.filesize);
// f->devmajor = x8u(header.devmajor);
// f->devminor = x8u(header.devminor);
// f->rdevmajor = x8u(header.rdevmajor);
// f->rdevminor = x8u(header.rdevminor);
f->namesize = x8u(header.namesize);
// f->check = x8u(header.check);
f->filename = malloc(f->namesize);
read(fd, f->filename, f->namesize);
file_align(fd, 4, 0);
if (strcmp(f->filename, ".") == 0 || strcmp(f->filename, "..") == 0) {
cpio_free(f);
continue;
}
if (strcmp(f->filename, "TRAILER!!!") == 0) {
cpio_free(f);
break;
}
if (f->filesize) {
f->data = malloc(f->filesize);
read(fd, f->data, f->filesize);
file_align(fd, 4, 0);
}
vec_push_back(v, f);
}
close(fd);
// Sort by name
vec_sort(v, cpio_compare);
}
static void dump_cpio(const char *filename, vector *v) {
printf("\nDump cpio: [%s]\n\n", filename);
int fd = open_new(filename);
unsigned inode = 300000;
char header[111];
cpio_file *f;
vec_for_each(v, f) {
if (f->remove) continue;
sprintf(header, "070701%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x",
inode++, // f->ino
f->mode,
f->uid,
f->gid,
1, // f->nlink
0, // f->mtime
f->filesize,
0, // f->devmajor
0, // f->devminor
0, // f->rdevmajor
0, // f->rdevminor
f->namesize,
0 // f->check
);
write(fd, header, 110);
write(fd, f->filename, f->namesize);
file_align(fd, 4, 1);
if (f->filesize) {
write(fd, f->data, f->filesize);
file_align(fd, 4, 1);
}
}
// Write trailer
sprintf(header, "070701%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x", inode++, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 11, 0);
write(fd, header, 110);
write(fd, "TRAILER!!!\0", 11);
file_align(fd, 4, 1);
close(fd);
}
static void cpio_vec_destroy(vector *v) {
// Free each cpio_file
cpio_file *f;
vec_for_each(v, f) {
cpio_free(f);
}
vec_destroy(v);
}
static void cpio_rm(int recursive, const char *entry, vector *v) {
cpio_file *f;
vec_for_each(v, f) {
if ((recursive && strncmp(f->filename, entry, strlen(entry)) == 0)
|| (strcmp(f->filename, entry) == 0) ) {
if (!f->remove) {
printf("Remove [%s]\n", entry);
f->remove = 1;
}
if (!recursive) return;
}
}
}
static void cpio_mkdir(mode_t mode, const char *entry, vector *v) {
cpio_file *f = calloc(sizeof(*f), 1);
f->mode = S_IFDIR | mode;
f->namesize = strlen(entry) + 1;
f->filename = malloc(f->namesize);
memcpy(f->filename, entry, f->namesize);
cpio_vec_insert(v, f);
printf("Create directory [%s] (%04o)\n",entry, mode);
}
static void cpio_add(mode_t mode, const char *entry, const char *filename, vector *v) {
int fd = open(filename, O_RDONLY);
if (fd < 0)
error(1, "Cannot open %s", filename);
cpio_file *f = calloc(sizeof(*f), 1);
f->mode = S_IFREG | mode;
f->namesize = strlen(entry) + 1;
f->filename = malloc(f->namesize);
memcpy(f->filename, entry, f->namesize);
f->filesize = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
f->data = malloc(f->filesize);
read(fd, f->data, f->filesize);
close(fd);
cpio_vec_insert(v, f);
printf("Add entry [%s] (%04o)\n", entry, mode);
}
static void cpio_test(vector *v) {
int ret = 0;
cpio_file *f;
vec_for_each(v, f) {
if (strcmp(f->filename, "sbin/launch_daemonsu.sh") == 0) {
if (!ret) ret = 2;
} else if (strcmp(f->filename, "init.magisk.rc") == 0) {
ret = 1;
break;
}
}
cpio_vec_destroy(v);
exit(ret);
}
static int check_verity_pattern(const char *s) {
int pos = 0;
if (s[0] == ',') ++pos;
if (strncmp(s + pos, "verify", 6) != 0) return -1;
pos += 6;
if (s[pos] == '=') {
while (s[pos] != ' ' && s[pos] != '\n' && s[pos] != ',') ++pos;
}
return pos;
}
static void cpio_dmverity(vector *v) {
cpio_file *f;
size_t read, write;
int skip;
vec_for_each(v, f) {
if (strstr(f->filename, "fstab") != NULL && S_ISREG(f->mode)) {
for (read = 0, write = 0; read < f->filesize; ++read, ++write) {
skip = check_verity_pattern(f->data + read);
if (skip > 0) {
printf("Remove pattern [%.*s] in [%s]\n", (int) skip, f->data + read, f->filename);
read += skip;
}
f->data[write] = f->data[read];
}
f->filesize = write;
} else if (strcmp(f->filename, "verity_key") == 0) {
f->remove = 1;
break;
}
}
}
static void cpio_forceencrypt(vector *v) {
cpio_file *f;
size_t read, write;
#define ENCRYPT_LIST_SIZE 2
const char *ENCRYPT_LIST[ENCRYPT_LIST_SIZE] = { "forceencrypt", "forcefdeorfbe" };
vec_for_each(v, f) {
if (strstr(f->filename, "fstab") != NULL && S_ISREG(f->mode)) {
for (read = 0, write = 0; read < f->filesize; ++read, ++write) {
for (int i = 0 ; i < ENCRYPT_LIST_SIZE; ++i) {
if (strncmp(f->data + read, ENCRYPT_LIST[i], strlen(ENCRYPT_LIST[i])) == 0) {
memcpy(f->data + write, "encryptable", 11);
printf("Replace [%s] with [%s] in [%s]\n", ENCRYPT_LIST[i], "encryptable", f->filename);
write += 11;
read += strlen(ENCRYPT_LIST[i]);
break;
}
}
f->data[write] = f->data[read];
}
f->filesize = write;
}
}
}
static void cpio_extract(const char *entry, const char *filename, vector *v) {
cpio_file *f;
vec_for_each(v, f) {
if (strcmp(f->filename, entry) == 0 && S_ISREG(f->mode)) {
printf("Extracting [%s] to [%s]\n\n", entry, filename);
int fd = open_new(filename);
write(fd, f->data, f->filesize);
fchmod(fd, f->mode);
fchown(fd, f->uid, f->gid);
close(fd);
exit(0);
}
}
error(1, "Cannot find the file entry [%s]", entry);
}
static void cpio_backup(const char *orig, vector *v) {
vector o_body, *o = &o_body, bak;
cpio_file *m, *n, *dir, *rem;
char chk1[21], chk2[21], buf[PATH_MAX];
int res, doBak;
dir = calloc(sizeof(*dir), 1);
rem = calloc(sizeof(*rem), 1);
vec_init(o);
vec_init(&bak);
// First push back the directory and the rmlist
vec_push_back(&bak, dir);
vec_push_back(&bak, rem);
parse_cpio(orig, o);
// Remove possible backups in original ramdisk
cpio_rm(1, ".backup", o);
cpio_rm(1, ".backup", v);
// Init the directory and rmlist
dir->filename = strdup(".backup");
dir->namesize = strlen(dir->filename) + 1;
dir->mode = S_IFDIR;
rem->filename = strdup(".backup/.rmlist");
rem->namesize = strlen(rem->filename) + 1;
rem->mode = S_IFREG;
// Start comparing
size_t i = 0, j = 0;
while(i != vec_size(o) || j != vec_size(v)) {
doBak = 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;
doBak = 1;
printf("Entry [%s] is missing\n", m->filename);
} else if (res == 0) {
++i; ++j;
if (m->filesize == n->filesize && memcmp(m->data, n->data, m->filesize) == 0)
continue;
// Not the same!
doBak = 1;
printf("Entry [%s] missmatch\n", m->filename);
} else {
// Someting new in ramdisk, record in rem
++j;
if (n->remove) continue;
rem->data = realloc(rem->data, rem->filesize + n->namesize);
memcpy(rem->data + rem->filesize, n->filename, n->namesize);
rem->filesize += n->namesize;
printf("Entry [%s] is new\n", n->filename);
}
if (doBak) {
m->namesize += 8;
m->filename = realloc(m->filename, m->namesize);
strcpy(buf, m->filename);
sprintf(m->filename, ".backup/%s", buf);
vec_push_back(&bak, m);
// NULL the original entry, so it won't be freed
vec_entry(o)[i - 1] = NULL;
}
}
// Add the backup files to the original ramdisk
vec_for_each(&bak, m) {
vec_push_back(v, m);
}
// Don't include if empty
if (rem->filesize == 0) {
rem->remove = 1;
if (bak.size == 2)
dir->remove = 1;
}
// Sort
vec_sort(v, cpio_compare);
// Cleanup
cpio_vec_destroy(o);
}
static int cpio_restore(vector *v) {
cpio_file *f, *n;
int ret = 1;
vec_for_each(v, f) {
if (strstr(f->filename, ".backup") != NULL) {
ret = 0;
f->remove = 1;
if (strcmp(f->filename, ".backup") == 0) continue;
if (strcmp(f->filename, ".backup/.rmlist") == 0) {
for (int pos = 0; pos < f->filesize; pos += strlen(f->data + pos) + 1)
cpio_rm(0, f->data + pos, v);
continue;
}
n = calloc(sizeof(*n), 1);
memcpy(n, f, sizeof(*f));
n->namesize -= 8;
n->filename = malloc(n->namesize);
memcpy(n->filename, f->filename + 8, n->namesize);
n->data = malloc(n->filesize);
memcpy(n->data, f->data, n->filesize);
n->remove = 0;
printf("Restoring [%s] -> [%s]\n", f->filename, n->filename);
cpio_vec_insert(v, n);
}
}
// Some known stuff we can remove
cpio_rm(0, "sbin/magic_mask.sh", v);
cpio_rm(0, "init.magisk.rc", v);
cpio_rm(0, "magisk", v);
return ret;
}
int cpio_commands(const char *command, int argc, char *argv[]) {
int recursive = 0, ret = 0;
command_t cmd;
char *incpio = argv[0];
++argv;
--argc;
if (strcmp(command, "test") == 0) {
cmd = TEST;
} else if (strcmp(command, "patch-dmverity") == 0) {
cmd = DMVERITY;
} else if (strcmp(command, "patch-forceencrypt") == 0) {
cmd = FORCEENCRYPT;
} else if (strcmp(command, "restore") == 0) {
cmd = RESTORE;
} else if (argc == 1 && strcmp(command, "backup") == 0) {
cmd = BACKUP;
} else if (argc > 0 && strcmp(command, "rm") == 0) {
cmd = RM;
if (argc == 2 && strcmp(argv[0], "-r") == 0) {
recursive = 1;
++argv;
--argc;
}
} else if (argc == 2 && strcmp(command, "extract") == 0) {
cmd = EXTRACT;
} else if (argc == 2 && strcmp(command, "mkdir") == 0) {
cmd = MKDIR;
} else if (argc == 3 && strcmp(command, "add") == 0) {
cmd = ADD;
} else {
cmd = NONE;
return 1;
}
vector v;
vec_init(&v);
parse_cpio(incpio, &v);
switch(cmd) {
case TEST:
cpio_test(&v);
break;
case DMVERITY:
cpio_dmverity(&v);
break;
case FORCEENCRYPT:
cpio_forceencrypt(&v);
break;
case RESTORE:
ret = cpio_restore(&v);
break;
case BACKUP:
cpio_backup(argv[0], &v);
case RM:
cpio_rm(recursive, argv[0], &v);
break;
case EXTRACT:
cpio_extract(argv[0], argv[1], &v);
break;
case MKDIR:
cpio_mkdir(strtoul(argv[0], NULL, 8), argv[1], &v);
break;
case ADD:
cpio_add(strtoul(argv[0], NULL, 8), argv[1], argv[2], &v);
break;
default:
// Never happen
break;
}
dump_cpio(incpio, &v);
cpio_vec_destroy(&v);
exit(ret);
}

View File

@@ -1,42 +0,0 @@
#ifndef _CPIO_H_
#define _CPIO_H_
#include <stdint.h>
typedef struct cpio_file {
// 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;
char *data;
int remove;
} cpio_file;
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;
#endif

View File

@@ -1,151 +0,0 @@
#ifndef _ELF_H_
#define _ELF_H_
#include <stdint.h>
/*
** ELF structure
**
** +-----------------+
** | ELF magic | | 4 bytes
** +------------ +
** | ELF class | | 1 byte
** +------------ +
** | ELF header |
** +-----------------+
** ~
** +-----------------+
** | program header | kernel info
** +-----------------+
** | program header | ramdisk info
** +-----------------+
** | program header | dtb info
** +-----------------+
** | program header | (possible) cmdline info
** +-----------------+
** ~
** +-----------------+
** | section header | cmdline info
** +-----------------+
** ~
** +-----------------+
** | |
** | Data |
** | |
** +-----------------+
*/
typedef uint32_t elf32_addr;
typedef uint16_t elf32_half;
typedef uint32_t elf32_off;
typedef uint32_t elf32_word;
typedef uint64_t elf64_addr;
typedef uint16_t elf64_half;
typedef uint64_t elf64_off;
typedef uint32_t elf64_word;
typedef uint64_t elf64_xword;
#define ELF_MAGIC "\x7f""ELF"
#define ELF_MAGIC_SIZE 4
#define EI_CLASS 4
#define EI_DATA 5
#define EI_VERSION 6
#define EI_OSABI 7
#define EI_PAD 8
#define ELFCLASSNONE 0
#define ELFCLASS32 1
#define ELFCLASS64 2
#define ELFCLASSNUM 3
#define ET_EXEC 2
#define EM_ARM 40
#define EI_NIDENT 16
typedef struct elf32_ehdr {
unsigned char e_ident[EI_NIDENT];
elf32_half e_type;
elf32_half e_machine;
elf32_word e_version;
elf32_addr e_entry; /* Entry point */
elf32_off e_phoff;
elf32_off e_shoff;
elf32_word e_flags;
elf32_half e_ehsize;
elf32_half e_phentsize;
elf32_half e_phnum;
elf32_half e_shentsize;
elf32_half e_shnum;
elf32_half e_shstrndx;
} elf32_ehdr;
typedef struct elf64_ehdr {
unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */
elf64_half e_type;
elf64_half e_machine;
elf64_word e_version;
elf64_addr e_entry; /* Entry point virtual address */
elf64_off e_phoff; /* Program header table file offset */
elf64_off e_shoff; /* Section header table file offset */
elf64_word e_flags;
elf64_half e_ehsize;
elf64_half e_phentsize;
elf64_half e_phnum;
elf64_half e_shentsize;
elf64_half e_shnum;
elf64_half e_shstrndx;
} elf64_ehdr;
typedef struct elf32_phdr {
elf32_word p_type;
elf32_off p_offset;
elf32_addr p_vaddr;
elf32_addr p_paddr;
elf32_word p_filesz;
elf32_word p_memsz;
elf32_word p_flags;
elf32_word p_align;
} elf32_phdr;
typedef struct elf64_phdr {
elf64_word p_type;
elf64_word p_flags;
elf64_off p_offset; /* Segment file offset */
elf64_addr p_vaddr; /* Segment virtual address */
elf64_addr p_paddr; /* Segment physical address */
elf64_xword p_filesz; /* Segment size in file */
elf64_xword p_memsz; /* Segment size in memory */
elf64_xword p_align; /* Segment alignment, file & memory */
} elf64_phdr;
typedef struct elf32_shdr {
elf32_word s_name;
elf32_word s_type;
elf32_word s_flags;
elf32_addr s_addr;
elf32_off s_offset;
elf32_word s_size;
elf32_word s_link;
elf32_word s_info;
elf32_word s_addralign;
elf32_word s_entsize;
} elf32_shdr;
typedef struct elf64_shdr {
elf64_word s_name; /* Section name, index in string tbl */
elf64_word s_type; /* Type of section */
elf64_xword s_flags; /* Miscellaneous section attributes */
elf64_addr s_addr; /* Section virtual addr at execution */
elf64_off s_offset; /* Section file offset */
elf64_xword s_size; /* Size of section in bytes */
elf64_word s_link; /* Index of another section */
elf64_word s_info; /* Additional section information */
elf64_xword s_addralign; /* Section alignment */
elf64_xword s_entsize; /* Entry size if section holds table */
} elf64_shdr;
#endif

View File

@@ -1,127 +0,0 @@
#ifndef _MAGISKBOOT_H_
#define _MAGISKBOOT_H_
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/sendfile.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>
#include "bootimg.h"
#include "sha1.h"
#define windowBits 15
#define ZLIB_GZIP 16
#define memLevel 8
#define CHUNK 0x40000
#define LZ4_HEADER_SIZE 19
#define LZ4_FOOTER_SIZE 4
#define CHROMEOS_MAGIC "CHROMEOS"
#define CHROMEOS_MAGIC_SIZE 8
#define KERNEL_FILE "kernel"
#define RAMDISK_FILE "ramdisk.cpio"
#define SECOND_FILE "second"
#define DTB_FILE "dtb"
#define NEW_BOOT "new-boot.img"
#define SUP_LIST "gzip, xz, lzma, lz4, bzip2"
#define SUP_NUM 5
typedef enum {
UNKNOWN,
CHROMEOS,
AOSP,
ELF,
GZIP,
LZOP,
XZ,
LZMA,
BZIP2,
LZ4,
MTK,
QCDT,
} file_t;
typedef enum {
NONE,
RM,
MKDIR,
ADD,
EXTRACT,
TEST,
DMVERITY,
FORCEENCRYPT,
BACKUP,
RESTORE
} command_t;
extern char *SUP_EXT_LIST[SUP_NUM];
extern file_t SUP_TYPE_LIST[SUP_NUM];
// Cannot declare in header, but place a copy here for convenience
// char *SUP_EXT_LIST[SUP_NUM] = { "gz", "xz", "lzma", "bz2", "lz4" };
// file_t SUP_TYPE_LIST[SUP_NUM] = { GZIP, XZ, LZMA, BZIP2, LZ4 };
// Vector
typedef struct vector {
size_t size;
size_t cap;
void **data;
} vector;
void vec_init(vector *v);
void vec_push_back(vector *v, void *p);
void vec_sort(vector *v, int (*compar)(const void *, const void *));
void vec_destroy(vector *v);
#define vec_size(v) (v)->size
#define vec_cap(v) (v)->cap
#define vec_entry(v) (v)->data
// vec_for_each(vector *v, void *e)
#define vec_for_each(v, e) \
e = (v)->data[0]; \
for (size_t _i = 0; _i < (v)->size; ++_i, e = (v)->data[_i])
// Global variables
extern unsigned char *kernel, *ramdisk, *second, *dtb, *extra;
extern boot_img_hdr hdr;
extern file_t boot_type, ramdisk_type, dtb_type;
extern int mtk_kernel, mtk_ramdisk;
// Main entries
void 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);
void error(int rc, const char *msg, ...);
void parse_img(unsigned char *orig, size_t size);
int cpio_commands(const char *command, int argc, char *argv[]);
void cleanup();
// Compressions
void gzip(int mode, const char* filename, const unsigned char* buf, size_t size);
void lzma(int mode, const char* filename, const unsigned char* buf, size_t size);
void lz4(int mode, const char* filename, const unsigned char* buf, size_t size);
void bzip2(int mode, const char* filename, const unsigned char* buf, size_t size);
int comp(file_t type, const char *to, const unsigned char *from, size_t size);
void comp_file(const char *method, const char *from, const char *to);
int decomp(file_t type, const char *to, const unsigned char *from, size_t size);
void decomp_file(char *from, const char *to);
// Utils
void mmap_ro(const char *filename, unsigned char **buf, size_t *size);
void mmap_rw(const char *filename, unsigned char **buf, size_t *size);
file_t check_type(const unsigned char *buf);
void write_zero(int fd, size_t size);
void mem_align(size_t *pos, size_t align);
void file_align(int fd, size_t align, int out);
int open_new(const char *filename);
void print_info();
#endif

View File

@@ -1,104 +0,0 @@
#include "magiskboot.h"
/********************
Patch Boot Image
*********************/
static void usage(char *arg0) {
fprintf(stderr, "%s --unpack <bootimg>\n", arg0);
fprintf(stderr, " Unpack <bootimg> to kernel, ramdisk.cpio, (second), (dtb) into the\n current directory\n");
fprintf(stderr, "\n");
fprintf(stderr, "%s --repack <origbootimg> [outbootimg]\n", arg0);
fprintf(stderr, " Repack kernel, ramdisk.cpio[.ext], second, dtb... from current directory\n");
fprintf(stderr, " to [outbootimg], or new-boot.img if not specified.\n");
fprintf(stderr, " It will compress ramdisk.cpio with the same method used in <origbootimg>\n");
fprintf(stderr, " if exists, or attempt to find ramdisk.cpio.[ext], and repack\n");
fprintf(stderr, " directly with the compressed ramdisk file\n");
fprintf(stderr, "\n");
fprintf(stderr, "%s --hexpatch <file> <hexpattern1> <hexpattern2>\n", arg0);
fprintf(stderr, " Search <hexpattern1> in <file>, and replace with <hexpattern2>\n");
fprintf(stderr, "\n");
fprintf(stderr, "%s --cpio-<cmd> <incpio> [flags...] [params...]\n", arg0);
fprintf(stderr, " Do cpio related cmds to <incpio> (modifications are done directly)\n Supported commands:\n");
fprintf(stderr, " --cpio-rm <incpio> [-r] <entry>\n Remove entry from cpio, flag -r to remove recursively\n");
fprintf(stderr, " --cpio-mkdir <incpio> <mode> <entry>\n Create directory as an <entry>\n");
fprintf(stderr, " --cpio-add <incpio> <mode> <entry> <infile>\n Add <infile> as an <entry>; replaces <entry> if already exists\n");
fprintf(stderr, " --cpio-extract <incpio> <entry> <outfile>\n Extract <entry> to <outfile>\n");
fprintf(stderr, " --cpio-test <incpio>\n Return value: 0/not patched 1/Magisk 2/SuperSU\n");
fprintf(stderr, " --cpio-patch-dmverity <incpio>\n Remove dm-verity\n");
fprintf(stderr, " --cpio-patch-forceencrypt <incpio>\n Change forceencrypt flag to encryptable\n");
fprintf(stderr, " --cpio-backup <incpio> <origcpio>\n Create ramdisk backups into <incpio> from <origcpio>\n");
fprintf(stderr, " --cpio-restore <incpio>\n Restore ramdisk from ramdisk backup within <incpio>\n");
fprintf(stderr, "\n");
fprintf(stderr, "%s --compress[=method] <infile> [outfile]\n", arg0);
fprintf(stderr, " Compress <infile> with [method](default: gzip), optionally to [outfile]\n Supported methods: " SUP_LIST "\n");
fprintf(stderr, "\n");
fprintf(stderr, "%s --decompress <infile> [outfile]\n", arg0);
fprintf(stderr, " Detect method and decompress <infile>, optionally to [outfile]\n Supported methods: " SUP_LIST "\n");
fprintf(stderr, "\n");
fprintf(stderr, "%s --sha1 <file>\n", arg0);
fprintf(stderr, " Print the SHA1 checksum for <file>\n");
fprintf(stderr, "\n");
fprintf(stderr, "%s --cleanup\n", arg0);
fprintf(stderr, " Cleanup the current working directory\n");
fprintf(stderr, "\n");
exit(1);
}
void error(int rc, const char *msg, ...) {
va_list ap;
va_start(ap, msg);
vfprintf(stderr, msg, ap);
fprintf(stderr,"\n\n");
va_end(ap);
exit(rc);
}
int main(int argc, char *argv[]) {
printf("MagiskBoot (by topjohnwu) - Boot Image Modification Tool\n\n");
if (argc > 1 && strcmp(argv[1], "--cleanup") == 0) {
cleanup();
} else if (argc > 2 && strcmp(argv[1], "--sha1") == 0) {
char sha1[21], *buf;
size_t size;
mmap_ro(argv[2], (unsigned char **) &buf, &size);
SHA1(sha1, buf, size);
for (int i = 0; i < 20; ++i)
printf("%02x", sha1[i]);
printf("\n");
munmap(buf, size);
} else if (argc > 2 && strcmp(argv[1], "--unpack") == 0) {
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 && strncmp(argv[1], "--cpio", 6) == 0) {
char *command;
command = strchr(argv[1] + 2, '-');
if (command == NULL) usage(argv[0]);
else ++command;
if (cpio_commands(command, argc - 2, argv + 2)) usage(argv[0]);
} else {
usage(argv[0]);
}
return 0;
}

View File

@@ -1,252 +0,0 @@
#include "bootimg.h"
#include "elf.h"
#include "magiskboot.h"
unsigned char *kernel, *ramdisk, *second, *dtb, *extra;
boot_img_hdr hdr;
int mtk_kernel = 0, mtk_ramdisk = 0;
file_t boot_type, ramdisk_type, dtb_type;
static void check_headers() {
// Check ramdisk compression type
ramdisk_type = check_type(ramdisk);
// Check MTK
if (check_type(kernel) == MTK) {
printf("MTK header found in kernel\n");
mtk_kernel = 1;
}
if (check_type(ramdisk) == MTK) {
printf("MTK header found in ramdisk\n");
mtk_ramdisk = 1;
}
// Check dtb if ELF boot
if (boot_type == ELF && hdr.dt_size) {
dtb_type = check_type(dtb);
}
// Print info
print_info();
}
static void elf_header_check(void *elf, int is64) {
size_t e_size, mach, ver, p_size, p_num, s_size, s_num;
size_t r_e_size, r_p_size, r_s_size;
if (is64) {
e_size = ((elf64_ehdr *) elf)->e_ehsize;
mach = ((elf64_ehdr *) elf)->e_machine;
ver = ((elf64_ehdr *) elf)->e_version;
p_size = ((elf64_ehdr *) elf)->e_phentsize;
p_num = ((elf64_ehdr *) elf)->e_phnum;
s_size = ((elf64_ehdr *) elf)->e_shentsize;
s_num = ((elf64_ehdr *) elf)->e_shnum;
r_e_size = sizeof(elf64_ehdr);
r_p_size = sizeof(elf64_phdr);
r_s_size = sizeof(elf64_shdr);
} else {
e_size = ((elf32_ehdr *) elf)->e_ehsize;
mach = ((elf32_ehdr *) elf)->e_machine;
ver = ((elf32_ehdr *) elf)->e_version;
p_size = ((elf32_ehdr *) elf)->e_phentsize;
p_num = ((elf32_ehdr *) elf)->e_phnum;
s_size = ((elf32_ehdr *) elf)->e_shentsize;
s_num = ((elf32_ehdr *) elf)->e_shnum;
r_e_size = sizeof(elf32_ehdr);
r_p_size = sizeof(elf32_phdr);
r_s_size = sizeof(elf32_shdr);
}
if (e_size != r_e_size)
error(1, "Header size not %d", r_e_size);
if (mach != EM_ARM)
error(1, "ELF machine is not ARM");
if (ver != 1)
error(1, "Unknown ELF version");
if (p_size != r_p_size)
error(1, "Program header size not %d", r_p_size);
if (p_num < 2 || p_num > 4)
error(1, "Unexpected number of elements: %d", p_num);
if (s_num && s_size != r_s_size)
error(1, "Section header size not %d", r_s_size);
if (s_num > 1)
error(1, "More than one section header");
}
static void elf_set(int i, unsigned char *base, size_t size, size_t offset, size_t addr) {
if (size <= 4096) {
// Possible cmdline
memset(hdr.cmdline, 0, BOOT_ARGS_SIZE);
strncpy((char *) hdr.cmdline, (char *) (base + offset), BOOT_ARGS_SIZE);
hdr.cmdline[strcspn((char*) hdr.cmdline, "\n")] = '\0';
return;
}
switch(i) {
case 0:
// kernel
kernel = base + offset;
hdr.kernel_size = size;
hdr.kernel_addr = addr;
break;
case 1:
// ramdisk
ramdisk = base + offset;
hdr.ramdisk_size = size;
hdr.ramdisk_addr = addr;
break;
case 2:
// dtb
dtb = base + offset;
hdr.dt_size = size;
hdr.tags_addr = addr;
break;
}
}
static void parse_elf(unsigned char *base) {
// Reset boot image header
memset(&hdr, 0, sizeof(hdr));
// Hardcode header magic and pagesize
memcpy(hdr.magic, BOOT_MAGIC, BOOT_MAGIC_SIZE);
hdr.page_size = 4096;
switch(base[EI_CLASS]) {
case ELFCLASS32: {
elf32_ehdr *elf32;
elf32_phdr *ph32;
elf32_shdr *sh32;
printf("IMAGE [ELF32]\n");
elf32 = (elf32_ehdr *) base;
elf_header_check(elf32, 0);
ph32 = (elf32_phdr *) (base + elf32->e_phoff);
sh32 = (elf32_shdr *) (base + elf32->e_shoff);
for (int i = 0; i < elf32->e_phnum; ++i) {
elf_set(i, base, ph32[i].p_filesz, ph32[i].p_offset, ph32[i].p_paddr);
}
if (elf32->e_shnum) {
// cmdline
memset(hdr.cmdline, 0, BOOT_ARGS_SIZE);
strncpy((char *) hdr.cmdline, (char *) (base + sh32->s_offset + 8), BOOT_ARGS_SIZE);
hdr.cmdline[strcspn((char*) hdr.cmdline, "\n")] = '\0';
}
break;
}
case ELFCLASS64: {
elf64_ehdr *elf64;
elf64_phdr *ph64;
elf64_shdr *sh64;
printf("IMAGE [ELF64]\n");
elf64 = (elf64_ehdr *) base;
elf_header_check(elf64, 1);
ph64 = (elf64_phdr *) (base + elf64->e_phoff);
sh64 = (elf64_shdr *) (base + elf64->e_shoff);
for (int i = 0; i < elf64->e_phnum; ++i) {
elf_set(i, base, ph64[i].p_filesz, ph64[i].p_offset, ph64[i].p_paddr);
}
if (elf64->e_shnum) {
// cmdline
memset(hdr.cmdline, 0, BOOT_ARGS_SIZE);
strncpy((char *) hdr.cmdline, (char *) (base + sh64->s_offset + 8), BOOT_ARGS_SIZE);
hdr.cmdline[strcspn((char*) hdr.cmdline, "\n")] = '\0';
}
break;
}
default:
error(1, "ELF format error!");
}
check_headers();
}
static void parse_aosp(unsigned char *base, size_t size) {
printf("IMG [AOSP]\n");
size_t pos = 0;
// Read the header
memcpy(&hdr, base, sizeof(hdr));
pos += hdr.page_size;
// Kernel position
kernel = base + pos;
pos += hdr.kernel_size;
mem_align(&pos, hdr.page_size);
// Ramdisk position
ramdisk = base + pos;
pos += hdr.ramdisk_size;
mem_align(&pos, hdr.page_size);
if (hdr.second_size) {
// Second position
second = base + pos;
pos += hdr.second_size;
mem_align(&pos, hdr.page_size);
}
if (hdr.dt_size) {
// dtb position
dtb = base + pos;
pos += hdr.dt_size;
mem_align(&pos, hdr.page_size);
}
if (pos < size) {
extra = base + pos;
}
check_headers();
}
void parse_img(unsigned char *orig, size_t size) {
unsigned char *base, *end;
for(base = orig, end = orig + size; base < end; base += 256, size -= 256) {
switch (check_type(base)) {
case CHROMEOS:
boot_type = CHROMEOS;
continue;
case AOSP:
// Don't override CHROMEOS
if (boot_type != CHROMEOS)
boot_type = AOSP;
parse_aosp(base, size);
return;
case ELF:
boot_type = ELF;
parse_elf(base);
return;
default:
continue;
}
}
error(1, "No boot image magic found!");
}

View File

@@ -1,146 +0,0 @@
#include "magiskboot.h"
static size_t restore(const char *filename, int fd) {
int ifd = open(filename, O_RDONLY);
if (ifd < 0)
error(1, "Cannot open %s\n", filename);
size_t size = lseek(ifd, 0, SEEK_END);
lseek(ifd, 0, SEEK_SET);
if (sendfile(fd, ifd, NULL, size) != size) {
error(1, "Cannot write %s\n", filename);
}
close(ifd);
return size;
}
static void restore_buf(int fd, const void *buf, size_t size) {
if (write(fd, buf, size) != size) {
error(1, "Cannot dump from input file\n");
}
}
void repack(const char* orig_image, const char* out_image) {
size_t size;
unsigned char *orig;
char name[PATH_MAX];
// There are possible two MTK headers
mtk_hdr mtk_kernel_hdr, mtk_ramdisk_hdr;
size_t mtk_kernel_off, mtk_ramdisk_off;
// Load original image
mmap_ro(orig_image, &orig, &size);
// Parse original image
printf("Parsing boot image: [%s]\n\n", orig_image);
parse_img(orig, size);
printf("Repack to boot image: [%s]\n\n", out_image);
// Create new image
int fd = open_new(out_image);
// Set all sizes to 0
hdr.kernel_size = 0;
hdr.ramdisk_size = 0;
hdr.second_size = 0;
hdr.dt_size = 0;
// Skip a page for header
write_zero(fd, hdr.page_size);
// Restore kernel
if (mtk_kernel) {
mtk_kernel_off = lseek(fd, 0, SEEK_CUR);
write_zero(fd, 512);
memcpy(&mtk_kernel_hdr, kernel, sizeof(mtk_kernel_hdr));
}
hdr.kernel_size = restore(KERNEL_FILE, fd);
file_align(fd, hdr.page_size, 1);
// Restore ramdisk
if (mtk_ramdisk) {
mtk_ramdisk_off = lseek(fd, 0, SEEK_CUR);
write_zero(fd, 512);
memcpy(&mtk_ramdisk_hdr, ramdisk, sizeof(mtk_ramdisk_hdr));
}
if (access(RAMDISK_FILE, R_OK) == 0) {
// If we found raw cpio, compress to original format
// Before we start, clean up previous compressed files
for (int i = 0; i < SUP_NUM; ++i) {
sprintf(name, "%s.%s", RAMDISK_FILE, SUP_EXT_LIST[i]);
unlink(name);
}
size_t cpio_size;
unsigned char *cpio;
mmap_ro(RAMDISK_FILE, &cpio, &cpio_size);
if (comp(ramdisk_type, RAMDISK_FILE, cpio, cpio_size))
error(1, "Unsupported ramdisk format!");
munmap(cpio, cpio_size);
}
int found = 0;
for (int i = 0; i < SUP_NUM; ++i) {
sprintf(name, "%s.%s", RAMDISK_FILE, SUP_EXT_LIST[i]);
if (access(name, R_OK) == 0) {
ramdisk_type = SUP_TYPE_LIST[i];
found = 1;
break;
}
}
if (!found)
error(1, "No ramdisk exists!");
hdr.ramdisk_size = restore(name, fd);
file_align(fd, hdr.page_size, 1);
// Restore second
if (access(SECOND_FILE, R_OK) == 0) {
hdr.second_size = restore(SECOND_FILE, fd);
file_align(fd, hdr.page_size, 1);
}
// Restore dtb
if (access(DTB_FILE, R_OK) == 0) {
hdr.dt_size = restore(DTB_FILE, fd);
file_align(fd, hdr.page_size, 1);
}
// Check extra info, currently only for LG Bump and Samsung SEANDROIDENFORCE
if (extra) {
if (memcmp(extra, "SEANDROIDENFORCE", 16) == 0 ||
memcmp(extra, "\x41\xa9\xe4\x67\x74\x4d\x1d\x1b\xa4\x29\xf2\xec\xea\x65\x52\x79", 16) == 0 ) {
restore_buf(fd, extra, 16);
}
}
// Write headers back
if (mtk_kernel) {
lseek(fd, mtk_kernel_off, SEEK_SET);
mtk_kernel_hdr.size = hdr.kernel_size;
hdr.kernel_size += 512;
restore_buf(fd, &mtk_kernel_hdr, sizeof(mtk_kernel_hdr));
}
if (mtk_ramdisk) {
lseek(fd, mtk_ramdisk_off, SEEK_SET);
mtk_ramdisk_hdr.size = hdr.ramdisk_size;
hdr.ramdisk_size += 512;
restore_buf(fd, &mtk_ramdisk_hdr, sizeof(mtk_ramdisk_hdr));
}
// Main header
lseek(fd, 0, SEEK_SET);
restore_buf(fd, &hdr, sizeof(hdr));
// Print new image info
print_info();
munmap(orig, size);
if (lseek(fd, 0, SEEK_END) > size) {
error(2, "Boot partition too small!");
}
close(fd);
}

View File

@@ -1,295 +0,0 @@
/*
SHA-1 in C
By Steve Reid <steve@edmweb.com>
100% Public Domain
Test Vectors (from FIPS PUB 180-1)
"abc"
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
A million repetitions of "a"
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
*/
/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */
/* #define SHA1HANDSOFF * Copies data before messing with it. */
#define SHA1HANDSOFF
#include <stdio.h>
#include <string.h>
/* for uint32_t */
#include <stdint.h>
#include "sha1.h"
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
/* blk0() and blk() perform the initial expand. */
/* I got the idea of expanding during the round function from SSLeay */
#if BYTE_ORDER == LITTLE_ENDIAN
#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
|(rol(block->l[i],8)&0x00FF00FF))
#elif BYTE_ORDER == BIG_ENDIAN
#define blk0(i) block->l[i]
#else
#error "Endianness not defined!"
#endif
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
^block->l[(i+2)&15]^block->l[i&15],1))
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
/* Hash a single 512-bit block. This is the core of the algorithm. */
void SHA1Transform(
uint32_t state[5],
const unsigned char buffer[64]
)
{
uint32_t a, b, c, d, e;
typedef union
{
unsigned char c[64];
uint32_t l[16];
} CHAR64LONG16;
#ifdef SHA1HANDSOFF
CHAR64LONG16 block[1]; /* use array to appear as a pointer */
memcpy(block, buffer, 64);
#else
/* The following had better never be used because it causes the
* pointer-to-const buffer to be cast into a pointer to non-const.
* And the result is written through. I threw a "const" in, hoping
* this will cause a diagnostic.
*/
CHAR64LONG16 *block = (const CHAR64LONG16 *) buffer;
#endif
/* Copy context->state[] to working vars */
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
/* 4 rounds of 20 operations each. Loop unrolled. */
R0(a, b, c, d, e, 0);
R0(e, a, b, c, d, 1);
R0(d, e, a, b, c, 2);
R0(c, d, e, a, b, 3);
R0(b, c, d, e, a, 4);
R0(a, b, c, d, e, 5);
R0(e, a, b, c, d, 6);
R0(d, e, a, b, c, 7);
R0(c, d, e, a, b, 8);
R0(b, c, d, e, a, 9);
R0(a, b, c, d, e, 10);
R0(e, a, b, c, d, 11);
R0(d, e, a, b, c, 12);
R0(c, d, e, a, b, 13);
R0(b, c, d, e, a, 14);
R0(a, b, c, d, e, 15);
R1(e, a, b, c, d, 16);
R1(d, e, a, b, c, 17);
R1(c, d, e, a, b, 18);
R1(b, c, d, e, a, 19);
R2(a, b, c, d, e, 20);
R2(e, a, b, c, d, 21);
R2(d, e, a, b, c, 22);
R2(c, d, e, a, b, 23);
R2(b, c, d, e, a, 24);
R2(a, b, c, d, e, 25);
R2(e, a, b, c, d, 26);
R2(d, e, a, b, c, 27);
R2(c, d, e, a, b, 28);
R2(b, c, d, e, a, 29);
R2(a, b, c, d, e, 30);
R2(e, a, b, c, d, 31);
R2(d, e, a, b, c, 32);
R2(c, d, e, a, b, 33);
R2(b, c, d, e, a, 34);
R2(a, b, c, d, e, 35);
R2(e, a, b, c, d, 36);
R2(d, e, a, b, c, 37);
R2(c, d, e, a, b, 38);
R2(b, c, d, e, a, 39);
R3(a, b, c, d, e, 40);
R3(e, a, b, c, d, 41);
R3(d, e, a, b, c, 42);
R3(c, d, e, a, b, 43);
R3(b, c, d, e, a, 44);
R3(a, b, c, d, e, 45);
R3(e, a, b, c, d, 46);
R3(d, e, a, b, c, 47);
R3(c, d, e, a, b, 48);
R3(b, c, d, e, a, 49);
R3(a, b, c, d, e, 50);
R3(e, a, b, c, d, 51);
R3(d, e, a, b, c, 52);
R3(c, d, e, a, b, 53);
R3(b, c, d, e, a, 54);
R3(a, b, c, d, e, 55);
R3(e, a, b, c, d, 56);
R3(d, e, a, b, c, 57);
R3(c, d, e, a, b, 58);
R3(b, c, d, e, a, 59);
R4(a, b, c, d, e, 60);
R4(e, a, b, c, d, 61);
R4(d, e, a, b, c, 62);
R4(c, d, e, a, b, 63);
R4(b, c, d, e, a, 64);
R4(a, b, c, d, e, 65);
R4(e, a, b, c, d, 66);
R4(d, e, a, b, c, 67);
R4(c, d, e, a, b, 68);
R4(b, c, d, e, a, 69);
R4(a, b, c, d, e, 70);
R4(e, a, b, c, d, 71);
R4(d, e, a, b, c, 72);
R4(c, d, e, a, b, 73);
R4(b, c, d, e, a, 74);
R4(a, b, c, d, e, 75);
R4(e, a, b, c, d, 76);
R4(d, e, a, b, c, 77);
R4(c, d, e, a, b, 78);
R4(b, c, d, e, a, 79);
/* Add the working vars back into context.state[] */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
/* Wipe variables */
a = b = c = d = e = 0;
#ifdef SHA1HANDSOFF
memset(block, '\0', sizeof(block));
#endif
}
/* SHA1Init - Initialize new context */
void SHA1Init(
SHA1_CTX * context
)
{
/* SHA1 initialization constants */
context->state[0] = 0x67452301;
context->state[1] = 0xEFCDAB89;
context->state[2] = 0x98BADCFE;
context->state[3] = 0x10325476;
context->state[4] = 0xC3D2E1F0;
context->count[0] = context->count[1] = 0;
}
/* Run your data through this. */
void SHA1Update(
SHA1_CTX * context,
const unsigned char *data,
uint32_t len
)
{
uint32_t i;
uint32_t j;
j = context->count[0];
if ((context->count[0] += len << 3) < j)
context->count[1]++;
context->count[1] += (len >> 29);
j = (j >> 3) & 63;
if ((j + len) > 63)
{
memcpy(&context->buffer[j], data, (i = 64 - j));
SHA1Transform(context->state, context->buffer);
for (; i + 63 < len; i += 64)
{
SHA1Transform(context->state, &data[i]);
}
j = 0;
}
else
i = 0;
memcpy(&context->buffer[j], &data[i], len - i);
}
/* Add padding and return the message digest. */
void SHA1Final(
unsigned char digest[20],
SHA1_CTX * context
)
{
unsigned i;
unsigned char finalcount[8];
unsigned char c;
#if 0 /* untested "improvement" by DHR */
/* Convert context->count to a sequence of bytes
* in finalcount. Second element first, but
* big-endian order within element.
* But we do it all backwards.
*/
unsigned char *fcp = &finalcount[8];
for (i = 0; i < 2; i++)
{
uint32_t t = context->count[i];
int j;
for (j = 0; j < 4; t >>= 8, j++)
*--fcp = (unsigned char) t}
#else
for (i = 0; i < 8; i++)
{
finalcount[i] = (unsigned char) ((context->count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255); /* Endian independent */
}
#endif
c = 0200;
SHA1Update(context, &c, 1);
while ((context->count[0] & 504) != 448)
{
c = 0000;
SHA1Update(context, &c, 1);
}
SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
for (i = 0; i < 20; i++)
{
digest[i] = (unsigned char)
((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
}
/* Wipe variables */
memset(context, '\0', sizeof(*context));
memset(&finalcount, '\0', sizeof(finalcount));
}
void SHA1(
char *hash_out,
const char *str,
int len)
{
SHA1_CTX ctx;
unsigned int ii;
SHA1Init(&ctx);
for (ii=0; ii<len; ii+=1)
SHA1Update(&ctx, (const unsigned char*)str + ii, 1);
SHA1Final((unsigned char *)hash_out, &ctx);
hash_out[20] = '\0';
}

View File

@@ -1,64 +0,0 @@
#include "magiskboot.h"
static void dump(unsigned char *buf, size_t size, const char *filename) {
int fd = open_new(filename);
if (write(fd, buf, size) != size)
error(1, "Cannot dump %s", filename);
close(fd);
}
void unpack(const char* image) {
size_t size;
unsigned char *orig;
mmap_ro(image, &orig, &size);
// Parse image
printf("Parsing boot image: [%s]\n\n", image);
parse_img(orig, size);
if (boot_type == CHROMEOS) {
// The caller should know it's chromeos, as it needs additional signing
dump(orig, 0, "chromeos");
}
char name[PATH_MAX];
// Dump kernel
if (mtk_kernel) {
kernel += 512;
hdr.kernel_size -= 512;
}
dump(kernel, hdr.kernel_size, KERNEL_FILE);
// Dump ramdisk
if (mtk_ramdisk) {
ramdisk += 512;
hdr.ramdisk_size -= 512;
}
if (decomp(ramdisk_type, RAMDISK_FILE, ramdisk, hdr.ramdisk_size)) {
// Dump the compressed ramdisk
dump(ramdisk, hdr.ramdisk_size, RAMDISK_FILE ".unsupport");
error(1, "Unsupported ramdisk format! Dumped to %s", RAMDISK_FILE ".unsupport");
}
if (hdr.second_size) {
// Dump second
dump(second, hdr.second_size, SECOND_FILE);
}
if (hdr.dt_size) {
if (boot_type == ELF && (dtb_type != QCDT && dtb_type != ELF)) {
printf("Non QC dtb found in ELF kernel, recreate kernel\n");
gzip(1, KERNEL_FILE, kernel, hdr.kernel_size);
int kfp = open(KERNEL_FILE, O_WRONLY | O_APPEND);
write(kfp, dtb, hdr.dt_size);
close(kfp);
} else {
// Dump dtb
dump(dtb, hdr.dt_size, DTB_FILE);
}
}
munmap(orig, size);
}

View File

@@ -1,179 +0,0 @@
#include "magiskboot.h"
#include "elf.h"
char *SUP_EXT_LIST[SUP_NUM] = { "gz", "xz", "lzma", "bz2", "lz4" };
file_t SUP_TYPE_LIST[SUP_NUM] = { GZIP, XZ, LZMA, BZIP2, LZ4 };
void mmap_ro(const char *filename, unsigned char **buf, size_t *size) {
int fd = open(filename, O_RDONLY);
if (fd < 0)
error(1, "Cannot open %s", filename);
*size = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
*buf = mmap(NULL, *size, PROT_READ, MAP_SHARED, fd, 0);
close(fd);
}
void mmap_rw(const char *filename, unsigned char **buf, size_t *size) {
int fd = open(filename, O_RDWR);
if (fd < 0)
error(1, "Cannot open %s", filename);
*size = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
*buf = mmap(NULL, *size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);
}
file_t check_type(const unsigned char *buf) {
if (memcmp(buf, CHROMEOS_MAGIC, CHROMEOS_MAGIC_SIZE) == 0) {
return CHROMEOS;
} else if (memcmp(buf, BOOT_MAGIC, BOOT_MAGIC_SIZE) == 0) {
return AOSP;
} else if (memcmp(buf, ELF_MAGIC, ELF_MAGIC_SIZE) == 0) {
return ELF;
} else if (memcmp(buf, "\x1f\x8b\x08\x00", 4) == 0) {
return GZIP;
} else if (memcmp(buf, "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a", 9) == 0) {
return LZOP;
} else if (memcmp(buf, "\xfd""7zXZ\x00", 6) == 0) {
return XZ;
} else if (memcmp(buf, "\x5d\x00\x00", 3) == 0
&& (buf[12] == (unsigned char) '\xff' || buf[12] == (unsigned char) '\x00')) {
return LZMA;
} else if (memcmp(buf, "BZh", 3) == 0) {
return BZIP2;
} else if ( ( memcmp(buf, "\x04\x22\x4d\x18", 4) == 0
|| memcmp(buf, "\x03\x21\x4c\x18", 4) == 0)
|| memcmp(buf, "\x02\x21\x4c\x18", 4) == 0) {
return LZ4;
} else if (memcmp(buf, "\x88\x16\x88\x58", 4) == 0) {
return MTK;
} else if (memcmp(buf, "QCDT", 4) == 0) {
return QCDT;
} else {
return UNKNOWN;
}
}
void write_zero(int fd, size_t size) {
size_t pos = lseek(fd, 0, SEEK_CUR);
ftruncate(fd, pos + size);
lseek(fd, pos + size, SEEK_SET);
}
void mem_align(size_t *pos, size_t align) {
size_t mask = align - 1;
if (*pos & mask) {
*pos += align - (*pos & mask);
}
}
void file_align(int fd, size_t align, int out) {
size_t pos = lseek(fd, 0, SEEK_CUR);
size_t mask = align - 1;
size_t off;
if (pos & mask) {
off = align - (pos & mask);
if (out) {
write_zero(fd, off);
} else {
lseek(fd, pos + off, SEEK_SET);
}
}
}
int open_new(const char *filename) {
int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd < 0)
error(1, "Unable to create %s", filename);
return fd;
}
void print_info() {
printf("KERNEL [%d] @ 0x%08x\n", hdr.kernel_size, hdr.kernel_addr);
printf("RAMDISK [%d] @ 0x%08x\n", hdr.ramdisk_size, hdr.ramdisk_addr);
printf("SECOND [%d] @ 0x%08x\n", hdr.second_size, hdr.second_addr);
printf("DTB [%d] @ 0x%08x\n", hdr.dt_size, hdr.tags_addr);
printf("PAGESIZE [%d]\n", hdr.page_size);
if (hdr.os_version != 0) {
int a,b,c,y,m = 0;
int os_version, os_patch_level;
os_version = hdr.os_version >> 11;
os_patch_level = hdr.os_version & 0x7ff;
a = (os_version >> 14) & 0x7f;
b = (os_version >> 7) & 0x7f;
c = os_version & 0x7f;
printf("OS_VERSION [%d.%d.%d]\n", a, b, c);
y = (os_patch_level >> 4) + 2000;
m = os_patch_level & 0xf;
printf("PATCH_LEVEL [%d-%02d]\n", y, m);
}
printf("NAME [%s]\n", hdr.name);
printf("CMDLINE [%s]\n", hdr.cmdline);
switch (ramdisk_type) {
case GZIP:
printf("COMPRESSION [%s]\n", "gzip");
break;
case XZ:
printf("COMPRESSION [%s]\n", "xz");
break;
case LZMA:
printf("COMPRESSION [%s]\n", "lzma");
break;
case BZIP2:
printf("COMPRESSION [%s]\n", "bzip2");
break;
case LZ4:
printf("COMPRESSION [%s]\n", "lz4");
break;
default:
fprintf(stderr, "Unknown ramdisk format!\n");
}
printf("\n");
}
void cleanup() {
printf("Cleaning up...\n");
char name[PATH_MAX];
unlink(KERNEL_FILE);
unlink(RAMDISK_FILE);
unlink(RAMDISK_FILE ".unsupport");
unlink(SECOND_FILE);
unlink(DTB_FILE);
unlink(NEW_BOOT);
for (int i = 0; i < SUP_NUM; ++i) {
sprintf(name, "%s.%s", RAMDISK_FILE, SUP_EXT_LIST[i]);
unlink(name);
}
}
void vec_init(vector *v) {
vec_size(v) = 0;
vec_cap(v) = 1;
vec_entry(v) = malloc(sizeof(void*));
}
void vec_push_back(vector *v, void *p) {
if (v == NULL) return;
if (vec_size(v) == vec_cap(v)) {
vec_cap(v) *= 2;
vec_entry(v) = realloc(vec_entry(v), sizeof(void*) * vec_cap(v));
}
vec_entry(v)[vec_size(v)] = p;
++vec_size(v);
}
void vec_sort(vector *v, int (*compar)(const void *, const void *)) {
qsort(vec_entry(v), vec_size(v), sizeof(void*), compar);
}
void vec_destroy(vector *v) {
// Will not free each entry!
// Manually free each entry, then call this function
vec_size(v) = 0;
vec_cap(v) = 0;
free(v->data);
}

View File

@@ -1,6 +0,0 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := magiskhide
LOCAL_SRC_FILES := main.c hide.c list_monitor.c proc_monitor.c util.c
include $(BUILD_EXECUTABLE)

View File

@@ -1,78 +0,0 @@
#include "magiskhide.h"
int hideMagisk() {
close(pipefd[1]);
int pid, fd;
char cache_block[256];
cache_block[0] = '\0';
while(1) {
read(pipefd[0], &pid, sizeof(pid));
// Termination called
if(pid == -1) break;
manage_selinux();
snprintf(buffer, sizeof(buffer), "/proc/%d/ns/mnt", pid);
if((fd = open(buffer, O_RDONLY)) == -1) continue; // Maybe process died..
if(setns(fd, 0) == -1) {
fprintf(logfile, "MagiskHide: Unable to change namespace for pid=%d\n", pid);
continue;
}
close(fd);
snprintf(buffer, sizeof(buffer), "/proc/%d/mounts", pid);
FILE *mount_fp = fopen(buffer, "r");
if (mount_fp == NULL) {
fprintf(logfile, "MagiskHide: Error opening mount list!\n");
continue;
}
int mount_size;
char **mount_list = file_to_str_arr(mount_fp, &mount_size);
// Find the cache block name if not found yet
if (strlen(cache_block) == 0) {
for(i = 0; i < mount_size; ++i) {
if (strstr(mount_list[i], " /cache ")) {
sscanf(mount_list[i], "%256s", cache_block);
break;
}
}
}
// First unmount the dummy skeletons, cache mounts, and /sbin links
for(i = mount_size - 1; i >= 0; --i) {
if (strstr(mount_list[i], "tmpfs /system") || strstr(mount_list[i], "tmpfs /vendor")
|| strstr(mount_list[i], "tmpfs /sbin")
|| (strstr(mount_list[i], cache_block) && strstr(mount_list[i], "/system/")) ) {
sscanf(mount_list[i], "%*s %512s", buffer);
lazy_unmount(buffer);
}
free(mount_list[i]);
}
free(mount_list);
// Re-read mount infos
fseek(mount_fp, 0, SEEK_SET);
mount_list = file_to_str_arr(mount_fp, &mount_size);
fclose(mount_fp);
// Unmount loop mounts
for(i = mount_size - 1; i >= 0; --i) {
if (strstr(mount_list[i], "/dev/block/loop") && !strstr(mount_list[i], DUMMYPATH)) {
sscanf(mount_list[i], "%*s %512s", buffer);
lazy_unmount(buffer);
}
free(mount_list[i]);
}
free(mount_list);
// Send resume signal
kill(pid, SIGCONT);
}
// Should never go here
return 1;
}

View File

@@ -1,56 +0,0 @@
#include "magiskhide.h"
void *monitor_list(void *path) {
char* listpath = (char*) path;
signal(SIGQUIT, quit_pthread);
int inotifyFd = -1;
char str[512];
while(1) {
if (inotifyFd == -1 || read(inotifyFd, str, sizeof(str)) == -1) {
close(inotifyFd);
inotifyFd = inotify_init();
if (inotifyFd == -1) {
fprintf(logfile, "MagiskHide: Unable to watch %s\n", listpath);
exit(1);
}
if (inotify_add_watch(inotifyFd, listpath, IN_MODIFY) == -1) {
fprintf(logfile, "MagiskHide: Unable to watch %s\n", listpath);
exit(1);
}
}
update_list(listpath);
}
return NULL;
}
void update_list(const char *listpath) {
FILE *hide_fp = fopen(listpath, "r");
if (hide_fp == NULL) {
fprintf(logfile, "MagiskHide: Error opening hide list\n");
exit(1);
}
pthread_mutex_lock(&mutex);
if (hide_list) {
// Free memory
for(i = 0; i < list_size; ++i)
free(hide_list[i]);
free(hide_list);
}
hide_list = file_to_str_arr(hide_fp, &list_size);
pthread_mutex_unlock(&mutex);
fclose(hide_fp);
if (list_size) fprintf(logfile, "MagiskHide: Update process/package list:\n");
for(i = 0; i < list_size; i++)
fprintf(logfile, "MagiskHide: [%s]\n", hide_list[i]);
}
void quit_pthread(int sig) {
// Free memory
for(i = 0; i < list_size; ++i)
free(hide_list[i]);
free(hide_list);
pthread_exit(NULL);
}

View File

@@ -1,52 +0,0 @@
#ifndef MAGISK_HIDE_H
#define MAGISK_HIDE_H
#define _GNU_SOURCE
#include <string.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <pthread.h>
#include <unistd.h>
#include <signal.h>
#include <sys/mount.h>
#include <sys/inotify.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/resource.h>
#define LOGFILE "/cache/magisk.log"
#define HIDELIST "/magisk/.core/magiskhide/hidelist"
#define DUMMYPATH "/dev/magisk/dummy"
#define ENFORCE_FILE "/sys/fs/selinux/enforce"
#define SEPOLICY_INJECT "/data/magisk/magiskpolicy"
// Main thread
void monitor_proc();
// Forked process for namespace setting
int hideMagisk();
// List monitor thread
void update_list(const char *listpath);
void quit_pthread(int sig);
void *monitor_list(void *path);
// Util functions
char **file_to_str_arr(FILE *fp, int *size);
void read_namespace(const int pid, char* target, const size_t size);
void lazy_unmount(const char* mountpoint);
void run_as_daemon();
void manage_selinux();
// Global variable sharing through process/threads
extern FILE *logfile;
extern int i, list_size, pipefd[2];
extern char **hide_list, buffer[512];
extern pthread_t list_monitor;
extern pthread_mutex_t mutex;
#endif

View File

@@ -1,65 +0,0 @@
#include "magiskhide.h"
FILE *logfile;
int i, list_size, pipefd[2];
char **hide_list = NULL, buffer[512];
pthread_t list_monitor;
pthread_mutex_t mutex;
static void terminate(int sig) {
// Close the config list monitor
pthread_kill(list_monitor, SIGQUIT);
pthread_mutex_destroy(&mutex);
// Terminate our children
i = -1;
write(pipefd[1], &i, sizeof(i));
exit(0);
}
int main(int argc, char *argv[]) {
if (argc > 1) {
if (strcmp(argv[1], "--daemon") == 0)
run_as_daemon();
else {
fprintf(stderr, "%s (with no options)\n\tRun magiskhide and output to stdout\n", argv[0]);
fprintf(stderr, "%s --daemon\n\tRun magiskhide as daemon, output to magisk.log\n", argv[0]);
return 1;
}
} else
logfile = stdout;
// Handle all killing signals
signal(SIGINT, terminate);
signal(SIGTERM, terminate);
// Fork a child to handle namespace switches and unmounts
pipe(pipefd);
switch(fork()) {
case -1:
exit(-1);
case 0:
return hideMagisk();
default:
break;
}
close(pipefd[0]);
// Start a thread to constantly check the hide list
pthread_mutex_init(&mutex, NULL);
pthread_create(&list_monitor, NULL, monitor_list, HIDELIST);
// Set main process to the top priority
setpriority(PRIO_PROCESS, 0, -20);
monitor_proc();
terminate(0);
fprintf(logfile, "MagiskHide: Cannot monitor am_proc_start, abort...\n");
fclose(logfile);
return 1;
}

View File

@@ -1,82 +0,0 @@
#include "magiskhide.h"
void monitor_proc() {
int pid, badns, zygote_num = 0;
char init_ns[32], zygote_ns[2][32];
// Get the mount namespace of init
read_namespace(1, init_ns, 32);
printf("%s\n", init_ns);
// Get the mount namespace of zygote
FILE *p = popen("ps | grep zygote | grep -v grep", "r");
while(fgets(buffer, sizeof(buffer), p)) {
if (zygote_num == 2) break;
sscanf(buffer, "%d", &pid);
do {
usleep(500);
read_namespace(pid, zygote_ns[zygote_num], 32);
} while (strcmp(zygote_ns[zygote_num], init_ns) == 0);
++zygote_num;
}
pclose(p);
for (i = 0; i < zygote_num; ++i)
fprintf(logfile, "Zygote(%d) ns=%s ", i, zygote_ns[i]);
fprintf(logfile, "\n");
// Monitor am_proc_start
p = popen("while true; do logcat -b events -c; 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] = ' ';
}
char processName[256];
int ret = sscanf(buffer, "[%*d %d %*d %256s", &pid, processName);
if(ret != 2)
continue;
pthread_mutex_lock(&mutex);
for (i = 0; i < list_size; ++i) {
if(strcmp(processName, hide_list[i]) == 0) {
while(1) {
badns = 0;
read_namespace(pid, buffer, 32);
for (i = 0; i < zygote_num; ++i) {
if (strcmp(buffer, zygote_ns[i]) == 0) {
usleep(500);
badns = 1;
break;
}
}
if (!badns) break;
}
// Send pause signal ASAP
if (kill(pid, SIGSTOP) == -1) continue;
fprintf(logfile, "MagiskHide: %s(PID=%d ns=%s)\n", processName, pid, buffer);
// Unmount start
write(pipefd[1], &pid, sizeof(pid));
break;
}
}
pthread_mutex_unlock(&mutex);
}
// Close the logcat monitor
pclose(p);
}

View File

@@ -1,91 +0,0 @@
#include "magiskhide.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;
}
void read_namespace(const int pid, char* target, const size_t size) {
char path[32];
snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
ssize_t len = readlink(path, target, size);
target[len] = '\0';
}
void lazy_unmount(const char* mountpoint) {
if (umount2(mountpoint, MNT_DETACH) != -1)
fprintf(logfile, "MagiskHide: Unmounted (%s)\n", mountpoint);
else
fprintf(logfile, "MagiskHide: Unmount Failed (%s)\n", mountpoint);
}
void run_as_daemon() {
switch(fork()) {
case -1:
exit(-1);
case 0:
if (setsid() < 0)
exit(-1);
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
logfile = fopen(LOGFILE, "a+");
setbuf(logfile, NULL);
break;
default:
exit(0);
}
}
void manage_selinux() {
char *argv[] = { SEPOLICY_INJECT, "--live", "permissive *", NULL };
char str[20];
int fd, ret;
fd = open(ENFORCE_FILE, O_RDONLY);
if (fd < 0)
return;
ret = read(fd, str, 20);
close(fd);
if (ret < 1)
return;
// Permissive
if (str[0] == '0') {
fprintf(logfile, "MagiskHide: Permissive detected, switching to pseudo enforced\n");
fd = open(ENFORCE_FILE, O_RDWR);
if (fd < 0)
return;
ret = write(fd, "1", 1);
close(fd);
if (ret < 1)
return;
switch(fork()) {
case -1:
return;
case 0:
execvp(argv[0], argv);
default:
return;
}
}
}

Submodule jni/magiskpolicy deleted from 2e6bea23ac

View File

@@ -1,7 +0,0 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := resetprop
LOCAL_SRC_FILES := resetprop.cpp system_properties.cpp libc_logging.cpp
LOCAL_LDLIBS += -latomic
include $(BUILD_EXECUTABLE)

View File

@@ -1,339 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) 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
this service 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 make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. 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.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
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
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the 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 a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE 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.
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
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
{description}
Copyright (C) {year} {fullname}
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 2 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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision 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, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
{signature of Ty Coon}, 1 April 1989
Ty Coon, President of Vice
This 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.

View File

@@ -1,659 +0,0 @@
/*
* Copyright (C) 2010 The Android Open Source Project
* All rights reserved.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "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 THE
* COPYRIGHT OWNER OR CONTRIBUTORS 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 "libc_logging.h" // Relative path so we can #include this .cpp file for testing.
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/un.h>
#include <time.h>
#include <unistd.h>
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
#include "_system_properties.h"
static pthread_mutex_t g_abort_msg_lock = PTHREAD_MUTEX_INITIALIZER;
__LIBC_HIDDEN__ abort_msg_t** __abort_message_ptr; // Accessible to __libc_init_common.
// Must be kept in sync with frameworks/base/core/java/android/util/EventLog.java.
enum AndroidEventLogType {
EVENT_TYPE_INT = 0,
EVENT_TYPE_LONG = 1,
EVENT_TYPE_STRING = 2,
EVENT_TYPE_LIST = 3,
EVENT_TYPE_FLOAT = 4,
};
struct BufferOutputStream {
public:
BufferOutputStream(char* buffer, size_t size) : total(0) {
buffer_ = buffer;
end_ = buffer + size - 1;
pos_ = buffer_;
pos_[0] = '\0';
}
~BufferOutputStream() {
}
void Send(const char* data, int len) {
if (len < 0) {
len = strlen(data);
}
total += len;
while (len > 0) {
int avail = end_ - pos_;
if (avail == 0) {
return;
}
if (avail > len) {
avail = len;
}
memcpy(pos_, data, avail);
pos_ += avail;
pos_[0] = '\0';
len -= avail;
}
}
size_t total;
private:
char* buffer_;
char* pos_;
char* end_;
};
struct FdOutputStream {
public:
FdOutputStream(int fd) : total(0), fd_(fd) {
}
void Send(const char* data, int len) {
if (len < 0) {
len = strlen(data);
}
total += len;
while (len > 0) {
int rc = TEMP_FAILURE_RETRY(write(fd_, data, len));
if (rc == -1) {
return;
}
data += rc;
len -= rc;
}
}
size_t total;
private:
int fd_;
};
/*** formatted output implementation
***/
/* Parse a decimal string from 'format + *ppos',
* return the value, and writes the new position past
* the decimal string in '*ppos' on exit.
*
* NOTE: Does *not* handle a sign prefix.
*/
static unsigned parse_decimal(const char *format, int *ppos) {
const char* p = format + *ppos;
unsigned result = 0;
for (;;) {
int ch = *p;
unsigned d = static_cast<unsigned>(ch - '0');
if (d >= 10U) {
break;
}
result = result*10 + d;
p++;
}
*ppos = p - format;
return result;
}
// Writes number 'value' in base 'base' into buffer 'buf' of size 'buf_size' bytes.
// Assumes that buf_size > 0.
static void format_unsigned(char* buf, size_t buf_size, uint64_t value, int base, bool caps) {
char* p = buf;
char* end = buf + buf_size - 1;
// Generate digit string in reverse order.
while (value) {
unsigned d = value % base;
value /= base;
if (p != end) {
char ch;
if (d < 10) {
ch = '0' + d;
} else {
ch = (caps ? 'A' : 'a') + (d - 10);
}
*p++ = ch;
}
}
// Special case for 0.
if (p == buf) {
if (p != end) {
*p++ = '0';
}
}
*p = '\0';
// Reverse digit string in-place.
size_t length = p - buf;
for (size_t i = 0, j = length - 1; i < j; ++i, --j) {
char ch = buf[i];
buf[i] = buf[j];
buf[j] = ch;
}
}
static void format_integer(char* buf, size_t buf_size, uint64_t value, char conversion) {
// Decode the conversion specifier.
int is_signed = (conversion == 'd' || conversion == 'i' || conversion == 'o');
int base = 10;
if (conversion == 'x' || conversion == 'X') {
base = 16;
} else if (conversion == 'o') {
base = 8;
}
bool caps = (conversion == 'X');
if (is_signed && static_cast<int64_t>(value) < 0) {
buf[0] = '-';
buf += 1;
buf_size -= 1;
value = static_cast<uint64_t>(-static_cast<int64_t>(value));
}
format_unsigned(buf, buf_size, value, base, caps);
}
template <typename Out>
static void SendRepeat(Out& o, char ch, int count) {
char pad[8];
memset(pad, ch, sizeof(pad));
const int pad_size = static_cast<int>(sizeof(pad));
while (count > 0) {
int avail = count;
if (avail > pad_size) {
avail = pad_size;
}
o.Send(pad, avail);
count -= avail;
}
}
/* Perform formatted output to an output target 'o' */
template <typename Out>
static void out_vformat(Out& o, const char* format, va_list args) {
int nn = 0;
for (;;) {
int mm;
int padZero = 0;
int padLeft = 0;
char sign = '\0';
int width = -1;
int prec = -1;
size_t bytelen = sizeof(int);
int slen;
char buffer[32]; /* temporary buffer used to format numbers */
char c;
/* first, find all characters that are not 0 or '%' */
/* then send them to the output directly */
mm = nn;
do {
c = format[mm];
if (c == '\0' || c == '%')
break;
mm++;
} while (1);
if (mm > nn) {
o.Send(format+nn, mm-nn);
nn = mm;
}
/* is this it ? then exit */
if (c == '\0')
break;
/* nope, we are at a '%' modifier */
nn++; // skip it
/* parse flags */
for (;;) {
c = format[nn++];
if (c == '\0') { /* single trailing '%' ? */
c = '%';
o.Send(&c, 1);
return;
}
else if (c == '0') {
padZero = 1;
continue;
}
else if (c == '-') {
padLeft = 1;
continue;
}
else if (c == ' ' || c == '+') {
sign = c;
continue;
}
break;
}
/* parse field width */
if ((c >= '0' && c <= '9')) {
nn --;
width = static_cast<int>(parse_decimal(format, &nn));
c = format[nn++];
}
/* parse precision */
if (c == '.') {
prec = static_cast<int>(parse_decimal(format, &nn));
c = format[nn++];
}
/* length modifier */
switch (c) {
case 'h':
bytelen = sizeof(short);
if (format[nn] == 'h') {
bytelen = sizeof(char);
nn += 1;
}
c = format[nn++];
break;
case 'l':
bytelen = sizeof(long);
if (format[nn] == 'l') {
bytelen = sizeof(long long);
nn += 1;
}
c = format[nn++];
break;
case 'z':
bytelen = sizeof(size_t);
c = format[nn++];
break;
case 't':
bytelen = sizeof(ptrdiff_t);
c = format[nn++];
break;
default:
;
}
/* conversion specifier */
const char* str = buffer;
if (c == 's') {
/* string */
str = va_arg(args, const char*);
if (str == NULL) {
str = "(null)";
}
} else if (c == 'c') {
/* character */
/* NOTE: char is promoted to int when passed through the stack */
buffer[0] = static_cast<char>(va_arg(args, int));
buffer[1] = '\0';
} else if (c == 'p') {
uint64_t value = reinterpret_cast<uintptr_t>(va_arg(args, void*));
buffer[0] = '0';
buffer[1] = 'x';
format_integer(buffer + 2, sizeof(buffer) - 2, value, 'x');
} else if (c == 'd' || c == 'i' || c == 'o' || c == 'u' || c == 'x' || c == 'X') {
/* integers - first read value from stack */
uint64_t value;
int is_signed = (c == 'd' || c == 'i' || c == 'o');
/* NOTE: int8_t and int16_t are promoted to int when passed
* through the stack
*/
switch (bytelen) {
case 1: value = static_cast<uint8_t>(va_arg(args, int)); break;
case 2: value = static_cast<uint16_t>(va_arg(args, int)); break;
case 4: value = va_arg(args, uint32_t); break;
case 8: value = va_arg(args, uint64_t); break;
default: return; /* should not happen */
}
/* sign extension, if needed */
if (is_signed) {
int shift = 64 - 8*bytelen;
value = static_cast<uint64_t>((static_cast<int64_t>(value << shift)) >> shift);
}
/* format the number properly into our buffer */
format_integer(buffer, sizeof(buffer), value, c);
} else if (c == '%') {
buffer[0] = '%';
buffer[1] = '\0';
} else {
__assert(__FILE__, __LINE__, "conversion specifier unsupported");
}
/* if we are here, 'str' points to the content that must be
* outputted. handle padding and alignment now */
slen = strlen(str);
if (sign != '\0' || prec != -1) {
__assert(__FILE__, __LINE__, "sign/precision unsupported");
}
if (slen < width && !padLeft) {
char padChar = padZero ? '0' : ' ';
SendRepeat(o, padChar, width - slen);
}
o.Send(str, slen);
if (slen < width && padLeft) {
char padChar = padZero ? '0' : ' ';
SendRepeat(o, padChar, width - slen);
}
}
}
int __libc_format_buffer(char* buffer, size_t buffer_size, const char* format, ...) {
BufferOutputStream os(buffer, buffer_size);
va_list args;
va_start(args, format);
out_vformat(os, format, args);
va_end(args);
return os.total;
}
int __libc_format_fd(int fd, const char* format, ...) {
FdOutputStream os(fd);
va_list args;
va_start(args, format);
out_vformat(os, format, args);
va_end(args);
return os.total;
}
static int __libc_write_stderr(const char* tag, const char* msg) {
int fd = TEMP_FAILURE_RETRY(open("/dev/stderr", O_CLOEXEC | O_WRONLY | O_APPEND));
if (fd == -1) {
return -1;
}
iovec vec[4];
vec[0].iov_base = const_cast<char*>(tag);
vec[0].iov_len = strlen(tag);
vec[1].iov_base = const_cast<char*>(": ");
vec[1].iov_len = 2;
vec[2].iov_base = const_cast<char*>(msg);
vec[2].iov_len = strlen(msg);
vec[3].iov_base = const_cast<char*>("\n");
vec[3].iov_len = 1;
int result = TEMP_FAILURE_RETRY(writev(fd, vec, 4));
close(fd);
return result;
}
static int __libc_open_log_socket() {
// ToDo: Ideally we want this to fail if the gid of the current
// process is AID_LOGD, but will have to wait until we have
// registered this in private/android_filesystem_config.h. We have
// found that all logd crashes thus far have had no problem stuffing
// the UNIX domain socket and moving on so not critical *today*.
int log_fd = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0));
if (log_fd < 0) {
return -1;
}
if (fcntl(log_fd, F_SETFL, O_NONBLOCK) == -1) {
close(log_fd);
return -1;
}
union {
struct sockaddr addr;
struct sockaddr_un addrUn;
} u;
memset(&u, 0, sizeof(u));
u.addrUn.sun_family = AF_UNIX;
strlcpy(u.addrUn.sun_path, "/dev/socket/logdw", sizeof(u.addrUn.sun_path));
if (TEMP_FAILURE_RETRY(connect(log_fd, &u.addr, sizeof(u.addrUn))) != 0) {
close(log_fd);
return -1;
}
return log_fd;
}
struct cache {
const prop_info* pinfo;
uint32_t serial;
char c;
};
static void refresh_cache(struct cache *cache, const char *key)
{
if (!cache->pinfo) {
cache->pinfo = __system_property_find(key);
if (!cache->pinfo) {
return;
}
}
uint32_t serial = __system_property_serial(cache->pinfo);
if (serial == cache->serial) {
return;
}
cache->serial = serial;
char buf[PROP_VALUE_MAX];
__system_property_read(cache->pinfo, 0, buf);
cache->c = buf[0];
}
// Timestamp state generally remains constant, since a change is
// rare, we can accept a trylock failure gracefully.
static pthread_mutex_t lock_clockid = PTHREAD_MUTEX_INITIALIZER;
static clockid_t __android_log_clockid()
{
static struct cache r_time_cache = { NULL, static_cast<uint32_t>(-1), 0 };
static struct cache p_time_cache = { NULL, static_cast<uint32_t>(-1), 0 };
char c;
if (pthread_mutex_trylock(&lock_clockid)) {
// We are willing to accept some race in this context
if (!(c = p_time_cache.c)) {
c = r_time_cache.c;
}
} else {
static uint32_t serial;
uint32_t current_serial = __system_property_area_serial();
if (current_serial != serial) {
refresh_cache(&r_time_cache, "ro.logd.timestamp");
refresh_cache(&p_time_cache, "persist.logd.timestamp");
serial = current_serial;
}
if (!(c = p_time_cache.c)) {
c = r_time_cache.c;
}
pthread_mutex_unlock(&lock_clockid);
}
return (tolower(c) == 'm') ? CLOCK_MONOTONIC : CLOCK_REALTIME;
}
struct log_time { // Wire format
uint32_t tv_sec;
uint32_t tv_nsec;
};
int __libc_write_log(int priority, const char* tag, const char* msg) {
int main_log_fd = __libc_open_log_socket();
if (main_log_fd == -1) {
// Try stderr instead.
return __libc_write_stderr(tag, msg);
}
iovec vec[6];
char log_id = (priority == ANDROID_LOG_FATAL) ? LOG_ID_CRASH : LOG_ID_MAIN;
vec[0].iov_base = &log_id;
vec[0].iov_len = sizeof(log_id);
uint16_t tid = gettid();
vec[1].iov_base = &tid;
vec[1].iov_len = sizeof(tid);
timespec ts;
clock_gettime(__android_log_clockid(), &ts);
log_time realtime_ts;
realtime_ts.tv_sec = ts.tv_sec;
realtime_ts.tv_nsec = ts.tv_nsec;
vec[2].iov_base = &realtime_ts;
vec[2].iov_len = sizeof(realtime_ts);
vec[3].iov_base = &priority;
vec[3].iov_len = 1;
vec[4].iov_base = const_cast<char*>(tag);
vec[4].iov_len = strlen(tag) + 1;
vec[5].iov_base = const_cast<char*>(msg);
vec[5].iov_len = strlen(msg) + 1;
int result = TEMP_FAILURE_RETRY(writev(main_log_fd, vec, sizeof(vec) / sizeof(vec[0])));
close(main_log_fd);
return result;
}
int __libc_format_log_va_list(int priority, const char* tag, const char* format, va_list args) {
char buffer[1024];
BufferOutputStream os(buffer, sizeof(buffer));
out_vformat(os, format, args);
return __libc_write_log(priority, tag, buffer);
}
int __libc_format_log(int priority, const char* tag, const char* format, ...) {
va_list args;
va_start(args, format);
int result = __libc_format_log_va_list(priority, tag, format, args);
va_end(args);
return result;
}
static int __libc_android_log_event(int32_t tag, char type, const void* payload, size_t len) {
iovec vec[6];
char log_id = LOG_ID_EVENTS;
vec[0].iov_base = &log_id;
vec[0].iov_len = sizeof(log_id);
uint16_t tid = gettid();
vec[1].iov_base = &tid;
vec[1].iov_len = sizeof(tid);
timespec ts;
clock_gettime(__android_log_clockid(), &ts);
log_time realtime_ts;
realtime_ts.tv_sec = ts.tv_sec;
realtime_ts.tv_nsec = ts.tv_nsec;
vec[2].iov_base = &realtime_ts;
vec[2].iov_len = sizeof(realtime_ts);
vec[3].iov_base = &tag;
vec[3].iov_len = sizeof(tag);
vec[4].iov_base = &type;
vec[4].iov_len = sizeof(type);
vec[5].iov_base = const_cast<void*>(payload);
vec[5].iov_len = len;
int event_log_fd = __libc_open_log_socket();
if (event_log_fd == -1) {
return -1;
}
int result = TEMP_FAILURE_RETRY(writev(event_log_fd, vec, sizeof(vec) / sizeof(vec[0])));
close(event_log_fd);
return result;
}
void __libc_android_log_event_int(int32_t tag, int value) {
__libc_android_log_event(tag, EVENT_TYPE_INT, &value, sizeof(value));
}
void __libc_android_log_event_uid(int32_t tag) {
__libc_android_log_event_int(tag, getuid());
}
void __fortify_chk_fail(const char* msg, uint32_t tag) {
if (tag != 0) {
__libc_android_log_event_uid(tag);
}
__libc_fatal("FORTIFY: %s", msg);
}
void __libc_fatal_no_abort(const char* format, ...) {
va_list args;
va_start(args, format);
__libc_fatal(format, args);
va_end(args);
}
void __libc_fatal(const char* format, ...) {
va_list args;
va_start(args, format);
__libc_fatal(format, args);
va_end(args);
abort();
}

View File

@@ -1,115 +0,0 @@
/*
* Copyright (C) 2010 The Android Open Source Project
* All rights reserved.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "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 THE
* COPYRIGHT OWNER OR CONTRIBUTORS 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 _LIBC_LOGGING_H
#define _LIBC_LOGGING_H
#include <sys/cdefs.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
__BEGIN_DECLS
enum {
ANDROID_LOG_UNKNOWN = 0,
ANDROID_LOG_DEFAULT, /* only for SetMinPriority() */
ANDROID_LOG_VERBOSE,
ANDROID_LOG_DEBUG,
ANDROID_LOG_INFO,
ANDROID_LOG_WARN,
ANDROID_LOG_ERROR,
ANDROID_LOG_FATAL,
ANDROID_LOG_SILENT, /* only for SetMinPriority(); must be last */
};
enum {
LOG_ID_MIN = 0,
LOG_ID_MAIN = 0,
LOG_ID_RADIO = 1,
LOG_ID_EVENTS = 2,
LOG_ID_SYSTEM = 3,
LOG_ID_CRASH = 4,
LOG_ID_MAX
};
struct abort_msg_t {
size_t size;
char msg[0];
};
//
// Formats a message to the log (priority 'fatal'), then aborts.
//
__LIBC_HIDDEN__ __noreturn void __libc_fatal(const char* format, ...) __printflike(1, 2);
//
// Formats a message to the log (priority 'fatal'), but doesn't abort.
// Used by the malloc implementation to ensure that debuggerd dumps memory
// around the bad address.
//
__LIBC_HIDDEN__ void __libc_fatal_no_abort(const char* format, ...)
__printflike(1, 2);
//
// Formatting routines for the C library's internal debugging.
// Unlike the usual alternatives, these don't allocate, and they don't drag in all of stdio.
//
__LIBC_HIDDEN__ int __libc_format_buffer(char* buffer, size_t buffer_size, const char* format, ...)
__printflike(3, 4);
__LIBC_HIDDEN__ int __libc_format_fd(int fd, const char* format, ...)
__printflike(2, 3);
__LIBC_HIDDEN__ int __libc_format_log(int priority, const char* tag, const char* format, ...)
__printflike(3, 4);
__LIBC_HIDDEN__ int __libc_format_log_va_list(int priority, const char* tag, const char* format,
va_list ap);
__LIBC_HIDDEN__ int __libc_write_log(int priority, const char* tag, const char* msg);
//
// Event logging.
//
__LIBC_HIDDEN__ void __libc_android_log_event_int(int32_t tag, int value);
__LIBC_HIDDEN__ void __libc_android_log_event_uid(int32_t tag);
__LIBC_HIDDEN__ __noreturn void __fortify_chk_fail(const char* msg, uint32_t event_tag);
__END_DECLS
#endif

View File

@@ -1,280 +0,0 @@
/*
*
* resetprop.cpp
*
* Copyright 2016 nkk71 <nkk71x@gmail.com>
* Copyright 2016 topjohnwu <topjohnwu#gmail.com>
*
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
#include "_system_properties.h"
#include <sys/system_properties.h>
/* Info:
*
* all changes are in
*
* bionic/libc/bionic/system_properties.cpp
*
* Functions that need to be patched/added in system_properties.cpp
*
* int __system_properties_init()
* on android 7, first tear down the everything then let it initialize again:
* if (initialized) {
* //list_foreach(contexts, [](context_node* l) { l->reset_access(); });
* //return 0;
* free_and_unmap_contexts();
* initialized = false;
* }
*
*
* static prop_area* map_prop_area(const char* filename, bool is_legacy)
* we dont want this read only so change: 'O_RDONLY' to 'O_RDWR'
*
* static prop_area* map_fd_ro(const int fd)
* we dont want this read only so change: 'PROT_READ' to 'PROT_READ | PROT_WRITE'
*
*
* Copy the code of prop_info *prop_area::find_property, and modify to delete props
* const prop_info *prop_area::find_property_and_del(prop_bt *const trie, const char *name)
* {
* ...
* ... Do not alloc a new prop_bt here, remove all code involve alloc_if_needed
* ...
*
* if (prop_offset != 0) {
* atomic_store_explicit(&current->prop, 0, memory_order_release); // Add this line to nullify the prop entry
* return to_prop_info(&current->prop);
* } else {
*
* ....
* }
*
*
* by patching just those functions directly, all other functions should be ok
* as is.
*
*
*/
int verbose = 0, del = 0, file = 0, trigger = 1;
static bool is_legal_property_name(const char* name, size_t namelen)
{
size_t i;
if (namelen >= PROP_NAME_MAX) return false;
if (namelen < 1) return false;
if (name[0] == '.') return false;
if (name[namelen - 1] == '.') return false;
/* Only allow alphanumeric, plus '.', '-', or '_' */
/* Don't allow ".." to appear in a property name */
for (i = 0; i < namelen; i++) {
if (name[i] == '.') {
// i=0 is guaranteed to never have a dot. See above.
if (name[i-1] == '.') return false;
continue;
}
if (name[i] == '_' || name[i] == '-') continue;
if (name[i] >= 'a' && name[i] <= 'z') continue;
if (name[i] >= 'A' && name[i] <= 'Z') continue;
if (name[i] >= '0' && name[i] <= '9') continue;
return false;
}
return true;
}
int x_property_set(const char *name, const char *value)
{
int ret;
char value_read[PROP_VALUE_MAX];
size_t namelen = strlen(name);
size_t valuelen = strlen(value);
if (trigger) {
printf("Set with property_service: '%s'='%s'\n", name, value);
} else {
printf("Modify data structure: '%s'='%s'\n", name, value);
}
__system_property_get(name, value_read);
if(strlen(value_read)) {
printf("Existing property: '%s'='%s'\n", name, value_read);
if (trigger) {
if (!strncmp(name, "ro.", 3)) __system_property_del(name); // Only delete ro props
ret = __system_property_set(name, value);
} else {
ret = __system_property_update((prop_info*) __system_property_find(name), value, valuelen);
}
} else {
if (trigger) {
ret = __system_property_set(name, value);
} else {
ret = __system_property_add(name, namelen, value, valuelen);
}
}
if (ret != 0) {
fprintf(stderr, "Failed to set '%s'='%s'\n", name, value);
return ret;
}
__system_property_get(name, value_read);
printf("Recheck property: '%s'='%s'\n", name, value_read);
return 0;
}
int read_prop_file(const char* filename) {
printf("Attempting to read props from \'%s\'\n", filename);
FILE *fp = fopen(filename, "r");
if (fp == NULL) {
fprintf(stderr, "Cannot open \'%s\'\n", filename);
return 1;
}
char *line = NULL, *pch;
size_t len;
ssize_t read;
int comment = 0, i;
while ((read = getline(&line, &len, fp)) != -1) {
// Remove the trailing newline
if (line[read - 1] == '\n') {
line[read - 1] = '\0';
--read;
}
comment = 0;
for (i = 0; i < read; ++i) {
// Ignore starting spaces
if (line[i] == ' ') continue;
else {
// A line starting with # is ignored
if (line[i] == '#') comment = 1;
break;
}
}
if (comment) continue;
pch = strchr(line, '=');
// Ignore ivalid formats
if ( ((pch == NULL) || (i >= (pch - line))) || (pch >= line + read - 1) ) continue;
// Separate the string
*pch = '\0';
x_property_set(line + i, pch + 1);
}
free(line);
fclose(fp);
return 0;
}
int usage(char* name) {
fprintf(stderr, "usage: %s [-v] [-n] [--file propfile] [--delete name] [ name value ] \n", name);
fprintf(stderr, " -v :\n");
fprintf(stderr, " verbose output (Default: Disabled)\n");
fprintf(stderr, " -n :\n");
fprintf(stderr, " no event triggers when changing props (Default: Will trigger events)\n");
fprintf(stderr, " --file propfile :\n");
fprintf(stderr, " Read props from prop files (e.g. build.prop)\n");
fprintf(stderr, " --delete name :\n");
fprintf(stderr, " Remove a prop entry\n\n");
return 1;
}
int main(int argc, char *argv[])
{
int exp_arg = 2, stdout_bak, null;
char *name, *value, *filename;
if (argc < 3) {
return usage(argv[0]);
}
for (int i = 1; i < argc; ++i) {
if (!strcmp("-v", argv[i])) {
verbose = 1;
} else if (!strcmp("-n", argv[i])) {
trigger = 0;
} else if (!strcmp("--file", argv[i])) {
file = 1;
exp_arg = 1;
} else if (!strcmp("--delete", argv[i])) {
del = 1;
exp_arg = 1;
} else {
if (i + exp_arg > argc) {
return usage(argv[0]);
}
if (file) {
filename = argv[i];
break;
} else {
if(!is_legal_property_name(argv[i], strlen(argv[i]))) {
fprintf(stderr, "Illegal property name \'%s\'\n", argv[i]);
return 1;
}
name = argv[i];
if (exp_arg > 1) {
if (strlen(argv[i + 1]) >= PROP_VALUE_MAX) {
fprintf(stderr, "Value too long \'%s\'\n", argv[i + 1]);
return 1;
}
value = argv[i + 1];
}
break;
}
}
}
if (!verbose) {
fflush(stdout);
stdout_bak = dup(1);
null = open("/dev/null", O_WRONLY);
dup2(null, 1);
}
printf("resetprop by nkk71 & topjohnwu\n");
printf("Initializing...\n");
if (__system_properties_init()) {
fprintf(stderr, "Error during init\n");
return 1;
}
if (file) {
if (read_prop_file(filename)) return 1;
} else if (del) {
printf("Attempting to delete '%s'\n", name);
if (__system_property_del(name)) return 1;
} else {
if(x_property_set(name, value)) return 1;
}
printf("Done!\n\n");
return 0;
}

File diff suppressed because it is too large Load Diff

Submodule jni/selinux deleted from d7c6efa178

1
jni/su

Submodule jni/su deleted from 356b2c0f5f

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_

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;
}

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