Compare commits

...

49 Commits
v13.0 ... v13.2

Author SHA1 Message Date
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
64 changed files with 5632 additions and 211557 deletions

View File

@@ -76,9 +76,9 @@ def build_apk(args):
if proc.returncode != 0: if proc.returncode != 0:
error('Build Magisk Manager failed!') error('Build Magisk Manager failed!')
unsigned = os.path.join('app', 'build', 'outputs', 'apk', 'app-release-unsigned.apk') unsigned = os.path.join('app', 'build', 'outputs', 'apk', 'release', 'app-release-unsigned.apk')
aligned = os.path.join('app', 'build', 'outputs', 'apk', 'app-release-aligned.apk') aligned = os.path.join('app', 'build', 'outputs', 'apk', 'release', 'app-release-aligned.apk')
release = os.path.join('app', 'build', 'outputs', 'apk', 'app-release.apk') release = os.path.join('app', 'build', 'outputs', 'apk', 'release', 'app-release.apk')
# Find the latest build tools # Find the latest build tools
build_tool = sorted(os.listdir(os.path.join(os.environ['ANDROID_HOME'], 'build-tools')))[-1] build_tool = sorted(os.listdir(os.path.join(os.environ['ANDROID_HOME'], 'build-tools')))[-1]
@@ -93,7 +93,7 @@ def build_apk(args):
error('Zipalign Magisk Manager failed!') error('Zipalign Magisk Manager failed!')
proc = subprocess.run('{} sign --ks {} --out {} {}'.format( proc = subprocess.run('{} sign --ks {} --out {} {}'.format(
os.path.join(os.environ['ANDROID_HOME'], 'build-tools', build_tool, 'apksigner'), 'java -jar {}'.format(os.path.join('../ziptools/apksigner.jar')),
os.path.join('..', 'release_signature.jks'), os.path.join('..', 'release_signature.jks'),
release, aligned), shell=True) release, aligned), shell=True)
if proc.returncode != 0: if proc.returncode != 0:
@@ -154,29 +154,51 @@ def zip_main(args):
zip_with_msg(zipf, source, target) zip_with_msg(zipf, source, target)
# APK # APK
source = os.path.join('MagiskManager', 'app', 'build', 'outputs', 'apk', 'app-release.apk' if args.release else 'app-debug.apk') source = os.path.join('MagiskManager', 'app', 'build', 'outputs', 'apk',
'release' if args.release else 'debug', 'app-release.apk' if args.release else 'app-debug.apk')
target = os.path.join('common', 'magisk.apk') target = os.path.join('common', 'magisk.apk')
zip_with_msg(zipf, source, target) zip_with_msg(zipf, source, target)
# Scripts # Scripts
# flash_script.sh
source = os.path.join('scripts', 'flash_script.sh') source = os.path.join('scripts', 'flash_script.sh')
with open(source, 'r') as flash_script: with open(source, 'r') as script:
# Add version info into flash script # Add version info into flash script
update_binary = flash_script.read().replace( update_binary = script.read().replace(
'MAGISK_VERSION_STUB', 'Magisk v{} Installer'.format(args.versionString)) 'MAGISK_VERSION_STUB', 'Magisk v{} Installer'.format(args.versionString))
target = os.path.join('META-INF', 'com', 'google', 'android', 'update-binary') target = os.path.join('META-INF', 'com', 'google', 'android', 'update-binary')
print('zip: ' + source + ' -> ' + target) print('zip: ' + source + ' -> ' + target)
zipf.writestr(target, update_binary) zipf.writestr(target, update_binary)
# addon.d.sh
source = os.path.join('scripts', 'addon.d.sh')
with open(source, 'r') as script:
# Add version info addon.d.sh
addond = script.read().replace(
'MAGISK_VERSION_STUB', 'Magisk v{} addon.d'.format(args.versionString))
target = os.path.join('addon.d', '99-magisk.sh')
print('zip: ' + source + ' -> ' + target)
zipf.writestr(target, addond)
# updater-script
target = os.path.join('META-INF', 'com', 'google', 'android', 'updater-script') target = os.path.join('META-INF', 'com', 'google', 'android', 'updater-script')
print('zip: ' + target) print('zip: ' + target)
zipf.writestr(target, '#MAGISK\n') zipf.writestr(target, '#MAGISK\n')
# init.magisk.rc
source = os.path.join('scripts', 'init.magisk.rc') source = os.path.join('scripts', 'init.magisk.rc')
target = os.path.join('common', 'init.magisk.rc') target = os.path.join('common', 'init.magisk.rc')
zip_with_msg(zipf, source, target) zip_with_msg(zipf, source, target)
# boot_patch.sh
source = os.path.join('scripts', 'boot_patch.sh') source = os.path.join('scripts', 'boot_patch.sh')
target = os.path.join('common', 'boot_patch.sh') target = os.path.join('common', 'boot_patch.sh')
zip_with_msg(zipf, source, target) 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', 'SCRIPT_VERSION={}'.format(args.versionCode))
target = os.path.join('common', 'util_functions.sh')
print('zip: ' + source + ' -> ' + target)
zipf.writestr(target, util_func)
# Prebuilts # Prebuilts
for chromeos in ['futility', 'kernel_data_key.vbprivk', 'kernel.keyblock']: for chromeos in ['futility', 'kernel_data_key.vbprivk', 'kernel.keyblock']:
source = os.path.join('chromeos', chromeos) source = os.path.join('chromeos', chromeos)
@@ -201,6 +223,16 @@ def zip_uninstaller(args):
target = 'magisk_uninstaller.sh' target = 'magisk_uninstaller.sh'
zip_with_msg(zipf, source, target) zip_with_msg(zipf, source, target)
# util_functions.sh
source = os.path.join('scripts', 'util_functions.sh')
with open(source, 'r') as script:
# Remove the stub
util_func = script.read().replace(
'MAGISK_VERSION_STUB', '')
target = os.path.join('util_functions.sh')
print('zip: ' + source + ' -> ' + target)
zipf.writestr(target, util_func)
source = os.path.join('scripts', 'uninstaller_loader.sh') source = os.path.join('scripts', 'uninstaller_loader.sh')
target = os.path.join('META-INF', 'com', 'google', 'android', 'update-binary') target = os.path.join('META-INF', 'com', 'google', 'android', 'update-binary')
zip_with_msg(zipf, source, target) zip_with_msg(zipf, source, target)
@@ -209,6 +241,13 @@ def zip_uninstaller(args):
print('zip: ' + target) print('zip: ' + target)
zipf.writestr(target, '#MAGISK\n') zipf.writestr(target, '#MAGISK\n')
# Prebuilts
for chromeos in ['futility', 'kernel_data_key.vbprivk', 'kernel.keyblock']:
source = os.path.join('chromeos', chromeos)
zip_with_msg(zipf, source, source)
# End of zipping
output = 'Magisk-uninstaller-{}.zip'.format(datetime.datetime.now().strftime('%Y%m%d')) output = 'Magisk-uninstaller-{}.zip'.format(datetime.datetime.now().strftime('%Y%m%d'))
sign_adjust_zip('tmp_unsigned.zip', output) sign_adjust_zip('tmp_unsigned.zip', output)
@@ -252,12 +291,13 @@ apk_parser.set_defaults(func=build_apk)
zip_parser = subparsers.add_parser('zip', help='zip and sign Magisk into a flashable zip') zip_parser = subparsers.add_parser('zip', help='zip and sign Magisk into a flashable zip')
zip_parser.add_argument('versionString') zip_parser.add_argument('versionString')
zip_parser.add_argument('versionCode', type=int)
zip_parser.set_defaults(func=zip_main) zip_parser.set_defaults(func=zip_main)
uninstaller_parser = subparsers.add_parser('uninstaller', help='create flashable uninstaller') uninstaller_parser = subparsers.add_parser('uninstaller', help='create flashable uninstaller')
uninstaller_parser.set_defaults(func=zip_uninstaller) uninstaller_parser.set_defaults(func=zip_uninstaller)
clean_parser = subparsers.add_parser('clean', help='clean [target...] Targets: binary apk zip (default: all)') clean_parser = subparsers.add_parser('clean', help='clean [target...] targets: binary apk zip')
clean_parser.add_argument('target', nargs='*') clean_parser.add_argument('target', nargs='*')
clean_parser.set_defaults(func=cleanup) clean_parser.set_defaults(func=cleanup)

View File

@@ -10,9 +10,8 @@ LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/daemon \ $(LOCAL_PATH)/daemon \
$(LOCAL_PATH)/resetprop \ $(LOCAL_PATH)/resetprop \
$(LOCAL_PATH)/magiskpolicy \ $(LOCAL_PATH)/magiskpolicy \
$(LOCAL_PATH)/selinux/libselinux/include \ $(LOCAL_PATH)/external \
$(LOCAL_PATH)/selinux/libsepol/include \ $(LOCAL_PATH)/selinux/libsepol/include
$(LOCAL_PATH)/sqlite3
LOCAL_SRC_FILES := \ LOCAL_SRC_FILES := \
main.c \ main.c \
@@ -20,15 +19,14 @@ LOCAL_SRC_FILES := \
utils/vector.c \ utils/vector.c \
utils/xwrap.c \ utils/xwrap.c \
utils/list.c \ utils/list.c \
utils/img.c \
daemon/daemon.c \ daemon/daemon.c \
daemon/socket_trans.c \ daemon/socket_trans.c \
daemon/log_monitor.c \ daemon/log_monitor.c \
daemon/bootstages.c \ daemon/bootstages.c \
magiskhide/magiskhide.c \ magiskhide/magiskhide.c \
magiskhide/hide_daemon.c \
magiskhide/proc_monitor.c \ magiskhide/proc_monitor.c \
magiskhide/pre_process.c \ magiskhide/hide_utils.c \
magiskhide/list_manager.c \
magiskpolicy/magiskpolicy.c \ magiskpolicy/magiskpolicy.c \
magiskpolicy/rules.c \ magiskpolicy/rules.c \
magiskpolicy/sepolicy.c \ magiskpolicy/sepolicy.c \
@@ -48,18 +46,11 @@ LOCAL_LDLIBS := -llog
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)
# Libraries # External shared libraries, build stub libraries for linking
include jni/selinux/libselinux/Android.mk include jni/external/Android.mk
include jni/selinux/libsepol/Android.mk
include jni/sqlite3/Android.mk
##################################################################### # libsepol, static library
# In order to build separate binaries, please comment out everything include jni/selinux/libsepol/Android.mk
# starting from line 3 (including the 3 lines for libraries)
# Then, uncomment the line you want below
#####################################################################
# include jni/resetprop/Android.mk
# include jni/magiskpolicy/Android.mk
# Build magiskboot # Build magiskboot
include jni/magiskboot/Android.mk include jni/magiskboot/Android.mk

View File

@@ -1,4 +1,8 @@
/* post_fs_data.c - post-fs-data actions /* 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 <stdlib.h>
@@ -29,11 +33,13 @@ static int debug_log_pid, debug_log_fd;
* Node structure * * Node structure *
******************/ ******************/
// Precedence: MODULE > SKEL > DUMMY // Precedence: MODULE > SKEL > INTER > DUMMY
#define DO_NOTHING 0x0 /* intermediate node */ #define IS_DUMMY 0x01 /* mount from mirror */
#define IS_DUMMY 0x1 /* mount from mirror */ #define IS_INTER 0x02 /* intermediate node */
#define IS_SKEL 0x2 /* mount from skeleton */ #define IS_SKEL 0x04 /* mount from skeleton */
#define IS_MODULE 0x4 /* mount from module */ #define IS_MODULE 0x08 /* mount from module */
#define IS_VENDOR 0x10 /* special vendor placeholder */
struct node_entry { struct node_entry {
const char *module; /* Only used when status & IS_MODULE */ const char *module; /* Only used when status & IS_MODULE */
@@ -52,45 +58,9 @@ struct node_entry {
* Image handling * * Image handling *
******************/ ******************/
static char *loopsetup(const char *img) {
char device[20];
struct loop_info64 info;
int i, lfd, ffd;
memset(&info, 0, sizeof(info));
// First get an empty loop device
for (i = 0; i <= 7; ++i) {
sprintf(device, "/dev/block/loop%d", i);
lfd = xopen(device, O_RDWR);
if (ioctl(lfd, LOOP_GET_STATUS64, &info) == -1)
break;
close(lfd);
}
if (i == 8) return NULL;
ffd = xopen(img, O_RDWR);
if (ioctl(lfd, LOOP_SET_FD, ffd) == -1)
return NULL;
strcpy((char *) info.lo_file_name, img);
ioctl(lfd, LOOP_SET_STATUS64, &info);
close(lfd);
close(ffd);
return strdup(device);
}
static char *mount_image(const char *img, const char *target) {
char *device = loopsetup(img);
if (device)
xmount(device, target, "ext4", 0, NULL);
return device;
}
static void umount_image(const char *target, const char *device) {
xumount(target);
int fd = xopen(device, O_RDWR);
ioctl(fd, LOOP_CLR_FD);
close(fd);
}
#define round_size(a) ((((a) / 32) + 2) * 32) #define round_size(a) ((((a) / 32) + 2) * 32)
#define SOURCE_TMP "/dev/source"
#define TARGET_TMP "/dev/target"
static int merge_img(const char *source, const char *target) { static int merge_img(const char *source, const char *target) {
if (access(source, F_OK) == -1) if (access(source, F_OK) == -1)
@@ -105,20 +75,20 @@ static int merge_img(const char *source, const char *target) {
get_img_size(source, &s_used, &s_total); get_img_size(source, &s_used, &s_total);
get_img_size(target, &t_used, &t_total); get_img_size(target, &t_used, &t_total);
n_total = round_size(s_used + t_used); n_total = round_size(s_used + t_used);
if (n_total != t_total && resize_img(target, n_total)) if (n_total != t_total)
return 1; resize_img(target, n_total);
xmkdir("/cache/source", 0755); xmkdir(SOURCE_TMP, 0755);
xmkdir("/cache/target", 0755); xmkdir(TARGET_TMP, 0755);
char *s_loop, *t_loop; char *s_loop, *t_loop;
s_loop = mount_image(source, "/cache/source"); s_loop = mount_image(source, SOURCE_TMP);
if (s_loop == NULL) return 1; if (s_loop == NULL) return 1;
t_loop = mount_image(target, "/cache/target"); t_loop = mount_image(target, TARGET_TMP);
if (t_loop == NULL) return 1; if (t_loop == NULL) return 1;
DIR *dir; DIR *dir;
struct dirent *entry; struct dirent *entry;
if (!(dir = opendir("/cache/source"))) if (!(dir = opendir(SOURCE_TMP)))
return 1; return 1;
while ((entry = xreaddir(dir))) { while ((entry = xreaddir(dir))) {
if (entry->d_type == DT_DIR) { if (entry->d_type == DT_DIR) {
@@ -127,22 +97,24 @@ static int merge_img(const char *source, const char *target) {
strcmp(entry->d_name, ".core") == 0 || strcmp(entry->d_name, ".core") == 0 ||
strcmp(entry->d_name, "lost+found") == 0) strcmp(entry->d_name, "lost+found") == 0)
continue; continue;
// Cleanup old module // Cleanup old module if exists
snprintf(buf, PATH_MAX, "/cache/target/%s", entry->d_name); snprintf(buf, PATH_MAX, "%s/%s", TARGET_TMP, entry->d_name);
if (access(buf, F_OK) == 0) { if (access(buf, F_OK) == 0) {
LOGI("merge module %s\n", entry->d_name); LOGI("Upgrade module: %s\n", entry->d_name);
rm_rf(buf); rm_rf(buf);
} else {
LOGI("New module: %s\n", entry->d_name);
} }
} }
} }
closedir(dir); closedir(dir);
clone_dir("/cache/source", "/cache/target"); clone_dir(SOURCE_TMP, TARGET_TMP);
// Unmount all loop devices // Unmount all loop devices
umount_image("/cache/source", s_loop); umount_image(SOURCE_TMP, s_loop);
umount_image("/cache/target", t_loop); umount_image(TARGET_TMP, t_loop);
rmdir("/cache/source"); rmdir(SOURCE_TMP);
rmdir("/cache/target"); rmdir(TARGET_TMP);
free(s_loop); free(s_loop);
free(t_loop); free(t_loop);
unlink(source); unlink(source);
@@ -248,9 +220,7 @@ static struct node_entry *insert_child(struct node_entry *p, struct node_entry *
// Exist duplicate // Exist duplicate
if (c->status > e->status) { if (c->status > e->status) {
// Precedence is higher, replace with new node // Precedence is higher, replace with new node
c->children = e->children; // Preserve all children destroy_subtree(e);
free(e->name);
free(e);
vec_entry(p->children)[_] = c; vec_entry(p->children)[_] = c;
return c; return c;
} else { } else {
@@ -285,25 +255,44 @@ static void construct_tree(const char *module, struct node_entry *parent) {
node->name = strdup(entry->d_name); node->name = strdup(entry->d_name);
node->type = entry->d_type; node->type = entry->d_type;
snprintf(buf, PATH_MAX, "%s/%s", parent_path, node->name); snprintf(buf, PATH_MAX, "%s/%s", parent_path, node->name);
// Check if the entry has a correspond target
/*
* 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) { if (IS_LNK(node) || access(buf, F_OK) == -1) {
clone = 1;
} else if (strcmp(parent->name, "/system") != 0 || 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 // Mark the parent folder as a skeleton
parent->status |= IS_SKEL; parent->status |= IS_SKEL; /* This will not overwrite if parent is module */
node->status |= IS_MODULE; node->status = IS_MODULE;
} else if (IS_DIR(node)) { } else if (IS_DIR(node)) {
// Check if marked as replace // Check if marked as replace
snprintf(buf2, PATH_MAX, "%s/%s%s/.replace", MOUNTPOINT, module, buf); snprintf(buf2, PATH_MAX, "%s/%s%s/.replace", MOUNTPOINT, module, buf);
if (access(buf2, F_OK) == 0) { if (access(buf2, F_OK) == 0) {
// Replace everything, mark as leaf // Replace everything, mark as leaf
node->status |= IS_MODULE; node->status = IS_MODULE;
} else {
// This will be an intermediate node
node->status = IS_INTER;
} }
} else if (IS_REG(node)) { } else if (IS_REG(node)) {
// This is a leaf, mark as target // This is a leaf, mark as target
node->status |= IS_MODULE; node->status = IS_MODULE;
} }
node = insert_child(parent, node); node = insert_child(parent, node);
if (IS_DIR(node) && !(node->status & IS_MODULE)) { if (node->status & (IS_SKEL | IS_INTER)) {
// Intermediate node, travel deeper // Intermediate folder, travel deeper
construct_tree(module, node); construct_tree(module, node);
} }
} }
@@ -321,7 +310,8 @@ static void clone_skeleton(struct node_entry *node) {
// Clone the structure // Clone the structure
char *full_path = get_full_path(node); char *full_path = get_full_path(node);
if (!(dir = opendir(full_path))) snprintf(buf, PATH_MAX, "%s%s", MIRRDIR, full_path);
if (!(dir = opendir(buf)))
goto cleanup; goto cleanup;
while ((entry = xreaddir(dir))) { while ((entry = xreaddir(dir))) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
@@ -330,7 +320,7 @@ static void clone_skeleton(struct node_entry *node) {
dummy = xcalloc(sizeof(*dummy), 1); dummy = xcalloc(sizeof(*dummy), 1);
dummy->name = strdup(entry->d_name); dummy->name = strdup(entry->d_name);
dummy->type = entry->d_type; dummy->type = entry->d_type;
dummy->status |= IS_DUMMY; dummy->status = IS_DUMMY;
insert_child(node, dummy); insert_child(node, dummy);
} }
closedir(dir); closedir(dir);
@@ -338,21 +328,31 @@ static void clone_skeleton(struct node_entry *node) {
snprintf(buf, PATH_MAX, "%s%s", DUMMDIR, full_path); snprintf(buf, PATH_MAX, "%s%s", DUMMDIR, full_path);
mkdir_p(buf, 0755); mkdir_p(buf, 0755);
clone_attr(full_path, buf); clone_attr(full_path, buf);
if (node->status & IS_SKEL)
bind_mount(buf, full_path); bind_mount(buf, full_path);
vec_for_each(node->children, child) { vec_for_each(node->children, child) {
snprintf(buf, PATH_MAX, "%s%s/%s", DUMMDIR, full_path, child->name); snprintf(buf, PATH_MAX, "%s%s/%s", DUMMDIR, full_path, child->name);
// Create the dummy file/directory // Create the dummy file/directory
if (IS_DIR(child)) if (IS_DIR(child))
xmkdir(buf, 0755); xmkdir(buf, 0755);
else if (IS_REG(child)) else if (IS_REG(child))
close(open_new(buf)); close(open_new(buf));
// Links will be handled later
if (child->status & IS_MODULE) { if (child->status & IS_VENDOR) {
if (IS_LNK(child)) {
cp_afc(MIRRDIR "/system/vendor", "/system/vendor");
LOGI("cplink: %s -> %s\n", MIRRDIR "/system/vendor", "/system/vendor");
}
// Skip
continue;
} else if (child->status & IS_MODULE) {
// Mount from module file to dummy file // Mount from module file to dummy file
snprintf(buf2, PATH_MAX, "%s/%s%s/%s", MOUNTPOINT, child->module, full_path, child->name); snprintf(buf2, PATH_MAX, "%s/%s%s/%s", MOUNTPOINT, child->module, full_path, child->name);
} else if (child->status & IS_SKEL) { } else if (child->status & (IS_SKEL | IS_INTER)) {
// It's another skeleton, recursive call and end // It's a intermediate folder, recursive clone
clone_skeleton(child); clone_skeleton(child);
continue; continue;
} else if (child->status & IS_DUMMY) { } else if (child->status & IS_DUMMY) {
@@ -361,11 +361,8 @@ static void clone_skeleton(struct node_entry *node) {
} }
if (IS_LNK(child)) { if (IS_LNK(child)) {
// Symlink special treatments // Copy symlinks directly
char *temp = xmalloc(PATH_MAX); cp_afc(buf2, buf);
xreadlink(buf2, temp, PATH_MAX);
symlink(temp, buf);
free(temp);
LOGI("cplink: %s -> %s\n", buf2, buf); LOGI("cplink: %s -> %s\n", buf2, buf);
} else { } else {
snprintf(buf, PATH_MAX, "%s/%s", full_path, child->name); snprintf(buf, PATH_MAX, "%s/%s", full_path, child->name);
@@ -381,15 +378,6 @@ static void magic_mount(struct node_entry *node) {
char *real_path; char *real_path;
struct node_entry *child; struct node_entry *child;
if (strcmp(node->name, "vendor") == 0 && strcmp(node->parent->name, "/system") == 0) {
snprintf(buf, PATH_MAX, "%s/%s/system/vendor", MOUNTPOINT, node->module);
snprintf(buf2, PATH_MAX, "%s/%s/vendor", MOUNTPOINT, node->module);
unlink(buf2);
symlink(buf, buf2);
return;
}
if (node->status) {
if (node->status & IS_MODULE) { if (node->status & IS_MODULE) {
// The real deal, mount module item // The real deal, mount module item
real_path = get_full_path(node); real_path = get_full_path(node);
@@ -399,13 +387,13 @@ static void magic_mount(struct node_entry *node) {
} else if (node->status & IS_SKEL) { } else if (node->status & IS_SKEL) {
// The node is labeled to be cloned with skeleton, lets do it // The node is labeled to be cloned with skeleton, lets do it
clone_skeleton(node); clone_skeleton(node);
} } else if (node->status & IS_INTER) {
// We should not see dummies, so no need to handle it here
} else {
// It's an intermediate node, travel deeper // It's an intermediate node, travel deeper
vec_for_each(node->children, child) vec_for_each(node->children, child)
magic_mount(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
} }
/**************** /****************
@@ -434,7 +422,7 @@ static void simple_mount(const char *path) {
free(new_path); free(new_path);
} else if (entry->d_type == DT_REG) { } else if (entry->d_type == DT_REG) {
// Actual file path // Actual file path
snprintf(buf, PATH_MAX, "%s/%s", buf, entry->d_name); snprintf(buf, PATH_MAX, "%s%s", CACHEMOUNT, buf2);
// Clone all attributes // Clone all attributes
clone_attr(buf2, buf); clone_attr(buf2, buf);
// Finally, mount the file // Finally, mount the file
@@ -523,19 +511,23 @@ void post_fs_data(int client) {
} }
// Magisk Manual Injector support // Magisk Manual Injector support
if (access("/data/local/tmp/magisk", F_OK) == 0) { if (access("/data/local/tmp/magisk_inject", F_OK) == 0) {
rm_rf(DATABIN); rm_rf(DATABIN);
rename("/data/local/tmp/magisk", DATABIN); rename("/data/local/tmp/magisk_inject", DATABIN);
} }
// Lazy.... use shell blob // Lazy.... use shell blob
system("mv /data/magisk/stock_boot* /data;"); system("mv /data/magisk/stock_boot* /data;");
// Merge images // Merge images
if (merge_img("/cache/magisk.img", MAINIMG)) if (merge_img("/cache/magisk.img", MAINIMG)) {
LOGE("Image merge %s -> %s failed!\n", "/cache/magisk.img", MAINIMG);
goto unblock; goto unblock;
if (merge_img("/data/magisk_merge.img", MAINIMG)) }
if (merge_img("/data/magisk_merge.img", MAINIMG)) {
LOGE("Image merge %s -> %s failed!\n", "/data/magisk_merge.img", MAINIMG);
goto unblock; goto unblock;
}
int new_img = 0; int new_img = 0;
@@ -545,9 +537,6 @@ void post_fs_data(int client) {
new_img = 1; new_img = 1;
} }
// Initialize resetprop for the daemon
init_resetprop();
LOGI("* Mounting " MAINIMG "\n"); LOGI("* Mounting " MAINIMG "\n");
// Mounting magisk image // Mounting magisk image
char *magiskloop = mount_image(MAINIMG, MOUNTPOINT); char *magiskloop = mount_image(MAINIMG, MOUNTPOINT);
@@ -555,10 +544,10 @@ void post_fs_data(int client) {
goto unblock; goto unblock;
if (new_img) { if (new_img) {
mkdir(COREDIR, 0755); xmkdir(COREDIR, 0755);
mkdir(COREDIR "/post-fs-data.d", 0755); xmkdir(COREDIR "/post-fs-data.d", 0755);
mkdir(COREDIR "/service.d", 0755); xmkdir(COREDIR "/service.d", 0755);
mkdir(COREDIR "/props", 0755); xmkdir(COREDIR "/props", 0755);
} }
// Run common scripts // Run common scripts
@@ -567,7 +556,7 @@ void post_fs_data(int client) {
// Core only mode // Core only mode
if (access(DISABLEFILE, F_OK) == 0) if (access(DISABLEFILE, F_OK) == 0)
goto unblock; goto core_only;
DIR *dir; DIR *dir;
struct dirent *entry; struct dirent *entry;
@@ -579,6 +568,7 @@ void post_fs_data(int client) {
// Create the system root entry // Create the system root entry
sys_root = xcalloc(sizeof(*sys_root), 1); sys_root = xcalloc(sizeof(*sys_root), 1);
sys_root->name = strdup("/system"); sys_root->name = strdup("/system");
sys_root->status = IS_INTER;
int has_modules = 0; int has_modules = 0;
@@ -624,6 +614,13 @@ void post_fs_data(int client) {
// Construct structure // Construct structure
has_modules = 1; has_modules = 1;
LOGI("%s: constructing magic mount structure\n", module); LOGI("%s: constructing magic mount structure\n", module);
// If /system/vendor exists in module, create a link outside
snprintf(buf2, PATH_MAX, "%s/system/vendor", buf);
if (access(buf2, F_OK) == 0) {
snprintf(buf, PATH_MAX, "%s/%s/vendor", MOUNTPOINT, module);
unlink(buf);
symlink(buf2, buf);
}
construct_tree(module, sys_root); construct_tree(module, sys_root);
} }
} }
@@ -674,46 +671,50 @@ void post_fs_data(int client) {
LOGI("link: %s -> %s\n", buf, buf2); LOGI("link: %s -> %s\n", buf, buf2);
} }
// Magic!! // Extract the vendor node out of system tree and swap with placeholder
magic_mount(sys_root);
// Get the vendor node if exists
vec_for_each(sys_root->children, child) { vec_for_each(sys_root->children, child) {
if (strcmp(child->name, "vendor") == 0) { if (strcmp(child->name, "vendor") == 0) {
ven_root = child; ven_root = child;
free(ven_root->name); child = xcalloc(sizeof(*child), 1);
child->type = seperate_vendor ? DT_LNK : DT_DIR;
child->parent = ven_root->parent;
child->name = ven_root->name;
child->status = IS_VENDOR;
vec_entry(sys_root->children)[_] = child;
ven_root->name = strdup("/vendor"); ven_root->name = strdup("/vendor");
ven_root->parent = NULL; ven_root->parent = NULL;
break; break;
} }
} }
if (ven_root)
magic_mount(ven_root); // Magic!!
magic_mount(sys_root);
if (ven_root) magic_mount(ven_root);
} }
// Cleanup memory // Cleanup memory
destroy_subtree(sys_root); destroy_subtree(sys_root);
if (ven_root) destroy_subtree(ven_root);
// Execute module scripts // Execute module scripts
LOGI("* Running module post-fs-data scripts\n"); LOGI("* Running module post-fs-data scripts\n");
exec_module_script("post-fs-data"); exec_module_script("post-fs-data");
core_only:
// Systemless hosts // Systemless hosts
if (access(HOSTSFILE, F_OK) == 0) { if (access(HOSTSFILE, F_OK) == 0) {
LOGI("* Enabling systemless hosts file support"); LOGI("* Enabling systemless hosts file support");
bind_mount(HOSTSFILE, "/system/etc/hosts"); bind_mount(HOSTSFILE, "/system/etc/hosts");
} }
// Start magiskhide if enabled // Enable magiskhide by default, only disable when set explicitly
char *hide_prop = getprop(MAGISKHIDE_PROP); char *hide_prop = getprop(MAGISKHIDE_PROP);
if (hide_prop) { if (hide_prop == NULL || strcmp(hide_prop, "0") != 0) {
if (strcmp(hide_prop, "1") == 0) {
pthread_t thread; pthread_t thread;
xpthread_create(&thread, NULL, start_magisk_hide, NULL); xpthread_create(&thread, NULL, start_magisk_hide, NULL);
pthread_detach(thread); pthread_detach(thread);
} }
free(hide_prop); free(hide_prop);
}
unblock: unblock:
unblock_boot_process(); unblock_boot_process();
@@ -735,18 +736,25 @@ void late_start(int client) {
// Run scripts after full patch, most reliable way to run scripts // Run scripts after full patch, most reliable way to run scripts
LOGI("* Running service.d scripts\n"); LOGI("* Running service.d scripts\n");
exec_common_script("service"); exec_common_script("service");
// Core only mode
if (access(DISABLEFILE, F_OK) == 0) {
setprop("ro.magisk.disable", "1");
return;
}
LOGI("* Running module service scripts\n"); LOGI("* Running module service scripts\n");
exec_module_script("service"); exec_module_script("service");
// Install Magisk Manager if exists // Install Magisk Manager if exists
if (access(MANAGERAPK, F_OK) == 0) { if (access(MANAGERAPK, F_OK) == 0) {
while(1) { while (1) {
sleep(5); sleep(5);
char *const command[] = { "sh", "-c", char *const command[] = { "sh", "-c",
"CLASSPATH=/system/framework/pm.jar " "CLASSPATH=/system/framework/pm.jar "
"/system/bin/app_process /system/bin " "/system/bin/app_process /system/bin "
"com.android.commands.pm.Pm install -r " MANAGERAPK, NULL }; "com.android.commands.pm.Pm install -r " MANAGERAPK, NULL };
int apk_res = 0, pid; int apk_res = -1, pid;
pid = run_command(1, &apk_res, "/system/bin/sh", command); pid = run_command(1, &apk_res, "/system/bin/sh", command);
waitpid(pid, NULL, 0); waitpid(pid, NULL, 0);
fdgets(buf, PATH_MAX, apk_res); fdgets(buf, PATH_MAX, apk_res);
@@ -761,11 +769,11 @@ void late_start(int client) {
// All boot stage done, cleanup everything // All boot stage done, cleanup everything
free(buf); free(buf);
free(buf2); free(buf2);
buf = buf2 = NULL;
vec_deep_destroy(&module_list); vec_deep_destroy(&module_list);
#ifdef DEBUG #ifdef DEBUG
// Stop recording the boot logcat after every boot task is done // Stop recording the boot logcat after every boot task is done
extern int debug_log_pid, debug_log_fd;
kill(debug_log_pid, SIGTERM); kill(debug_log_pid, SIGTERM);
waitpid(debug_log_pid, NULL, 0); waitpid(debug_log_pid, NULL, 0);
close(debug_log_fd); close(debug_log_fd);

View File

@@ -23,7 +23,6 @@
#include "magiskpolicy.h" #include "magiskpolicy.h"
pthread_t sepol_patch; pthread_t sepol_patch;
int null_fd;
static void *request_handler(void *args) { static void *request_handler(void *args) {
// Setup the default error handler for threads // Setup the default error handler for threads
@@ -89,17 +88,12 @@ static void *request_handler(void *args) {
default: default:
break; break;
} }
// Just in case
close(client);
return NULL; return NULL;
} }
/* Setup the address and return socket fd */ /* Setup the address and return socket fd */
static int setup_socket(struct sockaddr_un *sun) { static int setup_socket(struct sockaddr_un *sun) {
int fd = xsocket(AF_LOCAL, SOCK_STREAM, 0); int fd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
if (fcntl(fd, F_SETFD, FD_CLOEXEC))
PLOGE("fcntl FD_CLOEXEC");
memset(sun, 0, sizeof(*sun)); memset(sun, 0, sizeof(*sun));
sun->sun_family = AF_LOCAL; sun->sun_family = AF_LOCAL;
memcpy(sun->sun_path, REQUESTOR_DAEMON_PATH, REQUESTOR_DAEMON_PATH_LEN); memcpy(sun->sun_path, REQUESTOR_DAEMON_PATH, REQUESTOR_DAEMON_PATH_LEN);
@@ -137,10 +131,11 @@ void start_daemon(int client) {
xsetsid(); xsetsid();
setcon("u:r:su:s0"); setcon("u:r:su:s0");
umask(022); umask(022);
null_fd = xopen("/dev/null", O_RDWR | O_CLOEXEC); int fd = xopen("/dev/null", O_RDWR | O_CLOEXEC);
xdup2(null_fd, STDIN_FILENO); xdup2(fd, STDIN_FILENO);
xdup2(null_fd, STDOUT_FILENO); xdup2(fd, STDOUT_FILENO);
xdup2(null_fd, STDERR_FILENO); xdup2(fd, STDERR_FILENO);
close(fd);
// Patch selinux with medium patch before we do anything // Patch selinux with medium patch before we do anything
load_policydb(SELINUX_POLICY); load_policydb(SELINUX_POLICY);
@@ -151,7 +146,7 @@ void start_daemon(int client) {
pthread_create(&sepol_patch, NULL, large_sepol_patch, NULL); pthread_create(&sepol_patch, NULL, large_sepol_patch, NULL);
struct sockaddr_un sun; struct sockaddr_un sun;
int fd = setup_socket(&sun); fd = setup_socket(&sun);
xbind(fd, (struct sockaddr*) &sun, sizeof(sun)); xbind(fd, (struct sockaddr*) &sun, sizeof(sun));
xlisten(fd, 10); xlisten(fd, 10);
@@ -162,7 +157,7 @@ void start_daemon(int client) {
// It should stay intact under any circumstances // It should stay intact under any circumstances
err_handler = do_nothing; err_handler = do_nothing;
LOGI("Magisk v" xstr(MAGISK_VERSION) " daemon started\n"); LOGI("Magisk v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") daemon started\n");
// Unlock all blocks for rw // Unlock all blocks for rw
unlock_blocks(); unlock_blocks();
@@ -171,16 +166,14 @@ void start_daemon(int client) {
xmount(NULL, "/", NULL, MS_REMOUNT, NULL); xmount(NULL, "/", NULL, MS_REMOUNT, NULL);
create_links(NULL, "/sbin"); create_links(NULL, "/sbin");
xchmod("/sbin", 0755); xchmod("/sbin", 0755);
mkdir("/magisk", 0755); xmkdir("/magisk", 0755);
xchmod("/magisk", 0755); xchmod("/magisk", 0755);
xmount(NULL, "/", NULL, MS_REMOUNT | MS_RDONLY, NULL); xmount(NULL, "/", NULL, MS_REMOUNT | MS_RDONLY, NULL);
// Loop forever to listen for requests // Loop forever to listen for requests
while(1) { while(1) {
int *client = xmalloc(sizeof(int)); int *client = xmalloc(sizeof(int));
*client = xaccept(fd, NULL, NULL); *client = xaccept4(fd, NULL, NULL, SOCK_CLOEXEC);
// Just in case, set to close on exec
fcntl(*client, F_SETFD, FD_CLOEXEC);
pthread_t thread; pthread_t thread;
xpthread_create(&thread, NULL, request_handler, client); xpthread_create(&thread, NULL, request_handler, client);
// Detach the thread, we will never join it // Detach the thread, we will never join it
@@ -192,7 +185,6 @@ void start_daemon(int client) {
int connect_daemon() { int connect_daemon() {
struct sockaddr_un sun; struct sockaddr_un sun;
int fd = setup_socket(&sun); int fd = setup_socket(&sun);
// LOGD("client: trying to connect socket\n");
if (connect(fd, (struct sockaddr*) &sun, sizeof(sun))) { if (connect(fd, (struct sockaddr*) &sun, sizeof(sun))) {
/* If we cannot access the daemon, we start the daemon /* If we cannot access the daemon, we start the daemon
* since there is no clear entry point when the daemon should be started * since there is no clear entry point when the daemon should be started

View File

@@ -28,13 +28,13 @@ static void *logger_thread(void *args) {
// Start logcat // Start logcat
char *const command[] = { "logcat", "-s", "Magisk", "-v", "thread", NULL }; char *const command[] = { "logcat", "-s", "Magisk", "-v", "thread", NULL };
log_pid = run_command(0, &log_fd, "/system/bin/logcat", command); log_pid = run_command(0, &log_fd, "/system/bin/logcat", command);
if (log_pid > 0)
waitpid(log_pid, NULL, 0); waitpid(log_pid, NULL, 0);
// For some reason it went here, clear buffer and restart // For some reason it went here, clear buffer and restart
system("logcat -c"); system("logcat -c");
} }
// Should never be here, but well... // Should never be here, but well...
close(log_fd);
return NULL; return NULL;
} }

13
jni/external/Android.mk vendored Normal file
View File

@@ -0,0 +1,13 @@
LOCAL_PATH:= $(call my-dir)
# libsqlite.so (stub)
include $(CLEAR_VARS)
LOCAL_MODULE:= libsqlite
LOCAL_SRC_FILES := sqlite3_stub.c
include $(BUILD_SHARED_LIBRARY)
# libselinux.so (stub)
include $(CLEAR_VARS)
LOCAL_MODULE:= libselinux
LOCAL_SRC_FILES := selinux_stub.c
include $(BUILD_SHARED_LIBRARY)

1029
jni/external/selinux/av_permissions.h vendored Normal file

File diff suppressed because it is too large Load Diff

511
jni/external/selinux/avc.h vendored Normal file
View File

@@ -0,0 +1,511 @@
/*
* Access vector cache interface for object managers.
*
* Author : Eamon Walsh <ewalsh@epoch.ncsc.mil>
*/
#ifndef _SELINUX_AVC_H_
#define _SELINUX_AVC_H_
#include <stdint.h>
#include <errno.h>
#include <stdlib.h>
#include <selinux/selinux.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* SID format and operations
*/
struct security_id {
char * ctx;
unsigned int refcnt;
};
typedef struct security_id *security_id_t;
#define SECSID_WILD (security_id_t)NULL /* unspecified SID */
/**
* avc_sid_to_context - get copy of context corresponding to SID.
* @sid: input SID
* @ctx: pointer to context reference
*
* Return a copy of the security context corresponding to the input
* @sid in the memory referenced by @ctx. The caller is expected to
* free the context with freecon(). Return %0 on success, -%1 on
* failure, with @errno set to %ENOMEM if insufficient memory was
* available to make the copy, or %EINVAL if the input SID is invalid.
*/
int avc_sid_to_context(security_id_t sid, char ** ctx);
int avc_sid_to_context_raw(security_id_t sid, char ** ctx);
/**
* avc_context_to_sid - get SID for context.
* @ctx: input security context
* @sid: pointer to SID reference
*
* Look up security context @ctx in SID table, making
* a new entry if @ctx is not found. Increment the
* reference counter for the SID. Store a pointer
* to the SID structure into the memory referenced by @sid,
* returning %0 on success or -%1 on error with @errno set.
*/
int avc_context_to_sid(const char * ctx, security_id_t * sid);
int avc_context_to_sid_raw(const char * ctx, security_id_t * sid);
/**
* sidget - increment SID reference counter.
* @sid: SID reference
*
* Increment the reference counter for @sid, indicating that
* @sid is in use by an (additional) object. Return the
* new reference count, or zero if @sid is invalid (has zero
* reference count). Note that avc_context_to_sid() also
* increments reference counts.
*/
int sidget(security_id_t sid);
/**
* sidput - decrement SID reference counter.
* @sid: SID reference
*
* Decrement the reference counter for @sid, indicating that
* a reference to @sid is no longer in use. Return the
* new reference count. When the reference count reaches
* zero, the SID is invalid, and avc_context_to_sid() must
* be called to obtain a new SID for the security context.
*/
int sidput(security_id_t sid);
/**
* avc_get_initial_sid - get SID for an initial kernel security identifier
* @name: input name of initial kernel security identifier
* @sid: pointer to a SID reference
*
* Get the context for an initial kernel security identifier specified by
* @name using security_get_initial_context() and then call
* avc_context_to_sid() to get the corresponding SID.
*/
int avc_get_initial_sid(const char *name, security_id_t * sid);
/*
* AVC entry
*/
struct avc_entry;
struct avc_entry_ref {
struct avc_entry *ae;
};
/**
* avc_entry_ref_init - initialize an AVC entry reference.
* @aeref: pointer to avc entry reference structure
*
* Use this macro to initialize an avc entry reference structure
* before first use. These structures are passed to avc_has_perm(),
* which stores cache entry references in them. They can increase
* performance on repeated queries.
*/
#define avc_entry_ref_init(aeref) ((aeref)->ae = NULL)
/*
* User-provided callbacks for memory, auditing, and locking
*/
/* These structures are passed by reference to avc_init(). Passing
* a NULL reference will cause the AVC to use a default. The default
* memory callbacks are malloc() and free(). The default logging method
* is to print on stderr. If no thread callbacks are passed, a separate
* listening thread won't be started for kernel policy change messages.
* If no locking callbacks are passed, no locking will take place.
*/
struct avc_memory_callback {
/* malloc() equivalent. */
void *(*func_malloc) (size_t size);
/* free() equivalent. */
void (*func_free) (void *ptr);
/* Note that these functions should set errno on failure.
If not, some avc routines may return -1 without errno set. */
};
struct avc_log_callback {
/* log the printf-style format and arguments. */
void
#ifdef __GNUC__
__attribute__ ((format(printf, 1, 2)))
#endif
(*func_log) (const char *fmt, ...);
/* store a string representation of auditdata (corresponding
to the given security class) into msgbuf. */
void (*func_audit) (void *auditdata, security_class_t cls,
char *msgbuf, size_t msgbufsize);
};
struct avc_thread_callback {
/* create and start a thread, returning an opaque pointer to it;
the thread should run the given function. */
void *(*func_create_thread) (void (*run) (void));
/* cancel a given thread and free its resources. */
void (*func_stop_thread) (void *thread);
};
struct avc_lock_callback {
/* create a lock and return an opaque pointer to it. */
void *(*func_alloc_lock) (void);
/* obtain a given lock, blocking if necessary. */
void (*func_get_lock) (void *lock);
/* release a given lock. */
void (*func_release_lock) (void *lock);
/* destroy a given lock (free memory, etc.) */
void (*func_free_lock) (void *lock);
};
/*
* Available options
*/
/* no-op option, useful for unused slots in an array of options */
#define AVC_OPT_UNUSED 0
/* override kernel enforcing mode (boolean value) */
#define AVC_OPT_SETENFORCE 1
/*
* AVC operations
*/
/**
* avc_init - Initialize the AVC.
* @msgprefix: prefix for log messages
* @mem_callbacks: user-supplied memory callbacks
* @log_callbacks: user-supplied logging callbacks
* @thread_callbacks: user-supplied threading callbacks
* @lock_callbacks: user-supplied locking callbacks
*
* Initialize the access vector cache. Return %0 on
* success or -%1 with @errno set on failure.
* If @msgprefix is NULL, use "uavc". If any callback
* structure references are NULL, use default methods
* for those callbacks (see the definition of the callback
* structures above).
*/
int avc_init(const char *msgprefix,
const struct avc_memory_callback *mem_callbacks,
const struct avc_log_callback *log_callbacks,
const struct avc_thread_callback *thread_callbacks,
const struct avc_lock_callback *lock_callbacks);
/**
* avc_open - Initialize the AVC.
* @opts: array of selabel_opt structures specifying AVC options or NULL.
* @nopts: number of elements in opts array or zero for no options.
*
* This function is identical to avc_init(), except the message prefix
* is set to "avc" and any callbacks desired should be specified via
* selinux_set_callback(). Available options are listed above.
*/
int avc_open(struct selinux_opt *opts, unsigned nopts);
/**
* avc_cleanup - Remove unused SIDs and AVC entries.
*
* Search the SID table for SID structures with zero
* reference counts, and remove them along with all
* AVC entries that reference them. This can be used
* to return memory to the system.
*/
void avc_cleanup(void);
/**
* avc_reset - Flush the cache and reset statistics.
*
* Remove all entries from the cache and reset all access
* statistics (as returned by avc_cache_stats()) to zero.
* The SID mapping is not affected. Return %0 on success,
* -%1 with @errno set on error.
*/
int avc_reset(void);
/**
* avc_destroy - Free all AVC structures.
*
* Destroy all AVC structures and free all allocated
* memory. User-supplied locking, memory, and audit
* callbacks will be retained, but security-event
* callbacks will not. All SID's will be invalidated.
* User must call avc_init() if further use of AVC is desired.
*/
void avc_destroy(void);
/**
* avc_has_perm_noaudit - Check permissions but perform no auditing.
* @ssid: source security identifier
* @tsid: target security identifier
* @tclass: target security class
* @requested: requested permissions, interpreted based on @tclass
* @aeref: AVC entry reference
* @avd: access vector decisions
*
* Check the AVC to determine whether the @requested permissions are granted
* for the SID pair (@ssid, @tsid), interpreting the permissions
* based on @tclass, and call the security server on a cache miss to obtain
* a new decision and add it to the cache. Update @aeref to refer to an AVC
* entry with the resulting decisions, and return a copy of the decisions
* in @avd. Return %0 if all @requested permissions are granted, -%1 with
* @errno set to %EACCES if any permissions are denied, or to another value
* upon other errors. This function is typically called by avc_has_perm(),
* but may also be called directly to separate permission checking from
* auditing, e.g. in cases where a lock must be held for the check but
* should be released for the auditing.
*/
int avc_has_perm_noaudit(security_id_t ssid,
security_id_t tsid,
security_class_t tclass,
access_vector_t requested,
struct avc_entry_ref *aeref, struct av_decision *avd);
/**
* avc_has_perm - Check permissions and perform any appropriate auditing.
* @ssid: source security identifier
* @tsid: target security identifier
* @tclass: target security class
* @requested: requested permissions, interpreted based on @tclass
* @aeref: AVC entry reference
* @auditdata: auxiliary audit data
*
* Check the AVC to determine whether the @requested permissions are granted
* for the SID pair (@ssid, @tsid), interpreting the permissions
* based on @tclass, and call the security server on a cache miss to obtain
* a new decision and add it to the cache. Update @aeref to refer to an AVC
* entry with the resulting decisions. Audit the granting or denial of
* permissions in accordance with the policy. Return %0 if all @requested
* permissions are granted, -%1 with @errno set to %EACCES if any permissions
* are denied or to another value upon other errors.
*/
int avc_has_perm(security_id_t ssid, security_id_t tsid,
security_class_t tclass, access_vector_t requested,
struct avc_entry_ref *aeref, void *auditdata);
/**
* avc_audit - Audit the granting or denial of permissions.
* @ssid: source security identifier
* @tsid: target security identifier
* @tclass: target security class
* @requested: requested permissions
* @avd: access vector decisions
* @result: result from avc_has_perm_noaudit
* @auditdata: auxiliary audit data
*
* Audit the granting or denial of permissions in accordance
* with the policy. This function is typically called by
* avc_has_perm() after a permission check, but can also be
* called directly by callers who use avc_has_perm_noaudit()
* in order to separate the permission check from the auditing.
* For example, this separation is useful when the permission check must
* be performed under a lock, to allow the lock to be released
* before calling the auditing code.
*/
void avc_audit(security_id_t ssid, security_id_t tsid,
security_class_t tclass, access_vector_t requested,
struct av_decision *avd, int result, void *auditdata);
/**
* avc_compute_create - Compute SID for labeling a new object.
* @ssid: source security identifier
* @tsid: target security identifier
* @tclass: target security class
* @newsid: pointer to SID reference
*
* Call the security server to obtain a context for labeling a
* new object. Look up the context in the SID table, making
* a new entry if not found. Increment the reference counter
* for the SID. Store a pointer to the SID structure into the
* memory referenced by @newsid, returning %0 on success or -%1 on
* error with @errno set.
*/
int avc_compute_create(security_id_t ssid,
security_id_t tsid,
security_class_t tclass, security_id_t * newsid);
/**
* avc_compute_member - Compute SID for polyinstantation.
* @ssid: source security identifier
* @tsid: target security identifier
* @tclass: target security class
* @newsid: pointer to SID reference
*
* Call the security server to obtain a context for labeling an
* object instance. Look up the context in the SID table, making
* a new entry if not found. Increment the reference counter
* for the SID. Store a pointer to the SID structure into the
* memory referenced by @newsid, returning %0 on success or -%1 on
* error with @errno set.
*/
int avc_compute_member(security_id_t ssid,
security_id_t tsid,
security_class_t tclass, security_id_t * newsid);
/*
* security event callback facility
*/
/* security events */
#define AVC_CALLBACK_GRANT 1
#define AVC_CALLBACK_TRY_REVOKE 2
#define AVC_CALLBACK_REVOKE 4
#define AVC_CALLBACK_RESET 8
#define AVC_CALLBACK_AUDITALLOW_ENABLE 16
#define AVC_CALLBACK_AUDITALLOW_DISABLE 32
#define AVC_CALLBACK_AUDITDENY_ENABLE 64
#define AVC_CALLBACK_AUDITDENY_DISABLE 128
/**
* avc_add_callback - Register a callback for security events.
* @callback: callback function
* @events: bitwise OR of desired security events
* @ssid: source security identifier or %SECSID_WILD
* @tsid: target security identifier or %SECSID_WILD
* @tclass: target security class
* @perms: permissions
*
* Register a callback function for events in the set @events
* related to the SID pair (@ssid, @tsid) and
* and the permissions @perms, interpreting
* @perms based on @tclass. Returns %0 on success or
* -%1 if insufficient memory exists to add the callback.
*/
int avc_add_callback(int (*callback)
(uint32_t event, security_id_t ssid,
security_id_t tsid, security_class_t tclass,
access_vector_t perms,
access_vector_t * out_retained),
uint32_t events, security_id_t ssid,
security_id_t tsid, security_class_t tclass,
access_vector_t perms);
/*
* AVC statistics
*/
/* If set, cache statistics are tracked. This may
* become a compile-time option in the future.
*/
#define AVC_CACHE_STATS 1
struct avc_cache_stats {
unsigned entry_lookups;
unsigned entry_hits;
unsigned entry_misses;
unsigned entry_discards;
unsigned cav_lookups;
unsigned cav_hits;
unsigned cav_probes;
unsigned cav_misses;
};
/**
* avc_cache_stats - get cache access statistics.
* @stats: reference to statistics structure
*
* Fill the supplied structure with information about AVC
* activity since the last call to avc_init() or
* avc_reset(). See the structure definition for
* details.
*/
void avc_cache_stats(struct avc_cache_stats *stats);
/**
* avc_av_stats - log av table statistics.
*
* Log a message with information about the size and
* distribution of the access vector table. The audit
* callback is used to print the message.
*/
void avc_av_stats(void);
/**
* avc_sid_stats - log SID table statistics.
*
* Log a message with information about the size and
* distribution of the SID table. The audit callback
* is used to print the message.
*/
void avc_sid_stats(void);
/**
* avc_netlink_open - Create a netlink socket and connect to the kernel.
*/
int avc_netlink_open(int blocking);
/**
* avc_netlink_loop - Wait for netlink messages from the kernel
*/
void avc_netlink_loop(void);
/**
* avc_netlink_close - Close the netlink socket
*/
void avc_netlink_close(void);
/**
* avc_netlink_acquire_fd - Acquire netlink socket fd.
*
* Allows the application to manage messages from the netlink socket in
* its own main loop.
*/
int avc_netlink_acquire_fd(void);
/**
* avc_netlink_release_fd - Release netlink socket fd.
*
* Returns ownership of the netlink socket to the library.
*/
void avc_netlink_release_fd(void);
/**
* avc_netlink_check_nb - Check netlink socket for new messages.
*
* Called by the application when using avc_netlink_acquire_fd() to
* process kernel netlink events.
*/
int avc_netlink_check_nb(void);
/**
* selinux_status_open - Open and map SELinux kernel status page
*
*/
int selinux_status_open(int fallback);
/**
* selinux_status_close - Unmap and close SELinux kernel status page
*
*/
void selinux_status_close(void);
/**
* selinux_status_updated - Inform us whether the kernel status has been updated
*
*/
int selinux_status_updated(void);
/**
* selinux_status_getenforce - Get the enforce flag value
*
*/
int selinux_status_getenforce(void);
/**
* selinux_status_policyload - Get the number of policy reloaded
*
*/
int selinux_status_policyload(void);
/**
* selinux_status_deny_unknown - Get the behavior for undefined classes/permissions
*
*/
int selinux_status_deny_unknown(void);
#ifdef __cplusplus
}
#endif
#endif /* _SELINUX_AVC_H_ */

50
jni/external/selinux/context.h vendored Normal file
View File

@@ -0,0 +1,50 @@
#ifndef _SELINUX_CONTEXT_H_
#define _SELINUX_CONTEXT_H_
#ifdef __cplusplus
extern "C" {
#endif
/*
* Functions to deal with security contexts in user space.
*/
typedef struct {
void *ptr;
} context_s_t;
typedef context_s_t *context_t;
/* Return a new context initialized to a context string */
extern context_t context_new(const char *);
/*
* Return a pointer to the string value of the context_t
* Valid until the next call to context_str or context_free
* for the same context_t*
*/
extern char *context_str(context_t);
/* Free the storage used by a context */
extern void context_free(context_t);
/* Get a pointer to the string value of a context component */
extern const char *context_type_get(context_t);
extern const char *context_range_get(context_t);
extern const char *context_role_get(context_t);
extern const char *context_user_get(context_t);
/* Set a context component. Returns nonzero if unsuccessful */
extern int context_type_set(context_t, const char *);
extern int context_range_set(context_t, const char *);
extern int context_role_set(context_t, const char *);
extern int context_user_set(context_t, const char *);
#ifdef __cplusplus
}
#endif
#endif

118
jni/external/selinux/flask.h vendored Normal file
View File

@@ -0,0 +1,118 @@
/* This file is automatically generated. Do not edit. */
#ifndef _SELINUX_FLASK_H_
#define _SELINUX_FLASK_H_
#warning "Please remove any #include's of this header in your source code."
#warning "Instead, use string_to_security_class() to map the class name to a value."
/*
* Security object class definitions
*/
#define SECCLASS_SECURITY 1
#define SECCLASS_PROCESS 2
#define SECCLASS_SYSTEM 3
#define SECCLASS_CAPABILITY 4
#define SECCLASS_FILESYSTEM 5
#define SECCLASS_FILE 6
#define SECCLASS_DIR 7
#define SECCLASS_FD 8
#define SECCLASS_LNK_FILE 9
#define SECCLASS_CHR_FILE 10
#define SECCLASS_BLK_FILE 11
#define SECCLASS_SOCK_FILE 12
#define SECCLASS_FIFO_FILE 13
#define SECCLASS_SOCKET 14
#define SECCLASS_TCP_SOCKET 15
#define SECCLASS_UDP_SOCKET 16
#define SECCLASS_RAWIP_SOCKET 17
#define SECCLASS_NODE 18
#define SECCLASS_NETIF 19
#define SECCLASS_NETLINK_SOCKET 20
#define SECCLASS_PACKET_SOCKET 21
#define SECCLASS_KEY_SOCKET 22
#define SECCLASS_UNIX_STREAM_SOCKET 23
#define SECCLASS_UNIX_DGRAM_SOCKET 24
#define SECCLASS_SEM 25
#define SECCLASS_MSG 26
#define SECCLASS_MSGQ 27
#define SECCLASS_SHM 28
#define SECCLASS_IPC 29
#define SECCLASS_PASSWD 30
#define SECCLASS_X_DRAWABLE 31
#define SECCLASS_X_SCREEN 32
#define SECCLASS_X_GC 33
#define SECCLASS_X_FONT 34
#define SECCLASS_X_COLORMAP 35
#define SECCLASS_X_PROPERTY 36
#define SECCLASS_X_SELECTION 37
#define SECCLASS_X_CURSOR 38
#define SECCLASS_X_CLIENT 39
#define SECCLASS_X_DEVICE 40
#define SECCLASS_X_SERVER 41
#define SECCLASS_X_EXTENSION 42
#define SECCLASS_NETLINK_ROUTE_SOCKET 43
#define SECCLASS_NETLINK_FIREWALL_SOCKET 44
#define SECCLASS_NETLINK_TCPDIAG_SOCKET 45
#define SECCLASS_NETLINK_NFLOG_SOCKET 46
#define SECCLASS_NETLINK_XFRM_SOCKET 47
#define SECCLASS_NETLINK_SELINUX_SOCKET 48
#define SECCLASS_NETLINK_AUDIT_SOCKET 49
#define SECCLASS_NETLINK_IP6FW_SOCKET 50
#define SECCLASS_NETLINK_DNRT_SOCKET 51
#define SECCLASS_DBUS 52
#define SECCLASS_NSCD 53
#define SECCLASS_ASSOCIATION 54
#define SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET 55
#define SECCLASS_APPLETALK_SOCKET 56
#define SECCLASS_PACKET 57
#define SECCLASS_KEY 58
#define SECCLASS_CONTEXT 59
#define SECCLASS_DCCP_SOCKET 60
#define SECCLASS_MEMPROTECT 61
#define SECCLASS_DB_DATABASE 62
#define SECCLASS_DB_TABLE 63
#define SECCLASS_DB_PROCEDURE 64
#define SECCLASS_DB_COLUMN 65
#define SECCLASS_DB_TUPLE 66
#define SECCLASS_DB_BLOB 67
#define SECCLASS_PEER 68
#define SECCLASS_CAPABILITY2 69
#define SECCLASS_X_RESOURCE 70
#define SECCLASS_X_EVENT 71
#define SECCLASS_X_SYNTHETIC_EVENT 72
#define SECCLASS_X_APPLICATION_DATA 73
/*
* Security identifier indices for initial entities
*/
#define SECINITSID_KERNEL 1
#define SECINITSID_SECURITY 2
#define SECINITSID_UNLABELED 3
#define SECINITSID_FS 4
#define SECINITSID_FILE 5
#define SECINITSID_FILE_LABELS 6
#define SECINITSID_INIT 7
#define SECINITSID_ANY_SOCKET 8
#define SECINITSID_PORT 9
#define SECINITSID_NETIF 10
#define SECINITSID_NETMSG 11
#define SECINITSID_NODE 12
#define SECINITSID_IGMP_PACKET 13
#define SECINITSID_ICMP_SOCKET 14
#define SECINITSID_TCP_SOCKET 15
#define SECINITSID_SYSCTL_MODPROBE 16
#define SECINITSID_SYSCTL 17
#define SECINITSID_SYSCTL_FS 18
#define SECINITSID_SYSCTL_KERNEL 19
#define SECINITSID_SYSCTL_NET 20
#define SECINITSID_SYSCTL_NET_UNIX 21
#define SECINITSID_SYSCTL_VM 22
#define SECINITSID_SYSCTL_DEV 23
#define SECINITSID_KMOD 24
#define SECINITSID_POLICY 25
#define SECINITSID_SCMP_PACKET 26
#define SECINITSID_DEVNULL 27
#define SECINITSID_NUM 27
#endif

82
jni/external/selinux/get_context_list.h vendored Normal file
View File

@@ -0,0 +1,82 @@
#ifndef _SELINUX_GET_SID_LIST_H_
#define _SELINUX_GET_SID_LIST_H_
#include <selinux/selinux.h>
#ifdef __cplusplus
extern "C" {
#endif
#define SELINUX_DEFAULTUSER "user_u"
/* Get an ordered list of authorized security contexts for a user session
for 'user' spawned by 'fromcon' and set *conary to refer to the
NULL-terminated array of contexts. Every entry in the list will
be authorized by the policy, but the ordering is subject to user
customizable preferences. Returns number of entries in *conary.
If 'fromcon' is NULL, defaults to current context.
Caller must free via freeconary. */
extern int get_ordered_context_list(const char *user,
char * fromcon,
char *** list);
/* As above, but use the provided MLS level rather than the
default level for the user. */
int get_ordered_context_list_with_level(const char *user,
const char *level,
char * fromcon,
char *** list);
/* Get the default security context for a user session for 'user'
spawned by 'fromcon' and set *newcon to refer to it. The context
will be one of those authorized by the policy, but the selection
of a default is subject to user customizable preferences.
If 'fromcon' is NULL, defaults to current context.
Returns 0 on success or -1 otherwise.
Caller must free via freecon. */
extern int get_default_context(const char *user,
char * fromcon,
char ** newcon);
/* As above, but use the provided MLS level rather than the
default level for the user. */
int get_default_context_with_level(const char *user,
const char *level,
char * fromcon,
char ** newcon);
/* Same as get_default_context, but only return a context
that has the specified role. If no reachable context exists
for the user with that role, then return -1. */
int get_default_context_with_role(const char *user,
const char *role,
char * fromcon,
char ** newcon);
/* Same as get_default_context, but only return a context
that has the specified role and level. If no reachable context exists
for the user with that role, then return -1. */
int get_default_context_with_rolelevel(const char *user,
const char *role,
const char *level,
char * fromcon,
char ** newcon);
/* Given a list of authorized security contexts for the user,
query the user to select one and set *newcon to refer to it.
Caller must free via freecon.
Returns 0 on sucess or -1 otherwise. */
extern int query_user_context(char ** list,
char ** newcon);
/* Allow the user to manually enter a context as a fallback
if a list of authorized contexts could not be obtained.
Caller must free via freecon.
Returns 0 on success or -1 otherwise. */
extern int manual_user_enter_context(const char *user,
char ** newcon);
#ifdef __cplusplus
}
#endif
#endif

23
jni/external/selinux/get_default_type.h vendored Normal file
View File

@@ -0,0 +1,23 @@
/* get_default_type.h - contains header information and function prototypes
* for functions to get the default type for a role
*/
#ifndef _SELINUX_GET_DEFAULT_TYPE_H_
#define _SELINUX_GET_DEFAULT_TYPE_H_
#ifdef __cplusplus
extern "C" {
#endif
/* Return path to default type file. */
const char *selinux_default_type_path(void);
/* Get the default type (domain) for 'role' and set 'type' to refer to it.
Caller must free via free().
Return 0 on success or -1 otherwise. */
int get_default_type(const char *role, char **type);
#ifdef __cplusplus
}
#endif
#endif /* ifndef _GET_DEFAULT_TYPE_H_ */

190
jni/external/selinux/label.h vendored Normal file
View File

@@ -0,0 +1,190 @@
/*
* Labeling interface for userspace object managers and others.
*
* Author : Eamon Walsh <ewalsh@tycho.nsa.gov>
*/
#ifndef _SELABEL_H_
#define _SELABEL_H_
#include <stdbool.h>
#include <sys/types.h>
#include <selinux/selinux.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Opaque type used for all label handles.
*/
struct selabel_handle;
/*
* Available backends.
*/
/* file contexts */
#define SELABEL_CTX_FILE 0
/* media contexts */
#define SELABEL_CTX_MEDIA 1
/* x contexts */
#define SELABEL_CTX_X 2
/* db objects */
#define SELABEL_CTX_DB 3
/* Android property service contexts */
#define SELABEL_CTX_ANDROID_PROP 4
/* Android service contexts */
#define SELABEL_CTX_ANDROID_SERVICE 5
/*
* Available options
*/
/* no-op option, useful for unused slots in an array of options */
#define SELABEL_OPT_UNUSED 0
/* validate contexts before returning them (boolean value) */
#define SELABEL_OPT_VALIDATE 1
/* don't use local customizations to backend data (boolean value) */
#define SELABEL_OPT_BASEONLY 2
/* specify an alternate path to use when loading backend data */
#define SELABEL_OPT_PATH 3
/* select a subset of the search space as an optimization (file backend) */
#define SELABEL_OPT_SUBSET 4
/* require a hash calculation on spec files */
#define SELABEL_OPT_DIGEST 5
/* total number of options */
#define SELABEL_NOPT 6
/*
* Label operations
*/
/**
* selabel_open - Create a labeling handle.
* @backend: one of the constants specifying a supported labeling backend.
* @opts: array of selabel_opt structures specifying label options or NULL.
* @nopts: number of elements in opts array or zero for no options.
*
* Open a labeling backend for use. The available backend identifiers are
* listed above. Options may be provided via the opts parameter; available
* options are listed above. Not all options may be supported by every
* backend. Return value is the created handle on success or NULL with
* @errno set on failure.
*/
struct selabel_handle *selabel_open(unsigned int backend,
const struct selinux_opt *opts,
unsigned nopts);
/**
* selabel_close - Close a labeling handle.
* @handle: specifies handle to close
*
* Destroy the specified handle, closing files, freeing allocated memory,
* etc. The handle may not be further used after it has been closed.
*/
void selabel_close(struct selabel_handle *handle);
/**
* selabel_lookup - Perform labeling lookup operation.
* @handle: specifies backend instance to query
* @con: returns the appropriate context with which to label the object
* @key: string input to lookup operation
* @type: numeric input to the lookup operation
*
* Perform a labeling lookup operation. Return %0 on success, -%1 with
* @errno set on failure. The key and type arguments are the inputs to the
* lookup operation; appropriate values are dictated by the backend in use.
* The result is returned in the memory pointed to by @con and must be freed
* by the user with freecon().
*/
int selabel_lookup(struct selabel_handle *handle, char **con,
const char *key, int type);
int selabel_lookup_raw(struct selabel_handle *handle, char **con,
const char *key, int type);
bool selabel_partial_match(struct selabel_handle *handle, const char *key);
int selabel_lookup_best_match(struct selabel_handle *rec, char **con,
const char *key, const char **aliases, int type);
int selabel_lookup_best_match_raw(struct selabel_handle *rec, char **con,
const char *key, const char **aliases, int type);
/**
* selabel_digest - Retrieve the SHA1 digest and the list of specfiles used to
* generate the digest. The SELABEL_OPT_DIGEST option must
* be set in selabel_open() to initiate the digest generation.
* @handle: specifies backend instance to query
* @digest: returns a pointer to the SHA1 digest.
* @digest_len: returns length of digest in bytes.
* @specfiles: a list of specfiles used in the SHA1 digest generation.
* The list is NULL terminated and will hold @num_specfiles entries.
* @num_specfiles: number of specfiles in the list.
*
* Return %0 on success, -%1 with @errno set on failure.
*/
int selabel_digest(struct selabel_handle *rec,
unsigned char **digest, size_t *digest_len,
char ***specfiles, size_t *num_specfiles);
enum selabel_cmp_result {
SELABEL_SUBSET,
SELABEL_EQUAL,
SELABEL_SUPERSET,
SELABEL_INCOMPARABLE
};
/**
* selabel_cmp - Compare two label configurations.
* @h1: handle for the first label configuration
* @h2: handle for the first label configuration
*
* Compare two label configurations.
* Return %SELABEL_SUBSET if @h1 is a subset of @h2, %SELABEL_EQUAL
* if @h1 is identical to @h2, %SELABEL_SUPERSET if @h1 is a superset
* of @h2, and %SELABEL_INCOMPARABLE if @h1 and @h2 are incomparable.
*/
enum selabel_cmp_result selabel_cmp(struct selabel_handle *h1,
struct selabel_handle *h2);
/**
* selabel_stats - log labeling operation statistics.
* @handle: specifies backend instance to query
*
* Log a message with information about the number of queries performed,
* number of unused matching entries, or other operational statistics.
* Message is backend-specific, some backends may not output a message.
*/
void selabel_stats(struct selabel_handle *handle);
/*
* Type codes used by specific backends
*/
/* X backend */
#define SELABEL_X_PROP 1
#define SELABEL_X_EXT 2
#define SELABEL_X_CLIENT 3
#define SELABEL_X_EVENT 4
#define SELABEL_X_SELN 5
#define SELABEL_X_POLYPROP 6
#define SELABEL_X_POLYSELN 7
/* DB backend */
#define SELABEL_DB_DATABASE 1
#define SELABEL_DB_SCHEMA 2
#define SELABEL_DB_TABLE 3
#define SELABEL_DB_COLUMN 4
#define SELABEL_DB_SEQUENCE 5
#define SELABEL_DB_VIEW 6
#define SELABEL_DB_PROCEDURE 7
#define SELABEL_DB_BLOB 8
#define SELABEL_DB_TUPLE 9
#define SELABEL_DB_LANGUAGE 10
#define SELABEL_DB_EXCEPTION 11
#define SELABEL_DB_DATATYPE 12
#ifdef __cplusplus
}
#endif
#endif /* _SELABEL_H_ */

187
jni/external/selinux/restorecon.h vendored Normal file
View File

@@ -0,0 +1,187 @@
#ifndef _RESTORECON_H_
#define _RESTORECON_H_
#include <sys/types.h>
#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* selinux_restorecon - Relabel files.
* @pathname: specifies file/directory to relabel.
* @restorecon_flags: specifies the actions to be performed when relabeling.
*
* selinux_restorecon(3) will automatically call
* selinux_restorecon_default_handle(3) and selinux_restorecon_set_sehandle(3)
* first time through to set the selabel_open(3) parameters to use the
* currently loaded policy file_contexts and request their computed digest.
*
* Should other selabel_open(3) parameters be required see
* selinux_restorecon_set_sehandle(3).
*/
extern int selinux_restorecon(const char *pathname,
unsigned int restorecon_flags);
/*
* restorecon_flags options
*/
/*
* Force the checking of labels even if the stored SHA1
* digest matches the specfiles SHA1 digest.
*/
#define SELINUX_RESTORECON_IGNORE_DIGEST 0x0001
/*
* Do not change file labels.
*/
#define SELINUX_RESTORECON_NOCHANGE 0x0002
/*
* If set set change file label to that in spec file.
* If not only change type component to that in spec file.
*/
#define SELINUX_RESTORECON_SET_SPECFILE_CTX 0x0004
/*
* Recursively descend directories.
*/
#define SELINUX_RESTORECON_RECURSE 0x0008
/*
* Log changes to selinux log. Note that if VERBOSE and
* PROGRESS are set, then PROGRESS will take precedence.
*/
#define SELINUX_RESTORECON_VERBOSE 0x0010
/*
* If SELINUX_RESTORECON_PROGRESS is true and
* SELINUX_RESTORECON_MASS_RELABEL is true, then output approx % complete,
* else output the number of files in 1k blocks processed to stdout.
*/
#define SELINUX_RESTORECON_PROGRESS 0x0020
/*
* Convert passed-in pathname to canonical pathname.
*/
#define SELINUX_RESTORECON_REALPATH 0x0040
/*
* Prevent descending into directories that have a different
* device number than the pathname from which the descent began.
*/
#define SELINUX_RESTORECON_XDEV 0x0080
/*
* Attempt to add an association between an inode and a specification.
* If there is already an association for the inode and it conflicts
* with the specification, then use the last matching specification.
*/
#define SELINUX_RESTORECON_ADD_ASSOC 0x0100
/*
* Abort on errors during the file tree walk.
*/
#define SELINUX_RESTORECON_ABORT_ON_ERROR 0x0200
/*
* Log any label changes to syslog.
*/
#define SELINUX_RESTORECON_SYSLOG_CHANGES 0x0400
/*
* Log what spec matched each file.
*/
#define SELINUX_RESTORECON_LOG_MATCHES 0x0800
/*
* Ignore files that do not exist.
*/
#define SELINUX_RESTORECON_IGNORE_NOENTRY 0x1000
/*
* Do not read /proc/mounts to obtain a list of non-seclabel
* mounts to be excluded from relabeling checks.
*/
#define SELINUX_RESTORECON_IGNORE_MOUNTS 0x2000
/*
* Set if there is a mass relabel required.
* See SELINUX_RESTORECON_PROGRESS flag for details.
*/
#define SELINUX_RESTORECON_MASS_RELABEL 0x4000
/**
* selinux_restorecon_set_sehandle - Set the global fc handle.
* @hndl: specifies handle to set as the global fc handle.
*
* Called by a process that has already called selabel_open(3) with it's
* required parameters, or if selinux_restorecon_default_handle(3) has been
* called to set the default selabel_open(3) parameters.
*/
// extern void selinux_restorecon_set_sehandle(struct selabel_handle *hndl);
/**
* selinux_restorecon_default_handle - Sets default selabel_open(3) parameters
* to use the currently loaded policy and
* file_contexts, also requests the digest.
*
* Return value is the created handle on success or NULL with @errno set on
* failure.
*/
extern struct selabel_handle *selinux_restorecon_default_handle(void);
/**
* selinux_restorecon_set_exclude_list - Add a list of directories that are
* to be excluded from relabeling.
* @exclude_list: containing a NULL terminated list of one or more
* directories not to be relabeled.
*/
extern void selinux_restorecon_set_exclude_list(const char **exclude_list);
/**
* selinux_restorecon_set_alt_rootpath - Use alternate rootpath.
* @alt_rootpath: containing the alternate rootpath to be used.
*
* Return %0 on success, -%1 with @errno set on failure.
*/
extern int selinux_restorecon_set_alt_rootpath(const char *alt_rootpath);
/**
* selinux_restorecon_xattr - Read/remove RESTORECON_LAST xattr entries.
* @pathname: specifies directory path to check.
* @xattr_flags: specifies the actions to be performed.
* @xattr_list: a linked list of struct dir_xattr structures containing
* the directory, digest and result of the action on the
* RESTORECON_LAST entry.
*
* selinux_restorecon_xattr(3) will automatically call
* selinux_restorecon_default_handle(3) and selinux_restorecon_set_sehandle(3)
* first time through to set the selabel_open(3) parameters to use the
* currently loaded policy file_contexts and request their computed digest.
*
* Should other selabel_open(3) parameters be required see
* selinux_restorecon_set_sehandle(3), however note that a file_contexts
* computed digest is required for selinux_restorecon_xattr().
*/
enum digest_result {
MATCH = 0,
NOMATCH,
DELETED_MATCH,
DELETED_NOMATCH,
ERROR
};
struct dir_xattr {
char *directory;
char *digest; /* A hex encoded string that can be printed. */
enum digest_result result;
struct dir_xattr *next;
};
extern int selinux_restorecon_xattr(const char *pathname,
unsigned int xattr_flags,
struct dir_xattr ***xattr_list);
/*
* xattr_flags options
*/
/* Recursively descend directories. */
#define SELINUX_RESTORECON_XATTR_RECURSE 0x0001
/* Delete non-matching digests from each directory in pathname. */
#define SELINUX_RESTORECON_XATTR_DELETE_NONMATCH_DIGESTS 0x0002
/* Delete all digests found in pathname. */
#define SELINUX_RESTORECON_XATTR_DELETE_ALL_DIGESTS 0x0004
/* Do not read /proc/mounts. */
#define SELINUX_RESTORECON_XATTR_IGNORE_MOUNTS 0x0008
#ifdef __cplusplus
}
#endif
#endif

673
jni/external/selinux/selinux.h vendored Normal file
View File

@@ -0,0 +1,673 @@
#ifndef _SELINUX_H_
#define _SELINUX_H_
#include <sys/types.h>
#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Return 1 if we are running on a SELinux kernel, or 0 if not or -1 if we get an error. */
extern int is_selinux_enabled(void);
/* Return 1 if we are running on a SELinux MLS kernel, or 0 otherwise. */
extern int is_selinux_mls_enabled(void);
/* No longer used; here for compatibility with legacy callers. */
typedef char *security_context_t;
/* Free the memory allocated for a context by any of the below get* calls. */
extern void freecon(char * con);
/* Free the memory allocated for a context array by security_compute_user. */
extern void freeconary(char ** con);
/* Wrappers for the /proc/pid/attr API. */
/* Get current context, and set *con to refer to it.
Caller must free via freecon. */
extern int getcon(char ** con);
extern int getcon_raw(char ** con);
/* Set the current security context to con.
Note that use of this function requires that the entire application
be trusted to maintain any desired separation between the old and new
security contexts, unlike exec-based transitions performed via setexeccon.
When possible, decompose your application and use setexeccon()+execve()
instead. Note that the application may lose access to its open descriptors
as a result of a setcon() unless policy allows it to use descriptors opened
by the old context. */
extern int setcon(const char * con);
extern int setcon_raw(const char * con);
/* Get context of process identified by pid, and
set *con to refer to it. Caller must free via freecon. */
extern int getpidcon(pid_t pid, char ** con);
extern int getpidcon_raw(pid_t pid, char ** con);
/* Get previous context (prior to last exec), and set *con to refer to it.
Caller must free via freecon. */
extern int getprevcon(char ** con);
extern int getprevcon_raw(char ** con);
/* Get exec context, and set *con to refer to it.
Sets *con to NULL if no exec context has been set, i.e. using default.
If non-NULL, caller must free via freecon. */
extern int getexeccon(char ** con);
extern int getexeccon_raw(char ** con);
/* Set exec security context for the next execve.
Call with NULL if you want to reset to the default. */
extern int setexeccon(const char * con);
extern int setexeccon_raw(const char * con);
/* Get fscreate context, and set *con to refer to it.
Sets *con to NULL if no fs create context has been set, i.e. using default.
If non-NULL, caller must free via freecon. */
extern int getfscreatecon(char ** con);
extern int getfscreatecon_raw(char ** con);
/* Set the fscreate security context for subsequent file creations.
Call with NULL if you want to reset to the default. */
extern int setfscreatecon(const char * context);
extern int setfscreatecon_raw(const char * context);
/* Get keycreate context, and set *con to refer to it.
Sets *con to NULL if no key create context has been set, i.e. using default.
If non-NULL, caller must free via freecon. */
extern int getkeycreatecon(char ** con);
extern int getkeycreatecon_raw(char ** con);
/* Set the keycreate security context for subsequent key creations.
Call with NULL if you want to reset to the default. */
extern int setkeycreatecon(const char * context);
extern int setkeycreatecon_raw(const char * context);
/* Get sockcreate context, and set *con to refer to it.
Sets *con to NULL if no socket create context has been set, i.e. using default.
If non-NULL, caller must free via freecon. */
extern int getsockcreatecon(char ** con);
extern int getsockcreatecon_raw(char ** con);
/* Set the sockcreate security context for subsequent socket creations.
Call with NULL if you want to reset to the default. */
extern int setsockcreatecon(const char * context);
extern int setsockcreatecon_raw(const char * context);
/* Wrappers for the xattr API. */
/* Get file context, and set *con to refer to it.
Caller must free via freecon. */
extern int getfilecon(const char *path, char ** con);
extern int getfilecon_raw(const char *path, char ** con);
extern int lgetfilecon(const char *path, char ** con);
extern int lgetfilecon_raw(const char *path, char ** con);
extern int fgetfilecon(int fd, char ** con);
extern int fgetfilecon_raw(int fd, char ** con);
/* Set file context */
extern int setfilecon(const char *path, const char * con);
extern int setfilecon_raw(const char *path, const char * con);
extern int lsetfilecon(const char *path, const char * con);
extern int lsetfilecon_raw(const char *path, const char * con);
extern int fsetfilecon(int fd, const char * con);
extern int fsetfilecon_raw(int fd, const char * con);
/* Wrappers for the socket API */
/* Get context of peer socket, and set *con to refer to it.
Caller must free via freecon. */
extern int getpeercon(int fd, char ** con);
extern int getpeercon_raw(int fd, char ** con);
/* Wrappers for the selinuxfs (policy) API. */
typedef unsigned int access_vector_t;
typedef unsigned short security_class_t;
struct av_decision {
access_vector_t allowed;
access_vector_t decided;
access_vector_t auditallow;
access_vector_t auditdeny;
unsigned int seqno;
unsigned int flags;
};
/* Definitions of av_decision.flags */
#define SELINUX_AVD_FLAGS_PERMISSIVE 0x0001
/* Structure for passing options, used by AVC and label subsystems */
struct selinux_opt {
int type;
const char *value;
};
/* Callback facilities */
union selinux_callback {
/* log the printf-style format and arguments,
with the type code indicating the type of message */
int
#ifdef __GNUC__
__attribute__ ((format(printf, 2, 3)))
#endif
(*func_log) (int type, const char *fmt, ...);
/* store a string representation of auditdata (corresponding
to the given security class) into msgbuf. */
int (*func_audit) (void *auditdata, security_class_t cls,
char *msgbuf, size_t msgbufsize);
/* validate the supplied context, modifying if necessary */
int (*func_validate) (char **ctx);
/* netlink callback for setenforce message */
int (*func_setenforce) (int enforcing);
/* netlink callback for policyload message */
int (*func_policyload) (int seqno);
};
#define SELINUX_CB_LOG 0
#define SELINUX_CB_AUDIT 1
#define SELINUX_CB_VALIDATE 2
#define SELINUX_CB_SETENFORCE 3
#define SELINUX_CB_POLICYLOAD 4
extern union selinux_callback selinux_get_callback(int type);
extern void selinux_set_callback(int type, union selinux_callback cb);
/* Logging type codes, passed to the logging callback */
#define SELINUX_ERROR 0
#define SELINUX_WARNING 1
#define SELINUX_INFO 2
#define SELINUX_AVC 3
#define SELINUX_TRANS_DIR "/var/run/setrans"
/* Compute an access decision. */
extern int security_compute_av(const char * scon,
const char * tcon,
security_class_t tclass,
access_vector_t requested,
struct av_decision *avd);
extern int security_compute_av_raw(const char * scon,
const char * tcon,
security_class_t tclass,
access_vector_t requested,
struct av_decision *avd);
extern int security_compute_av_flags(const char * scon,
const char * tcon,
security_class_t tclass,
access_vector_t requested,
struct av_decision *avd);
extern int security_compute_av_flags_raw(const char * scon,
const char * tcon,
security_class_t tclass,
access_vector_t requested,
struct av_decision *avd);
/* Compute a labeling decision and set *newcon to refer to it.
Caller must free via freecon. */
extern int security_compute_create(const char * scon,
const char * tcon,
security_class_t tclass,
char ** newcon);
extern int security_compute_create_raw(const char * scon,
const char * tcon,
security_class_t tclass,
char ** newcon);
extern int security_compute_create_name(const char * scon,
const char * tcon,
security_class_t tclass,
const char *objname,
char ** newcon);
extern int security_compute_create_name_raw(const char * scon,
const char * tcon,
security_class_t tclass,
const char *objname,
char ** newcon);
/* Compute a relabeling decision and set *newcon to refer to it.
Caller must free via freecon. */
extern int security_compute_relabel(const char * scon,
const char * tcon,
security_class_t tclass,
char ** newcon);
extern int security_compute_relabel_raw(const char * scon,
const char * tcon,
security_class_t tclass,
char ** newcon);
/* Compute a polyinstantiation member decision and set *newcon to refer to it.
Caller must free via freecon. */
extern int security_compute_member(const char * scon,
const char * tcon,
security_class_t tclass,
char ** newcon);
extern int security_compute_member_raw(const char * scon,
const char * tcon,
security_class_t tclass,
char ** newcon);
/* Compute the set of reachable user contexts and set *con to refer to
the NULL-terminated array of contexts. Caller must free via freeconary. */
extern int security_compute_user(const char * scon,
const char *username,
char *** con);
extern int security_compute_user_raw(const char * scon,
const char *username,
char *** con);
/* Load a policy configuration. */
extern int security_load_policy(void *data, size_t len);
/* Get the context of an initial kernel security identifier by name.
Caller must free via freecon */
extern int security_get_initial_context(const char *name,
char ** con);
extern int security_get_initial_context_raw(const char *name,
char ** con);
/*
* Make a policy image and load it.
* This function provides a higher level interface for loading policy
* than security_load_policy, internally determining the right policy
* version, locating and opening the policy file, mapping it into memory,
* manipulating it as needed for current boolean settings and/or local
* definitions, and then calling security_load_policy to load it.
*
* 'preservebools' is a boolean flag indicating whether current
* policy boolean values should be preserved into the new policy (if 1)
* or reset to the saved policy settings (if 0). The former case is the
* default for policy reloads, while the latter case is an option for policy
* reloads but is primarily for the initial policy load.
*/
extern int selinux_mkload_policy(int preservebools);
/*
* Perform the initial policy load.
* This function determines the desired enforcing mode, sets the
* the *enforce argument accordingly for the caller to use, sets the
* SELinux kernel enforcing status to match it, and loads the policy.
* It also internally handles the initial selinuxfs mount required to
* perform these actions.
*
* The function returns 0 if everything including the policy load succeeds.
* In this case, init is expected to re-exec itself in order to transition
* to the proper security context.
* Otherwise, the function returns -1, and init must check *enforce to
* determine how to proceed. If enforcing (*enforce > 0), then init should
* halt the system. Otherwise, init may proceed normally without a re-exec.
*/
extern int selinux_init_load_policy(int *enforce);
/* Translate boolean strict to name value pair. */
typedef struct {
char *name;
int value;
} SELboolean;
/* save a list of booleans in a single transaction. */
extern int security_set_boolean_list(size_t boolcnt,
SELboolean * boollist, int permanent);
/* Load policy boolean settings.
Path may be NULL, in which case the booleans are loaded from
the active policy boolean configuration file. */
extern int security_load_booleans(char *path);
/* Check the validity of a security context. */
extern int security_check_context(const char * con);
extern int security_check_context_raw(const char * con);
/* Canonicalize a security context. */
extern int security_canonicalize_context(const char * con,
char ** canoncon);
extern int security_canonicalize_context_raw(const char * con,
char ** canoncon);
/* Get the enforce flag value. */
extern int security_getenforce(void);
/* Set the enforce flag value. */
extern int security_setenforce(int value);
/* Get the behavior for undefined classes/permissions */
extern int security_deny_unknown(void);
/* Disable SELinux at runtime (must be done prior to initial policy load). */
extern int security_disable(void);
/* Get the policy version number. */
extern int security_policyvers(void);
/* Get the boolean names */
extern int security_get_boolean_names(char ***names, int *len);
/* Get the pending value for the boolean */
extern int security_get_boolean_pending(const char *name);
/* Get the active value for the boolean */
extern int security_get_boolean_active(const char *name);
/* Set the pending value for the boolean */
extern int security_set_boolean(const char *name, int value);
/* Commit the pending values for the booleans */
extern int security_commit_booleans(void);
/* Userspace class mapping support */
struct security_class_mapping {
const char *name;
const char *perms[sizeof(access_vector_t) * 8 + 1];
};
/**
* selinux_set_mapping - Enable dynamic mapping between integer offsets and security class names
* @map: array of security_class_mapping structures
*
* The core avc_has_perm() API uses integers to represent security
* classes; previous to the introduction of this function, it was
* common for userspace object managers to be compiled using generated
* offsets for a particular policy. However, that strongly ties the build of the userspace components to a particular policy.
*
* By using this function to map between integer offsets and security
* class names, it's possible to replace a system policies that have
* at least the same set of security class names as used by the
* userspace object managers.
*
* To correctly use this function, you should override the generated
* security class defines from the system policy in a local header,
* starting at 1, and have one security_class_mapping structure entry
* per define.
*/
extern int selinux_set_mapping(struct security_class_mapping *map);
/* Common helpers */
/* Convert between mode and security class values */
extern security_class_t mode_to_security_class(mode_t mode);
/* Convert between security class values and string names */
extern security_class_t string_to_security_class(const char *name);
extern const char *security_class_to_string(security_class_t cls);
/* Convert between individual access vector permissions and string names */
extern const char *security_av_perm_to_string(security_class_t tclass,
access_vector_t perm);
extern access_vector_t string_to_av_perm(security_class_t tclass,
const char *name);
/* Returns an access vector in a string representation. User must free the
* returned string via free(). */
extern int security_av_string(security_class_t tclass,
access_vector_t av, char **result);
/* Display an access vector in a string representation. */
extern void print_access_vector(security_class_t tclass, access_vector_t av);
/* Set the function used by matchpathcon_init when displaying
errors about the file_contexts configuration. If not set,
then this defaults to fprintf(stderr, fmt, ...). */
extern void set_matchpathcon_printf(void (*f) (const char *fmt, ...));
/* Set the function used by matchpathcon_init when checking the
validity of a context in the file contexts configuration. If not set,
then this defaults to a test based on security_check_context().
The function is also responsible for reporting any such error, and
may include the 'path' and 'lineno' in such error messages. */
extern void set_matchpathcon_invalidcon(int (*f) (const char *path,
unsigned lineno,
char *context));
/* Same as above, but also allows canonicalization of the context,
by changing *context to refer to the canonical form. If not set,
and invalidcon is also not set, then this defaults to calling
security_canonicalize_context(). */
extern void set_matchpathcon_canoncon(int (*f) (const char *path,
unsigned lineno,
char **context));
/* Set flags controlling operation of matchpathcon_init or matchpathcon. */
#define MATCHPATHCON_BASEONLY 1 /* Only process the base file_contexts file. */
#define MATCHPATHCON_NOTRANS 2 /* Do not perform any context translation. */
#define MATCHPATHCON_VALIDATE 4 /* Validate/canonicalize contexts at init time. */
extern void set_matchpathcon_flags(unsigned int flags);
/* Load the file contexts configuration specified by 'path'
into memory for use by subsequent matchpathcon calls.
If 'path' is NULL, then load the active file contexts configuration,
i.e. the path returned by selinux_file_context_path().
Unless the MATCHPATHCON_BASEONLY flag has been set, this
function also checks for a 'path'.homedirs file and
a 'path'.local file and loads additional specifications
from them if present. */
extern int matchpathcon_init(const char *path);
/* Same as matchpathcon_init, but only load entries with
regexes that have stems that are prefixes of 'prefix'. */
extern int matchpathcon_init_prefix(const char *path, const char *prefix);
/* Free the memory allocated by matchpathcon_init. */
extern void matchpathcon_fini(void);
/* Resolve all of the symlinks and relative portions of a pathname, but NOT
* the final component (same a realpath() unless the final component is a
* symlink. Resolved path must be a path of size PATH_MAX + 1 */
extern int realpath_not_final(const char *name, char *resolved_path);
/* Match the specified pathname and mode against the file contexts
configuration and set *con to refer to the resulting context.
'mode' can be 0 to disable mode matching.
Caller must free via freecon.
If matchpathcon_init has not already been called, then this function
will call it upon its first invocation with a NULL path. */
extern int matchpathcon(const char *path,
mode_t mode, char ** con);
/* Same as above, but return a specification index for
later use in a matchpathcon_filespec_add() call - see below. */
extern int matchpathcon_index(const char *path,
mode_t mode, char ** con);
/* Maintain an association between an inode and a specification index,
and check whether a conflicting specification is already associated
with the same inode (e.g. due to multiple hard links). If so, then
use the latter of the two specifications based on their order in the
file contexts configuration. Return the used specification index. */
extern int matchpathcon_filespec_add(ino_t ino, int specind, const char *file);
/* Destroy any inode associations that have been added, e.g. to restart
for a new filesystem. */
extern void matchpathcon_filespec_destroy(void);
/* Display statistics on the hash table usage for the associations. */
extern void matchpathcon_filespec_eval(void);
/* Check to see whether any specifications had no matches and report them.
The 'str' is used as a prefix for any warning messages. */
extern void matchpathcon_checkmatches(char *str);
/* Match the specified media and against the media contexts
configuration and set *con to refer to the resulting context.
Caller must free con via freecon. */
extern int matchmediacon(const char *media, char ** con);
/*
selinux_getenforcemode reads the /etc/selinux/config file and determines
whether the machine should be started in enforcing (1), permissive (0) or
disabled (-1) mode.
*/
extern int selinux_getenforcemode(int *enforce);
/*
selinux_boolean_sub reads the /etc/selinux/TYPE/booleans.subs_dist file
looking for a record with boolean_name. If a record exists selinux_boolean_sub
returns the translated name otherwise it returns the original name.
The returned value needs to be freed. On failure NULL will be returned.
*/
extern char *selinux_boolean_sub(const char *boolean_name);
/*
selinux_getpolicytype reads the /etc/selinux/config file and determines
what the default policy for the machine is. Calling application must
free policytype.
*/
extern int selinux_getpolicytype(char **policytype);
/*
selinux_policy_root reads the /etc/selinux/config file and returns
the directory path under which the compiled policy file and context
configuration files exist.
*/
extern const char *selinux_policy_root(void);
/*
selinux_set_policy_root sets an alternate policy root directory path under
which the compiled policy file and context configuration files exist.
*/
extern int selinux_set_policy_root(const char *rootpath);
/* These functions return the paths to specific files under the
policy root directory. */
extern const char *selinux_current_policy_path(void);
extern const char *selinux_binary_policy_path(void);
extern const char *selinux_failsafe_context_path(void);
extern const char *selinux_removable_context_path(void);
extern const char *selinux_default_context_path(void);
extern const char *selinux_user_contexts_path(void);
extern const char *selinux_file_context_path(void);
extern const char *selinux_file_context_homedir_path(void);
extern const char *selinux_file_context_local_path(void);
extern const char *selinux_file_context_subs_path(void);
extern const char *selinux_file_context_subs_dist_path(void);
extern const char *selinux_homedir_context_path(void);
extern const char *selinux_media_context_path(void);
extern const char *selinux_virtual_domain_context_path(void);
extern const char *selinux_virtual_image_context_path(void);
extern const char *selinux_lxc_contexts_path(void);
extern const char *selinux_x_context_path(void);
extern const char *selinux_sepgsql_context_path(void);
extern const char *selinux_openrc_contexts_path(void);
extern const char *selinux_openssh_contexts_path(void);
extern const char *selinux_snapperd_contexts_path(void);
extern const char *selinux_systemd_contexts_path(void);
extern const char *selinux_contexts_path(void);
extern const char *selinux_securetty_types_path(void);
extern const char *selinux_booleans_subs_path(void);
extern const char *selinux_booleans_path(void);
extern const char *selinux_customizable_types_path(void);
extern const char *selinux_users_path(void);
extern const char *selinux_usersconf_path(void);
extern const char *selinux_translations_path(void);
extern const char *selinux_colors_path(void);
extern const char *selinux_netfilter_context_path(void);
extern const char *selinux_path(void);
/**
* selinux_check_access - Check permissions and perform appropriate auditing.
* @scon: source security context
* @tcon: target security context
* @tclass: target security class string
* @perm: requested permissions string, interpreted based on @tclass
* @auditdata: auxiliary audit data
*
* Check the AVC to determine whether the @perm permissions are granted
* for the SID pair (@scon, @tcon), interpreting the permissions
* based on @tclass.
* Return %0 if all @perm permissions are granted, -%1 with
* @errno set to %EACCES if any permissions are denied or to another
* value upon other errors.
* If auditing or logging is configured the appropriate callbacks will be called
* and passed the auditdata field
*/
extern int selinux_check_access(const char * scon, const char * tcon, const char *tclass, const char *perm, void *auditdata);
/* Check a permission in the passwd class.
Return 0 if granted or -1 otherwise. */
extern int selinux_check_passwd_access(access_vector_t requested);
extern int checkPasswdAccess(access_vector_t requested);
/* Check if the tty_context is defined as a securetty
Return 0 if secure, < 0 otherwise. */
extern int selinux_check_securetty_context(const char * tty_context);
/* Set the path to the selinuxfs mount point explicitly.
Normally, this is determined automatically during libselinux
initialization, but this is not always possible, e.g. for /sbin/init
which performs the initial mount of selinuxfs. */
void set_selinuxmnt(const char *mnt);
/* Check if selinuxfs exists as a kernel filesystem */
int selinuxfs_exists(void);
/* clear selinuxmnt variable and free allocated memory */
void fini_selinuxmnt(void);
/* Set an appropriate security context based on the filename of a helper
* program, falling back to a new context with the specified type. */
extern int setexecfilecon(const char *filename, const char *fallback_type);
#ifndef DISABLE_RPM
/* Execute a helper for rpm in an appropriate security context. */
extern int rpm_execcon(unsigned int verified,
const char *filename,
char *const argv[], char *const envp[]);
#endif
/* Returns whether a file context is customizable, and should not
be relabeled . */
extern int is_context_customizable(const char * scontext);
/* Perform context translation between the human-readable format
("translated") and the internal system format ("raw").
Caller must free the resulting context via freecon.
Returns -1 upon an error or 0 otherwise.
If passed NULL, sets the returned context to NULL and returns 0. */
extern int selinux_trans_to_raw_context(const char * trans,
char ** rawp);
extern int selinux_raw_to_trans_context(const char * raw,
char ** transp);
/* Perform context translation between security contexts
and display colors. Returns a space-separated list of ten
ten hex RGB triples prefixed by hash marks, e.g. "#ff0000".
Caller must free the resulting string via free.
Returns -1 upon an error or 0 otherwise. */
extern int selinux_raw_context_to_color(const char * raw,
char **color_str);
/* Get the SELinux username and level to use for a given Linux username.
These values may then be passed into the get_ordered_context_list*
and get_default_context* functions to obtain a context for the user.
Returns 0 on success or -1 otherwise.
Caller must free the returned strings via free. */
extern int getseuserbyname(const char *linuxuser, char **seuser, char **level);
/* Get the SELinux username and level to use for a given Linux username and service.
These values may then be passed into the get_ordered_context_list*
and get_default_context* functions to obtain a context for the user.
Returns 0 on success or -1 otherwise.
Caller must free the returned strings via free. */
extern int getseuser(const char *username, const char *service,
char **r_seuser, char **r_level);
/* Compare two file contexts, return 0 if equivalent. */
extern int selinux_file_context_cmp(const char * a,
const char * b);
/*
* Verify the context of the file 'path' against policy.
* Return 1 if match, 0 if not and -1 on error.
*/
extern int selinux_file_context_verify(const char *path, mode_t mode);
/* This function sets the file context on to the system defaults returns 0 on success */
extern int selinux_lsetfilecon_default(const char *path);
/*
* Force a reset of the loaded configuration
* WARNING: This is not thread safe. Be very sure that no other threads
* are calling into libselinux when this is called.
*/
extern void selinux_reset_config(void);
#ifdef __cplusplus
}
#endif
#endif

355
jni/external/selinux_stub.c vendored Normal file
View File

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

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

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

View File

@@ -75,7 +75,6 @@ extern char *argv0; /* For changing process name */
extern char *applet[]; extern char *applet[];
extern int (*applet_main[]) (int, char *[]); extern int (*applet_main[]) (int, char *[]);
extern int null_fd;
// Multi-call entrypoints // Multi-call entrypoints
int magiskhide_main(int argc, char *argv[]); int magiskhide_main(int argc, char *argv[]);

View File

@@ -12,16 +12,15 @@ LOCAL_C_INCLUDES := \
LOCAL_SRC_FILES := \ LOCAL_SRC_FILES := \
main.c \ main.c \
unpack.c \ bootimg.c \
repack.c \
hexpatch.c \ hexpatch.c \
parseimg.c \
compress.c \ compress.c \
utils.c \ boot_utils.c \
cpio.c \ cpio.c \
sha1.c \ sha1.c \
../utils/xwrap.c \ ../utils/xwrap.c \
../utils/vector.c ../utils/vector.c \
../utils/list.c
LOCAL_CFLAGS += -DZLIB_CONST LOCAL_CFLAGS += -DZLIB_CONST
include $(BUILD_EXECUTABLE) include $(BUILD_EXECUTABLE)

View File

@@ -82,55 +82,6 @@ int open_new(const char *filename) {
return xopen(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); return xopen(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
} }
void 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;
case LZ4_LEGACY:
printf("COMPRESSION [%s]\n", "lz4_legacy");
break;
default:
fprintf(stderr, "Unknown ramdisk format!\n");
}
printf("\n");
}
void cleanup() { void cleanup() {
printf("Cleaning up...\n"); printf("Cleaning up...\n");
char name[PATH_MAX]; char name[PATH_MAX];

310
jni/magiskboot/bootimg.c Normal file
View File

@@ -0,0 +1,310 @@
#include "bootimg.h"
#include "magiskboot.h"
static unsigned char *kernel, *ramdisk, *second, *dtb, *extra;
static boot_img_hdr hdr;
static int mtk_kernel = 0, mtk_ramdisk = 0;
static file_t ramdisk_type;
static void dump(unsigned char *buf, size_t size, const char *filename) {
int fd = open_new(filename);
xwrite(fd, buf, size);
close(fd);
}
static size_t restore(const char *filename, int fd) {
int ifd = xopen(filename, O_RDONLY);
size_t size = lseek(ifd, 0, SEEK_END);
lseek(ifd, 0, SEEK_SET);
xsendfile(fd, ifd, NULL, size);
close(ifd);
return size;
}
static void restore_buf(int fd, const void *buf, size_t size) {
xwrite(fd, buf, size);
}
static void print_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;
case LZ4_LEGACY:
printf("COMPRESSION [%s]\n", "lz4_legacy");
break;
default:
fprintf(stderr, "Unknown ramdisk format!\n");
}
printf("\n");
}
int parse_img(unsigned char *orig, size_t size) {
unsigned char *base, *end;
size_t pos = 0;
int ret = 0;
for(base = orig, end = orig + size; base < end; base += 256, size -= 256) {
switch (check_type(base)) {
case CHROMEOS:
// The caller should know it's chromeos, as it needs additional signing
ret = 2;
continue;
case ELF32:
exit(3);
case ELF64:
exit(4);
case AOSP:
// 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 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 (ramdisk_type == MTK) {
printf("MTK header found in ramdisk\n");
mtk_ramdisk = 1;
ramdisk_type = check_type(ramdisk + 512);
}
// Print info
print_info();
return ret;
default:
continue;
}
}
LOGE(1, "No boot image magic found!\n");
}
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);
int ret = parse_img(orig, size);
// 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");
LOGE(1, "Unsupported ramdisk format! Dumped to %s\n", RAMDISK_FILE ".unsupport");
}
if (hdr.second_size) {
// Dump second
dump(second, hdr.second_size, SECOND_FILE);
}
if (hdr.dt_size) {
// Dump dtb
dump(dtb, hdr.dt_size, DTB_FILE);
}
munmap(orig, size);
exit(ret);
}
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);
restore_buf(fd, kernel, 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);
restore_buf(fd, ramdisk, 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; SUP_EXT_LIST[i]; ++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))
LOGE(1, "Unsupported ramdisk format!\n");
munmap(cpio, cpio_size);
}
int found = 0;
for (int i = 0; SUP_EXT_LIST[i]; ++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)
LOGE(1, "No ramdisk exists!\n");
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);
close(fd);
}

View File

@@ -125,7 +125,7 @@ void lzma(int mode, const char* filename, const unsigned char* buf, size_t size)
ret = lzma_auto_decoder(&strm, UINT64_MAX, 0); ret = lzma_auto_decoder(&strm, UINT64_MAX, 0);
break; break;
case 1: case 1:
ret = lzma_stream_encoder(&strm, filters, LZMA_CHECK_CRC64); ret = lzma_stream_encoder(&strm, filters, LZMA_CHECK_CRC32);
break; break;
case 2: case 2:
ret = lzma_alone_encoder(&strm, &opt); ret = lzma_alone_encoder(&strm, &opt);

View File

@@ -1,6 +1,7 @@
#include "magiskboot.h" #include "magiskboot.h"
#include "cpio.h" #include "cpio.h"
#include "vector.h" #include "vector.h"
#include "list.h"
static uint32_t x8u(char *hex) { static uint32_t x8u(char *hex) {
uint32_t val, inpos = 8, outpos; uint32_t val, inpos = 8, outpos;
@@ -220,33 +221,93 @@ static int check_verity_pattern(const char *s) {
return pos; return pos;
} }
static void cpio_dmverity(struct vector *v) { static struct list_head *block_to_list(char *data) {
struct list_head *head = xmalloc(sizeof(*head));
line_list *line;
init_list_head(head);
char *tok;
tok = strsep(&data, "\n");
while (tok) {
line = xcalloc(sizeof(*line), 1);
line->line = tok;
list_insert_end(head, &line->pos);
tok = strsep(&data, "\n");
}
return head;
}
static char *list_to_block(struct list_head *head, uint32_t filesize) {
line_list *line;
char *data = xmalloc(filesize);
uint32_t off = 0;
list_for_each(line, head, line_list, pos) {
strcpy(data + off, line->line);
off += strlen(line->line);
data[off++] = '\n';
}
return data;
}
static void free_newline(line_list *line) {
if (line->isNew)
free(line->line);
}
static void cpio_patch(struct vector *v, int keepverity, int keepforceencrypt) {
struct list_head *head;
line_list *line;
cpio_file *f; cpio_file *f;
int skip, injected = 0;
size_t read, write; size_t read, write;
int skip; const char *ENCRYPT_LIST[] = { "forceencrypt", "forcefdeorfbe", "fileencryptioninline", NULL };
vec_for_each(v, f) { vec_for_each(v, f) {
if (strcmp(f->filename, "init.rc") == 0) {
head = block_to_list(f->data);
list_for_each(line, head, line_list, pos) {
if (strstr(line->line, "import")) {
if (strstr(line->line, "init.magisk.rc"))
injected = 1;
if (injected)
continue;
// Inject magisk script as import
printf("Inject new line [import /init.magisk.rc] in [init.rc]\n");
line = xcalloc(sizeof(*line), 1);
line->line = strdup("import /init.magisk.rc");
line->isNew = 1;
f->filesize += 23;
list_insert(__->prev, &line->pos);
injected = 1;
} else if (strstr(line->line, "selinux.reload_policy")) {
// Remove this line
printf("Remove line [%s] in [init.rc]\n", line->line);
f->filesize -= strlen(line->line) + 1;
__ = list_pop(&line->pos);
free(line);
}
}
char *temp = list_to_block(head, f->filesize);
free(f->data);
f->data = temp;
list_destory(head, list_head, pos, free_newline);
free(head);
} else {
if (!keepverity) {
if (strstr(f->filename, "fstab") != NULL && S_ISREG(f->mode)) { if (strstr(f->filename, "fstab") != NULL && S_ISREG(f->mode)) {
for (read = 0, write = 0; read < f->filesize; ++read, ++write) { for (read = 0, write = 0; read < f->filesize; ++read, ++write) {
skip = check_verity_pattern(f->data + read); skip = check_verity_pattern(f->data + read);
if (skip > 0) { if (skip > 0) {
printf("Remove pattern [%.*s] in [%s]\n", (int) skip, f->data + read, f->filename); printf("Remove pattern [%.*s] in [%s]\n", skip, f->data + read, f->filename);
read += skip; read += skip;
} }
f->data[write] = f->data[read]; f->data[write] = f->data[read];
} }
f->filesize = write; f->filesize = write;
} else if (strcmp(f->filename, "verity_key") == 0) { } else if (strcmp(f->filename, "verity_key") == 0) {
printf("Remove [verity_key]\n");
f->remove = 1; f->remove = 1;
break;
} }
} }
} if (!keepforceencrypt) {
static void cpio_forceencrypt(struct vector *v) {
cpio_file *f;
size_t read, write;
const char *ENCRYPT_LIST[] = { "forceencrypt", "forcefdeorfbe", "fileencryptioninline", NULL };
vec_for_each(v, f) {
if (strstr(f->filename, "fstab") != NULL && S_ISREG(f->mode)) { if (strstr(f->filename, "fstab") != NULL && S_ISREG(f->mode)) {
for (read = 0, write = 0; read < f->filesize; ++read, ++write) { for (read = 0, write = 0; read < f->filesize; ++read, ++write) {
for (int i = 0 ; ENCRYPT_LIST[i]; ++i) { for (int i = 0 ; ENCRYPT_LIST[i]; ++i) {
@@ -263,6 +324,8 @@ static void cpio_forceencrypt(struct vector *v) {
f->filesize = write; f->filesize = write;
} }
} }
}
}
} }
static void cpio_extract(const char *entry, const char *filename, struct vector *v) { static void cpio_extract(const char *entry, const char *filename, struct vector *v) {
@@ -415,10 +478,6 @@ int cpio_commands(const char *command, int argc, char *argv[]) {
--argc; --argc;
if (strcmp(command, "test") == 0) { if (strcmp(command, "test") == 0) {
cmd = TEST; 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) { } else if (strcmp(command, "restore") == 0) {
cmd = RESTORE; cmd = RESTORE;
} else if (argc == 1 && strcmp(command, "backup") == 0) { } else if (argc == 1 && strcmp(command, "backup") == 0) {
@@ -430,6 +489,8 @@ int cpio_commands(const char *command, int argc, char *argv[]) {
++argv; ++argv;
--argc; --argc;
} }
} else if (argc == 2 && strcmp(command, "patch") == 0) {
cmd = PATCH;
} else if (argc == 2 && strcmp(command, "extract") == 0) { } else if (argc == 2 && strcmp(command, "extract") == 0) {
cmd = EXTRACT; cmd = EXTRACT;
} else if (argc == 2 && strcmp(command, "mkdir") == 0) { } else if (argc == 2 && strcmp(command, "mkdir") == 0) {
@@ -438,7 +499,6 @@ int cpio_commands(const char *command, int argc, char *argv[]) {
cmd = ADD; cmd = ADD;
} else { } else {
cmd = NONE; cmd = NONE;
return 1;
} }
struct vector v; struct vector v;
vec_init(&v); vec_init(&v);
@@ -447,12 +507,6 @@ int cpio_commands(const char *command, int argc, char *argv[]) {
case TEST: case TEST:
cpio_test(&v); cpio_test(&v);
break; break;
case DMVERITY:
cpio_dmverity(&v);
break;
case FORCEENCRYPT:
cpio_forceencrypt(&v);
break;
case RESTORE: case RESTORE:
ret = cpio_restore(&v); ret = cpio_restore(&v);
break; break;
@@ -461,6 +515,9 @@ int cpio_commands(const char *command, int argc, char *argv[]) {
case RM: case RM:
cpio_rm(recursive, argv[0], &v); cpio_rm(recursive, argv[0], &v);
break; break;
case PATCH:
cpio_patch(&v, strcmp(argv[0], "true") == 0, strcmp(argv[1], "true") == 0);
break;
case EXTRACT: case EXTRACT:
cpio_extract(argv[0], argv[1], &v); cpio_extract(argv[0], argv[1], &v);
break; break;
@@ -470,9 +527,8 @@ int cpio_commands(const char *command, int argc, char *argv[]) {
case ADD: case ADD:
cpio_add(strtoul(argv[0], NULL, 8), argv[1], argv[2], &v); cpio_add(strtoul(argv[0], NULL, 8), argv[1], argv[2], &v);
break; break;
default: case NONE:
// Never happen return 1;
break;
} }
dump_cpio(incpio, &v); dump_cpio(incpio, &v);
cpio_vec_destroy(&v); cpio_vec_destroy(&v);

View File

@@ -3,6 +3,8 @@
#include <stdint.h> #include <stdint.h>
#include "list.h"
typedef struct cpio_file { typedef struct cpio_file {
// uint32_t ino; // uint32_t ino;
uint32_t mode; uint32_t mode;
@@ -22,6 +24,12 @@ typedef struct cpio_file {
int remove; int remove;
} cpio_file; } cpio_file;
typedef struct line_list {
char *line;
int isNew;
struct list_head pos;
} line_list;
typedef struct cpio_newc_header { typedef struct cpio_newc_header {
char magic[6]; char magic[6];
char ino[8]; char ino[8];

View File

@@ -53,8 +53,7 @@ typedef enum {
ADD, ADD,
EXTRACT, EXTRACT,
TEST, TEST,
DMVERITY, PATCH,
FORCEENCRYPT,
BACKUP, BACKUP,
RESTORE RESTORE
} command_t; } command_t;
@@ -63,17 +62,11 @@ extern char *SUP_LIST[];
extern char *SUP_EXT_LIST[]; extern char *SUP_EXT_LIST[];
extern file_t SUP_TYPE_LIST[]; extern file_t SUP_TYPE_LIST[];
// Global variables
extern unsigned char *kernel, *ramdisk, *second, *dtb, *extra;
extern boot_img_hdr hdr;
extern file_t ramdisk_type;
extern int mtk_kernel, mtk_ramdisk;
// Main entries // Main entries
void unpack(const char *image); void unpack(const char *image);
void repack(const char* orig_image, const char* out_image); void repack(const char* orig_image, const char* out_image);
void hexpatch(const char *image, const char *from, const char *to); void hexpatch(const char *image, const char *from, const char *to);
void parse_img(unsigned char *orig, size_t size); int parse_img(unsigned char *orig, size_t size);
int cpio_commands(const char *command, int argc, char *argv[]); int cpio_commands(const char *command, int argc, char *argv[]);
void cleanup(); void cleanup();
@@ -96,6 +89,5 @@ void write_zero(int fd, size_t size);
void mem_align(size_t *pos, size_t align); void mem_align(size_t *pos, size_t align);
void file_align(int fd, size_t align, int out); void file_align(int fd, size_t align, int out);
int open_new(const char *filename); int open_new(const char *filename);
void print_info();
#endif #endif

View File

@@ -25,9 +25,8 @@ static void usage(char *arg0) {
" --cpio-mkdir <incpio> <mode> <entry>\n Create directory as an <entry>\n" " --cpio-mkdir <incpio> <mode> <entry>\n Create directory as an <entry>\n"
" --cpio-add <incpio> <mode> <entry> <infile>\n Add <infile> as an <entry>; replaces <entry> if already exists\n" " --cpio-add <incpio> <mode> <entry> <infile>\n Add <infile> as an <entry>; replaces <entry> if already exists\n"
" --cpio-extract <incpio> <entry> <outfile>\n Extract <entry> to <outfile>\n" " --cpio-extract <incpio> <entry> <outfile>\n Extract <entry> to <outfile>\n"
" --cpio-test <incpio>\n Return value: 0/not patched 1/Magisk 2/SuperSU\n" " --cpio-test <incpio>\n Return value: 0/not patched 1/Magisk 2/Other (e.g. phh, SuperSU)\n"
" --cpio-patch-dmverity <incpio>\n Remove dm-verity\n" " --cpio-patch <KEEPVERITY> <KEEPFORCEENCRYPT>\n Patch cpio for Magisk. KEEP**** are true/false values\n"
" --cpio-patch-forceencrypt <incpio>\n Change forceencrypt flag to encryptable\n"
" --cpio-backup <incpio> <origcpio>\n Create ramdisk backups into <incpio> from <origcpio>\n" " --cpio-backup <incpio> <origcpio>\n Create ramdisk backups into <incpio> from <origcpio>\n"
" --cpio-restore <incpio>\n Restore ramdisk from ramdisk backup within <incpio>\n" " --cpio-restore <incpio>\n Restore ramdisk from ramdisk backup within <incpio>\n"
"\n" "\n"
@@ -59,7 +58,7 @@ static void usage(char *arg0) {
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
printf("MagiskBoot v" xstr(MAGISK_VERSION) " (by topjohnwu) - Boot Image Modification Tool\n\n"); printf("MagiskBoot v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") (by topjohnwu) - Boot Image Modification Tool\n\n");
if (argc > 1 && strcmp(argv[1], "--cleanup") == 0) { if (argc > 1 && strcmp(argv[1], "--cleanup") == 0) {
cleanup(); cleanup();

View File

@@ -1,91 +0,0 @@
#include "bootimg.h"
#include "magiskboot.h"
unsigned char *kernel, *ramdisk, *second, *dtb, *extra;
boot_img_hdr hdr;
int mtk_kernel = 0, mtk_ramdisk = 0;
file_t ramdisk_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 (ramdisk_type == MTK) {
printf("MTK header found in ramdisk\n");
mtk_ramdisk = 1;
ramdisk_type = check_type(ramdisk + 512);
}
// Print info
print_info();
}
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:
// The caller should know it's chromeos, as it needs additional signing
close(open_new("chromeos"));
continue;
case ELF32:
exit(2);
return;
case ELF64:
exit(3);
return;
case AOSP:
parse_aosp(base, size);
return;
default:
continue;
}
}
LOGE(1, "No boot image magic found!\n");
}

View File

@@ -1,136 +0,0 @@
#include "magiskboot.h"
static size_t restore(const char *filename, int fd) {
int ifd = xopen(filename, O_RDONLY);
size_t size = lseek(ifd, 0, SEEK_END);
lseek(ifd, 0, SEEK_SET);
xsendfile(fd, ifd, NULL, size);
close(ifd);
return size;
}
static void restore_buf(int fd, const void *buf, size_t size) {
xwrite(fd, buf, size);
}
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);
restore_buf(fd, kernel, 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);
restore_buf(fd, ramdisk, 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; SUP_EXT_LIST[i]; ++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))
LOGE(1, "Unsupported ramdisk format!\n");
munmap(cpio, cpio_size);
}
int found = 0;
for (int i = 0; SUP_EXT_LIST[i]; ++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)
LOGE(1, "No ramdisk exists!\n");
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);
close(fd);
}

View File

@@ -1,48 +0,0 @@
#include "magiskboot.h"
static void dump(unsigned char *buf, size_t size, const char *filename) {
int fd = open_new(filename);
xwrite(fd, buf, size);
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);
// 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");
LOGE(1, "Unsupported ramdisk format! Dumped to %s\n", RAMDISK_FILE ".unsupport");
}
if (hdr.second_size) {
// Dump second
dump(second, hdr.second_size, SECOND_FILE);
}
if (hdr.dt_size) {
// Dump dtb
dump(dtb, hdr.dt_size, DTB_FILE);
}
munmap(orig, size);
}

View File

@@ -1,127 +0,0 @@
/* hide_daemon.c - MagiskHide daemon
*
* A dedicated process to join the target namespace,
* and hide all traces in that particular namespace
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mount.h>
#include "magisk.h"
#include "utils.h"
#include "magiskhide.h"
static int pid;
static void lazy_unmount(const char* mountpoint) {
if (umount2(mountpoint, MNT_DETACH) != -1)
LOGI("hide_daemon: Unmounted (%s)\n", mountpoint);
else
LOGI("hide_daemon: Unmount Failed (%s)\n", mountpoint);
}
static void hide_daemon_err() {
LOGD("hide_daemon: error occured, stopping magiskhide services\n");
// Resume process if possible
kill(pid, SIGCONT);
int err = 1;
write(sv[1], &err, sizeof(err));
_exit(-1);
}
int hide_daemon() {
// Fork to a new process
hide_pid = fork();
switch(hide_pid) {
case -1:
PLOGE("fork");
return 1;
case 0:
break;
default:
return 0;
}
close(sv[0]);
// Set the process name
strcpy(argv0, "magiskhide_daemon");
// When an error occurs, report its failure to main process
err_handler = hide_daemon_err;
char buffer[4096], cache_block[256], *line;
struct vector mount_list;
cache_block[0] = '\0';
while(1) {
xxread(sv[1], &pid, sizeof(pid));
// Termination called
if(pid == -1) {
LOGD("hide_daemon: received termination request\n");
_exit(0);
}
manage_selinux();
relink_sbin();
if (switch_mnt_ns(pid))
continue;
snprintf(buffer, sizeof(buffer), "/proc/%d/mounts", pid);
vec_init(&mount_list);
file_to_vector(buffer, &mount_list);
// Find the cache block name if not found yet
if (strlen(cache_block) == 0) {
vec_for_each(&mount_list, line) {
if (strstr(line, " /cache ")) {
sscanf(line, "%256s", cache_block);
break;
}
}
}
// First unmount the dummy skeletons, cache mounts, and /sbin links
vec_for_each_r(&mount_list, line) {
if (strstr(line, "tmpfs /system") || strstr(line, "tmpfs /vendor") || strstr(line, "tmpfs /sbin")
|| (strstr(line, cache_block) && strstr(line, "/system/")) ) {
sscanf(line, "%*s %512s", buffer);
lazy_unmount(buffer);
}
free(line);
}
vec_destroy(&mount_list);
// Re-read mount infos
snprintf(buffer, sizeof(buffer), "/proc/%d/mounts", pid);
vec_init(&mount_list);
file_to_vector(buffer, &mount_list);
// Unmount loop mounts
vec_for_each_r(&mount_list, line) {
if (strstr(line, "/dev/block/loop") && !strstr(line, DUMMDIR)) {
sscanf(line, "%*s %512s", buffer);
lazy_unmount(buffer);
}
free(line);
}
vec_destroy(&mount_list);
// All done, send resume signal
kill(pid, SIGCONT);
// Tell main process all is well
pid = 0;
xwrite(sv[1], &pid, sizeof(pid));
}
// Should never go here
}

View File

@@ -1,14 +1,98 @@
/* list_manager.c - Hide list management /* hide_utils.c - Some utility functions for MagiskHide
*/ */
#include <string.h> #include <stdio.h>
#include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <pthread.h> #include <errno.h>
#include <dirent.h>
#include <string.h>
#include <sys/mount.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <selinux/selinux.h>
#include "magisk.h" #include "magisk.h"
#include "utils.h" #include "utils.h"
#include "daemon.h" #include "resetprop.h"
#include "magiskhide.h" #include "magiskhide.h"
#include "daemon.h"
static char *prop_key[] =
{ "ro.boot.verifiedbootstate", "ro.boot.flash.locked", "ro.boot.veritymode", "ro.boot.warranty_bit", "ro.warranty_bit",
"ro.debuggable", "ro.secure", "ro.build.type", "ro.build.tags", "ro.build.selinux", NULL };
static char *prop_value[] =
{ "green", "1", "enforcing", "0", "0", "0", "1", "user", "release-keys", "0", NULL };
static int mocked = 0;
void manage_selinux() {
if (mocked) return;
char val[1];
int fd = xopen(SELINUX_ENFORCE, O_RDONLY);
xxread(fd, val, 1);
close(fd);
// Permissive
if (val[0] == '0') {
LOGI("hide_daemon: Permissive detected, hide the state\n");
chmod(SELINUX_ENFORCE, 0640);
chmod(SELINUX_POLICY, 0440);
mocked = 1;
}
}
void hide_sensitive_props() {
LOGI("hide_utils: Hiding sensitive props\n");
// Hide all sensitive props
char *value;
for (int i = 0; prop_key[i]; ++i) {
value = getprop(prop_key[i]);
if (value) {
if (strcmp(value, prop_value[i]) != 0)
setprop2(prop_key[i], prop_value[i], 0);
free(value);
}
}
}
void relink_sbin() {
struct stat st;
if (stat("/sbin_orig", &st) == -1 && errno == ENOENT) {
// Re-link all binaries and bind mount
DIR *dir;
struct dirent *entry;
char from[PATH_MAX], to[PATH_MAX];
LOGI("hide_utils: Re-linking /sbin\n");
xmount(NULL, "/", NULL, MS_REMOUNT, NULL);
xrename("/sbin", "/sbin_orig");
xmkdir("/sbin", 0755);
xchmod("/sbin", 0755);
xmount(NULL, "/", NULL, MS_REMOUNT | MS_RDONLY, NULL);
xmkdir("/dev/sbin_bind", 0755);
xchmod("/dev/sbin_bind", 0755);
dir = xopendir("/sbin_orig");
while ((entry = xreaddir(dir))) {
if (strcmp(entry->d_name, "..") == 0)
continue;
snprintf(from, sizeof(from), "/sbin_orig/%s", entry->d_name);
if (entry->d_type == DT_LNK)
xreadlink(from, from, sizeof(from));
snprintf(to, sizeof(to), "/dev/sbin_bind/%s", entry->d_name);
symlink(from, to);
lsetfilecon(to, "u:object_r:rootfs:s0");
}
closedir(dir);
xmount("/dev/sbin_bind", "/sbin", NULL, MS_BIND, NULL);
}
}
int add_list(char *proc) { int add_list(char *proc) {
if (!hideEnabled) { if (!hideEnabled) {

View File

@@ -16,7 +16,6 @@
#include "daemon.h" #include "daemon.h"
#include "resetprop.h" #include "resetprop.h"
int sv[2], hide_pid = -1;
struct vector *hide_list = NULL; struct vector *hide_list = NULL;
int hideEnabled = 0; int hideEnabled = 0;
@@ -29,7 +28,7 @@ void kill_proc(int pid) {
static void usage(char *arg0) { static void usage(char *arg0) {
fprintf(stderr, fprintf(stderr,
"MagiskHide v" xstr(MAGISK_VERSION) " (by topjohnwu) - Hide Magisk!\n\n" "MagiskHide v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") (by topjohnwu) - Hide Magisk!\n\n"
"%s [--options [arguments...] ]\n\n" "%s [--options [arguments...] ]\n\n"
"Options:\n" "Options:\n"
" --enable: Start the magiskhide daemon\n" " --enable: Start the magiskhide daemon\n"
@@ -46,35 +45,23 @@ void launch_magiskhide(int client) {
err_handler = do_nothing; err_handler = do_nothing;
if (hideEnabled) { if (hideEnabled) {
if (client > 0) {
write_int(client, HIDE_IS_ENABLED); write_int(client, HIDE_IS_ENABLED);
close(client); close(client);
}
return; return;
} }
hideEnabled = 1;
LOGI("* Starting MagiskHide\n"); LOGI("* Starting MagiskHide\n");
hideEnabled = 1; if (client > 0) {
if (client != -1) {
if (setprop(MAGISKHIDE_PROP, "1")) if (setprop(MAGISKHIDE_PROP, "1"))
goto error; goto error;
} }
hide_sensitive_props(); hide_sensitive_props();
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sv) == -1)
goto error;
/*
* The setns system call do not support multithread processes
* We have to fork a new process, and communicate with sockets
*/
if (hide_daemon())
goto error;
close(sv[1]);
// Initialize the mutex lock // Initialize the mutex lock
pthread_mutex_init(&hide_lock, NULL); pthread_mutex_init(&hide_lock, NULL);
pthread_mutex_init(&file_lock, NULL); pthread_mutex_init(&file_lock, NULL);
@@ -86,8 +73,10 @@ void launch_magiskhide(int client) {
// Add SafetyNet by default // Add SafetyNet by default
add_list(strdup("com.google.android.gms.unstable")); add_list(strdup("com.google.android.gms.unstable"));
if (client > 0) {
write_int(client, DAEMON_SUCCESS); write_int(client, DAEMON_SUCCESS);
close(client); close(client);
}
// Get thread reference // Get thread reference
proc_monitor_thread = pthread_self(); proc_monitor_thread = pthread_self();
@@ -97,15 +86,9 @@ void launch_magiskhide(int client) {
error: error:
hideEnabled = 0; hideEnabled = 0;
if (client > 0) {
write_int(client, DAEMON_ERROR); write_int(client, DAEMON_ERROR);
close(client); close(client);
if (hide_pid != -1) {
int kill = -1;
// Kill hide daemon
write(sv[0], &kill, sizeof(kill));
close(sv[0]);
waitpid(hide_pid, NULL, 0);
hide_pid = -1;
} }
return; return;
} }

View File

@@ -6,13 +6,10 @@
// Kill process // Kill process
void kill_proc(int pid); void kill_proc(int pid);
// Hide daemon
int hide_daemon();
// Process monitor // Process monitor
void proc_monitor(); void proc_monitor();
// Preprocess // Utility functions
void manage_selinux(); void manage_selinux();
void hide_sensitive_props(); void hide_sensitive_props();
void relink_sbin(); void relink_sbin();
@@ -23,7 +20,7 @@ int rm_list(char *proc);
int init_list(); int init_list();
int destroy_list(); int destroy_list();
extern int sv[2], hide_pid, hideEnabled; extern int hideEnabled;
extern struct vector *hide_list; extern struct vector *hide_list;
extern pthread_mutex_t hide_lock, file_lock; extern pthread_mutex_t hide_lock, file_lock;

View File

@@ -1,90 +0,0 @@
/* pre_process.c - Some pre-processes for MagiskHide to hide properly
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <dirent.h>
#include <string.h>
#include <sys/mount.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <selinux/selinux.h>
#include "magisk.h"
#include "utils.h"
#include "resetprop.h"
#include "magiskhide.h"
static char *prop_key[] =
{ "ro.boot.verifiedbootstate", "ro.boot.flash.locked", "ro.boot.veritymode", "ro.boot.warranty_bit", "ro.warranty_bit",
"ro.debuggable", "ro.secure", NULL };
static char *prop_value[] =
{ "green", "1", "enforcing", "0", "0", "0", "1", NULL };
static int isMocked = 0;
void manage_selinux() {
if (isMocked) return;
char val[1];
int fd = xopen(SELINUX_ENFORCE, O_RDONLY);
xxread(fd, val, 1);
close(fd);
// Permissive
if (val[0] == '0') {
LOGI("hide_daemon: Permissive detected, hide the state\n");
chmod(SELINUX_ENFORCE, 0640);
chmod(SELINUX_POLICY, 0440);
isMocked = 1;
}
}
void hide_sensitive_props() {
LOGI("hide_pre_proc: Hiding sensitive props\n");
// Hide all sensitive props
char *value;
for (int i = 0; prop_key[i]; ++i) {
value = getprop(prop_key[i]);
if (value) {
if (strcmp(value, prop_value[i]) != 0)
setprop2(prop_key[i], prop_value[i], 0);
free(value);
}
}
}
void relink_sbin() {
struct stat st;
if (stat("/sbin_orig", &st) == -1 && errno == ENOENT) {
// Re-link all binaries and bind mount
DIR *dir;
struct dirent *entry;
char from[PATH_MAX], to[PATH_MAX];
LOGI("hide_pre_proc: Re-linking /sbin\n");
xmount(NULL, "/", NULL, MS_REMOUNT, NULL);
xrename("/sbin", "/sbin_orig");
xmkdir("/sbin", 0755);
xchmod("/sbin", 0755);
xmount(NULL, "/", NULL, MS_REMOUNT | MS_RDONLY, NULL);
xmkdir("/dev/sbin_bind", 0755);
xchmod("/dev/sbin_bind", 0755);
dir = xopendir("/sbin_orig");
while ((entry = xreaddir(dir))) {
snprintf(from, sizeof(from), "%s/%s", "/sbin_orig", entry->d_name);
snprintf(to, sizeof(to), "%s/%s", "/dev/sbin_bind", entry->d_name);
symlink(from, to);
lsetfilecon(to, "u:object_r:system_file:s0");
}
closedir(dir);
xmount("/dev/sbin_bind", "/sbin", NULL, MS_BIND, NULL);
}
}

View File

@@ -1,7 +1,8 @@
/* proc_monitor.c - Monitor am_proc_start events /* proc_monitor.c - Monitor am_proc_start events and unmount
* *
* We monitor the logcat am_proc_start events, pause it, * We monitor the logcat am_proc_start events. When a target starts up,
* and send the target PID to hide daemon ASAP * we pause it ASAP, and fork a new process to join its mount namespace
* and do all the unmounting/mocking
*/ */
#include <stdlib.h> #include <stdlib.h>
@@ -12,22 +13,17 @@
#include <pthread.h> #include <pthread.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/mount.h>
#include "magisk.h" #include "magisk.h"
#include "utils.h" #include "utils.h"
#include "magiskhide.h" #include "magiskhide.h"
static int zygote_num = 0; static int zygote_num;
static char init_ns[32], zygote_ns[2][32]; static char init_ns[32], zygote_ns[2][32], cache_block[256];
static int log_pid = 0, log_fd = 0; static int log_pid, log_fd, target_pid;
static char *buffer; static char *buffer;
static void read_namespace(const int pid, char* target, const size_t size) {
char path[32];
snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
xreadlink(path, target, size);
}
// Workaround for the lack of pthread_cancel // Workaround for the lack of pthread_cancel
static void quit_pthread(int sig) { static void quit_pthread(int sig) {
err_handler = do_nothing; err_handler = do_nothing;
@@ -36,23 +32,34 @@ static void quit_pthread(int sig) {
free(buffer); free(buffer);
hideEnabled = 0; hideEnabled = 0;
// Kill the logging if needed // Kill the logging if needed
if (log_pid) { if (log_pid > 0) {
kill(log_pid, SIGTERM); kill(log_pid, SIGTERM);
waitpid(log_pid, NULL, 0); waitpid(log_pid, NULL, 0);
close(log_fd); close(log_fd);
log_fd = log_pid = 0;
} }
int kill = -1; // Resume process if possible
// If process monitor dies, kill hide daemon too if (target_pid > 0)
write(sv[0], &kill, sizeof(kill)); kill(target_pid, SIGCONT);
close(sv[0]);
waitpid(hide_pid, NULL, 0);
pthread_mutex_destroy(&hide_lock); pthread_mutex_destroy(&hide_lock);
pthread_mutex_destroy(&file_lock); pthread_mutex_destroy(&file_lock);
LOGD("proc_monitor: terminating...\n"); LOGD("proc_monitor: terminating...\n");
pthread_exit(NULL); pthread_exit(NULL);
} }
static void proc_monitor_err() {
LOGD("proc_monitor: error occured, stopping magiskhide services\n");
quit_pthread(SIGUSR1);
}
static int read_namespace(const int pid, char* target, const size_t size) {
char path[32];
snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
if (access(path, R_OK) == -1)
return 1;
xreadlink(path, target, size);
return 0;
}
static void store_zygote_ns(int pid) { static void store_zygote_ns(int pid) {
if (zygote_num == 2) return; if (zygote_num == 2) return;
do { do {
@@ -62,9 +69,74 @@ static void store_zygote_ns(int pid) {
++zygote_num; ++zygote_num;
} }
static void proc_monitor_err() { static void lazy_unmount(const char* mountpoint) {
LOGD("proc_monitor: error occured, stopping magiskhide services\n"); if (umount2(mountpoint, MNT_DETACH) != -1)
quit_pthread(SIGUSR1); LOGD("hide_daemon: Unmounted (%s)\n", mountpoint);
else
LOGD("hide_daemon: Unmount Failed (%s)\n", mountpoint);
}
static void hide_daemon_err() {
LOGD("hide_daemon: error occured, stopping magiskhide services\n");
_exit(-1);
}
static void hide_daemon(int pid) {
LOGD("hide_daemon: start unmount for pid=[%d]\n", pid);
// When an error occurs, report its failure to main process
err_handler = hide_daemon_err;
char *line;
struct vector mount_list;
manage_selinux();
relink_sbin();
if (switch_mnt_ns(pid))
return;
snprintf(buffer, PATH_MAX, "/proc/%d/mounts", pid);
vec_init(&mount_list);
file_to_vector(buffer, &mount_list);
// Find the cache block name if not found yet
if (cache_block[0] == '\0') {
vec_for_each(&mount_list, line) {
if (strstr(line, " /cache ")) {
sscanf(line, "%256s", cache_block);
break;
}
}
}
// First unmount dummy skeletons, /sbin links, cache mounts, and mirrors
vec_for_each(&mount_list, line) {
if (strstr(line, "tmpfs /system") || strstr(line, "tmpfs /vendor") || strstr(line, "tmpfs /sbin")
|| (strstr(line, cache_block) && (strstr(line, " /system") || strstr(line, " /vendor")))
|| strstr(line, MIRRDIR)) {
sscanf(line, "%*s %4096s", buffer);
lazy_unmount(buffer);
}
free(line);
}
vec_destroy(&mount_list);
// Re-read mount infos
snprintf(buffer, PATH_MAX, "/proc/%d/mounts", pid);
vec_init(&mount_list);
file_to_vector(buffer, &mount_list);
// Unmount any loop mounts and dummy mounts
vec_for_each(&mount_list, line) {
if (strstr(line, "/dev/block/loop") || strstr(line, DUMMDIR)) {
sscanf(line, "%*s %4096s", buffer);
lazy_unmount(buffer);
}
free(line);
}
// Free uo memory
vec_destroy(&mount_list);
} }
void proc_monitor() { void proc_monitor() {
@@ -76,15 +148,20 @@ void proc_monitor() {
// The error handler should stop magiskhide services // The error handler should stop magiskhide services
err_handler = proc_monitor_err; err_handler = proc_monitor_err;
log_pid = target_pid = -1;
int pid;
buffer = xmalloc(PATH_MAX); buffer = xmalloc(PATH_MAX);
cache_block[0] = '\0';
// Get the mount namespace of init // Get the mount namespace of init
read_namespace(1, init_ns, 32); if (read_namespace(1, init_ns, 32)) {
LOGE("proc_monitor: Your kernel doesn't support mount namespace :(\n");
proc_monitor_err();
}
LOGI("proc_monitor: init ns=%s\n", init_ns); LOGI("proc_monitor: init ns=%s\n", init_ns);
// Get the mount namespace of zygote // Get the mount namespace of zygote
zygote_num = 0;
while(!zygote_num) { while(!zygote_num) {
// Check zygote every 2 secs // Check zygote every 2 secs
sleep(2); sleep(2);
@@ -97,20 +174,24 @@ void proc_monitor() {
LOGI("proc_monitor: zygote ns=%s\n", zygote_ns[0]); LOGI("proc_monitor: zygote ns=%s\n", zygote_ns[0]);
break; break;
case 2: case 2:
LOGI("proc_monitor: zygote (32-bit) ns=%s (64-bit) ns=%s\n", zygote_ns[0], zygote_ns[1]); LOGI("proc_monitor: zygote ns=%s zygote64 ns=%s\n", zygote_ns[0], zygote_ns[1]);
break; break;
} }
while (1) { while (1) {
// Clear previous buffer // Clear previous logcat buffer
system("logcat -b events -c"); system("logcat -b events -c");
// Monitor am_proc_start // Monitor am_proc_start
char *const command[] = { "logcat", "-b", "events", "-v", "raw", "-s", "am_proc_start", NULL }; char *const command[] = { "logcat", "-b", "events", "-v", "raw", "-s", "am_proc_start", NULL };
log_fd = -1;
log_pid = run_command(0, &log_fd, "/system/bin/logcat", command); log_pid = run_command(0, &log_fd, "/system/bin/logcat", command);
if (log_pid < 0) continue;
if (kill(log_pid, 0)) continue;
while(fdgets(buffer, PATH_MAX, log_fd)) { while(fdgets(buffer, PATH_MAX, log_fd)) {
int ret, comma = 0; int pid, ret, comma = 0;
char *pos = buffer, *line, processName[256]; char *pos = buffer, *line, processName[256];
while(1) { while(1) {
@@ -135,10 +216,11 @@ void proc_monitor() {
pthread_mutex_lock(&hide_lock); pthread_mutex_lock(&hide_lock);
vec_for_each(hide_list, line) { vec_for_each(hide_list, line) {
if (strcmp(processName, line) == 0) { if (strcmp(processName, line) == 0) {
target_pid = pid;
while(1) { while(1) {
ret = 1; ret = 1;
for (int i = 0; i < zygote_num; ++i) { for (int i = 0; i < zygote_num; ++i) {
read_namespace(pid, buffer, 32); read_namespace(target_pid, buffer, 32);
if (strcmp(buffer, zygote_ns[i]) == 0) { if (strcmp(buffer, zygote_ns[i]) == 0) {
usleep(50); usleep(50);
ret = 0; ret = 0;
@@ -148,29 +230,39 @@ void proc_monitor() {
if (ret) break; if (ret) break;
} }
ret = 0;
// Send pause signal ASAP // Send pause signal ASAP
if (kill(pid, SIGSTOP) == -1) continue; if (kill(target_pid, SIGSTOP) == -1) continue;
LOGI("proc_monitor: %s (PID=%d ns=%s)\n", processName, pid, buffer); LOGI("proc_monitor: %s (PID=%d ns=%s)\n", processName, target_pid, buffer);
// Unmount start /*
xwrite(sv[0], &pid, sizeof(pid)); * The setns system call do not support multithread processes
* We have to fork a new process, setns, then do the unmounts
*/
int hide_pid = fork();
switch(hide_pid) {
case -1:
PLOGE("fork");
return;
case 0:
hide_daemon(target_pid);
_exit(0);
default:
break;
}
// Get the hide daemon return code // Wait till the unmount process is done
xxread(sv[0], &ret, sizeof(ret)); waitpid(hide_pid, &ret, 0);
LOGD("proc_monitor: hide daemon response code: %d\n", ret); if (WEXITSTATUS(ret))
quit_pthread(SIGUSR1);
// All done, send resume signal
kill(target_pid, SIGCONT);
target_pid = -1;
break; break;
} }
} }
pthread_mutex_unlock(&hide_lock); pthread_mutex_unlock(&hide_lock);
if (ret) {
// Wait hide process to kill itself
waitpid(hide_pid, NULL, 0);
quit_pthread(SIGUSR1);
}
} }
// For some reason it went here, restart logging // For some reason it went here, restart logging

View File

@@ -22,7 +22,7 @@ __thread void (*err_handler)(void);
static void usage() { static void usage() {
fprintf(stderr, fprintf(stderr,
"Magisk v" xstr(MAGISK_VERSION) " multi-call binary\n" "Magisk v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") (by topjohnwu) multi-call binary\n"
"\n" "\n"
"Usage: %s [applet [arguments]...]\n" "Usage: %s [applet [arguments]...]\n"
" or: %s --install [SOURCE] <DIR> \n" " or: %s --install [SOURCE] <DIR> \n"
@@ -32,6 +32,9 @@ static void usage() {
" or: %s --imgsize <PATH>\n" " or: %s --imgsize <PATH>\n"
" or: %s --resizeimg <PATH> <SIZE>\n" " or: %s --resizeimg <PATH> <SIZE>\n"
" SIZE is interpreted in MB\n" " SIZE is interpreted in MB\n"
" or: %s --mountimg <IMG> <PATH>\n"
" Prints out the loop device\n"
" or: %s --umountimg <PATH> <LOOP>\n"
" or: %s --[boot stage]\n" " or: %s --[boot stage]\n"
" start boot stage service\n" " start boot stage service\n"
" or: %s [options]\n" " or: %s [options]\n"
@@ -46,7 +49,7 @@ static void usage() {
" -V print daemon version code\n" " -V print daemon version code\n"
"\n" "\n"
"Supported applets:\n" "Supported applets:\n"
, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0); , argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0);
for (int i = 0; applet[i]; ++i) { for (int i = 0; applet[i]; ++i) {
fprintf(stderr, i ? ", %s" : " %s", applet[i]); fprintf(stderr, i ? ", %s" : " %s", applet[i]);
@@ -99,7 +102,7 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "Cannot check %s size\n", argv[2]); fprintf(stderr, "Cannot check %s size\n", argv[2]);
return 1; return 1;
} }
printf("Used: %dM\tTotal: %dM\n", used, total); printf("%d %d\n", used, total);
return 0; return 0;
} else if (strcmp(argv[1], "--resizeimg") == 0) { } else if (strcmp(argv[1], "--resizeimg") == 0) {
if (argc < 4) usage(); if (argc < 4) usage();
@@ -114,6 +117,21 @@ int main(int argc, char *argv[]) {
return 1; return 1;
} }
return resize_img(argv[2], size); 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], "--post-fs") == 0) { } else if (strcmp(argv[1], "--post-fs") == 0) {
int fd = connect_daemon(); int fd = connect_daemon();
write_int(fd, POST_FS); write_int(fd, POST_FS);

View File

@@ -73,22 +73,22 @@ int __system_property_area_init2();
/* Read the global serial number of the system properties /* Read the global serial number of the system properties
** **
** Called to predict if a series of cached __system_property_find2 ** Called to predict if a series of cached __system_property_find
** objects will have seen __system_property_serial2 values change. ** objects will have seen __system_property_serial values change.
** But also aids the converse, as changes in the global serial can ** But also aids the converse, as changes in the global serial can
** also be used to predict if a failed __system_property_find2 ** also be used to predict if a failed __system_property_find
** could in-turn now find a new object; thus preventing the ** could in-turn now find a new object; thus preventing the
** cycles of effort to poll __system_property_find2. ** cycles of effort to poll __system_property_find.
** **
** Typically called at beginning of a cache cycle to signal if _any_ possible ** Typically called at beginning of a cache cycle to signal if _any_ possible
** changes have occurred since last. If there is, one may check each individual ** changes have occurred since last. If there is, one may check each individual
** __system_property_serial2 to confirm dirty, or __system_property_find2 ** __system_property_serial to confirm dirty, or __system_property_find
** to check if the property now exists. If a call to __system_property_add2 ** to check if the property now exists. If a call to __system_property_add
** or __system_property_update2 has completed between two calls to ** or __system_property_update has completed between two calls to
** __system_property_area_serial2 then the second call will return a larger ** __system_property_area_serial then the second call will return a larger
** value than the first call. Beware of race conditions as changes to the ** value than the first call. Beware of race conditions as changes to the
** properties are not atomic, the main value of this call is to determine ** properties are not atomic, the main value of this call is to determine
** whether the expensive __system_property_find2 is worth retrying to see if ** whether the expensive __system_property_find is worth retrying to see if
** a property now exists. ** a property now exists.
** **
** Returns the serial number on success, -1 on error. ** Returns the serial number on success, -1 on error.
@@ -112,7 +112,7 @@ int __system_property_add2(const char *name, unsigned int namelen, const char *v
int __system_property_del(const char *name); int __system_property_del(const char *name);
/* Update the value of a system property returned by /* Update the value of a system property returned by
** __system_property_find2. Can only be done by a single process ** __system_property_find. Can only be done by a single process
** that has write access to the property area, and that process ** that has write access to the property area, and that process
** must handle sequencing to ensure that only one property is ** must handle sequencing to ensure that only one property is
** updated at a time. ** updated at a time.
@@ -122,7 +122,7 @@ int __system_property_del(const char *name);
int __system_property_update2(prop_info *pi, const char *value, unsigned int len); int __system_property_update2(prop_info *pi, const char *value, unsigned int len);
/* Read the serial number of a system property returned by /* Read the serial number of a system property returned by
** __system_property_find2. ** __system_property_find.
** **
** Returns the serial number on success, -1 on error. ** Returns the serial number on success, -1 on error.
*/ */
@@ -136,7 +136,7 @@ uint32_t __system_property_serial2(const prop_info* pi);
*/ */
int __system_properties_init2(); int __system_properties_init2();
/* Deprecated: use __system_property_wait2 instead. */ /* Deprecated: use __system_property_wait instead. */
uint32_t __system_property_wait_any2(uint32_t old_serial); uint32_t __system_property_wait_any2(uint32_t old_serial);
__END_DECLS __END_DECLS

View File

@@ -17,6 +17,8 @@
#ifndef _BIONIC_MACROS_H_ #ifndef _BIONIC_MACROS_H_
#define _BIONIC_MACROS_H_ #define _BIONIC_MACROS_H_
#include <stdint.h>
// Frameworks OpenGL code currently leaks this header and allows // Frameworks OpenGL code currently leaks this header and allows
// collisions with other declarations, e.g., from libnativehelper. // collisions with other declarations, e.g., from libnativehelper.
// TODO: Remove once cleaned up. b/18334516 // TODO: Remove once cleaned up. b/18334516
@@ -46,4 +48,22 @@
? (1UL << (64 - __builtin_clzl(static_cast<unsigned long>(value)))) \ ? (1UL << (64 - __builtin_clzl(static_cast<unsigned long>(value)))) \
: (1UL << (32 - __builtin_clz(static_cast<unsigned int>(value))))) : (1UL << (32 - __builtin_clz(static_cast<unsigned int>(value)))))
static constexpr uintptr_t align_down(uintptr_t p, size_t align) {
return p & ~(align - 1);
}
static constexpr uintptr_t align_up(uintptr_t p, size_t align) {
return (p + align - 1) & ~(align - 1);
}
template <typename T>
static inline T* align_down(T* p, size_t align) {
return reinterpret_cast<T*>(align_down(reinterpret_cast<uintptr_t>(p), align));
}
template <typename T>
static inline T* align_up(T* p, size_t align) {
return reinterpret_cast<T*>(align_up(reinterpret_cast<uintptr_t>(p), align));
}
#endif // _BIONIC_MACROS_H_ #endif // _BIONIC_MACROS_H_

View File

@@ -60,27 +60,13 @@
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
#include "_system_properties.h" #include "_system_properties.h"
#include <sys/system_properties.h> #include "system_properties.h"
#ifdef INDEP_BINARY
int resetprop_main(int argc, char *argv[]);
int main(int argc, char *argv[]) {
return resetprop_main(argc, argv);
}
#define PRINT_D(...) if (verbose) printf(__VA_ARGS__)
#define PRINT_E(...) fprintf(stderr, __VA_ARGS__)
#else
#include "magisk.h" #include "magisk.h"
#include "resetprop.h"
#define PRINT_D(...) { LOGD(__VA_ARGS__); if (verbose) printf(__VA_ARGS__); } #define PRINT_D(...) { LOGD(__VA_ARGS__); if (verbose) printf(__VA_ARGS__); }
#define PRINT_E(...) { LOGE(__VA_ARGS__); fprintf(stderr, __VA_ARGS__); } #define PRINT_E(...) { LOGE(__VA_ARGS__); fprintf(stderr, __VA_ARGS__); }
#endif
#include "resetprop.h"
static int verbose = 0; static int verbose = 0;
static bool is_legal_property_name(const char* name, size_t namelen) { static bool is_legal_property_name(const char* name, size_t namelen) {
@@ -108,7 +94,7 @@ static bool is_legal_property_name(const char* name, size_t namelen) {
static int usage(char* arg0) { static int usage(char* arg0) {
fprintf(stderr, fprintf(stderr,
"resetprop v" xstr(MAGISK_VERSION) " (by topjohnwu & nkk71) - System Props Modification Tool\n\n" "resetprop v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") (by topjohnwu & nkk71) - System Props Modification Tool\n\n"
"Usage: %s [options] [args...]\n" "Usage: %s [options] [args...]\n"
"%s <name> <value>: Set property entry <name> with <value>\n" "%s <name> <value>: Set property entry <name> with <value>\n"
"%s --file <prop file>: Load props from <prop file>\n" "%s --file <prop file>: Load props from <prop file>\n"
@@ -121,8 +107,7 @@ static int usage(char* arg0) {
return 1; return 1;
} }
int init_resetprop() { static int init_resetprop() {
PRINT_D("resetprop: Initializing...\n");
if (__system_properties_init2()) { if (__system_properties_init2()) {
PRINT_E("resetprop: Initialize error\n"); PRINT_E("resetprop: Initialize error\n");
return -1; return -1;
@@ -130,15 +115,21 @@ int init_resetprop() {
return 0; return 0;
} }
int prop_exist(const char *name) {
if (init_resetprop()) return 0;
return __system_property_find2(name) != NULL;
}
static void read_prop_info(void* cookie, const char *name, const char *value, uint32_t serial) { static void read_prop_info(void* cookie, const char *name, const char *value, uint32_t serial) {
strcpy((char *) cookie, value); strcpy((char *) cookie, value);
} }
// Get prop by name, return string (should free manually!) // Get prop by name, return string (should free manually!)
char *getprop(const char *name) { char *getprop(const char *name) {
if (init_resetprop()) return NULL;
const prop_info *pi = __system_property_find2(name); const prop_info *pi = __system_property_find2(name);
if (pi == NULL) { if (pi == NULL) {
PRINT_D("resetprop: failed to get [%s]\n", name); PRINT_D("resetprop: prop [%s] does not exist\n", name);
return NULL; return NULL;
} }
char value[PROP_VALUE_MAX]; char value[PROP_VALUE_MAX];
@@ -152,16 +143,16 @@ int setprop(const char *name, const char *value) {
} }
int setprop2(const char *name, const char *value, const int trigger) { int setprop2(const char *name, const char *value, const int trigger) {
if (init_resetprop()) return -1;
int ret; int ret;
char *check = getprop(name); prop_info *pi = (prop_info*) __system_property_find2(name);
if (check) { if (pi != NULL) {
free(check);
if (trigger) { if (trigger) {
if (!strncmp(name, "ro.", 3)) deleteprop(name); if (!strncmp(name, "ro.", 3)) deleteprop(name);
ret = __system_property_set2(name, value); ret = __system_property_set2(name, value);
} else { } else {
ret = __system_property_update2((prop_info*) __system_property_find2(name), value, strlen(value)); ret = __system_property_update2(pi, value, strlen(value));
} }
} else { } else {
PRINT_D("resetprop: New prop [%s]\n", name); PRINT_D("resetprop: New prop [%s]\n", name);
@@ -182,6 +173,7 @@ int setprop2(const char *name, const char *value, const int trigger) {
} }
int deleteprop(const char *name) { int deleteprop(const char *name) {
if (init_resetprop()) return -1;
PRINT_D("resetprop: deleteprop [%s]\n", name); PRINT_D("resetprop: deleteprop [%s]\n", name);
if (__system_property_del(name)) { if (__system_property_del(name)) {
PRINT_E("resetprop: delete prop: [%s] error\n", name); PRINT_E("resetprop: delete prop: [%s] error\n", name);
@@ -191,6 +183,7 @@ int deleteprop(const char *name) {
} }
int read_prop_file(const char* filename, const int trigger) { int read_prop_file(const char* filename, const int trigger) {
if (init_resetprop()) return -1;
PRINT_D("resetprop: Load prop file [%s]\n", filename); PRINT_D("resetprop: Load prop file [%s]\n", filename);
FILE *fp = fopen(filename, "r"); FILE *fp = fopen(filename, "r");
if (fp == NULL) { if (fp == NULL) {
@@ -277,8 +270,6 @@ int resetprop_main(int argc, char *argv[]) {
} }
} }
init_resetprop();
if (file) { if (file) {
return read_prop_file(filename, trigger); return read_prop_file(filename, trigger);
} else if (del) { } else if (del) {

View File

@@ -8,7 +8,7 @@
extern "C" { extern "C" {
#endif #endif
int init_resetprop(); int prop_exist(const char *name);
int setprop(const char *name, const char *value); int setprop(const char *name, const char *value);
int setprop2(const char *name, const char *value, const int trigger); int setprop2(const char *name, const char *value, const int trigger);
char *getprop(const char *name); char *getprop(const char *name);

View File

@@ -1149,9 +1149,7 @@ int __system_properties_init2() {
if (initialized) { if (initialized) {
// list_foreach(contexts, [](context_node* l) { l->reset_access(); }); // resetprop remove // list_foreach(contexts, [](context_node* l) { l->reset_access(); }); // resetprop remove
// return 0; // resetprop remove return 0;
free_and_unmap_contexts(); // resetprop add
initialized = false; // resetprop add
} }
if (is_dir(property_filename)) { if (is_dir(property_filename)) {
if (!initialize_properties()) { if (!initialize_properties()) {
@@ -1207,7 +1205,7 @@ uint32_t __system_property_area_serial2() {
if (!pa) { if (!pa) {
return -1; return -1;
} }
// Make sure this read fulfilled before __system_property_serial2 // Make sure this read fulfilled before __system_property_serial
return atomic_load_explicit(pa->serial(), memory_order_acquire); return atomic_load_explicit(pa->serial(), memory_order_acquire);
} }
@@ -1298,7 +1296,7 @@ void __system_property_read_callback2(const prop_info* pi,
memcpy(value_buf, pi->value, len); memcpy(value_buf, pi->value, len);
value_buf[len] = '\0'; value_buf[len] = '\0';
// TODO: see todo in __system_property_read2 function // TODO: see todo in __system_property_read function
atomic_thread_fence(memory_order_acquire); atomic_thread_fence(memory_order_acquire);
if (serial == load_const_atomic(&(pi->serial), memory_order_relaxed)) { if (serial == load_const_atomic(&(pi->serial), memory_order_relaxed)) {
callback(cookie, pi->name, value_buf, serial); callback(cookie, pi->name, value_buf, serial);

View File

@@ -47,7 +47,7 @@ int __system_property_set2(const char* key, const char* value) __INTRODUCED_IN(1
/* /*
* Returns a `prop_info` corresponding system property `name`, or nullptr if it doesn't exist. * Returns a `prop_info` corresponding system property `name`, or nullptr if it doesn't exist.
* Use __system_property_read_callback2 to query the current value. * Use __system_property_read_callback to query the current value.
* *
* Property lookup is expensive, so it can be useful to cache the result of this function. * Property lookup is expensive, so it can be useful to cache the result of this function.
*/ */
@@ -62,7 +62,7 @@ void __system_property_read_callback2(const prop_info *pi,
/* /*
* Passes a `prop_info` for each system property to the provided * Passes a `prop_info` for each system property to the provided
* callback. Use __system_property_read_callback2() to read the value. * callback. Use __system_property_read_callback() to read the value.
* *
* This method is for inspecting and debugging the property system, and not generally useful. * This method is for inspecting and debugging the property system, and not generally useful.
*/ */
@@ -90,11 +90,11 @@ bool __system_property_wait2(const prop_info* pi,
/* Deprecated. In Android O and above, there's no limit on property name length. */ /* Deprecated. In Android O and above, there's no limit on property name length. */
#define PROP_NAME_MAX 32 #define PROP_NAME_MAX 32
/* Deprecated. Use __system_property_read_callback2 instead. */ /* Deprecated. Use __system_property_read_callback instead. */
int __system_property_read2(const prop_info* pi, char* name, char* value); int __system_property_read2(const prop_info* pi, char* name, char* value);
/* Deprecated. Use __system_property_read_callback2 instead. */ /* Deprecated. Use __system_property_read_callback instead. */
int __system_property_get2(const char* name, char* value); int __system_property_get2(const char* name, char* value);
/* Deprecated. Use __system_property_foreach2 instead. */ /* Deprecated. Use __system_property_foreach instead. */
const prop_info* __system_property_find_nth2(unsigned n); const prop_info* __system_property_find_nth2(unsigned n);
__END_DECLS __END_DECLS

View File

@@ -1,10 +0,0 @@
LOCAL_PATH:= $(call my-dir)
##
# libsqlite.so
#
include $(CLEAR_VARS)
LOCAL_MODULE:= libsqlite
LOCAL_SRC_FILES := sqlite3.c shell.c
include $(BUILD_SHARED_LIBRARY)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,564 +0,0 @@
/*
** 2006 June 7
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the SQLite interface for use by
** shared libraries that want to be imported as extensions into
** an SQLite instance. Shared libraries that intend to be loaded
** as extensions by SQLite should #include this file instead of
** sqlite3.h.
*/
#ifndef SQLITE3EXT_H
#define SQLITE3EXT_H
#include "sqlite3.h"
/*
** The following structure holds pointers to all of the SQLite API
** routines.
**
** WARNING: In order to maintain backwards compatibility, add new
** interfaces to the end of this structure only. If you insert new
** interfaces in the middle of this structure, then older different
** versions of SQLite will not be able to load each other's shared
** libraries!
*/
struct sqlite3_api_routines {
void * (*aggregate_context)(sqlite3_context*,int nBytes);
int (*aggregate_count)(sqlite3_context*);
int (*bind_blob)(sqlite3_stmt*,int,const void*,int n,void(*)(void*));
int (*bind_double)(sqlite3_stmt*,int,double);
int (*bind_int)(sqlite3_stmt*,int,int);
int (*bind_int64)(sqlite3_stmt*,int,sqlite_int64);
int (*bind_null)(sqlite3_stmt*,int);
int (*bind_parameter_count)(sqlite3_stmt*);
int (*bind_parameter_index)(sqlite3_stmt*,const char*zName);
const char * (*bind_parameter_name)(sqlite3_stmt*,int);
int (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*));
int (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*));
int (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*);
int (*busy_handler)(sqlite3*,int(*)(void*,int),void*);
int (*busy_timeout)(sqlite3*,int ms);
int (*changes)(sqlite3*);
int (*close)(sqlite3*);
int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,
int eTextRep,const char*));
int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,
int eTextRep,const void*));
const void * (*column_blob)(sqlite3_stmt*,int iCol);
int (*column_bytes)(sqlite3_stmt*,int iCol);
int (*column_bytes16)(sqlite3_stmt*,int iCol);
int (*column_count)(sqlite3_stmt*pStmt);
const char * (*column_database_name)(sqlite3_stmt*,int);
const void * (*column_database_name16)(sqlite3_stmt*,int);
const char * (*column_decltype)(sqlite3_stmt*,int i);
const void * (*column_decltype16)(sqlite3_stmt*,int);
double (*column_double)(sqlite3_stmt*,int iCol);
int (*column_int)(sqlite3_stmt*,int iCol);
sqlite_int64 (*column_int64)(sqlite3_stmt*,int iCol);
const char * (*column_name)(sqlite3_stmt*,int);
const void * (*column_name16)(sqlite3_stmt*,int);
const char * (*column_origin_name)(sqlite3_stmt*,int);
const void * (*column_origin_name16)(sqlite3_stmt*,int);
const char * (*column_table_name)(sqlite3_stmt*,int);
const void * (*column_table_name16)(sqlite3_stmt*,int);
const unsigned char * (*column_text)(sqlite3_stmt*,int iCol);
const void * (*column_text16)(sqlite3_stmt*,int iCol);
int (*column_type)(sqlite3_stmt*,int iCol);
sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol);
void * (*commit_hook)(sqlite3*,int(*)(void*),void*);
int (*complete)(const char*sql);
int (*complete16)(const void*sql);
int (*create_collation)(sqlite3*,const char*,int,void*,
int(*)(void*,int,const void*,int,const void*));
int (*create_collation16)(sqlite3*,const void*,int,void*,
int(*)(void*,int,const void*,int,const void*));
int (*create_function)(sqlite3*,const char*,int,int,void*,
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*));
int (*create_function16)(sqlite3*,const void*,int,int,void*,
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*));
int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*);
int (*data_count)(sqlite3_stmt*pStmt);
sqlite3 * (*db_handle)(sqlite3_stmt*);
int (*declare_vtab)(sqlite3*,const char*);
int (*enable_shared_cache)(int);
int (*errcode)(sqlite3*db);
const char * (*errmsg)(sqlite3*);
const void * (*errmsg16)(sqlite3*);
int (*exec)(sqlite3*,const char*,sqlite3_callback,void*,char**);
int (*expired)(sqlite3_stmt*);
int (*finalize)(sqlite3_stmt*pStmt);
void (*free)(void*);
void (*free_table)(char**result);
int (*get_autocommit)(sqlite3*);
void * (*get_auxdata)(sqlite3_context*,int);
int (*get_table)(sqlite3*,const char*,char***,int*,int*,char**);
int (*global_recover)(void);
void (*interruptx)(sqlite3*);
sqlite_int64 (*last_insert_rowid)(sqlite3*);
const char * (*libversion)(void);
int (*libversion_number)(void);
void *(*malloc)(int);
char * (*mprintf)(const char*,...);
int (*open)(const char*,sqlite3**);
int (*open16)(const void*,sqlite3**);
int (*prepare)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
int (*prepare16)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
void * (*profile)(sqlite3*,void(*)(void*,const char*,sqlite_uint64),void*);
void (*progress_handler)(sqlite3*,int,int(*)(void*),void*);
void *(*realloc)(void*,int);
int (*reset)(sqlite3_stmt*pStmt);
void (*result_blob)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_double)(sqlite3_context*,double);
void (*result_error)(sqlite3_context*,const char*,int);
void (*result_error16)(sqlite3_context*,const void*,int);
void (*result_int)(sqlite3_context*,int);
void (*result_int64)(sqlite3_context*,sqlite_int64);
void (*result_null)(sqlite3_context*);
void (*result_text)(sqlite3_context*,const char*,int,void(*)(void*));
void (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_value)(sqlite3_context*,sqlite3_value*);
void * (*rollback_hook)(sqlite3*,void(*)(void*),void*);
int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,
const char*,const char*),void*);
void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
char * (*snprintf)(int,char*,const char*,...);
int (*step)(sqlite3_stmt*);
int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,
char const**,char const**,int*,int*,int*);
void (*thread_cleanup)(void);
int (*total_changes)(sqlite3*);
void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*);
int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*);
void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,
sqlite_int64),void*);
void * (*user_data)(sqlite3_context*);
const void * (*value_blob)(sqlite3_value*);
int (*value_bytes)(sqlite3_value*);
int (*value_bytes16)(sqlite3_value*);
double (*value_double)(sqlite3_value*);
int (*value_int)(sqlite3_value*);
sqlite_int64 (*value_int64)(sqlite3_value*);
int (*value_numeric_type)(sqlite3_value*);
const unsigned char * (*value_text)(sqlite3_value*);
const void * (*value_text16)(sqlite3_value*);
const void * (*value_text16be)(sqlite3_value*);
const void * (*value_text16le)(sqlite3_value*);
int (*value_type)(sqlite3_value*);
char *(*vmprintf)(const char*,va_list);
/* Added ??? */
int (*overload_function)(sqlite3*, const char *zFuncName, int nArg);
/* Added by 3.3.13 */
int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
int (*clear_bindings)(sqlite3_stmt*);
/* Added by 3.4.1 */
int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*,
void (*xDestroy)(void *));
/* Added by 3.5.0 */
int (*bind_zeroblob)(sqlite3_stmt*,int,int);
int (*blob_bytes)(sqlite3_blob*);
int (*blob_close)(sqlite3_blob*);
int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64,
int,sqlite3_blob**);
int (*blob_read)(sqlite3_blob*,void*,int,int);
int (*blob_write)(sqlite3_blob*,const void*,int,int);
int (*create_collation_v2)(sqlite3*,const char*,int,void*,
int(*)(void*,int,const void*,int,const void*),
void(*)(void*));
int (*file_control)(sqlite3*,const char*,int,void*);
sqlite3_int64 (*memory_highwater)(int);
sqlite3_int64 (*memory_used)(void);
sqlite3_mutex *(*mutex_alloc)(int);
void (*mutex_enter)(sqlite3_mutex*);
void (*mutex_free)(sqlite3_mutex*);
void (*mutex_leave)(sqlite3_mutex*);
int (*mutex_try)(sqlite3_mutex*);
int (*open_v2)(const char*,sqlite3**,int,const char*);
int (*release_memory)(int);
void (*result_error_nomem)(sqlite3_context*);
void (*result_error_toobig)(sqlite3_context*);
int (*sleep)(int);
void (*soft_heap_limit)(int);
sqlite3_vfs *(*vfs_find)(const char*);
int (*vfs_register)(sqlite3_vfs*,int);
int (*vfs_unregister)(sqlite3_vfs*);
int (*xthreadsafe)(void);
void (*result_zeroblob)(sqlite3_context*,int);
void (*result_error_code)(sqlite3_context*,int);
int (*test_control)(int, ...);
void (*randomness)(int,void*);
sqlite3 *(*context_db_handle)(sqlite3_context*);
int (*extended_result_codes)(sqlite3*,int);
int (*limit)(sqlite3*,int,int);
sqlite3_stmt *(*next_stmt)(sqlite3*,sqlite3_stmt*);
const char *(*sql)(sqlite3_stmt*);
int (*status)(int,int*,int*,int);
int (*backup_finish)(sqlite3_backup*);
sqlite3_backup *(*backup_init)(sqlite3*,const char*,sqlite3*,const char*);
int (*backup_pagecount)(sqlite3_backup*);
int (*backup_remaining)(sqlite3_backup*);
int (*backup_step)(sqlite3_backup*,int);
const char *(*compileoption_get)(int);
int (*compileoption_used)(const char*);
int (*create_function_v2)(sqlite3*,const char*,int,int,void*,
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*),
void(*xDestroy)(void*));
int (*db_config)(sqlite3*,int,...);
sqlite3_mutex *(*db_mutex)(sqlite3*);
int (*db_status)(sqlite3*,int,int*,int*,int);
int (*extended_errcode)(sqlite3*);
void (*log)(int,const char*,...);
sqlite3_int64 (*soft_heap_limit64)(sqlite3_int64);
const char *(*sourceid)(void);
int (*stmt_status)(sqlite3_stmt*,int,int);
int (*strnicmp)(const char*,const char*,int);
int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*);
int (*wal_autocheckpoint)(sqlite3*,int);
int (*wal_checkpoint)(sqlite3*,const char*);
void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
int (*vtab_config)(sqlite3*,int op,...);
int (*vtab_on_conflict)(sqlite3*);
/* Version 3.7.16 and later */
int (*close_v2)(sqlite3*);
const char *(*db_filename)(sqlite3*,const char*);
int (*db_readonly)(sqlite3*,const char*);
int (*db_release_memory)(sqlite3*);
const char *(*errstr)(int);
int (*stmt_busy)(sqlite3_stmt*);
int (*stmt_readonly)(sqlite3_stmt*);
int (*stricmp)(const char*,const char*);
int (*uri_boolean)(const char*,const char*,int);
sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
const char *(*uri_parameter)(const char*,const char*);
char *(*vsnprintf)(int,char*,const char*,va_list);
int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
/* Version 3.8.7 and later */
int (*auto_extension)(void(*)(void));
int (*bind_blob64)(sqlite3_stmt*,int,const void*,sqlite3_uint64,
void(*)(void*));
int (*bind_text64)(sqlite3_stmt*,int,const char*,sqlite3_uint64,
void(*)(void*),unsigned char);
int (*cancel_auto_extension)(void(*)(void));
int (*load_extension)(sqlite3*,const char*,const char*,char**);
void *(*malloc64)(sqlite3_uint64);
sqlite3_uint64 (*msize)(void*);
void *(*realloc64)(void*,sqlite3_uint64);
void (*reset_auto_extension)(void);
void (*result_blob64)(sqlite3_context*,const void*,sqlite3_uint64,
void(*)(void*));
void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64,
void(*)(void*), unsigned char);
int (*strglob)(const char*,const char*);
/* Version 3.8.11 and later */
sqlite3_value *(*value_dup)(const sqlite3_value*);
void (*value_free)(sqlite3_value*);
int (*result_zeroblob64)(sqlite3_context*,sqlite3_uint64);
int (*bind_zeroblob64)(sqlite3_stmt*, int, sqlite3_uint64);
/* Version 3.9.0 and later */
unsigned int (*value_subtype)(sqlite3_value*);
void (*result_subtype)(sqlite3_context*,unsigned int);
/* Version 3.10.0 and later */
int (*status64)(int,sqlite3_int64*,sqlite3_int64*,int);
int (*strlike)(const char*,const char*,unsigned int);
int (*db_cacheflush)(sqlite3*);
/* Version 3.12.0 and later */
int (*system_errno)(sqlite3*);
/* Version 3.14.0 and later */
int (*trace_v2)(sqlite3*,unsigned,int(*)(unsigned,void*,void*,void*),void*);
char *(*expanded_sql)(sqlite3_stmt*);
/* Version 3.18.0 and later */
void (*set_last_insert_rowid)(sqlite3*,sqlite3_int64);
};
/*
** This is the function signature used for all extension entry points. It
** is also defined in the file "loadext.c".
*/
typedef int (*sqlite3_loadext_entry)(
sqlite3 *db, /* Handle to the database. */
char **pzErrMsg, /* Used to set error string on failure. */
const sqlite3_api_routines *pThunk /* Extension API function pointers. */
);
/*
** The following macros redefine the API routines so that they are
** redirected through the global sqlite3_api structure.
**
** This header file is also used by the loadext.c source file
** (part of the main SQLite library - not an extension) so that
** it can get access to the sqlite3_api_routines structure
** definition. But the main library does not want to redefine
** the API. So the redefinition macros are only valid if the
** SQLITE_CORE macros is undefined.
*/
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
#define sqlite3_aggregate_context sqlite3_api->aggregate_context
#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_aggregate_count sqlite3_api->aggregate_count
#endif
#define sqlite3_bind_blob sqlite3_api->bind_blob
#define sqlite3_bind_double sqlite3_api->bind_double
#define sqlite3_bind_int sqlite3_api->bind_int
#define sqlite3_bind_int64 sqlite3_api->bind_int64
#define sqlite3_bind_null sqlite3_api->bind_null
#define sqlite3_bind_parameter_count sqlite3_api->bind_parameter_count
#define sqlite3_bind_parameter_index sqlite3_api->bind_parameter_index
#define sqlite3_bind_parameter_name sqlite3_api->bind_parameter_name
#define sqlite3_bind_text sqlite3_api->bind_text
#define sqlite3_bind_text16 sqlite3_api->bind_text16
#define sqlite3_bind_value sqlite3_api->bind_value
#define sqlite3_busy_handler sqlite3_api->busy_handler
#define sqlite3_busy_timeout sqlite3_api->busy_timeout
#define sqlite3_changes sqlite3_api->changes
#define sqlite3_close sqlite3_api->close
#define sqlite3_collation_needed sqlite3_api->collation_needed
#define sqlite3_collation_needed16 sqlite3_api->collation_needed16
#define sqlite3_column_blob sqlite3_api->column_blob
#define sqlite3_column_bytes sqlite3_api->column_bytes
#define sqlite3_column_bytes16 sqlite3_api->column_bytes16
#define sqlite3_column_count sqlite3_api->column_count
#define sqlite3_column_database_name sqlite3_api->column_database_name
#define sqlite3_column_database_name16 sqlite3_api->column_database_name16
#define sqlite3_column_decltype sqlite3_api->column_decltype
#define sqlite3_column_decltype16 sqlite3_api->column_decltype16
#define sqlite3_column_double sqlite3_api->column_double
#define sqlite3_column_int sqlite3_api->column_int
#define sqlite3_column_int64 sqlite3_api->column_int64
#define sqlite3_column_name sqlite3_api->column_name
#define sqlite3_column_name16 sqlite3_api->column_name16
#define sqlite3_column_origin_name sqlite3_api->column_origin_name
#define sqlite3_column_origin_name16 sqlite3_api->column_origin_name16
#define sqlite3_column_table_name sqlite3_api->column_table_name
#define sqlite3_column_table_name16 sqlite3_api->column_table_name16
#define sqlite3_column_text sqlite3_api->column_text
#define sqlite3_column_text16 sqlite3_api->column_text16
#define sqlite3_column_type sqlite3_api->column_type
#define sqlite3_column_value sqlite3_api->column_value
#define sqlite3_commit_hook sqlite3_api->commit_hook
#define sqlite3_complete sqlite3_api->complete
#define sqlite3_complete16 sqlite3_api->complete16
#define sqlite3_create_collation sqlite3_api->create_collation
#define sqlite3_create_collation16 sqlite3_api->create_collation16
#define sqlite3_create_function sqlite3_api->create_function
#define sqlite3_create_function16 sqlite3_api->create_function16
#define sqlite3_create_module sqlite3_api->create_module
#define sqlite3_create_module_v2 sqlite3_api->create_module_v2
#define sqlite3_data_count sqlite3_api->data_count
#define sqlite3_db_handle sqlite3_api->db_handle
#define sqlite3_declare_vtab sqlite3_api->declare_vtab
#define sqlite3_enable_shared_cache sqlite3_api->enable_shared_cache
#define sqlite3_errcode sqlite3_api->errcode
#define sqlite3_errmsg sqlite3_api->errmsg
#define sqlite3_errmsg16 sqlite3_api->errmsg16
#define sqlite3_exec sqlite3_api->exec
#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_expired sqlite3_api->expired
#endif
#define sqlite3_finalize sqlite3_api->finalize
#define sqlite3_free sqlite3_api->free
#define sqlite3_free_table sqlite3_api->free_table
#define sqlite3_get_autocommit sqlite3_api->get_autocommit
#define sqlite3_get_auxdata sqlite3_api->get_auxdata
#define sqlite3_get_table sqlite3_api->get_table
#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_global_recover sqlite3_api->global_recover
#endif
#define sqlite3_interrupt sqlite3_api->interruptx
#define sqlite3_last_insert_rowid sqlite3_api->last_insert_rowid
#define sqlite3_libversion sqlite3_api->libversion
#define sqlite3_libversion_number sqlite3_api->libversion_number
#define sqlite3_malloc sqlite3_api->malloc
#define sqlite3_mprintf sqlite3_api->mprintf
#define sqlite3_open sqlite3_api->open
#define sqlite3_open16 sqlite3_api->open16
#define sqlite3_prepare sqlite3_api->prepare
#define sqlite3_prepare16 sqlite3_api->prepare16
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
#define sqlite3_profile sqlite3_api->profile
#define sqlite3_progress_handler sqlite3_api->progress_handler
#define sqlite3_realloc sqlite3_api->realloc
#define sqlite3_reset sqlite3_api->reset
#define sqlite3_result_blob sqlite3_api->result_blob
#define sqlite3_result_double sqlite3_api->result_double
#define sqlite3_result_error sqlite3_api->result_error
#define sqlite3_result_error16 sqlite3_api->result_error16
#define sqlite3_result_int sqlite3_api->result_int
#define sqlite3_result_int64 sqlite3_api->result_int64
#define sqlite3_result_null sqlite3_api->result_null
#define sqlite3_result_text sqlite3_api->result_text
#define sqlite3_result_text16 sqlite3_api->result_text16
#define sqlite3_result_text16be sqlite3_api->result_text16be
#define sqlite3_result_text16le sqlite3_api->result_text16le
#define sqlite3_result_value sqlite3_api->result_value
#define sqlite3_rollback_hook sqlite3_api->rollback_hook
#define sqlite3_set_authorizer sqlite3_api->set_authorizer
#define sqlite3_set_auxdata sqlite3_api->set_auxdata
#define sqlite3_snprintf sqlite3_api->snprintf
#define sqlite3_step sqlite3_api->step
#define sqlite3_table_column_metadata sqlite3_api->table_column_metadata
#define sqlite3_thread_cleanup sqlite3_api->thread_cleanup
#define sqlite3_total_changes sqlite3_api->total_changes
#define sqlite3_trace sqlite3_api->trace
#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_transfer_bindings sqlite3_api->transfer_bindings
#endif
#define sqlite3_update_hook sqlite3_api->update_hook
#define sqlite3_user_data sqlite3_api->user_data
#define sqlite3_value_blob sqlite3_api->value_blob
#define sqlite3_value_bytes sqlite3_api->value_bytes
#define sqlite3_value_bytes16 sqlite3_api->value_bytes16
#define sqlite3_value_double sqlite3_api->value_double
#define sqlite3_value_int sqlite3_api->value_int
#define sqlite3_value_int64 sqlite3_api->value_int64
#define sqlite3_value_numeric_type sqlite3_api->value_numeric_type
#define sqlite3_value_text sqlite3_api->value_text
#define sqlite3_value_text16 sqlite3_api->value_text16
#define sqlite3_value_text16be sqlite3_api->value_text16be
#define sqlite3_value_text16le sqlite3_api->value_text16le
#define sqlite3_value_type sqlite3_api->value_type
#define sqlite3_vmprintf sqlite3_api->vmprintf
#define sqlite3_vsnprintf sqlite3_api->vsnprintf
#define sqlite3_overload_function sqlite3_api->overload_function
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
#define sqlite3_clear_bindings sqlite3_api->clear_bindings
#define sqlite3_bind_zeroblob sqlite3_api->bind_zeroblob
#define sqlite3_blob_bytes sqlite3_api->blob_bytes
#define sqlite3_blob_close sqlite3_api->blob_close
#define sqlite3_blob_open sqlite3_api->blob_open
#define sqlite3_blob_read sqlite3_api->blob_read
#define sqlite3_blob_write sqlite3_api->blob_write
#define sqlite3_create_collation_v2 sqlite3_api->create_collation_v2
#define sqlite3_file_control sqlite3_api->file_control
#define sqlite3_memory_highwater sqlite3_api->memory_highwater
#define sqlite3_memory_used sqlite3_api->memory_used
#define sqlite3_mutex_alloc sqlite3_api->mutex_alloc
#define sqlite3_mutex_enter sqlite3_api->mutex_enter
#define sqlite3_mutex_free sqlite3_api->mutex_free
#define sqlite3_mutex_leave sqlite3_api->mutex_leave
#define sqlite3_mutex_try sqlite3_api->mutex_try
#define sqlite3_open_v2 sqlite3_api->open_v2
#define sqlite3_release_memory sqlite3_api->release_memory
#define sqlite3_result_error_nomem sqlite3_api->result_error_nomem
#define sqlite3_result_error_toobig sqlite3_api->result_error_toobig
#define sqlite3_sleep sqlite3_api->sleep
#define sqlite3_soft_heap_limit sqlite3_api->soft_heap_limit
#define sqlite3_vfs_find sqlite3_api->vfs_find
#define sqlite3_vfs_register sqlite3_api->vfs_register
#define sqlite3_vfs_unregister sqlite3_api->vfs_unregister
#define sqlite3_threadsafe sqlite3_api->xthreadsafe
#define sqlite3_result_zeroblob sqlite3_api->result_zeroblob
#define sqlite3_result_error_code sqlite3_api->result_error_code
#define sqlite3_test_control sqlite3_api->test_control
#define sqlite3_randomness sqlite3_api->randomness
#define sqlite3_context_db_handle sqlite3_api->context_db_handle
#define sqlite3_extended_result_codes sqlite3_api->extended_result_codes
#define sqlite3_limit sqlite3_api->limit
#define sqlite3_next_stmt sqlite3_api->next_stmt
#define sqlite3_sql sqlite3_api->sql
#define sqlite3_status sqlite3_api->status
#define sqlite3_backup_finish sqlite3_api->backup_finish
#define sqlite3_backup_init sqlite3_api->backup_init
#define sqlite3_backup_pagecount sqlite3_api->backup_pagecount
#define sqlite3_backup_remaining sqlite3_api->backup_remaining
#define sqlite3_backup_step sqlite3_api->backup_step
#define sqlite3_compileoption_get sqlite3_api->compileoption_get
#define sqlite3_compileoption_used sqlite3_api->compileoption_used
#define sqlite3_create_function_v2 sqlite3_api->create_function_v2
#define sqlite3_db_config sqlite3_api->db_config
#define sqlite3_db_mutex sqlite3_api->db_mutex
#define sqlite3_db_status sqlite3_api->db_status
#define sqlite3_extended_errcode sqlite3_api->extended_errcode
#define sqlite3_log sqlite3_api->log
#define sqlite3_soft_heap_limit64 sqlite3_api->soft_heap_limit64
#define sqlite3_sourceid sqlite3_api->sourceid
#define sqlite3_stmt_status sqlite3_api->stmt_status
#define sqlite3_strnicmp sqlite3_api->strnicmp
#define sqlite3_unlock_notify sqlite3_api->unlock_notify
#define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint
#define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint
#define sqlite3_wal_hook sqlite3_api->wal_hook
#define sqlite3_blob_reopen sqlite3_api->blob_reopen
#define sqlite3_vtab_config sqlite3_api->vtab_config
#define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict
/* Version 3.7.16 and later */
#define sqlite3_close_v2 sqlite3_api->close_v2
#define sqlite3_db_filename sqlite3_api->db_filename
#define sqlite3_db_readonly sqlite3_api->db_readonly
#define sqlite3_db_release_memory sqlite3_api->db_release_memory
#define sqlite3_errstr sqlite3_api->errstr
#define sqlite3_stmt_busy sqlite3_api->stmt_busy
#define sqlite3_stmt_readonly sqlite3_api->stmt_readonly
#define sqlite3_stricmp sqlite3_api->stricmp
#define sqlite3_uri_boolean sqlite3_api->uri_boolean
#define sqlite3_uri_int64 sqlite3_api->uri_int64
#define sqlite3_uri_parameter sqlite3_api->uri_parameter
#define sqlite3_uri_vsnprintf sqlite3_api->vsnprintf
#define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2
/* Version 3.8.7 and later */
#define sqlite3_auto_extension sqlite3_api->auto_extension
#define sqlite3_bind_blob64 sqlite3_api->bind_blob64
#define sqlite3_bind_text64 sqlite3_api->bind_text64
#define sqlite3_cancel_auto_extension sqlite3_api->cancel_auto_extension
#define sqlite3_load_extension sqlite3_api->load_extension
#define sqlite3_malloc64 sqlite3_api->malloc64
#define sqlite3_msize sqlite3_api->msize
#define sqlite3_realloc64 sqlite3_api->realloc64
#define sqlite3_reset_auto_extension sqlite3_api->reset_auto_extension
#define sqlite3_result_blob64 sqlite3_api->result_blob64
#define sqlite3_result_text64 sqlite3_api->result_text64
#define sqlite3_strglob sqlite3_api->strglob
/* Version 3.8.11 and later */
#define sqlite3_value_dup sqlite3_api->value_dup
#define sqlite3_value_free sqlite3_api->value_free
#define sqlite3_result_zeroblob64 sqlite3_api->result_zeroblob64
#define sqlite3_bind_zeroblob64 sqlite3_api->bind_zeroblob64
/* Version 3.9.0 and later */
#define sqlite3_value_subtype sqlite3_api->value_subtype
#define sqlite3_result_subtype sqlite3_api->result_subtype
/* Version 3.10.0 and later */
#define sqlite3_status64 sqlite3_api->status64
#define sqlite3_strlike sqlite3_api->strlike
#define sqlite3_db_cacheflush sqlite3_api->db_cacheflush
/* Version 3.12.0 and later */
#define sqlite3_system_errno sqlite3_api->system_errno
/* Version 3.14.0 and later */
#define sqlite3_trace_v2 sqlite3_api->trace_v2
#define sqlite3_expanded_sql sqlite3_api->expanded_sql
/* Version 3.18.0 and later */
#define sqlite3_set_last_insert_rowid sqlite3_api->set_last_insert_rowid
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
/* This case when the file really is being compiled as a loadable
** extension */
# define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0;
# define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v;
# define SQLITE_EXTENSION_INIT3 \
extern const sqlite3_api_routines *sqlite3_api;
#else
/* This case when the file is being statically linked into the
** application */
# define SQLITE_EXTENSION_INIT1 /*no-op*/
# define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */
# define SQLITE_EXTENSION_INIT3 /*no-op*/
#endif
#endif /* SQLITE3EXT_H */

2
jni/su

Submodule jni/su updated: 1bbf96a0a7...e2821025ef

148
jni/utils/img.c Normal file
View File

@@ -0,0 +1,148 @@
/* img.c - All image related functions
*/
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/mount.h>
#include <linux/loop.h>
#include "magisk.h"
#include "utils.h"
static int e2fsck(const char *img) {
// Check and repair ext4 image
char buffer[128];
int pid, fd = -1;
char *const command[] = { "e2fsck", "-yf", (char *) img, NULL };
pid = run_command(1, &fd, "/system/bin/e2fsck", command);
if (pid < 0)
return 1;
while (fdgets(buffer, sizeof(buffer), fd))
LOGD("magisk_img: %s", buffer);
waitpid(pid, NULL, 0);
close(fd);
return 0;
}
static char *loopsetup(const char *img) {
char device[20];
struct loop_info64 info;
int i, lfd, ffd;
memset(&info, 0, sizeof(info));
// First get an empty loop device
for (i = 0; i <= 7; ++i) {
sprintf(device, "/dev/block/loop%d", i);
lfd = xopen(device, O_RDWR);
if (ioctl(lfd, LOOP_GET_STATUS64, &info) == -1)
break;
close(lfd);
}
if (i == 8) return NULL;
ffd = xopen(img, O_RDWR);
if (ioctl(lfd, LOOP_SET_FD, ffd) == -1)
return NULL;
strcpy((char *) info.lo_file_name, img);
ioctl(lfd, LOOP_SET_STATUS64, &info);
close(lfd);
close(ffd);
return strdup(device);
}
int create_img(const char *img, int size) {
unlink(img);
LOGI("Create %s with size %dM\n", img, size);
// Create a temp file with the file contexts
char file_contexts[] = "/magisk(/.*)? u:object_r:system_file:s0\n";
// If not root, attempt to create in current diretory
char *filename = getuid() == UID_ROOT ? "/dev/file_contexts_image" : "file_contexts_image";
int pid, status, fd = xopen(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
xwrite(fd, file_contexts, sizeof(file_contexts));
close(fd);
char buffer[16];
snprintf(buffer, sizeof(buffer), "%dM", size);
char *const command[] = { "make_ext4fs", "-l", buffer, "-a", "/magisk", "-S", filename, (char *) img, NULL };
pid = run_command(0, NULL, "/system/bin/make_ext4fs", command);
if (pid < 0)
return 1;
waitpid(pid, &status, 0);
unlink(filename);
return WEXITSTATUS(status);
}
int get_img_size(const char *img, int *used, int *total) {
if (access(img, R_OK) == -1)
return 1;
char buffer[PATH_MAX];
int pid, fd = -1, status = 1;
char *const command[] = { "e2fsck", "-n", (char *) img, NULL };
pid = run_command(1, &fd, "/system/bin/e2fsck", command);
if (pid < 0)
return 1;
while (fdgets(buffer, sizeof(buffer), fd)) {
if (strstr(buffer, img)) {
char *tok = strtok(buffer, ",");
while(tok != NULL) {
if (strstr(tok, "blocks")) {
status = 0;
break;
}
tok = strtok(NULL, ",");
}
if (status) continue;
sscanf(tok, "%d/%d", used, total);
*used = *used / 256 + 1;
*total /= 256;
break;
}
}
close(fd);
waitpid(pid, NULL, 0);
return 0;
}
int resize_img(const char *img, int size) {
LOGI("Resize %s to %dM\n", img, size);
if (e2fsck(img))
return 1;
char buffer[128];
int pid, status, fd = -1;
snprintf(buffer, sizeof(buffer), "%dM", size);
char *const command[] = { "resize2fs", (char *) img, buffer, NULL };
pid = run_command(1, &fd, "/system/bin/resize2fs", command);
if (pid < 0)
return 1;
while (fdgets(buffer, sizeof(buffer), fd))
LOGD("magisk_img: %s", buffer);
close(fd);
waitpid(pid, &status, 0);
return WEXITSTATUS(status);
}
char *mount_image(const char *img, const char *target) {
if (access(img, F_OK) == -1)
return NULL;
if (access(target, F_OK) == -1) {
if (xmkdir(target, 0755) == -1) {
xmount(NULL, "/", NULL, MS_REMOUNT, NULL);
xmkdir(target, 0755);
xmount(NULL, "/", NULL, MS_REMOUNT | MS_RDONLY, NULL);
}
}
if (e2fsck(img))
return NULL;
char *device = loopsetup(img);
if (device)
xmount(device, target, "ext4", 0, NULL);
return device;
}
void umount_image(const char *target, const char *device) {
xumount(target);
int fd = xopen(device, O_RDWR);
ioctl(fd, LOOP_CLR_FD);
close(fd);
}

View File

@@ -24,15 +24,19 @@ void list_insert_end(struct list_head *head, struct list_head *node) {
list_insert(head->prev, node); list_insert(head->prev, node);
} }
void list_pop(struct list_head *pos) { struct list_head *list_pop(struct list_head *pos) {
struct list_head *ret;
ret = pos->prev;
// Maintain the list // Maintain the list
pos->prev->next = pos->next; pos->prev->next = pos->next;
pos->next->prev = pos->prev; pos->next->prev = pos->prev;
// Remove references // Remove references
pos->next = pos; pos->next = pos;
pos->prev = pos; pos->prev = pos;
// Return the previous node in the list
return ret;
} }
void list_pop_end(struct list_head *head) { struct list_head *list_pop_end(struct list_head *head) {
return list_pop(head->prev); return list_pop(head->prev);
} }

View File

@@ -14,17 +14,30 @@ struct list_head {
void init_list_head(struct list_head *head); void init_list_head(struct list_head *head);
void list_insert(struct list_head *pos, struct list_head *node); void list_insert(struct list_head *pos, struct list_head *node);
void list_insert_end(struct list_head *head, struct list_head *node); void list_insert_end(struct list_head *head, struct list_head *node);
void list_pop(struct list_head *pos); struct list_head *list_pop(struct list_head *pos);
void list_pop_end(struct list_head *head); struct list_head *list_pop_end(struct list_head *head);
#define list_entry(ptr, type, member) ({ \ #define list_entry(pos, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \ const typeof( ((type *)0)->member ) *__mptr = (pos); \
(type *)( (char *)__mptr - offsetof(type,member) );}) (type *)( (char *)__mptr - offsetof(type,member) );})
#define list_for_each(pos, head) \ #define list_for_each(ptr, head, type, member) \
for (pos = (head)->next; pos != (head); pos = pos->next) ptr = list_entry((head)->next, type, member); \
for (struct list_head *__ = (head)->next; __ != (head); __ = __->next, ptr = list_entry(__, type, member))
#define list_for_each_r(pos, head) \ #define list_for_each_r(ptr, head, type, member) \
for (pos = (head)->prev; pos != (head); pos = pos->prev) ptr = list_entry((head)->prev, type, member); \
for (struct list_head *__ = (head)->prev; __ != (head); __ = __->prev, ptr = list_entry(__, type, member))
#define list_destory(head, type, member, func) ({ \
struct list_head *node = head->next; \
while(node != head) { \
node = node->next; \
if (func) func(list_entry(node->prev, line_list, pos)); \
free(list_entry(node->prev, line_list, pos)); \
} \
head->next = head; \
head->prev = head; \
})
#endif #endif

View File

@@ -221,30 +221,31 @@ void setup_sighandlers(void (*handler)(int)) {
/* /*
fd == NULL -> Ignore output fd == NULL -> Ignore output
*fd == 0 -> Open pipe and set *fd to the read end *fd < 0 -> Open pipe and set *fd to the read end
*fd != 0 -> STDOUT (or STDERR) will be redirected to *fd *fd >= 0 -> STDOUT (or STDERR) will be redirected to *fd
*/ */
int run_command(int err, int *fd, const char *path, char *const argv[]) { int run_command(int err, int *fd, const char *path, char *const argv[]) {
int pipefd[2], writeEnd = 0; int pipefd[2], writeEnd = -1;
if (fd) { if (fd) {
if (*fd == 0) { if (*fd < 0) {
if (pipe(pipefd) == -1) if (xpipe2(pipefd, O_CLOEXEC) == -1)
return -1; return -1;
writeEnd = pipefd[1]; writeEnd = pipefd[1];
// Give the read end of the pipe // Give the read end of the pipe
*fd = pipefd[0]; *fd = pipefd[0];
} else {
writeEnd = *fd;
} }
} }
int pid = fork(); int pid = fork();
if (pid != 0) { if (pid != 0) {
if (writeEnd) close(writeEnd); close(writeEnd);
return pid; return pid;
} }
if (fd) { if (fd) {
if (writeEnd == 0) writeEnd = *fd;
xdup2(writeEnd, STDOUT_FILENO); xdup2(writeEnd, STDOUT_FILENO);
if (err) xdup2(writeEnd, STDERR_FILENO); if (err) xdup2(writeEnd, STDERR_FILENO);
} }
@@ -277,11 +278,11 @@ int mkdir_p(const char *pathname, mode_t mode) {
int bind_mount(const char *from, const char *to) { int bind_mount(const char *from, const char *to) {
int ret = xmount(from, to, NULL, MS_BIND, NULL); int ret = xmount(from, to, NULL, MS_BIND, NULL);
#ifdef DEBUG #ifdef DEBUG
LOGD("bind_mount: %s -> %s\n", from, to); LOGD("bind_mount: %s -> %s\n", from, to);
#else #else
LOGI("bind_mount: %s\n", to); LOGI("bind_mount: %s\n", to);
#endif #endif
return ret; return ret;
} }
@@ -300,17 +301,14 @@ int cp_afc(const char *source, const char *target) {
sfd = xopen(source, O_RDONLY); sfd = xopen(source, O_RDONLY);
tfd = xopen(target, O_WRONLY | O_CREAT | O_TRUNC); tfd = xopen(target, O_WRONLY | O_CREAT | O_TRUNC);
xsendfile(tfd, sfd, NULL, buf.st_size); xsendfile(tfd, sfd, NULL, buf.st_size);
fchmod(tfd, buf.st_mode & 0777); fclone_attr(sfd, tfd);
fchown(tfd, buf.st_uid, buf.st_gid);
fgetfilecon(sfd, &con);
fsetfilecon(tfd, con);
free(con);
close(sfd); close(sfd);
close(tfd); close(tfd);
} else if (S_ISLNK(buf.st_mode)) { } else if (S_ISLNK(buf.st_mode)) {
char buffer[PATH_MAX]; char buffer[PATH_MAX];
xreadlink(source, buffer, sizeof(buffer)); xreadlink(source, buffer, sizeof(buffer));
xsymlink(buffer, target); xsymlink(buffer, target);
lchown(target, buf.st_uid, buf.st_gid);
lgetfilecon(source, &con); lgetfilecon(source, &con);
lsetfilecon(target, con); lsetfilecon(target, con);
free(con); free(con);
@@ -359,38 +357,10 @@ int clone_dir(const char *source, const char *target) {
int rm_rf(const char *target) { int rm_rf(const char *target) {
if (access(target, F_OK) == -1) if (access(target, F_OK) == -1)
return 0; return 0;
struct stat buf; // Use external rm command, saves a lot of headache and issues
xlstat(target, &buf); char command[PATH_MAX];
char *next; snprintf(command, sizeof(command), "rm -rf %s", target);
if (S_ISDIR(buf.st_mode)) { return system(command);
DIR *dir;
struct dirent *entry;
if (!(dir = xopendir(target)))
return 1;
next = xmalloc(PATH_MAX);
while ((entry = xreaddir(dir))) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue;
snprintf(next, PATH_MAX, "%s/%s", target, entry->d_name);
switch (entry->d_type) {
case DT_DIR:
rm_rf(next);
break;
case DT_REG:
case DT_LNK:
unlink(next);
break;
}
}
free(next);
closedir(dir);
rmdir(target);
} else if (S_ISREG(buf.st_mode) || S_ISLNK(buf.st_mode)) {
unlink(target);
} else {
return 1;
}
return 0;
} }
void clone_attr(const char *source, const char *target) { void clone_attr(const char *source, const char *target) {
@@ -404,62 +374,23 @@ void clone_attr(const char *source, const char *target) {
free(con); free(con);
} }
void fclone_attr(const int sourcefd, const int targetfd) {
struct stat buf;
fstat(sourcefd, &buf);
fchmod(targetfd, buf.st_mode & 0777);
fchown(targetfd, buf.st_uid, buf.st_gid);
char *con;
fgetfilecon(sourcefd, &con);
fsetfilecon(sourcefd, con);
free(con);
}
void get_client_cred(int fd, struct ucred *cred) { void get_client_cred(int fd, struct ucred *cred) {
socklen_t ucred_length = sizeof(*cred); socklen_t ucred_length = sizeof(*cred);
if(getsockopt(fd, SOL_SOCKET, SO_PEERCRED, cred, &ucred_length)) if(getsockopt(fd, SOL_SOCKET, SO_PEERCRED, cred, &ucred_length))
PLOGE("getsockopt"); PLOGE("getsockopt");
} }
int create_img(const char *img, int size) {
unlink(img);
LOGI("Create %s with size %dM\n", img, size);
// Create a temp file with the file contexts
char file_contexts[] = "/magisk(/.*)? u:object_r:system_file:s0\n";
int fd = xopen("/dev/file_contexts_image", O_WRONLY | O_CREAT | O_TRUNC, 0644);
xwrite(fd, file_contexts, sizeof(file_contexts));
close(fd);
char command[PATH_MAX];
snprintf(command, sizeof(command),
"make_ext4fs -l %dM -a /magisk -S /dev/file_contexts_image %s", size, img);
int ret = system(command);
unlink("/dev/file_contexts_image");
return ret;
}
int get_img_size(const char *img, int *used, int *total) {
if (access(img, R_OK) == -1)
return 1;
char buffer[PATH_MAX];
snprintf(buffer, sizeof(buffer), "e2fsck -n %s 2>/dev/null | tail -n 1", img);
char *const command[] = { "sh", "-c", buffer, NULL };
int pid, fd = 0;
pid = run_command(0, &fd, "/system/bin/sh", command);
fdgets(buffer, sizeof(buffer), fd);
close(fd);
if (pid == -1)
return 1;
waitpid(pid, NULL, 0);
char *tok;
tok = strtok(buffer, ",");
while(tok != NULL) {
if (strstr(tok, "blocks"))
break;
tok = strtok(NULL, ",");
}
sscanf(tok, "%d/%d", used, total);
*used = *used / 256 + 1;
*total /= 256;
return 0;
}
int resize_img(const char *img, int size) {
LOGI("Resize %s to %dM\n", img, size);
char buffer[PATH_MAX];
snprintf(buffer, PATH_MAX, "e2fsck -yf %s; resize2fs %s %dM;", img, img, size);
return system(buffer);
}
int switch_mnt_ns(int pid) { int switch_mnt_ns(int pid) {
char mnt[32]; char mnt[32];
snprintf(mnt, sizeof(mnt), "/proc/%d/ns/mnt", pid); snprintf(mnt, sizeof(mnt), "/proc/%d/ns/mnt", pid);

View File

@@ -31,7 +31,7 @@ int xopen3(const char *pathname, int flags, mode_t mode);
ssize_t xwrite(int fd, const void *buf, size_t count); ssize_t xwrite(int fd, const void *buf, size_t count);
ssize_t xread(int fd, void *buf, size_t count); ssize_t xread(int fd, void *buf, size_t count);
ssize_t xxread(int fd, void *buf, size_t count); ssize_t xxread(int fd, void *buf, size_t count);
int xpipe(int pipefd[2]); int xpipe2(int pipefd[2], int flags);
int xsetns(int fd, int nstype); int xsetns(int fd, int nstype);
DIR *xopendir(const char *name); DIR *xopendir(const char *name);
struct dirent *xreaddir(DIR *dirp); struct dirent *xreaddir(DIR *dirp);
@@ -40,7 +40,7 @@ int xsocket(int domain, int type, int protocol);
int xbind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); int xbind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
int xconnect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); int xconnect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
int xlisten(int sockfd, int backlog); int xlisten(int sockfd, int backlog);
int xaccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); int xaccept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
void *xmalloc(size_t size); void *xmalloc(size_t size);
void *xcalloc(size_t nmemb, size_t size); void *xcalloc(size_t nmemb, size_t size);
void *xrealloc(void *ptr, size_t size); void *xrealloc(void *ptr, size_t size);
@@ -89,11 +89,16 @@ int open_new(const char *filename);
int cp_afc(const char *source, const char *target); int cp_afc(const char *source, const char *target);
int clone_dir(const char *source, const char *target); int clone_dir(const char *source, const char *target);
int rm_rf(const char *target); int rm_rf(const char *target);
void fclone_attr(const int sourcefd, const int targetfd);
void clone_attr(const char *source, const char *target); void clone_attr(const char *source, const char *target);
void get_client_cred(int fd, struct ucred *cred); void get_client_cred(int fd, struct ucred *cred);
int switch_mnt_ns(int pid);
// img.c
int create_img(const char *img, int size); int create_img(const char *img, int size);
int get_img_size(const char *img, int *used, int *total); int get_img_size(const char *img, int *used, int *total);
int resize_img(const char *img, int size); int resize_img(const char *img, int size);
int switch_mnt_ns(int pid); char *mount_image(const char *img, const char *target);
void umount_image(const char *target, const char *device);
#endif #endif

View File

@@ -82,10 +82,10 @@ ssize_t xxread(int fd, void *buf, size_t count) {
return ret; return ret;
} }
int xpipe(int pipefd[2]) { int xpipe2(int pipefd[2], int flags) {
int ret = pipe(pipefd); int ret = pipe2(pipefd, flags);
if (ret == -1) { if (ret == -1) {
PLOGE("pipe"); PLOGE("pipe2");
} }
return ret; return ret;
} }
@@ -155,8 +155,8 @@ int xlisten(int sockfd, int backlog) {
return ret; return ret;
} }
int xaccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { int xaccept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) {
int fd = accept(sockfd, addr, addrlen); int fd = accept4(sockfd, addr, addrlen, flags);
if (fd == -1) { if (fd == -1) {
PLOGE("accept"); PLOGE("accept");
} }
@@ -307,7 +307,7 @@ int xrename(const char *oldpath, const char *newpath) {
int xmkdir(const char *pathname, mode_t mode) { int xmkdir(const char *pathname, mode_t mode) {
int ret = mkdir(pathname, mode); int ret = mkdir(pathname, mode);
if (ret == -1) { if (ret == -1 && errno != EEXIST) {
PLOGE("mkdir %s %u", pathname, mode); PLOGE("mkdir %s %u", pathname, mode);
} }
return ret; return ret;

97
scripts/addon.d.sh Normal file
View File

@@ -0,0 +1,97 @@
#!/sbin/sh
##########################################################################################
#
# Magisk Survival Script for ROMs with addon.d support
# by topjohnwu
#
# Inspired by 99-flashafterupdate.sh of osm0sis @ xda-developers
#
##########################################################################################
. /tmp/backuptool.functions
main() {
# Magisk binaries
MAGISKBIN=/data/magisk
# This script always run in recovery
BOOTMODE=false
if [ ! -d $MAGISKBIN ]; then
echo "! Cannot find Magisk binaries!"
exit 1
fi
# Wait for post addon.d processes to finish
sleep 5
mount -o ro /system 2>/dev/null
mount -o ro /vendor 2>/dev/null
mount /data 2>/dev/null
# Load utility functions
. $MAGISKBIN/util_functions.sh
[ -f /system/build.prop ] || abort "! /system could not be mounted!"
ui_print "************************"
ui_print "* MAGISK_VERSION_STUB"
ui_print "************************"
api_level_arch_detect
# Check if system root is installed and remove
remove_system_su
recovery_actions
find_boot_image
[ -z $BOOTIMAGE ] && abort "! Unable to detect boot image"
ui_print "- Found Boot Image: $BOOTIMAGE"
SOURCEDMODE=true
cd $MAGISKBIN
# Source the boot patcher
. $MAGISKBIN/boot_patch.sh "$BOOTIMAGE"
[ -f stock_boot* ] && rm -f /data/stock_boot* 2>/dev/null
ui_print "- Flashing new boot image"
if [ -L "$BOOTIMAGE" ]; then
dd if=new-boot.img of="$BOOTIMAGE" bs=4096
else
cat new-boot.img /dev/zero | dd of="$BOOTIMAGE" bs=4096 >/dev/null 2>&1
fi
rm -f new-boot.img
cd /
recovery_cleanup
ui_print "- Done"
exit 0
}
case "$1" in
backup)
# Stub
;;
restore)
# Stub
;;
pre-backup)
# Stub
;;
post-backup)
# Stub
;;
pre-restore)
# Stub
;;
post-restore)
# Get the FD for ui_print
OUTFD=`ps | grep -v grep | grep -oE "update(.*)" | cut -d" " -f3`
# Run the main function in a parallel subshell
(main) &
;;
esac

View File

@@ -4,7 +4,7 @@
# Magisk Boot Image Patcher # Magisk Boot Image Patcher
# by topjohnwu # by topjohnwu
# #
# This script should be placed in a directory with at least the following files: # This script should be placed in a directory with the following files:
# #
# File name type Description # File name type Description
# #
@@ -14,32 +14,20 @@
# magisk binary The main binary for all Magisk operations. # magisk binary The main binary for all Magisk operations.
# It is also used to patch the sepolicy in the ramdisk. # It is also used to patch the sepolicy in the ramdisk.
# magiskboot binary A tool to unpack boot image, decompress ramdisk, extract ramdisk # magiskboot binary A tool to unpack boot image, decompress ramdisk, extract ramdisk
# and patch common patches such as forceencrypt, remove dm-verity. # , and patch the ramdisk for Magisk support
# init.magisk.rc script A new line will be added to init.rc to import this script. # init.magisk.rc script A new line will be added to init.rc to import this script.
# All magisk entrypoints are defined here # All magisk entrypoints are defined here
# chromeos folder This folder should store all the utilities and keys to sign
# (optional) a chromeos device, used in the tablet Pixel C
# #
# If the script is not running as root, then the input boot image should be a stock image # If the script is not running as root, then the input boot image should be a stock image
# or have a backup included in ramdisk internally, since we cannot access the stock boot # or have a backup included in ramdisk internally, since we cannot access the stock boot
# image placed under /data we've created when previously installing # image placed under /data we've created when previously installing
# #
########################################################################################## ##########################################################################################
##########################################################################################
CWD=`pwd` # Functions
cd `dirname $1` ##########################################################################################
BOOTIMAGE="`pwd`/`basename $1`"
cd "$CWD"
if [ -z $BOOTIMAGE ]; then
ui_print_wrap "This script requires a boot image as a parameter"
exit 1
fi
# Presets
[ -z $KEEPVERITY ] && KEEPVERITY=false
[ -z $KEEPFORCEENCRYPT ] && KEEPFORCEENCRYPT=false
# Detect whether running as root
[ `id -u` -eq 0 ] && ROOT=true || ROOT=false
# Call ui_print_wrap if exists, or else simply use echo # Call ui_print_wrap if exists, or else simply use echo
# Useful when wrapped in flashable zip # Useful when wrapped in flashable zip
@@ -47,6 +35,33 @@ ui_print_wrap() {
type ui_print >/dev/null 2>&1 && ui_print "$1" || echo "$1" type ui_print >/dev/null 2>&1 && ui_print "$1" || echo "$1"
} }
# Call abort if exists, or else show error message and exit
# Essential when wrapped in flashable zip
abort_wrap() {
type abort >/dev/null 2>&1
if [ $? -ne 0 ]; then
ui_print_wrap "$1"
exit 1
else
abort "$1"
fi
}
# Pure bash dirname implementation
dirname_wrap() {
if echo $1 | grep "/" >/dev/null 2>&1; then
RES=${1%/*}
[ -z $RES ] && echo "/" || echo $RES
else
echo "."
fi
}
# Pure bash basename implementation
basename_wrap() {
echo ${1##*/}
}
grep_prop() { grep_prop() {
REGEX="s/^$1=//p" REGEX="s/^$1=//p"
shift shift
@@ -59,47 +74,66 @@ grep_prop() {
# --cpio-add <incpio> <mode> <entry> <infile> # --cpio-add <incpio> <mode> <entry> <infile>
cpio_add() { cpio_add() {
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --cpio-add ramdisk.cpio $1 $2 $3 ./magiskboot --cpio-add ramdisk.cpio $1 $2 $3
} }
# --cpio-extract <incpio> <entry> <outfile> # --cpio-extract <incpio> <entry> <outfile>
cpio_extract() { cpio_extract() {
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --cpio-extract ramdisk.cpio $1 $2 ./magiskboot --cpio-extract ramdisk.cpio $1 $2
} }
# --cpio-mkdir <incpio> <mode> <entry> # --cpio-mkdir <incpio> <mode> <entry>
cpio_mkdir() { cpio_mkdir() {
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --cpio-mkdir ramdisk.cpio $1 $2 ./magiskboot --cpio-mkdir ramdisk.cpio $1 $2
} }
########################################################################################## ##########################################################################################
# Prework # Initialization
########################################################################################## ##########################################################################################
CWD=`pwd`
cd "`dirname_wrap $1`"
BOOTIMAGE="`pwd`/`basename_wrap $1`"
cd "$CWD"
if [ -z "$BOOTIMAGE" ]; then
ui_print_wrap "This script requires a boot image as a parameter"
exit 1
fi
# Presets
[ -z $KEEPVERITY ] && KEEPVERITY=false
[ -z $KEEPFORCEENCRYPT ] && KEEPFORCEENCRYPT=false
# Detect whether running as root
[ `id -u` -eq 0 ] && ROOT=true || ROOT=false
# Switch to the location of the script file # Switch to the location of the script file
[ -z $SOURCEDMODE ] && cd "`dirname "${BASH_SOURCE:-$0}"`" [ -z $SOURCEDMODE ] && cd "`dirname_wrap "${BASH_SOURCE:-$0}"`"
chmod +x ./* chmod +x ./*
# Detect ARCH ##########################################################################################
[ -d /system/lib64 ] && SYSTEMLIB=/system/lib64 || SYSTEMLIB=/system/lib # Unpack
##########################################################################################
ui_print_wrap "- Unpacking boot image" ui_print_wrap "- Unpacking boot image"
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --unpack $BOOTIMAGE ./magiskboot --unpack "$BOOTIMAGE"
CHROMEOS=false
case $? in case $? in
1 ) 1 )
ui_print_wrap "! Unable to unpack boot image" abort_wrap "! Unable to unpack boot image"
exit 1
;; ;;
2 ) 2 )
ui_print_wrap "! Sony ELF32 format detected" CHROMEOS=true
ui_print_wrap "! Please use BootBridge from @AdrianDC to flash Magisk"
exit 1
;; ;;
3 ) 3 )
ui_print_wrap "! Sony ELF32 format detected"
abort_wrap "! Please use BootBridge from @AdrianDC to flash Magisk"
;;
4 )
ui_print_wrap "! Sony ELF64 format detected" ui_print_wrap "! Sony ELF64 format detected"
ui_print_wrap "! Stock kernel cannot be patched, please use a custom kernel" abort_wrap "! Stock kernel cannot be patched, please use a custom kernel"
exit 1
esac esac
########################################################################################## ##########################################################################################
@@ -108,28 +142,28 @@ esac
# Test patch status and do restore, after this section, ramdisk.cpio.orig is guaranteed to exist # Test patch status and do restore, after this section, ramdisk.cpio.orig is guaranteed to exist
ui_print_wrap "- Checking ramdisk status" ui_print_wrap "- Checking ramdisk status"
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --cpio-test ramdisk.cpio ./magiskboot --cpio-test ramdisk.cpio
case $? in case $? in
0 ) # Stock boot 0 ) # Stock boot
ui_print_wrap "- Stock boot image detected!" ui_print_wrap "- Stock boot image detected!"
ui_print_wrap "- Backing up stock boot image" ui_print_wrap "- Backing up stock boot image"
SHA1=`LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --sha1 $BOOTIMAGE | tail -n 1` SHA1=`./magiskboot --sha1 "$BOOTIMAGE" | tail -n 1`
STOCKDUMP=stock_boot_${SHA1}.img STOCKDUMP=stock_boot_${SHA1}.img
dd if=$BOOTIMAGE of=$STOCKDUMP dd if="$BOOTIMAGE" of=$STOCKDUMP
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --compress $STOCKDUMP ./magiskboot --compress $STOCKDUMP
cp -af ramdisk.cpio ramdisk.cpio.orig cp -af ramdisk.cpio ramdisk.cpio.orig
;; ;;
1 ) # Magisk patched 1 ) # Magisk patched
ui_print_wrap "- Magisk patched image detected!" ui_print_wrap "- Magisk patched image detected!"
# Find SHA1 of stock boot image # Find SHA1 of stock boot image
if [ -z $SHA1 ]; then if [ -z $SHA1 ]; then
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --cpio-extract ramdisk.cpio init.magisk.rc init.magisk.rc.old ./magiskboot --cpio-extract ramdisk.cpio init.magisk.rc init.magisk.rc.old
SHA1=`grep_prop "# STOCKSHA1" init.magisk.rc.old` SHA1=`grep_prop "# STOCKSHA1" init.magisk.rc.old`
rm -f init.magisk.rc.old rm -f init.magisk.rc.old
fi fi
OK=false OK=false
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --cpio-restore ramdisk.cpio ./magiskboot --cpio-restore ramdisk.cpio
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
ui_print_wrap "- Ramdisk restored from internal backup" ui_print_wrap "- Ramdisk restored from internal backup"
OK=true OK=true
@@ -141,8 +175,8 @@ case $? in
STOCKDUMP=/data/stock_boot_${SHA1}.img STOCKDUMP=/data/stock_boot_${SHA1}.img
if [ -f ${STOCKDUMP}.gz ]; then if [ -f ${STOCKDUMP}.gz ]; then
ui_print_wrap "- Stock boot image backup found" ui_print_wrap "- Stock boot image backup found"
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --decompress ${STOCKDUMP}.gz stock_boot.img ./magiskboot --decompress ${STOCKDUMP}.gz stock_boot.img
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --unpack stock_boot.img ./magiskboot --unpack stock_boot.img
rm -f stock_boot.img rm -f stock_boot.img
OK=true OK=true
fi fi
@@ -156,8 +190,7 @@ case $? in
;; ;;
2 ) # Other patched 2 ) # Other patched
ui_print_wrap "! Boot image patched by other programs!" ui_print_wrap "! Boot image patched by other programs!"
ui_print_wrap "! Please restore stock boot image" abort_wrap "! Please restore stock boot image"
exit 1
;; ;;
esac esac
@@ -167,20 +200,12 @@ esac
ui_print_wrap "- Patching ramdisk" ui_print_wrap "- Patching ramdisk"
# The common patches
$KEEPVERITY || LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --cpio-patch-dmverity ramdisk.cpio
$KEEPFORCEENCRYPT || LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --cpio-patch-forceencrypt ramdisk.cpio
# Add magisk entrypoint # Add magisk entrypoint
cpio_extract init.rc init.rc ./magiskboot --cpio-patch ramdisk.cpio $KEEPVERITY $KEEPFORCEENCRYPT
grep "import /init.magisk.rc" init.rc >/dev/null || sed -i '1,/.*import.*/s/.*import.*/import \/init.magisk.rc\n&/' init.rc
sed -i "/selinux.reload_policy/d" init.rc
cpio_add 750 init.rc init.rc
rm -f init.rc
# sepolicy patches # sepolicy patches
cpio_extract sepolicy sepolicy cpio_extract sepolicy sepolicy
LD_LIBRARY_PATH=$SYSTEMLIB ./magisk magiskpolicy --load sepolicy --save sepolicy --minimal ./magisk magiskpolicy --load sepolicy --save sepolicy --minimal
cpio_add 644 sepolicy sepolicy cpio_add 644 sepolicy sepolicy
rm -f sepolicy rm -f sepolicy
@@ -190,11 +215,11 @@ if [ ! -z $SHA1 ]; then
echo "# STOCKSHA1=$SHA1" >> init.magisk.rc echo "# STOCKSHA1=$SHA1" >> init.magisk.rc
fi fi
cpio_add 750 init.magisk.rc init.magisk.rc cpio_add 750 init.magisk.rc init.magisk.rc
[ -f init.magisk.rc.bak ] && mv init.magisk.rc.bak init.magisk.rc mv init.magisk.rc.bak init.magisk.rc 2>/dev/null
cpio_add 755 sbin/magisk magisk cpio_add 755 sbin/magisk magisk
# Create ramdisk backups # Create ramdisk backups
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --cpio-backup ramdisk.cpio ramdisk.cpio.orig ./magiskboot --cpio-backup ramdisk.cpio ramdisk.cpio.orig
rm -f ramdisk.cpio.orig rm -f ramdisk.cpio.orig
@@ -205,16 +230,23 @@ rm -f ramdisk.cpio.orig
# Hexpatches # Hexpatches
# Remove Samsung RKP in stock kernel # Remove Samsung RKP in stock kernel
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --hexpatch kernel \ ./magiskboot --hexpatch kernel \
49010054011440B93FA00F71E9000054010840B93FA00F7189000054001840B91FA00F7188010054 \ 49010054011440B93FA00F71E9000054010840B93FA00F7189000054001840B91FA00F7188010054 \
A1020054011440B93FA00F7140020054010840B93FA00F71E0010054001840B91FA00F7181010054 A1020054011440B93FA00F7140020054010840B93FA00F71E0010054001840B91FA00F7181010054
ui_print_wrap "- Repacking boot image" ui_print_wrap "- Repacking boot image"
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --repack $BOOTIMAGE ./magiskboot --repack "$BOOTIMAGE" || abort_wrap "! Unable to repack boot image!"
if [ $? -ne 0 ]; then # Sign chromeos boot
ui_print_wrap "! Unable to repack boot image!" if $CHROMEOS; then
exit 1 echo > empty
./chromeos/futility vbutil_kernel --pack new-boot.img.signed \
--keyblock ./chromeos/kernel.keyblock --signprivate ./chromeos/kernel_data_key.vbprivk \
--version 1 --vmlinuz new-boot.img --config empty --arch arm --bootloader empty --flags 0x1
rm -f empty new-boot.img
mv new-boot.img.signed new-boot.img
fi fi
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --cleanup ./magiskboot --cleanup

View File

@@ -9,167 +9,41 @@
# #
########################################################################################## ##########################################################################################
##########################################################################################
# Preparation
##########################################################################################
# Detect whether in boot mode # Detect whether in boot mode
ps | grep zygote | grep -v grep >/dev/null && BOOTMODE=true || BOOTMODE=false ps | grep zygote | grep -v grep >/dev/null && BOOTMODE=true || BOOTMODE=false
$BOOTMODE || ps -A | grep zygote | grep -v grep >/dev/null && BOOTMODE=true $BOOTMODE || ps -A 2>/dev/null | grep zygote | grep -v grep >/dev/null && BOOTMODE=true
# This path should work in any cases # This path should work in any cases
TMPDIR=/dev/tmp TMPDIR=/dev/tmp
INSTALLER=$TMPDIR/magisk INSTALLER=$TMPDIR/install
COMMONDIR=$INSTALLER/common COMMONDIR=$INSTALLER/common
BOOTTMP=$TMPDIR/boottmp
COREDIR=/magisk/.core
CHROMEDIR=$INSTALLER/chromeos CHROMEDIR=$INSTALLER/chromeos
COREDIR=/magisk/.core
# Default permissions # Default permissions
umask 022 umask 022
##########################################################################################
# Flashable update-binary preparation
##########################################################################################
OUTFD=$2 OUTFD=$2
ZIP=$3 ZIP=$3
readlink /proc/$$/fd/$OUTFD 2>/dev/null | grep /tmp >/dev/null rm -rf $TMPDIR 2>/dev/null
if [ "$?" -eq "0" ]; then mkdir -p $INSTALLER
OUTFD=0 unzip -o "$ZIP" -d $INSTALLER 2>/dev/null
for FD in `ls /proc/$$/fd`; do if [ ! -d "$COMMONDIR" ]; then
readlink /proc/$$/fd/$FD 2>/dev/null | grep pipe >/dev/null echo "! Unable to extract zip file!"
if [ "$?" -eq "0" ]; then exit 1
ps | grep " 3 $FD " | grep -v grep >/dev/null
if [ "$?" -eq "0" ]; then
OUTFD=$FD
break
fi
fi
done
fi fi
mkdir -p $INSTALLER # Load utility fuctions
cd $INSTALLER . $COMMONDIR/util_functions.sh
unzip -o "$ZIP"
########################################################################################## get_outfd
# Functions
##########################################################################################
ui_print() {
if $BOOTMODE; then
echo "$1"
else
echo -n -e "ui_print $1\n" >> /proc/self/fd/$OUTFD
echo -n -e "ui_print\n" >> /proc/self/fd/$OUTFD
fi
}
getvar() {
local VARNAME=$1
local VALUE=$(eval echo \$"$VARNAME");
for FILE in /dev/.magisk /data/.magisk /cache/.magisk /system/.magisk; do
if [ -z "$VALUE" ]; then
LINE=$(cat $FILE 2>/dev/null | grep "$VARNAME=")
if [ ! -z "$LINE" ]; then
VALUE=${LINE#*=}
fi
fi
done
eval $VARNAME=\$VALUE
}
find_boot_image() {
if [ -z "$BOOTIMAGE" ]; then
for PARTITION in kern-a KERN-A android_boot ANDROID_BOOT kernel KERNEL boot BOOT lnx LNX; do
BOOTIMAGE=`readlink /dev/block/by-name/$PARTITION || readlink /dev/block/platform/*/by-name/$PARTITION || readlink /dev/block/platform/*/*/by-name/$PARTITION`
if [ ! -z "$BOOTIMAGE" ]; then break; fi
done
fi
if [ -z "$BOOTIMAGE" ]; then
FSTAB="/etc/recovery.fstab"
[ ! -f "$FSTAB" ] && FSTAB="/etc/recovery.fstab.bak"
[ -f "$FSTAB" ] && BOOTIMAGE=`grep -E '\b/boot\b' "$FSTAB" | grep -oE '/dev/[a-zA-Z0-9_./-]*'`
fi
}
is_mounted() {
if [ ! -z "$2" ]; then
cat /proc/mounts | grep $1 | grep $2, >/dev/null
else
cat /proc/mounts | grep $1 >/dev/null
fi
return $?
}
mount_image() {
if [ ! -d "$2" ]; then
mount -o rw,remount rootfs /
mkdir -p $2 2>/dev/null
($BOOTMODE) && mount -o ro,remount rootfs /
[ ! -d "$2" ] && return 1
fi
if (! is_mounted $2); then
LOOPDEVICE=
for LOOP in 0 1 2 3 4 5 6 7; do
if (! is_mounted $2); then
LOOPDEVICE=/dev/block/loop$LOOP
if [ ! -f "$LOOPDEVICE" ]; then
mknod $LOOPDEVICE b 7 $LOOP 2>/dev/null
fi
losetup $LOOPDEVICE $1
if [ "$?" -eq "0" ]; then
mount -t ext4 -o loop $LOOPDEVICE $2
if (! is_mounted $2); then
/system/bin/toolbox mount -t ext4 -o loop $LOOPDEVICE $2
fi
if (! is_mounted $2); then
/system/bin/toybox mount -t ext4 -o loop $LOOPDEVICE $2
fi
fi
if (is_mounted $2); then
ui_print "- Mounting $1 to $2"
break;
fi
fi
done
fi
}
grep_prop() {
REGEX="s/^$1=//p"
shift
FILES=$@
if [ -z "$FILES" ]; then
FILES='/system/build.prop'
fi
cat $FILES 2>/dev/null | sed -n "$REGEX" | head -n 1
}
remove_system_su() {
if [ -f /system/bin/su -o -f /system/xbin/su ] && [ ! -f /su/bin/su ]; then
ui_print "! System installed root detected, mount rw :("
mount -o rw,remount /system
# SuperSU
if [ -e /system/bin/.ext/.su ]; then
mv -f /system/bin/app_process32_original /system/bin/app_process32 2>/dev/null
mv -f /system/bin/app_process64_original /system/bin/app_process64 2>/dev/null
mv -f /system/bin/install-recovery_original.sh /system/bin/install-recovery.sh 2>/dev/null
cd /system/bin
if [ -e app_process64 ]; then
ln -sf app_process64 app_process
else
ln -sf app_process32 app_process
fi
fi
rm -rf /system/.pin /system/bin/.ext /system/etc/.installed_su_daemon /system/etc/.has_su_daemon \
/system/xbin/daemonsu /system/xbin/su /system/xbin/sugote /system/xbin/sugote-mksh /system/xbin/supolicy \
/system/bin/app_process_init /system/bin/su /cache/su /system/lib/libsupol.so /system/lib64/libsupol.so \
/system/su.d /system/etc/install-recovery.sh /system/etc/init.d/99SuperSUDaemon /cache/install-recovery.sh \
/system/.supersu /cache/.supersu /data/.supersu \
/system/app/Superuser.apk /system/app/SuperSU /cache/Superuser.apk 2>/dev/null
fi
}
########################################################################################## ##########################################################################################
# Detection # Detection
@@ -179,59 +53,34 @@ ui_print "************************"
ui_print "* MAGISK_VERSION_STUB" ui_print "* MAGISK_VERSION_STUB"
ui_print "************************" ui_print "************************"
if [ ! -d "$COMMONDIR" ]; then ui_print "- Mounting /system, /vendor, /cache, /data"
ui_print "! Failed: Unable to extract zip file!"
exit 1
fi
ui_print "- Mounting /system(ro), /cache, /data"
mount -o ro /system 2>/dev/null mount -o ro /system 2>/dev/null
mount -o ro /vendor 2>/dev/null
mount /cache 2>/dev/null mount /cache 2>/dev/null
mount /data 2>/dev/null mount /data 2>/dev/null
if [ ! -f '/system/build.prop' ]; then [ -f /system/build.prop ] || abort "! /system could not be mounted!"
ui_print "! Failed: /system could not be mounted!"
exit 1
fi
# read override variables # read override variables
getvar KEEPVERITY getvar KEEPVERITY
getvar KEEPFORCEENCRYPT getvar KEEPFORCEENCRYPT
getvar BOOTIMAGE getvar BOOTIMAGE
# Detect version and architecture
api_level_arch_detect
[ $API -lt 21 ] && abort "! Magisk is only for Lollipop 5.0+ (SDK 21+)"
# Check if system root is installed and remove # Check if system root is installed and remove
remove_system_su remove_system_su
API=`grep_prop ro.build.version.sdk`
ABI=`grep_prop ro.product.cpu.abi | cut -c-3`
ABI2=`grep_prop ro.product.cpu.abi2 | cut -c-3`
ABILONG=`grep_prop ro.product.cpu.abi`
ARCH=arm
IS64BIT=false
if [ "$ABI" = "x86" ]; then ARCH=x86; fi;
if [ "$ABI2" = "x86" ]; then ARCH=x86; fi;
if [ "$ABILONG" = "arm64-v8a" ]; then ARCH=arm64; IS64BIT=true; fi;
if [ "$ABILONG" = "x86_64" ]; then ARCH=x64; IS64BIT=true; fi;
if [ "$API" -lt "21" ]; then
ui_print "! Magisk is only for Lollipop 5.0+ (SDK 21+)"
exit 1
fi
ui_print "- Device platform: $ARCH" ui_print "- Device platform: $ARCH"
BINDIR=$INSTALLER/$ARCH BINDIR=$INSTALLER/$ARCH
chmod -R 755 $CHROMEDIR $BINDIR chmod -R 755 $CHROMEDIR $BINDIR
$IS64BIT && SYSTEMLIB=/system/lib64 || SYSTEMLIB=/system/lib
find_boot_image find_boot_image
if [ -z $BOOTIMAGE ]; then [ -z $BOOTIMAGE ] && abort "! Unable to detect boot image"
ui_print "! Unable to detect boot image"
exit 1
fi
########################################################################################## ##########################################################################################
# Environment # Environment
@@ -245,16 +94,25 @@ is_mounted /data && MAGISKBIN=/data/magisk || MAGISKBIN=/cache/data_bin
rm -rf $MAGISKBIN 2>/dev/null rm -rf $MAGISKBIN 2>/dev/null
mkdir -p $MAGISKBIN mkdir -p $MAGISKBIN
cp -af $BINDIR/. $COMMONDIR/. $MAGISKBIN cp -af $BINDIR/. $COMMONDIR/. $MAGISKBIN
cp -af $CHROMEDIR $MAGISKBIN
chmod -R 755 $MAGISKBIN chmod -R 755 $MAGISKBIN
chcon -hR u:object_r:system_file:s0 $MAGISKBIN
# addon.d
if [ -d /system/addon.d ]; then
ui_print "- Adding addon.d survival script"
mount -o rw,remount /system
cp $INSTALLER/addon.d/99-magisk.sh /system/addon.d/99-magisk.sh
chmod 755 /system/addon.d/99-magisk.sh
fi
########################################################################################## ##########################################################################################
# Magisk Image # Magisk Image
########################################################################################## ##########################################################################################
$BOOTMODE || recovery_actions
# Fix SuperSU..... # Fix SuperSU.....
$BOOTMODE && $BINDIR/magiskpolicy --live "allow fsck * * *" $BOOTMODE && $MAGISKBIN/magisk magiskpolicy --live "allow fsck * * *"
if (is_mounted /data); then if (is_mounted /data); then
IMG=/data/magisk.img IMG=/data/magisk.img
@@ -267,21 +125,20 @@ if [ -f $IMG ]; then
ui_print "- $IMG detected!" ui_print "- $IMG detected!"
else else
ui_print "- Creating $IMG" ui_print "- Creating $IMG"
$BINDIR/magisk --createimg $IMG 64M $MAGISKBIN/magisk --createimg $IMG 64M
fi fi
mount_image $IMG /magisk if ! is_mounted /magisk; then
if (! is_mounted /magisk); then ui_print "- Mounting $IMG to /magisk"
ui_print "! Magisk image mount failed..." MAGISKLOOP=`$MAGISKBIN/magisk --mountimg $IMG /magisk`
exit 1
fi fi
MAGISKLOOP=$LOOPDEVICE is_mounted /magisk || abort "! Magisk image mount failed..."
# Core folders # Core folders
mkdir -p $COREDIR/props $COREDIR/post-fs-data.d $COREDIR/service.d 2>/dev/null mkdir -p $COREDIR/props $COREDIR/post-fs-data.d $COREDIR/service.d 2>/dev/null
chmod -R 755 $COREDIR/post-fs-data.d $COREDIR/service.d chmod 755 $COREDIR/post-fs-data.d $COREDIR/service.d
chown -R 0.0 $COREDIR/post-fs-data.d $COREDIR/service.d chown 0.0 $COREDIR/post-fs-data.d $COREDIR/service.d
# Legacy cleanup # Legacy cleanup
mv $COREDIR/magiskhide/hidelist $COREDIR/hidelist 2>/dev/null mv $COREDIR/magiskhide/hidelist $COREDIR/hidelist 2>/dev/null
@@ -295,51 +152,37 @@ ui_print "- Found Boot Image: $BOOTIMAGE"
# Update our previous backup to new format if exists # Update our previous backup to new format if exists
if [ -f /data/stock_boot.img ]; then if [ -f /data/stock_boot.img ]; then
SHA1=`LD_LIBRARY_PATH=$SYSTEMLIB $BINDIR/magiskboot --sha1 /data/stock_boot.img | tail -n 1` SHA1=`$MAGISKBIN/magiskboot --sha1 /data/stock_boot.img | tail -n 1`
STOCKDUMP=/data/stock_boot_${SHA1}.img STOCKDUMP=/data/stock_boot_${SHA1}.img
mv /data/stock_boot.img $STOCKDUMP mv /data/stock_boot.img $STOCKDUMP
LD_LIBRARY_PATH=$SYSTEMLIB $BINDIR/magiskboot --compress $STOCKDUMP $MAGISKBIN/magiskboot --compress $STOCKDUMP
fi fi
SOURCEDMODE=true SOURCEDMODE=true
cd $MAGISKBIN cd $MAGISKBIN
# Source the boot patcher # Source the boot patcher
. $COMMONDIR/boot_patch.sh $BOOTIMAGE . $COMMONDIR/boot_patch.sh "$BOOTIMAGE"
# Sign chromeos boot if [ -f stock_boot* ]; then
if [ -f chromeos ]; then rm -f /data/stock_boot* 2>/dev/null
echo > empty
LD_LIBRARY_PATH=$SYSTEMLIB $CHROMEDIR/futility vbutil_kernel --pack new-boot.img.signed \
--keyblock $CHROMEDIR/kernel.keyblock --signprivate $CHROMEDIR/kernel_data_key.vbprivk \
--version 1 --vmlinuz new-boot.img --config empty --arch arm --bootloader empty --flags 0x1
rm -f empty new-boot.img
mv new-boot.img.signed new-boot.img
fi
if is_mounted /data; then
rm -f /data/stock_boot*
mv stock_boot* /data mv stock_boot* /data
fi fi
ui_print "- Flashing new boot image" ui_print "- Flashing new boot image"
if [ -L $BOOTIMAGE ]; then if [ -L "$BOOTIMAGE" ]; then
dd if=new-boot.img of=$BOOTIMAGE bs=4096 dd if=new-boot.img of="$BOOTIMAGE" bs=4096
else else
cat new-boot.img /dev/zero | dd of=$BOOTIMAGE bs=4096 cat new-boot.img /dev/zero | dd of="$BOOTIMAGE" bs=4096 >/dev/null 2>&1
fi fi
rm -f new-boot.img rm -f new-boot.img
cd / cd /
if ! $BOOTMODE; then if ! $BOOTMODE; then
ui_print "- Unmounting partitions" $MAGISKBIN/magisk --umountimg /magisk $MAGISKLOOP
umount /magisk
losetup -d $MAGISKLOOP 2>/dev/null
rmdir /magisk rmdir /magisk
umount /system recovery_cleanup
fi fi
ui_print "- Done" ui_print "- Done"

View File

@@ -8,120 +8,103 @@
# The Magisk main binary will pick up the script, and uninstall itself, following a reboot # The Magisk main binary will pick up the script, and uninstall itself, following a reboot
# This script can also be used in flashable zip with the uninstaller_loader.sh # This script can also be used in flashable zip with the uninstaller_loader.sh
# #
# This script will try to do restoration in the following order: # This script will try to do restoration with the following:
# 1. Find and restore the original stock boot image dump (OTA proof) # 1-1. Find and restore the original stock boot image dump (OTA proof)
# 2. Restore ramdisk from the internal backup (ramdisk fully restored, not OTA friendly) # 1-2. If 1-1 fails, restore ramdisk from the internal backup
# 3. Remove added files in ramdisk, modified files are remained intact. By doing so, Magisk # (ramdisk fully restored, not OTA friendly)
# will not be started at boot, but not removed clean enough # 1-3. If 1-2 fails, it will remove added files in ramdisk, however modified files
# # are remained modified, because we have no backups. By doing so, Magisk will
# Finally, this uninstaller will remove all Magisk related files # not be started at boot, but this isn't actually 100% cleaned up
# 2. Remove all Magisk related files
# (The list is LARGE, most likely due to bad decision in early versions # (The list is LARGE, most likely due to bad decision in early versions
# the latest versions has much less bloat to cleanup) # the latest versions has much less bloat to cleanup)
# #
########################################################################################## ##########################################################################################
[ -z $BOOTMODE ] && BOOTMODE=false
MAGISKBIN=/data/magisk
CHROMEDIR=$MAGISKBIN/chromeos
[ -d /system/lib64 ] && SYSTEMLIB=/system/lib64 || SYSTEMLIB=/system/lib
# Default permissions
umask 022
# Call ui_print_wrap if exists, or else simply use echo # Call ui_print_wrap if exists, or else simply use echo
# Useful when wrapped in flashable zip # Useful when wrapped in flashable zip
ui_print_wrap() { ui_print_wrap() {
type ui_print >/dev/null 2>&1 && ui_print "$1" || echo "$1" type ui_print >/dev/null 2>&1 && ui_print "$1" || echo "$1"
} }
grep_prop() { # Call abort if exists, or else show error message and exit
REGEX="s/^$1=//p" # Essential when wrapped in flashable zip
shift abort_wrap() {
FILES=$@ type abort >/dev/null 2>&1
if [ -z "$FILES" ]; then if [ $? -ne 0 ]; then
FILES='/system/build.prop' ui_print_wrap "$1"
fi exit 1
cat $FILES 2>/dev/null | sed -n "$REGEX" | head -n 1 else
} abort "$1"
find_boot_image() {
if [ -z "$BOOTIMAGE" ]; then
for PARTITION in kern-a KERN-A android_boot ANDROID_BOOT kernel KERNEL boot BOOT lnx LNX; do
BOOTIMAGE=`readlink /dev/block/by-name/$PARTITION || readlink /dev/block/platform/*/by-name/$PARTITION || readlink /dev/block/platform/*/*/by-name/$PARTITION`
if [ ! -z "$BOOTIMAGE" ]; then break; fi
done
fi
if [ -z "$BOOTIMAGE" ]; then
FSTAB="/etc/recovery.fstab"
[ ! -f "$FSTAB" ] && FSTAB="/etc/recovery.fstab.bak"
[ -f "$FSTAB" ] && BOOTIMAGE=`grep -E '\b/boot\b' "$FSTAB" | grep -oE '/dev/[a-zA-Z0-9_./-]*'`
fi fi
} }
# Environments if [ ! -d $MAGISKBIN -o ! -f $MAGISKBIN/magiskboot -o ! -f $MAGISKBIN/util_functions.sh ]; then
# Set permissions ui_print_wrap "! Cannot find $MAGISKBIN"
chmod -R 755 $CHROMEDIR/futility $MAGISKBIN 2>/dev/null exit 1
fi
[ -z $BOOTMODE ] && BOOTMODE=false
MAGISKBIN=/data/magisk
CHROMEDIR=$MAGISKBIN/chromeos
# Default permissions
umask 022
# Load utility functions
. $MAGISKBIN/util_functions.sh
# Find the boot image # Find the boot image
find_boot_image find_boot_image
if [ -z "$BOOTIMAGE" ]; then [ -z $BOOTIMAGE ] && abort "! Unable to detect boot image"
ui_print_wrap "! Unable to detect boot image"
exit 1
fi
ui_print_wrap "- Found Boot Image: $BOOTIMAGE" ui_print_wrap "- Found Boot Image: $BOOTIMAGE"
cd $MAGISKBIN cd $MAGISKBIN
ui_print_wrap "- Unpacking boot image" ui_print_wrap "- Unpacking boot image"
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --unpack $BOOTIMAGE ./magiskboot --unpack "$BOOTIMAGE"
if [ $? -ne 0 ]; then [ $? -ne 0 ] && abort_wrap "! Unable to unpack boot image"
ui_print_wrap "! Unable to unpack boot image"
exit 1
fi
# Update our previous backups to new format if exists # Update our previous backup to new format if exists
if [ -f /data/stock_boot.img ]; then if [ -f /data/stock_boot.img ]; then
SHA1=`LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --sha1 /data/stock_boot.img | tail -n 1` SHA1=`./magiskboot --sha1 /data/stock_boot.img | tail -n 1`
STOCKDUMP=/data/stock_boot_${SHA1}.img STOCKDUMP=/data/stock_boot_${SHA1}.img
mv /data/stock_boot.img $STOCKDUMP mv /data/stock_boot.img $STOCKDUMP
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --compress $STOCKDUMP ./magiskboot --compress $STOCKDUMP
fi fi
# Detect boot image state # Detect boot image state
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --cpio-test ramdisk.cpio ./magiskboot --cpio-test ramdisk.cpio
case $? in case $? in
0 ) 0 ) # Stock boot
ui_print_wrap "- Stock boot image detected!" ui_print_wrap "- Stock boot image detected!"
ui_print_wrap "! Magisk is not installed!" ui_print_wrap "! Magisk is not installed!"
exit exit
;; ;;
1 ) 1 ) # Magisk patched
ui_print_wrap "- Magisk patched image detected!" ui_print_wrap "- Magisk patched image detected!"
# Find SHA1 of stock boot image # Find SHA1 of stock boot image
if [ -z $SHA1 ]; then if [ -z $SHA1 ]; then
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --cpio-extract ramdisk.cpio init.magisk.rc init.magisk.rc.old ./magiskboot --cpio-extract ramdisk.cpio init.magisk.rc init.magisk.rc.old
SHA1=`grep_prop "# STOCKSHA1" init.magisk.rc.old` SHA1=`grep_prop "# STOCKSHA1" init.magisk.rc.old`
[ ! -z $SHA1 ] && STOCKDUMP=/data/stock_boot_${SHA1}.img
rm -f init.magisk.rc.old rm -f init.magisk.rc.old
fi fi
[ ! -z $SHA1 ] && STOCKDUMP=/data/stock_boot_${SHA1}.img
if [ -f ${STOCKDUMP}.gz ]; then if [ -f ${STOCKDUMP}.gz ]; then
ui_print_wrap "- Boot image backup found!" ui_print_wrap "- Boot image backup found!"
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --decompress ${STOCKDUMP}.gz stock_boot.img ./magiskboot --decompress ${STOCKDUMP}.gz stock_boot.img
else else
ui_print_wrap "! Boot image backup unavailable" ui_print_wrap "! Boot image backup unavailable"
ui_print_wrap "- Restoring ramdisk with backup" ui_print_wrap "- Restoring ramdisk with backup"
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --cpio-restore ramdisk.cpio ./magiskboot --cpio-restore ramdisk.cpio
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --repack $BOOTIMAGE stock_boot.img ./magiskboot --repack $BOOTIMAGE stock_boot.img
fi fi
;; ;;
2 ) # Other patched 2 ) # Other patched
ui_print_wrap "! Boot image patched by other programs!" ui_print_wrap "! Boot image patched by other programs!"
ui_print_wrap "! Cannot uninstall with this uninstaller" abort_wrap "! Cannot uninstall with this uninstaller"
exit 1
;; ;;
esac esac
@@ -138,10 +121,10 @@ if [ -f chromeos ]; then
fi fi
ui_print_wrap "- Flashing stock/reverted image" ui_print_wrap "- Flashing stock/reverted image"
if [ -L $BOOTIMAGE ]; then if [ -L "$BOOTIMAGE" ]; then
dd if=stock_boot.img of=$BOOTIMAGE bs=4096 dd if=stock_boot.img of="$BOOTIMAGE" bs=4096
else else
cat stock_boot.img /dev/zero | dd of=$BOOTIMAGE bs=4096 cat stock_boot.img /dev/zero | dd of="$BOOTIMAGE" bs=4096 >/dev/null 2>&1
fi fi
rm -f stock_boot.img rm -f stock_boot.img

View File

@@ -8,100 +8,49 @@
# #
########################################################################################## ##########################################################################################
INSTALLER=/tmp/uninstall ##########################################################################################
# Preparation
##########################################################################################
BOOTMODE=false
INSTALLER=/tmp/uninstall
# Default permissions # Default permissions
umask 022 umask 022
##########################################################################################
# Flashable update-binary preparation
##########################################################################################
OUTFD=$2 OUTFD=$2
ZIP=$3 ZIP=$3
readlink /proc/$$/fd/$OUTFD 2>/dev/null | grep /tmp >/dev/null rm -rf $INSTALLER 2>/dev/null
if [ "$?" -eq "0" ]; then mkdir -p $INSTALLER
OUTFD=0 unzip -o "$ZIP" -d $INSTALLER 2>/dev/null
for FD in `ls /proc/$$/fd`; do if [ ! -f $INSTALLER/util_functions.sh ]; then
readlink /proc/$$/fd/$FD 2>/dev/null | grep pipe >/dev/null echo "! Failed: Unable to extract zip file!"
if [ "$?" -eq "0" ]; then exit 1
ps | grep " 3 $FD " | grep -v grep >/dev/null
if [ "$?" -eq "0" ]; then
OUTFD=$FD
break
fi
fi
done
fi fi
mkdir -p $INSTALLER # Load utility functions
cd $INSTALLER . $INSTALLER/util_functions.sh
unzip -o "$ZIP"
########################################################################################## get_outfd
# Functions
##########################################################################################
ui_print() {
echo -n -e "ui_print $1\n" >> /proc/self/fd/$OUTFD
echo -n -e "ui_print\n" >> /proc/self/fd/$OUTFD
}
is_mounted() {
if [ ! -z "$2" ]; then
cat /proc/mounts | grep $1 | grep $2, >/dev/null
else
cat /proc/mounts | grep $1 >/dev/null
fi
return $?
}
grep_prop() {
REGEX="s/^$1=//p"
shift
FILES=$@
if [ -z "$FILES" ]; then
FILES='/system/build.prop'
fi
cat $FILES 2>/dev/null | sed -n $REGEX | head -n 1
}
########################################################################################## ##########################################################################################
# Main # Main
########################################################################################## ##########################################################################################
ui_print "*****************************" ui_print "************************"
ui_print " Magisk Uninstaller " ui_print " Magisk Uninstaller "
ui_print "*****************************" ui_print "************************"
if [ ! -d "$INSTALLER/arm" ]; then ui_print "- Mounting /system, /vendor, /cache, /data"
ui_print "! Failed: Unable to extract zip file!"
exit 1
fi
ui_print "- Mounting /system(ro), /cache, /data"
mount -o ro /system 2>/dev/null mount -o ro /system 2>/dev/null
mount -o ro /vendor 2>/dev/null
mount /cache 2>/dev/null mount /cache 2>/dev/null
mount /data 2>/dev/null mount /data 2>/dev/null
if [ ! -f '/system/build.prop' ]; then [ -f /system/build.prop ] || abort "! /system could not be mounted!"
ui_print "! Failed: /system could not be mounted!"
exit 1
fi
API=`grep_prop ro.build.version.sdk` api_level_arch_detect
ABI=`grep_prop ro.product.cpu.abi | cut -c-3`
ABI2=`grep_prop ro.product.cpu.abi2 | cut -c-3`
ABILONG=`grep_prop ro.product.cpu.abi`
ARCH=arm
IS64BIT=false
if [ "$ABI" = "x86" ]; then ARCH=x86; fi;
if [ "$ABI2" = "x86" ]; then ARCH=x86; fi;
if [ "$ABILONG" = "arm64-v8a" ]; then ARCH=arm64; IS64BIT=true; fi;
if [ "$ABILONG" = "x86_64" ]; then ARCH=x64; IS64BIT=true; fi;
ui_print "- Device platform: $ARCH" ui_print "- Device platform: $ARCH"
CHROMEDIR=$INSTALLER/chromeos CHROMEDIR=$INSTALLER/chromeos
@@ -111,12 +60,20 @@ BINDIR=$INSTALLER/$ARCH
# Detection all done, start installing # Detection all done, start installing
########################################################################################## ##########################################################################################
if (is_mounted /data); then MAGISKBIN=/data/magisk
if is_mounted /data; then
# Copy the binaries to /data/magisk, in case they do not exist # Copy the binaries to /data/magisk, in case they do not exist
rm -rf /data/magisk 2>/dev/null rm -rf $MAGISKBIN 2>/dev/null
mkdir -p /data/magisk 2>/dev/null mkdir -p $MAGISKBIN
cp -af $BINDIR/. $CHROMEDIR /data/magisk cp -af $BINDIR/. $MAGISKBIN
cp -af $CHROMEDIR $MAGISKBIN
cp -af $INSTALLER/util_functions.sh $MAGISKBIN
chmod -R 755 $MAGISKBIN
# Run the acttual uninstallation
recovery_actions
. $INSTALLER/magisk_uninstaller.sh . $INSTALLER/magisk_uninstaller.sh
recovery_cleanup
else else
ui_print "! Data unavailable" ui_print "! Data unavailable"
ui_print "! Placing uninstall script to /cache" ui_print "! Placing uninstall script to /cache"
@@ -128,6 +85,5 @@ else
reboot reboot
fi fi
umount /system
ui_print "- Done" ui_print "- Done"
exit 0 exit 0

194
scripts/util_functions.sh Normal file
View File

@@ -0,0 +1,194 @@
##########################################################################################
#
# Magisk General Utility Functions
# by topjohnwu
#
# Used in flash_script.sh, addon.d.sh, magisk module installers, and uninstaller
#
##########################################################################################
MAGISK_VERSION_STUB
get_outfd() {
readlink /proc/$$/fd/$OUTFD 2>/dev/null | grep /tmp >/dev/null
if [ "$?" -eq "0" ]; then
OUTFD=0
for FD in `ls /proc/$$/fd`; do
readlink /proc/$$/fd/$FD 2>/dev/null | grep pipe >/dev/null
if [ "$?" -eq "0" ]; then
ps | grep " 3 $FD " | grep -v grep >/dev/null
if [ "$?" -eq "0" ]; then
OUTFD=$FD
break
fi
fi
done
fi
}
ui_print() {
if $BOOTMODE; then
echo "$1"
else
echo -n -e "ui_print $1\n" >> /proc/self/fd/$OUTFD
echo -n -e "ui_print\n" >> /proc/self/fd/$OUTFD
fi
}
getvar() {
local VARNAME=$1
local VALUE=$(eval echo \$"$VARNAME");
for FILE in /dev/.magisk /data/.magisk /cache/.magisk /system/.magisk; do
if [ -z "$VALUE" ]; then
LINE=$(cat $FILE 2>/dev/null | grep "$VARNAME=")
if [ ! -z "$LINE" ]; then
VALUE=${LINE#*=}
fi
fi
done
eval $VARNAME=\$VALUE
}
find_boot_image() {
if [ -z "$BOOTIMAGE" ]; then
for BLOCK in boot_a BOOT_A kern-a KERN-A android_boot ANDROID_BOOT kernel KERNEL boot BOOT lnx LNX; do
BOOTIMAGE=`ls /dev/block/by-name/$BLOCK || ls /dev/block/platform/*/by-name/$BLOCK || ls /dev/block/platform/*/*/by-name/$BLOCK` 2>/dev/null
[ ! -z $BOOTIMAGE ] && break
done
fi
# Recovery fallback
if [ -z "$BOOTIMAGE" ]; then
for FSTAB in /etc/*fstab*; do
BOOTIMAGE=`grep -E '\b/boot\b' $FSTAB | grep -v "#" | grep -oE '/dev/[a-zA-Z0-9_./-]*'`
[ ! -z $BOOTIMAGE ] && break
done
fi
[ -L "$BOOTIMAGE" ] && BOOTIMAGE=`readlink $BOOTIMAGE`
}
is_mounted() {
if [ ! -z "$2" ]; then
cat /proc/mounts | grep $1 | grep $2, >/dev/null
else
cat /proc/mounts | grep $1 >/dev/null
fi
return $?
}
grep_prop() {
REGEX="s/^$1=//p"
shift
FILES=$@
if [ -z "$FILES" ]; then
FILES='/system/build.prop'
fi
cat $FILES 2>/dev/null | sed -n "$REGEX" | head -n 1
}
remove_system_su() {
if [ -f /system/bin/su -o -f /system/xbin/su ] && [ ! -f /su/bin/su ]; then
ui_print "! System installed root detected, mount rw :("
mount -o rw,remount /system
# SuperSU
if [ -e /system/bin/.ext/.su ]; then
mv -f /system/bin/app_process32_original /system/bin/app_process32 2>/dev/null
mv -f /system/bin/app_process64_original /system/bin/app_process64 2>/dev/null
mv -f /system/bin/install-recovery_original.sh /system/bin/install-recovery.sh 2>/dev/null
cd /system/bin
if [ -e app_process64 ]; then
ln -sf app_process64 app_process
else
ln -sf app_process32 app_process
fi
fi
rm -rf /system/.pin /system/bin/.ext /system/etc/.installed_su_daemon /system/etc/.has_su_daemon \
/system/xbin/daemonsu /system/xbin/su /system/xbin/sugote /system/xbin/sugote-mksh /system/xbin/supolicy \
/system/bin/app_process_init /system/bin/su /cache/su /system/lib/libsupol.so /system/lib64/libsupol.so \
/system/su.d /system/etc/install-recovery.sh /system/etc/init.d/99SuperSUDaemon /cache/install-recovery.sh \
/system/.supersu /cache/.supersu /data/.supersu \
/system/app/Superuser.apk /system/app/SuperSU /cache/Superuser.apk 2>/dev/null
fi
}
api_level_arch_detect() {
API=`grep_prop ro.build.version.sdk`
ABI=`grep_prop ro.product.cpu.abi | cut -c-3`
ABI2=`grep_prop ro.product.cpu.abi2 | cut -c-3`
ABILONG=`grep_prop ro.product.cpu.abi`
ARCH=arm
IS64BIT=false
if [ "$ABI" = "x86" ]; then ARCH=x86; fi;
if [ "$ABI2" = "x86" ]; then ARCH=x86; fi;
if [ "$ABILONG" = "arm64-v8a" ]; then ARCH=arm64; IS64BIT=true; fi;
if [ "$ABILONG" = "x86_64" ]; then ARCH=x64; IS64BIT=true; fi;
}
recovery_actions() {
# TWRP bug fix
mount -o bind /dev/urandom /dev/random
# Temporarily block out all custom recovery binaries/libs
mv /sbin /sbin_tmp
# Add all possible library paths
OLD_LD_PATH=$LD_LIBRARY_PATH
$IS64BIT && export LD_LIBRARY_PATH=/system/lib64:/system/vendor/lib64 || export LD_LIBRARY_PATH=/system/lib:/system/vendor/lib
}
recovery_cleanup() {
mv /sbin_tmp /sbin
# Clear LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$OLD_LD_PATH
ui_print "- Unmounting partitions"
umount -l /system
umount -l /vendor 2>/dev/null
umount -l /dev/random
}
abort() {
ui_print "$1"
mv /sbin_tmp /sbin 2>/dev/null
exit 1
}
set_perm() {
chown $2:$3 $1 || exit 1
chmod $4 $1 || exit 1
if [ ! -z $5 ]; then
chcon $5 $1 2>/dev/null
else
chcon 'u:object_r:system_file:s0' $1 2>/dev/null
fi
}
set_perm_recursive() {
find $1 -type d 2>/dev/null | while read dir; do
set_perm $dir $2 $3 $4 $6
done
find $1 -type f 2>/dev/null | while read file; do
set_perm $file $2 $3 $5 $6
done
}
mktouch() {
mkdir -p ${1%/*}
if [ -z "$2" ]; then
touch $1
else
echo $2 > $1
fi
chmod 644 $1
}
request_size_check() {
reqSizeM=`du -s $1 | cut -f1`
reqSizeM=$((reqSizeM / 1024 + 1))
}
image_size_check() {
SIZE="`$MAGISKBIN/magisk --imgsize $IMG`"
curUsedM=`echo "$SIZE" | cut -d" " -f1`
curSizeM=`echo "$SIZE" | cut -d" " -f2`
curFreeM=$((curSizeM - curUsedM))
}

BIN
ziptools/apksigner.jar Normal file

Binary file not shown.