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
c8ac6c07
Commit
c8ac6c07
authored
Oct 13, 2021
by
topjohnwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Load Zygisk modules
parent
27814e30
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
365 additions
and
119 deletions
+365
-119
core.hpp
native/jni/core/core.hpp
+1
-1
module.cpp
native/jni/core/module.cpp
+64
-18
scripting.cpp
native/jni/core/scripting.cpp
+9
-10
socket.cpp
native/jni/core/socket.cpp
+4
-1
daemon.hpp
native/jni/include/daemon.hpp
+1
-0
api.hpp
native/jni/zygisk/api.hpp
+4
-4
entry.cpp
native/jni/zygisk/entry.cpp
+39
-24
hook.cpp
native/jni/zygisk/hook.cpp
+123
-59
module.hpp
native/jni/zygisk/module.hpp
+117
-0
zygisk.hpp
native/jni/zygisk/zygisk.hpp
+3
-2
No files found.
native/jni/core/core.hpp
View file @
c8ac6c07
...
@@ -31,6 +31,6 @@ void exec_module_scripts(const char *stage);
...
@@ -31,6 +31,6 @@ void exec_module_scripts(const char *stage);
// Scripting
// Scripting
void
exec_script
(
const
char
*
script
);
void
exec_script
(
const
char
*
script
);
void
exec_common_scripts
(
const
char
*
stage
);
void
exec_common_scripts
(
const
char
*
stage
);
void
exec_module_scripts
(
const
char
*
stage
,
const
std
::
vector
<
std
::
string
>
&
module_list
);
void
exec_module_scripts
(
const
char
*
stage
,
const
std
::
vector
<
std
::
string
_view
>
&
modules
);
void
install_apk
(
const
char
*
apk
);
void
install_apk
(
const
char
*
apk
);
[[
noreturn
]]
void
install_module
(
const
char
*
file
);
[[
noreturn
]]
void
install_module
(
const
char
*
file
);
native/jni/core/module.cpp
View file @
c8ac6c07
...
@@ -22,8 +22,6 @@ using namespace std;
...
@@ -22,8 +22,6 @@ using namespace std;
#define TYPE_CUSTOM (1 << 5)
/* custom node type overrides all */
#define TYPE_CUSTOM (1 << 5)
/* custom node type overrides all */
#define TYPE_DIR (TYPE_INTER|TYPE_TMPFS|TYPE_ROOT)
#define TYPE_DIR (TYPE_INTER|TYPE_TMPFS|TYPE_ROOT)
static
vector
<
string
>
module_list
;
class
node_entry
;
class
node_entry
;
class
dir_node
;
class
dir_node
;
class
inter_node
;
class
inter_node
;
...
@@ -543,12 +541,22 @@ static void inject_magisk_bins(root_node *system) {
...
@@ -543,12 +541,22 @@ static void inject_magisk_bins(root_node *system) {
delete
bin
->
extract
(
init_applet
[
i
]);
delete
bin
->
extract
(
init_applet
[
i
]);
}
}
struct
module_info
{
string
name
;
int
z32
=
-
1
;
#if defined(__LP64__)
int
z64
=
-
1
;
#endif
};
static
vector
<
module_info
>
*
modules
;
#define mount_zygisk(bit) \
#define mount_zygisk(bit) \
if (access("/system/bin/app_process" #bit, F_OK) == 0) { \
if (access("/system/bin/app_process" #bit, F_OK) == 0) { \
string zbin = zygisk_bin + "/app_process" #bit; \
string zbin = zygisk_bin + "/app_process" #bit; \
string mbin = MAGISKTMP + "/magisk" #bit; \
string mbin = MAGISKTMP + "/magisk" #bit; \
int src = xopen(mbin.data(), O_RDONLY
);
\
int src = xopen(mbin.data(), O_RDONLY
| O_CLOEXEC);
\
int out = xopen(zbin.data(), O_CREAT | O_WRONLY, 0); \
int out = xopen(zbin.data(), O_CREAT | O_WRONLY
| O_CLOEXEC
, 0); \
xsendfile(out, src, nullptr, INT_MAX); \
xsendfile(out, src, nullptr, INT_MAX); \
close(src); \
close(src); \
close(out); \
close(out); \
...
@@ -566,8 +574,8 @@ void magic_mount() {
...
@@ -566,8 +574,8 @@ void magic_mount() {
char
buf
[
4096
];
char
buf
[
4096
];
LOGI
(
"* Loading modules
\n
"
);
LOGI
(
"* Loading modules
\n
"
);
for
(
const
auto
&
m
:
module_list
)
{
for
(
const
auto
&
m
:
*
modules
)
{
auto
module
=
m
.
data
();
const
char
*
module
=
m
.
name
.
data
();
char
*
b
=
buf
+
sprintf
(
buf
,
"%s/"
MODULEMNT
"/%s/"
,
MAGISKTMP
.
data
(),
module
);
char
*
b
=
buf
+
sprintf
(
buf
,
"%s/"
MODULEMNT
"/%s/"
,
MAGISKTMP
.
data
(),
module
);
// Read props
// Read props
...
@@ -676,8 +684,8 @@ static void foreach_module(Func fn) {
...
@@ -676,8 +684,8 @@ static void foreach_module(Func fn) {
}
}
}
}
static
void
collect_modules
()
{
static
void
collect_modules
(
bool
open_zygisk
)
{
foreach_module
([](
int
dfd
,
dirent
*
entry
,
int
modfd
)
{
foreach_module
([
=
](
int
dfd
,
dirent
*
entry
,
int
modfd
)
{
if
(
faccessat
(
modfd
,
"remove"
,
F_OK
,
0
)
==
0
)
{
if
(
faccessat
(
modfd
,
"remove"
,
F_OK
,
0
)
==
0
)
{
LOGI
(
"%s: remove
\n
"
,
entry
->
d_name
);
LOGI
(
"%s: remove
\n
"
,
entry
->
d_name
);
auto
uninstaller
=
MODULEROOT
+
"/"
s
+
entry
->
d_name
+
"/uninstall.sh"
;
auto
uninstaller
=
MODULEROOT
+
"/"
s
+
entry
->
d_name
+
"/uninstall.sh"
;
...
@@ -690,24 +698,42 @@ static void collect_modules() {
...
@@ -690,24 +698,42 @@ static void collect_modules() {
unlinkat
(
modfd
,
"update"
,
0
);
unlinkat
(
modfd
,
"update"
,
0
);
if
(
faccessat
(
modfd
,
"disable"
,
F_OK
,
0
)
==
0
)
if
(
faccessat
(
modfd
,
"disable"
,
F_OK
,
0
)
==
0
)
return
;
return
;
// Riru and its modules are not compatible with zygisk
if
(
zygisk_enabled
&&
(
entry
->
d_name
==
"riru-core"
sv
||
faccessat
(
modfd
,
"riru"
,
F_OK
,
0
)
==
0
))
return
;
module_list
.
emplace_back
(
entry
->
d_name
);
module_info
info
;
if
(
zygisk_enabled
)
{
// Riru and its modules are not compatible with zygisk
if
(
entry
->
d_name
==
"riru-core"
sv
||
faccessat
(
modfd
,
"riru"
,
F_OK
,
0
)
==
0
)
return
;
if
(
open_zygisk
)
{
#if defined(__arm__)
info
.
z32
=
openat
(
modfd
,
"zygisk/armeabi-v7a.so"
,
O_RDONLY
|
O_CLOEXEC
);
#elif defined(__aarch64__)
info
.
z32
=
openat
(
modfd
,
"zygisk/armeabi-v7a.so"
,
O_RDONLY
|
O_CLOEXEC
);
info
.
z64
=
openat
(
modfd
,
"zygisk/arm64-v8a.so"
,
O_RDONLY
|
O_CLOEXEC
);
#elif defined(__i386__)
info
.
z32
=
openat
(
modfd
,
"zygisk/x86.so"
,
O_RDONLY
|
O_CLOEXEC
);
#elif defined(__x86_64__)
info
.
z32
=
openat
(
modfd
,
"zygisk/x86.so"
,
O_RDONLY
|
O_CLOEXEC
);
info
.
z64
=
openat
(
modfd
,
"zygisk/x86_64.so"
,
O_RDONLY
|
O_CLOEXEC
);
#else
#error Unsupported ABI
#endif
}
}
info
.
name
=
entry
->
d_name
;
modules
->
push_back
(
info
);
});
});
}
}
void
handle_modules
()
{
void
handle_modules
()
{
default_new
(
modules
);
prepare_modules
();
prepare_modules
();
collect_modules
();
collect_modules
(
false
);
exec_module_scripts
(
"post-fs-data"
);
exec_module_scripts
(
"post-fs-data"
);
// Recollect modules (module scripts could remove itself)
// Recollect modules (module scripts could remove itself)
module
_list
.
clear
();
module
s
->
clear
();
collect_modules
();
collect_modules
(
true
);
}
}
void
disable_modules
()
{
void
disable_modules
()
{
...
@@ -726,5 +752,25 @@ void remove_modules() {
...
@@ -726,5 +752,25 @@ void remove_modules() {
}
}
void
exec_module_scripts
(
const
char
*
stage
)
{
void
exec_module_scripts
(
const
char
*
stage
)
{
exec_module_scripts
(
stage
,
module_list
);
vector
<
string_view
>
module_names
;
std
::
transform
(
modules
->
begin
(),
modules
->
end
(),
std
::
back_inserter
(
module_names
),
[](
const
module_info
&
info
)
{
return
info
.
name
;
});
exec_module_scripts
(
stage
,
module_names
);
}
vector
<
int
>
zygisk_module_fds
(
bool
is_64_bit
)
{
vector
<
int
>
fds
;
// All fds passed to send_fds have to be valid file descriptors.
// To workaround this issue, send over STDOUT_FILENO as an indicator of an
// invalid fd as it will always be /dev/null in magiskd
if
(
is_64_bit
)
{
#if defined(__LP64__)
std
::
transform
(
modules
->
begin
(),
modules
->
end
(),
std
::
back_inserter
(
fds
),
[](
const
module_info
&
info
)
{
return
info
.
z64
<
0
?
STDOUT_FILENO
:
info
.
z64
;
});
#endif
}
else
{
std
::
transform
(
modules
->
begin
(),
modules
->
end
(),
std
::
back_inserter
(
fds
),
[](
const
module_info
&
info
)
{
return
info
.
z32
<
0
?
STDOUT_FILENO
:
info
.
z32
;
});
}
return
fds
;
}
}
native/jni/core/scripting.cpp
View file @
c8ac6c07
...
@@ -107,16 +107,15 @@ void exec_common_scripts(const char *stage) {
...
@@ -107,16 +107,15 @@ void exec_common_scripts(const char *stage) {
PFS_DONE
()
PFS_DONE
()
}
}
// Return if a > b
static
bool
operator
>
(
const
timespec
&
a
,
const
timespec
&
b
)
{
static
bool
timespec_larger
(
timespec
*
a
,
timespec
*
b
)
{
if
(
a
.
tv_sec
!=
b
.
tv_sec
)
if
(
a
->
tv_sec
!=
b
->
tv_sec
)
return
a
.
tv_sec
>
b
.
tv_sec
;
return
a
->
tv_sec
>
b
->
tv_sec
;
return
a
.
tv_nsec
>
b
.
tv_nsec
;
return
a
->
tv_nsec
>
b
->
tv_nsec
;
}
}
void
exec_module_scripts
(
const
char
*
stage
,
const
vector
<
string
>
&
module_list
)
{
void
exec_module_scripts
(
const
char
*
stage
,
const
vector
<
string
_view
>
&
modules
)
{
LOGI
(
"* Running module %s scripts
\n
"
,
stage
);
LOGI
(
"* Running module %s scripts
\n
"
,
stage
);
if
(
module
_list
.
empty
())
if
(
module
s
.
empty
())
return
;
return
;
bool
pfs
=
stage
==
"post-fs-data"
sv
;
bool
pfs
=
stage
==
"post-fs-data"
sv
;
...
@@ -124,15 +123,15 @@ void exec_module_scripts(const char *stage, const vector<string> &module_list) {
...
@@ -124,15 +123,15 @@ void exec_module_scripts(const char *stage, const vector<string> &module_list) {
timespec
now
{};
timespec
now
{};
clock_gettime
(
CLOCK_MONOTONIC
,
&
now
);
clock_gettime
(
CLOCK_MONOTONIC
,
&
now
);
// If we had already timed out, treat it as service mode
// If we had already timed out, treat it as service mode
if
(
timespec_larger
(
&
now
,
&
pfs_timeout
)
)
if
(
now
>
pfs_timeout
)
pfs
=
false
;
pfs
=
false
;
}
}
int
timer_pid
=
-
1
;
int
timer_pid
=
-
1
;
PFS_SETUP
()
PFS_SETUP
()
char
path
[
4096
];
char
path
[
4096
];
for
(
auto
&
m
:
module
_list
)
{
for
(
auto
&
m
:
module
s
)
{
const
char
*
module
=
m
.
data
();
const
char
*
module
=
m
.
data
();
sprintf
(
path
,
MODULEROOT
"/%s/%s.sh"
,
module
,
stage
);
sprintf
(
path
,
MODULEROOT
"/%s/%s.sh"
,
module
,
stage
);
if
(
access
(
path
,
F_OK
)
==
-
1
)
if
(
access
(
path
,
F_OK
)
==
-
1
)
continue
;
continue
;
...
...
native/jni/core/socket.cpp
View file @
c8ac6c07
...
@@ -93,14 +93,17 @@ static void *recv_fds(int sockfd, char *cmsgbuf, size_t bufsz, int cnt) {
...
@@ -93,14 +93,17 @@ static void *recv_fds(int sockfd, char *cmsgbuf, size_t bufsz, int cnt) {
}
}
vector
<
int
>
recv_fds
(
int
sockfd
)
{
vector
<
int
>
recv_fds
(
int
sockfd
)
{
vector
<
int
>
results
;
// Peek fd count to allocate proper buffer
// Peek fd count to allocate proper buffer
int
cnt
;
int
cnt
;
recv
(
sockfd
,
&
cnt
,
sizeof
(
cnt
),
MSG_PEEK
);
recv
(
sockfd
,
&
cnt
,
sizeof
(
cnt
),
MSG_PEEK
);
if
(
cnt
==
0
)
return
results
;
vector
<
char
>
cmsgbuf
;
vector
<
char
>
cmsgbuf
;
cmsgbuf
.
resize
(
CMSG_SPACE
(
sizeof
(
int
)
*
cnt
));
cmsgbuf
.
resize
(
CMSG_SPACE
(
sizeof
(
int
)
*
cnt
));
vector
<
int
>
results
;
void
*
data
=
recv_fds
(
sockfd
,
cmsgbuf
.
data
(),
cmsgbuf
.
size
(),
cnt
);
void
*
data
=
recv_fds
(
sockfd
,
cmsgbuf
.
data
(),
cmsgbuf
.
size
(),
cnt
);
if
(
data
==
nullptr
)
if
(
data
==
nullptr
)
return
results
;
return
results
;
...
...
native/jni/include/daemon.hpp
View file @
c8ac6c07
...
@@ -65,6 +65,7 @@ void boot_complete(int client);
...
@@ -65,6 +65,7 @@ void boot_complete(int client);
void
denylist_handler
(
int
client
,
ucred
*
cred
);
void
denylist_handler
(
int
client
,
ucred
*
cred
);
void
su_daemon_handler
(
int
client
,
ucred
*
credential
);
void
su_daemon_handler
(
int
client
,
ucred
*
credential
);
void
zygisk_handler
(
int
client
,
ucred
*
cred
);
void
zygisk_handler
(
int
client
,
ucred
*
cred
);
std
::
vector
<
int
>
zygisk_module_fds
(
bool
is_64_bit
);
// Denylist
// Denylist
void
initialize_denylist
();
void
initialize_denylist
();
...
...
native/jni/zygisk/api.hpp
View file @
c8ac6c07
...
@@ -172,7 +172,7 @@ struct Api {
...
@@ -172,7 +172,7 @@ struct Api {
// The original function pointer will be saved in each JNINativeMethod's fnPtr.
// The original function pointer will be saved in each JNINativeMethod's fnPtr.
// If no matching class, method name, or signature is found, that specific JNINativeMethod.fnPtr
// If no matching class, method name, or signature is found, that specific JNINativeMethod.fnPtr
// will be set to nullptr.
// will be set to nullptr.
void
hookJniNativeMethods
(
const
char
*
className
,
JNINativeMethod
*
methods
,
int
numMethods
);
void
hookJniNativeMethods
(
JNIEnv
*
env
,
const
char
*
className
,
JNINativeMethod
*
methods
,
int
numMethods
);
// For ELFs loaded in memory matching `regex`, replace function `symbol` with `newFunc`.
// For ELFs loaded in memory matching `regex`, replace function `symbol` with `newFunc`.
// If `oldFunc` is not nullptr, the original function pointer will be saved to `oldFunc`.
// If `oldFunc` is not nullptr, the original function pointer will be saved to `oldFunc`.
...
@@ -241,7 +241,7 @@ struct api_table {
...
@@ -241,7 +241,7 @@ struct api_table {
bool
(
*
registerModule
)(
api_table
*
,
module_abi
*
);
bool
(
*
registerModule
)(
api_table
*
,
module_abi
*
);
// Utility functions
// Utility functions
void
(
*
hookJniNativeMethods
)(
const
char
*
,
JNINativeMethod
*
,
int
);
void
(
*
hookJniNativeMethods
)(
JNIEnv
*
,
const
char
*
,
JNINativeMethod
*
,
int
);
void
(
*
pltHookRegister
)(
const
char
*
,
const
char
*
,
void
*
,
void
**
);
void
(
*
pltHookRegister
)(
const
char
*
,
const
char
*
,
void
*
,
void
**
);
void
(
*
pltHookExclude
)(
const
char
*
,
const
char
*
);
void
(
*
pltHookExclude
)(
const
char
*
,
const
char
*
);
bool
(
*
pltHookCommit
)();
bool
(
*
pltHookCommit
)();
...
@@ -269,8 +269,8 @@ int Api::connectCompanion() {
...
@@ -269,8 +269,8 @@ int Api::connectCompanion() {
void
Api
::
forceDenyListUnmount
()
{
void
Api
::
forceDenyListUnmount
()
{
impl
->
forceDenyListUnmount
(
impl
->
_this
);
impl
->
forceDenyListUnmount
(
impl
->
_this
);
}
}
void
Api
::
hookJniNativeMethods
(
const
char
*
className
,
JNINativeMethod
*
methods
,
int
numMethods
)
{
void
Api
::
hookJniNativeMethods
(
JNIEnv
*
env
,
const
char
*
className
,
JNINativeMethod
*
methods
,
int
numMethods
)
{
impl
->
hookJniNativeMethods
(
className
,
methods
,
numMethods
);
impl
->
hookJniNativeMethods
(
env
,
className
,
methods
,
numMethods
);
}
}
void
Api
::
pltHookRegister
(
const
char
*
regex
,
const
char
*
symbol
,
void
*
newFunc
,
void
**
oldFunc
)
{
void
Api
::
pltHookRegister
(
const
char
*
regex
,
const
char
*
symbol
,
void
*
newFunc
,
void
**
oldFunc
)
{
impl
->
pltHookRegister
(
regex
,
symbol
,
newFunc
,
oldFunc
);
impl
->
pltHookRegister
(
regex
,
symbol
,
newFunc
,
oldFunc
);
...
...
native/jni/zygisk/entry.cpp
View file @
c8ac6c07
...
@@ -213,17 +213,21 @@ static int zygisk_log(int prio, const char *fmt, va_list ap) {
...
@@ -213,17 +213,21 @@ static int zygisk_log(int prio, const char *fmt, va_list ap) {
return
ret
;
return
ret
;
}
}
void
remote_get_app_info
(
int
uid
,
const
char
*
process
,
AppInfo
*
info
)
{
std
::
vector
<
int
>
remote_get_info
(
int
uid
,
const
char
*
process
,
AppInfo
*
info
)
{
vector
<
int
>
fds
;
if
(
int
fd
=
connect_daemon
();
fd
>=
0
)
{
if
(
int
fd
=
connect_daemon
();
fd
>=
0
)
{
write_int
(
fd
,
ZYGISK_REQUEST
);
write_int
(
fd
,
ZYGISK_REQUEST
);
write_int
(
fd
,
ZYGISK_GET_
APP
INFO
);
write_int
(
fd
,
ZYGISK_GET_INFO
);
write_int
(
fd
,
uid
);
write_int
(
fd
,
uid
);
write_string
(
fd
,
process
);
write_string
(
fd
,
process
);
xxread
(
fd
,
info
,
sizeof
(
*
info
));
xxread
(
fd
,
info
,
sizeof
(
*
info
));
if
(
!
info
->
on_denylist
)
{
fds
=
recv_fds
(
fd
);
}
close
(
fd
);
close
(
fd
);
}
}
return
fds
;
}
}
int
remote_request_unmount
()
{
int
remote_request_unmount
()
{
...
@@ -261,12 +265,12 @@ static void setup_files(int client, ucred *cred) {
...
@@ -261,12 +265,12 @@ static void setup_files(int client, ucred *cred) {
int
cached_manager_app_id
=
-
1
;
int
cached_manager_app_id
=
-
1
;
static
time_t
last_modified
=
0
;
static
time_t
last_modified
=
0
;
static
void
get_
app_info
(
int
client
)
{
static
void
get_
process_info
(
int
client
,
ucred
*
cred
)
{
AppInfo
info
{};
AppInfo
info
{};
int
uid
=
read_int
(
client
);
int
uid
=
read_int
(
client
);
string
process
=
read_string
(
client
);
string
process
=
read_string
(
client
);
// This function is called on every single zygote
app
process specialization,
// This function is called on every single zygote process specialization,
// so performance is critical. get_manager_app_id() is expensive as it goes
// so performance is critical. get_manager_app_id() is expensive as it goes
// through a SQLite query and potentially multiple filesystem stats, so we
// through a SQLite query and potentially multiple filesystem stats, so we
// really want to cache the app ID value. Check the last modify timestamp of
// really want to cache the app ID value. Check the last modify timestamp of
...
@@ -275,29 +279,40 @@ static void get_app_info(int client) {
...
@@ -275,29 +279,40 @@ static void get_app_info(int client) {
// If denylist is enabled, inotify will invalidate the app ID cache for us.
// If denylist is enabled, inotify will invalidate the app ID cache for us.
// In this case, we can skip the timestamp check all together.
// In this case, we can skip the timestamp check all together.
int
manager_app_id
=
cached_manager_app_id
;
if
(
uid
!=
1000
)
{
int
manager_app_id
=
cached_manager_app_id
;
// Denylist not enabled, check packages.xml timestamp
// Denylist not enabled, check packages.xml timestamp
if
(
!
denylist_enabled
&&
manager_app_id
>
0
)
{
if
(
!
denylist_enabled
&&
manager_app_id
>
0
)
{
struct
stat
st
{};
struct
stat
st
{};
stat
(
"/data/system/packages.xml"
,
&
st
);
stat
(
"/data/system/packages.xml"
,
&
st
);
if
(
st
.
st_atim
.
tv_sec
>
last_modified
)
{
if
(
st
.
st_atim
.
tv_sec
>
last_modified
)
{
manager_app_id
=
-
1
;
manager_app_id
=
-
1
;
last_modified
=
st
.
st_atim
.
tv_sec
;
last_modified
=
st
.
st_atim
.
tv_sec
;
}
}
}
}
if
(
manager_app_id
<
0
)
{
if
(
manager_app_id
<
0
)
{
manager_app_id
=
get_manager_app_id
();
manager_app_id
=
get_manager_app_id
();
cached_manager_app_id
=
manager_app_id
;
cached_manager_app_id
=
manager_app_id
;
}
}
if
(
to_app_id
(
uid
)
==
manager_app_id
)
{
if
(
to_app_id
(
uid
)
==
manager_app_id
)
{
info
.
is_magisk_app
=
true
;
info
.
is_magisk_app
=
true
;
}
else
if
(
denylist_enabled
)
{
}
else
if
(
denylist_enabled
)
{
info
.
on_denylist
=
is_deny_target
(
uid
,
process
);
info
.
on_denylist
=
is_deny_target
(
uid
,
process
);
}
}
}
xwrite
(
client
,
&
info
,
sizeof
(
info
));
xwrite
(
client
,
&
info
,
sizeof
(
info
));
if
(
!
info
.
on_denylist
)
{
char
buf
[
256
];
snprintf
(
buf
,
sizeof
(
buf
),
"/proc/%d/exe"
,
cred
->
pid
);
xreadlink
(
buf
,
buf
,
sizeof
(
buf
));
vector
<
int
>
fds
=
zygisk_module_fds
(
str_ends
(
buf
,
"64"
));
send_fds
(
client
,
fds
.
data
(),
fds
.
size
());
}
}
}
static
void
do_unmount
(
int
client
,
ucred
*
cred
)
{
static
void
do_unmount
(
int
client
,
ucred
*
cred
)
{
...
@@ -325,8 +340,8 @@ void zygisk_handler(int client, ucred *cred) {
...
@@ -325,8 +340,8 @@ void zygisk_handler(int client, ucred *cred) {
case
ZYGISK_SETUP
:
case
ZYGISK_SETUP
:
setup_files
(
client
,
cred
);
setup_files
(
client
,
cred
);
break
;
break
;
case
ZYGISK_GET_
APP
INFO
:
case
ZYGISK_GET_INFO
:
get_
app_info
(
client
);
get_
process_info
(
client
,
cred
);
break
;
break
;
case
ZYGISK_UNMOUNT
:
case
ZYGISK_UNMOUNT
:
do_unmount
(
client
,
cred
);
do_unmount
(
client
,
cred
);
...
...
native/jni/zygisk/hook.cpp
View file @
c8ac6c07
...
@@ -8,7 +8,7 @@
...
@@ -8,7 +8,7 @@
#include "zygisk.hpp"
#include "zygisk.hpp"
#include "memory.hpp"
#include "memory.hpp"
#include "
api
.hpp"
#include "
module
.hpp"
using
namespace
std
;
using
namespace
std
;
using
jni_hook
::
hash_map
;
using
jni_hook
::
hash_map
;
...
@@ -22,57 +22,13 @@ using xstring = jni_hook::string;
...
@@ -22,57 +22,13 @@ using xstring = jni_hook::string;
namespace
{
namespace
{
enum
{
enum
{
DENY
_FLAG
,
UNMOUNT
_FLAG
,
FORK_AND_SPECIALIZE
,
FORK_AND_SPECIALIZE
,
APP_SPECIALIZE
,
APP_SPECIALIZE
,
SERVER_SPECIALIZE
,
SERVER_SPECIALIZE
,
FLAG_MAX
FLAG_MAX
};
};
struct
AppSpecializeArgsImpl
{
jint
&
uid
;
jint
&
gid
;
jintArray
&
gids
;
jint
&
runtime_flags
;
jint
&
mount_external
;
jstring
&
se_info
;
jstring
&
nice_name
;
jstring
&
instruction_set
;
jstring
&
app_data_dir
;
/* Optional */
jboolean
*
is_child_zygote
=
nullptr
;
jboolean
*
is_top_app
=
nullptr
;
jobjectArray
*
pkg_data_info_list
=
nullptr
;
jobjectArray
*
whitelisted_data_info_list
=
nullptr
;
jboolean
*
mount_data_dirs
=
nullptr
;
jboolean
*
mount_storage_dirs
=
nullptr
;
AppSpecializeArgsImpl
(
jint
&
uid
,
jint
&
gid
,
jintArray
&
gids
,
jint
&
runtime_flags
,
jint
&
mount_external
,
jstring
&
se_info
,
jstring
&
nice_name
,
jstring
&
instruction_set
,
jstring
&
app_data_dir
)
:
uid
(
uid
),
gid
(
gid
),
gids
(
gids
),
runtime_flags
(
runtime_flags
),
mount_external
(
mount_external
),
se_info
(
se_info
),
nice_name
(
nice_name
),
instruction_set
(
instruction_set
),
app_data_dir
(
app_data_dir
)
{}
};
struct
ServerSpecializeArgsImpl
{
jint
&
uid
;
jint
&
gid
;
jintArray
&
gids
;
jint
&
runtime_flags
;
jlong
&
permitted_capabilities
;
jlong
&
effective_capabilities
;
ServerSpecializeArgsImpl
(
jint
&
uid
,
jint
&
gid
,
jintArray
&
gids
,
jint
&
runtime_flags
,
jlong
&
permitted_capabilities
,
jlong
&
effective_capabilities
)
:
uid
(
uid
),
gid
(
gid
),
gids
(
gids
),
runtime_flags
(
runtime_flags
),
permitted_capabilities
(
permitted_capabilities
),
effective_capabilities
(
effective_capabilities
)
{}
};
#define DCL_PRE_POST(name) \
#define DCL_PRE_POST(name) \
void name##_pre(); \
void name##_pre(); \
void name##_post();
void name##_post();
...
@@ -88,14 +44,16 @@ struct HookContext {
...
@@ -88,14 +44,16 @@ struct HookContext {
int
pid
;
int
pid
;
bitset
<
FLAG_MAX
>
flags
;
bitset
<
FLAG_MAX
>
flags
;
AppInfo
info
;
AppInfo
info
;
vector
<
ZygiskModule
>
modules
;
HookContext
()
:
pid
(
-
1
),
info
{}
{}
HookContext
()
:
pid
(
-
1
),
info
{}
{}
static
void
close_fds
();
static
void
close_fds
();
void
toggle_unmount
();
DCL_PRE_POST
(
fork
)
DCL_PRE_POST
(
fork
)
DCL_PRE_POST
(
run_modules
)
void
run_modules_pre
(
const
vector
<
int
>
&
fds
);
void
run_modules_post
();
DCL_PRE_POST
(
nativeForkAndSpecialize
)
DCL_PRE_POST
(
nativeForkAndSpecialize
)
DCL_PRE_POST
(
nativeSpecializeAppProcess
)
DCL_PRE_POST
(
nativeSpecializeAppProcess
)
DCL_PRE_POST
(
nativeForkSystemServer
)
DCL_PRE_POST
(
nativeForkSystemServer
)
...
@@ -184,7 +142,7 @@ DCL_HOOK_FUNC(int, fork) {
...
@@ -184,7 +142,7 @@ DCL_HOOK_FUNC(int, fork) {
// This is the latest point where we can still connect to the magiskd main socket
// This is the latest point where we can still connect to the magiskd main socket
DCL_HOOK_FUNC
(
int
,
selinux_android_setcontext
,
DCL_HOOK_FUNC
(
int
,
selinux_android_setcontext
,
uid_t
uid
,
int
isSystemServer
,
const
char
*
seinfo
,
const
char
*
pkgname
)
{
uid_t
uid
,
int
isSystemServer
,
const
char
*
seinfo
,
const
char
*
pkgname
)
{
if
(
g_ctx
&&
g_ctx
->
flags
[
DENY
_FLAG
])
{
if
(
g_ctx
&&
g_ctx
->
flags
[
UNMOUNT
_FLAG
])
{
if
(
remote_request_unmount
()
==
0
)
{
if
(
remote_request_unmount
()
==
0
)
{
LOGD
(
"zygisk: mount namespace cleaned up
\n
"
);
LOGD
(
"zygisk: mount namespace cleaned up
\n
"
);
}
}
...
@@ -267,13 +225,121 @@ DCL_HOOK_FUNC(void, setArgv0, void *self, const char *argv0, bool setProcName) {
...
@@ -267,13 +225,121 @@ DCL_HOOK_FUNC(void, setArgv0, void *self, const char *argv0, bool setProcName) {
// -----------------------------------------------------------------
// -----------------------------------------------------------------
void
HookContext
::
run_modules_pre
()
{
/* TODO */
}
void
hookJniNativeMethods
(
JNIEnv
*
env
,
const
char
*
clz
,
JNINativeMethod
*
methods
,
int
numMethods
)
{
void
HookContext
::
run_modules_post
()
{
/* TODO */
}
auto
class_map
=
jni_method_map
->
find
(
clz
);
if
(
class_map
==
jni_method_map
->
end
())
{
for
(
int
i
=
0
;
i
<
numMethods
;
++
i
)
{
methods
[
i
].
fnPtr
=
nullptr
;
}
return
;
}
vector
<
JNINativeMethod
>
hooks
;
for
(
int
i
=
0
;
i
<
numMethods
;
++
i
)
{
auto
method_map
=
class_map
->
second
.
find
(
methods
[
i
].
name
);
if
(
method_map
!=
class_map
->
second
.
end
())
{
auto
it
=
method_map
->
second
.
find
(
methods
[
i
].
signature
);
if
(
it
!=
method_map
->
second
.
end
())
{
// Copy the JNINativeMethod
hooks
.
push_back
(
methods
[
i
]);
// Save the original function pointer
methods
[
i
].
fnPtr
=
it
->
second
;
// Do not allow double hook, remove method from map
method_map
->
second
.
erase
(
it
);
continue
;
}
}
// No matching method found, set fnPtr to null
methods
[
i
].
fnPtr
=
nullptr
;
}
if
(
hooks
.
empty
())
return
;
old_jniRegisterNativeMethods
(
env
,
clz
,
hooks
.
data
(),
hooks
.
size
());
}
bool
ZygiskModule
::
registerModule
(
ApiTable
*
table
,
long
*
module
)
{
long
ver
=
*
module
;
// Unsupported version
if
(
ver
>
ZYGISK_API_VERSION
)
return
false
;
// Set the actual module_abi*
table
->
module
->
ver
=
module
;
// Fill in API accordingly with module API version
table
->
v1
.
hookJniNativeMethods
=
&
hookJniNativeMethods
;
table
->
v1
.
pltHookRegister
=
[](
const
char
*
path
,
const
char
*
symbol
,
void
*
n
,
void
**
o
)
{
xhook_register
(
path
,
symbol
,
n
,
o
);
};
table
->
v1
.
pltHookExclude
=
[](
const
char
*
path
,
const
char
*
symbol
)
{
xhook_ignore
(
path
,
symbol
);
};
table
->
v1
.
pltHookCommit
=
[]()
{
return
xhook_refresh
(
0
)
==
0
;
};
table
->
v1
.
connectCompanion
=
[](
ZygiskModule
*
m
)
{
return
m
->
connectCompanion
();
};
table
->
v1
.
forceDenyListUnmount
=
[](
auto
)
{
ZygiskModule
::
forceDenyListUnmount
();
};
return
true
;
}
int
ZygiskModule
::
connectCompanion
()
{
// TODO
(
void
)
id
;
return
-
1
;
}
void
ZygiskModule
::
forceDenyListUnmount
()
{
if
(
g_ctx
==
nullptr
)
return
;
g_ctx
->
toggle_unmount
();
}
void
HookContext
::
run_modules_pre
(
const
vector
<
int
>
&
fds
)
{
char
buf
[
256
];
for
(
int
i
=
0
;
i
<
fds
.
size
();
++
i
)
{
snprintf
(
buf
,
sizeof
(
buf
),
"/proc/self/fd/%d"
,
fds
[
i
]);
if
(
void
*
h
=
dlopen
(
buf
,
RTLD_LAZY
))
{
void
(
*
module_entry
)(
void
*
,
void
*
);
*
(
void
**
)
&
module_entry
=
dlsym
(
h
,
"zygisk_module_entry"
);
if
(
module_entry
)
{
modules
.
emplace_back
(
i
);
auto
api
=
new
ApiTable
(
&
modules
.
back
());
module_entry
(
api
,
env
);
}
}
close
(
fds
[
i
]);
}
for
(
auto
&
m
:
modules
)
{
if
(
flags
[
APP_SPECIALIZE
])
{
m
.
preAppSpecialize
(
args
);
}
else
if
(
flags
[
SERVER_SPECIALIZE
])
{
m
.
preServerSpecialize
(
server_args
);
}
}
}
void
HookContext
::
run_modules_post
()
{
for
(
auto
&
m
:
modules
)
{
if
(
flags
[
APP_SPECIALIZE
])
{
m
.
postAppSpecialize
(
args
);
}
else
if
(
flags
[
SERVER_SPECIALIZE
])
{
m
.
postServerSpecialize
(
server_args
);
}
}
}
void
HookContext
::
close_fds
()
{
void
HookContext
::
close_fds
()
{
close
(
logd_fd
.
exchange
(
-
1
));
close
(
logd_fd
.
exchange
(
-
1
));
}
}
void
HookContext
::
toggle_unmount
()
{
if
(
flags
[
APP_SPECIALIZE
])
{
// TODO: Handle MOUNT_EXTERNAL_NONE
flags
[
UNMOUNT_FLAG
]
=
args
->
mount_external
!=
0
;
}
}
// -----------------------------------------------------------------
// -----------------------------------------------------------------
void
HookContext
::
nativeSpecializeAppProcess_pre
()
{
void
HookContext
::
nativeSpecializeAppProcess_pre
()
{
...
@@ -286,14 +352,12 @@ void HookContext::nativeSpecializeAppProcess_pre() {
...
@@ -286,14 +352,12 @@ void HookContext::nativeSpecializeAppProcess_pre() {
VLOG
(
"zygisk: pre specialize [%s]
\n
"
,
process
);
VLOG
(
"zygisk: pre specialize [%s]
\n
"
,
process
);
}
}
remote_get_app_info
(
args
->
uid
,
process
,
&
info
);
auto
module_fds
=
remote_get_info
(
args
->
uid
,
process
,
&
info
);
if
(
info
.
on_denylist
)
{
/* TODO: Handle MOUNT_EXTERNAL_NONE */
if
(
args
->
mount_external
!=
0
&&
info
.
on_denylist
)
{
LOGI
(
"zygisk: [%s] is on the denylist
\n
"
,
process
);
LOGI
(
"zygisk: [%s] is on the denylist
\n
"
,
process
);
flags
[
DENY_FLAG
]
=
true
;
toggle_unmount
()
;
}
else
{
}
else
{
run_modules_pre
();
run_modules_pre
(
module_fds
);
}
}
}
}
...
@@ -305,7 +369,7 @@ void HookContext::nativeSpecializeAppProcess_post() {
...
@@ -305,7 +369,7 @@ void HookContext::nativeSpecializeAppProcess_post() {
}
}
env
->
ReleaseStringUTFChars
(
args
->
nice_name
,
process
);
env
->
ReleaseStringUTFChars
(
args
->
nice_name
,
process
);
if
(
flags
[
DENY_FLAG
]
)
{
if
(
info
.
on_denylist
)
{
self_unload
();
self_unload
();
}
else
{
}
else
{
run_modules_post
();
run_modules_post
();
...
@@ -325,7 +389,7 @@ void HookContext::nativeForkSystemServer_pre() {
...
@@ -325,7 +389,7 @@ void HookContext::nativeForkSystemServer_pre() {
flags
[
SERVER_SPECIALIZE
]
=
true
;
flags
[
SERVER_SPECIALIZE
]
=
true
;
if
(
pid
==
0
)
{
if
(
pid
==
0
)
{
VLOG
(
"zygisk: pre forkSystemServer
\n
"
);
VLOG
(
"zygisk: pre forkSystemServer
\n
"
);
run_modules_pre
();
run_modules_pre
(
remote_get_info
(
1000
,
"system_server"
,
&
info
)
);
close_fds
();
close_fds
();
}
}
}
}
...
...
native/jni/zygisk/module.hpp
0 → 100644
View file @
c8ac6c07
#pragma once
#include "api.hpp"
namespace
{
using
module_abi_v1
=
zygisk
::
internal
::
module_abi
;
struct
HookContext
;
struct
ApiTable
;
struct
AppSpecializeArgsImpl
{
jint
&
uid
;
jint
&
gid
;
jintArray
&
gids
;
jint
&
runtime_flags
;
jint
&
mount_external
;
jstring
&
se_info
;
jstring
&
nice_name
;
jstring
&
instruction_set
;
jstring
&
app_data_dir
;
/* Optional */
jboolean
*
is_child_zygote
=
nullptr
;
jboolean
*
is_top_app
=
nullptr
;
jobjectArray
*
pkg_data_info_list
=
nullptr
;
jobjectArray
*
whitelisted_data_info_list
=
nullptr
;
jboolean
*
mount_data_dirs
=
nullptr
;
jboolean
*
mount_storage_dirs
=
nullptr
;
AppSpecializeArgsImpl
(
jint
&
uid
,
jint
&
gid
,
jintArray
&
gids
,
jint
&
runtime_flags
,
jint
&
mount_external
,
jstring
&
se_info
,
jstring
&
nice_name
,
jstring
&
instruction_set
,
jstring
&
app_data_dir
)
:
uid
(
uid
),
gid
(
gid
),
gids
(
gids
),
runtime_flags
(
runtime_flags
),
mount_external
(
mount_external
),
se_info
(
se_info
),
nice_name
(
nice_name
),
instruction_set
(
instruction_set
),
app_data_dir
(
app_data_dir
)
{}
};
struct
ServerSpecializeArgsImpl
{
jint
&
uid
;
jint
&
gid
;
jintArray
&
gids
;
jint
&
runtime_flags
;
jlong
&
permitted_capabilities
;
jlong
&
effective_capabilities
;
ServerSpecializeArgsImpl
(
jint
&
uid
,
jint
&
gid
,
jintArray
&
gids
,
jint
&
runtime_flags
,
jlong
&
permitted_capabilities
,
jlong
&
effective_capabilities
)
:
uid
(
uid
),
gid
(
gid
),
gids
(
gids
),
runtime_flags
(
runtime_flags
),
permitted_capabilities
(
permitted_capabilities
),
effective_capabilities
(
effective_capabilities
)
{}
};
template
<
typename
T
>
struct
force_cast_wrapper
{
template
<
typename
U
>
operator
U
()
const
{
return
reinterpret_cast
<
U
>
(
mX
);
}
force_cast_wrapper
(
T
&&
x
)
:
mX
(
std
::
forward
<
T
>
(
x
))
{}
force_cast_wrapper
&
operator
=
(
const
force_cast_wrapper
&
)
=
delete
;
private
:
T
&&
mX
;
};
template
<
typename
R
>
force_cast_wrapper
<
R
>
force_cast
(
R
&&
x
)
{
return
force_cast_wrapper
<
R
>
(
std
::
forward
<
R
>
(
x
));
}
struct
ZygiskModule
{
void
preAppSpecialize
(
AppSpecializeArgsImpl
*
args
)
{
v1
->
preAppSpecialize
(
v1
->
_this
,
force_cast
(
args
));
}
void
postAppSpecialize
(
const
AppSpecializeArgsImpl
*
args
)
{
v1
->
postAppSpecialize
(
v1
->
_this
,
force_cast
(
args
));
}
void
preServerSpecialize
(
ServerSpecializeArgsImpl
*
args
)
{
v1
->
preServerSpecialize
(
v1
->
_this
,
force_cast
(
args
));
}
void
postServerSpecialize
(
const
ServerSpecializeArgsImpl
*
args
)
{
v1
->
postServerSpecialize
(
v1
->
_this
,
force_cast
(
args
));
}
int
connectCompanion
();
static
void
forceDenyListUnmount
();
static
bool
registerModule
(
ApiTable
*
table
,
long
*
module
);
ZygiskModule
(
int
id
)
:
id
(
id
)
{}
private
:
int
id
;
union
{
long
*
ver
=
nullptr
;
module_abi_v1
*
v1
;
};
};
struct
ApiTable
{
ZygiskModule
*
module
;
bool
(
*
registerModule
)(
ApiTable
*
,
long
*
);
union
{
void
*
padding
[
6
]
=
{};
struct
{
void
(
*
hookJniNativeMethods
)(
JNIEnv
*
,
const
char
*
,
JNINativeMethod
*
,
int
);
void
(
*
pltHookRegister
)(
const
char
*
,
const
char
*
,
void
*
,
void
**
);
void
(
*
pltHookExclude
)(
const
char
*
,
const
char
*
);
bool
(
*
pltHookCommit
)();
int
(
*
connectCompanion
)(
ZygiskModule
*
);
void
(
*
forceDenyListUnmount
)(
ZygiskModule
*
);
}
v1
;
};
ApiTable
(
ZygiskModule
*
m
)
:
module
(
m
),
registerModule
(
&
ZygiskModule
::
registerModule
)
{}
};
}
// namespace
native/jni/zygisk/zygisk.hpp
View file @
c8ac6c07
...
@@ -2,13 +2,14 @@
...
@@ -2,13 +2,14 @@
#include <stdint.h>
#include <stdint.h>
#include <jni.h>
#include <jni.h>
#include <vector>
#define INJECT_ENV_1 "MAGISK_INJ_1"
#define INJECT_ENV_1 "MAGISK_INJ_1"
#define INJECT_ENV_2 "MAGISK_INJ_2"
#define INJECT_ENV_2 "MAGISK_INJ_2"
enum
:
int
{
enum
:
int
{
ZYGISK_SETUP
,
ZYGISK_SETUP
,
ZYGISK_GET_
APP
INFO
,
ZYGISK_GET_INFO
,
ZYGISK_UNMOUNT
,
ZYGISK_UNMOUNT
,
ZYGISK_GET_LOG_PIPE
,
ZYGISK_GET_LOG_PIPE
,
};
};
...
@@ -33,5 +34,5 @@ struct AppInfo {
...
@@ -33,5 +34,5 @@ struct AppInfo {
void
self_unload
();
void
self_unload
();
void
hook_functions
();
void
hook_functions
();
bool
unhook_functions
();
bool
unhook_functions
();
void
remote_get_app
_info
(
int
uid
,
const
char
*
process
,
AppInfo
*
info
);
std
::
vector
<
int
>
remote_get
_info
(
int
uid
,
const
char
*
process
,
AppInfo
*
info
);
int
remote_request_unmount
();
int
remote_request_unmount
();
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