1
mirror of https://github.com/topjohnwu/Magisk synced 2025-10-31 10:40:52 +01:00

Compare commits

...

21 Commits
v14.2 ... v14.3

Author SHA1 Message Date
topjohnwu
cdc5d983f3 Bump MagiskManager version 2017-10-15 03:21:33 +08:00
topjohnwu
96688e4dac Fix proper Lollipop selinux support 2017-10-14 22:37:02 +08:00
topjohnwu
28a945fee9 Fix SEGFAULT in magisk log dumper 2017-10-14 21:10:52 +08:00
topjohnwu
c7e777255a Reduce unnecessary stack memory allocation 2017-10-14 21:10:51 +08:00
topjohnwu
2dd4cf040e Prevent multiple process clashes to start daemon 2017-10-14 21:10:51 +08:00
topjohnwu
d1b9eca5eb Fix bug that cause boot delay 2017-10-14 00:19:13 +08:00
topjohnwu
594a67fe28 Cleanup and add more xwraps 2017-10-14 00:08:12 +08:00
topjohnwu
cddeaffada Remove err_handler 2017-10-13 22:26:42 +08:00
topjohnwu
2a8898e7c3 Fix lz4 legacy on LG zImages 2017-10-13 00:18:40 +08:00
topjohnwu
ce3f3b09b4 Brute force resizeimg for Crapsung device :) 2017-10-12 14:32:40 +08:00
topjohnwu
fe4b3df7e9 Fix selinux context on Magisk files 2017-10-12 14:32:40 +08:00
topjohnwu
25bdbcf526 Add new file operations 2017-10-12 14:32:40 +08:00
topjohnwu
df7eaa5598 Reduce update-binary size 2017-10-11 02:26:43 +08:00
topjohnwu
bb7099376b Improve daemon startup and log management 2017-10-11 02:26:28 +08:00
topjohnwu
0327fd9710 Restart MagiskHide if daemon restarted 2017-10-10 19:49:15 +08:00
topjohnwu
e645c6e465 Refactor resetprop 2017-10-10 02:04:50 +08:00
topjohnwu
78a3d36ccc Allow devices without separate vendor partition 2017-10-09 21:53:50 +08:00
topjohnwu
3942858ccd Introduce a single general purpose logcat monitor 2017-10-09 05:39:40 +08:00
topjohnwu
03c8d716cc Introduce Invincible Mode: Self recover service 2017-10-08 22:00:22 +08:00
topjohnwu
60181c4fcb MagiskManager -> java 2017-10-07 22:48:16 +08:00
topjohnwu
c215447405 Fix Pixel C installation 2017-10-07 22:08:10 +08:00
46 changed files with 1299 additions and 1767 deletions

3
.gitignore vendored
View File

@@ -2,6 +2,7 @@ obj/
libs/
*.zip
*.jks
*.apk
# Copied binaries
# Built binaries
ziptools/zipadjust

2
.gitmodules vendored
View File

@@ -11,7 +11,7 @@
path = jni/magiskpolicy
url = https://github.com/topjohnwu/magiskpolicy.git
[submodule "MagiskManager"]
path = MagiskManager
path = java
url = https://github.com/topjohnwu/MagiskManager.git
[submodule "jni/busybox"]
path = jni/external/busybox

Submodule MagiskManager deleted from 773c24b7fc

View File

@@ -45,7 +45,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
## Credits
**MagiskManager** (`MagiskManager`)
**MagiskManager** (`java`)
* Copyright 2016-2017, John Wu (@topjohnwu)
* All contributors and translators

View File

@@ -51,6 +51,10 @@ def zip_with_msg(zipfile, source, target):
print('zip: {} -> {}'.format(source, target))
zipfile.write(source, target)
def cp(source, target):
print('cp: {} -> {}'.format(source, target))
shutil.copyfile(source, target)
def build_all(args):
build_binary(args)
build_apk(args)
@@ -75,26 +79,23 @@ def build_apk(args):
for key in ['public.certificate.x509.pem', 'private.key.pk8']:
source = os.path.join('ziptools', key)
target = os.path.join('MagiskManager', 'app', 'src', 'main', 'assets', key)
print('cp: {} -> {}'.format(source, target))
shutil.copyfile(source, target)
target = os.path.join('java', 'app', 'src', 'main', 'assets', key)
cp(source, target)
for script in ['magisk_uninstaller.sh', 'util_functions.sh']:
source = os.path.join('scripts', script)
target = os.path.join('MagiskManager', 'app', 'src', 'main', 'assets', script)
print('cp: {} -> {}'.format(source, target))
shutil.copyfile(source, target)
target = os.path.join('java', 'app', 'src', 'main', 'assets', script)
cp(source, target)
os.chdir('MagiskManager')
os.chdir('java')
# Build unhide app and place in assets
proc = subprocess.run('{} unhide::assembleRelease'.format(os.path.join('.', 'gradlew')), shell=True)
proc = subprocess.run('{} unhide:assembleRelease'.format(os.path.join('.', 'gradlew')), shell=True)
if proc.returncode != 0:
error('Build Magisk Manager failed!')
source = os.path.join('unhide', 'build', 'outputs', 'apk', 'release', 'unhide-release-unsigned.apk')
target = os.path.join('app', 'src', 'main', 'assets', 'unhide.apk')
print('cp: {} -> {}'.format(source, target))
shutil.copyfile(source, target)
cp(source, target)
print('')
@@ -102,7 +103,7 @@ def build_apk(args):
if not os.path.exists(os.path.join('..', 'release_signature.jks')):
error('Please generate a java keystore and place it in \'release_signature.jks\'')
proc = subprocess.run('{} app::assembleRelease'.format(os.path.join('.', 'gradlew')), shell=True)
proc = subprocess.run('{} app:assembleRelease'.format(os.path.join('.', 'gradlew')), shell=True)
if proc.returncode != 0:
error('Build Magisk Manager failed!')
@@ -141,16 +142,26 @@ def build_apk(args):
silentremove(unsigned)
silentremove(aligned)
else:
proc = subprocess.run('{} app::assembleDebug'.format(os.path.join('.', 'gradlew')), shell=True)
proc = subprocess.run('{} app:assembleDebug'.format(os.path.join('.', 'gradlew')), shell=True)
if proc.returncode != 0:
error('Build Magisk Manager failed!')
# Return to upper directory
os.chdir('..')
def sign_adjust_zip(unsigned, output):
def build_snet(args):
os.chdir('java')
proc = subprocess.run('{} snet:assembleRelease'.format(os.path.join('.', 'gradlew')), shell=True)
if proc.returncode != 0:
error('Build snet extention failed!')
source = os.path.join('snet', 'build', 'outputs', 'apk', 'release', 'snet-release-unsigned.apk')
target = os.path.join('..', 'snet.apk')
print('')
cp(source, target)
os.chdir('..')
zipsigner = os.path.join('ziptools', 'zipsigner', 'build', 'libs', 'zipsigner.jar')
def sign_adjust_zip(unsigned, output):
jarsigner = os.path.join('java', 'jarsigner', 'build', 'libs', 'jarsigner-fat.jar')
if os.name != 'nt' and not os.path.exists(os.path.join('ziptools', 'zipadjust')):
header('* Building zipadjust')
@@ -158,13 +169,13 @@ def sign_adjust_zip(unsigned, output):
proc = subprocess.run('gcc -o ziptools/zipadjust ziptools/zipadjust_src/*.c -lz', shell=True)
if proc.returncode != 0:
error('Build zipadjust failed!')
if not os.path.exists(zipsigner):
header('* Building zipsigner.jar')
os.chdir(os.path.join('ziptools', 'zipsigner'))
proc = subprocess.run('{} shadowJar'.format(os.path.join('.', 'gradlew')), shell=True)
if not os.path.exists(jarsigner):
header('* Building jarsigner-fat.jar')
os.chdir('java')
proc = subprocess.run('{} jarsigner:shadowJar'.format(os.path.join('.', 'gradlew')), shell=True)
if proc.returncode != 0:
error('Build zipsigner.jar failed!')
os.chdir(os.path.join('..', '..'))
error('Build jarsigner-fat.jar failed!')
os.chdir('..')
header('* Signing / Adjusting Zip')
@@ -172,7 +183,7 @@ def sign_adjust_zip(unsigned, output):
privateKey = os.path.join('ziptools', 'private.key.pk8')
# Unsigned->signed
proc = subprocess.run(['java', '-jar', zipsigner,
proc = subprocess.run(['java', '-jar', jarsigner,
publicKey, privateKey, unsigned, 'tmp_signed.zip'])
if proc.returncode != 0:
error('First sign flashable zip failed!')
@@ -183,7 +194,7 @@ def sign_adjust_zip(unsigned, output):
error('Adjust flashable zip failed!')
# Adjusted -> output
proc = subprocess.run(['java', '-jar', zipsigner,
proc = subprocess.run(['java', '-jar', jarsigner,
"-m", publicKey, privateKey, 'tmp_adjusted.zip', output])
if proc.returncode != 0:
error('Second sign flashable zip failed!')
@@ -199,15 +210,15 @@ def gen_update_binary():
if not os.path.exists(binary):
error('Please build \'binary\' before zipping!')
with open(binary, 'rb') as b64xz:
update_bin.append('#! /sbin/sh\nEX_ARM=')
update_bin.append(''.join("\\\\x{:02X}".format(c) for c in b64xz.read()))
update_bin.append('#! /sbin/sh\nEX_ARM=\'')
update_bin.append(''.join("\\x{:02X}".format(c) for c in b64xz.read()))
binary = os.path.join('libs', 'x86', 'b64xz')
with open(binary, 'rb') as b64xz:
update_bin.append('\nEX_X86=')
update_bin.append(''.join("\\\\x{:02X}".format(c) for c in b64xz.read()))
update_bin.append('\'\nEX_X86=\'')
update_bin.append(''.join("\\x{:02X}".format(c) for c in b64xz.read()))
binary = os.path.join('libs', 'armeabi-v7a', 'busybox')
with open(binary, 'rb') as busybox:
update_bin.append('\nBB_ARM=')
update_bin.append('\'\nBB_ARM=')
update_bin.append(base64.b64encode(lzma.compress(busybox.read())).decode('ascii'))
binary = os.path.join('libs', 'x86', 'busybox')
with open(binary, 'rb') as busybox:
@@ -243,7 +254,7 @@ def zip_main(args):
zip_with_msg(zipf, source, target)
# APK
source = os.path.join('MagiskManager', 'app', 'build', 'outputs', 'apk',
source = os.path.join('java', '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)
@@ -328,20 +339,21 @@ def zip_uninstaller(args):
def cleanup(args):
if len(args.target) == 0:
args.target = ['binary', 'apk', 'zip']
args.target = ['binary', 'java', 'zip']
if 'binary' in args.target:
header('* Cleaning Magisk binaries')
header('* Cleaning binaries')
subprocess.run(os.path.join(os.environ['ANDROID_HOME'], 'ndk-bundle', 'ndk-build') + ' clean', shell=True)
if 'apk' in args.target:
header('* Cleaning Magisk Manager')
os.chdir('MagiskManager')
if 'java' in args.target:
header('* Cleaning java')
os.chdir('java')
subprocess.run('{} clean'.format(os.path.join('.', 'gradlew')), shell=True)
os.chdir('..')
silentremove('snet.apk')
if 'zip' in args.target:
header('* Cleaning created zip files')
header('* Cleaning zip files')
for f in os.listdir('.'):
if '.zip' in f:
print('rm {}'.format(f))
@@ -364,6 +376,9 @@ binary_parser.set_defaults(func=build_binary)
apk_parser = subparsers.add_parser('apk', help='build Magisk Manager APK')
apk_parser.set_defaults(func=build_apk)
snet_parser = subparsers.add_parser('snet', help='build snet extention for Magisk Manager')
snet_parser.set_defaults(func=build_snet)
zip_parser = subparsers.add_parser('zip', help='zip and sign Magisk into a flashable zip')
zip_parser.add_argument('versionString')
zip_parser.add_argument('versionCode', type=int)
@@ -372,7 +387,7 @@ 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')
clean_parser = subparsers.add_parser('clean', help='clean [target...] targets: binary java zip')
clean_parser.add_argument('target', nargs='*')
clean_parser.set_defaults(func=cleanup)

1
java Submodule

Submodule java added at 13bf1b27b4

View File

@@ -40,6 +40,7 @@ LOCAL_SRC_FILES := \
utils/xwrap.c \
utils/list.c \
utils/img.c \
utils/file.c \
magiskhide/magiskhide.c \
magiskhide/proc_monitor.c \
magiskhide/hide_utils.c \
@@ -97,10 +98,12 @@ LOCAL_C_INCLUDES := jni/include $(LIBSEPOL)
LOCAL_SRC_FILES := \
magiskinit.c \
magiskboot/boot_utils.c \
utils/file.c \
utils/xwrap.c \
magiskpolicy/rules.c \
magiskpolicy/sepolicy.c \
magiskpolicy/api.c
LOCAL_CFLAGS := -DNO_SELINUX
LOCAL_LDFLAGS := -static
include $(BUILD_EXECUTABLE)
endif

File diff suppressed because it is too large Load Diff

View File

@@ -21,13 +21,12 @@
#include "utils.h"
#include "daemon.h"
#include "magiskpolicy.h"
#include "resetprop.h"
pthread_t sepol_patch;
int is_restart = 0;
static void *request_handler(void *args) {
// Setup the default error handler for threads
err_handler = exit_thread;
int client = *((int *) args);
free(args);
client_request req = read_int(client);
@@ -114,25 +113,22 @@ static void *large_sepol_patch(void *args) {
return NULL;
}
void start_daemon(int client) {
// Launch the daemon, create new session, set proper context
if (getuid() != UID_ROOT || getgid() != UID_ROOT) {
fprintf(stderr, "Starting daemon requires root: %s\n", strerror(errno));
PLOGE("start daemon");
}
static void *start_magisk_hide(void *args) {
launch_magiskhide(-1);
return NULL;
}
switch (fork()) {
case -1:
PLOGE("fork");
case 0:
break;
default:
return;
void auto_start_magiskhide() {
char *hide_prop = getprop2(MAGISKHIDE_PROP, 1);
if (hide_prop == NULL || strcmp(hide_prop, "0") != 0) {
pthread_t thread;
xpthread_create(&thread, NULL, start_magisk_hide, NULL);
pthread_detach(thread);
}
free(hide_prop);
}
// First close the client, it's useless for us
close(client);
xsetsid();
void start_daemon() {
setcon("u:r:su:s0");
umask(0);
int fd = xopen("/dev/null", O_RDWR | O_CLOEXEC);
@@ -146,32 +142,36 @@ void start_daemon(int client) {
sepol_med_rules();
dump_policydb(SELINUX_LOAD);
// Continue the larger patch in another thread, we will join later
pthread_create(&sepol_patch, NULL, large_sepol_patch, NULL);
struct sockaddr_un sun;
fd = setup_socket(&sun);
xbind(fd, (struct sockaddr*) &sun, sizeof(sun));
if (xbind(fd, (struct sockaddr*) &sun, sizeof(sun)) == -1)
exit(1);
xlisten(fd, 10);
if ((is_restart = access(UNBLOCKFILE, F_OK) == 0)) {
// Restart stuffs if the daemon is restarted
exec_command_sync("logcat", "-b", "all", "-c", NULL);
auto_start_magiskhide();
start_debug_log();
}
// Start the log monitor
monitor_logs();
// Continue the larger patch in another thread, we will join later
xpthread_create(&sepol_patch, NULL, large_sepol_patch, NULL);
LOGI("Magisk v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") daemon started\n");
// Change process name
strcpy(argv0, "magisk_daemon");
// The root daemon should not do anything if an error occurs
// It should stay intact under any circumstances
err_handler = do_nothing;
LOGI("Magisk v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") daemon started\n");
// Unlock all blocks for rw
unlock_blocks();
// Setup links under /sbin
xmount(NULL, "/", NULL, MS_REMOUNT, NULL);
create_links(NULL, "/sbin");
xchmod("/sbin", 0755);
xmkdir("/magisk", 0755);
xmount(NULL, "/", NULL, MS_REMOUNT | MS_RDONLY, NULL);
// Notifiy init the daemon is started
close(xopen(UNBLOCKFILE, O_RDONLY | O_CREAT));
// Loop forever to listen for requests
while(1) {
@@ -188,12 +188,21 @@ void start_daemon(int client) {
int connect_daemon() {
struct sockaddr_un sun;
int fd = setup_socket(&sun);
if (connect(fd, (struct sockaddr*) &sun, sizeof(sun))) {
/* If we cannot access the daemon, we start the daemon
* since there is no clear entry point when the daemon should be started
*/
LOGD("client: connect fail, try launching new daemon process\n");
start_daemon(fd);
if (xconnect(fd, (struct sockaddr*) &sun, sizeof(sun))) {
// If we cannot access the daemon, we start a daemon in the child process if possible
if (getuid() != UID_ROOT || getgid() != UID_ROOT) {
fprintf(stderr, "No daemon is currently running!\n");
exit(1);
}
if (xfork() == 0) {
LOGD("client: connect fail, try launching new daemon process\n");
close(fd);
xsetsid();
start_daemon();
}
do {
// Wait for 10ms
usleep(10);

View File

@@ -1,8 +1,8 @@
/* log_monitor.c - New thread to monitor logcat
*
* Open a new thread to call logcat and get logs with tag "Magisk"
* Also, write the logs to a log file for debugging purpose
*
* A universal logcat monitor for many usages. Add listeners to the list,
* and the pointer of the new log line will be sent through pipes to trigger
* asynchronous events without polling
*/
#include <stdio.h>
@@ -13,33 +13,146 @@
#include "magisk.h"
#include "utils.h"
#include "daemon.h"
int logcat_events[] = { -1, -1, -1 };
extern int is_restart;
#ifdef MAGISK_DEBUG
static int debug_log_pid, debug_log_fd;
#endif
static void *logger_thread(void *args) {
// Setup error handler
err_handler = exit_thread;
int log_fd = -1, log_pid;
char line[4096];
rename(LOGFILE, LASTLOG);
int log_fd, log_pid;
log_fd = xopen(LOGFILE, O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC, 0644);
LOGD("log_monitor: logger start");
while (1) {
// Start logcat
log_pid = exec_command(0, &log_fd, NULL, "logcat", "-v", "thread", "Magisk:I", "*:S", NULL);
if (log_pid > 0)
waitpid(log_pid, NULL, 0);
// For some reason it went here, clear buffer and restart
exec_command_sync("logcat", "-c", NULL);
log_pid = exec_command(0, &log_fd, NULL, "logcat", "-b", "all" , "-v", "threadtime", "-s", "am_proc_start", "Magisk", NULL);
while (fdgets(line, sizeof(line), log_fd)) {
for (int i = 0; i < (sizeof(logcat_events) / sizeof(int)); ++i) {
if (logcat_events[i] > 0) {
char *s = strdup(line);
xwrite(logcat_events[i], &s, sizeof(s));
}
}
if (kill(log_pid, 0))
break;
}
// Clear buffer if restart required
exec_command_sync("logcat", "-b", "all", "-c", NULL);
}
// Should never be here, but well...
return NULL;
}
/* Start a new thread to monitor logcat and dump to logfile */
static void *magisk_log_thread(void *args) {
int have_data = 0;
// Temp buffer for logs before we have data access
struct vector logs;
vec_init(&logs);
FILE *log;
int pipefd[2];
if (xpipe2(pipefd, O_CLOEXEC) == -1)
return NULL;
// Register our listener
logcat_events[LOG_EVENT] = pipefd[1];
LOGD("log_monitor: magisk log dumper start");
for (char *line; xxread(pipefd[0], &line, sizeof(line)) > 0; free(line)) {
char *ss;
if ((ss = strstr(line, " Magisk")) && (ss[-1] != 'D') && (ss[-1] != 'V')) {
if (!have_data) {
if ((have_data = check_data())) {
// Dump buffered logs to file
if (!is_restart)
rename(LOGFILE, LASTLOG);
log = xfopen(LOGFILE, "a");
setbuf(log, NULL);
char *tmp;
vec_for_each(&logs, tmp) {
fprintf(log, "%s", tmp);
free(tmp);
}
vec_destroy(&logs);
} else {
vec_push_back(&logs, strdup(line));
}
}
if (have_data)
fprintf(log, "%s", line);
}
}
return NULL;
}
static void *debug_magisk_log_thread(void *args) {
FILE *log = xfopen(DEBUG_LOG, "a");
setbuf(log, NULL);
int pipefd[2];
if (xpipe2(pipefd, O_CLOEXEC) == -1)
return NULL;
LOGD("log_monitor: debug log dumper start");
// Register our listener
logcat_events[DEBUG_EVENT] = pipefd[1];
for (char *line; xxread(pipefd[0], &line, sizeof(line)) > 0; free(line)) {
char *ss;
if ((ss = strstr(line, "Magisk")))
fprintf(log, "%s", line);
}
return NULL;
}
/* Start new threads to monitor logcat and dump to logfile */
void monitor_logs() {
pthread_t thread;
// Start log file dumper before monitor
xpthread_create(&thread, NULL, magisk_log_thread, NULL);
pthread_detach(thread);
// Start logcat monitor
xpthread_create(&thread, NULL, logger_thread, NULL);
pthread_detach(thread);
}
void start_debug_full_log() {
#ifdef MAGISK_DEBUG
// Log everything initially
debug_log_fd = xopen(DEBUG_LOG, O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC, 0644);
debug_log_pid = exec_command(0, &debug_log_fd, NULL, "logcat", "-v", "threadtime", NULL);
close(debug_log_fd);
#endif
}
void stop_debug_full_log() {
#ifdef MAGISK_DEBUG
// Stop recording the boot logcat after every boot task is done
kill(debug_log_pid, SIGTERM);
waitpid(debug_log_pid, NULL, 0);
pthread_t thread;
// Start debug thread
xpthread_create(&thread, NULL, debug_magisk_log_thread, NULL);
pthread_detach(thread);
start_debug_log();
#endif
}
void start_debug_log() {
#ifdef MAGISK_DEBUG
pthread_t thread;
// Start debug thread
xpthread_create(&thread, NULL, debug_magisk_log_thread, NULL);
pthread_detach(thread);
#endif
}

View File

@@ -32,10 +32,6 @@ int create_links(const char *bin, const char *path) {
return ret;
}
// Global error hander function
// Should be changed each thread/process
__thread void (*err_handler)(void);
static void usage() {
fprintf(stderr,
"Magisk v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") (by topjohnwu) multi-call binary\n"
@@ -54,11 +50,12 @@ static void usage() {
" --resizeimg IMG SIZE resize ext4 image. SIZE is interpreted in MB\n"
" --mountimg IMG PATH mount IMG to PATH and prints the loop device\n"
" --umountimg PATH LOOP unmount PATH and delete LOOP device\n"
" --[boot stage] start boot stage service\n"
" --[init service] start init service\n"
" --unlock-blocks set BLKROSET flag to OFF for all block devices\n"
" --restorecon fix selinux context on Magisk files and folders\n"
"\n"
"Supported boot stages:\n"
" post-fs, post-fs-data, service\n"
"Supported init services:\n"
" daemon post-fs, post-fs-data, service\n"
"\n"
"Supported applets:\n"
, argv0, argv0);
@@ -71,8 +68,6 @@ static void usage() {
int main(int argc, char *argv[]) {
argv0 = argv[0];
// Exit the whole app if error occurs by default
err_handler = exit_proc;
char * arg = strrchr(argv[0], '/');
if (arg) ++arg;
else arg = argv[0];
@@ -146,6 +141,12 @@ int main(int argc, char *argv[]) {
} else if (strcmp(argv[1], "--unlock-blocks") == 0) {
unlock_blocks();
return 0;
} else if (strcmp(argv[1], "--restorecon") == 0) {
fix_filecon();
return 0;
} else if (strcmp(argv[1], "--daemon") == 0) {
// Start daemon, this process won't return
start_daemon();
} else if (strcmp(argv[1], "--post-fs") == 0) {
int fd = connect_daemon();
write_int(fd, POST_FS);

View File

@@ -7,6 +7,7 @@
#include <pthread.h>
extern pthread_t sepol_patch;
extern int is_restart;
// Commands require connecting to daemon
typedef enum {
@@ -38,8 +39,9 @@ typedef enum {
// daemon.c
void start_daemon(int client);
void start_daemon();
int connect_daemon();
void auto_start_magiskhide();
// socket_trans.c
@@ -50,10 +52,6 @@ void write_int(int fd, int val);
char* read_string(int fd);
void write_string(int fd, const char* val);
// log_monitor.c
void monitor_logs();
/***************
* Boot Stages *
***************/
@@ -61,6 +59,7 @@ void monitor_logs();
void post_fs(int client);
void post_fs_data(int client);
void late_start(int client);
void fix_filecon();
/**************
* MagiskHide *

View File

@@ -15,14 +15,6 @@
#define LOG_TAG "Magisk"
// Global handler for PLOGE
extern __thread void (*err_handler)(void);
// Common error handlers
static inline void exit_proc() { exit(1); }
static inline void exit_thread() { pthread_exit(NULL); }
static inline void do_nothing() {}
#ifdef MAGISK_DEBUG
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#else
@@ -32,7 +24,19 @@ static inline void do_nothing() {}
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define PLOGE(fmt, args...) { LOGE(fmt " failed with %d: %s", ##args, errno, strerror(errno)); err_handler(); }
#define PLOGE(fmt, args...) LOGE(fmt " failed with %d: %s", ##args, errno, strerror(errno))
enum {
HIDE_EVENT,
LOG_EVENT,
DEBUG_EVENT
};
extern int logcat_events[];
void monitor_logs();
void start_debug_full_log();
void stop_debug_full_log();
void start_debug_log();
#else // IS_DAEMON

View File

@@ -12,9 +12,11 @@ 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);
int deleteprop(const char *name, const int trigger);
char *getprop2(const char *name, int persist);
int deleteprop(const char *name);
int deleteprop2(const char *name, const int persist);
int read_prop_file(const char* filename, const int trigger);
void getprop_all(void (*cbk)(const char *name));
void getprop_all(void (*callback)(const char*, const char*));
#ifdef __cplusplus
}

View File

@@ -6,8 +6,6 @@
#include <stdio.h>
#include <dirent.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
@@ -18,8 +16,6 @@
#define UID_SYSTEM (get_system_uid())
#define UID_RADIO (get_radio_uid())
extern int quit_signals[];
// xwrap.c
FILE *xfopen(const char *pathname, const char *mode);
@@ -28,12 +24,14 @@ FILE *xfdopen(int fd, const char *mode);
#define xopen(...) GET_MACRO(__VA_ARGS__, xopen3, xopen2)(__VA_ARGS__)
int xopen2(const char *pathname, int flags);
int xopen3(const char *pathname, int flags, mode_t mode);
int xopenat(int dirfd, const char *pathname, int flags);
ssize_t xwrite(int fd, const void *buf, size_t count);
ssize_t xread(int fd, void *buf, size_t count);
ssize_t xxread(int fd, void *buf, size_t count);
int xpipe2(int pipefd[2], int flags);
int xsetns(int fd, int nstype);
DIR *xopendir(const char *name);
DIR *xfdopendir(int fd);
struct dirent *xreaddir(DIR *dirp);
pid_t xsetsid();
int xsocket(int domain, int type, int protocol);
@@ -53,22 +51,26 @@ int xstat(const char *pathname, struct stat *buf);
int xlstat(const char *pathname, struct stat *buf);
int xdup2(int oldfd, int newfd);
ssize_t xreadlink(const char *pathname, char *buf, size_t bufsiz);
ssize_t xreadlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz);
int xsymlink(const char *target, const char *linkpath);
int xmount(const char *source, const char *target,
const char *filesystemtype, unsigned long mountflags,
const void *data);
int xumount(const char *target);
int xumount2(const char *target, int flags);
int xchmod(const char *pathname, mode_t mode);
int xrename(const char *oldpath, const char *newpath);
int xmkdir(const char *pathname, mode_t mode);
int xmkdir_p(const char *pathname, mode_t mode);
int xmkdirat(int dirfd, const char *pathname, mode_t mode);
void *xmmap(void *addr, size_t length, int prot, int flags,
int fd, off_t offset);
ssize_t xsendfile(int out_fd, int in_fd, off_t *offset, size_t count);
int xmkdir_p(const char *pathname, mode_t mode);
pid_t xfork();
// misc.c
extern int quit_signals[];
unsigned get_shell_uid();
unsigned get_system_uid();
unsigned get_radio_uid();
@@ -82,14 +84,38 @@ void unlock_blocks();
void setup_sighandlers(void (*handler)(int));
int exec_command(int err, int *fd, void (*setupenv)(struct vector*), const char *argv0, ...);
int exec_command_sync(char *const argv0, ...);
int mkdir_p(const char *pathname, mode_t mode);
int bind_mount(const char *from, const char *to);
int open_new(const char *filename);
int cp_afc(const char *source, 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);
int fork_dont_care();
// file.c
extern char **excl_list;
struct file_attr {
struct stat st;
char con[128];
};
int fd_getpath(int fd, char *path, size_t size);
int mkdir_p(const char *pathname, mode_t mode);
void rm_rf(const char *path);
void frm_rf(int dirfd);
void mv_f(const char *source, const char *destination);
void mv_dir(int src, int dest);
void cp_afc(const char *source, const char *destination);
void clone_dir(int src, int dest);
int getattr(const char *path, struct file_attr *a);
int getattrat(int dirfd, const char *pathname, struct file_attr *a);
int fgetattr(int fd, struct file_attr *a);
int setattr(const char *path, struct file_attr *a);
int setattrat(int dirfd, const char *pathname, struct file_attr *a);
int fsetattr(int fd, struct file_attr *a);
void fclone_attr(const int sourcefd, const int targetfd);
void clone_attr(const char *source, const char *target);
void restorecon(int dirfd, int force);
// img.c

View File

@@ -8,7 +8,7 @@ void mmap_ro(const char *filename, void **buf, size_t *size) {
int fd = xopen(filename, O_RDONLY);
*size = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
*buf = xmmap(NULL, *size, PROT_READ, MAP_SHARED, fd, 0);
*buf = *size > 0 ? xmmap(NULL, *size, PROT_READ, MAP_SHARED, fd, 0) : NULL;
close(fd);
}
@@ -16,7 +16,7 @@ void mmap_rw(const char *filename, void **buf, size_t *size) {
int fd = xopen(filename, O_RDWR);
*size = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
*buf = xmmap(NULL, *size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
*buf = *size > 0 ? xmmap(NULL, *size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0) : NULL;
close(fd);
}

View File

@@ -30,7 +30,7 @@ static void print_hdr(const boot_img_hdr *hdr) {
fprintf(stderr, "KERNEL [%d] @ 0x%08x\n", hdr->kernel_size, hdr->kernel_addr);
fprintf(stderr, "RAMDISK [%d] @ 0x%08x\n", hdr->ramdisk_size, hdr->ramdisk_addr);
fprintf(stderr, "SECOND [%d] @ 0x%08x\n", hdr->second_size, hdr->second_addr);
fprintf(stderr, "DTB [%d] @ 0x%08x\n", hdr->dt_size, hdr->tags_addr);
fprintf(stderr, "EXTRA [%d] @ 0x%08x\n", hdr->extra_size, hdr->tags_addr);
fprintf(stderr, "PAGESIZE [%d]\n", hdr->page_size);
if (hdr->os_version != 0) {
int a,b,c,y,m = 0;
@@ -88,26 +88,24 @@ int parse_img(void *orig, size_t size, boot_img *boot) {
mem_align(&pos, boot->hdr.page_size);
}
if (boot->hdr.dt_size) {
boot->dtb = base + pos;
pos += boot->hdr.dt_size;
if (boot->hdr.extra_size) {
boot->extra = base + pos;
pos += boot->hdr.extra_size;
mem_align(&pos, boot->hdr.page_size);
}
if (pos < size) {
boot->extra = base + pos;
boot->tail = base + pos;
boot->tail_size = end - base - pos;
}
// Search for dtb in kernel if not found
if (boot->hdr.dt_size == 0) {
for (int i = 0; i < boot->hdr.kernel_size; ++i) {
if (memcmp(boot->kernel + i, DTB_MAGIC, 4) == 0) {
boot->flags |= APPEND_DTB;
boot->dtb = boot->kernel + i;
boot->hdr.dt_size = boot->hdr.kernel_size - i;
boot->hdr.kernel_size = i;
fprintf(stderr, "APPEND_DTB [%d]\n", boot->hdr.dt_size);
}
// Search for dtb in kernel
for (int i = 0; i < boot->hdr.kernel_size; ++i) {
if (memcmp(boot->kernel + i, DTB_MAGIC, 4) == 0) {
boot->dtb = boot->kernel + i;
boot->dt_size = boot->hdr.kernel_size - i;
boot->hdr.kernel_size = i;
fprintf(stderr, "DTB [%d]\n", boot->dt_size);
}
}
@@ -146,6 +144,7 @@ int parse_img(void *orig, size_t size, boot_img *boot) {
}
}
LOGE("No boot image magic found!\n");
return 1;
}
void unpack(const char* image) {
@@ -160,22 +159,27 @@ void unpack(const char* image) {
int ret = parse_img(orig, size, &boot);
// Dump kernel
if (boot.kernel_type == UNKNOWN) {
dump(boot.kernel, boot.hdr.kernel_size, KERNEL_FILE);
} else {
if (COMPRESSED(boot.kernel_type)) {
fd = open_new(KERNEL_FILE);
decomp(boot.kernel_type, fd, boot.kernel, boot.hdr.kernel_size);
close(fd);
} else {
dump(boot.kernel, boot.hdr.kernel_size, KERNEL_FILE);
}
if (boot.dt_size) {
// Dump dtb
dump(boot.dtb, boot.dt_size, DTB_FILE);
}
// Dump ramdisk
if (boot.ramdisk_type == UNKNOWN) {
dump(boot.ramdisk, boot.hdr.ramdisk_size, RAMDISK_FILE ".raw");
LOGE("Unknown ramdisk format! Dumped to %s\n", RAMDISK_FILE ".raw");
} else {
if (COMPRESSED(boot.ramdisk_type)) {
fd = open_new(RAMDISK_FILE);
decomp(boot.ramdisk_type, fd, boot.ramdisk, boot.hdr.ramdisk_size);
close(fd);
} else {
dump(boot.ramdisk, boot.hdr.ramdisk_size, RAMDISK_FILE ".raw");
LOGE("Unknown ramdisk format! Dumped to %s\n", RAMDISK_FILE ".raw");
}
if (boot.hdr.second_size) {
@@ -183,9 +187,9 @@ void unpack(const char* image) {
dump(boot.second, boot.hdr.second_size, SECOND_FILE);
}
if (boot.hdr.dt_size) {
// Dump dtb
dump(boot.dtb, boot.hdr.dt_size, DTB_FILE);
if (boot.hdr.extra_size) {
// Dump extra
dump(boot.extra, boot.hdr.extra_size, EXTRA_FILE);
}
munmap(orig, size);
@@ -220,18 +224,18 @@ void repack(const char* orig_image, const char* out_image) {
mtk_kernel_off = lseek(fd, 0, SEEK_CUR);
write_zero(fd, 512);
}
if (boot.kernel_type == UNKNOWN) {
boot.hdr.kernel_size = restore(KERNEL_FILE, fd);
} else {
if (COMPRESSED(boot.kernel_type)) {
size_t raw_size;
void *kernel_raw;
mmap_ro(KERNEL_FILE, &kernel_raw, &raw_size);
boot.hdr.kernel_size = comp(boot.kernel_type, fd, kernel_raw, raw_size);
munmap(kernel_raw, raw_size);
} else {
boot.hdr.kernel_size = restore(KERNEL_FILE, fd);
}
if (boot.flags & APPEND_DTB) {
// Restore dtb
if (boot.dt_size && access(DTB_FILE, R_OK) == 0) {
boot.hdr.kernel_size += restore(DTB_FILE, fd);
boot.hdr.dt_size = 0;
}
file_align(fd, boot.hdr.page_size, 1);
@@ -270,18 +274,17 @@ void repack(const char* orig_image, const char* out_image) {
file_align(fd, boot.hdr.page_size, 1);
}
// Restore dtb
if (boot.hdr.dt_size && access(DTB_FILE, R_OK) == 0) {
printf("Here\n");
boot.hdr.dt_size = restore(DTB_FILE, fd);
// Restore extra
if (boot.hdr.extra_size && access(EXTRA_FILE, R_OK) == 0) {
boot.hdr.extra_size = restore(EXTRA_FILE, fd);
file_align(fd, boot.hdr.page_size, 1);
}
// Check extra info, currently only for LG Bump and Samsung SEANDROIDENFORCE
if (boot.extra) {
if (memcmp(boot.extra, "SEANDROIDENFORCE", 16) == 0 ||
memcmp(boot.extra, LG_BUMP_MAGIC, 16) == 0 ) {
restore_buf(fd, boot.extra, 16);
// Check tail info, currently only for LG Bump and Samsung SEANDROIDENFORCE
if (boot.tail_size >= 16) {
if (memcmp(boot.tail, "SEANDROIDENFORCE", 16) == 0 ||
memcmp(boot.tail, LG_BUMP_MAGIC, 16) == 0 ) {
restore_buf(fd, boot.tail, 16);
}
}

View File

@@ -44,7 +44,7 @@ struct boot_img_hdr
uint32_t tags_addr; /* physical addr for kernel tags */
uint32_t page_size; /* flash page size we assume */
uint32_t dt_size; /* device tree in bytes */
uint32_t extra_size; /* extra blob size in bytes */
/* operating system version and security patch level; for
* version "A.B.C" and patch level "Y-M-D":
@@ -74,13 +74,13 @@ struct boot_img_hdr
** +-----------------+
** | second stage | o pages
** +-----------------+
** | device tree | p pages
** | extra blobs | p pages
** +-----------------+
**
** n = (kernel_size + page_size - 1) / page_size
** m = (ramdisk_size + page_size - 1) / page_size
** o = (second_size + page_size - 1) / page_size
** p = (dt_size + page_size - 1) / page_size
** p = (extra_size + page_size - 1) / page_size
**
** 0. all entities are page_size aligned in flash
** 1. kernel and ramdisk are required (size != 0)
@@ -103,16 +103,18 @@ typedef struct mtk_hdr {
// Flags
#define MTK_KERNEL 0x1
#define MTK_RAMDISK 0x2
#define APPEND_DTB 0x4
typedef struct boot_img {
boot_img_hdr hdr;
void *kernel;
void *dtb;
uint32_t dt_size;
void *ramdisk;
void *second;
void *dtb;
void *extra;
int flags;
void *tail;
uint32_t tail_size;
uint32_t flags;
file_t kernel_type, ramdisk_type;
mtk_hdr mtk_kernel_hdr, mtk_ramdisk_hdr;
} boot_img;

View File

@@ -5,6 +5,7 @@
#include <lzma.h>
#include <lz4.h>
#include <lz4frame.h>
#include <lz4hc.h>
#include <bzlib.h>
#include "magiskboot.h"
@@ -37,8 +38,6 @@ size_t gzip(int mode, int fd, const void *buf, size_t size) {
case 1:
ret = deflateInit2(&strm, 9, Z_DEFLATED, windowBits | ZLIB_GZIP, memLevel, Z_DEFAULT_STRATEGY);
break;
default:
LOGE("Unsupported gzip mode!\n");
}
if (ret != Z_OK)
@@ -98,7 +97,7 @@ size_t lzma(int mode, int fd, const void *buf, size_t size) {
unsigned char out[BUFSIZ];
// Initialize preset
lzma_lzma_preset(&opt, LZMA_PRESET_DEFAULT);
lzma_lzma_preset(&opt, 9);
lzma_filter filters[] = {
{ .id = LZMA_FILTER_LZMA2, .options = &opt },
{ .id = LZMA_VLI_UNKNOWN, .options = NULL },
@@ -114,8 +113,6 @@ size_t lzma(int mode, int fd, const void *buf, size_t size) {
case 2:
ret = lzma_alone_encoder(&strm, &opt);
break;
default:
LOGE("Unsupported lzma mode!\n");
}
@@ -168,8 +165,6 @@ size_t lz4(int mode, int fd, const void *buf, size_t size) {
case 1:
ret = LZ4F_createCompressionContext(&cctx, LZ4F_VERSION);
break;
default:
LOGE("Unsupported lz4 mode!\n");
}
if (LZ4F_isError(ret))
@@ -283,8 +278,6 @@ size_t bzip2(int mode, int fd, const void* buf, size_t size) {
case 1:
ret = BZ2_bzCompressInit(&strm, 9, 0, 0);
break;
default:
LOGE("Unsupported bzip2 mode!\n");
}
if (ret != BZ_OK)
@@ -333,11 +326,10 @@ size_t bzip2(int mode, int fd, const void* buf, size_t size) {
// Mode: 0 = decode; 1 = encode
size_t lz4_legacy(int mode, int fd, const void* buf, size_t size) {
size_t pos = 0, total = 0;
size_t pos = 0;
int have;
char *out;
unsigned block_size, insize;
unsigned char block_size_le[4];
unsigned block_size, insize, total = 0;
switch(mode) {
case 0:
@@ -350,22 +342,17 @@ size_t lz4_legacy(int mode, int fd, const void* buf, size_t size) {
// Write magic
total += xwrite(fd, "\x02\x21\x4c\x18", 4);
break;
default:
LOGE("Unsupported lz4_legacy mode!\n");
}
do {
const char *buff = buf;
switch(mode) {
case 0:
block_size = buff[pos];
block_size += (buff[pos + 1]<<8);
block_size += (buff[pos + 2]<<16);
block_size += ((unsigned)buff[pos + 3])<<24;
// Read block size
block_size = *(unsigned *)(buf + pos);
pos += 4;
if (block_size > LZ4_COMPRESSBOUND(LZ4_LEGACY_BLOCKSIZE))
LOGE("lz4_legacy block size too large!\n");
have = LZ4_decompress_safe((const char*) (buf + pos), out, block_size, LZ4_LEGACY_BLOCKSIZE);
goto done;
have = LZ4_decompress_safe(buf + pos, out, block_size, LZ4_LEGACY_BLOCKSIZE);
if (have < 0)
LOGE("Cannot decode lz4_legacy block\n");
pos += block_size;
@@ -375,21 +362,24 @@ size_t lz4_legacy(int mode, int fd, const void* buf, size_t size) {
insize = size - pos;
else
insize = LZ4_LEGACY_BLOCKSIZE;
have = LZ4_compress_default((const char*) (buf + pos), out, insize, LZ4_COMPRESSBOUND(LZ4_LEGACY_BLOCKSIZE));
have = LZ4_compress_HC(buf + pos, out, insize, LZ4_COMPRESSBOUND(LZ4_LEGACY_BLOCKSIZE), 9);
if (have == 0)
LOGE("lz4_legacy compression error\n");
pos += insize;
block_size_le[0] = have & 0xff;
block_size_le[1] = (have >> 8) & 0xff;
block_size_le[2] = (have >> 16) & 0xff;
block_size_le[3] = (have >> 24) & 0xff;
total += xwrite(fd, block_size_le, 4);
// Write block size
total += xwrite(fd, &have, sizeof(have));
break;
}
// Write main data
total += xwrite(fd, out, have);
} while(pos < size);
done:
if (mode == 1) {
// Append original size to output
unsigned uncomp = size;
xwrite(fd, &uncomp, sizeof(uncomp));
}
free(out);
return total;
}

View File

@@ -5,16 +5,14 @@
#include "magiskboot.h"
#include "utils.h"
/* Left here for debugging */
// static void print_subnode(const void *fdt, int parent, int depth) {
// int node;
// fdt_for_each_subnode(node, fdt, parent) {
// for (int i = 0; i < depth; ++i) printf(" ");
// printf("%d: %s\n", node, fdt_get_name(fdt, node, NULL));
// print_subnode(fdt, node, depth + 1);
// }
// }
static void print_subnode(const void *fdt, int parent, int depth) {
int node;
fdt_for_each_subnode(node, fdt, parent) {
for (int i = 0; i < depth; ++i) printf(" ");
printf("%d: %s\n", node, fdt_get_name(fdt, node, NULL));
print_subnode(fdt, node, depth + 1);
}
}
static int find_fstab(const void *fdt, int parent) {
int node, fstab;
@@ -28,6 +26,25 @@ static int find_fstab(const void *fdt, int parent) {
return -1;
}
void dtb_print(const char *file) {
size_t size ;
void *dtb, *fdt;
fprintf(stderr, "Loading dtbs from [%s]\n", file);
mmap_ro(file, &dtb, &size);
// Loop through all the dtbs
int dtb_num = 0;
for (int i = 0; i < size; ++i) {
if (memcmp(dtb + i, DTB_MAGIC, 4) == 0) {
fdt = dtb + i;
fprintf(stderr, "\nPrinting dtb.%04d\n\n", dtb_num++);
print_subnode(fdt, 0, 0);
}
}
fprintf(stderr, "\n");
munmap(dtb, size);
exit(0);
}
void dtb_patch(const char *file) {
size_t size ;
void *dtb, *fdt;

View File

@@ -24,7 +24,7 @@ void hexpatch(const char *image, const char *from, const char *to) {
patch = xmalloc(patchsize);
hex2byte(from, pattern);
hex2byte(to, patch);
for (size_t i = 0; i < filesize - patternsize; ++i) {
for (size_t i = 0; filesize > 0 && i < filesize - patternsize; ++i) {
if (memcmp(file + i, pattern, patternsize) == 0) {
fprintf(stderr, "Pattern %s found!\nPatching to %s\n", from, to);
memset(file + i, 0, patternsize);

View File

@@ -8,6 +8,7 @@
#define KERNEL_FILE "kernel"
#define RAMDISK_FILE "ramdisk.cpio"
#define SECOND_FILE "second"
#define EXTRA_FILE "extra"
#define DTB_FILE "dtb"
#define NEW_BOOT "new-boot.img"
@@ -22,6 +23,7 @@ int parse_img(void *orig, size_t size, boot_img *boot);
int cpio_commands(const char *command, int argc, char *argv[]);
void comp_file(const char *method, const char *from, const char *to);
void decomp_file(char *from, const char *to);
void dtb_print(const char *file);
void dtb_patch(const char *file);
// Compressions

View File

@@ -54,6 +54,9 @@ static void usage(char *arg0) {
" -stocksha1\n"
" Get stock boot SHA1 recorded within <incpio>\n"
"\n"
" --dtb-print <dtb>\n"
" Print all nodes in <dtb>, for debugging\n"
"\n"
" --dtb-patch <dtb>\n"
" Search for fstab in <dtb> and remove verity checks\n"
"\n"
@@ -94,6 +97,7 @@ int main(int argc, char *argv[]) {
unlink(RAMDISK_FILE ".raw");
unlink(SECOND_FILE);
unlink(DTB_FILE);
unlink(EXTRA_FILE);
for (int i = 0; SUP_EXT_LIST[i]; ++i) {
sprintf(name, "%s.%s", RAMDISK_FILE, SUP_EXT_LIST[i]);
unlink(name);
@@ -113,6 +117,8 @@ int main(int argc, char *argv[]) {
repack(argv[2], argc > 3 ? argv[3] : NEW_BOOT);
} else if (argc > 2 && strcmp(argv[1], "--decompress") == 0) {
decomp_file(argv[2], argc > 3 ? argv[3] : NULL);
} else if (argc > 2 && strcmp(argv[1], "--dtb-print") == 0) {
dtb_print(argv[2]);
} else if (argc > 2 && strcmp(argv[1], "--dtb-patch") == 0) {
dtb_patch(argv[2]);
} else if (argc > 2 && strncmp(argv[1], "--compress", 10) == 0) {

View File

@@ -18,6 +18,8 @@ typedef enum {
DTB
} file_t;
#define COMPRESSED(type) (type >= GZIP && type <= LZ4_LEGACY)
#define CHROMEOS_MAGIC "CHROMEOS"
#define ELF32_MAGIC "\x7f""ELF\x01"
#define ELF64_MAGIC "\x7f""ELF\x02"

View File

@@ -58,9 +58,9 @@ void hide_sensitive_props() {
}
}
static void rm_magisk_prop(const char *name) {
static void rm_magisk_prop(const char *name, const char *value) {
if (strstr(name, "magisk")) {
deleteprop(name, 0);
deleteprop2(name, 0);
}
}
@@ -69,42 +69,6 @@ void clean_magisk_props() {
getprop_all(rm_magisk_prop);
}
void relink_sbin() {
struct stat st;
if (stat("/sbin_orig", &st) == -1 && errno == ENOENT) {
// Re-link all binaries and bind mount
DIR *dir;
struct dirent *entry;
char from[PATH_MAX], to[PATH_MAX];
LOGI("hide_utils: Re-linking /sbin\n");
xmount(NULL, "/", NULL, MS_REMOUNT, NULL);
xrename("/sbin", "/sbin_orig");
xmkdir("/sbin", 0755);
xchmod("/sbin", 0755);
xmount(NULL, "/", NULL, MS_REMOUNT | MS_RDONLY, NULL);
xmkdir("/dev/sbin_bind", 0755);
xchmod("/dev/sbin_bind", 0755);
dir = xopendir("/sbin_orig");
while ((entry = xreaddir(dir))) {
if (strcmp(entry->d_name, "..") == 0)
continue;
snprintf(from, sizeof(from), "/sbin_orig/%s", entry->d_name);
if (entry->d_type == DT_LNK)
xreadlink(from, from, sizeof(from));
snprintf(to, sizeof(to), "/dev/sbin_bind/%s", entry->d_name);
symlink(from, to);
lsetfilecon(to, "u:object_r:rootfs:s0");
}
closedir(dir);
xmount("/dev/sbin_bind", "/sbin", NULL, MS_BIND, NULL);
}
}
int add_list(char *proc) {
if (!hideEnabled) {
free(proc);
@@ -223,7 +187,6 @@ int destroy_list() {
}
void add_hide_list(int client) {
err_handler = do_nothing;
char *proc = read_string(client);
// ack
write_int(client, add_list(proc));
@@ -231,7 +194,6 @@ void add_hide_list(int client) {
}
void rm_hide_list(int client) {
err_handler = do_nothing;
char *proc = read_string(client);
// ack
write_int(client, rm_list(proc));
@@ -239,7 +201,6 @@ void rm_hide_list(int client) {
}
void ls_hide_list(int client) {
err_handler = do_nothing;
if (!hideEnabled) {
write_int(client, HIDE_NOT_ENABLED);
return;

View File

@@ -41,9 +41,6 @@ static void usage(char *arg0) {
}
void launch_magiskhide(int client) {
// We manually handle crashes
err_handler = do_nothing;
if (hideEnabled) {
if (client > 0) {
write_int(client, HIDE_IS_ENABLED);
@@ -55,7 +52,7 @@ void launch_magiskhide(int client) {
hideEnabled = 1;
LOGI("* Starting MagiskHide\n");
deleteprop(MAGISKHIDE_PROP, 1);
deleteprop2(MAGISKHIDE_PROP, 1);
hide_sensitive_props();
@@ -102,7 +99,7 @@ void stop_magiskhide(int client) {
hideEnabled = 0;
setprop(MAGISKHIDE_PROP, "0");
// Remove without actually removing persist props
deleteprop(MAGISKHIDE_PROP, 0);
deleteprop2(MAGISKHIDE_PROP, 0);
pthread_kill(proc_monitor_thread, SIGUSR1);
write_int(client, DAEMON_SUCCESS);
@@ -124,6 +121,8 @@ int magiskhide_main(int argc, char *argv[]) {
req = RM_HIDELIST;
} else if (strcmp(argv[1], "--ls") == 0) {
req = LS_HIDELIST;
} else {
usage(argv[0]);
}
int fd = connect_daemon();
write_int(fd, req);

View File

@@ -12,7 +12,6 @@ void proc_monitor();
// Utility functions
void manage_selinux();
void hide_sensitive_props();
void relink_sbin();
void clean_magisk_props();
// List managements

View File

@@ -19,38 +19,25 @@
#include "utils.h"
#include "magiskhide.h"
static int zygote_num;
static char init_ns[32], zygote_ns[2][32], cache_block[256];
static int log_pid, log_fd, target_pid, has_cache = 1;
static char *buffer;
static int zygote_num, has_cache = 1, pipefd[2] = { -1, -1 };
// Workaround for the lack of pthread_cancel
static void quit_pthread(int sig) {
err_handler = do_nothing;
LOGD("proc_monitor: running cleanup\n");
destroy_list();
free(buffer);
hideEnabled = 0;
// Kill the logging if needed
if (log_pid > 0) {
kill(log_pid, SIGTERM);
waitpid(log_pid, NULL, 0);
close(log_fd);
}
// Resume process if possible
if (target_pid > 0)
kill(target_pid, SIGCONT);
// Unregister listener
logcat_events[HIDE_EVENT] = -1;
close(pipefd[0]);
close(pipefd[1]);
pipefd[0] = pipefd[1] = -1;
pthread_mutex_destroy(&hide_lock);
pthread_mutex_destroy(&file_lock);
LOGD("proc_monitor: terminating...\n");
pthread_exit(NULL);
}
static void 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);
@@ -76,27 +63,19 @@ static void lazy_unmount(const char* mountpoint) {
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;
char *line, buffer[PATH_MAX];
struct vector mount_list;
manage_selinux();
relink_sbin();
clean_magisk_props();
if (switch_mnt_ns(pid))
return;
goto exit;
snprintf(buffer, PATH_MAX, "/proc/%d/mounts", pid);
snprintf(buffer, sizeof(buffer), "/proc/%d/mounts", pid);
vec_init(&mount_list);
file_to_vector(buffer, &mount_list);
@@ -133,7 +112,7 @@ static void hide_daemon(int pid) {
vec_destroy(&mount_list);
// Re-read mount infos
snprintf(buffer, PATH_MAX, "/proc/%d/mounts", pid);
snprintf(buffer, sizeof(buffer), "/proc/%d/mounts", pid);
vec_init(&mount_list);
file_to_vector(buffer, &mount_list);
@@ -146,8 +125,12 @@ static void hide_daemon(int pid) {
free(line);
}
// Free uo memory
exit:
// Send resume signal
kill(pid, SIGCONT);
// Free up memory
vec_destroy(&mount_list);
_exit(0);
}
void proc_monitor() {
@@ -157,17 +140,12 @@ void proc_monitor() {
act.sa_handler = quit_pthread;
sigaction(SIGUSR1, &act, NULL);
// The error handler should stop magiskhide services
err_handler = proc_monitor_err;
log_pid = target_pid = -1;
buffer = xmalloc(PATH_MAX);
cache_block[0] = '\0';
// Get the mount namespace of init
if (read_namespace(1, init_ns, 32)) {
LOGE("proc_monitor: Your kernel doesn't support mount namespace :(\n");
proc_monitor_err();
quit_pthread(SIGUSR1);
}
LOGI("proc_monitor: init ns=%s\n", init_ns);
@@ -189,20 +167,15 @@ void proc_monitor() {
break;
}
while (1) {
// Clear previous logcat buffer
exec_command_sync("logcat", "-b", "events", "-c", NULL);
// Register our listener to logcat monitor
xpipe2(pipefd, O_CLOEXEC);
logcat_events[HIDE_EVENT] = pipefd[1];
// Monitor am_proc_start
log_fd = -1;
log_pid = exec_command(0, &log_fd, NULL, "logcat", "-b", "events", "-v", "raw", "-s", "am_proc_start", NULL);
if (log_pid < 0) continue;
if (kill(log_pid, 0)) continue;
while(fdgets(buffer, PATH_MAX, log_fd)) {
for (char *log, *line; xxread(pipefd[0], &log, sizeof(log)) > 0; free(log)) {
char *ss;
if ((ss = strstr(log, "am_proc_start")) && (ss = strchr(ss, '['))) {
int pid, ret, comma = 0;
char *pos = buffer, *line, processName[256];
char *pos = ss, processName[256], ns[32];
while(1) {
pos = strchr(pos, ',');
@@ -213,9 +186,9 @@ void proc_monitor() {
}
if (comma == 6)
ret = sscanf(buffer, "[%*d %d %*d %*d %256s", &pid, processName);
ret = sscanf(ss, "[%*d %d %*d %*d %256s", &pid, processName);
else
ret = sscanf(buffer, "[%*d %d %*d %256s", &pid, processName);
ret = sscanf(ss, "[%*d %d %*d %256s", &pid, processName);
if(ret != 2)
continue;
@@ -226,12 +199,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(target_pid, buffer, 32);
if (strcmp(buffer, zygote_ns[i]) == 0) {
read_namespace(pid, ns, sizeof(ns));
if (strcmp(ns, zygote_ns[i]) == 0) {
usleep(50);
ret = 0;
break;
@@ -241,43 +213,21 @@ void proc_monitor() {
}
// Send pause signal ASAP
if (kill(target_pid, SIGSTOP) == -1) continue;
if (kill(pid, SIGSTOP) == -1) continue;
LOGI("proc_monitor: %s (PID=%d ns=%s)\n", processName, target_pid, buffer);
LOGI("proc_monitor: %s (PID=%d ns=%s)\n", processName, pid, ns);
/*
* 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;
}
if (fork_dont_care() == 0)
hide_daemon(pid);
// 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);
}
// For some reason it went here, restart logging
kill(log_pid, SIGTERM);
waitpid(log_pid, NULL, 0);
close(log_fd);
}
}

View File

@@ -25,6 +25,7 @@
#include <cil/cil.h>
#include "utils.h"
#include "magiskpolicy.h"
struct cmdline {
@@ -46,114 +47,6 @@ extern void mmap_ro(const char *filename, void **buf, size_t *size);
extern void mmap_rw(const char *filename, void **buf, size_t *size);
extern void *patch_init_rc(char *data, uint32_t *size);
static void clone_dir(int src, int dest) {
struct dirent *entry;
DIR *dir;
int srcfd, destfd, newsrc, newdest;
struct stat st;
char buf[PATH_MAX];
ssize_t size;
dir = fdopendir(src);
while ((entry = readdir(dir))) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue;
fstatat(src, entry->d_name, &st, AT_SYMLINK_NOFOLLOW);
switch (entry->d_type) {
case DT_DIR:
mkdirat(dest, entry->d_name, st.st_mode & 0777);
fchownat(dest, entry->d_name, st.st_uid, st.st_gid, 0);
// Don't clone recursive if it's /system
if (strcmp(entry->d_name, "system") == 0)
continue;
newsrc = openat(src, entry->d_name, O_RDONLY | O_CLOEXEC);
newdest = openat(dest, entry->d_name, O_RDONLY | O_CLOEXEC);
clone_dir(newsrc, newdest);
close(newsrc);
close(newdest);
break;
case DT_REG:
destfd = openat(dest, entry->d_name, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, st.st_mode & 0777);
srcfd = openat(src, entry->d_name, O_RDONLY | O_CLOEXEC);
sendfile(destfd, srcfd, 0, st.st_size);
fchownat(dest, entry->d_name, st.st_uid, st.st_gid, 0);
close(destfd);
close(srcfd);
break;
case DT_LNK:
size = readlinkat(src, entry->d_name, buf, sizeof(buf));
buf[size] = '\0';
symlinkat(buf, dest, entry->d_name);
fchownat(dest, entry->d_name, st.st_uid, st.st_gid, AT_SYMLINK_NOFOLLOW);
break;
}
}
}
static void mv_dir(int src, int dest) {
struct dirent *entry;
DIR *dir;
int newsrc, newdest;
struct stat st;
char buf[PATH_MAX];
ssize_t size;
dir = fdopendir(src);
while ((entry = readdir(dir))) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue;
fstatat(src, entry->d_name, &st, AT_SYMLINK_NOFOLLOW);
switch (entry->d_type) {
case DT_DIR:
mkdirat(dest, entry->d_name, st.st_mode & 0777);
fchownat(dest, entry->d_name, st.st_uid, st.st_gid, 0);
newsrc = openat(src, entry->d_name, O_RDONLY | O_CLOEXEC);
newdest = openat(dest, entry->d_name, O_RDONLY | O_CLOEXEC);
mv_dir(newsrc, newdest);
close(newsrc);
close(newdest);
break;
case DT_REG:
renameat(src, entry->d_name, dest, entry->d_name);
fchmodat(dest, entry->d_name, st.st_mode & 0777, 0);
fchownat(dest, entry->d_name, st.st_uid, st.st_gid, 0);
break;
case DT_LNK:
size = readlinkat(src, entry->d_name, buf, sizeof(buf));
buf[size] = '\0';
symlinkat(buf, dest, entry->d_name);
fchownat(dest, entry->d_name, st.st_uid, st.st_gid, AT_SYMLINK_NOFOLLOW);
break;
}
unlinkat(src, entry->d_name, AT_REMOVEDIR);
}
}
static void rm_rf(int path) {
struct dirent *entry;
int newfd;
DIR *dir = fdopendir(path);
while ((entry = readdir(dir))) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue;
switch (entry->d_type) {
case DT_DIR:
// Preserve overlay
if (strcmp(entry->d_name, "overlay") == 0)
continue;
newfd = openat(path, entry->d_name, O_RDONLY | O_CLOEXEC);
rm_rf(newfd);
close(newfd);
unlinkat(path, entry->d_name, AT_REMOVEDIR);
break;
default:
unlinkat(path, entry->d_name, 0);
break;
}
}
}
static void parse_cmdline(struct cmdline *cmd) {
char *tok;
char buffer[4096];
@@ -197,8 +90,6 @@ static void parse_device(struct device *dev, char *uevent) {
static int setup_block(struct device *dev, const char *partname) {
char buffer[1024], path[128];
mkdir("/sys", 0755);
mount("sysfs", "/sys", "sysfs", 0, NULL);
struct dirent *entry;
DIR *dir = opendir("/sys/dev/block");
if (dir == NULL)
@@ -266,7 +157,8 @@ static void patch_sepolicy() {
if (sepolicy == NULL && access("/vendor/etc/selinux/precompiled_sepolicy", R_OK) == 0) {
void *sys_sha = NULL, *ven_sha = NULL;
size_t sys_size = 0, ven_size = 0;
dir = opendir("/vendor/etc/selinux");
if ((dir = opendir("/vendor/etc/selinux")) == NULL)
goto check_done;
while ((entry = readdir(dir))) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue;
@@ -277,7 +169,8 @@ static void patch_sepolicy() {
}
}
closedir(dir);
dir = opendir("/system/etc/selinux");
if ((dir = opendir("/system/etc/selinux")) == NULL)
goto check_done;
while ((entry = readdir(dir))) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue;
@@ -294,6 +187,8 @@ static void patch_sepolicy() {
munmap(ven_sha, ven_size);
}
check_done:
if (sepolicy) {
load_policydb(sepolicy);
} else {
@@ -362,7 +257,13 @@ int main(int argc, char *argv[]) {
// Normal boot mode
// Clear rootfs
int root = open("/", O_RDONLY | O_CLOEXEC);
rm_rf(root);
// Exclude overlay folder
excl_list = (char *[]) { "overlay", NULL };
frm_rf(root);
mkdir("/sys", 0755);
mount("sysfs", "/sys", "sysfs", 0, NULL);
char partname[32];
snprintf(partname, sizeof(partname), "system%s", cmd.slot);
@@ -373,7 +274,11 @@ int main(int argc, char *argv[]) {
mkdir("/system_root", 0755);
mount(dev.path, "/system_root", "ext4", MS_RDONLY, NULL);
int system_root = open("/system_root", O_RDONLY | O_CLOEXEC);
// Exclude system folder
excl_list = (char *[]) { "system", NULL };
clone_dir(system_root, root);
mkdir("/system", 0755);
mount("/system_root/system", "/system", NULL, MS_BIND, NULL);
int overlay = open("/overlay", O_RDONLY | O_CLOEXEC);
@@ -381,8 +286,10 @@ int main(int argc, char *argv[]) {
mv_dir(overlay, root);
snprintf(partname, sizeof(partname), "vendor%s", cmd.slot);
setup_block(&dev, partname);
mount(dev.path, "/vendor", "ext4", MS_RDONLY, NULL);
// We need to mount independent vendor partition
if (setup_block(&dev, partname) == 0)
mount(dev.path, "/vendor", "ext4", MS_RDONLY, NULL);
patch_ramdisk();
patch_sepolicy();

File diff suppressed because it is too large Load Diff

2
jni/su

Submodule jni/su updated: c912c192e0...6de95e0d9b

333
jni/utils/file.c Normal file

File diff suppressed because it is too large Load Diff

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