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
1ddd7468
Commit
1ddd7468
authored
May 31, 2017
by
topjohnwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Switch to DB based su config
parent
48ace3de
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
93 additions
and
80 deletions
+93
-80
activity.c
activity.c
+2
-2
db.c
db.c
+52
-20
su.c
su.c
+19
-27
su.h
su.h
+7
-7
su_daemon.c
su_daemon.c
+13
-24
No files found.
activity.c
View file @
1ddd7468
...
...
@@ -40,7 +40,7 @@ static void silent_run(char* const args[]) {
}
static
int
setup_user
(
struct
su_context
*
ctx
,
char
*
user
)
{
switch
(
ctx
->
user
.
multiuser_mode
)
{
switch
(
ctx
->
info
->
multiuser_mode
)
{
case
MULTIUSER_MODE_OWNER_ONLY
:
/* Should already be denied if not owner */
case
MULTIUSER_MODE_OWNER_MANAGED
:
sprintf
(
user
,
"%d"
,
0
);
...
...
@@ -60,7 +60,7 @@ void app_send_result(struct su_context *ctx, policy_t policy) {
sprintf
(
toUid
,
"%d"
,
ctx
->
to
.
uid
);
char
pid
[
16
];
sprintf
(
pid
,
"%d"
,
ctx
->
info
->
pid
);
sprintf
(
pid
,
"%d"
,
ctx
->
pid
);
char
user
[
16
];
int
notify
=
setup_user
(
ctx
,
user
);
...
...
db.c
View file @
1ddd7468
/*
** Copyright 2017, John Wu (@topjohnwu)
** Copyright 2013, Koushik Dutta (@koush)
**
*/
...
...
@@ -14,20 +15,15 @@
#include "magisk.h"
#include "su.h"
static
int
database
_callback
(
void
*
v
,
int
argc
,
char
**
argv
,
char
**
azColName
)
{
static
int
policy
_callback
(
void
*
v
,
int
argc
,
char
**
argv
,
char
**
azColName
)
{
struct
su_context
*
ctx
=
(
struct
su_context
*
)
v
;
policy_t
policy
=
QUERY
;
time_t
until
=
0
;
for
(
int
i
=
0
;
i
<
argc
;
i
++
)
{
if
(
strcmp
(
azColName
[
i
],
"policy"
)
==
0
)
{
if
(
argv
[
i
]
!=
NULL
)
{
policy
=
atoi
(
argv
[
i
]);
}
}
else
if
(
strcmp
(
azColName
[
i
],
"until"
)
==
0
)
{
if
(
argv
[
i
]
!=
NULL
)
{
until
=
atol
(
argv
[
i
]);
}
}
for
(
int
i
=
0
;
i
<
argc
;
i
++
)
{
if
(
strcmp
(
azColName
[
i
],
"policy"
)
==
0
)
policy
=
atoi
(
argv
[
i
]);
else
if
(
strcmp
(
azColName
[
i
],
"until"
)
==
0
)
until
=
atol
(
argv
[
i
]);
}
if
(
policy
==
DENY
)
...
...
@@ -35,18 +31,44 @@ static int database_callback(void *v, int argc, char **argv, char **azColName) {
else
if
(
policy
==
ALLOW
&&
(
until
==
0
||
until
>
time
(
NULL
)))
ctx
->
info
->
policy
=
ALLOW
;
LOGD
(
"su_db: query policy=[%d]
\n
"
,
ctx
->
info
->
policy
);
return
0
;
}
static
int
settings_callback
(
void
*
v
,
int
argc
,
char
**
argv
,
char
**
azColName
)
{
struct
su_context
*
ctx
=
(
struct
su_context
*
)
v
;
int
*
target
,
value
;
char
*
entry
;
for
(
int
i
=
0
;
i
<
argc
;
++
i
)
{
if
(
strcmp
(
azColName
[
i
],
"key"
)
==
0
)
{
if
(
strcmp
(
argv
[
i
],
ROOT_ACCESS_ENTRY
)
==
0
)
target
=
&
ctx
->
info
->
root_access
;
else
if
(
strcmp
(
argv
[
i
],
MULTIUSER_MODE_ENTRY
)
==
0
)
target
=
&
ctx
->
info
->
multiuser_mode
;
entry
=
argv
[
i
];
}
else
if
(
strcmp
(
azColName
[
i
],
"value"
)
==
0
)
{
value
=
atoi
(
argv
[
i
]);
}
}
LOGD
(
"su_db: query %s=[%d]
\n
"
,
entry
,
value
);
*
target
=
value
;
return
0
;
}
void
database_check
(
struct
su_context
*
ctx
)
{
sqlite3
*
db
=
NULL
;
// Set default values
ctx
->
info
->
root_access
=
ROOT_ACCESS_APPS_AND_ADB
;
ctx
->
info
->
multiuser_mode
=
MULTIUSER_MODE_OWNER_ONLY
;
ctx
->
info
->
policy
=
QUERY
;
// Check if file is readable
if
(
access
(
ctx
->
user
.
database_path
,
R_OK
)
==
-
1
)
return
;
char
query
[
512
];
snprintf
(
query
,
sizeof
(
query
),
"SELECT policy, until FROM policies WHERE uid=%d"
,
ctx
->
info
->
uid
%
100000
);
// Open database
int
ret
=
sqlite3_open_v2
(
ctx
->
user
.
database_path
,
&
db
,
SQLITE_OPEN_READONLY
,
NULL
);
if
(
ret
)
{
LOGD
(
"sqlite3 open failure: %s
\n
"
,
sqlite3_errstr
(
ret
));
...
...
@@ -54,11 +76,21 @@ void database_check(struct su_context *ctx) {
return
;
}
char
*
err
=
NULL
;
ret
=
sqlite3_exec
(
db
,
query
,
database_callback
,
ctx
,
&
err
);
sqlite3_close
(
db
);
if
(
err
!=
NULL
)
{
char
query
[
512
],
*
err
=
NULL
;
// Query for policy
snprintf
(
query
,
sizeof
(
query
),
"SELECT policy, until FROM policies WHERE uid=%d"
,
ctx
->
info
->
uid
%
100000
);
sqlite3_exec
(
db
,
query
,
policy_callback
,
ctx
,
&
err
);
if
(
err
!=
NULL
)
LOGE
(
"sqlite3_exec: %s
\n
"
,
err
);
ctx
->
info
->
policy
=
DENY
;
}
err
=
NULL
;
// Query for settings
snprintf
(
query
,
sizeof
(
query
),
"SELECT key, value FROM settings"
);
sqlite3_exec
(
db
,
query
,
settings_callback
,
ctx
,
&
err
);
if
(
err
!=
NULL
)
LOGE
(
"sqlite3_exec: %s
\n
"
,
err
);
sqlite3_close
(
db
);
}
su.c
View file @
1ddd7468
...
...
@@ -237,7 +237,7 @@ int su_daemon_main(int argc, char **argv) {
printf
(
"%s
\n
"
,
MAGISKSU_VER_STR
);
exit2
(
EXIT_SUCCESS
);
case
'u'
:
switch
(
su_ctx
->
user
.
multiuser_mode
)
{
switch
(
su_ctx
->
info
->
multiuser_mode
)
{
case
MULTIUSER_MODE_USER
:
printf
(
"Owner only: Only owner has root access
\n
"
);
break
;
...
...
@@ -293,34 +293,26 @@ int su_daemon_main(int argc, char **argv) {
// Setup done, now every error leads to deny
err_handler
=
deny
;
// Check property of root configuration
char
*
root_prop
=
getprop
(
ROOT_ACCESS_PROP
);
if
(
root_prop
)
{
int
prop_status
=
atoi
(
root_prop
);
switch
(
prop_status
)
{
case
ROOT_ACCESS_DISABLED
:
LOGE
(
"Root access is disabled!
\n
"
);
// Check root_access configuration
switch
(
su_ctx
->
info
->
root_access
)
{
case
ROOT_ACCESS_DISABLED
:
LOGE
(
"Root access is disabled!
\n
"
);
exit
(
EXIT_FAILURE
);
case
ROOT_ACCESS_APPS_ONLY
:
if
(
su_ctx
->
info
->
uid
==
UID_SHELL
)
{
LOGE
(
"Root access is disabled for ADB!
\n
"
);
exit
(
EXIT_FAILURE
);
}
break
;
case
ROOT_ACCESS_ADB_ONLY
:
if
(
su_ctx
->
info
->
uid
!=
UID_SHELL
)
{
LOGE
(
"Root access limited to ADB only!
\n
"
);
exit
(
EXIT_FAILURE
);
case
ROOT_ACCESS_APPS_ONLY
:
if
(
su_ctx
->
info
->
uid
==
UID_SHELL
)
{
LOGE
(
"Root access is disabled for ADB!
\n
"
);
exit
(
EXIT_FAILURE
);
}
break
;
case
ROOT_ACCESS_ADB_ONLY
:
if
(
su_ctx
->
info
->
uid
!=
UID_SHELL
)
{
LOGE
(
"Root access limited to ADB only!
\n
"
);
exit
(
EXIT_FAILURE
);
}
break
;
case
ROOT_ACCESS_APPS_AND_ADB
:
default
:
break
;
}
free
(
root_prop
)
;
}
else
{
// Not initialized yet, set the prop to allow everything by default
setprop
(
ROOT_ACCESS_PROP
,
xstr
(
ROOT_ACCESS_APPS_AND_ADB
))
;
break
;
case
ROOT_ACCESS_APPS_AND_ADB
:
default
:
break
;
}
// New request or no db exist, notify user for response
...
...
su.h
View file @
1ddd7468
...
...
@@ -12,14 +12,14 @@
#define MAGISKSU_VER_STR xstr(MAGISK_VERSION) ":MAGISKSU (topjohnwu)"
// Property check for root access
#define ROOT_ACCESS_
PROP "persist.magisk.root
"
#define ROOT_ACCESS_
ENTRY "root_access
"
#define ROOT_ACCESS_DISABLED 0
#define ROOT_ACCESS_APPS_ONLY 1
#define ROOT_ACCESS_ADB_ONLY 2
#define ROOT_ACCESS_APPS_AND_ADB 3
// Property for multiuser
#define MULTIUSER_MODE_
PROP "persist.magisk.multiuser
"
#define MULTIUSER_MODE_
ENTRY "multiuser_mode
"
#define MULTIUSER_MODE_OWNER_ONLY 0
#define MULTIUSER_MODE_OWNER_MANAGED 1
#define MULTIUSER_MODE_USER 2
...
...
@@ -51,13 +51,14 @@ typedef enum {
ALLOW
=
2
,
}
policy_t
;
struct
su_initiator
{
pid_t
pid
;
struct
su_info
{
unsigned
uid
;
policy_t
policy
;
pthread_mutex_t
lock
;
int
count
;
int
clock
;
int
multiuser_mode
;
int
root_access
;
struct
list_head
pos
;
};
...
...
@@ -75,8 +76,6 @@ struct su_user_info {
// the user in android userspace (multiuser)
// that invoked this action.
unsigned
android_user_id
;
// how su behaves with multiuser. see enum below.
int
multiuser_mode
;
// path to superuser directory. this is populated according
// to the multiuser mode.
// this is used to check uid/gid for protecting socket.
...
...
@@ -89,9 +88,10 @@ struct su_user_info {
};
struct
su_context
{
struct
su_in
itiator
*
info
;
struct
su_in
fo
*
info
;
struct
su_request
to
;
struct
su_user_info
user
;
pid_t
pid
;
int
notify
;
mode_t
umask
;
char
sock_path
[
PATH_MAX
];
...
...
su_daemon.c
View file @
1ddd7468
...
...
@@ -63,27 +63,16 @@ static void sigpipe_handler(int sig) {
LOGD
(
"su: Client killed unexpectedly
\n
"
);
}
static
int
get_multiuser_mode
()
{
char
*
prop
=
getprop
(
MULTIUSER_MODE_PROP
);
if
(
prop
)
{
int
ret
=
atoi
(
prop
);
free
(
prop
);
return
ret
;
}
return
MULTIUSER_MODE_OWNER_ONLY
;
}
// Maintain the lists periodically
static
void
*
collector
(
void
*
args
)
{
LOGD
(
"su: collector started
\n
"
);
struct
list_head
*
pos
,
*
temp
;
struct
su_in
itiator
*
node
;
struct
su_in
fo
*
node
;
while
(
1
)
{
sleep
(
1
);
pthread_mutex_lock
(
&
list_lock
);
list_for_each
(
pos
,
&
active_list
)
{
node
=
list_entry
(
pos
,
struct
su_in
itiator
,
pos
);
node
=
list_entry
(
pos
,
struct
su_in
fo
,
pos
);
--
node
->
clock
;
// Timeout, move to waiting list
if
(
node
->
clock
==
0
)
{
...
...
@@ -94,7 +83,7 @@ static void *collector(void *args) {
}
}
list_for_each
(
pos
,
&
waiting_list
)
{
node
=
list_entry
(
pos
,
struct
su_in
itiator
,
pos
);
node
=
list_entry
(
pos
,
struct
su_in
fo
,
pos
);
// Nothing is using the info, remove it
if
(
node
->
count
==
0
)
{
temp
=
pos
;
...
...
@@ -111,7 +100,7 @@ static void *collector(void *args) {
void
su_daemon_receiver
(
int
client
)
{
LOGD
(
"su: request from client: %d
\n
"
,
client
);
struct
su_in
itiator
*
info
=
NULL
,
*
node
;
struct
su_in
fo
*
info
=
NULL
,
*
node
;
struct
list_head
*
pos
;
int
new_request
=
0
;
...
...
@@ -129,7 +118,7 @@ void su_daemon_receiver(int client) {
// Search for existing in the active list
list_for_each
(
pos
,
&
active_list
)
{
node
=
list_entry
(
pos
,
struct
su_in
itiator
,
pos
);
node
=
list_entry
(
pos
,
struct
su_in
fo
,
pos
);
if
(
node
->
uid
==
credential
.
uid
)
info
=
node
;
}
...
...
@@ -154,8 +143,6 @@ void su_daemon_receiver(int client) {
// Lock before the policy is determined
pthread_mutex_lock
(
&
info
->
lock
);
info
->
pid
=
credential
.
pid
;
// Default values
struct
su_context
ctx
=
{
.
info
=
info
,
...
...
@@ -168,8 +155,8 @@ void su_daemon_receiver(int client) {
},
.
user
=
{
.
android_user_id
=
info
->
uid
/
100000
,
.
multiuser_mode
=
get_multiuser_mode
(),
},
.
pid
=
credential
.
pid
,
.
umask
=
022
,
.
notify
=
new_request
,
};
...
...
@@ -191,8 +178,12 @@ void su_daemon_receiver(int client) {
// Not cached, do the checks
if
(
info
->
policy
==
QUERY
)
{
// Get data from database
database_check
(
su_ctx
);
// Handle multiuser denies
if
(
su_ctx
->
user
.
android_user_id
&&
su_ctx
->
user
.
multiuser_mode
==
MULTIUSER_MODE_OWNER_ONLY
)
{
su_ctx
->
info
->
multiuser_mode
==
MULTIUSER_MODE_OWNER_ONLY
)
{
info
->
policy
=
DENY
;
su_ctx
->
notify
=
0
;
}
...
...
@@ -200,19 +191,17 @@ void su_daemon_receiver(int client) {
// always allow if this is Magisk Manager
if
(
info
->
policy
==
QUERY
&&
(
info
->
uid
%
100000
)
==
(
st
.
st_uid
%
100000
))
{
info
->
policy
=
ALLOW
;
info
->
root_access
=
ROOT_ACCESS_APPS_AND_ADB
;
su_ctx
->
notify
=
0
;
}
// always allow if it's root
if
(
info
->
uid
==
UID_ROOT
)
{
info
->
policy
=
ALLOW
;
info
->
root_access
=
ROOT_ACCESS_APPS_AND_ADB
;
su_ctx
->
notify
=
0
;
}
// If not determined, check database
if
(
info
->
policy
==
QUERY
)
database_check
(
su_ctx
);
// If still not determined, open a pipe and wait for results
if
(
info
->
policy
==
QUERY
)
pipe2
(
pipefd
,
O_CLOEXEC
);
...
...
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