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
40b6de59
Commit
40b6de59
authored
Jul 16, 2017
by
topjohnwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Prevent client error
parent
09392be0
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
51 additions
and
32 deletions
+51
-32
su.h
su.h
+9
-4
su_daemon.c
su_daemon.c
+42
-28
No files found.
su.h
View file @
40b6de59
...
@@ -59,15 +59,20 @@ typedef enum {
...
@@ -59,15 +59,20 @@ typedef enum {
}
policy_t
;
}
policy_t
;
struct
su_info
{
struct
su_info
{
unsigned
uid
;
unsigned
uid
;
/* Key to find su_info */
pthread_mutex_t
lock
;
/* Internal lock */
int
count
;
/* Just a count for debugging purpose */
/* These values should be guarded with internal lock */
policy_t
policy
;
policy_t
policy
;
pthread_mutex_t
lock
;
int
count
;
int
clock
;
int
multiuser_mode
;
int
multiuser_mode
;
int
root_access
;
int
root_access
;
int
mnt_ns
;
int
mnt_ns
;
/* These should be guarded with global list lock */
struct
list_head
pos
;
struct
list_head
pos
;
int
ref
;
int
clock
;
};
};
struct
su_request
{
struct
su_request
{
...
...
su_daemon.c
View file @
40b6de59
...
@@ -30,6 +30,11 @@
...
@@ -30,6 +30,11 @@
#define TIMEOUT 3
#define TIMEOUT 3
#define LOCK_LIST() pthread_mutex_lock(&list_lock)
#define LOCK_UID() pthread_mutex_lock(&info->lock)
#define UNLOCK_LIST() pthread_mutex_unlock(&list_lock)
#define UNLOCK_UID() pthread_mutex_unlock(&info->lock)
static
struct
list_head
active_list
,
waiting_list
;
static
struct
list_head
active_list
,
waiting_list
;
static
pthread_t
su_collector
=
0
;
static
pthread_t
su_collector
=
0
;
static
pthread_mutex_t
list_lock
=
PTHREAD_MUTEX_INITIALIZER
;
static
pthread_mutex_t
list_lock
=
PTHREAD_MUTEX_INITIALIZER
;
...
@@ -59,17 +64,13 @@ static void sighandler(int sig) {
...
@@ -59,17 +64,13 @@ static void sighandler(int sig) {
}
}
}
}
static
void
sigpipe_handler
(
int
sig
)
{
LOGD
(
"su: Client killed unexpectedly
\n
"
);
}
// Maintain the lists periodically
// Maintain the lists periodically
static
void
*
collector
(
void
*
args
)
{
static
void
*
collector
(
void
*
args
)
{
LOGD
(
"su: collector started
\n
"
);
LOGD
(
"su: collector started
\n
"
);
struct
su_info
*
node
;
struct
su_info
*
node
;
while
(
1
)
{
while
(
1
)
{
sleep
(
1
);
sleep
(
1
);
pthread_mutex_lock
(
&
list_lock
);
LOCK_LIST
(
);
list_for_each
(
node
,
&
active_list
,
struct
su_info
,
pos
)
{
list_for_each
(
node
,
&
active_list
,
struct
su_info
,
pos
)
{
if
(
--
node
->
clock
==
0
)
{
if
(
--
node
->
clock
==
0
)
{
// Timeout, move to waiting list
// Timeout, move to waiting list
...
@@ -78,14 +79,14 @@ static void *collector(void *args) {
...
@@ -78,14 +79,14 @@ static void *collector(void *args) {
}
}
}
}
list_for_each
(
node
,
&
waiting_list
,
struct
su_info
,
pos
)
{
list_for_each
(
node
,
&
waiting_list
,
struct
su_info
,
pos
)
{
if
(
node
->
count
==
0
)
{
if
(
node
->
ref
==
0
)
{
// Nothing is using the info, remove it
// Nothing is using the info, remove it
__
=
list_pop
(
&
node
->
pos
);
__
=
list_pop
(
&
node
->
pos
);
pthread_mutex_destroy
(
&
node
->
lock
);
pthread_mutex_destroy
(
&
node
->
lock
);
free
(
node
);
free
(
node
);
}
}
}
}
pthread_mutex_unlock
(
&
list_lock
);
UNLOCK_LIST
(
);
}
}
}
}
...
@@ -95,7 +96,7 @@ void su_daemon_receiver(int client) {
...
@@ -95,7 +96,7 @@ void su_daemon_receiver(int client) {
struct
su_info
*
info
=
NULL
,
*
node
;
struct
su_info
*
info
=
NULL
,
*
node
;
int
new_request
=
0
;
int
new_request
=
0
;
pthread_mutex_lock
(
&
list_lock
);
LOCK_LIST
(
);
if
(
!
su_collector
)
{
if
(
!
su_collector
)
{
init_list_head
(
&
active_list
);
init_list_head
(
&
active_list
);
...
@@ -109,8 +110,10 @@ void su_daemon_receiver(int client) {
...
@@ -109,8 +110,10 @@ void su_daemon_receiver(int client) {
// Search for existing in the active list
// Search for existing in the active list
list_for_each
(
node
,
&
active_list
,
struct
su_info
,
pos
)
{
list_for_each
(
node
,
&
active_list
,
struct
su_info
,
pos
)
{
if
(
node
->
uid
==
credential
.
uid
)
if
(
node
->
uid
==
credential
.
uid
)
{
info
=
node
;
info
=
node
;
break
;
}
}
}
// If no exist, create a new request
// If no exist, create a new request
...
@@ -119,19 +122,17 @@ void su_daemon_receiver(int client) {
...
@@ -119,19 +122,17 @@ void su_daemon_receiver(int client) {
info
=
malloc
(
sizeof
(
*
info
));
info
=
malloc
(
sizeof
(
*
info
));
info
->
uid
=
credential
.
uid
;
info
->
uid
=
credential
.
uid
;
info
->
policy
=
QUERY
;
info
->
policy
=
QUERY
;
info
->
ref
=
0
;
info
->
count
=
0
;
info
->
count
=
0
;
pthread_mutex_init
(
&
info
->
lock
,
NULL
);
pthread_mutex_init
(
&
info
->
lock
,
NULL
);
list_insert_end
(
&
active_list
,
&
info
->
pos
);
list_insert_end
(
&
active_list
,
&
info
->
pos
);
}
}
info
->
clock
=
TIMEOUT
;
/* Reset timer */
info
->
clock
=
TIMEOUT
;
/* Reset timer */
++
info
->
count
;
/* Increment reference count */
++
info
->
ref
;
/* Increment reference count */
pthread_mutex_unlock
(
&
list_lock
);
UNLOCK_LIST
(
);
LOGD
(
"su: request from uid=[%d] (#%d)
\n
"
,
info
->
uid
,
info
->
count
);
LOGD
(
"su: request from uid=[%d] (#%d)
\n
"
,
info
->
uid
,
++
info
->
count
);
// Lock before the policy is determined
pthread_mutex_lock
(
&
info
->
lock
);
// Default values
// Default values
struct
su_context
ctx
=
{
struct
su_context
ctx
=
{
...
@@ -165,6 +166,9 @@ void su_daemon_receiver(int client) {
...
@@ -165,6 +166,9 @@ void su_daemon_receiver(int client) {
info
->
policy
=
DENY
;
info
->
policy
=
DENY
;
}
}
// Lock before the policy is determined
LOCK_UID
();
// Not cached, do the checks
// Not cached, do the checks
if
(
info
->
policy
==
QUERY
)
{
if
(
info
->
policy
==
QUERY
)
{
// Get data from database
// Get data from database
...
@@ -193,7 +197,7 @@ void su_daemon_receiver(int client) {
...
@@ -193,7 +197,7 @@ void su_daemon_receiver(int client) {
// If still not determined, open a pipe and wait for results
// If still not determined, open a pipe and wait for results
if
(
info
->
policy
==
QUERY
)
if
(
info
->
policy
==
QUERY
)
pipe2
(
pipefd
,
O_CLOEXEC
);
x
pipe2
(
pipefd
,
O_CLOEXEC
);
}
}
// Fork a new process, the child process will need to setsid,
// Fork a new process, the child process will need to setsid,
...
@@ -213,35 +217,45 @@ void su_daemon_receiver(int client) {
...
@@ -213,35 +217,45 @@ void su_daemon_receiver(int client) {
}
}
// The policy is determined, unlock
// The policy is determined, unlock
pthread_mutex_unlock
(
&
info
->
lock
);
UNLOCK_UID
(
);
// Wait result
// Wait result
LOGD
(
"su: wait
_result waiting for %d
\n
"
,
child
);
LOGD
(
"su: wait
ing child: [%d]
\n
"
,
child
);
int
status
,
code
;
int
status
,
code
;
// Handle SIGPIPE, since we don't want to crash our daemon
struct
sigaction
act
;
memset
(
&
act
,
0
,
sizeof
(
act
));
act
.
sa_handler
=
sigpipe_handler
;
sigaction
(
SIGPIPE
,
&
act
,
NULL
);
if
(
waitpid
(
child
,
&
status
,
0
)
>
0
)
if
(
waitpid
(
child
,
&
status
,
0
)
>
0
)
code
=
WEXITSTATUS
(
status
);
code
=
WEXITSTATUS
(
status
);
else
else
code
=
-
1
;
code
=
-
1
;
// Pass the return code back to the client
/* Passing the return code back to the client:
write
(
client
,
&
code
,
sizeof
(
code
));
/* Might SIGPIPE, ignored */
* The client might be closed unexpectedly (e.g. swipe a root app out of recents)
LOGD
(
"su: return code to client: %d
\n
"
,
code
);
* In that case, writing to the client (which doesn't exist) will result in SIGPIPE
* Here we simply just ignore the situation.
*/
struct
sigaction
act
;
memset
(
&
act
,
0
,
sizeof
(
act
));
act
.
sa_handler
=
SIG_IGN
;
sigaction
(
SIGPIPE
,
&
act
,
NULL
);
LOGD
(
"su: return code: [%d]
\n
"
,
code
);
write
(
client
,
&
code
,
sizeof
(
code
));
close
(
client
);
close
(
client
);
// Restore default handler for SIGPIPE
act
.
sa_handler
=
SIG_DFL
;
sigaction
(
SIGPIPE
,
&
act
,
NULL
);
// Decrement reference count
// Decrement reference count
--
info
->
count
;
LOCK_LIST
();
--
info
->
ref
;
UNLOCK_LIST
();
return
;
return
;
}
}
LOGD
(
"su: child process started
\n
"
);
LOGD
(
"su: child process started
\n
"
);
UNLOCK_UID
();
// ack
// ack
write_int
(
client
,
1
);
write_int
(
client
,
1
);
...
...
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