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
44029875
Commit
44029875
authored
Sep 09, 2022
by
topjohnwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add new API exemptFd
parent
ccf21b09
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
102 additions
and
49 deletions
+102
-49
api.hpp
native/src/zygisk/api.hpp
+28
-17
hook.cpp
native/src/zygisk/hook.cpp
+66
-32
module.hpp
native/src/zygisk/module.hpp
+8
-0
No files found.
native/src/zygisk/api.hpp
View file @
44029875
...
@@ -23,7 +23,7 @@
...
@@ -23,7 +23,7 @@
#include <jni.h>
#include <jni.h>
#define ZYGISK_API_VERSION
3
#define ZYGISK_API_VERSION
4
/*
/*
...
@@ -73,12 +73,11 @@ struct ServerSpecializeArgs;
...
@@ -73,12 +73,11 @@ struct ServerSpecializeArgs;
class
ModuleBase
{
class
ModuleBase
{
public
:
public
:
// This function is called when the module is loaded into the target process.
// This method is called as soon as the module is loaded into the target process.
// A Zygisk API handle will be sent as an argument; call utility functions or interface
// A Zygisk API handle will be passed as an argument.
// with Zygisk through this handle.
virtual
void
onLoad
([[
maybe_unused
]]
Api
*
api
,
[[
maybe_unused
]]
JNIEnv
*
env
)
{}
virtual
void
onLoad
([[
maybe_unused
]]
Api
*
api
,
[[
maybe_unused
]]
JNIEnv
*
env
)
{}
// This
function
is called before the app process is specialized.
// This
method
is called before the app process is specialized.
// At this point, the process just got forked from zygote, but no app specific specialization
// At this point, the process just got forked from zygote, but no app specific specialization
// is applied. This means that the process does not have any sandbox restrictions and
// is applied. This means that the process does not have any sandbox restrictions and
// still runs with the same privilege of zygote.
// still runs with the same privilege of zygote.
...
@@ -92,16 +91,16 @@ public:
...
@@ -92,16 +91,16 @@ public:
// See Api::connectCompanion() for more info.
// See Api::connectCompanion() for more info.
virtual
void
preAppSpecialize
([[
maybe_unused
]]
AppSpecializeArgs
*
args
)
{}
virtual
void
preAppSpecialize
([[
maybe_unused
]]
AppSpecializeArgs
*
args
)
{}
// This
function
is called after the app process is specialized.
// This
method
is called after the app process is specialized.
// At this point, the process has all sandbox restrictions enabled for this application.
// At this point, the process has all sandbox restrictions enabled for this application.
// This means that this
function
runs as the same privilege of the app's own code.
// This means that this
method
runs as the same privilege of the app's own code.
virtual
void
postAppSpecialize
([[
maybe_unused
]]
const
AppSpecializeArgs
*
args
)
{}
virtual
void
postAppSpecialize
([[
maybe_unused
]]
const
AppSpecializeArgs
*
args
)
{}
// This
function
is called before the system server process is specialized.
// This
method
is called before the system server process is specialized.
// See preAppSpecialize(args) for more info.
// See preAppSpecialize(args) for more info.
virtual
void
preServerSpecialize
([[
maybe_unused
]]
ServerSpecializeArgs
*
args
)
{}
virtual
void
preServerSpecialize
([[
maybe_unused
]]
ServerSpecializeArgs
*
args
)
{}
// This
function
is called after the system server process is specialized.
// This
method
is called after the system server process is specialized.
// At this point, the process runs with the privilege of system_server.
// At this point, the process runs with the privilege of system_server.
virtual
void
postServerSpecialize
([[
maybe_unused
]]
const
ServerSpecializeArgs
*
args
)
{}
virtual
void
postServerSpecialize
([[
maybe_unused
]]
const
ServerSpecializeArgs
*
args
)
{}
};
};
...
@@ -173,21 +172,21 @@ enum StateFlag : uint32_t {
...
@@ -173,21 +172,21 @@ enum StateFlag : uint32_t {
PROCESS_ON_DENYLIST
=
(
1u
<<
1
),
PROCESS_ON_DENYLIST
=
(
1u
<<
1
),
};
};
// All API
function
s will stop working after post[XXX]Specialize as Zygisk will be unloaded
// All API
method
s will stop working after post[XXX]Specialize as Zygisk will be unloaded
// from the specialized process afterwards.
// from the specialized process afterwards.
struct
Api
{
struct
Api
{
// Connect to a root companion process and get a Unix domain socket for IPC.
// Connect to a root companion process and get a Unix domain socket for IPC.
//
//
// This API only works in the pre[XXX]Specialize
function
s due to SELinux restrictions.
// This API only works in the pre[XXX]Specialize
method
s due to SELinux restrictions.
//
//
// The pre[XXX]Specialize
function
s run with the same privilege of zygote.
// The pre[XXX]Specialize
method
s run with the same privilege of zygote.
// If you would like to do some operations with superuser permissions, register a handler
// If you would like to do some operations with superuser permissions, register a handler
// function that would be called in the root process with REGISTER_ZYGISK_COMPANION(func).
// function that would be called in the root process with REGISTER_ZYGISK_COMPANION(func).
// Another good use case for a companion process is that if you want to share some resources
// Another good use case for a companion process is that if you want to share some resources
// across multiple processes, hold the resources in the companion process and pass it over.
// across multiple processes, hold the resources in the companion process and pass it over.
//
//
// The root companion process is ABI aware; that is, when calling this
function
from a 32-bit
// The root companion process is ABI aware; that is, when calling this
method
from a 32-bit
// process, you will be connected to a 32-bit companion process, and vice versa for 64-bit.
// process, you will be connected to a 32-bit companion process, and vice versa for 64-bit.
//
//
// Returns a file descriptor to a socket that is connected to the socket passed to your
// Returns a file descriptor to a socket that is connected to the socket passed to your
...
@@ -196,8 +195,8 @@ struct Api {
...
@@ -196,8 +195,8 @@ struct Api {
// Get the file descriptor of the root folder of the current module.
// Get the file descriptor of the root folder of the current module.
//
//
// This API only works in the pre[XXX]Specialize
function
s.
// This API only works in the pre[XXX]Specialize
method
s.
// Accessing the directory returned is only possible in the pre[XXX]Specialize
function
s
// Accessing the directory returned is only possible in the pre[XXX]Specialize
method
s
// or in the root companion process (assuming that you sent the fd over the socket).
// or in the root companion process (assuming that you sent the fd over the socket).
// Both restrictions are due to SELinux and UID.
// Both restrictions are due to SELinux and UID.
//
//
...
@@ -205,7 +204,7 @@ struct Api {
...
@@ -205,7 +204,7 @@ struct Api {
int
getModuleDir
();
int
getModuleDir
();
// Set various options for your module.
// Set various options for your module.
// Please note that this
function
accepts one single option at a time.
// Please note that this
method
accepts one single option at a time.
// Check zygisk::Option for the full list of options available.
// Check zygisk::Option for the full list of options available.
void
setOption
(
Option
opt
);
void
setOption
(
Option
opt
);
...
@@ -213,9 +212,17 @@ struct Api {
...
@@ -213,9 +212,17 @@ struct Api {
// Returns bitwise-or'd zygisk::StateFlag values.
// Returns bitwise-or'd zygisk::StateFlag values.
uint32_t
getFlags
();
uint32_t
getFlags
();
// Exempt the provided file descriptor from being automatically closed.
//
// This API only make sense in preAppSpecialize; calling this method in any other situation
// is either a no-op (returns true) or an error (returns false).
//
// When false is returned, the provided file descriptor will eventually be closed by zygote.
bool
exemptFd
(
int
fd
);
// Hook JNI native methods for a class
// Hook JNI native methods for a class
//
//
// Lookup all registered JNI native methods and replace it with your own
function
s.
// Lookup all registered JNI native methods and replace it with your own
method
s.
// 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.
...
@@ -295,6 +302,7 @@ struct api_table {
...
@@ -295,6 +302,7 @@ struct api_table {
void
(
*
setOption
)(
void
*
/* impl */
,
Option
);
void
(
*
setOption
)(
void
*
/* impl */
,
Option
);
int
(
*
getModuleDir
)(
void
*
/* impl */
);
int
(
*
getModuleDir
)(
void
*
/* impl */
);
uint32_t
(
*
getFlags
)(
void
*
/* impl */
);
uint32_t
(
*
getFlags
)(
void
*
/* impl */
);
bool
(
*
exemptFd
)(
int
);
};
};
template
<
class
T
>
template
<
class
T
>
...
@@ -321,6 +329,9 @@ inline void Api::setOption(Option opt) {
...
@@ -321,6 +329,9 @@ inline void Api::setOption(Option opt) {
inline
uint32_t
Api
::
getFlags
()
{
inline
uint32_t
Api
::
getFlags
()
{
return
tbl
->
getFlags
?
tbl
->
getFlags
(
tbl
->
impl
)
:
0
;
return
tbl
->
getFlags
?
tbl
->
getFlags
(
tbl
->
impl
)
:
0
;
}
}
inline
bool
Api
::
exemptFd
(
int
fd
)
{
return
tbl
->
exemptFd
!=
nullptr
&&
tbl
->
exemptFd
(
fd
);
}
inline
void
Api
::
hookJniNativeMethods
(
JNIEnv
*
env
,
const
char
*
className
,
JNINativeMethod
*
methods
,
int
numMethods
)
{
inline
void
Api
::
hookJniNativeMethods
(
JNIEnv
*
env
,
const
char
*
className
,
JNINativeMethod
*
methods
,
int
numMethods
)
{
if
(
tbl
->
hookJniNativeMethods
)
tbl
->
hookJniNativeMethods
(
env
,
className
,
methods
,
numMethods
);
if
(
tbl
->
hookJniNativeMethods
)
tbl
->
hookJniNativeMethods
(
env
,
className
,
methods
,
numMethods
);
}
}
...
...
native/src/zygisk/hook.cpp
View file @
44029875
...
@@ -28,12 +28,13 @@ static bool unhook_functions();
...
@@ -28,12 +28,13 @@ static bool unhook_functions();
namespace
{
namespace
{
enum
{
enum
{
POST_SPECIALIZE
,
APP_FORK_AND_SPECIALIZE
,
APP_FORK_AND_SPECIALIZE
,
APP_SPECIALIZE
,
APP_SPECIALIZE
,
SERVER_FORK_AND_SPECIALIZE
,
SERVER_FORK_AND_SPECIALIZE
,
DO_REVERT_UNMOUNT
,
DO_REVERT_UNMOUNT
,
CAN_UNLOAD_ZYGISK
,
CAN_UNLOAD_ZYGISK
,
SKIP_
CLOSE_LOGD_FD
,
SKIP_
FD_SANITIZATION
,
FLAG_MAX
FLAG_MAX
};
};
...
@@ -59,10 +60,10 @@ struct HookContext {
...
@@ -59,10 +60,10 @@ struct HookContext {
bitset
<
FLAG_MAX
>
flags
;
bitset
<
FLAG_MAX
>
flags
;
uint32_t
info_flags
;
uint32_t
info_flags
;
bitset
<
MAX_FD_SIZE
>
allowed_fds
;
bitset
<
MAX_FD_SIZE
>
allowed_fds
;
vector
<
int
>
exempted_fds
;
HookContext
()
:
env
(
nullptr
),
args
{
nullptr
},
process
(
nullptr
),
pid
(
-
1
),
info_flags
(
0
)
{}
HookContext
()
:
env
(
nullptr
),
args
{
nullptr
},
process
(
nullptr
),
pid
(
-
1
),
info_flags
(
0
)
{}
void
sanitize_fds
();
void
run_modules_pre
(
const
vector
<
int
>
&
fds
);
void
run_modules_pre
(
const
vector
<
int
>
&
fds
);
void
run_modules_post
();
void
run_modules_post
();
DCL_PRE_POST
(
fork
)
DCL_PRE_POST
(
fork
)
...
@@ -72,6 +73,8 @@ struct HookContext {
...
@@ -72,6 +73,8 @@ struct HookContext {
DCL_PRE_POST
(
nativeForkSystemServer
)
DCL_PRE_POST
(
nativeForkSystemServer
)
void
unload_zygisk
();
void
unload_zygisk
();
void
sanitize_fds
();
bool
exempt_fd
(
int
fd
);
};
};
#undef DCL_PRE_POST
#undef DCL_PRE_POST
...
@@ -178,16 +181,17 @@ DCL_HOOK_FUNC(int, unshare, int flags) {
...
@@ -178,16 +181,17 @@ DCL_HOOK_FUNC(int, unshare, int flags) {
// Close logd_fd if necessary to prevent crashing
// Close logd_fd if necessary to prevent crashing
// For more info, check comments in zygisk_log_write
// For more info, check comments in zygisk_log_write
DCL_HOOK_FUNC
(
void
,
android_log_close
)
{
DCL_HOOK_FUNC
(
void
,
android_log_close
)
{
if
(
g_ctx
==
nullptr
||
g_ctx
->
pid
>
0
)
{
if
(
g_ctx
==
nullptr
)
{
//
This happens either in the zygote daemon or during nativeForkApp, nativeForkUsap etc.
//
Happens during un-managed fork like nativeForkApp, nativeForkUsap
close
(
logd_fd
.
exchange
(
-
1
));
close
(
logd_fd
.
exchange
(
-
1
));
// Do NOT revert back to android logging
}
else
if
(
!
g_ctx
->
flags
[
SKIP_FD_SANITIZATION
])
{
}
else
if
(
!
g_ctx
->
flags
[
SKIP_CLOSE_LOGD_FD
])
{
close
(
logd_fd
.
exchange
(
-
1
));
close
(
logd_fd
.
exchange
(
-
1
));
if
(
g_ctx
->
pid
<=
0
)
{
// Switch to plain old android logging because we cannot talk
// Switch to plain old android logging because we cannot talk
// to magiskd to fetch our log pipe afterwards anyways.
// to magiskd to fetch our log pipe afterwards anyways.
android_logging
();
android_logging
();
}
}
}
old_android_log_close
();
old_android_log_close
();
}
}
...
@@ -318,6 +322,11 @@ bool ZygiskModule::RegisterModuleImpl(api_abi_base *api, long *module) {
...
@@ -318,6 +322,11 @@ bool ZygiskModule::RegisterModuleImpl(api_abi_base *api, long *module) {
// Fill in API accordingly with module API version
// Fill in API accordingly with module API version
switch
(
api_version
)
{
switch
(
api_version
)
{
case
4
:
{
auto
v4
=
static_cast
<
api_abi_v4
*>
(
api
);
v4
->
exemptFd
=
[](
int
fd
)
{
return
g_ctx
!=
nullptr
&&
g_ctx
->
exempt_fd
(
fd
);
};
}
// fallthrough
case
3
:
case
3
:
case
2
:
{
case
2
:
{
auto
v2
=
static_cast
<
api_abi_v2
*>
(
api
);
auto
v2
=
static_cast
<
api_abi_v2
*>
(
api
);
...
@@ -401,7 +410,7 @@ void HookContext::fork_pre() {
...
@@ -401,7 +410,7 @@ void HookContext::fork_pre() {
// First block SIGCHLD, unblock after original fork is done
// First block SIGCHLD, unblock after original fork is done
sigmask
(
SIG_BLOCK
,
SIGCHLD
);
sigmask
(
SIG_BLOCK
,
SIGCHLD
);
pid
=
old_fork
();
pid
=
old_fork
();
if
(
pid
!=
0
)
if
(
pid
!=
0
||
flags
[
SKIP_FD_SANITIZATION
]
)
return
;
return
;
// Record all open fds
// Record all open fds
...
@@ -419,11 +428,30 @@ void HookContext::fork_pre() {
...
@@ -419,11 +428,30 @@ void HookContext::fork_pre() {
}
}
void
HookContext
::
sanitize_fds
()
{
void
HookContext
::
sanitize_fds
()
{
if
(
flags
[
SKIP_FD_SANITIZATION
])
return
;
if
(
flags
[
APP_FORK_AND_SPECIALIZE
])
{
if
(
flags
[
APP_FORK_AND_SPECIALIZE
])
{
if
(
args
.
app
->
fds_to_ignore
==
nullptr
)
{
auto
update_fd_array
=
[
&
](
int
off
)
->
jintArray
{
// The field fds_to_ignore don't exist before Android 8.0, which FDs are not checked
if
(
exempted_fds
.
empty
())
flags
[
SKIP_CLOSE_LOGD_FD
]
=
true
;
return
nullptr
;
}
else
if
(
jintArray
fdsToIgnore
=
*
args
.
app
->
fds_to_ignore
)
{
jintArray
array
=
env
->
NewIntArray
(
off
+
exempted_fds
.
size
());
if
(
array
==
nullptr
)
return
nullptr
;
env
->
SetIntArrayRegion
(
array
,
off
,
exempted_fds
.
size
(),
exempted_fds
.
data
());
for
(
int
fd
:
exempted_fds
)
{
if
(
fd
>=
0
&&
fd
<
MAX_FD_SIZE
)
{
allowed_fds
[
fd
]
=
true
;
}
}
*
args
.
app
->
fds_to_ignore
=
array
;
flags
[
SKIP_FD_SANITIZATION
]
=
true
;
return
array
;
};
if
(
jintArray
fdsToIgnore
=
*
args
.
app
->
fds_to_ignore
)
{
int
*
arr
=
env
->
GetIntArrayElements
(
fdsToIgnore
,
nullptr
);
int
*
arr
=
env
->
GetIntArrayElements
(
fdsToIgnore
,
nullptr
);
int
len
=
env
->
GetArrayLength
(
fdsToIgnore
);
int
len
=
env
->
GetArrayLength
(
fdsToIgnore
);
for
(
int
i
=
0
;
i
<
len
;
++
i
)
{
for
(
int
i
=
0
;
i
<
len
;
++
i
)
{
...
@@ -432,24 +460,12 @@ void HookContext::sanitize_fds() {
...
@@ -432,24 +460,12 @@ void HookContext::sanitize_fds() {
allowed_fds
[
fd
]
=
true
;
allowed_fds
[
fd
]
=
true
;
}
}
}
}
if
(
jintArray
newFdList
=
update_fd_array
(
len
))
{
jintArray
newFdList
=
nullptr
;
if
(
logd_fd
>=
0
&&
(
newFdList
=
env
->
NewIntArray
(
len
+
1
)))
{
env
->
SetIntArrayRegion
(
newFdList
,
0
,
len
,
arr
);
env
->
SetIntArrayRegion
(
newFdList
,
0
,
len
,
arr
);
int
fd
=
logd_fd
;
env
->
SetIntArrayRegion
(
newFdList
,
len
,
1
,
&
fd
);
*
args
.
app
->
fds_to_ignore
=
newFdList
;
flags
[
SKIP_CLOSE_LOGD_FD
]
=
true
;
}
}
env
->
ReleaseIntArrayElements
(
fdsToIgnore
,
arr
,
JNI_ABORT
);
env
->
ReleaseIntArrayElements
(
fdsToIgnore
,
arr
,
JNI_ABORT
);
}
else
{
}
else
{
jintArray
newFdList
=
nullptr
;
update_fd_array
(
0
);
if
(
logd_fd
>=
0
&&
(
newFdList
=
env
->
NewIntArray
(
1
)))
{
int
fd
=
logd_fd
;
env
->
SetIntArrayRegion
(
newFdList
,
0
,
1
,
&
fd
);
*
args
.
app
->
fds_to_ignore
=
newFdList
;
flags
[
SKIP_CLOSE_LOGD_FD
]
=
true
;
}
}
}
}
}
...
@@ -510,6 +526,7 @@ void HookContext::run_modules_pre(const vector<int> &fds) {
...
@@ -510,6 +526,7 @@ void HookContext::run_modules_pre(const vector<int> &fds) {
}
}
void
HookContext
::
run_modules_post
()
{
void
HookContext
::
run_modules_post
()
{
flags
[
POST_SPECIALIZE
]
=
true
;
for
(
const
auto
&
m
:
modules
)
{
for
(
const
auto
&
m
:
modules
)
{
if
(
flags
[
APP_SPECIALIZE
])
{
if
(
flags
[
APP_SPECIALIZE
])
{
m
.
postAppSpecialize
(
args
.
app
);
m
.
postAppSpecialize
(
args
.
app
);
...
@@ -564,14 +581,23 @@ void HookContext::unload_zygisk() {
...
@@ -564,14 +581,23 @@ void HookContext::unload_zygisk() {
}
}
}
}
bool
HookContext
::
exempt_fd
(
int
fd
)
{
if
(
flags
[
POST_SPECIALIZE
]
||
flags
[
SKIP_FD_SANITIZATION
])
return
true
;
if
(
!
flags
[
APP_FORK_AND_SPECIALIZE
])
return
false
;
exempted_fds
.
push_back
(
fd
);
return
true
;
}
// -----------------------------------------------------------------
// -----------------------------------------------------------------
void
HookContext
::
nativeSpecializeAppProcess_pre
()
{
void
HookContext
::
nativeSpecializeAppProcess_pre
()
{
g_ctx
=
this
;
// App specialize does not check FD
flags
[
SKIP_CLOSE_LOGD_FD
]
=
true
;
process
=
env
->
GetStringUTFChars
(
args
.
app
->
nice_name
,
nullptr
);
process
=
env
->
GetStringUTFChars
(
args
.
app
->
nice_name
,
nullptr
);
ZLOGV
(
"pre specialize [%s]
\n
"
,
process
);
ZLOGV
(
"pre specialize [%s]
\n
"
,
process
);
g_ctx
=
this
;
// App specialize does not check FD
flags
[
SKIP_FD_SANITIZATION
]
=
true
;
app_specialize_pre
();
app_specialize_pre
();
}
}
...
@@ -623,8 +649,16 @@ void HookContext::nativeForkSystemServer_post() {
...
@@ -623,8 +649,16 @@ void HookContext::nativeForkSystemServer_post() {
void
HookContext
::
nativeForkAndSpecialize_pre
()
{
void
HookContext
::
nativeForkAndSpecialize_pre
()
{
process
=
env
->
GetStringUTFChars
(
args
.
app
->
nice_name
,
nullptr
);
process
=
env
->
GetStringUTFChars
(
args
.
app
->
nice_name
,
nullptr
);
flags
[
APP_FORK_AND_SPECIALIZE
]
=
true
;
ZLOGV
(
"pre forkAndSpecialize [%s]
\n
"
,
process
);
ZLOGV
(
"pre forkAndSpecialize [%s]
\n
"
,
process
);
flags
[
APP_FORK_AND_SPECIALIZE
]
=
true
;
if
(
args
.
app
->
fds_to_ignore
==
nullptr
)
{
// The field fds_to_ignore don't exist before Android 8.0, which FDs are not checked
flags
[
SKIP_FD_SANITIZATION
]
=
true
;
}
else
if
(
logd_fd
>=
0
)
{
exempted_fds
.
push_back
(
logd_fd
);
}
fork_pre
();
fork_pre
();
if
(
pid
==
0
)
{
if
(
pid
==
0
)
{
app_specialize_pre
();
app_specialize_pre
();
...
...
native/src/zygisk/module.hpp
View file @
44029875
...
@@ -10,14 +10,17 @@ struct ZygiskModule;
...
@@ -10,14 +10,17 @@ struct ZygiskModule;
struct
AppSpecializeArgs_v1
;
struct
AppSpecializeArgs_v1
;
using
AppSpecializeArgs_v2
=
AppSpecializeArgs_v1
;
using
AppSpecializeArgs_v2
=
AppSpecializeArgs_v1
;
struct
AppSpecializeArgs_v3
;
struct
AppSpecializeArgs_v3
;
using
AppSpecializeArgs_v4
=
AppSpecializeArgs_v3
;
struct
module_abi_v1
;
struct
module_abi_v1
;
using
module_abi_v2
=
module_abi_v1
;
using
module_abi_v2
=
module_abi_v1
;
using
module_abi_v3
=
module_abi_v1
;
using
module_abi_v3
=
module_abi_v1
;
using
module_abi_v4
=
module_abi_v1
;
struct
api_abi_v1
;
struct
api_abi_v1
;
struct
api_abi_v2
;
struct
api_abi_v2
;
using
api_abi_v3
=
api_abi_v2
;
using
api_abi_v3
=
api_abi_v2
;
struct
api_abi_v4
;
struct
AppSpecializeArgs_v3
{
struct
AppSpecializeArgs_v3
{
jint
&
uid
;
jint
&
uid
;
...
@@ -132,6 +135,10 @@ struct api_abi_v2 : public api_abi_v1 {
...
@@ -132,6 +135,10 @@ struct api_abi_v2 : public api_abi_v1 {
uint32_t
(
*
getFlags
)(
ZygiskModule
*
);
uint32_t
(
*
getFlags
)(
ZygiskModule
*
);
};
};
struct
api_abi_v4
:
public
api_abi_v2
{
bool
(
*
exemptFd
)(
int
);
};
#define call_app(method) \
#define call_app(method) \
switch (*mod.api_version) { \
switch (*mod.api_version) { \
case 1: \
case 1: \
...
@@ -141,6 +148,7 @@ case 2: { \
...
@@ -141,6 +148,7 @@ case 2: { \
break; \
break; \
} \
} \
case 3: \
case 3: \
case 4: \
mod.v1->method(mod.v1->impl, args);\
mod.v1->method(mod.v1->impl, args);\
break; \
break; \
}
}
...
...
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