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
7999b66c
Commit
7999b66c
authored
Feb 12, 2022
by
LoveSy
Committed by
John Wu
Mar 01, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor daemon connection
parent
c82a46c1
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
301 additions
and
226 deletions
+301
-226
bootstages.cpp
native/jni/core/bootstages.cpp
+1
-0
daemon.cpp
native/jni/core/daemon.cpp
+88
-57
magisk.cpp
native/jni/core/magisk.cpp
+14
-22
daemon.hpp
native/jni/include/daemon.hpp
+17
-21
rootdir.cpp
native/jni/init/rootdir.cpp
+1
-1
su.cpp
native/jni/su/su.cpp
+1
-4
misc.hpp
native/jni/utils/misc.hpp
+31
-0
cli.cpp
native/jni/zygisk/deny/cli.cpp
+51
-44
deny.hpp
native/jni/zygisk/deny/deny.hpp
+34
-21
utils.cpp
native/jni/zygisk/deny/utils.cpp
+23
-23
entry.cpp
native/jni/zygisk/entry.cpp
+20
-14
hook.cpp
native/jni/zygisk/hook.cpp
+2
-6
main.cpp
native/jni/zygisk/main.cpp
+2
-7
zygisk.hpp
native/jni/zygisk/zygisk.hpp
+16
-6
No files found.
native/jni/core/bootstages.cpp
View file @
7999b66c
...
...
@@ -14,6 +14,7 @@
#include <selinux.hpp>
#include "core.hpp"
#include "zygisk/deny/deny.hpp"
using
namespace
std
;
...
...
native/jni/core/daemon.cpp
View file @
7999b66c
...
...
@@ -86,20 +86,20 @@ void clear_poll() {
static
void
poll_ctrl_handler
(
pollfd
*
pfd
)
{
int
code
=
read_int
(
pfd
->
fd
);
switch
(
code
)
{
case
POLL_CTRL_NEW
:
{
pollfd
new_fd
;
poll_callback
cb
;
xxread
(
pfd
->
fd
,
&
new_fd
,
sizeof
(
new_fd
));
xxread
(
pfd
->
fd
,
&
cb
,
sizeof
(
cb
));
register_poll
(
&
new_fd
,
cb
);
break
;
}
case
POLL_CTRL_RM
:
{
int
fd
=
read_int
(
pfd
->
fd
);
bool
auto_close
=
read_int
(
pfd
->
fd
);
unregister_poll
(
fd
,
auto_close
);
break
;
}
case
POLL_CTRL_NEW
:
{
pollfd
new_fd
;
poll_callback
cb
;
xxread
(
pfd
->
fd
,
&
new_fd
,
sizeof
(
new_fd
));
xxread
(
pfd
->
fd
,
&
cb
,
sizeof
(
cb
));
register_poll
(
&
new_fd
,
cb
);
break
;
}
case
POLL_CTRL_RM
:
{
int
fd
=
read_int
(
pfd
->
fd
);
bool
auto_close
=
read_int
(
pfd
->
fd
);
unregister_poll
(
fd
,
auto_close
);
break
;
}
}
}
...
...
@@ -133,61 +133,63 @@ static void poll_ctrl_handler(pollfd *pfd) {
}
}
static
void
handle_request_async
(
int
client
,
int
code
,
const
sock_cred
&
cred
)
{
static
void
handle_request_async
(
int
client
,
DaemonRequest
code
,
const
sock_cred
&
cred
)
{
// using enum DAEMON_REQUEST;
switch
(
code
)
{
case
DENYLIST
:
case
D
aemonRequest
:
:
D
ENYLIST
:
denylist_handler
(
client
,
&
cred
);
break
;
case
SUPERUSER
:
case
DaemonRequest
:
:
SUPERUSER
:
su_daemon_handler
(
client
,
&
cred
);
break
;
case
POST_FS_DATA
:
case
DaemonRequest
:
:
POST_FS_DATA
:
post_fs_data
(
client
);
break
;
case
LATE_START
:
case
DaemonRequest
:
:
LATE_START
:
late_start
(
client
);
break
;
case
BOOT_COMPLETE
:
case
DaemonRequest
:
:
BOOT_COMPLETE
:
boot_complete
(
client
);
break
;
case
SQLITE_CMD
:
case
DaemonRequest
:
:
SQLITE_CMD
:
exec_sql
(
client
);
break
;
case
REMOVE_MODULES
:
case
DaemonRequest
:
:
REMOVE_MODULES
:
remove_modules
();
write_int
(
client
,
0
);
close
(
client
);
reboot
();
break
;
case
ZYGISK_REQUEST
:
case
ZYGISK_PASSTHROUGH
:
case
DaemonRequest
:
:
ZYGISK_REQUEST
:
zygisk_handler
(
client
,
&
cred
);
break
;
default
:
close
(
client
);
break
;
__builtin_unreachable
();
}
}
static
void
handle_request_sync
(
int
client
,
int
code
)
{
static
void
handle_request_sync
(
int
client
,
DaemonRequest
code
)
{
// using enum DAEMON_REQUEST;
switch
(
code
)
{
case
CHECK_VERSION
:
case
DaemonRequest
:
:
CHECK_VERSION
:
write_string
(
client
,
MAGISK_VERSION
":MAGISK"
);
break
;
case
CHECK_VERSION_CODE
:
case
DaemonRequest
:
:
CHECK_VERSION_CODE
:
write_int
(
client
,
MAGISK_VER_CODE
);
break
;
case
GET_PATH
:
case
DaemonRequest
:
:
GET_PATH
:
write_string
(
client
,
MAGISKTMP
.
data
());
break
;
case
START_DAEMON
:
case
DaemonRequest
:
:
START_DAEMON
:
setup_logfile
(
true
);
break
;
case
STOP_DAEMON
:
case
DaemonRequest
:
:
STOP_DAEMON
:
denylist_handler
(
-
1
,
nullptr
);
write_int
(
client
,
0
);
// Terminate the daemon!
exit
(
0
);
default
:
__builtin_unreachable
();
}
}
...
...
@@ -195,11 +197,17 @@ static bool is_client(pid_t pid) {
// Verify caller is the same as server
char
path
[
32
];
sprintf
(
path
,
"/proc/%d/exe"
,
pid
);
struct
stat
st
;
struct
stat
st
{}
;
return
!
(
stat
(
path
,
&
st
)
||
st
.
st_dev
!=
self_st
.
st_dev
||
st
.
st_ino
!=
self_st
.
st_ino
);
}
inline
static
void
write_response
(
int
client
,
DaemonResponse
res
)
{
write_int
(
client
,
static_cast
<
std
::
underlying_type_t
<
DaemonResponse
>>
(
res
));
}
static
void
handle_request
(
pollfd
*
pfd
)
{
// using enum DAEMON_REQUEST;
// using enum DAEMON_RESPONSE;
int
client
=
xaccept4
(
pfd
->
fd
,
nullptr
,
nullptr
,
SOCK_CLOEXEC
);
// Verify client credentials
...
...
@@ -207,6 +215,7 @@ static void handle_request(pollfd *pfd) {
bool
is_root
;
bool
is_zygote
;
int
code
;
DaemonRequest
req
;
if
(
!
get_client_cred
(
client
,
&
cred
))
goto
done
;
...
...
@@ -217,44 +226,46 @@ static void handle_request(pollfd *pfd) {
goto
done
;
code
=
read_int
(
client
);
if
(
code
<
0
||
(
code
&
DAEMON_CODE_MASK
)
>=
DAEMON_CODE_END
)
static_assert
(
is_scoped_enum_v
<
DaemonRequest
>
);
if
(
code
<
0
||
code
>=
DaemonRequest
::
END
||
code
==
DaemonRequest
::
_SYNC_BARRIER_
)
goto
done
;
req
=
static_cast
<
DaemonRequest
>
(
code
);
// Check client permissions
switch
(
code
)
{
case
POST_FS_DATA
:
case
LATE_START
:
case
BOOT_COMPLETE
:
case
SQLITE_CMD
:
case
GET_PATH
:
case
DENYLIST
:
case
STOP_DAEMON
:
switch
(
req
)
{
case
DaemonRequest
:
:
POST_FS_DATA
:
case
DaemonRequest
:
:
LATE_START
:
case
DaemonRequest
:
:
BOOT_COMPLETE
:
case
DaemonRequest
:
:
SQLITE_CMD
:
case
DaemonRequest
:
:
GET_PATH
:
case
D
aemonRequest
:
:
D
ENYLIST
:
case
DaemonRequest
:
:
STOP_DAEMON
:
if
(
!
is_root
)
{
write_
int
(
client
,
ROOT_REQUIRED
);
write_
response
(
client
,
DaemonResponse
::
ROOT_REQUIRED
);
goto
done
;
}
break
;
case
REMOVE_MODULES
:
case
DaemonRequest
:
:
REMOVE_MODULES
:
if
(
!
is_root
&&
cred
.
uid
!=
UID_SHELL
)
{
write_
int
(
client
,
1
);
write_
response
(
client
,
DaemonResponse
::
ROOT_REQUIRED
);
goto
done
;
}
break
;
case
ZYGISK_REQUEST
:
if
(
!
is_zygote
)
{
write_int
(
client
,
DAEMON_ERROR
);
goto
done
;
}
default
:
break
;
}
if
(
code
&
SYNC_FLAG
)
{
handle_request_sync
(
client
,
code
);
write_response
(
client
,
DaemonResponse
::
OK
);
if
(
req
<
DaemonRequest
::
_SYNC_BARRIER_
)
{
handle_request_sync
(
client
,
req
);
goto
done
;
}
// Handle complex requests in another thread
exec_task
([
=
]
{
handle_request_async
(
client
,
code
,
cred
);
});
exec_task
([
=
]
{
handle_request_async
(
client
,
req
,
cred
);
});
return
;
done
:
...
...
@@ -376,7 +387,7 @@ static void daemon_entry() {
sockaddr_un
sun
{};
socklen_t
len
=
setup_sockaddr
(
&
sun
,
MAIN_SOCKET
);
fd
=
xsocket
(
AF_LOCAL
,
SOCK_STREAM
|
SOCK_CLOEXEC
,
0
);
if
(
xbind
(
fd
,
(
sockaddr
*
)
&
sun
,
len
))
if
(
xbind
(
fd
,
(
sockaddr
*
)
&
sun
,
len
))
exit
(
1
);
xlisten
(
fd
,
10
);
...
...
@@ -391,11 +402,12 @@ static void daemon_entry() {
poll_loop
();
}
int
connect_daemon
(
bool
create
)
{
int
connect_daemon
(
DaemonRequest
req
,
bool
create
)
{
// using enum DAEMON_RESPONSE;
sockaddr_un
sun
{};
socklen_t
len
=
setup_sockaddr
(
&
sun
,
MAIN_SOCKET
);
int
fd
=
xsocket
(
AF_UNIX
,
SOCK_STREAM
|
SOCK_CLOEXEC
,
0
);
if
(
connect
(
fd
,
(
sockaddr
*
)
&
sun
,
len
))
{
if
(
connect
(
fd
,
(
sockaddr
*
)
&
sun
,
len
))
{
if
(
!
create
||
getuid
()
!=
UID_ROOT
)
{
LOGE
(
"No daemon is currently running!
\n
"
);
close
(
fd
);
...
...
@@ -407,8 +419,27 @@ int connect_daemon(bool create) {
daemon_entry
();
}
while
(
connect
(
fd
,
(
struct
sockaddr
*
)
&
sun
,
len
))
while
(
connect
(
fd
,
(
struct
sockaddr
*
)
&
sun
,
len
))
usleep
(
10000
);
}
write_int
(
fd
,
static_cast
<
int
>
(
req
));
int
ret
=
read_int
(
fd
);
auto
res
=
(
ret
<
DaemonResponse
::
ERROR
||
ret
>=
DaemonResponse
::
END
)
?
DaemonResponse
::
ERROR
:
static_cast
<
DaemonResponse
>
(
ret
);
switch
(
res
)
{
case
DaemonResponse
:
:
OK
:
break
;
case
DaemonResponse
:
:
ERROR
:
LOGE
(
"Daemon error
\n
"
);
exit
(
-
1
);
case
DaemonResponse
:
:
ROOT_REQUIRED
:
LOGE
(
"Root is required for this operation
\n
"
);
exit
(
-
1
);
case
DaemonResponse
:
:
INVALID_REQUEST
:
LOGE
(
"Invalid request
\n
"
);
exit
(
-
1
);
case
DaemonResponse
:
:
END
:
__builtin_unreachable
();
}
return
fd
;
}
native/jni/core/magisk.cpp
View file @
7999b66c
...
...
@@ -50,20 +50,19 @@ Available applets:
}
int
magisk_main
(
int
argc
,
char
*
argv
[])
{
// using enum DAEMON_REQUEST;
if
(
argc
<
2
)
usage
();
if
(
argv
[
1
]
==
"-c"
sv
)
{
printf
(
MAGISK_VERSION
":MAGISK ("
str
(
MAGISK_VER_CODE
)
")
\n
"
);
return
0
;
}
else
if
(
argv
[
1
]
==
"-v"
sv
)
{
int
fd
=
connect_daemon
();
write_int
(
fd
,
CHECK_VERSION
);
int
fd
=
connect_daemon
(
DaemonRequest
::
CHECK_VERSION
);
string
v
=
read_string
(
fd
);
printf
(
"%s
\n
"
,
v
.
data
());
return
0
;
}
else
if
(
argv
[
1
]
==
"-V"
sv
)
{
int
fd
=
connect_daemon
();
write_int
(
fd
,
CHECK_VERSION_CODE
);
int
fd
=
connect_daemon
(
DaemonRequest
::
CHECK_VERSION_CODE
);
printf
(
"%d
\n
"
,
read_int
(
fd
));
return
0
;
}
else
if
(
argv
[
1
]
==
"--list"
sv
)
{
...
...
@@ -76,37 +75,32 @@ int magisk_main(int argc, char *argv[]) {
}
else
if
(
argv
[
1
]
==
"--restorecon"
sv
)
{
restorecon
();
return
0
;
}
else
if
(
argc
>=
4
&&
argv
[
1
]
==
"--clone-attr"
sv
)
{
;
}
else
if
(
argc
>=
4
&&
argv
[
1
]
==
"--clone-attr"
sv
)
{
clone_attr
(
argv
[
2
],
argv
[
3
]);
return
0
;
}
else
if
(
argc
>=
4
&&
argv
[
1
]
==
"--clone"
sv
)
{
cp_afc
(
argv
[
2
],
argv
[
3
]);
return
0
;
}
else
if
(
argv
[
1
]
==
"--daemon"
sv
)
{
int
fd
=
connect_daemon
(
true
);
write_int
(
fd
,
START_DAEMON
);
int
fd
=
connect_daemon
(
DaemonRequest
::
START_DAEMON
,
true
);
close
(
fd
);
return
0
;
}
else
if
(
argv
[
1
]
==
"--stop"
sv
)
{
int
fd
=
connect_daemon
();
write_int
(
fd
,
STOP_DAEMON
);
int
fd
=
connect_daemon
(
DaemonRequest
::
STOP_DAEMON
);
return
read_int
(
fd
);
}
else
if
(
argv
[
1
]
==
"--post-fs-data"
sv
)
{
int
fd
=
connect_daemon
(
true
);
write_int
(
fd
,
POST_FS_DATA
);
int
fd
=
connect_daemon
(
DaemonRequest
::
POST_FS_DATA
,
true
);
return
read_int
(
fd
);
}
else
if
(
argv
[
1
]
==
"--service"
sv
)
{
int
fd
=
connect_daemon
(
true
);
write_int
(
fd
,
LATE_START
);
int
fd
=
connect_daemon
(
DaemonRequest
::
LATE_START
,
true
);
return
read_int
(
fd
);
}
else
if
(
argv
[
1
]
==
"--boot-complete"
sv
)
{
int
fd
=
connect_daemon
(
true
);
write_int
(
fd
,
BOOT_COMPLETE
);
int
fd
=
connect_daemon
(
DaemonRequest
::
BOOT_COMPLETE
,
true
);
return
read_int
(
fd
);
}
else
if
(
argv
[
1
]
==
"--denylist"
sv
)
{
return
denylist_cli
(
argc
-
1
,
argv
+
1
);
}
else
if
(
argc
>=
3
&&
argv
[
1
]
==
"--sqlite"
sv
)
{
int
fd
=
connect_daemon
();
write_int
(
fd
,
SQLITE_CMD
);
}
else
if
(
argc
>=
3
&&
argv
[
1
]
==
"--sqlite"
sv
)
{
int
fd
=
connect_daemon
(
DaemonRequest
::
SQLITE_CMD
);
write_string
(
fd
,
argv
[
2
]);
string
res
;
for
(;;)
{
...
...
@@ -116,12 +110,10 @@ int magisk_main(int argc, char *argv[]) {
printf
(
"%s
\n
"
,
res
.
data
());
}
}
else
if
(
argv
[
1
]
==
"--remove-modules"
sv
)
{
int
fd
=
connect_daemon
();
write_int
(
fd
,
REMOVE_MODULES
);
int
fd
=
connect_daemon
(
DaemonRequest
::
REMOVE_MODULES
);
return
read_int
(
fd
);
}
else
if
(
argv
[
1
]
==
"--path"
sv
)
{
int
fd
=
connect_daemon
();
write_int
(
fd
,
GET_PATH
);
int
fd
=
connect_daemon
(
DaemonRequest
::
GET_PATH
);
string
path
=
read_string
(
fd
);
printf
(
"%s
\n
"
,
path
.
data
());
return
0
;
...
...
native/jni/include/daemon.hpp
View file @
7999b66c
...
...
@@ -9,20 +9,17 @@
#include <socket.hpp>
// Daemon command code flags/masks
enum
:
int
{
SYNC_FLAG
=
(
1
<<
30
),
DAEMON_CODE_MASK
=
std
::
numeric_limits
<
int
>::
max
()
>>
1
};
// Daemon command codes
enum
:
int
{
START_DAEMON
=
SYNC_FLAG
|
0
,
CHECK_VERSION
=
SYNC_FLAG
|
1
,
CHECK_VERSION_CODE
=
SYNC_FLAG
|
2
,
GET_PATH
=
SYNC_FLAG
|
3
,
STOP_DAEMON
=
SYNC_FLAG
|
4
,
SUPERUSER
=
5
,
enum
class
DaemonRequest
:
int
{
START_DAEMON
,
CHECK_VERSION
,
CHECK_VERSION_CODE
,
GET_PATH
,
STOP_DAEMON
,
_SYNC_BARRIER_
,
SUPERUSER
,
POST_FS_DATA
,
LATE_START
,
BOOT_COMPLETE
,
...
...
@@ -30,16 +27,16 @@ enum : int {
SQLITE_CMD
,
REMOVE_MODULES
,
ZYGISK_REQUEST
,
ZYGISK_PASSTHROUGH
,
DAEMON_CODE_END
,
END
,
};
// Return codes for daemon
enum
:
int
{
DAEMON_
ERROR
=
-
1
,
DAEMON_SUCCESS
=
0
,
enum
class
DaemonResponse
:
int
{
ERROR
=
-
1
,
OK
=
0
,
ROOT_REQUIRED
,
DAEMON_LAST
INVALID_REQUEST
,
END
};
struct
module_info
{
...
...
@@ -55,7 +52,7 @@ extern int app_process_32;
extern
int
app_process_64
;
extern
std
::
vector
<
module_info
>
*
module_list
;
int
connect_daemon
(
bool
create
=
false
);
int
connect_daemon
(
DaemonRequest
req
,
bool
create
=
false
);
// Poll control
using
poll_callback
=
void
(
*
)(
pollfd
*
);
...
...
@@ -81,5 +78,4 @@ void zygisk_handler(int client, const sock_cred *cred);
// Denylist
void
initialize_denylist
();
int
disable_deny
();
int
denylist_cli
(
int
argc
,
char
**
argv
);
native/jni/init/rootdir.cpp
View file @
7999b66c
...
...
@@ -240,7 +240,7 @@ void SARBase::patch_rootdir() {
make_pair
(
SPLIT_PLAT_CIL
,
"xxx"
),
/* Force loading monolithic sepolicy */
make_pair
(
MONOPOLICY
,
sepol
)
/* Redirect /sepolicy to custom path */
});
if
(
avd_hack
)
{
if
constexpr
(
avd_hack
)
{
// Force disable early mount on original init
init
.
patch
({
make_pair
(
"android,fstab"
,
"xxx"
)
});
}
...
...
native/jni/su/su.cpp
View file @
7999b66c
...
...
@@ -159,10 +159,7 @@ int su_client_main(int argc, char *argv[]) {
int
ptmx
,
fd
;
// Connect to client
fd
=
connect_daemon
();
// Tell the daemon we are su
write_int
(
fd
,
SUPERUSER
);
fd
=
connect_daemon
(
DaemonRequest
::
SUPERUSER
);
// Send su_request
xwrite
(
fd
,
&
su_req
,
sizeof
(
su_req_base
));
...
...
native/jni/utils/misc.hpp
View file @
7999b66c
...
...
@@ -5,6 +5,8 @@
#include <functional>
#include <string_view>
#include <bitset>
#include <compare>
#include "xwrap.hpp"
#define UID_ROOT 0
#define UID_SHELL 2000
...
...
@@ -197,3 +199,32 @@ void exec_command_async(Args &&...args) {
};
exec_command
(
exec
);
}
template
<
class
_Tp
,
bool
=
std
::
is_enum_v
<
_Tp
>
>
struct
__is_scoped_enum_helper
:
std
::
false_type
{};
template
<
class
_Tp
>
struct
__is_scoped_enum_helper
<
_Tp
,
true
>
:
public
std
::
bool_constant
<!
std
::
is_convertible_v
<
_Tp
,
std
::
underlying_type_t
<
_Tp
>
>
>
{};
template
<
class
_Tp
>
struct
is_scoped_enum
:
public
__is_scoped_enum_helper
<
_Tp
>
{};
template
<
class
_Tp
>
inline
constexpr
bool
is_scoped_enum_v
=
is_scoped_enum
<
_Tp
>::
value
;
template
<
typename
Enum
>
requires
(
is_scoped_enum_v
<
Enum
>
)
constexpr
inline
auto
operator
<=>
(
std
::
underlying_type_t
<
Enum
>
a
,
Enum
b
)
{
return
a
<=>
static_cast
<
std
::
underlying_type_t
<
Enum
>>
(
b
);
}
template
<
typename
Enum
>
requires
(
is_scoped_enum_v
<
Enum
>
)
constexpr
inline
auto
operator
!=
(
std
::
underlying_type_t
<
Enum
>
a
,
Enum
b
)
{
return
a
!=
static_cast
<
std
::
underlying_type_t
<
Enum
>>
(
b
);
}
template
<
typename
Enum
>
requires
(
is_scoped_enum_v
<
Enum
>
)
constexpr
inline
auto
operator
==
(
std
::
underlying_type_t
<
Enum
>
a
,
Enum
b
)
{
return
a
==
static_cast
<
std
::
underlying_type_t
<
Enum
>>
(
b
);
}
native/jni/zygisk/deny/cli.cpp
View file @
7999b66c
...
...
@@ -32,31 +32,40 @@ void denylist_handler(int client, const sock_cred *cred) {
return
;
}
int
req
=
read_int
(
client
);
int
res
=
DAEMON_ERROR
;
DenyResponse
res
=
DenyResponse
::
ERROR
;
int
code
=
read_int
(
client
);
auto
req
=
static_cast
<
DenyRequest
>
(
code
);
if
(
code
<
0
||
code
>=
DenyRequest
::
END
)
{
goto
done
;
}
switch
(
req
)
{
case
ENFORCE_DENY
:
case
DenyRequest
:
:
ENFORCE
:
res
=
enable_deny
();
break
;
case
D
ISABLE_DENY
:
case
D
enyRequest
:
:
DISABLE
:
res
=
disable_deny
();
break
;
case
ADD_LIST
:
case
DenyRequest
:
:
ADD
:
res
=
add_list
(
client
);
break
;
case
RM_LIST
:
case
DenyRequest
:
:
REMOVE
:
res
=
rm_list
(
client
);
break
;
case
LS_
LIST
:
case
DenyRequest
:
:
LIST
:
ls_list
(
client
);
return
;
case
DENY_STATUS
:
res
=
(
zygisk_enabled
&&
denylist_enforced
)
?
DENY_IS_ENFORCED
:
DENY_NOT_ENFORCED
;
case
DenyRequest
:
:
STATUS
:
res
=
(
zygisk_enabled
&&
denylist_enforced
)
?
DenyResponse
::
ENFORCED
:
DenyResponse
::
NOT_ENFORCED
;
break
;
case
DenyRequest
:
:
END
:
__builtin_unreachable
();
}
write_int
(
client
,
res
);
done
:
write_int
(
client
,
static_cast
<
int
>
(
res
)
);
close
(
client
);
}
...
...
@@ -64,19 +73,19 @@ int denylist_cli(int argc, char **argv) {
if
(
argc
<
2
)
usage
();
in
t
req
;
DenyReques
t
req
;
if
(
argv
[
1
]
==
"enable"
sv
)
req
=
ENFORCE_DENY
;
req
=
DenyRequest
::
ENFORCE
;
else
if
(
argv
[
1
]
==
"disable"
sv
)
req
=
D
ISABLE_DENY
;
req
=
D
enyRequest
::
DISABLE
;
else
if
(
argv
[
1
]
==
"add"
sv
)
req
=
ADD_LIST
;
req
=
DenyRequest
::
ADD
;
else
if
(
argv
[
1
]
==
"rm"
sv
)
req
=
RM_LIST
;
req
=
DenyRequest
::
REMOVE
;
else
if
(
argv
[
1
]
==
"ls"
sv
)
req
=
LS_
LIST
;
req
=
DenyRequest
::
LIST
;
else
if
(
argv
[
1
]
==
"status"
sv
)
req
=
D
ENY_
STATUS
;
req
=
D
enyRequest
::
STATUS
;
else
if
(
argv
[
1
]
==
"exec"
sv
&&
argc
>
2
)
{
xunshare
(
CLONE_NEWNS
);
xmount
(
nullptr
,
"/"
,
nullptr
,
MS_PRIVATE
|
MS_REC
,
nullptr
);
...
...
@@ -88,56 +97,54 @@ int denylist_cli(int argc, char **argv) {
}
// Send request
int
fd
=
connect_daemon
();
write_int
(
fd
,
DENYLIST
);
write_int
(
fd
,
req
);
if
(
req
==
ADD_LIST
||
req
==
RM_LIST
)
{
int
fd
=
deny_request
(
req
);
if
(
req
==
DenyRequest
::
ADD
||
req
==
DenyRequest
::
REMOVE
)
{
write_string
(
fd
,
argv
[
2
]);
write_string
(
fd
,
argv
[
3
]
?
argv
[
3
]
:
""
);
}
// Get response
int
code
=
read_int
(
fd
);
switch
(
code
)
{
case
DAEMON_SUCCESS
:
break
;
case
D
ENY_
NOT_ENFORCED
:
auto
res
=
(
code
<
0
||
code
>=
DenyResponse
::
END
)
?
DenyResponse
::
ERROR
:
static_cast
<
DenyResponse
>
(
code
);
switch
(
res
)
{
case
D
enyResponse
:
:
NOT_ENFORCED
:
fprintf
(
stderr
,
"Denylist is not enforced
\n
"
);
goto
return_code
;
case
D
ENY_IS_
ENFORCED
:
case
D
enyResponse
:
:
ENFORCED
:
fprintf
(
stderr
,
"Denylist is enforced
\n
"
);
goto
return_code
;
case
D
ENYLIST_
ITEM_EXIST
:
case
D
enyResponse
:
:
ITEM_EXIST
:
fprintf
(
stderr
,
"Target already exists in denylist
\n
"
);
goto
return_code
;
case
D
ENYLIST_
ITEM_NOT_EXIST
:
case
D
enyResponse
:
:
ITEM_NOT_EXIST
:
fprintf
(
stderr
,
"Target does not exist in denylist
\n
"
);
goto
return_code
;
case
D
ENY_
NO_NS
:
case
D
enyResponse
:
:
NO_NS
:
fprintf
(
stderr
,
"The kernel does not support mount namespace
\n
"
);
goto
return_code
;
case
D
ENYLIST_
INVALID_PKG
:
case
D
enyResponse
:
:
INVALID_PKG
:
fprintf
(
stderr
,
"Invalid package / process name
\n
"
);
goto
return_code
;
case
ROOT_REQUIRED
:
fprintf
(
stderr
,
"
Root is required for this operation
\n
"
);
goto
return_code
;
case
D
AEMON_ERROR
:
default
:
fprintf
(
stderr
,
"Daemon error
\n
"
);
return
DAEMON_ERROR
;
case
DenyResponse
:
:
ERROR
:
fprintf
(
stderr
,
"
deny: Daemon error
\n
"
);
return
-
1
;
case
D
enyResponse
:
:
OK
:
break
;
case
DenyResponse
:
:
END
:
__builtin_unreachable
()
;
}
if
(
req
==
LS_
LIST
)
{
string
res
;
if
(
req
==
DenyRequest
::
LIST
)
{
string
out
;
for
(;;)
{
read_string
(
fd
,
res
);
if
(
res
.
empty
())
read_string
(
fd
,
out
);
if
(
out
.
empty
())
break
;
printf
(
"%s
\n
"
,
res
.
data
());
printf
(
"%s
\n
"
,
out
.
data
());
}
}
return_code
:
return
req
==
D
ENY_STATUS
?
(
code
==
DENY_IS_ENFORCED
?
0
:
1
)
:
code
!=
DAEMON_SUCCESS
;
return
req
==
D
enyRequest
::
STATUS
?
res
!=
DenyResponse
::
ENFORCED
:
res
!=
DenyResponse
::
OK
;
}
native/jni/zygisk/deny/deny.hpp
View file @
7999b66c
...
...
@@ -10,11 +10,36 @@
#define ISOLATED_MAGIC "isolated"
enum
class
DenyRequest
:
int
{
ENFORCE
,
DISABLE
,
ADD
,
REMOVE
,
LIST
,
STATUS
,
END
};
enum
class
DenyResponse
:
int
{
OK
,
ENFORCED
,
NOT_ENFORCED
,
ITEM_EXIST
,
ITEM_NOT_EXIST
,
INVALID_PKG
,
NO_NS
,
ERROR
,
END
};
// CLI entries
int
enable_deny
();
int
disable_deny
();
int
add_list
(
int
client
);
int
rm_list
(
int
client
);
DenyResponse
enable_deny
();
DenyResponse
disable_deny
();
DenyResponse
add_list
(
int
client
);
DenyResponse
rm_list
(
int
client
);
void
ls_list
(
int
client
);
// Utility functions
...
...
@@ -25,20 +50,8 @@ void revert_unmount();
extern
std
::
atomic
<
bool
>
denylist_enforced
;
extern
std
::
atomic
<
int
>
cached_manager_app_id
;
enum
:
int
{
ENFORCE_DENY
,
DISABLE_DENY
,
ADD_LIST
,
RM_LIST
,
LS_LIST
,
DENY_STATUS
,
};
enum
:
int
{
DENY_IS_ENFORCED
=
DAEMON_LAST
+
1
,
DENY_NOT_ENFORCED
,
DENYLIST_ITEM_EXIST
,
DENYLIST_ITEM_NOT_EXIST
,
DENYLIST_INVALID_PKG
,
DENY_NO_NS
,
};
inline
int
deny_request
(
DenyRequest
req
)
{
int
fd
=
connect_daemon
(
DaemonRequest
::
DENYLIST
);
write_int
(
fd
,
static_cast
<
std
::
underlying_type_t
<
DenyRequest
>>
(
req
));
return
fd
;
}
native/jni/zygisk/deny/utils.cpp
View file @
7999b66c
...
...
@@ -226,20 +226,20 @@ error:
return
false
;
}
static
int
add_list
(
const
char
*
pkg
,
const
char
*
proc
)
{
static
DenyResponse
add_list
(
const
char
*
pkg
,
const
char
*
proc
)
{
if
(
proc
[
0
]
==
'\0'
)
proc
=
pkg
;
if
(
!
validate
(
pkg
,
proc
))
return
D
ENYLIST_
INVALID_PKG
;
return
D
enyResponse
::
INVALID_PKG
;
{
mutex_guard
lock
(
data_lock
);
if
(
!
ensure_data
())
return
D
AEMON_
ERROR
;
return
D
enyResponse
::
ERROR
;
auto
p
=
add_hide_set
(
pkg
,
proc
);
if
(
!
p
.
second
)
return
D
ENYLIST_
ITEM_EXIST
;
return
D
enyResponse
::
ITEM_EXIST
;
update_pkg_uid
(
*
p
.
first
,
false
);
}
...
...
@@ -248,21 +248,21 @@ static int add_list(const char *pkg, const char *proc) {
snprintf
(
sql
,
sizeof
(
sql
),
"INSERT INTO denylist (package_name, process) VALUES('%s', '%s')"
,
pkg
,
proc
);
char
*
err
=
db_exec
(
sql
);
db_err_cmd
(
err
,
return
D
AEMON_
ERROR
)
return
D
AEMON_SUCCESS
;
db_err_cmd
(
err
,
return
D
enyResponse
::
ERROR
)
return
D
enyResponse
::
OK
;
}
int
add_list
(
int
client
)
{
DenyResponse
add_list
(
int
client
)
{
string
pkg
=
read_string
(
client
);
string
proc
=
read_string
(
client
);
return
add_list
(
pkg
.
data
(),
proc
.
data
());
}
static
int
rm_list
(
const
char
*
pkg
,
const
char
*
proc
)
{
static
DenyResponse
rm_list
(
const
char
*
pkg
,
const
char
*
proc
)
{
{
mutex_guard
lock
(
data_lock
);
if
(
!
ensure_data
())
return
D
AEMON_
ERROR
;
return
D
enyResponse
::
ERROR
;
bool
remove
=
false
;
...
...
@@ -284,7 +284,7 @@ static int rm_list(const char *pkg, const char *proc) {
}
if
(
!
remove
)
return
D
ENYLIST_
ITEM_NOT_EXIST
;
return
D
enyResponse
::
ITEM_NOT_EXIST
;
}
char
sql
[
4096
];
...
...
@@ -294,11 +294,11 @@ static int rm_list(const char *pkg, const char *proc) {
snprintf
(
sql
,
sizeof
(
sql
),
"DELETE FROM denylist WHERE package_name='%s' AND process='%s'"
,
pkg
,
proc
);
char
*
err
=
db_exec
(
sql
);
db_err_cmd
(
err
,
return
D
AEMON_
ERROR
)
return
D
AEMON_SUCCESS
;
db_err_cmd
(
err
,
return
D
enyResponse
::
ERROR
)
return
D
enyResponse
::
OK
;
}
int
rm_list
(
int
client
)
{
DenyResponse
rm_list
(
int
client
)
{
string
pkg
=
read_string
(
client
);
string
proc
=
read_string
(
client
);
return
rm_list
(
pkg
.
data
(),
proc
.
data
());
...
...
@@ -308,11 +308,11 @@ void ls_list(int client) {
{
mutex_guard
lock
(
data_lock
);
if
(
!
ensure_data
())
{
write_int
(
client
,
DAEMON_ERROR
);
write_int
(
client
,
static_cast
<
int
>
(
DenyResponse
::
ERROR
)
);
return
;
}
write_int
(
client
,
DAEMON_SUCCESS
);
write_int
(
client
,
static_cast
<
int
>
(
DenyResponse
::
OK
)
);
for
(
const
auto
&
[
pkg
,
procs
]
:
pkg_to_procs
)
{
for
(
const
auto
&
proc
:
procs
)
{
...
...
@@ -342,19 +342,19 @@ static void update_deny_config() {
db_err
(
err
);
}
int
enable_deny
()
{
DenyResponse
enable_deny
()
{
if
(
denylist_enforced
)
{
return
D
AEMON_SUCCESS
;
return
D
enyResponse
::
OK
;
}
else
{
mutex_guard
lock
(
data_lock
);
if
(
access
(
"/proc/self/ns/mnt"
,
F_OK
)
!=
0
)
{
LOGW
(
"The kernel does not support mount namespace
\n
"
);
return
D
ENY_
NO_NS
;
return
D
enyResponse
::
NO_NS
;
}
if
(
procfp
==
nullptr
&&
(
procfp
=
opendir
(
"/proc"
))
==
nullptr
)
return
D
AEMON_
ERROR
;
return
D
enyResponse
::
ERROR
;
LOGI
(
"* Enable DenyList
\n
"
);
...
...
@@ -362,7 +362,7 @@ int enable_deny() {
if
(
!
ensure_data
())
{
denylist_enforced
=
false
;
return
D
AEMON_
ERROR
;
return
D
enyResponse
::
ERROR
;
}
// On Android Q+, also kill blastula pool and all app zygotes
...
...
@@ -374,16 +374,16 @@ int enable_deny() {
}
update_deny_config
();
return
D
AEMON_SUCCESS
;
return
D
enyResponse
::
OK
;
}
int
disable_deny
()
{
DenyResponse
disable_deny
()
{
if
(
denylist_enforced
)
{
denylist_enforced
=
false
;
LOGI
(
"* Disable DenyList
\n
"
);
}
update_deny_config
();
return
D
AEMON_SUCCESS
;
return
D
enyResponse
::
OK
;
}
void
initialize_denylist
()
{
...
...
native/jni/zygisk/entry.cpp
View file @
7999b66c
...
...
@@ -142,9 +142,7 @@ static int zygisk_log(int prio, const char *fmt, va_list ap) {
if
(
logd_fd
<
0
)
{
// Change logging temporarily to prevent infinite recursion and stack overflow
android_logging
();
if
(
int
fd
=
connect_daemon
();
fd
>=
0
)
{
write_int
(
fd
,
ZYGISK_REQUEST
);
write_int
(
fd
,
ZYGISK_GET_LOG_PIPE
);
if
(
int
fd
=
zygisk_request
(
ZygiskRequest
::
GET_LOG_PIPE
);
fd
>=
0
)
{
if
(
read_int
(
fd
)
==
0
)
{
logd_fd
=
recv_fd
(
fd
);
}
...
...
@@ -178,10 +176,7 @@ static inline bool should_load_modules(uint32_t flags) {
}
int
remote_get_info
(
int
uid
,
const
char
*
process
,
uint32_t
*
flags
,
vector
<
int
>
&
fds
)
{
if
(
int
fd
=
connect_daemon
();
fd
>=
0
)
{
write_int
(
fd
,
ZYGISK_REQUEST
);
write_int
(
fd
,
ZYGISK_GET_INFO
);
if
(
int
fd
=
zygisk_request
(
ZygiskRequest
::
GET_INFO
);
fd
>=
0
)
{
write_int
(
fd
,
uid
);
write_string
(
fd
,
process
);
xxread
(
fd
,
flags
,
sizeof
(
*
flags
));
...
...
@@ -404,28 +399,39 @@ static void get_moddir(int client) {
}
void
zygisk_handler
(
int
client
,
const
sock_cred
*
cred
)
{
// using enum ZYGISK_REQUEST;
int
code
=
read_int
(
client
);
char
buf
[
256
];
switch
(
code
)
{
case
ZYGISK_SETUP
:
if
(
code
<
ZygiskRequest
::
SETUP
||
code
>=
ZygiskRequest
::
END
)
{
write_int
(
client
,
-
1
);
return
;
}
auto
req
=
static_cast
<
ZygiskRequest
>
(
code
);
if
(
req
!=
ZygiskRequest
::
PASSTHROUGH
&&
cred
->
context
!=
"u:r:zygote:s0"
)
{
return
;
}
switch
(
req
)
{
case
ZygiskRequest
:
:
SETUP
:
setup_files
(
client
,
cred
);
break
;
case
Z
YGISK_
PASSTHROUGH
:
case
Z
ygiskRequest
:
:
PASSTHROUGH
:
magiskd_passthrough
(
client
);
break
;
case
Z
YGISK_
GET_INFO
:
case
Z
ygiskRequest
:
:
GET_INFO
:
get_process_info
(
client
,
cred
);
break
;
case
Z
YGISK_
GET_LOG_PIPE
:
case
Z
ygiskRequest
:
:
GET_LOG_PIPE
:
send_log_pipe
(
client
);
break
;
case
Z
YGISK_
CONNECT_COMPANION
:
case
Z
ygiskRequest
:
:
CONNECT_COMPANION
:
get_exe
(
cred
->
pid
,
buf
,
sizeof
(
buf
));
connect_companion
(
client
,
str_ends
(
buf
,
"64"
));
break
;
case
Z
YGISK_
GET_MODDIR
:
case
Z
ygiskRequest
:
:
GET_MODDIR
:
get_moddir
(
client
);
break
;
case
ZygiskRequest
:
:
END
:
__builtin_unreachable
();
}
close
(
client
);
}
native/jni/zygisk/hook.cpp
View file @
7999b66c
...
...
@@ -317,9 +317,7 @@ bool ZygiskModule::RegisterModule(ApiTable *table, long *module) {
}
int
ZygiskModule
::
connectCompanion
()
const
{
if
(
int
fd
=
connect_daemon
();
fd
>=
0
)
{
write_int
(
fd
,
ZYGISK_REQUEST
);
write_int
(
fd
,
ZYGISK_CONNECT_COMPANION
);
if
(
int
fd
=
zygisk_request
(
ZygiskRequest
::
CONNECT_COMPANION
);
fd
>=
0
)
{
write_int
(
fd
,
id
);
return
fd
;
}
...
...
@@ -327,9 +325,7 @@ int ZygiskModule::connectCompanion() const {
}
int
ZygiskModule
::
getModuleDir
()
const
{
if
(
int
fd
=
connect_daemon
();
fd
>=
0
)
{
write_int
(
fd
,
ZYGISK_REQUEST
);
write_int
(
fd
,
ZYGISK_GET_MODDIR
);
if
(
int
fd
=
zygisk_request
(
ZygiskRequest
::
GET_MODDIR
);
fd
>=
0
)
{
write_int
(
fd
,
id
);
int
dfd
=
recv_fd
(
fd
);
close
(
fd
);
...
...
native/jni/zygisk/main.cpp
View file @
7999b66c
...
...
@@ -57,11 +57,8 @@ int app_process_main(int argc, char *argv[]) {
return
1
;
}
if
(
int
socket
=
connect_daemon
(
);
socket
>=
0
)
{
if
(
int
socket
=
zygisk_request
(
ZygiskRequest
::
SETUP
);
socket
>=
0
)
{
do
{
write_int
(
socket
,
ZYGISK_REQUEST
);
write_int
(
socket
,
ZYGISK_SETUP
);
if
(
read_int
(
socket
)
!=
0
)
break
;
...
...
@@ -176,9 +173,7 @@ int zygisk_main(int argc, char *argv[]) {
int
is_64_bit
=
parse_int
(
argv
[
3
]);
if
(
fcntl
(
client
,
F_GETFD
)
<
0
)
return
1
;
if
(
int
magiskd
=
connect_daemon
();
magiskd
>=
0
)
{
write_int
(
magiskd
,
ZYGISK_PASSTHROUGH
);
write_int
(
magiskd
,
ZYGISK_PASSTHROUGH
);
if
(
int
magiskd
=
zygisk_request
(
ZygiskRequest
::
PASSTHROUGH
);
magiskd
>=
0
)
{
write_int
(
magiskd
,
is_64_bit
);
if
(
read_int
(
magiskd
)
!=
0
)
{
...
...
native/jni/zygisk/zygisk.hpp
View file @
7999b66c
...
...
@@ -3,18 +3,21 @@
#include <stdint.h>
#include <jni.h>
#include <vector>
#include <daemon.hpp>
#define INJECT_ENV_1 "MAGISK_INJ_1"
#define INJECT_ENV_2 "MAGISK_INJ_2"
#define MAGISKFD_ENV "MAGISKFD"
#define MAGISKTMP_ENV "MAGISKTMP"
enum
:
int
{
ZYGISK_SETUP
,
ZYGISK_GET_INFO
,
ZYGISK_GET_LOG_PIPE
,
ZYGISK_CONNECT_COMPANION
,
ZYGISK_GET_MODDIR
,
enum
class
ZygiskRequest
:
int
{
SETUP
,
GET_INFO
,
GET_LOG_PIPE
,
CONNECT_COMPANION
,
GET_MODDIR
,
PASSTHROUGH
,
END
};
#if defined(__LP64__)
...
...
@@ -47,3 +50,10 @@ extern void *self_handle;
void
hook_functions
();
int
remote_get_info
(
int
uid
,
const
char
*
process
,
uint32_t
*
flags
,
std
::
vector
<
int
>
&
fds
);
int
remote_request_unmount
();
inline
int
zygisk_request
(
ZygiskRequest
req
)
{
int
fd
=
connect_daemon
(
DaemonRequest
::
ZYGISK_REQUEST
,
false
);
write_int
(
fd
,
static_cast
<
int
>
(
req
));
return
fd
;
}
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