mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-12-11 10:52:21 +00:00
Compare commits
49 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a87ad35a50 | ||
|
|
cf56d7e4ed | ||
|
|
e33a5eb307 | ||
|
|
e5b704eb32 | ||
|
|
56457bd325 | ||
|
|
bdbb3c6657 | ||
|
|
c4d7001489 | ||
|
|
c07bac9a63 | ||
|
|
d27d04783f | ||
|
|
58de5a7ec7 | ||
|
|
504a9b4746 | ||
|
|
cccb5a3e08 | ||
|
|
d75fa62cab | ||
|
|
3d43c3c5bc | ||
|
|
b570b363d9 | ||
|
|
b9968aa1e6 | ||
|
|
c0d77808f6 | ||
|
|
9679492c28 | ||
|
|
f3b68e6543 | ||
|
|
0dcfaaf5ff | ||
|
|
ba513dcb9a | ||
|
|
ebabc60477 | ||
|
|
cf565d0145 | ||
|
|
52a23e7904 | ||
|
|
9e22b80714 | ||
|
|
7eed9c4a6d | ||
|
|
bf42fce17e | ||
|
|
9d421226a7 | ||
|
|
7b9be8369e | ||
|
|
7cf4b819ae | ||
|
|
9e1aea33c3 | ||
|
|
8767a88854 | ||
|
|
47c0084641 | ||
|
|
54e6a790cf | ||
|
|
2a86bc8695 | ||
|
|
04538372c6 | ||
|
|
9430ed66cd | ||
|
|
96f8efc27a | ||
|
|
a90e8b6112 | ||
|
|
561c1fb798 | ||
|
|
806fec7017 | ||
|
|
b3da28eade | ||
|
|
166f6412c2 | ||
|
|
1e877808bc | ||
|
|
1777d9f751 | ||
|
|
309b99eac0 | ||
|
|
a5aa1b3917 | ||
|
|
aced0632ec | ||
|
|
4e801788d7 |
Submodule MagiskManager updated: d3ff482c9b...1a69b16d36
58
build.py
58
build.py
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
bind_mount(buf, full_path);
|
if (node->status & IS_SKEL)
|
||||||
|
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,31 +378,22 @@ 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) {
|
if (node->status & IS_MODULE) {
|
||||||
snprintf(buf, PATH_MAX, "%s/%s/system/vendor", MOUNTPOINT, node->module);
|
// The real deal, mount module item
|
||||||
snprintf(buf2, PATH_MAX, "%s/%s/vendor", MOUNTPOINT, node->module);
|
real_path = get_full_path(node);
|
||||||
unlink(buf2);
|
snprintf(buf, PATH_MAX, "%s/%s%s", MOUNTPOINT, node->module, real_path);
|
||||||
symlink(buf, buf2);
|
bind_mount(buf, real_path);
|
||||||
return;
|
free(real_path);
|
||||||
}
|
} else if (node->status & IS_SKEL) {
|
||||||
|
// The node is labeled to be cloned with skeleton, lets do it
|
||||||
if (node->status) {
|
clone_skeleton(node);
|
||||||
if (node->status & IS_MODULE) {
|
} else if (node->status & IS_INTER) {
|
||||||
// The real deal, mount module item
|
|
||||||
real_path = get_full_path(node);
|
|
||||||
snprintf(buf, PATH_MAX, "%s/%s%s", MOUNTPOINT, node->module, real_path);
|
|
||||||
bind_mount(buf, real_path);
|
|
||||||
free(real_path);
|
|
||||||
} else if (node->status & IS_SKEL) {
|
|
||||||
// The node is labeled to be cloned with skeleton, lets do it
|
|
||||||
clone_skeleton(node);
|
|
||||||
}
|
|
||||||
// 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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
waitpid(log_pid, NULL, 0);
|
if (log_pid > 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
13
jni/external/Android.mk
vendored
Normal 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
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
511
jni/external/selinux/avc.h
vendored
Normal 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
50
jni/external/selinux/context.h
vendored
Normal 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
118
jni/external/selinux/flask.h
vendored
Normal 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
82
jni/external/selinux/get_context_list.h
vendored
Normal 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
23
jni/external/selinux/get_default_type.h
vendored
Normal 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
190
jni/external/selinux/label.h
vendored
Normal 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
187
jni/external/selinux/restorecon.h
vendored
Normal 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
673
jni/external/selinux/selinux.h
vendored
Normal 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
355
jni/external/selinux_stub.c
vendored
Normal 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
676
jni/external/sqlite3_stub.c
vendored
Normal 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; }
|
||||||
@@ -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[]);
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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
310
jni/magiskboot/bootimg.c
Normal 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);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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,47 +221,109 @@ 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) {
|
||||||
cpio_file *f;
|
struct list_head *head = xmalloc(sizeof(*head));
|
||||||
size_t read, write;
|
line_list *line;
|
||||||
int skip;
|
init_list_head(head);
|
||||||
vec_for_each(v, f) {
|
char *tok;
|
||||||
if (strstr(f->filename, "fstab") != NULL && S_ISREG(f->mode)) {
|
tok = strsep(&data, "\n");
|
||||||
for (read = 0, write = 0; read < f->filesize; ++read, ++write) {
|
while (tok) {
|
||||||
skip = check_verity_pattern(f->data + read);
|
line = xcalloc(sizeof(*line), 1);
|
||||||
if (skip > 0) {
|
line->line = tok;
|
||||||
printf("Remove pattern [%.*s] in [%s]\n", (int) skip, f->data + read, f->filename);
|
list_insert_end(head, &line->pos);
|
||||||
read += skip;
|
tok = strsep(&data, "\n");
|
||||||
}
|
|
||||||
f->data[write] = f->data[read];
|
|
||||||
}
|
|
||||||
f->filesize = write;
|
|
||||||
} else if (strcmp(f->filename, "verity_key") == 0) {
|
|
||||||
f->remove = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return head;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cpio_forceencrypt(struct vector *v) {
|
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;
|
||||||
const char *ENCRYPT_LIST[] = { "forceencrypt", "forcefdeorfbe", "fileencryptioninline", NULL };
|
const char *ENCRYPT_LIST[] = { "forceencrypt", "forcefdeorfbe", "fileencryptioninline", NULL };
|
||||||
vec_for_each(v, f) {
|
vec_for_each(v, f) {
|
||||||
if (strstr(f->filename, "fstab") != NULL && S_ISREG(f->mode)) {
|
if (strcmp(f->filename, "init.rc") == 0) {
|
||||||
for (read = 0, write = 0; read < f->filesize; ++read, ++write) {
|
head = block_to_list(f->data);
|
||||||
for (int i = 0 ; ENCRYPT_LIST[i]; ++i) {
|
list_for_each(line, head, line_list, pos) {
|
||||||
if (strncmp(f->data + read, ENCRYPT_LIST[i], strlen(ENCRYPT_LIST[i])) == 0) {
|
if (strstr(line->line, "import")) {
|
||||||
memcpy(f->data + write, "encryptable", 11);
|
if (strstr(line->line, "init.magisk.rc"))
|
||||||
printf("Replace [%s] with [%s] in [%s]\n", ENCRYPT_LIST[i], "encryptable", f->filename);
|
injected = 1;
|
||||||
write += 11;
|
if (injected)
|
||||||
read += strlen(ENCRYPT_LIST[i]);
|
continue;
|
||||||
break;
|
// 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)) {
|
||||||
|
for (read = 0, write = 0; read < f->filesize; ++read, ++write) {
|
||||||
|
skip = check_verity_pattern(f->data + read);
|
||||||
|
if (skip > 0) {
|
||||||
|
printf("Remove pattern [%.*s] in [%s]\n", skip, f->data + read, f->filename);
|
||||||
|
read += skip;
|
||||||
|
}
|
||||||
|
f->data[write] = f->data[read];
|
||||||
|
}
|
||||||
|
f->filesize = write;
|
||||||
|
} else if (strcmp(f->filename, "verity_key") == 0) {
|
||||||
|
printf("Remove [verity_key]\n");
|
||||||
|
f->remove = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!keepforceencrypt) {
|
||||||
|
if (strstr(f->filename, "fstab") != NULL && S_ISREG(f->mode)) {
|
||||||
|
for (read = 0, write = 0; read < f->filesize; ++read, ++write) {
|
||||||
|
for (int i = 0 ; ENCRYPT_LIST[i]; ++i) {
|
||||||
|
if (strncmp(f->data + read, ENCRYPT_LIST[i], strlen(ENCRYPT_LIST[i])) == 0) {
|
||||||
|
memcpy(f->data + write, "encryptable", 11);
|
||||||
|
printf("Replace [%s] with [%s] in [%s]\n", ENCRYPT_LIST[i], "encryptable", f->filename);
|
||||||
|
write += 11;
|
||||||
|
read += strlen(ENCRYPT_LIST[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f->data[write] = f->data[read];
|
||||||
|
}
|
||||||
|
f->filesize = write;
|
||||||
}
|
}
|
||||||
f->data[write] = f->data[read];
|
|
||||||
}
|
}
|
||||||
f->filesize = write;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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,41 +499,36 @@ 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);
|
||||||
parse_cpio(incpio, &v);
|
parse_cpio(incpio, &v);
|
||||||
switch(cmd) {
|
switch(cmd) {
|
||||||
case TEST:
|
case TEST:
|
||||||
cpio_test(&v);
|
cpio_test(&v);
|
||||||
break;
|
break;
|
||||||
case DMVERITY:
|
case RESTORE:
|
||||||
cpio_dmverity(&v);
|
ret = cpio_restore(&v);
|
||||||
break;
|
break;
|
||||||
case FORCEENCRYPT:
|
case BACKUP:
|
||||||
cpio_forceencrypt(&v);
|
cpio_backup(argv[0], &v);
|
||||||
break;
|
case RM:
|
||||||
case RESTORE:
|
cpio_rm(recursive, argv[0], &v);
|
||||||
ret = cpio_restore(&v);
|
break;
|
||||||
break;
|
case PATCH:
|
||||||
case BACKUP:
|
cpio_patch(&v, strcmp(argv[0], "true") == 0, strcmp(argv[1], "true") == 0);
|
||||||
cpio_backup(argv[0], &v);
|
break;
|
||||||
case RM:
|
case EXTRACT:
|
||||||
cpio_rm(recursive, argv[0], &v);
|
cpio_extract(argv[0], argv[1], &v);
|
||||||
break;
|
break;
|
||||||
case EXTRACT:
|
case MKDIR:
|
||||||
cpio_extract(argv[0], argv[1], &v);
|
cpio_mkdir(strtoul(argv[0], NULL, 8), argv[1], &v);
|
||||||
break;
|
break;
|
||||||
case MKDIR:
|
case ADD:
|
||||||
cpio_mkdir(strtoul(argv[0], NULL, 8), argv[1], &v);
|
cpio_add(strtoul(argv[0], NULL, 8), argv[1], argv[2], &v);
|
||||||
break;
|
break;
|
||||||
case ADD:
|
case NONE:
|
||||||
cpio_add(strtoul(argv[0], NULL, 8), argv[1], argv[2], &v);
|
return 1;
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// Never happen
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
dump_cpio(incpio, &v);
|
dump_cpio(incpio, &v);
|
||||||
cpio_vec_destroy(&v);
|
cpio_vec_destroy(&v);
|
||||||
|
|||||||
@@ -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];
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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");
|
|
||||||
}
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -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) {
|
||||||
@@ -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) {
|
||||||
write_int(client, HIDE_IS_ENABLED);
|
if (client > 0) {
|
||||||
close(client);
|
write_int(client, HIDE_IS_ENABLED);
|
||||||
|
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"));
|
||||||
|
|
||||||
write_int(client, DAEMON_SUCCESS);
|
if (client > 0) {
|
||||||
close(client);
|
write_int(client, DAEMON_SUCCESS);
|
||||||
|
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;
|
||||||
write_int(client, DAEMON_ERROR);
|
if (client > 0) {
|
||||||
close(client);
|
write_int(client, DAEMON_ERROR);
|
||||||
if (hide_pid != -1) {
|
close(client);
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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
|
||||||
|
|||||||
Submodule jni/magiskpolicy updated: 193d160bed...c1c6f55f8f
24
jni/main.c
24
jni/main.c
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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_
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Submodule jni/selinux updated: 0b14ed89aa...3d9b8bcb05
@@ -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)
|
|
||||||
7387
jni/sqlite3/shell.c
7387
jni/sqlite3/shell.c
File diff suppressed because it is too large
Load Diff
202113
jni/sqlite3/sqlite3.c
202113
jni/sqlite3/sqlite3.c
File diff suppressed because it is too large
Load Diff
@@ -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
2
jni/su
Submodule jni/su updated: 1bbf96a0a7...e2821025ef
148
jni/utils/img.c
Normal file
148
jni/utils/img.c
Normal 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);
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
125
jni/utils/misc.c
125
jni/utils/misc.c
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
97
scripts/addon.d.sh
Normal 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
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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
|
||||||
# (The list is LARGE, most likely due to bad decision in early versions
|
# 2. Remove all Magisk related files
|
||||||
# the latest versions has much less bloat to cleanup)
|
# (The list is LARGE, most likely due to bad decision in early versions
|
||||||
|
# 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
|
||||||
|
|
||||||
|
|||||||
@@ -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
194
scripts/util_functions.sh
Normal 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
BIN
ziptools/apksigner.jar
Normal file
Binary file not shown.
Reference in New Issue
Block a user