mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-12-11 10:02:24 +00:00
Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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:
|
||||
error('Build Magisk Manager failed!')
|
||||
|
||||
unsigned = os.path.join('app', 'build', 'outputs', 'apk', 'app-release-unsigned.apk')
|
||||
aligned = os.path.join('app', 'build', 'outputs', 'apk', 'app-release-aligned.apk')
|
||||
release = os.path.join('app', 'build', 'outputs', 'apk', 'app-release.apk')
|
||||
unsigned = os.path.join('app', 'build', 'outputs', 'apk', 'release', 'app-release-unsigned.apk')
|
||||
aligned = os.path.join('app', 'build', 'outputs', 'apk', 'release', 'app-release-aligned.apk')
|
||||
release = os.path.join('app', 'build', 'outputs', 'apk', 'release', 'app-release.apk')
|
||||
|
||||
# Find the latest build tools
|
||||
build_tool = sorted(os.listdir(os.path.join(os.environ['ANDROID_HOME'], 'build-tools')))[-1]
|
||||
@@ -93,7 +93,7 @@ def build_apk(args):
|
||||
error('Zipalign Magisk Manager failed!')
|
||||
|
||||
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'),
|
||||
release, aligned), shell=True)
|
||||
if proc.returncode != 0:
|
||||
@@ -154,29 +154,51 @@ def zip_main(args):
|
||||
zip_with_msg(zipf, source, target)
|
||||
|
||||
# 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')
|
||||
zip_with_msg(zipf, source, target)
|
||||
|
||||
# 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
|
||||
update_binary = flash_script.read().replace(
|
||||
update_binary = script.read().replace(
|
||||
'MAGISK_VERSION_STUB', 'Magisk v{} Installer'.format(args.versionString))
|
||||
target = os.path.join('META-INF', 'com', 'google', 'android', 'update-binary')
|
||||
print('zip: ' + source + ' -> ' + target)
|
||||
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')
|
||||
print('zip: ' + target)
|
||||
zipf.writestr(target, '#MAGISK\n')
|
||||
# init.magisk.rc
|
||||
source = os.path.join('scripts', 'init.magisk.rc')
|
||||
target = os.path.join('common', 'init.magisk.rc')
|
||||
zip_with_msg(zipf, source, target)
|
||||
# boot_patch.sh
|
||||
source = os.path.join('scripts', 'boot_patch.sh')
|
||||
target = os.path.join('common', 'boot_patch.sh')
|
||||
zip_with_msg(zipf, source, target)
|
||||
|
||||
# util_functions.sh
|
||||
source = os.path.join('scripts', 'util_functions.sh')
|
||||
with open(source, 'r') as script:
|
||||
# Add version info util_functions.sh
|
||||
util_func = script.read().replace(
|
||||
'MAGISK_VERSION_STUB', 'SCRIPT_VERSION={}'.format(args.versionCode))
|
||||
target = os.path.join('common', 'util_functions.sh')
|
||||
print('zip: ' + source + ' -> ' + target)
|
||||
zipf.writestr(target, util_func)
|
||||
# Prebuilts
|
||||
for chromeos in ['futility', 'kernel_data_key.vbprivk', 'kernel.keyblock']:
|
||||
source = os.path.join('chromeos', chromeos)
|
||||
@@ -201,6 +223,16 @@ def zip_uninstaller(args):
|
||||
target = 'magisk_uninstaller.sh'
|
||||
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')
|
||||
target = os.path.join('META-INF', 'com', 'google', 'android', 'update-binary')
|
||||
zip_with_msg(zipf, source, target)
|
||||
@@ -209,6 +241,13 @@ def zip_uninstaller(args):
|
||||
print('zip: ' + target)
|
||||
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'))
|
||||
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.add_argument('versionString')
|
||||
zip_parser.add_argument('versionCode', type=int)
|
||||
zip_parser.set_defaults(func=zip_main)
|
||||
|
||||
uninstaller_parser = subparsers.add_parser('uninstaller', help='create flashable uninstaller')
|
||||
uninstaller_parser.set_defaults(func=zip_uninstaller)
|
||||
|
||||
clean_parser = subparsers.add_parser('clean', help='clean [target...] Targets: binary 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.set_defaults(func=cleanup)
|
||||
|
||||
|
||||
@@ -10,9 +10,8 @@ LOCAL_C_INCLUDES := \
|
||||
$(LOCAL_PATH)/daemon \
|
||||
$(LOCAL_PATH)/resetprop \
|
||||
$(LOCAL_PATH)/magiskpolicy \
|
||||
$(LOCAL_PATH)/selinux/libselinux/include \
|
||||
$(LOCAL_PATH)/selinux/libsepol/include \
|
||||
$(LOCAL_PATH)/sqlite3
|
||||
$(LOCAL_PATH)/external \
|
||||
$(LOCAL_PATH)/selinux/libsepol/include
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
main.c \
|
||||
@@ -20,15 +19,14 @@ LOCAL_SRC_FILES := \
|
||||
utils/vector.c \
|
||||
utils/xwrap.c \
|
||||
utils/list.c \
|
||||
utils/img.c \
|
||||
daemon/daemon.c \
|
||||
daemon/socket_trans.c \
|
||||
daemon/log_monitor.c \
|
||||
daemon/bootstages.c \
|
||||
magiskhide/magiskhide.c \
|
||||
magiskhide/hide_daemon.c \
|
||||
magiskhide/proc_monitor.c \
|
||||
magiskhide/pre_process.c \
|
||||
magiskhide/list_manager.c \
|
||||
magiskhide/hide_utils.c \
|
||||
magiskpolicy/magiskpolicy.c \
|
||||
magiskpolicy/rules.c \
|
||||
magiskpolicy/sepolicy.c \
|
||||
@@ -48,14 +46,15 @@ LOCAL_LDLIBS := -llog
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
# Libraries
|
||||
include jni/selinux/libselinux/Android.mk
|
||||
# External shared libraries, build stub libraries for linking
|
||||
include jni/external/Android.mk
|
||||
|
||||
# libsepol, static library
|
||||
include jni/selinux/libsepol/Android.mk
|
||||
include jni/sqlite3/Android.mk
|
||||
|
||||
#####################################################################
|
||||
# In order to build separate binaries, please comment out everything
|
||||
# starting from line 3 (including the 3 lines for libraries)
|
||||
# above (including the lines for libraries)
|
||||
# Then, uncomment the line you want below
|
||||
#####################################################################
|
||||
# include jni/resetprop/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>
|
||||
@@ -29,11 +33,13 @@ static int debug_log_pid, debug_log_fd;
|
||||
* Node structure *
|
||||
******************/
|
||||
|
||||
// Precedence: MODULE > SKEL > DUMMY
|
||||
#define DO_NOTHING 0x0 /* intermediate node */
|
||||
#define IS_DUMMY 0x1 /* mount from mirror */
|
||||
#define IS_SKEL 0x2 /* mount from skeleton */
|
||||
#define IS_MODULE 0x4 /* mount from module */
|
||||
// Precedence: MODULE > SKEL > INTER > DUMMY
|
||||
#define IS_DUMMY 0x01 /* mount from mirror */
|
||||
#define IS_INTER 0x02 /* intermediate node */
|
||||
#define IS_SKEL 0x04 /* mount from skeleton */
|
||||
#define IS_MODULE 0x08 /* mount from module */
|
||||
|
||||
#define IS_VENDOR 0x10 /* special vendor placeholder */
|
||||
|
||||
struct node_entry {
|
||||
const char *module; /* Only used when status & IS_MODULE */
|
||||
@@ -52,45 +58,9 @@ struct node_entry {
|
||||
* 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 SOURCE_TMP "/dev/source"
|
||||
#define TARGET_TMP "/dev/target"
|
||||
|
||||
static int merge_img(const char *source, const char *target) {
|
||||
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(target, &t_used, &t_total);
|
||||
n_total = round_size(s_used + t_used);
|
||||
if (n_total != t_total && resize_img(target, n_total))
|
||||
return 1;
|
||||
if (n_total != t_total)
|
||||
resize_img(target, n_total);
|
||||
|
||||
xmkdir("/cache/source", 0755);
|
||||
xmkdir("/cache/target", 0755);
|
||||
xmkdir(SOURCE_TMP, 0755);
|
||||
xmkdir(TARGET_TMP, 0755);
|
||||
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;
|
||||
t_loop = mount_image(target, "/cache/target");
|
||||
t_loop = mount_image(target, TARGET_TMP);
|
||||
if (t_loop == NULL) return 1;
|
||||
|
||||
DIR *dir;
|
||||
struct dirent *entry;
|
||||
if (!(dir = opendir("/cache/source")))
|
||||
if (!(dir = opendir(SOURCE_TMP)))
|
||||
return 1;
|
||||
while ((entry = xreaddir(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, "lost+found") == 0)
|
||||
continue;
|
||||
// Cleanup old module
|
||||
snprintf(buf, PATH_MAX, "/cache/target/%s", entry->d_name);
|
||||
// Cleanup old module if exists
|
||||
snprintf(buf, PATH_MAX, "%s/%s", TARGET_TMP, entry->d_name);
|
||||
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);
|
||||
} else {
|
||||
LOGI("New module: %s\n", entry->d_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
clone_dir("/cache/source", "/cache/target");
|
||||
clone_dir(SOURCE_TMP, TARGET_TMP);
|
||||
|
||||
// Unmount all loop devices
|
||||
umount_image("/cache/source", s_loop);
|
||||
umount_image("/cache/target", t_loop);
|
||||
rmdir("/cache/source");
|
||||
rmdir("/cache/target");
|
||||
umount_image(SOURCE_TMP, s_loop);
|
||||
umount_image(TARGET_TMP, t_loop);
|
||||
rmdir(SOURCE_TMP);
|
||||
rmdir(TARGET_TMP);
|
||||
free(s_loop);
|
||||
free(t_loop);
|
||||
unlink(source);
|
||||
@@ -248,9 +220,7 @@ static struct node_entry *insert_child(struct node_entry *p, struct node_entry *
|
||||
// Exist duplicate
|
||||
if (c->status > e->status) {
|
||||
// Precedence is higher, replace with new node
|
||||
c->children = e->children; // Preserve all children
|
||||
free(e->name);
|
||||
free(e);
|
||||
destroy_subtree(e);
|
||||
vec_entry(p->children)[_] = c;
|
||||
return c;
|
||||
} else {
|
||||
@@ -285,25 +255,44 @@ static void construct_tree(const char *module, struct node_entry *parent) {
|
||||
node->name = strdup(entry->d_name);
|
||||
node->type = entry->d_type;
|
||||
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) {
|
||||
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
|
||||
parent->status |= IS_SKEL;
|
||||
node->status |= IS_MODULE;
|
||||
parent->status |= IS_SKEL; /* This will not overwrite if parent is module */
|
||||
node->status = IS_MODULE;
|
||||
} else if (IS_DIR(node)) {
|
||||
// Check if marked as replace
|
||||
snprintf(buf2, PATH_MAX, "%s/%s%s/.replace", MOUNTPOINT, module, buf);
|
||||
if (access(buf2, F_OK) == 0) {
|
||||
// Replace everything, mark as leaf
|
||||
node->status |= IS_MODULE;
|
||||
node->status = IS_MODULE;
|
||||
} else {
|
||||
// This will be an intermediate node
|
||||
node->status = IS_INTER;
|
||||
}
|
||||
} else if (IS_REG(node)) {
|
||||
// This is a leaf, mark as target
|
||||
node->status |= IS_MODULE;
|
||||
node->status = IS_MODULE;
|
||||
}
|
||||
node = insert_child(parent, node);
|
||||
if (IS_DIR(node) && !(node->status & IS_MODULE)) {
|
||||
// Intermediate node, travel deeper
|
||||
if (node->status & (IS_SKEL | IS_INTER)) {
|
||||
// Intermediate folder, travel deeper
|
||||
construct_tree(module, node);
|
||||
}
|
||||
}
|
||||
@@ -321,7 +310,8 @@ static void clone_skeleton(struct node_entry *node) {
|
||||
|
||||
// Clone the structure
|
||||
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;
|
||||
while ((entry = xreaddir(dir))) {
|
||||
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->name = strdup(entry->d_name);
|
||||
dummy->type = entry->d_type;
|
||||
dummy->status |= IS_DUMMY;
|
||||
dummy->status = IS_DUMMY;
|
||||
insert_child(node, dummy);
|
||||
}
|
||||
closedir(dir);
|
||||
@@ -338,21 +328,31 @@ static void clone_skeleton(struct node_entry *node) {
|
||||
snprintf(buf, PATH_MAX, "%s%s", DUMMDIR, full_path);
|
||||
mkdir_p(buf, 0755);
|
||||
clone_attr(full_path, buf);
|
||||
if (node->status & IS_SKEL)
|
||||
bind_mount(buf, full_path);
|
||||
|
||||
vec_for_each(node->children, child) {
|
||||
snprintf(buf, PATH_MAX, "%s%s/%s", DUMMDIR, full_path, child->name);
|
||||
|
||||
// Create the dummy file/directory
|
||||
if (IS_DIR(child))
|
||||
xmkdir(buf, 0755);
|
||||
else if (IS_REG(child))
|
||||
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
|
||||
snprintf(buf2, PATH_MAX, "%s/%s%s/%s", MOUNTPOINT, child->module, full_path, child->name);
|
||||
} else if (child->status & IS_SKEL) {
|
||||
// It's another skeleton, recursive call and end
|
||||
} else if (child->status & (IS_SKEL | IS_INTER)) {
|
||||
// It's a intermediate folder, recursive clone
|
||||
clone_skeleton(child);
|
||||
continue;
|
||||
} else if (child->status & IS_DUMMY) {
|
||||
@@ -361,11 +361,8 @@ static void clone_skeleton(struct node_entry *node) {
|
||||
}
|
||||
|
||||
if (IS_LNK(child)) {
|
||||
// Symlink special treatments
|
||||
char *temp = xmalloc(PATH_MAX);
|
||||
xreadlink(buf2, temp, PATH_MAX);
|
||||
symlink(temp, buf);
|
||||
free(temp);
|
||||
// Copy symlinks directly
|
||||
cp_afc(buf2, buf);
|
||||
LOGI("cplink: %s -> %s\n", buf2, buf);
|
||||
} else {
|
||||
snprintf(buf, PATH_MAX, "%s/%s", full_path, child->name);
|
||||
@@ -381,15 +378,6 @@ static void magic_mount(struct node_entry *node) {
|
||||
char *real_path;
|
||||
struct node_entry *child;
|
||||
|
||||
if (strcmp(node->name, "vendor") == 0 && strcmp(node->parent->name, "/system") == 0) {
|
||||
snprintf(buf, PATH_MAX, "%s/%s/system/vendor", MOUNTPOINT, node->module);
|
||||
snprintf(buf2, PATH_MAX, "%s/%s/vendor", MOUNTPOINT, node->module);
|
||||
unlink(buf2);
|
||||
symlink(buf, buf2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (node->status) {
|
||||
if (node->status & IS_MODULE) {
|
||||
// The real deal, mount module item
|
||||
real_path = get_full_path(node);
|
||||
@@ -399,13 +387,13 @@ static void magic_mount(struct node_entry *node) {
|
||||
} 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 {
|
||||
} else if (node->status & IS_INTER) {
|
||||
// It's an intermediate node, travel deeper
|
||||
vec_for_each(node->children, child)
|
||||
magic_mount(child);
|
||||
}
|
||||
// The only thing goes here should be vendor placeholder
|
||||
// There should be no dummies, so don't need to handle it here
|
||||
}
|
||||
|
||||
/****************
|
||||
@@ -434,7 +422,7 @@ static void simple_mount(const char *path) {
|
||||
free(new_path);
|
||||
} else if (entry->d_type == DT_REG) {
|
||||
// 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_attr(buf2, buf);
|
||||
// Finally, mount the file
|
||||
@@ -523,19 +511,23 @@ void post_fs_data(int client) {
|
||||
}
|
||||
|
||||
// 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);
|
||||
rename("/data/local/tmp/magisk", DATABIN);
|
||||
rename("/data/local/tmp/magisk_inject", DATABIN);
|
||||
}
|
||||
|
||||
// Lazy.... use shell blob
|
||||
system("mv /data/magisk/stock_boot* /data;");
|
||||
|
||||
// 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;
|
||||
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;
|
||||
}
|
||||
|
||||
int new_img = 0;
|
||||
|
||||
@@ -545,9 +537,6 @@ void post_fs_data(int client) {
|
||||
new_img = 1;
|
||||
}
|
||||
|
||||
// Initialize resetprop for the daemon
|
||||
init_resetprop();
|
||||
|
||||
LOGI("* Mounting " MAINIMG "\n");
|
||||
// Mounting magisk image
|
||||
char *magiskloop = mount_image(MAINIMG, MOUNTPOINT);
|
||||
@@ -555,10 +544,10 @@ void post_fs_data(int client) {
|
||||
goto unblock;
|
||||
|
||||
if (new_img) {
|
||||
mkdir(COREDIR, 0755);
|
||||
mkdir(COREDIR "/post-fs-data.d", 0755);
|
||||
mkdir(COREDIR "/service.d", 0755);
|
||||
mkdir(COREDIR "/props", 0755);
|
||||
xmkdir(COREDIR, 0755);
|
||||
xmkdir(COREDIR "/post-fs-data.d", 0755);
|
||||
xmkdir(COREDIR "/service.d", 0755);
|
||||
xmkdir(COREDIR "/props", 0755);
|
||||
}
|
||||
|
||||
// Run common scripts
|
||||
@@ -579,6 +568,7 @@ void post_fs_data(int client) {
|
||||
// Create the system root entry
|
||||
sys_root = xcalloc(sizeof(*sys_root), 1);
|
||||
sys_root->name = strdup("/system");
|
||||
sys_root->status = IS_INTER;
|
||||
|
||||
int has_modules = 0;
|
||||
|
||||
@@ -624,6 +614,13 @@ void post_fs_data(int client) {
|
||||
// Construct structure
|
||||
has_modules = 1;
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -674,25 +671,30 @@ void post_fs_data(int client) {
|
||||
LOGI("link: %s -> %s\n", buf, buf2);
|
||||
}
|
||||
|
||||
// Magic!!
|
||||
|
||||
magic_mount(sys_root);
|
||||
// Get the vendor node if exists
|
||||
// Extract the vendor node out of system tree and swap with placeholder
|
||||
vec_for_each(sys_root->children, child) {
|
||||
if (strcmp(child->name, "vendor") == 0) {
|
||||
ven_root = child;
|
||||
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->parent = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ven_root)
|
||||
magic_mount(ven_root);
|
||||
|
||||
// Magic!!
|
||||
magic_mount(sys_root);
|
||||
if (ven_root) magic_mount(ven_root);
|
||||
}
|
||||
|
||||
// Cleanup memory
|
||||
destroy_subtree(sys_root);
|
||||
if (ven_root) destroy_subtree(ven_root);
|
||||
|
||||
// Execute module scripts
|
||||
LOGI("* Running module post-fs-data scripts\n");
|
||||
@@ -704,16 +706,14 @@ void post_fs_data(int client) {
|
||||
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);
|
||||
if (hide_prop) {
|
||||
if (strcmp(hide_prop, "1") == 0) {
|
||||
if (hide_prop == NULL || strcmp(hide_prop, "0") != 0) {
|
||||
pthread_t thread;
|
||||
xpthread_create(&thread, NULL, start_magisk_hide, NULL);
|
||||
pthread_detach(thread);
|
||||
}
|
||||
free(hide_prop);
|
||||
}
|
||||
|
||||
unblock:
|
||||
unblock_boot_process();
|
||||
@@ -735,6 +735,13 @@ void late_start(int client) {
|
||||
// Run scripts after full patch, most reliable way to run scripts
|
||||
LOGI("* Running service.d scripts\n");
|
||||
exec_common_script("service");
|
||||
|
||||
// Core only mode
|
||||
if (access(DISABLEFILE, F_OK) == 0) {
|
||||
setprop("ro.magisk.disable", "1");
|
||||
return;
|
||||
}
|
||||
|
||||
LOGI("* Running module service scripts\n");
|
||||
exec_module_script("service");
|
||||
|
||||
@@ -746,7 +753,7 @@ void late_start(int client) {
|
||||
"CLASSPATH=/system/framework/pm.jar "
|
||||
"/system/bin/app_process /system/bin "
|
||||
"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);
|
||||
waitpid(pid, NULL, 0);
|
||||
fdgets(buf, PATH_MAX, apk_res);
|
||||
@@ -761,11 +768,11 @@ void late_start(int client) {
|
||||
// All boot stage done, cleanup everything
|
||||
free(buf);
|
||||
free(buf2);
|
||||
buf = buf2 = NULL;
|
||||
vec_deep_destroy(&module_list);
|
||||
|
||||
#ifdef DEBUG
|
||||
// Stop recording the boot logcat after every boot task is done
|
||||
extern int debug_log_pid, debug_log_fd;
|
||||
kill(debug_log_pid, SIGTERM);
|
||||
waitpid(debug_log_pid, NULL, 0);
|
||||
close(debug_log_fd);
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "magiskpolicy.h"
|
||||
|
||||
pthread_t sepol_patch;
|
||||
int null_fd;
|
||||
|
||||
static void *request_handler(void *args) {
|
||||
// Setup the default error handler for threads
|
||||
@@ -89,17 +88,12 @@ static void *request_handler(void *args) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// Just in case
|
||||
close(client);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Setup the address and return socket fd */
|
||||
static int setup_socket(struct sockaddr_un *sun) {
|
||||
int fd = xsocket(AF_LOCAL, SOCK_STREAM, 0);
|
||||
if (fcntl(fd, F_SETFD, FD_CLOEXEC))
|
||||
PLOGE("fcntl FD_CLOEXEC");
|
||||
|
||||
int fd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||
memset(sun, 0, sizeof(*sun));
|
||||
sun->sun_family = AF_LOCAL;
|
||||
memcpy(sun->sun_path, REQUESTOR_DAEMON_PATH, REQUESTOR_DAEMON_PATH_LEN);
|
||||
@@ -137,10 +131,11 @@ void start_daemon(int client) {
|
||||
xsetsid();
|
||||
setcon("u:r:su:s0");
|
||||
umask(022);
|
||||
null_fd = xopen("/dev/null", O_RDWR | O_CLOEXEC);
|
||||
xdup2(null_fd, STDIN_FILENO);
|
||||
xdup2(null_fd, STDOUT_FILENO);
|
||||
xdup2(null_fd, STDERR_FILENO);
|
||||
int fd = xopen("/dev/null", O_RDWR | O_CLOEXEC);
|
||||
xdup2(fd, STDIN_FILENO);
|
||||
xdup2(fd, STDOUT_FILENO);
|
||||
xdup2(fd, STDERR_FILENO);
|
||||
close(fd);
|
||||
|
||||
// Patch selinux with medium patch before we do anything
|
||||
load_policydb(SELINUX_POLICY);
|
||||
@@ -151,7 +146,7 @@ void start_daemon(int client) {
|
||||
pthread_create(&sepol_patch, NULL, large_sepol_patch, NULL);
|
||||
|
||||
struct sockaddr_un sun;
|
||||
int fd = setup_socket(&sun);
|
||||
fd = setup_socket(&sun);
|
||||
|
||||
xbind(fd, (struct sockaddr*) &sun, sizeof(sun));
|
||||
xlisten(fd, 10);
|
||||
@@ -162,7 +157,7 @@ void start_daemon(int client) {
|
||||
// It should stay intact under any circumstances
|
||||
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_blocks();
|
||||
@@ -171,16 +166,14 @@ void start_daemon(int client) {
|
||||
xmount(NULL, "/", NULL, MS_REMOUNT, NULL);
|
||||
create_links(NULL, "/sbin");
|
||||
xchmod("/sbin", 0755);
|
||||
mkdir("/magisk", 0755);
|
||||
xmkdir("/magisk", 0755);
|
||||
xchmod("/magisk", 0755);
|
||||
xmount(NULL, "/", NULL, MS_REMOUNT | MS_RDONLY, NULL);
|
||||
|
||||
// Loop forever to listen for requests
|
||||
while(1) {
|
||||
int *client = xmalloc(sizeof(int));
|
||||
*client = xaccept(fd, NULL, NULL);
|
||||
// Just in case, set to close on exec
|
||||
fcntl(*client, F_SETFD, FD_CLOEXEC);
|
||||
*client = xaccept4(fd, NULL, NULL, SOCK_CLOEXEC);
|
||||
pthread_t thread;
|
||||
xpthread_create(&thread, NULL, request_handler, client);
|
||||
// Detach the thread, we will never join it
|
||||
@@ -192,7 +185,6 @@ void start_daemon(int client) {
|
||||
int connect_daemon() {
|
||||
struct sockaddr_un sun;
|
||||
int fd = setup_socket(&sun);
|
||||
// LOGD("client: trying to connect socket\n");
|
||||
if (connect(fd, (struct sockaddr*) &sun, sizeof(sun))) {
|
||||
/* If we cannot access the daemon, we start the daemon
|
||||
* 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
|
||||
char *const command[] = { "logcat", "-s", "Magisk", "-v", "thread", NULL };
|
||||
log_pid = run_command(0, &log_fd, "/system/bin/logcat", command);
|
||||
if (log_pid > 0)
|
||||
waitpid(log_pid, NULL, 0);
|
||||
// For some reason it went here, clear buffer and restart
|
||||
system("logcat -c");
|
||||
}
|
||||
|
||||
// Should never be here, but well...
|
||||
close(log_fd);
|
||||
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
|
||||
357
jni/external/selinux_stub.c
vendored
Normal file
357
jni/external/selinux_stub.c
vendored
Normal file
@@ -0,0 +1,357 @@
|
||||
#include <sys/types.h>
|
||||
#include <stdarg.h>
|
||||
#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; }
|
||||
677
jni/external/sqlite3_stub.c
vendored
Normal file
677
jni/external/sqlite3_stub.c
vendored
Normal file
@@ -0,0 +1,677 @@
|
||||
#include <stdlib.h>
|
||||
#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 int (*applet_main[]) (int, char *[]);
|
||||
extern int null_fd;
|
||||
|
||||
// Multi-call entrypoints
|
||||
int magiskhide_main(int argc, char *argv[]);
|
||||
|
||||
@@ -17,11 +17,12 @@ LOCAL_SRC_FILES := \
|
||||
hexpatch.c \
|
||||
parseimg.c \
|
||||
compress.c \
|
||||
utils.c \
|
||||
boot_utils.c \
|
||||
cpio.c \
|
||||
sha1.c \
|
||||
../utils/xwrap.c \
|
||||
../utils/vector.c
|
||||
../utils/vector.c \
|
||||
../utils/list.c
|
||||
LOCAL_CFLAGS += -DZLIB_CONST
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "magiskboot.h"
|
||||
#include "cpio.h"
|
||||
#include "vector.h"
|
||||
#include "list.h"
|
||||
|
||||
static uint32_t x8u(char *hex) {
|
||||
uint32_t val, inpos = 8, outpos;
|
||||
@@ -220,33 +221,93 @@ static int check_verity_pattern(const char *s) {
|
||||
return pos;
|
||||
}
|
||||
|
||||
static void cpio_dmverity(struct vector *v) {
|
||||
static struct list_head *block_to_list(char *data) {
|
||||
struct list_head *head = xmalloc(sizeof(*head));
|
||||
line_list *line;
|
||||
init_list_head(head);
|
||||
char *tok;
|
||||
tok = strsep(&data, "\n");
|
||||
while (tok) {
|
||||
line = xcalloc(sizeof(*line), 1);
|
||||
line->line = tok;
|
||||
list_insert_end(head, &line->pos);
|
||||
tok = strsep(&data, "\n");
|
||||
}
|
||||
return head;
|
||||
}
|
||||
|
||||
static char *list_to_block(struct list_head *head, uint32_t filesize) {
|
||||
line_list *line;
|
||||
char *data = xmalloc(filesize);
|
||||
uint32_t off = 0;
|
||||
list_for_each(line, head, line_list, pos) {
|
||||
strcpy(data + off, line->line);
|
||||
off += strlen(line->line);
|
||||
data[off++] = '\n';
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
static void free_newline(line_list *line) {
|
||||
if (line->isNew)
|
||||
free(line->line);
|
||||
}
|
||||
|
||||
static void cpio_patch(struct vector *v, int keepverity, int keepforceencrypt) {
|
||||
struct list_head *head;
|
||||
line_list *line;
|
||||
cpio_file *f;
|
||||
int skip, injected = 0;
|
||||
size_t read, write;
|
||||
int skip;
|
||||
const char *ENCRYPT_LIST[] = { "forceencrypt", "forcefdeorfbe", "fileencryptioninline", NULL };
|
||||
vec_for_each(v, f) {
|
||||
if (strcmp(f->filename, "init.rc") == 0) {
|
||||
head = block_to_list(f->data);
|
||||
list_for_each(line, head, line_list, pos) {
|
||||
if (strstr(line->line, "import")) {
|
||||
if (strstr(line->line, "init.magisk.rc"))
|
||||
injected = 1;
|
||||
if (injected)
|
||||
continue;
|
||||
// Inject magisk script as import
|
||||
printf("Inject new line [import /init.magisk.rc] in [init.rc]\n");
|
||||
line = xcalloc(sizeof(*line), 1);
|
||||
line->line = strdup("import /init.magisk.rc");
|
||||
line->isNew = 1;
|
||||
f->filesize += 23;
|
||||
list_insert(__->prev, &line->pos);
|
||||
injected = 1;
|
||||
} else if (strstr(line->line, "selinux.reload_policy")) {
|
||||
// Remove this line
|
||||
printf("Remove line [%s] in [init.rc]\n", line->line);
|
||||
f->filesize -= strlen(line->line) + 1;
|
||||
__ = list_pop(&line->pos);
|
||||
free(line);
|
||||
}
|
||||
}
|
||||
char *temp = list_to_block(head, f->filesize);
|
||||
free(f->data);
|
||||
f->data = temp;
|
||||
list_destory(head, list_head, pos, free_newline);
|
||||
free(head);
|
||||
} else {
|
||||
if (!keepverity) {
|
||||
if (strstr(f->filename, "fstab") != NULL && S_ISREG(f->mode)) {
|
||||
for (read = 0, write = 0; read < f->filesize; ++read, ++write) {
|
||||
skip = check_verity_pattern(f->data + read);
|
||||
if (skip > 0) {
|
||||
printf("Remove pattern [%.*s] in [%s]\n", (int) skip, f->data + read, f->filename);
|
||||
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;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cpio_forceencrypt(struct vector *v) {
|
||||
cpio_file *f;
|
||||
size_t read, write;
|
||||
const char *ENCRYPT_LIST[] = { "forceencrypt", "forcefdeorfbe", "fileencryptioninline", NULL };
|
||||
vec_for_each(v, f) {
|
||||
if (!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) {
|
||||
@@ -264,6 +325,8 @@ static void cpio_forceencrypt(struct vector *v) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cpio_extract(const char *entry, const char *filename, struct vector *v) {
|
||||
cpio_file *f;
|
||||
@@ -415,10 +478,6 @@ int cpio_commands(const char *command, int argc, char *argv[]) {
|
||||
--argc;
|
||||
if (strcmp(command, "test") == 0) {
|
||||
cmd = TEST;
|
||||
} else if (strcmp(command, "patch-dmverity") == 0) {
|
||||
cmd = DMVERITY;
|
||||
} else if (strcmp(command, "patch-forceencrypt") == 0) {
|
||||
cmd = FORCEENCRYPT;
|
||||
} else if (strcmp(command, "restore") == 0) {
|
||||
cmd = RESTORE;
|
||||
} else if (argc == 1 && strcmp(command, "backup") == 0) {
|
||||
@@ -430,6 +489,8 @@ int cpio_commands(const char *command, int argc, char *argv[]) {
|
||||
++argv;
|
||||
--argc;
|
||||
}
|
||||
} else if (argc == 2 && strcmp(command, "patch") == 0) {
|
||||
cmd = PATCH;
|
||||
} else if (argc == 2 && strcmp(command, "extract") == 0) {
|
||||
cmd = EXTRACT;
|
||||
} else if (argc == 2 && strcmp(command, "mkdir") == 0) {
|
||||
@@ -438,7 +499,6 @@ int cpio_commands(const char *command, int argc, char *argv[]) {
|
||||
cmd = ADD;
|
||||
} else {
|
||||
cmd = NONE;
|
||||
return 1;
|
||||
}
|
||||
struct vector v;
|
||||
vec_init(&v);
|
||||
@@ -447,12 +507,6 @@ int cpio_commands(const char *command, int argc, char *argv[]) {
|
||||
case TEST:
|
||||
cpio_test(&v);
|
||||
break;
|
||||
case DMVERITY:
|
||||
cpio_dmverity(&v);
|
||||
break;
|
||||
case FORCEENCRYPT:
|
||||
cpio_forceencrypt(&v);
|
||||
break;
|
||||
case RESTORE:
|
||||
ret = cpio_restore(&v);
|
||||
break;
|
||||
@@ -461,6 +515,9 @@ int cpio_commands(const char *command, int argc, char *argv[]) {
|
||||
case RM:
|
||||
cpio_rm(recursive, argv[0], &v);
|
||||
break;
|
||||
case PATCH:
|
||||
cpio_patch(&v, strcmp(argv[0], "true") == 0, strcmp(argv[1], "true") == 0);
|
||||
break;
|
||||
case EXTRACT:
|
||||
cpio_extract(argv[0], argv[1], &v);
|
||||
break;
|
||||
@@ -470,9 +527,8 @@ int cpio_commands(const char *command, int argc, char *argv[]) {
|
||||
case ADD:
|
||||
cpio_add(strtoul(argv[0], NULL, 8), argv[1], argv[2], &v);
|
||||
break;
|
||||
default:
|
||||
// Never happen
|
||||
break;
|
||||
case NONE:
|
||||
return 1;
|
||||
}
|
||||
dump_cpio(incpio, &v);
|
||||
cpio_vec_destroy(&v);
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "list.h"
|
||||
|
||||
typedef struct cpio_file {
|
||||
// uint32_t ino;
|
||||
uint32_t mode;
|
||||
@@ -22,6 +24,12 @@ typedef struct cpio_file {
|
||||
int remove;
|
||||
} cpio_file;
|
||||
|
||||
typedef struct line_list {
|
||||
char *line;
|
||||
int isNew;
|
||||
struct list_head pos;
|
||||
} line_list;
|
||||
|
||||
typedef struct cpio_newc_header {
|
||||
char magic[6];
|
||||
char ino[8];
|
||||
|
||||
@@ -53,8 +53,7 @@ typedef enum {
|
||||
ADD,
|
||||
EXTRACT,
|
||||
TEST,
|
||||
DMVERITY,
|
||||
FORCEENCRYPT,
|
||||
PATCH,
|
||||
BACKUP,
|
||||
RESTORE
|
||||
} command_t;
|
||||
|
||||
@@ -25,9 +25,8 @@ static void usage(char *arg0) {
|
||||
" --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-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-patch-dmverity <incpio>\n Remove dm-verity\n"
|
||||
" --cpio-patch-forceencrypt <incpio>\n Change forceencrypt flag to encryptable\n"
|
||||
" --cpio-test <incpio>\n Return value: 0/not patched 1/Magisk 2/Other (e.g. phh, SuperSU)\n"
|
||||
" --cpio-patch <KEEPVERITY> <KEEPFORCEENCRYPT>\n Patch cpio for Magisk. KEEP**** are true/false values\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"
|
||||
"\n"
|
||||
@@ -59,7 +58,7 @@ static void usage(char *arg0) {
|
||||
}
|
||||
|
||||
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) {
|
||||
cleanup();
|
||||
|
||||
@@ -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,94 @@
|
||||
/* 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 <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 "utils.h"
|
||||
#include "daemon.h"
|
||||
#include "resetprop.h"
|
||||
#include "magiskhide.h"
|
||||
#include "daemon.h"
|
||||
|
||||
static char *prop_key[] =
|
||||
{ "ro.boot.verifiedbootstate", "ro.boot.flash.locked", "ro.boot.veritymode", "ro.boot.warranty_bit", "ro.warranty_bit",
|
||||
"ro.debuggable", "ro.secure", "ro.build.type", "ro.build.tags", "ro.build.selinux", NULL };
|
||||
|
||||
static char *prop_value[] =
|
||||
{ "green", "1", "enforcing", "0", "0", "0", "1", "user", "release-keys", "0", NULL };
|
||||
|
||||
static int mocked = 0;
|
||||
|
||||
void manage_selinux() {
|
||||
if (mocked) return;
|
||||
char val[1];
|
||||
int fd = xopen(SELINUX_ENFORCE, O_RDONLY);
|
||||
xxread(fd, val, 1);
|
||||
close(fd);
|
||||
// Permissive
|
||||
if (val[0] == '0') {
|
||||
LOGI("hide_daemon: Permissive detected, hide the state\n");
|
||||
|
||||
chmod(SELINUX_ENFORCE, 0640);
|
||||
chmod(SELINUX_POLICY, 0440);
|
||||
mocked = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void hide_sensitive_props() {
|
||||
LOGI("hide_utils: Hiding sensitive props\n");
|
||||
|
||||
// Hide all sensitive props
|
||||
char *value;
|
||||
for (int i = 0; prop_key[i]; ++i) {
|
||||
value = getprop(prop_key[i]);
|
||||
if (value) {
|
||||
if (strcmp(value, prop_value[i]) != 0)
|
||||
setprop2(prop_key[i], prop_value[i], 0);
|
||||
free(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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))) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
int add_list(char *proc) {
|
||||
if (!hideEnabled) {
|
||||
@@ -16,7 +16,6 @@
|
||||
#include "daemon.h"
|
||||
#include "resetprop.h"
|
||||
|
||||
int sv[2], hide_pid = -1;
|
||||
struct vector *hide_list = NULL;
|
||||
|
||||
int hideEnabled = 0;
|
||||
@@ -29,7 +28,7 @@ void kill_proc(int pid) {
|
||||
|
||||
static void usage(char *arg0) {
|
||||
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"
|
||||
"Options:\n"
|
||||
" --enable: Start the magiskhide daemon\n"
|
||||
@@ -46,35 +45,23 @@ void launch_magiskhide(int client) {
|
||||
err_handler = do_nothing;
|
||||
|
||||
if (hideEnabled) {
|
||||
if (client > 0) {
|
||||
write_int(client, HIDE_IS_ENABLED);
|
||||
close(client);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
hideEnabled = 1;
|
||||
LOGI("* Starting MagiskHide\n");
|
||||
|
||||
hideEnabled = 1;
|
||||
|
||||
if (client != -1) {
|
||||
if (client > 0) {
|
||||
if (setprop(MAGISKHIDE_PROP, "1"))
|
||||
goto error;
|
||||
}
|
||||
|
||||
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
|
||||
pthread_mutex_init(&hide_lock, NULL);
|
||||
pthread_mutex_init(&file_lock, NULL);
|
||||
@@ -86,8 +73,10 @@ void launch_magiskhide(int client) {
|
||||
// Add SafetyNet by default
|
||||
add_list(strdup("com.google.android.gms.unstable"));
|
||||
|
||||
if (client > 0) {
|
||||
write_int(client, DAEMON_SUCCESS);
|
||||
close(client);
|
||||
}
|
||||
|
||||
// Get thread reference
|
||||
proc_monitor_thread = pthread_self();
|
||||
@@ -97,15 +86,9 @@ void launch_magiskhide(int client) {
|
||||
|
||||
error:
|
||||
hideEnabled = 0;
|
||||
if (client > 0) {
|
||||
write_int(client, DAEMON_ERROR);
|
||||
close(client);
|
||||
if (hide_pid != -1) {
|
||||
int kill = -1;
|
||||
// Kill hide daemon
|
||||
write(sv[0], &kill, sizeof(kill));
|
||||
close(sv[0]);
|
||||
waitpid(hide_pid, NULL, 0);
|
||||
hide_pid = -1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -6,13 +6,10 @@
|
||||
// Kill process
|
||||
void kill_proc(int pid);
|
||||
|
||||
// Hide daemon
|
||||
int hide_daemon();
|
||||
|
||||
// Process monitor
|
||||
void proc_monitor();
|
||||
|
||||
// Preprocess
|
||||
// Utility functions
|
||||
void manage_selinux();
|
||||
void hide_sensitive_props();
|
||||
void relink_sbin();
|
||||
@@ -23,7 +20,7 @@ int rm_list(char *proc);
|
||||
int init_list();
|
||||
int destroy_list();
|
||||
|
||||
extern int sv[2], hide_pid, hideEnabled;
|
||||
extern int hideEnabled;
|
||||
extern struct vector *hide_list;
|
||||
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,
|
||||
* and send the target PID to hide daemon ASAP
|
||||
* We monitor the logcat am_proc_start events. When a target starts up,
|
||||
* we pause it ASAP, and fork a new process to join its mount namespace
|
||||
* and do all the unmounting/mocking
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
@@ -12,22 +13,17 @@
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/mount.h>
|
||||
|
||||
#include "magisk.h"
|
||||
#include "utils.h"
|
||||
#include "magiskhide.h"
|
||||
|
||||
static int zygote_num = 0;
|
||||
static char init_ns[32], zygote_ns[2][32];
|
||||
static int log_pid = 0, log_fd = 0;
|
||||
static int zygote_num;
|
||||
static char init_ns[32], zygote_ns[2][32], cache_block[256];
|
||||
static int log_pid, log_fd, target_pid;
|
||||
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
|
||||
static void quit_pthread(int sig) {
|
||||
err_handler = do_nothing;
|
||||
@@ -36,23 +32,34 @@ static void quit_pthread(int sig) {
|
||||
free(buffer);
|
||||
hideEnabled = 0;
|
||||
// Kill the logging if needed
|
||||
if (log_pid) {
|
||||
if (log_pid > 0) {
|
||||
kill(log_pid, SIGTERM);
|
||||
waitpid(log_pid, NULL, 0);
|
||||
close(log_fd);
|
||||
log_fd = log_pid = 0;
|
||||
}
|
||||
int kill = -1;
|
||||
// If process monitor dies, kill hide daemon too
|
||||
write(sv[0], &kill, sizeof(kill));
|
||||
close(sv[0]);
|
||||
waitpid(hide_pid, NULL, 0);
|
||||
// Resume process if possible
|
||||
if (target_pid > 0)
|
||||
kill(target_pid, SIGCONT);
|
||||
pthread_mutex_destroy(&hide_lock);
|
||||
pthread_mutex_destroy(&file_lock);
|
||||
LOGD("proc_monitor: terminating...\n");
|
||||
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) {
|
||||
if (zygote_num == 2) return;
|
||||
do {
|
||||
@@ -62,9 +69,74 @@ static void store_zygote_ns(int pid) {
|
||||
++zygote_num;
|
||||
}
|
||||
|
||||
static void proc_monitor_err() {
|
||||
LOGD("proc_monitor: error occured, stopping magiskhide services\n");
|
||||
quit_pthread(SIGUSR1);
|
||||
static void lazy_unmount(const char* mountpoint) {
|
||||
if (umount2(mountpoint, MNT_DETACH) != -1)
|
||||
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() {
|
||||
@@ -76,15 +148,20 @@ void proc_monitor() {
|
||||
|
||||
// The error handler should stop magiskhide services
|
||||
err_handler = proc_monitor_err;
|
||||
log_pid = target_pid = -1;
|
||||
|
||||
int pid;
|
||||
buffer = xmalloc(PATH_MAX);
|
||||
cache_block[0] = '\0';
|
||||
|
||||
// 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);
|
||||
|
||||
// Get the mount namespace of zygote
|
||||
zygote_num = 0;
|
||||
while(!zygote_num) {
|
||||
// Check zygote every 2 secs
|
||||
sleep(2);
|
||||
@@ -97,20 +174,24 @@ void proc_monitor() {
|
||||
LOGI("proc_monitor: zygote ns=%s\n", zygote_ns[0]);
|
||||
break;
|
||||
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;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
// Clear previous buffer
|
||||
// Clear previous logcat buffer
|
||||
system("logcat -b events -c");
|
||||
|
||||
// Monitor am_proc_start
|
||||
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);
|
||||
|
||||
if (log_pid < 0) continue;
|
||||
if (kill(log_pid, 0)) continue;
|
||||
|
||||
while(fdgets(buffer, PATH_MAX, log_fd)) {
|
||||
int ret, comma = 0;
|
||||
int pid, ret, comma = 0;
|
||||
char *pos = buffer, *line, processName[256];
|
||||
|
||||
while(1) {
|
||||
@@ -135,10 +216,11 @@ void proc_monitor() {
|
||||
pthread_mutex_lock(&hide_lock);
|
||||
vec_for_each(hide_list, line) {
|
||||
if (strcmp(processName, line) == 0) {
|
||||
target_pid = pid;
|
||||
while(1) {
|
||||
ret = 1;
|
||||
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) {
|
||||
usleep(50);
|
||||
ret = 0;
|
||||
@@ -148,29 +230,39 @@ void proc_monitor() {
|
||||
if (ret) break;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
// 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
|
||||
xxread(sv[0], &ret, sizeof(ret));
|
||||
LOGD("proc_monitor: hide daemon response code: %d\n", ret);
|
||||
// Wait till the unmount process is done
|
||||
waitpid(hide_pid, &ret, 0);
|
||||
if (WEXITSTATUS(ret))
|
||||
quit_pthread(SIGUSR1);
|
||||
|
||||
// All done, send resume signal
|
||||
kill(target_pid, SIGCONT);
|
||||
target_pid = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
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
|
||||
|
||||
Submodule jni/magiskpolicy updated: 193d160bed...5529dab84e
24
jni/main.c
24
jni/main.c
@@ -22,7 +22,7 @@ __thread void (*err_handler)(void);
|
||||
|
||||
static void usage() {
|
||||
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"
|
||||
"Usage: %s [applet [arguments]...]\n"
|
||||
" or: %s --install [SOURCE] <DIR> \n"
|
||||
@@ -32,6 +32,9 @@ static void usage() {
|
||||
" or: %s --imgsize <PATH>\n"
|
||||
" or: %s --resizeimg <PATH> <SIZE>\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"
|
||||
" start boot stage service\n"
|
||||
" or: %s [options]\n"
|
||||
@@ -46,7 +49,7 @@ static void usage() {
|
||||
" -V print daemon version code\n"
|
||||
"\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) {
|
||||
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]);
|
||||
return 1;
|
||||
}
|
||||
printf("Used: %dM\tTotal: %dM\n", used, total);
|
||||
printf("%d %d\n", used, total);
|
||||
return 0;
|
||||
} else if (strcmp(argv[1], "--resizeimg") == 0) {
|
||||
if (argc < 4) usage();
|
||||
@@ -114,6 +117,21 @@ int main(int argc, char *argv[]) {
|
||||
return 1;
|
||||
}
|
||||
return resize_img(argv[2], size);
|
||||
} else if (strcmp(argv[1], "--mountimg") == 0) {
|
||||
if (argc < 4) usage();
|
||||
char *loop = mount_image(argv[2], argv[3]);
|
||||
if (loop == NULL) {
|
||||
fprintf(stderr, "Cannot mount image!\n");
|
||||
return 1;
|
||||
} else {
|
||||
printf("%s\n", loop);
|
||||
free(loop);
|
||||
return 0;
|
||||
}
|
||||
} else if (strcmp(argv[1], "--umountimg") == 0) {
|
||||
if (argc < 4) usage();
|
||||
umount_image(argv[2], argv[3]);
|
||||
return 0;
|
||||
} else if (strcmp(argv[1], "--post-fs") == 0) {
|
||||
int fd = connect_daemon();
|
||||
write_int(fd, POST_FS);
|
||||
|
||||
@@ -73,22 +73,22 @@ int __system_property_area_init2();
|
||||
|
||||
/* Read the global serial number of the system properties
|
||||
**
|
||||
** Called to predict if a series of cached __system_property_find2
|
||||
** objects will have seen __system_property_serial2 values change.
|
||||
** Called to predict if a series of cached __system_property_find
|
||||
** objects will have seen __system_property_serial values change.
|
||||
** 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
|
||||
** 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
|
||||
** changes have occurred since last. If there is, one may check each individual
|
||||
** __system_property_serial2 to confirm dirty, or __system_property_find2
|
||||
** to check if the property now exists. If a call to __system_property_add2
|
||||
** or __system_property_update2 has completed between two calls to
|
||||
** __system_property_area_serial2 then the second call will return a larger
|
||||
** __system_property_serial to confirm dirty, or __system_property_find
|
||||
** to check if the property now exists. If a call to __system_property_add
|
||||
** or __system_property_update has completed between two calls to
|
||||
** __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
|
||||
** 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.
|
||||
**
|
||||
** 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);
|
||||
|
||||
/* 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
|
||||
** must handle sequencing to ensure that only one property is
|
||||
** 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);
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
@@ -136,7 +136,7 @@ uint32_t __system_property_serial2(const prop_info* pi);
|
||||
*/
|
||||
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);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#ifndef _BIONIC_MACROS_H_
|
||||
#define _BIONIC_MACROS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// Frameworks OpenGL code currently leaks this header and allows
|
||||
// collisions with other declarations, e.g., from libnativehelper.
|
||||
// TODO: Remove once cleaned up. b/18334516
|
||||
@@ -46,4 +48,22 @@
|
||||
? (1UL << (64 - __builtin_clzl(static_cast<unsigned long>(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_
|
||||
|
||||
@@ -108,7 +108,7 @@ static bool is_legal_property_name(const char* name, size_t namelen) {
|
||||
|
||||
static int usage(char* arg0) {
|
||||
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"
|
||||
"%s <name> <value>: Set property entry <name> with <value>\n"
|
||||
"%s --file <prop file>: Load props from <prop file>\n"
|
||||
@@ -121,8 +121,7 @@ static int usage(char* arg0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int init_resetprop() {
|
||||
PRINT_D("resetprop: Initializing...\n");
|
||||
static int init_resetprop() {
|
||||
if (__system_properties_init2()) {
|
||||
PRINT_E("resetprop: Initialize error\n");
|
||||
return -1;
|
||||
@@ -130,15 +129,21 @@ int init_resetprop() {
|
||||
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) {
|
||||
strcpy((char *) cookie, value);
|
||||
}
|
||||
|
||||
// Get prop by name, return string (should free manually!)
|
||||
char *getprop(const char *name) {
|
||||
if (init_resetprop()) return NULL;
|
||||
const prop_info *pi = __system_property_find2(name);
|
||||
if (pi == NULL) {
|
||||
PRINT_D("resetprop: failed to get [%s]\n", name);
|
||||
PRINT_D("resetprop: prop [%s] does not exist\n", name);
|
||||
return NULL;
|
||||
}
|
||||
char value[PROP_VALUE_MAX];
|
||||
@@ -152,16 +157,16 @@ int setprop(const char *name, const char *value) {
|
||||
}
|
||||
|
||||
int setprop2(const char *name, const char *value, const int trigger) {
|
||||
if (init_resetprop()) return -1;
|
||||
int ret;
|
||||
|
||||
char *check = getprop(name);
|
||||
if (check) {
|
||||
free(check);
|
||||
prop_info *pi = (prop_info*) __system_property_find2(name);
|
||||
if (pi != NULL) {
|
||||
if (trigger) {
|
||||
if (!strncmp(name, "ro.", 3)) deleteprop(name);
|
||||
ret = __system_property_set2(name, value);
|
||||
} else {
|
||||
ret = __system_property_update2((prop_info*) __system_property_find2(name), value, strlen(value));
|
||||
ret = __system_property_update2(pi, value, strlen(value));
|
||||
}
|
||||
} else {
|
||||
PRINT_D("resetprop: New prop [%s]\n", name);
|
||||
@@ -182,6 +187,7 @@ int setprop2(const char *name, const char *value, const int trigger) {
|
||||
}
|
||||
|
||||
int deleteprop(const char *name) {
|
||||
if (init_resetprop()) return -1;
|
||||
PRINT_D("resetprop: deleteprop [%s]\n", name);
|
||||
if (__system_property_del(name)) {
|
||||
PRINT_E("resetprop: delete prop: [%s] error\n", name);
|
||||
@@ -191,6 +197,7 @@ int deleteprop(const char *name) {
|
||||
}
|
||||
|
||||
int read_prop_file(const char* filename, const int trigger) {
|
||||
if (init_resetprop()) return -1;
|
||||
PRINT_D("resetprop: Load prop file [%s]\n", filename);
|
||||
FILE *fp = fopen(filename, "r");
|
||||
if (fp == NULL) {
|
||||
@@ -277,8 +284,6 @@ int resetprop_main(int argc, char *argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
init_resetprop();
|
||||
|
||||
if (file) {
|
||||
return read_prop_file(filename, trigger);
|
||||
} else if (del) {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int init_resetprop();
|
||||
int prop_exist(const char *name);
|
||||
int setprop(const char *name, const char *value);
|
||||
int setprop2(const char *name, const char *value, const int trigger);
|
||||
char *getprop(const char *name);
|
||||
|
||||
@@ -1149,9 +1149,7 @@ int __system_properties_init2() {
|
||||
|
||||
if (initialized) {
|
||||
// list_foreach(contexts, [](context_node* l) { l->reset_access(); }); // resetprop remove
|
||||
// return 0; // resetprop remove
|
||||
free_and_unmap_contexts(); // resetprop add
|
||||
initialized = false; // resetprop add
|
||||
return 0;
|
||||
}
|
||||
if (is_dir(property_filename)) {
|
||||
if (!initialize_properties()) {
|
||||
@@ -1207,7 +1205,7 @@ uint32_t __system_property_area_serial2() {
|
||||
if (!pa) {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -1298,7 +1296,7 @@ void __system_property_read_callback2(const prop_info* pi,
|
||||
memcpy(value_buf, pi->value, len);
|
||||
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);
|
||||
if (serial == load_const_atomic(&(pi->serial), memory_order_relaxed)) {
|
||||
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.
|
||||
* 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.
|
||||
*/
|
||||
@@ -62,7 +62,7 @@ void __system_property_read_callback2(const prop_info *pi,
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
@@ -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. */
|
||||
#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);
|
||||
/* Deprecated. Use __system_property_read_callback2 instead. */
|
||||
/* Deprecated. Use __system_property_read_callback instead. */
|
||||
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);
|
||||
|
||||
__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);
|
||||
}
|
||||
|
||||
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
|
||||
pos->prev->next = pos->next;
|
||||
pos->next->prev = pos->prev;
|
||||
// Remove references
|
||||
pos->next = 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);
|
||||
}
|
||||
|
||||
@@ -14,17 +14,30 @@ struct list_head {
|
||||
void init_list_head(struct list_head *head);
|
||||
void list_insert(struct list_head *pos, struct list_head *node);
|
||||
void list_insert_end(struct list_head *head, struct list_head *node);
|
||||
void list_pop(struct list_head *pos);
|
||||
void list_pop_end(struct list_head *head);
|
||||
struct list_head *list_pop(struct list_head *pos);
|
||||
struct list_head *list_pop_end(struct list_head *head);
|
||||
|
||||
#define list_entry(ptr, type, member) ({ \
|
||||
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
|
||||
#define list_entry(pos, type, member) ({ \
|
||||
const typeof( ((type *)0)->member ) *__mptr = (pos); \
|
||||
(type *)( (char *)__mptr - offsetof(type,member) );})
|
||||
|
||||
#define list_for_each(pos, head) \
|
||||
for (pos = (head)->next; pos != (head); pos = pos->next)
|
||||
#define list_for_each(ptr, head, type, member) \
|
||||
ptr = list_entry((head)->next, type, member); \
|
||||
for (struct list_head *__ = (head)->next; __ != (head); __ = __->next, ptr = list_entry(__, type, member))
|
||||
|
||||
#define list_for_each_r(pos, head) \
|
||||
for (pos = (head)->prev; pos != (head); pos = pos->prev)
|
||||
#define list_for_each_r(ptr, head, type, member) \
|
||||
ptr = list_entry((head)->prev, type, member); \
|
||||
for (struct list_head *__ = (head)->prev; __ != (head); __ = __->prev, ptr = list_entry(__, type, member))
|
||||
|
||||
#define list_destory(head, type, member, func) ({ \
|
||||
struct list_head *node = head->next; \
|
||||
while(node != head) { \
|
||||
node = node->next; \
|
||||
if (func) func(list_entry(node->prev, line_list, pos)); \
|
||||
free(list_entry(node->prev, line_list, pos)); \
|
||||
} \
|
||||
head->next = head; \
|
||||
head->prev = head; \
|
||||
})
|
||||
|
||||
#endif
|
||||
119
jni/utils/misc.c
119
jni/utils/misc.c
@@ -221,30 +221,31 @@ void setup_sighandlers(void (*handler)(int)) {
|
||||
|
||||
/*
|
||||
fd == NULL -> Ignore output
|
||||
*fd == 0 -> Open pipe and set *fd to the read end
|
||||
*fd != 0 -> STDOUT (or STDERR) will be redirected to *fd
|
||||
*fd < 0 -> Open pipe and set *fd to the read end
|
||||
*fd >= 0 -> STDOUT (or STDERR) will be redirected to *fd
|
||||
*/
|
||||
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 == 0) {
|
||||
if (pipe(pipefd) == -1)
|
||||
if (*fd < 0) {
|
||||
if (xpipe2(pipefd, O_CLOEXEC) == -1)
|
||||
return -1;
|
||||
writeEnd = pipefd[1];
|
||||
// Give the read end of the pipe
|
||||
*fd = pipefd[0];
|
||||
} else {
|
||||
writeEnd = *fd;
|
||||
}
|
||||
}
|
||||
|
||||
int pid = fork();
|
||||
if (pid != 0) {
|
||||
if (writeEnd) close(writeEnd);
|
||||
close(writeEnd);
|
||||
return pid;
|
||||
}
|
||||
|
||||
if (fd) {
|
||||
if (writeEnd == 0) writeEnd = *fd;
|
||||
xdup2(writeEnd, STDOUT_FILENO);
|
||||
if (err) xdup2(writeEnd, STDERR_FILENO);
|
||||
}
|
||||
@@ -300,17 +301,14 @@ int cp_afc(const char *source, const char *target) {
|
||||
sfd = xopen(source, O_RDONLY);
|
||||
tfd = xopen(target, O_WRONLY | O_CREAT | O_TRUNC);
|
||||
xsendfile(tfd, sfd, NULL, buf.st_size);
|
||||
fchmod(tfd, buf.st_mode & 0777);
|
||||
fchown(tfd, buf.st_uid, buf.st_gid);
|
||||
fgetfilecon(sfd, &con);
|
||||
fsetfilecon(tfd, con);
|
||||
free(con);
|
||||
fclone_attr(sfd, tfd);
|
||||
close(sfd);
|
||||
close(tfd);
|
||||
} else if (S_ISLNK(buf.st_mode)) {
|
||||
char buffer[PATH_MAX];
|
||||
xreadlink(source, buffer, sizeof(buffer));
|
||||
xsymlink(buffer, target);
|
||||
lchown(target, buf.st_uid, buf.st_gid);
|
||||
lgetfilecon(source, &con);
|
||||
lsetfilecon(target, con);
|
||||
free(con);
|
||||
@@ -359,38 +357,10 @@ int clone_dir(const char *source, const char *target) {
|
||||
int rm_rf(const char *target) {
|
||||
if (access(target, F_OK) == -1)
|
||||
return 0;
|
||||
struct stat buf;
|
||||
xlstat(target, &buf);
|
||||
char *next;
|
||||
if (S_ISDIR(buf.st_mode)) {
|
||||
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;
|
||||
// Use external rm command, saves a lot of headache and issues
|
||||
char command[PATH_MAX];
|
||||
snprintf(command, sizeof(command), "rm -rf %s", target);
|
||||
return system(command);
|
||||
}
|
||||
|
||||
void clone_attr(const char *source, const char *target) {
|
||||
@@ -404,62 +374,23 @@ void clone_attr(const char *source, const char *target) {
|
||||
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) {
|
||||
socklen_t ucred_length = sizeof(*cred);
|
||||
if(getsockopt(fd, SOL_SOCKET, SO_PEERCRED, cred, &ucred_length))
|
||||
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) {
|
||||
char mnt[32];
|
||||
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 xread(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);
|
||||
DIR *xopendir(const char *name);
|
||||
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 xconnect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
|
||||
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 *xcalloc(size_t nmemb, 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 clone_dir(const char *source, 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 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 get_img_size(const char *img, int *used, int *total);
|
||||
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
|
||||
|
||||
@@ -82,10 +82,10 @@ ssize_t xxread(int fd, void *buf, size_t count) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
int xpipe(int pipefd[2]) {
|
||||
int ret = pipe(pipefd);
|
||||
int xpipe2(int pipefd[2], int flags) {
|
||||
int ret = pipe2(pipefd, flags);
|
||||
if (ret == -1) {
|
||||
PLOGE("pipe");
|
||||
PLOGE("pipe2");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -155,8 +155,8 @@ int xlisten(int sockfd, int backlog) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
int xaccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
|
||||
int fd = accept(sockfd, addr, addrlen);
|
||||
int xaccept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) {
|
||||
int fd = accept4(sockfd, addr, addrlen, flags);
|
||||
if (fd == -1) {
|
||||
PLOGE("accept");
|
||||
}
|
||||
@@ -307,7 +307,7 @@ int xrename(const char *oldpath, const char *newpath) {
|
||||
|
||||
int xmkdir(const char *pathname, mode_t mode) {
|
||||
int ret = mkdir(pathname, mode);
|
||||
if (ret == -1) {
|
||||
if (ret == -1 && errno != EEXIST) {
|
||||
PLOGE("mkdir %s %u", pathname, mode);
|
||||
}
|
||||
return ret;
|
||||
|
||||
94
scripts/addon.d.sh
Normal file
94
scripts/addon.d.sh
Normal file
@@ -0,0 +1,94 @@
|
||||
#!/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
|
||||
|
||||
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
|
||||
# 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
|
||||
#
|
||||
@@ -14,32 +14,20 @@
|
||||
# magisk binary The main binary for all Magisk operations.
|
||||
# It is also used to patch the sepolicy in the 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.
|
||||
# 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
|
||||
# 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
|
||||
#
|
||||
##########################################################################################
|
||||
|
||||
CWD=`pwd`
|
||||
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
|
||||
##########################################################################################
|
||||
# Functions
|
||||
##########################################################################################
|
||||
|
||||
# Call ui_print_wrap if exists, or else simply use echo
|
||||
# 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"
|
||||
}
|
||||
|
||||
# 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() {
|
||||
REGEX="s/^$1=//p"
|
||||
shift
|
||||
@@ -59,47 +74,62 @@ grep_prop() {
|
||||
|
||||
# --cpio-add <incpio> <mode> <entry> <infile>
|
||||
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() {
|
||||
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() {
|
||||
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
|
||||
[ -z $SOURCEDMODE ] && cd "`dirname "${BASH_SOURCE:-$0}"`"
|
||||
[ -z $SOURCEDMODE ] && cd "`dirname_wrap "${BASH_SOURCE:-$0}"`"
|
||||
chmod +x ./*
|
||||
|
||||
# Detect ARCH
|
||||
[ -d /system/lib64 ] && SYSTEMLIB=/system/lib64 || SYSTEMLIB=/system/lib
|
||||
##########################################################################################
|
||||
# Unpack
|
||||
##########################################################################################
|
||||
|
||||
ui_print_wrap "- Unpacking boot image"
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --unpack $BOOTIMAGE
|
||||
./magiskboot --unpack "$BOOTIMAGE"
|
||||
|
||||
case $? in
|
||||
1 )
|
||||
ui_print_wrap "! Unable to unpack boot image"
|
||||
exit 1
|
||||
abort_wrap "! Unable to unpack boot image"
|
||||
;;
|
||||
2 )
|
||||
ui_print_wrap "! Sony ELF32 format detected"
|
||||
ui_print_wrap "! Please use BootBridge from @AdrianDC to flash Magisk"
|
||||
exit 1
|
||||
abort_wrap "! Please use BootBridge from @AdrianDC to flash Magisk"
|
||||
;;
|
||||
3 )
|
||||
ui_print_wrap "! Sony ELF64 format detected"
|
||||
ui_print_wrap "! Stock kernel cannot be patched, please use a custom kernel"
|
||||
exit 1
|
||||
abort_wrap "! Stock kernel cannot be patched, please use a custom kernel"
|
||||
esac
|
||||
|
||||
##########################################################################################
|
||||
@@ -108,28 +138,28 @@ esac
|
||||
|
||||
# Test patch status and do restore, after this section, ramdisk.cpio.orig is guaranteed to exist
|
||||
ui_print_wrap "- Checking ramdisk status"
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --cpio-test ramdisk.cpio
|
||||
./magiskboot --cpio-test ramdisk.cpio
|
||||
case $? in
|
||||
0 ) # Stock boot
|
||||
ui_print_wrap "- Stock boot image detected!"
|
||||
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
|
||||
dd if=$BOOTIMAGE of=$STOCKDUMP
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --compress $STOCKDUMP
|
||||
dd if="$BOOTIMAGE" of=$STOCKDUMP
|
||||
./magiskboot --compress $STOCKDUMP
|
||||
cp -af ramdisk.cpio ramdisk.cpio.orig
|
||||
;;
|
||||
1 ) # Magisk patched
|
||||
ui_print_wrap "- Magisk patched image detected!"
|
||||
# Find SHA1 of stock boot image
|
||||
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`
|
||||
rm -f init.magisk.rc.old
|
||||
fi
|
||||
|
||||
OK=false
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --cpio-restore ramdisk.cpio
|
||||
./magiskboot --cpio-restore ramdisk.cpio
|
||||
if [ $? -eq 0 ]; then
|
||||
ui_print_wrap "- Ramdisk restored from internal backup"
|
||||
OK=true
|
||||
@@ -141,8 +171,8 @@ case $? in
|
||||
STOCKDUMP=/data/stock_boot_${SHA1}.img
|
||||
if [ -f ${STOCKDUMP}.gz ]; then
|
||||
ui_print_wrap "- Stock boot image backup found"
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --decompress ${STOCKDUMP}.gz stock_boot.img
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --unpack stock_boot.img
|
||||
./magiskboot --decompress ${STOCKDUMP}.gz stock_boot.img
|
||||
./magiskboot --unpack stock_boot.img
|
||||
rm -f stock_boot.img
|
||||
OK=true
|
||||
fi
|
||||
@@ -156,8 +186,7 @@ case $? in
|
||||
;;
|
||||
2 ) # Other patched
|
||||
ui_print_wrap "! Boot image patched by other programs!"
|
||||
ui_print_wrap "! Please restore stock boot image"
|
||||
exit 1
|
||||
abort_wrap "! Please restore stock boot image"
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -167,20 +196,12 @@ esac
|
||||
|
||||
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
|
||||
cpio_extract init.rc init.rc
|
||||
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
|
||||
./magiskboot --cpio-patch ramdisk.cpio $KEEPVERITY $KEEPFORCEENCRYPT
|
||||
|
||||
# sepolicy patches
|
||||
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
|
||||
rm -f sepolicy
|
||||
|
||||
@@ -190,11 +211,11 @@ if [ ! -z $SHA1 ]; then
|
||||
echo "# STOCKSHA1=$SHA1" >> init.magisk.rc
|
||||
fi
|
||||
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
|
||||
|
||||
# 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
|
||||
|
||||
@@ -205,16 +226,23 @@ rm -f ramdisk.cpio.orig
|
||||
# Hexpatches
|
||||
|
||||
# Remove Samsung RKP in stock kernel
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --hexpatch kernel \
|
||||
./magiskboot --hexpatch kernel \
|
||||
49010054011440B93FA00F71E9000054010840B93FA00F7189000054001840B91FA00F7188010054 \
|
||||
A1020054011440B93FA00F7140020054010840B93FA00F71E0010054001840B91FA00F7181010054
|
||||
|
||||
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
|
||||
ui_print_wrap "! Unable to repack boot image!"
|
||||
exit 1
|
||||
# Sign chromeos boot
|
||||
if [ -f chromeos ]; then
|
||||
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
|
||||
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --cleanup
|
||||
./magiskboot --cleanup
|
||||
|
||||
@@ -9,167 +9,41 @@
|
||||
#
|
||||
##########################################################################################
|
||||
|
||||
##########################################################################################
|
||||
# Preparation
|
||||
##########################################################################################
|
||||
|
||||
# Detect whether in boot mode
|
||||
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
|
||||
TMPDIR=/dev/tmp
|
||||
|
||||
INSTALLER=$TMPDIR/magisk
|
||||
INSTALLER=$TMPDIR/install
|
||||
COMMONDIR=$INSTALLER/common
|
||||
BOOTTMP=$TMPDIR/boottmp
|
||||
COREDIR=/magisk/.core
|
||||
CHROMEDIR=$INSTALLER/chromeos
|
||||
COREDIR=/magisk/.core
|
||||
|
||||
# Default permissions
|
||||
umask 022
|
||||
|
||||
##########################################################################################
|
||||
# Flashable update-binary preparation
|
||||
##########################################################################################
|
||||
|
||||
OUTFD=$2
|
||||
ZIP=$3
|
||||
|
||||
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
|
||||
|
||||
rm -rf $TMPDIR 2>/dev/null
|
||||
mkdir -p $INSTALLER
|
||||
cd $INSTALLER
|
||||
unzip -o "$ZIP"
|
||||
unzip -o "$ZIP" -d $INSTALLER 2>/dev/null
|
||||
|
||||
##########################################################################################
|
||||
# Functions
|
||||
##########################################################################################
|
||||
if [ ! -d "$COMMONDIR" ]; then
|
||||
echo "! Unable to extract zip file!"
|
||||
exit 1
|
||||
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
|
||||
}
|
||||
# Load utility fuctions
|
||||
. $COMMONDIR/util_functions.sh
|
||||
|
||||
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
|
||||
}
|
||||
get_outfd
|
||||
|
||||
##########################################################################################
|
||||
# Detection
|
||||
@@ -179,20 +53,13 @@ ui_print "************************"
|
||||
ui_print "* MAGISK_VERSION_STUB"
|
||||
ui_print "************************"
|
||||
|
||||
if [ ! -d "$COMMONDIR" ]; then
|
||||
ui_print "! Failed: Unable to extract zip file!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ui_print "- Mounting /system(ro), /cache, /data"
|
||||
ui_print "- Mounting /system, /vendor, /cache, /data"
|
||||
mount -o ro /system 2>/dev/null
|
||||
mount -o ro /vendor 2>/dev/null
|
||||
mount /cache 2>/dev/null
|
||||
mount /data 2>/dev/null
|
||||
|
||||
if [ ! -f '/system/build.prop' ]; then
|
||||
ui_print "! Failed: /system could not be mounted!"
|
||||
exit 1
|
||||
fi
|
||||
[ -f /system/build.prop ] || abort "! /system could not be mounted!"
|
||||
|
||||
# read override variables
|
||||
getvar KEEPVERITY
|
||||
@@ -202,36 +69,18 @@ getvar BOOTIMAGE
|
||||
# Check if system root is installed and remove
|
||||
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`
|
||||
# Detect version and architecture
|
||||
api_level_arch_detect
|
||||
|
||||
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
|
||||
[ $API -lt 21 ] && abort "! Magisk is only for Lollipop 5.0+ (SDK 21+)"
|
||||
|
||||
ui_print "- Device platform: $ARCH"
|
||||
|
||||
BINDIR=$INSTALLER/$ARCH
|
||||
chmod -R 755 $CHROMEDIR $BINDIR
|
||||
|
||||
$IS64BIT && SYSTEMLIB=/system/lib64 || SYSTEMLIB=/system/lib
|
||||
|
||||
find_boot_image
|
||||
if [ -z $BOOTIMAGE ]; then
|
||||
ui_print "! Unable to detect boot image"
|
||||
exit 1
|
||||
fi
|
||||
[ -z $BOOTIMAGE ] && abort "! Unable to detect boot image"
|
||||
|
||||
##########################################################################################
|
||||
# Environment
|
||||
@@ -245,16 +94,25 @@ is_mounted /data && MAGISKBIN=/data/magisk || MAGISKBIN=/cache/data_bin
|
||||
rm -rf $MAGISKBIN 2>/dev/null
|
||||
mkdir -p $MAGISKBIN
|
||||
cp -af $BINDIR/. $COMMONDIR/. $MAGISKBIN
|
||||
|
||||
cp -af $CHROMEDIR $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
|
||||
##########################################################################################
|
||||
|
||||
$BOOTMODE || recovery_actions
|
||||
|
||||
# Fix SuperSU.....
|
||||
$BOOTMODE && $BINDIR/magiskpolicy --live "allow fsck * * *"
|
||||
$BOOTMODE && $MAGISKBIN/magisk magiskpolicy --live "allow fsck * * *"
|
||||
|
||||
if (is_mounted /data); then
|
||||
IMG=/data/magisk.img
|
||||
@@ -267,21 +125,20 @@ if [ -f $IMG ]; then
|
||||
ui_print "- $IMG detected!"
|
||||
else
|
||||
ui_print "- Creating $IMG"
|
||||
$BINDIR/magisk --createimg $IMG 64M
|
||||
$MAGISKBIN/magisk --createimg $IMG 64M
|
||||
fi
|
||||
|
||||
mount_image $IMG /magisk
|
||||
if (! is_mounted /magisk); then
|
||||
ui_print "! Magisk image mount failed..."
|
||||
exit 1
|
||||
if ! is_mounted /magisk; then
|
||||
ui_print "- Mounting $IMG to /magisk"
|
||||
MAGISKLOOP=`$MAGISKBIN/magisk --mountimg $IMG /magisk`
|
||||
fi
|
||||
MAGISKLOOP=$LOOPDEVICE
|
||||
is_mounted /magisk || abort "! Magisk image mount failed..."
|
||||
|
||||
# Core folders
|
||||
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
|
||||
chown -R 0.0 $COREDIR/post-fs-data.d $COREDIR/service.d
|
||||
chmod 755 $COREDIR/post-fs-data.d $COREDIR/service.d
|
||||
chown 0.0 $COREDIR/post-fs-data.d $COREDIR/service.d
|
||||
|
||||
# Legacy cleanup
|
||||
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
|
||||
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
|
||||
mv /data/stock_boot.img $STOCKDUMP
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB $BINDIR/magiskboot --compress $STOCKDUMP
|
||||
$MAGISKBIN/magiskboot --compress $STOCKDUMP
|
||||
fi
|
||||
|
||||
SOURCEDMODE=true
|
||||
cd $MAGISKBIN
|
||||
|
||||
# Source the boot patcher
|
||||
. $COMMONDIR/boot_patch.sh $BOOTIMAGE
|
||||
. $COMMONDIR/boot_patch.sh "$BOOTIMAGE"
|
||||
|
||||
# Sign chromeos boot
|
||||
if [ -f chromeos ]; then
|
||||
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*
|
||||
if [ -f stock_boot* ]; then
|
||||
rm -f /data/stock_boot* 2>/dev/null
|
||||
mv stock_boot* /data
|
||||
fi
|
||||
|
||||
ui_print "- Flashing new boot image"
|
||||
if [ -L $BOOTIMAGE ]; then
|
||||
dd if=new-boot.img of=$BOOTIMAGE bs=4096
|
||||
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
|
||||
cat new-boot.img /dev/zero | dd of="$BOOTIMAGE" bs=4096 >/dev/null 2>&1
|
||||
fi
|
||||
rm -f new-boot.img
|
||||
|
||||
cd /
|
||||
|
||||
if ! $BOOTMODE; then
|
||||
ui_print "- Unmounting partitions"
|
||||
umount /magisk
|
||||
losetup -d $MAGISKLOOP 2>/dev/null
|
||||
$MAGISKBIN/magisk --umountimg /magisk $MAGISKLOOP
|
||||
rmdir /magisk
|
||||
umount /system
|
||||
recovery_cleanup
|
||||
fi
|
||||
|
||||
ui_print "- Done"
|
||||
|
||||
@@ -8,120 +8,103 @@
|
||||
# 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 will try to do restoration in the following order:
|
||||
# 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)
|
||||
# 3. Remove added files in ramdisk, modified files are remained intact. By doing so, Magisk
|
||||
# will not be started at boot, but not removed clean enough
|
||||
#
|
||||
# Finally, this uninstaller will remove all Magisk related files
|
||||
# This script will try to do restoration with the following:
|
||||
# 1-1. Find and restore the original stock boot image dump (OTA proof)
|
||||
# 1-2. If 1-1 fails, restore ramdisk from the internal backup
|
||||
# (ramdisk fully restored, not OTA friendly)
|
||||
# 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
|
||||
# not be started at boot, but this isn't actually 100% cleaned up
|
||||
# 2. Remove all Magisk related files
|
||||
# (The list is LARGE, most likely due to bad decision in early versions
|
||||
# the 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
|
||||
# Useful when wrapped in flashable zip
|
||||
ui_print_wrap() {
|
||||
type ui_print >/dev/null 2>&1 && ui_print "$1" || echo "$1"
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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_./-]*'`
|
||||
# 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
|
||||
}
|
||||
|
||||
# Environments
|
||||
# Set permissions
|
||||
chmod -R 755 $CHROMEDIR/futility $MAGISKBIN 2>/dev/null
|
||||
if [ ! -d $MAGISKBIN -o ! -f $MAGISKBIN/magiskboot -o ! -f $MAGISKBIN/util_functions.sh ]; then
|
||||
ui_print_wrap "! Cannot find $MAGISKBIN"
|
||||
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_boot_image
|
||||
if [ -z "$BOOTIMAGE" ]; then
|
||||
ui_print_wrap "! Unable to detect boot image"
|
||||
exit 1
|
||||
fi
|
||||
[ -z $BOOTIMAGE ] && abort "! Unable to detect boot image"
|
||||
|
||||
ui_print_wrap "- Found Boot Image: $BOOTIMAGE"
|
||||
|
||||
cd $MAGISKBIN
|
||||
|
||||
ui_print_wrap "- Unpacking boot image"
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --unpack $BOOTIMAGE
|
||||
if [ $? -ne 0 ]; then
|
||||
ui_print_wrap "! Unable to unpack boot image"
|
||||
exit 1
|
||||
fi
|
||||
./magiskboot --unpack "$BOOTIMAGE"
|
||||
[ $? -ne 0 ] && abort_wrap "! Unable to unpack boot image"
|
||||
|
||||
# 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
|
||||
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
|
||||
mv /data/stock_boot.img $STOCKDUMP
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --compress $STOCKDUMP
|
||||
./magiskboot --compress $STOCKDUMP
|
||||
fi
|
||||
|
||||
# Detect boot image state
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --cpio-test ramdisk.cpio
|
||||
./magiskboot --cpio-test ramdisk.cpio
|
||||
case $? in
|
||||
0 )
|
||||
0 ) # Stock boot
|
||||
ui_print_wrap "- Stock boot image detected!"
|
||||
ui_print_wrap "! Magisk is not installed!"
|
||||
exit
|
||||
;;
|
||||
1 )
|
||||
1 ) # Magisk patched
|
||||
ui_print_wrap "- Magisk patched image detected!"
|
||||
# Find SHA1 of stock boot image
|
||||
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`
|
||||
[ ! -z $SHA1 ] && STOCKDUMP=/data/stock_boot_${SHA1}.img
|
||||
rm -f init.magisk.rc.old
|
||||
fi
|
||||
[ ! -z $SHA1 ] && STOCKDUMP=/data/stock_boot_${SHA1}.img
|
||||
if [ -f ${STOCKDUMP}.gz ]; then
|
||||
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
|
||||
ui_print_wrap "! Boot image backup unavailable"
|
||||
ui_print_wrap "- Restoring ramdisk with backup"
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --cpio-restore ramdisk.cpio
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB ./magiskboot --repack $BOOTIMAGE stock_boot.img
|
||||
./magiskboot --cpio-restore ramdisk.cpio
|
||||
./magiskboot --repack $BOOTIMAGE stock_boot.img
|
||||
fi
|
||||
;;
|
||||
2 ) # Other patched
|
||||
ui_print_wrap "! Boot image patched by other programs!"
|
||||
ui_print_wrap "! Cannot uninstall with this uninstaller"
|
||||
exit 1
|
||||
abort_wrap "! Cannot uninstall with this uninstaller"
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -138,10 +121,10 @@ if [ -f chromeos ]; then
|
||||
fi
|
||||
|
||||
ui_print_wrap "- Flashing stock/reverted image"
|
||||
if [ -L $BOOTIMAGE ]; then
|
||||
dd if=stock_boot.img of=$BOOTIMAGE bs=4096
|
||||
if [ -L "$BOOTIMAGE" ]; then
|
||||
dd if=stock_boot.img of="$BOOTIMAGE" bs=4096
|
||||
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
|
||||
rm -f stock_boot.img
|
||||
|
||||
|
||||
@@ -8,100 +8,49 @@
|
||||
#
|
||||
##########################################################################################
|
||||
|
||||
INSTALLER=/tmp/uninstall
|
||||
##########################################################################################
|
||||
# Preparation
|
||||
##########################################################################################
|
||||
|
||||
BOOTMODE=false
|
||||
INSTALLER=/tmp/uninstall
|
||||
# Default permissions
|
||||
umask 022
|
||||
|
||||
##########################################################################################
|
||||
# Flashable update-binary preparation
|
||||
##########################################################################################
|
||||
|
||||
OUTFD=$2
|
||||
ZIP=$3
|
||||
|
||||
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
|
||||
|
||||
rm -rf $INSTALLER 2>/dev/null
|
||||
mkdir -p $INSTALLER
|
||||
cd $INSTALLER
|
||||
unzip -o "$ZIP"
|
||||
unzip -o "$ZIP" -d $INSTALLER 2>/dev/null
|
||||
|
||||
##########################################################################################
|
||||
# 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
|
||||
if [ ! -f $INSTALLER/util_functions.sh ]; then
|
||||
echo "! Failed: Unable to extract zip file!"
|
||||
exit 1
|
||||
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
|
||||
}
|
||||
# Load utility functions
|
||||
. $INSTALLER/util_functions.sh
|
||||
|
||||
get_outfd
|
||||
|
||||
##########################################################################################
|
||||
# Main
|
||||
##########################################################################################
|
||||
|
||||
ui_print "*****************************"
|
||||
ui_print "************************"
|
||||
ui_print " Magisk Uninstaller "
|
||||
ui_print "*****************************"
|
||||
ui_print "************************"
|
||||
|
||||
if [ ! -d "$INSTALLER/arm" ]; then
|
||||
ui_print "! Failed: Unable to extract zip file!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ui_print "- Mounting /system(ro), /cache, /data"
|
||||
ui_print "- Mounting /system, /vendor, /cache, /data"
|
||||
mount -o ro /system 2>/dev/null
|
||||
mount -o ro /vendor 2>/dev/null
|
||||
mount /cache 2>/dev/null
|
||||
mount /data 2>/dev/null
|
||||
|
||||
if [ ! -f '/system/build.prop' ]; then
|
||||
ui_print "! Failed: /system could not be mounted!"
|
||||
exit 1
|
||||
fi
|
||||
[ -f /system/build.prop ] || abort "! /system could not be mounted!"
|
||||
|
||||
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;
|
||||
api_level_arch_detect
|
||||
|
||||
ui_print "- Device platform: $ARCH"
|
||||
CHROMEDIR=$INSTALLER/chromeos
|
||||
@@ -111,12 +60,20 @@ BINDIR=$INSTALLER/$ARCH
|
||||
# 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
|
||||
rm -rf /data/magisk 2>/dev/null
|
||||
mkdir -p /data/magisk 2>/dev/null
|
||||
cp -af $BINDIR/. $CHROMEDIR /data/magisk
|
||||
rm -rf $MAGISKBIN 2>/dev/null
|
||||
mkdir -p $MAGISKBIN
|
||||
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
|
||||
recovery_cleanup
|
||||
else
|
||||
ui_print "! Data unavailable"
|
||||
ui_print "! Placing uninstall script to /cache"
|
||||
@@ -128,6 +85,5 @@ else
|
||||
reboot
|
||||
fi
|
||||
|
||||
umount /system
|
||||
ui_print "- Done"
|
||||
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