Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
M
Magisk
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Magisk
Commits
8f6b33d7
Commit
8f6b33d7
authored
Apr 05, 2017
by
topjohnwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Rewrite magiskhide
parent
f476daa0
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
438 additions
and
418 deletions
+438
-418
Android.mk
jni/Android.mk
+3
-4
magisk.h
jni/magisk.h
+20
-3
Android.mk
jni/magiskhide/Android.mk
+0
-7
hide.c
jni/magiskhide/hide.c
+0
-78
hide_daemon.c
jni/magiskhide/hide_daemon.c
+129
-0
list_monitor.c
jni/magiskhide/list_monitor.c
+0
-56
magiskhide.c
jni/magiskhide/magiskhide.c
+42
-60
magiskhide.h
jni/magiskhide/magiskhide.h
+7
-42
proc_monitor.c
jni/magiskhide/proc_monitor.c
+89
-62
util.c
jni/magiskhide/util.c
+0
-80
main.c
jni/main.c
+22
-17
log_monitor.c
jni/utils/log_monitor.c
+2
-3
misc.c
jni/utils/misc.c
+36
-0
utils.h
jni/utils/utils.h
+11
-0
vector.c
jni/utils/vector.c
+17
-4
vector.h
jni/utils/vector.h
+5
-0
xwrap.c
jni/utils/xwrap.c
+55
-2
No files found.
jni/Android.mk
View file @
8f6b33d7
...
@@ -13,14 +13,13 @@ LOCAL_C_INCLUDES := \
...
@@ -13,14 +13,13 @@ LOCAL_C_INCLUDES := \
LOCAL_SRC_FILES := \
LOCAL_SRC_FILES := \
main.c \
main.c \
utils/
log_monitor
.c \
utils/
misc
.c \
utils/vector.c \
utils/vector.c \
utils/xwrap.c \
utils/xwrap.c \
utils/log_monitor.c \
magiskhide/magiskhide.c \
magiskhide/magiskhide.c \
magiskhide/hide.c \
magiskhide/hide_daemon.c \
magiskhide/list_monitor.c \
magiskhide/proc_monitor.c \
magiskhide/proc_monitor.c \
magiskhide/util.c \
magiskpolicy/magiskpolicy.c \
magiskpolicy/magiskpolicy.c \
magiskpolicy/rules.c \
magiskpolicy/rules.c \
magiskpolicy/sepolicy.c \
magiskpolicy/sepolicy.c \
...
...
jni/magisk.h
View file @
8f6b33d7
/* magisk.h - Top header
*
* Contain global functions like logging,
* and entrypoint for main
*/
#ifndef _MAGISK_H_
#ifndef _MAGISK_H_
#define _MAGISK_H_
#define _MAGISK_H_
...
@@ -12,16 +18,19 @@
...
@@ -12,16 +18,19 @@
#else
#else
#define LOGD(...) stub(__VA_ARGS__)
#define LOGD(...) stub(__VA_ARGS__)
#endif
#endif
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
#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 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))
#define PLOGEV(fmt, err, args...) LOGE(fmt " failed with %d: %s", ##args, err, strerror(err))
#define PLOGE(fmt, args...) LOGE(fmt " failed with %d: %s", ##args, errno, strerror(errno)); exit(1)
#define PLOGEV(fmt, err, args...) LOGE(fmt " failed with %d: %s", ##args, err, strerror(err)); exit(1)
void
stub
(
const
char
*
fmt
,
...);
void
stub
(
const
char
*
fmt
,
...);
// Global buffer
// Global buffer
(only for main thread!!)
#define BUF_SIZE 4096
#define BUF_SIZE 4096
extern
char
magiskbuf
[
BUF_SIZE
];
extern
char
magiskbuf
[
BUF_SIZE
];
extern
char
*
argv0
;
/* For changing process name */
// Multi-call entrypoints
// Multi-call entrypoints
int
magiskhide_main
(
int
argc
,
char
*
argv
[]);
int
magiskhide_main
(
int
argc
,
char
*
argv
[]);
...
@@ -36,4 +45,12 @@ int resetprop_main(int argc, char *argv[]);
...
@@ -36,4 +45,12 @@ int resetprop_main(int argc, char *argv[]);
}
}
#endif
#endif
/**************
* MagiskHide *
**************/
void
launch_magiskhide
();
void
stop_magiskhide
();
#endif
#endif
jni/magiskhide/Android.mk
deleted
100644 → 0
View file @
f476daa0
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := magiskhide
LOCAL_SRC_FILES := magiskhide.c hide.c list_monitor.c proc_monitor.c util.c
LOCAL_CFLAGS := -DINDEP_BINARY
include $(BUILD_EXECUTABLE)
\ No newline at end of file
jni/magiskhide/hide.c
deleted
100644 → 0
View file @
f476daa0
#include "magiskhide.h"
int
hideMagisk
()
{
close
(
pipefd
[
1
]);
int
pid
,
fd
;
char
cache_block
[
256
];
cache_block
[
0
]
=
'\0'
;
while
(
1
)
{
read
(
pipefd
[
0
],
&
pid
,
sizeof
(
pid
));
// Termination called
if
(
pid
==
-
1
)
break
;
manage_selinux
();
snprintf
(
buffer
,
sizeof
(
buffer
),
"/proc/%d/ns/mnt"
,
pid
);
if
((
fd
=
open
(
buffer
,
O_RDONLY
))
==
-
1
)
continue
;
// Maybe process died..
if
(
setns
(
fd
,
0
)
==
-
1
)
{
fprintf
(
logfile
,
"MagiskHide: Unable to change namespace for pid=%d
\n
"
,
pid
);
continue
;
}
close
(
fd
);
snprintf
(
buffer
,
sizeof
(
buffer
),
"/proc/%d/mounts"
,
pid
);
FILE
*
mount_fp
=
fopen
(
buffer
,
"r"
);
if
(
mount_fp
==
NULL
)
{
fprintf
(
logfile
,
"MagiskHide: Error opening mount list!
\n
"
);
continue
;
}
int
mount_size
;
char
**
mount_list
=
file_to_str_arr
(
mount_fp
,
&
mount_size
);
// Find the cache block name if not found yet
if
(
strlen
(
cache_block
)
==
0
)
{
for
(
i
=
0
;
i
<
mount_size
;
++
i
)
{
if
(
strstr
(
mount_list
[
i
],
" /cache "
))
{
sscanf
(
mount_list
[
i
],
"%256s"
,
cache_block
);
break
;
}
}
}
// First unmount the dummy skeletons, cache mounts, and /sbin links
for
(
i
=
mount_size
-
1
;
i
>=
0
;
--
i
)
{
if
(
strstr
(
mount_list
[
i
],
"tmpfs /system"
)
||
strstr
(
mount_list
[
i
],
"tmpfs /vendor"
)
||
strstr
(
mount_list
[
i
],
"tmpfs /sbin"
)
||
(
strstr
(
mount_list
[
i
],
cache_block
)
&&
strstr
(
mount_list
[
i
],
"/system/"
))
)
{
sscanf
(
mount_list
[
i
],
"%*s %512s"
,
buffer
);
lazy_unmount
(
buffer
);
}
free
(
mount_list
[
i
]);
}
free
(
mount_list
);
// Re-read mount infos
fseek
(
mount_fp
,
0
,
SEEK_SET
);
mount_list
=
file_to_str_arr
(
mount_fp
,
&
mount_size
);
fclose
(
mount_fp
);
// Unmount loop mounts
for
(
i
=
mount_size
-
1
;
i
>=
0
;
--
i
)
{
if
(
strstr
(
mount_list
[
i
],
"/dev/block/loop"
)
&&
!
strstr
(
mount_list
[
i
],
DUMMYPATH
))
{
sscanf
(
mount_list
[
i
],
"%*s %512s"
,
buffer
);
lazy_unmount
(
buffer
);
}
free
(
mount_list
[
i
]);
}
free
(
mount_list
);
// Send resume signal
kill
(
pid
,
SIGCONT
);
}
// Should never go here
return
1
;
}
jni/magiskhide/hide_daemon.c
0 → 100644
View file @
8f6b33d7
/* 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 <sys/types.h>
#include <sys/stat.h>
#include <sys/mount.h>
#include <sys/prctl.h>
#include "magisk.h"
#include "utils.h"
#include "magiskhide.h"
static
int
isMocked
=
0
;
static
void
manage_selinux
()
{
if
(
isMocked
)
return
;
char
val
[
1
];
int
fd
=
xopen
(
ENFORCE_FILE
,
O_RDONLY
);
xxread
(
fd
,
val
,
1
);
close
(
fd
);
// Permissive
if
(
val
[
0
]
==
'0'
)
{
LOGI
(
"hide_daemon: Permissive detected, hide the state
\n
"
);
chmod
(
ENFORCE_FILE
,
0640
);
chmod
(
POLICY_FILE
,
0440
);
isMocked
=
1
;
}
}
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
);
}
void
hide_daemon
()
{
// Fork to a new process
switch
(
fork
())
{
case
-
1
:
PLOGE
(
"fork"
);
case
0
:
break
;
default:
return
;
}
close
(
pipefd
[
1
]);
strcpy
(
argv0
,
"magiskhide_daemon"
);
int
pid
,
fd
;
FILE
*
fp
;
char
cache_block
[
256
],
*
line
;
struct
vector
mount_list
;
cache_block
[
0
]
=
'\0'
;
while
(
1
)
{
xxread
(
pipefd
[
0
],
&
pid
,
sizeof
(
pid
));
// Termination called
if
(
pid
==
-
1
)
exit
(
0
);
snprintf
(
magiskbuf
,
BUF_SIZE
,
"/proc/%d/ns/mnt"
,
pid
);
if
(
access
(
magiskbuf
,
F_OK
)
==
-
1
)
continue
;
// Maybe process died..
fd
=
xopen
(
magiskbuf
,
O_RDONLY
);
// Switch to its namespace
xsetns
(
fd
,
0
);
close
(
fd
);
manage_selinux
();
snprintf
(
magiskbuf
,
BUF_SIZE
,
"/proc/%d/mounts"
,
pid
);
fp
=
xfopen
(
magiskbuf
,
"r"
);
vec_init
(
&
mount_list
);
file_to_vector
(
&
mount_list
,
fp
);
// 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"
,
magiskbuf
);
lazy_unmount
(
magiskbuf
);
}
free
(
line
);
}
vec_destroy
(
&
mount_list
);
// Re-read mount infos
fseek
(
fp
,
0
,
SEEK_SET
);
vec_init
(
&
mount_list
);
file_to_vector
(
&
mount_list
,
fp
);
fclose
(
fp
);
// Unmount loop mounts
vec_for_each_r
(
&
mount_list
,
line
)
{
if
(
strstr
(
line
,
"/dev/block/loop"
)
&&
!
strstr
(
line
,
DUMMYPATH
))
{
sscanf
(
line
,
"%*s %512s"
,
magiskbuf
);
lazy_unmount
(
magiskbuf
);
}
free
(
line
);
}
vec_destroy
(
&
mount_list
);
// All done, send resume signal
kill
(
pid
,
SIGCONT
);
}
// Should never go here
}
jni/magiskhide/list_monitor.c
deleted
100644 → 0
View file @
f476daa0
#include "magiskhide.h"
void
*
monitor_list
(
void
*
path
)
{
char
*
listpath
=
(
char
*
)
path
;
signal
(
SIGQUIT
,
quit_pthread
);
int
inotifyFd
=
-
1
;
char
str
[
512
];
while
(
1
)
{
if
(
inotifyFd
==
-
1
||
read
(
inotifyFd
,
str
,
sizeof
(
str
))
==
-
1
)
{
close
(
inotifyFd
);
inotifyFd
=
inotify_init
();
if
(
inotifyFd
==
-
1
)
{
fprintf
(
logfile
,
"MagiskHide: Unable to watch %s
\n
"
,
listpath
);
exit
(
1
);
}
if
(
inotify_add_watch
(
inotifyFd
,
listpath
,
IN_CLOSE_WRITE
)
==
-
1
)
{
fprintf
(
logfile
,
"MagiskHide: Unable to watch %s
\n
"
,
listpath
);
exit
(
1
);
}
}
update_list
(
listpath
);
}
return
NULL
;
}
void
update_list
(
const
char
*
listpath
)
{
FILE
*
hide_fp
=
fopen
(
listpath
,
"r"
);
if
(
hide_fp
==
NULL
)
{
fprintf
(
logfile
,
"MagiskHide: Error opening hide list
\n
"
);
exit
(
1
);
}
pthread_mutex_lock
(
&
mutex
);
if
(
hide_list
)
{
// Free memory
for
(
i
=
0
;
i
<
list_size
;
++
i
)
free
(
hide_list
[
i
]);
free
(
hide_list
);
}
hide_list
=
file_to_str_arr
(
hide_fp
,
&
list_size
);
pthread_mutex_unlock
(
&
mutex
);
fclose
(
hide_fp
);
if
(
list_size
)
fprintf
(
logfile
,
"MagiskHide: Update process/package list:
\n
"
);
for
(
i
=
0
;
i
<
list_size
;
i
++
)
fprintf
(
logfile
,
"MagiskHide: [%s]
\n
"
,
hide_list
[
i
]);
}
void
quit_pthread
(
int
sig
)
{
// Free memory
for
(
i
=
0
;
i
<
list_size
;
++
i
)
free
(
hide_list
[
i
]);
free
(
hide_list
);
pthread_exit
(
NULL
);
}
jni/magiskhide/magiskhide.c
View file @
8f6b33d7
#include "magiskhide.h"
/* magiskhide.c - initialize the environment for Magiskhide
*/
#ifdef INDEP_BINARY
// TODO: Functions to modify hiding list
int
magiskhide_main
(
int
argc
,
char
*
argv
[]);
int
main
(
int
argc
,
char
*
argv
[])
{
return
magiskhide_main
(
argc
,
argv
);
}
#else
#include "magisk.h"
#endif
FILE
*
logfile
;
#include <stdio.h>
int
i
,
list_size
,
pipefd
[
2
];
#include <stdlib.h>
char
**
hide_list
=
NULL
,
buffer
[
512
];
#include <unistd.h>
pthread_t
list_monitor
;
#include <pthread.h>
pthread_mutex_t
mutex
;
static
void
terminate
(
int
sig
)
{
#include "magisk.h"
// Close the config list monitor
#include "utils.h"
pthread_kill
(
list_monitor
,
SIGQUIT
);
#include "magiskhide.h"
pthread_mutex_destroy
(
&
mutex
);
// Terminate our children
int
pipefd
[
2
];
i
=
-
1
;
struct
vector
*
hide_list
,
*
new_list
;
write
(
pipefd
[
1
],
&
i
,
sizeof
(
i
));
exit
(
0
);
}
int
magiskhide_main
(
int
argc
,
char
*
argv
[])
{
static
pthread_t
proc_monitor_thread
;
if
(
argc
>
1
)
{
void
launch_magiskhide
()
{
if
(
strcmp
(
argv
[
1
],
"--daemon"
)
==
0
)
/*
run_as_daemon
();
* The setns system call do not support multithread processes
else
{
* We have to fork a new process, and communicate with pipe
fprintf
(
stderr
,
"%s (with no options)
\n\t
Run magiskhide and output to stdout
\n
"
,
argv
[
0
]);
*/
fprintf
(
stderr
,
"%s --daemon
\n\t
Run magiskhide as daemon, output to magisk.log
\n
"
,
argv
[
0
]);
return
1
;
}
}
else
logfile
=
stdout
;
xpipe
(
pipefd
);
// Handle all killing signals
// Launch the hide daemon
signal
(
SIGINT
,
terminate
);
hide_daemon
();
signal
(
SIGTERM
,
terminate
);
// Fork a child to handle namespace switches and unmounts
pipe
(
pipefd
);
switch
(
fork
())
{
case
-
1
:
exit
(
-
1
);
case
0
:
return
hideMagisk
();
default:
break
;
}
close
(
pipefd
[
0
]);
close
(
pipefd
[
0
]);
// Start a thread to constantly check the hide list
// Initialize the hide list
pthread_mutex_init
(
&
mutex
,
NULL
);
hide_list
=
new_list
=
malloc
(
sizeof
(
*
hide_list
));
pthread_create
(
&
list_monitor
,
NULL
,
monitor_list
,
HIDELIST
);
vec_init
(
hide_list
);
FILE
*
fp
=
xfopen
(
HIDELIST
,
"r"
);
file_to_vector
(
hide_list
,
fp
);
fclose
(
fp
);
// Set main process to the top priority
// Start a new thread to monitor processes
setpriority
(
PRIO_PROCESS
,
0
,
-
20
);
pthread_create
(
&
proc_monitor_thread
,
NULL
,
proc_monitor
,
NULL
);
}
monitor_proc
();
terminate
(
0
);
fprintf
(
logfile
,
"MagiskHide: Cannot monitor am_proc_start, abort...
\n
"
);
void
stop_magiskhide
()
{
fclose
(
logfile
);
int
kill
=
-
1
;
// Terminate hide daemon
xwrite
(
pipefd
[
1
],
&
kill
,
sizeof
(
kill
));
// Stop process monitor
pthread_kill
(
proc_monitor_thread
,
SIGUSR1
);
pthread_join
(
proc_monitor_thread
,
NULL
);
}
return
1
;
int
magiskhide_main
(
int
argc
,
char
*
argv
[])
{
}
launch_magiskhide
();
\ No newline at end of file
return
0
;
}
jni/magiskhide/magiskhide.h
View file @
8f6b33d7
#ifndef MAGISK_HIDE_H
#ifndef MAGISK_HIDE_H
#define MAGISK_HIDE_H
#define MAGISK_HIDE_H
#define _GNU_SOURCE
#define HIDELIST "/magisk/.core/magiskhide/hidelist"
#include <string.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <pthread.h>
#include <unistd.h>
#include <signal.h>
#include <sys/mount.h>
#include <sys/inotify.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/resource.h>
#define LOGFILE "/cache/magisk.log"
#define HIDELIST "/magisk/.core/magiskhide/hidelist"
#define DUMMYPATH "/dev/magisk/dummy"
#define DUMMYPATH "/dev/magisk/dummy"
#define ENFORCE_FILE "/sys/fs/selinux/enforce"
#define ENFORCE_FILE "/sys/fs/selinux/enforce"
#define POLICY_FILE "/sys/fs/selinux/policy"
#define POLICY_FILE "/sys/fs/selinux/policy"
#define SEPOLICY_INJECT "/data/magisk/magiskpolicy"
// Main thread
void
monitor_proc
();
// Forked process for namespace setting
int
hideMagisk
();
// List monitor thread
// Hide daemon
void
update_list
(
const
char
*
listpath
);
void
hide_daemon
();
void
quit_pthread
(
int
sig
);
void
*
monitor_list
(
void
*
path
);
// Util functions
// Process monitor
char
**
file_to_str_arr
(
FILE
*
fp
,
int
*
size
);
void
*
proc_monitor
(
void
*
args
);
void
read_namespace
(
const
int
pid
,
char
*
target
,
const
size_t
size
);
void
lazy_unmount
(
const
char
*
mountpoint
);
void
run_as_daemon
();
void
manage_selinux
();
// Global variable sharing through process/threads
extern
int
pipefd
[
2
];
extern
FILE
*
logfile
;
extern
struct
vector
*
hide_list
,
*
new_list
;
extern
int
i
,
list_size
,
pipefd
[
2
];
extern
char
**
hide_list
,
buffer
[
512
];
extern
pthread_t
list_monitor
;
extern
pthread_mutex_t
mutex
;
#endif
#endif
jni/magiskhide/proc_monitor.c
View file @
8f6b33d7
/* proc_monitor.c - Monitor am_proc_start events
*
* We monitor the logcat am_proc_start events, pause it,
* and send the target PID to hide daemon ASAP
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
#include <sys/types.h>
#include "magisk.h"
#include "utils.h"
#include "magiskhide.h"
#include "magiskhide.h"
void
monitor_proc
()
{
/* WTF... the macro in the NDK pthread.h is broken.... */
int
pid
,
badns
,
i
,
zygote_num
=
0
;
#define pthread_cleanup_push_fix(routine, arg) \
char
init_ns
[
32
],
zygote_ns
[
2
][
32
]
;
pthread_cleanup_push(routine, arg) } while(0)
;
// Get the mount namespace of init
static
void
read_namespace
(
const
int
pid
,
char
*
target
,
const
size_t
size
)
{
read_namespace
(
1
,
init_ns
,
32
);
char
path
[
32
];
snprintf
(
path
,
sizeof
(
path
),
"/proc/%d/ns/mnt"
,
pid
);
ssize_t
len
=
readlink
(
path
,
target
,
size
);
target
[
len
]
=
'\0'
;
}
printf
(
"%s
\n
"
,
init_ns
);
// Workaround for the lack of pthread_cancel
static
void
quit_pthread
(
int
sig
)
{
pthread_exit
(
NULL
);
}
// Get the mount namespace of zygote
static
void
cleanup_handler
(
void
*
arg
)
{
FILE
*
p
=
popen
(
"ps | grep zygote | grep -v grep"
,
"r"
);
vec_deep_destroy
(
hide_list
);
while
(
fgets
(
buffer
,
sizeof
(
buffer
),
p
))
{
vec_deep_destroy
(
new_list
);
if
(
zygote_num
==
2
)
break
;
free
(
hide_list
);
sscanf
(
buffer
,
"%d"
,
&
pid
);
free
(
new_list
);
do
{
hide_list
=
new_list
=
NULL
;
usleep
(
500
);
}
read_namespace
(
pid
,
zygote_ns
[
zygote_num
],
32
);
}
while
(
strcmp
(
zygote_ns
[
zygote_num
],
init_ns
)
==
0
);
++
zygote_num
;
}
pclose
(
p
);
for
(
i
=
0
;
i
<
zygote_num
;
++
i
)
void
*
proc_monitor
(
void
*
args
)
{
fprintf
(
logfile
,
"Zygote(%d) ns=%s "
,
i
,
zygote_ns
[
i
]);
// Register the cancel signal
fprintf
(
logfile
,
"
\n
"
);
signal
(
SIGUSR1
,
quit_pthread
);
pthread_cleanup_push_fix
(
cleanup_handler
,
NULL
);
// get a sample line from am_proc_start
p
=
popen
(
"logcat -b events -v raw -s am_proc_start -t 1"
,
"r"
);
/**
* Format of am_proc_start is (as of Android 5.1 and 6.0)
* UserID, pid, unix uid, processName, hostingType, hostingName
* but sometimes can have 7 fields, with processName as 5th field
*/
fgets
(
buffer
,
sizeof
(
buffer
),
p
);
int
commas
=
0
;
char
*
s
=
buffer
;
for
(
i
=
0
;
s
[
i
]
!=
'\0'
;
i
++
)
{
if
(
s
[
i
]
==
','
)
commas
++
;
}
int
pid
,
zygote_num
=
0
;
int
numFields
=
commas
+
1
;
char
init_ns
[
32
],
zygote_ns
[
2
][
32
],
buffer
[
512
];
FILE
*
p
;
pclose
(
p
);
// Get the mount namespace of init
read_namespace
(
1
,
init_ns
,
32
);
LOGI
(
"proc_monitor: init ns=%s
\n
"
,
init_ns
);
// Get the mount namespace of zygote
// TODO: Crawl through /proc to get process names
switch
(
zygote_num
)
{
case
1
:
LOGI
(
"proc_monitor: zygote ns=%s
\n
"
,
zygote_ns
[
0
]);
break
;
case
2
:
LOGI
(
"proc_monitor: zygote (1) ns=%s (2) ns=%s
\n
"
,
zygote_ns
[
0
],
zygote_ns
[
1
]);
break
;
}
// Monitor am_proc_start
// Monitor am_proc_start
(the command shall never end)
p
=
popen
(
"
logcat -b events -c; logcat -b events -v raw -s am_proc_start
"
,
"r"
);
p
=
popen
(
"
while true; do logcat -b events -c; logcat -b events -v raw -s am_proc_start; sleep 1; done
"
,
"r"
);
while
(
!
feof
(
p
))
{
while
(
fgets
(
buffer
,
sizeof
(
buffer
),
p
))
{
fgets
(
buffer
,
sizeof
(
buffer
),
p
);
int
ret
,
comma
=
0
;
char
*
pos
=
buffer
,
*
line
,
processName
[
256
];
struct
vector
*
temp
=
NULL
;
char
*
pos
=
buffer
;
while
(
1
)
{
while
(
1
)
{
pos
=
strchr
(
pos
,
','
);
pos
=
strchr
(
pos
,
','
);
if
(
pos
==
NULL
)
if
(
pos
==
NULL
)
break
;
break
;
pos
[
0
]
=
' '
;
pos
[
0
]
=
' '
;
++
comma
;
}
}
char
processName
[
256
];
if
(
comma
==
6
)
int
ret
;
if
(
numFields
==
7
)
{
ret
=
sscanf
(
buffer
,
"[%*d %d %*d %*d %256s"
,
&
pid
,
processName
);
ret
=
sscanf
(
buffer
,
"[%*d %d %*d %*d %256s"
,
&
pid
,
processName
);
}
else
{
else
ret
=
sscanf
(
buffer
,
"[%*d %d %*d %256s"
,
&
pid
,
processName
);
ret
=
sscanf
(
buffer
,
"[%*d %d %*d %256s"
,
&
pid
,
processName
);
}
if
(
ret
!=
2
)
if
(
ret
!=
2
)
continue
;
continue
;
pthread_mutex_lock
(
&
mutex
);
// Should be thread safe
for
(
i
=
0
;
i
<
list_size
;
++
i
)
{
if
(
hide_list
!=
new_list
)
{
if
(
strcmp
(
processName
,
hide_list
[
i
])
==
0
)
{
temp
=
hide_list
;
hide_list
=
new_list
;
}
vec_for_each
(
hide_list
,
line
)
{
if
(
strcmp
(
processName
,
line
)
==
0
)
{
read_namespace
(
pid
,
buffer
,
32
);
while
(
1
)
{
while
(
1
)
{
badns
=
0
;
ret
=
1
;
read_namespace
(
pid
,
buffer
,
32
);
for
(
int
i
=
0
;
i
<
zygote_num
;
++
i
)
{
for
(
i
=
0
;
i
<
zygote_num
;
++
i
)
{
if
(
strcmp
(
buffer
,
zygote_ns
[
i
])
==
0
)
{
if
(
strcmp
(
buffer
,
zygote_ns
[
i
])
==
0
)
{
usleep
(
500
);
usleep
(
500
);
badns
=
1
;
ret
=
0
;
break
;
break
;
}
}
}
}
if
(
!
badns
)
break
;
if
(
ret
)
break
;
}
}
// Send pause signal ASAP
// Send pause signal ASAP
if
(
kill
(
pid
,
SIGSTOP
)
==
-
1
)
continue
;
if
(
kill
(
pid
,
SIGSTOP
)
==
-
1
)
continue
;
fprintf
(
logfile
,
"MagiskHide
: %s(PID=%d ns=%s)
\n
"
,
processName
,
pid
,
buffer
);
LOGI
(
"proc_monitor
: %s(PID=%d ns=%s)
\n
"
,
processName
,
pid
,
buffer
);
// Unmount start
// Unmount start
write
(
pipefd
[
1
],
&
pid
,
sizeof
(
pid
));
x
write
(
pipefd
[
1
],
&
pid
,
sizeof
(
pid
));
break
;
break
;
}
}
}
}
pthread_mutex_unlock
(
&
mutex
);
if
(
temp
)
{
vec_deep_destroy
(
temp
);
free
(
temp
);
}
}
}
//
Close the logcat monitor
//
Should never be here
pclose
(
p
);
pclose
(
p
);
quit_pthread
(
SIGUSR1
);
return
NULL
;
}
}
jni/magiskhide/util.c
deleted
100644 → 0
View file @
f476daa0
#include "magiskhide.h"
static
int
isMocked
=
0
;
char
**
file_to_str_arr
(
FILE
*
fp
,
int
*
size
)
{
int
allocated
=
16
;
char
*
line
=
NULL
,
**
array
;
size_t
len
=
0
;
ssize_t
read
;
array
=
(
char
**
)
malloc
(
sizeof
(
char
*
)
*
allocated
);
*
size
=
0
;
while
((
read
=
getline
(
&
line
,
&
len
,
fp
))
!=
-
1
)
{
if
(
*
size
>=
allocated
)
{
// Double our allocation and re-allocate
allocated
*=
2
;
array
=
(
char
**
)
realloc
(
array
,
sizeof
(
char
*
)
*
allocated
);
}
// Remove end newline
if
(
line
[
read
-
1
]
==
'\n'
)
{
line
[
read
-
1
]
=
'\0'
;
}
array
[
*
size
]
=
line
;
line
=
NULL
;
++
(
*
size
);
}
return
array
;
}
void
read_namespace
(
const
int
pid
,
char
*
target
,
const
size_t
size
)
{
char
path
[
32
];
snprintf
(
path
,
sizeof
(
path
),
"/proc/%d/ns/mnt"
,
pid
);
ssize_t
len
=
readlink
(
path
,
target
,
size
);
target
[
len
]
=
'\0'
;
}
void
lazy_unmount
(
const
char
*
mountpoint
)
{
if
(
umount2
(
mountpoint
,
MNT_DETACH
)
!=
-
1
)
fprintf
(
logfile
,
"MagiskHide: Unmounted (%s)
\n
"
,
mountpoint
);
else
fprintf
(
logfile
,
"MagiskHide: Unmount Failed (%s)
\n
"
,
mountpoint
);
}
void
run_as_daemon
()
{
switch
(
fork
())
{
case
-
1
:
exit
(
-
1
);
case
0
:
if
(
setsid
()
<
0
)
exit
(
-
1
);
close
(
STDIN_FILENO
);
close
(
STDOUT_FILENO
);
close
(
STDERR_FILENO
);
logfile
=
fopen
(
LOGFILE
,
"a+"
);
setbuf
(
logfile
,
NULL
);
break
;
default:
exit
(
0
);
}
}
void
manage_selinux
()
{
if
(
isMocked
)
return
;
char
val
[
1
];
int
fd
=
open
(
ENFORCE_FILE
,
O_RDONLY
);
if
(
fd
<
0
)
return
;
if
(
read
(
fd
,
val
,
1
)
<
1
)
return
;
close
(
fd
);
// Permissive
if
(
val
[
0
]
==
'0'
)
{
fprintf
(
logfile
,
"MagiskHide: Permissive detected, hide the state
\n
"
);
chmod
(
ENFORCE_FILE
,
0640
);
chmod
(
POLICY_FILE
,
0440
);
isMocked
=
1
;
}
}
jni/main.c
View file @
8f6b33d7
...
@@ -4,39 +4,44 @@
...
@@ -4,39 +4,44 @@
#include "utils.h"
#include "utils.h"
#include "magisk.h"
#include "magisk.h"
// Global buffer
char
magiskbuf
[
BUF_SIZE
];
char
magiskbuf
[
BUF_SIZE
];
char
*
argv0
;
void
stub
(
const
char
*
fmt
,
...)
{}
void
stub
(
const
char
*
fmt
,
...)
{}
int
main
(
int
argc
,
char
*
argv
[])
{
int
main
(
int
argc
,
char
*
argv
[])
{
char
*
argv0
=
strrchr
(
argv
[
0
],
'/'
);
argv0
=
argv
[
0
];
if
(
argv0
)
argv
[
0
]
=
argv0
+
1
;
char
*
arg
=
strrchr
(
argv
[
0
],
'/'
);
if
(
strcmp
(
argv
[
0
],
"magisk"
)
==
0
)
{
if
(
arg
)
++
arg
;
if
(
strcmp
(
argv
[
1
],
"--daemon"
)
==
0
)
{
if
(
strcmp
(
arg
,
"magisk"
)
==
0
)
{
// Start daemon
if
(
strcmp
(
argv
[
1
],
"--post-fs"
)
==
0
)
{
// TODO: post-fs mode
return
0
;
}
else
if
(
strcmp
(
argv
[
1
],
"--post-fs-data"
)
==
0
)
{
// TODO: post-fs-data mode
return
0
;
return
0
;
}
else
if
(
strcmp
(
argv
[
1
],
"--install"
)
==
0
)
{
}
else
if
(
strcmp
(
argv
[
1
],
"--install"
)
==
0
)
{
// Install symlinks
//
TODO:
Install symlinks
return
0
;
return
0
;
}
else
{
}
else
{
// It's calling applets
// It's calling applets
--
argc
;
--
argc
;
++
argv
;
++
argv
;
arg
=
argv
[
0
];
}
}
}
}
// Applets
// Applets
if
(
strcmp
(
arg
v
[
0
],
"magiskhide
"
)
==
0
)
{
if
(
strcmp
(
arg
,
"su
"
)
==
0
)
{
magiskhide
_main
(
argc
,
argv
);
return
su
_main
(
argc
,
argv
);
}
else
if
(
strcmp
(
arg
v
[
0
]
,
"magiskpolicy"
)
==
0
)
{
}
else
if
(
strcmp
(
arg
,
"magiskpolicy"
)
==
0
)
{
magiskpolicy_main
(
argc
,
argv
);
return
magiskpolicy_main
(
argc
,
argv
);
}
else
if
(
strcmp
(
arg
v
[
0
]
,
"resetprop"
)
==
0
)
{
}
else
if
(
strcmp
(
arg
,
"resetprop"
)
==
0
)
{
resetprop_main
(
argc
,
argv
);
re
turn
re
setprop_main
(
argc
,
argv
);
}
else
if
(
strcmp
(
arg
v
[
0
],
"su
"
)
==
0
)
{
}
else
if
(
strcmp
(
arg
,
"magiskhide
"
)
==
0
)
{
su
_main
(
argc
,
argv
);
return
magiskhide
_main
(
argc
,
argv
);
}
else
{
}
else
{
fprintf
(
stderr
,
"Applet
\'
%s
\'
not found
\n
"
,
arg
v
[
0
]
);
fprintf
(
stderr
,
"Applet
\'
%s
\'
not found
\n
"
,
arg
);
}
}
return
0
;
return
1
;
}
}
\ No newline at end of file
jni/utils/log_monitor.c
View file @
8f6b33d7
...
@@ -8,6 +8,7 @@
...
@@ -8,6 +8,7 @@
#include <stdio.h>
#include <stdio.h>
#include <pthread.h>
#include <pthread.h>
#include "magisk.h"
#include "utils.h"
#include "utils.h"
static
void
*
logger_thread
(
void
*
args
)
{
static
void
*
logger_thread
(
void
*
args
)
{
...
@@ -23,10 +24,8 @@ static void *logger_thread(void *args) {
...
@@ -23,10 +24,8 @@ static void *logger_thread(void *args) {
return
NULL
;
return
NULL
;
}
}
/* Start a new thread to monitor logcat and dump to file */
/* Start a new thread to monitor logcat and dump to
log
file */
void
monitor_logs
()
{
void
monitor_logs
()
{
pthread_t
log_monitor
;
pthread_t
log_monitor
;
pthread_create
(
&
log_monitor
,
NULL
,
logger_thread
,
NULL
);
pthread_create
(
&
log_monitor
,
NULL
,
logger_thread
,
NULL
);
printf
(
"Hello :)
\n
"
);
pthread_join
(
log_monitor
,
NULL
);
}
}
\ No newline at end of file
jni/utils/misc.c
0 → 100644
View file @
8f6b33d7
/* misc.c - Store all functions that are unable to be catagorized clearly
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "utils.h"
int
check_data
()
{
FILE
*
fp
=
xfopen
(
"/proc/mounts"
,
"r"
);
while
(
fgets
(
magiskbuf
,
BUF_SIZE
,
fp
))
{
if
(
strstr
(
magiskbuf
,
" /data "
))
{
if
(
strstr
(
magiskbuf
,
"tmpfs"
))
return
0
;
else
return
1
;
}
}
return
0
;
}
/* All the string should be freed manually!! */
void
file_to_vector
(
struct
vector
*
v
,
FILE
*
fp
)
{
char
*
line
=
NULL
;
size_t
len
=
0
;
ssize_t
read
;
while
((
read
=
getline
(
&
line
,
&
len
,
fp
))
!=
-
1
)
{
// Remove end newline
if
(
line
[
read
-
1
]
==
'\n'
)
line
[
read
-
1
]
=
'\0'
;
vec_push_back
(
v
,
line
);
line
=
NULL
;
}
}
jni/utils/utils.h
View file @
8f6b33d7
...
@@ -9,6 +9,12 @@
...
@@ -9,6 +9,12 @@
// xwrap.c
// xwrap.c
FILE
*
xfopen
(
const
char
*
pathname
,
const
char
*
mode
);
FILE
*
xfopen
(
const
char
*
pathname
,
const
char
*
mode
);
int
xopen
(
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
xpipe
(
int
pipefd
[
2
]);
int
xsetns
(
int
fd
,
int
nstype
);
// vector.c
// vector.c
...
@@ -18,4 +24,9 @@ FILE *xfopen(const char *pathname, const char *mode);
...
@@ -18,4 +24,9 @@ FILE *xfopen(const char *pathname, const char *mode);
void
monitor_logs
();
void
monitor_logs
();
// misc.c
int
check_data
();
void
file_to_vector
(
struct
vector
*
v
,
FILE
*
fp
);
#endif
#endif
\ No newline at end of file
jni/utils/vector.c
View file @
8f6b33d7
...
@@ -25,10 +25,23 @@ void vec_sort(struct vector *v, int (*compar)(const void *, const void *)) {
...
@@ -25,10 +25,23 @@ void vec_sort(struct vector *v, int (*compar)(const void *, const void *)) {
qsort
(
vec_entry
(
v
),
vec_size
(
v
),
sizeof
(
void
*
),
compar
);
qsort
(
vec_entry
(
v
),
vec_size
(
v
),
sizeof
(
void
*
),
compar
);
}
}
/* Will cleanup only the vector itself
* use in cases when each element requires special cleanup
*/
void
vec_destroy
(
struct
vector
*
v
)
{
void
vec_destroy
(
struct
vector
*
v
)
{
// Will not free each entry!
// Manually free each entry, then call this function
vec_size
(
v
)
=
0
;
vec_size
(
v
)
=
0
;
vec_cap
(
v
)
=
0
;
vec_cap
(
v
)
=
0
;
free
(
v
->
data
);
free
(
vec_entry
(
v
));
}
vec_entry
(
v
)
=
NULL
;
// Prevent double destroy segfault
\ No newline at end of file
}
/* Will cleanup each element AND the vector itself
* Shall be the general case
*/
void
vec_deep_destroy
(
struct
vector
*
v
)
{
void
*
e
;
vec_for_each
(
v
,
e
)
{
free
(
e
);
}
vec_destroy
(
v
);
}
jni/utils/vector.h
View file @
8f6b33d7
...
@@ -15,6 +15,7 @@ void vec_init(struct vector *v);
...
@@ -15,6 +15,7 @@ void vec_init(struct vector *v);
void
vec_push_back
(
struct
vector
*
v
,
void
*
p
);
void
vec_push_back
(
struct
vector
*
v
,
void
*
p
);
void
vec_sort
(
struct
vector
*
v
,
int
(
*
compar
)(
const
void
*
,
const
void
*
));
void
vec_sort
(
struct
vector
*
v
,
int
(
*
compar
)(
const
void
*
,
const
void
*
));
void
vec_destroy
(
struct
vector
*
v
);
void
vec_destroy
(
struct
vector
*
v
);
void
vec_deep_destroy
(
struct
vector
*
v
);
#define vec_size(v) (v)->size
#define vec_size(v) (v)->size
#define vec_cap(v) (v)->cap
#define vec_cap(v) (v)->cap
#define vec_entry(v) (v)->data
#define vec_entry(v) (v)->data
...
@@ -23,4 +24,8 @@ void vec_destroy(struct vector *v);
...
@@ -23,4 +24,8 @@ void vec_destroy(struct vector *v);
e = (v)->data[0]; \
e = (v)->data[0]; \
for (size_t _ = 0; _ < (v)->size; ++_, e = (v)->data[_])
for (size_t _ = 0; _ < (v)->size; ++_, e = (v)->data[_])
#define vec_for_each_r(v, e) \
e = (v)->data[(v)->size - 1]; \
for (size_t _ = (v)->size - 1; _ >= 0; --_, e = (v)->data[_])
#endif
#endif
\ No newline at end of file
jni/utils/xwrap.c
View file @
8f6b33d7
...
@@ -6,8 +6,14 @@
...
@@ -6,8 +6,14 @@
*
*
*/
*/
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "utils.h"
#include "utils.h"
...
@@ -15,7 +21,54 @@ FILE *xfopen(const char *pathname, const char *mode) {
...
@@ -15,7 +21,54 @@ FILE *xfopen(const char *pathname, const char *mode) {
FILE
*
fp
=
fopen
(
pathname
,
mode
);
FILE
*
fp
=
fopen
(
pathname
,
mode
);
if
(
fp
==
NULL
)
{
if
(
fp
==
NULL
)
{
PLOGE
(
"fopen"
);
PLOGE
(
"fopen"
);
exit
(
1
);
}
}
return
fp
;
return
fp
;
}
}
\ No newline at end of file
int
xopen
(
const
char
*
pathname
,
int
flags
)
{
int
fd
=
open
(
pathname
,
flags
);
if
(
fd
<
0
)
{
PLOGE
(
"open"
);
}
return
fd
;
}
ssize_t
xwrite
(
int
fd
,
const
void
*
buf
,
size_t
count
)
{
if
(
count
!=
write
(
fd
,
buf
,
count
))
{
PLOGE
(
"write"
);
}
return
count
;
}
// Read error other than EOF
ssize_t
xread
(
int
fd
,
void
*
buf
,
size_t
count
)
{
int
ret
=
read
(
fd
,
buf
,
count
);
if
(
ret
<
0
)
{
PLOGE
(
"read"
);
}
return
ret
;
}
// Read exact same size as count
ssize_t
xxread
(
int
fd
,
void
*
buf
,
size_t
count
)
{
if
(
count
!=
read
(
fd
,
buf
,
count
))
{
PLOGE
(
"read"
);
}
return
count
;
}
int
xpipe
(
int
pipefd
[
2
])
{
if
(
pipe
(
pipefd
)
==
-
1
)
{
PLOGE
(
"pipe"
);
exit
(
1
);
}
return
0
;
}
int
xsetns
(
int
fd
,
int
nstype
)
{
if
(
setns
(
fd
,
nstype
)
==
-
1
)
{
PLOGE
(
"setns"
);
}
return
0
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment