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
b2f71998
Commit
b2f71998
authored
Jun 12, 2018
by
topjohnwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move database logic outside of MagiskSU
parent
7e2ba41c
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
135 additions
and
290 deletions
+135
-290
activity.c
activity.c
+5
-5
db.c
db.c
+0
-148
su.c
su.c
+13
-35
su.h
su.h
+6
-42
su_daemon.c
su_daemon.c
+111
-60
No files found.
activity.c
View file @
b2f71998
...
...
@@ -45,7 +45,7 @@ static void silent_run(char* const args[]) {
}
static
int
setup_user
(
struct
su_context
*
ctx
,
char
*
user
)
{
switch
(
ctx
->
info
->
multiuser_mode
)
{
switch
(
ctx
->
info
->
dbs
.
v
[
SU_MULTIUSER_MODE
]
)
{
case
MULTIUSER_MODE_OWNER_ONLY
:
/* Should already be denied if not owner */
case
MULTIUSER_MODE_OWNER_MANAGED
:
sprintf
(
user
,
"%d"
,
0
);
...
...
@@ -59,7 +59,7 @@ static int setup_user(struct su_context *ctx, char* user) {
void
app_send_result
(
struct
su_context
*
ctx
,
policy_t
policy
)
{
char
fromUid
[
16
];
if
(
ctx
->
info
->
multiuser_mode
==
MULTIUSER_MODE_OWNER_MANAGED
)
if
(
ctx
->
info
->
dbs
.
v
[
SU_MULTIUSER_MODE
]
==
MULTIUSER_MODE_OWNER_MANAGED
)
sprintf
(
fromUid
,
"%d"
,
ctx
->
info
->
uid
%
100000
);
else
sprintf
(
fromUid
,
"%d"
,
ctx
->
info
->
uid
);
...
...
@@ -74,7 +74,7 @@ void app_send_result(struct su_context *ctx, policy_t policy) {
int
notify
=
setup_user
(
ctx
,
user
);
char
activity
[
128
];
sprintf
(
activity
,
ACTION_RESULT
,
ctx
->
info
->
pkg_name
);
sprintf
(
activity
,
ACTION_RESULT
,
ctx
->
info
->
str
.
s
[
SU_REQUESTER
]
);
// Send notice to manager, enable logging
char
*
result_command
[]
=
{
...
...
@@ -113,7 +113,7 @@ void app_send_request(struct su_context *ctx) {
int
notify
=
setup_user
(
ctx
,
user
);
char
activity
[
128
];
sprintf
(
activity
,
ACTION_REQUEST
,
ctx
->
info
->
pkg_name
);
sprintf
(
activity
,
ACTION_REQUEST
,
ctx
->
info
->
str
.
s
[
SU_REQUESTER
]
);
char
*
request_command
[]
=
{
AM_PATH
,
"start"
,
"-n"
,
...
...
@@ -128,7 +128,7 @@ void app_send_request(struct su_context *ctx) {
// Send notice to user to tell them root is managed by owner
if
(
notify
)
{
sprintf
(
user
,
"%d"
,
notify
);
sprintf
(
activity
,
ACTION_RESULT
,
ctx
->
info
->
pkg_name
);
sprintf
(
activity
,
ACTION_RESULT
,
ctx
->
info
->
str
.
s
[
SU_REQUESTER
]
);
char
*
notify_command
[]
=
{
AM_PATH
,
"broadcast"
,
"-n"
,
activity
,
...
...
db.c
deleted
100644 → 0
View file @
7e2ba41c
/*
** Copyright 2017, John Wu (@topjohnwu)
** Copyright 2013, Koushik Dutta (@koush)
**
*/
#include <stdlib.h>
#include <stdio.h>
#include <sqlite3.h>
#include <time.h>
#include <string.h>
#include <unistd.h>
#include "magisk.h"
#include "su.h"
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
)
policy
=
atoi
(
argv
[
i
]);
else
if
(
strcmp
(
azColName
[
i
],
"until"
)
==
0
)
until
=
atol
(
argv
[
i
]);
}
if
(
policy
==
DENY
)
ctx
->
info
->
policy
=
DENY
;
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
;
else
if
(
strcmp
(
argv
[
i
],
NAMESPACE_MODE_ENTRY
)
==
0
)
target
=
&
ctx
->
info
->
mnt_ns
;
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
;
}
static
int
strings_callback
(
void
*
v
,
int
argc
,
char
**
argv
,
char
**
azColName
)
{
struct
su_context
*
ctx
=
(
struct
su_context
*
)
v
;
char
*
entry
,
*
target
,
*
value
;
for
(
int
i
=
0
;
i
<
argc
;
++
i
)
{
if
(
strcmp
(
azColName
[
i
],
"key"
)
==
0
)
{
if
(
strcmp
(
argv
[
i
],
REQUESTER_ENTRY
)
==
0
)
target
=
ctx
->
info
->
pkg_name
;
entry
=
argv
[
i
];
}
else
if
(
strcmp
(
azColName
[
i
],
"value"
)
==
0
)
{
value
=
argv
[
i
];
}
}
LOGD
(
"su_db: query %s=[%s]
\n
"
,
entry
,
value
);
strcpy
(
target
,
value
);
return
0
;
}
void
database_check
(
struct
su_context
*
ctx
)
{
sqlite3
*
db
=
NULL
;
int
ret
;
char
buffer
[
PATH_MAX
],
*
err
=
NULL
;
const
char
*
base
=
access
(
"/data/user_de"
,
F_OK
)
==
0
?
"/data/user_de"
:
"/data/user"
;
// Set default values
ctx
->
info
->
root_access
=
ROOT_ACCESS_APPS_AND_ADB
;
ctx
->
info
->
multiuser_mode
=
MULTIUSER_MODE_OWNER_ONLY
;
ctx
->
info
->
mnt_ns
=
NAMESPACE_MODE_REQUESTER
;
strcpy
(
ctx
->
info
->
pkg_name
,
"???"
);
/* bad string so it doesn't exist */
// Open database
ret
=
sqlite3_open_v2
(
MAGISKDB
,
&
db
,
SQLITE_OPEN_READONLY
,
NULL
);
if
(
ret
)
{
LOGE
(
"sqlite3 open failure: %s
\n
"
,
sqlite3_errstr
(
ret
));
sqlite3_close
(
db
);
goto
stat_requester
;
}
// Query for strings
sqlite3_exec
(
db
,
"SELECT key, value FROM strings"
,
strings_callback
,
ctx
,
&
err
);
if
(
err
)
LOGE
(
"sqlite3_exec: %s
\n
"
,
err
);
err
=
NULL
;
// Query for settings
sqlite3_exec
(
db
,
"SELECT key, value FROM settings"
,
settings_callback
,
ctx
,
&
err
);
if
(
err
)
LOGE
(
"sqlite3_exec: %s
\n
"
,
err
);
err
=
NULL
;
// Query for policy
int
uid
=
-
1
;
switch
(
ctx
->
info
->
multiuser_mode
)
{
case
MULTIUSER_MODE_OWNER_ONLY
:
if
(
ctx
->
info
->
uid
/
100000
)
{
uid
=
-
1
;
ctx
->
info
->
policy
=
DENY
;
ctx
->
notify
=
0
;
}
else
{
uid
=
ctx
->
info
->
uid
;
}
break
;
case
MULTIUSER_MODE_OWNER_MANAGED
:
uid
=
ctx
->
info
->
uid
%
100000
;
break
;
case
MULTIUSER_MODE_USER
:
uid
=
ctx
->
info
->
uid
;
break
;
}
sprintf
(
buffer
,
"SELECT policy, until FROM policies WHERE uid=%d"
,
uid
);
sqlite3_exec
(
db
,
buffer
,
policy_callback
,
ctx
,
&
err
);
if
(
err
)
LOGE
(
"sqlite3_exec: %s
\n
"
,
err
);
sqlite3_close
(
db
);
stat_requester:
// We prefer the original name
sprintf
(
buffer
,
"%s/0/"
JAVA_PACKAGE_NAME
,
base
);
if
(
stat
(
buffer
,
&
ctx
->
info
->
st
)
==
0
)
{
strcpy
(
ctx
->
info
->
pkg_name
,
JAVA_PACKAGE_NAME
);
}
else
{
sprintf
(
buffer
,
"%s/0/%s"
,
base
,
ctx
->
info
->
pkg_name
);
if
(
stat
(
buffer
,
&
ctx
->
info
->
st
)
==
-
1
)
{
LOGE
(
"su: cannot find requester"
);
memset
(
&
ctx
->
info
->
st
,
0
,
sizeof
(
ctx
->
info
->
st
));
}
}
}
su.c
View file @
b2f71998
...
...
@@ -104,7 +104,7 @@ void set_identity(unsigned uid) {
static
__attribute__
((
noreturn
))
void
allow
()
{
char
*
argv
[]
=
{
NULL
,
NULL
,
NULL
,
NULL
};
if
(
su_ctx
->
notify
)
if
(
su_ctx
->
info
->
access
.
notify
||
su_ctx
->
info
->
access
.
log
)
app_send_result
(
su_ctx
,
ALLOW
);
if
(
su_ctx
->
to
.
login
)
...
...
@@ -129,7 +129,7 @@ static __attribute__ ((noreturn)) void allow() {
}
static
__attribute__
((
noreturn
))
void
deny
()
{
if
(
su_ctx
->
notify
)
if
(
su_ctx
->
info
->
access
.
notify
||
su_ctx
->
info
->
access
.
log
)
app_send_result
(
su_ctx
,
DENY
);
LOGW
(
"su: request rejected (%u->%u)"
,
su_ctx
->
info
->
uid
,
su_ctx
->
to
.
uid
);
...
...
@@ -140,7 +140,7 @@ static __attribute__ ((noreturn)) void deny() {
static
void
socket_cleanup
()
{
if
(
su_ctx
&&
su_ctx
->
sock_path
[
0
])
{
unlink
(
su_ctx
->
sock_path
);
su_ctx
->
sock_path
[
0
]
=
0
;
su_ctx
->
sock_path
[
0
]
=
'\0'
;
}
}
...
...
@@ -151,8 +151,9 @@ static void cleanup_signal(int sig) {
__attribute__
((
noreturn
))
void
exit2
(
int
status
)
{
// Handle the pipe, or the daemon will get stuck
if
(
su_ctx
->
info
->
policy
==
QUERY
)
{
xwrite
(
su_ctx
->
pipefd
[
1
],
&
su_ctx
->
info
->
policy
,
sizeof
(
su_ctx
->
info
->
policy
));
if
(
su_ctx
->
pipefd
[
0
]
>=
0
)
{
int
i
=
DENY
;
xwrite
(
su_ctx
->
pipefd
[
1
],
&
i
,
sizeof
(
i
));
close
(
su_ctx
->
pipefd
[
0
]);
close
(
su_ctx
->
pipefd
[
1
]);
}
...
...
@@ -215,7 +216,6 @@ int su_daemon_main(int argc, char **argv) {
case
'c'
:
su_ctx
->
to
.
command
=
concat_commands
(
argc
,
argv
);
optind
=
argc
;
su_ctx
->
notify
=
1
;
break
;
case
'h'
:
usage
(
EXIT_SUCCESS
);
...
...
@@ -240,7 +240,7 @@ int su_daemon_main(int argc, char **argv) {
// Do nothing, placed here for legacy support :)
break
;
case
'M'
:
su_ctx
->
info
->
mnt_ns
=
NAMESPACE_MODE_GLOBAL
;
su_ctx
->
info
->
dbs
.
v
[
SU_MNT_NS
]
=
NAMESPACE_MODE_GLOBAL
;
break
;
default
:
/* Bionic getopt_long doesn't terminate its error output by newline */
...
...
@@ -265,7 +265,7 @@ int su_daemon_main(int argc, char **argv) {
}
// Handle namespaces
switch
(
su_ctx
->
info
->
mnt_ns
)
{
switch
(
su_ctx
->
info
->
dbs
.
v
[
SU_MNT_NS
]
)
{
case
NAMESPACE_MODE_GLOBAL
:
LOGD
(
"su: use global namespace
\n
"
);
break
;
...
...
@@ -285,30 +285,8 @@ int su_daemon_main(int argc, char **argv) {
// Change directory to cwd
chdir
(
su_ctx
->
cwd
);
// 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
);
}
break
;
case
ROOT_ACCESS_APPS_AND_ADB
:
default
:
break
;
}
// New request or no db exist, notify user for response
if
(
su_ctx
->
info
->
policy
==
QUERY
&&
su_ctx
->
info
->
st
.
st_uid
!
=
0
)
{
if
(
su_ctx
->
pipefd
[
0
]
>
=
0
)
{
socket_serv_fd
=
socket_create_temp
(
su_ctx
->
sock_path
,
sizeof
(
su_ctx
->
sock_path
));
setup_sighandlers
(
cleanup_signal
);
...
...
@@ -326,17 +304,17 @@ int su_daemon_main(int argc, char **argv) {
socket_cleanup
();
if
(
strcmp
(
result
,
"socket:ALLOW"
)
==
0
)
su_ctx
->
info
->
policy
=
ALLOW
;
su_ctx
->
info
->
access
.
policy
=
ALLOW
;
else
su_ctx
->
info
->
policy
=
DENY
;
su_ctx
->
info
->
access
.
policy
=
DENY
;
// Report the policy to main daemon
xwrite
(
su_ctx
->
pipefd
[
1
],
&
su_ctx
->
info
->
policy
,
sizeof
(
su_ctx
->
info
->
policy
));
xwrite
(
su_ctx
->
pipefd
[
1
],
&
su_ctx
->
info
->
access
.
policy
,
sizeof
(
policy_t
));
close
(
su_ctx
->
pipefd
[
0
]);
close
(
su_ctx
->
pipefd
[
1
]);
}
if
(
su_ctx
->
info
->
policy
==
ALLOW
)
if
(
su_ctx
->
info
->
access
.
policy
==
ALLOW
)
allow
();
else
deny
();
...
...
su.h
View file @
b2f71998
...
...
@@ -8,57 +8,26 @@
#include <sys/types.h>
#include <sys/stat.h>
#include "db.h"
#include "list.h"
#define MAGISKSU_VER_STR xstr(MAGISK_VERSION) ":MAGISKSU (topjohnwu)"
// DB settings for root access
#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
// DB settings for multiuser
#define MULTIUSER_MODE_ENTRY "multiuser_mode"
#define MULTIUSER_MODE_OWNER_ONLY 0
#define MULTIUSER_MODE_OWNER_MANAGED 1
#define MULTIUSER_MODE_USER 2
// DB settings for namespace seperation
#define NAMESPACE_MODE_ENTRY "mnt_ns"
#define NAMESPACE_MODE_GLOBAL 0
#define NAMESPACE_MODE_REQUESTER 1
#define NAMESPACE_MODE_ISOLATE 2
// DB entry for requester
#define REQUESTER_ENTRY "requester"
// DO NOT CHANGE LINE BELOW, java package name will always be the same
#define JAVA_PACKAGE_NAME "com.topjohnwu.magisk"
// This is used if wrapping the fragment classes and activities
// with classes in another package.
#define REQUESTOR_PREFIX JAVA_PACKAGE_NAME ".superuser"
#define DEFAULT_SHELL "/system/bin/sh"
typedef
enum
{
QUERY
=
0
,
DENY
=
1
,
ALLOW
=
2
,
}
policy_t
;
struct
su_info
{
unsigned
uid
;
/* K
ey to find su_info */
unsigned
uid
;
/* Unique k
ey to find su_info */
pthread_mutex_t
lock
;
/* Internal lock */
int
count
;
/* Just a count for debugging purpose */
int
count
;
/* Just a count for debugging purpose */
/* These values should be guarded with internal lock */
policy_t
policy
;
int
multiuser_mode
;
int
root_access
;
int
mnt_ns
;
char
pkg_name
[
PATH_MAX
];
struct
db_settings
dbs
;
struct
db_strings
str
;
struct
su_access
access
;
struct
stat
st
;
/* These should be guarded with global list lock */
...
...
@@ -79,7 +48,6 @@ struct su_context {
struct
su_info
*
info
;
struct
su_request
to
;
pid_t
pid
;
int
notify
;
char
cwd
[
PATH_MAX
];
char
sock_path
[
PATH_MAX
];
int
pipefd
[
2
];
...
...
@@ -105,8 +73,4 @@ void socket_receive_result(int fd, char *result, ssize_t result_len);
void
app_send_result
(
struct
su_context
*
ctx
,
policy_t
policy
);
void
app_send_request
(
struct
su_context
*
ctx
);
// db.c
void
database_check
(
struct
su_context
*
ctx
);
#endif
su_daemon.c
View file @
b2f71998
...
...
@@ -31,7 +31,7 @@
#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)
#define UNLOCK_UID() pthread_mutex_unlock(&
ctx.
info->lock)
static
struct
list_head
active_list
,
waiting_list
;
static
pthread_t
su_collector
=
0
;
...
...
@@ -88,11 +88,41 @@ static void *collector(void *args) {
}
}
void
su_daemon_receiver
(
int
client
,
struct
ucred
*
credential
)
{
LOGD
(
"su: request from client: %d
\n
"
,
client
);
static
void
database_check
(
struct
su_info
*
info
)
{
int
uid
=
info
->
uid
;
sqlite3
*
db
=
get_magiskdb
();
if
(
db
)
{
get_db_settings
(
db
,
-
1
,
&
info
->
dbs
);
get_db_strings
(
db
,
-
1
,
&
info
->
str
);
// Check multiuser settings
switch
(
info
->
dbs
.
v
[
SU_MULTIUSER_MODE
])
{
case
MULTIUSER_MODE_OWNER_ONLY
:
if
(
info
->
uid
/
100000
)
{
uid
=
-
1
;
info
->
access
=
NO_SU_ACCESS
;
}
break
;
case
MULTIUSER_MODE_OWNER_MANAGED
:
uid
=
info
->
uid
%
100000
;
break
;
case
MULTIUSER_MODE_USER
:
default:
break
;
}
if
(
uid
>
0
)
get_uid_policy
(
db
,
uid
,
&
info
->
access
);
sqlite3_close
(
db
);
}
// We need to check our manager
if
(
info
->
access
.
log
||
info
->
access
.
notify
)
validate_manager
(
info
->
str
.
s
[
SU_REQUESTER
],
uid
/
100000
,
&
info
->
st
);
}
static
struct
su_info
*
get_su_info
(
unsigned
uid
)
{
struct
su_info
*
info
=
NULL
,
*
node
;
int
new_request
=
0
;
LOCK_LIST
();
...
...
@@ -104,7 +134,7 @@ void su_daemon_receiver(int client, struct ucred *credential) {
// Search for existing in the active list
list_for_each
(
node
,
&
active_list
,
struct
su_info
,
pos
)
{
if
(
node
->
uid
==
credential
->
uid
)
{
if
(
node
->
uid
==
uid
)
{
info
=
node
;
break
;
}
...
...
@@ -112,10 +142,11 @@ void su_daemon_receiver(int client, struct ucred *credential) {
// If no exist, create a new request
if
(
info
==
NULL
)
{
new_request
=
1
;
info
=
malloc
(
sizeof
(
*
info
));
info
->
uid
=
credential
->
uid
;
info
->
policy
=
QUERY
;
info
->
uid
=
uid
;
info
->
dbs
=
DEFAULT_DB_SETTINGS
;
info
->
access
=
DEFAULT_SU_ACCESS
;
INIT_DB_STRINGS
(
&
info
->
str
);
info
->
ref
=
0
;
info
->
count
=
0
;
pthread_mutex_init
(
&
info
->
lock
,
NULL
);
...
...
@@ -128,65 +159,85 @@ void su_daemon_receiver(int client, struct ucred *credential) {
LOGD
(
"su: request from uid=[%d] (#%d)
\n
"
,
info
->
uid
,
++
info
->
count
);
// Default values
struct
su_context
ctx
=
{
.
info
=
info
,
.
to
=
{
.
uid
=
UID_ROOT
,
.
login
=
0
,
.
keepenv
=
0
,
.
shell
=
DEFAULT_SHELL
,
.
command
=
NULL
,
},
.
pid
=
credential
->
pid
,
.
notify
=
new_request
,
};
// Lock before the policy is determined
LOCK_UID
();
// Not cached, do the checks
if
(
info
->
policy
==
QUERY
)
{
// Get data from database
database_check
(
&
ctx
);
// Check requester
if
(
info
->
policy
==
QUERY
)
{
if
(
info
->
st
.
st_gid
!=
info
->
st
.
st_uid
)
{
LOGE
(
"Bad uid/gid %d/%d for Superuser Requestor"
,
info
->
st
.
st_gid
,
info
->
st
.
st_uid
);
info
->
policy
=
DENY
;
ctx
.
notify
=
0
;
}
else
if
((
info
->
uid
%
100000
)
==
(
info
->
st
.
st_uid
%
100000
))
{
info
->
policy
=
ALLOW
;
info
->
root_access
=
ROOT_ACCESS_APPS_AND_ADB
;
ctx
.
notify
=
0
;
}
if
(
info
->
access
.
policy
==
QUERY
)
{
// Not cached, get data from database
database_check
(
info
);
// Check su access settings
switch
(
info
->
dbs
.
v
[
ROOT_ACCESS
])
{
case
ROOT_ACCESS_DISABLED
:
LOGE
(
"Root access is disabled!
\n
"
);
info
->
access
=
NO_SU_ACCESS
;
break
;
case
ROOT_ACCESS_ADB_ONLY
:
if
(
info
->
uid
!=
UID_SHELL
)
{
LOGE
(
"Root access is disabled for ADB!
\n
"
);
info
->
access
=
NO_SU_ACCESS
;
}
break
;
case
ROOT_ACCESS_APPS_ONLY
:
if
(
info
->
uid
==
UID_SHELL
)
{
LOGE
(
"Root access limited to ADB only!
\n
"
);
info
->
access
=
NO_SU_ACCESS
;
}
break
;
case
ROOT_ACCESS_APPS_AND_ADB
:
default:
break
;
}
// always allow if it's root
if
(
info
->
uid
==
UID_ROOT
)
{
info
->
policy
=
ALLOW
;
info
->
root_access
=
ROOT_ACCESS_APPS_AND_ADB
;
ctx
.
notify
=
0
;
}
// If it's the manager, allow it silently
if
((
info
->
uid
%
100000
)
==
(
info
->
st
.
st_uid
%
100000
))
info
->
access
=
SILENT_SU_ACCESS
;
// Allow if it's root
if
(
info
->
uid
==
UID_ROOT
)
info
->
access
=
SILENT_SU_ACCESS
;
// If still not determined,
open a pipe and wait for resul
ts
if
(
info
->
policy
==
QUERY
)
xpipe2
(
ctx
.
pipefd
,
O_CLOEXEC
)
;
// If still not determined,
check if manager exis
ts
if
(
info
->
access
.
policy
==
QUERY
&&
info
->
str
.
s
[
SU_REQUESTER
][
0
]
==
'\0'
)
info
->
access
=
NO_SU_ACCESS
;
}
return
info
;
}
void
su_daemon_receiver
(
int
client
,
struct
ucred
*
credential
)
{
LOGD
(
"su: request from client: %d
\n
"
,
client
);
// Default values
struct
su_context
ctx
=
{
.
info
=
get_su_info
(
credential
->
uid
),
.
to
=
{
.
uid
=
UID_ROOT
,
.
login
=
0
,
.
keepenv
=
0
,
.
shell
=
DEFAULT_SHELL
,
.
command
=
NULL
,
},
.
pid
=
credential
->
pid
,
.
pipefd
=
{
-
1
,
-
1
}
};
// If still not determined, open a pipe and wait for results
if
(
ctx
.
info
->
access
.
policy
==
QUERY
)
xpipe2
(
ctx
.
pipefd
,
O_CLOEXEC
);
// Fork a new process, the child process will need to setsid,
// open a pseudo-terminal if needed, and will eventually run exec
// The parent process will wait for the result and
// send the return code back to our client
/* Fork a new process, the child process will need to setsid,
* open a pseudo-terminal if needed, and will eventually run exec
* The parent process will wait for the result and
* send the return code back to our client
*/
int
child
=
fork
();
if
(
child
<
0
)
PLOGE
(
"fork"
);
if
(
child
)
{
// Wait for results
if
(
info
->
policy
==
QUERY
)
{
xxread
(
ctx
.
pipefd
[
0
],
&
info
->
policy
,
sizeof
(
info
->
policy
));
if
(
ctx
.
pipefd
[
0
]
>=
0
)
{
xxread
(
ctx
.
pipefd
[
0
],
&
ctx
.
info
->
access
.
policy
,
sizeof
(
policy_t
));
close
(
ctx
.
pipefd
[
0
]);
close
(
ctx
.
pipefd
[
1
]);
}
...
...
@@ -223,7 +274,7 @@ void su_daemon_receiver(int client, struct ucred *credential) {
// Decrement reference count
LOCK_LIST
();
--
info
->
ref
;
--
ctx
.
info
->
ref
;
UNLOCK_LIST
();
return
;
...
...
@@ -276,7 +327,7 @@ void su_daemon_receiver(int client, struct ucred *credential) {
char
*
pts_slave
=
read_string
(
client
);
LOGD
(
"su: pts_slave=[%s]
\n
"
,
pts_slave
);
// The
the
FDs for each of the streams
// The FDs for each of the streams
int
infd
=
recv_fd
(
client
);
int
outfd
=
recv_fd
(
client
);
int
errfd
=
recv_fd
(
client
);
...
...
@@ -286,12 +337,12 @@ void su_daemon_receiver(int client, struct ucred *credential) {
close
(
client
);
if
(
pts_slave
[
0
])
{
//Check pts_slave file is owned by daemon_from_uid
struct
stat
st
buf
;
xstat
(
pts_slave
,
&
st
buf
);
//
Check pts_slave file is owned by daemon_from_uid
struct
stat
st
;
xstat
(
pts_slave
,
&
st
);
//If caller is not root, ensure the owner of pts_slave is the caller
if
(
st
buf
.
st_uid
!=
info
->
uid
&&
info
->
uid
!=
0
)
{
//
If caller is not root, ensure the owner of pts_slave is the caller
if
(
st
.
st_uid
!=
credential
->
uid
&&
credential
->
uid
!=
0
)
{
LOGE
(
"su: Wrong permission of pts_slave"
);
exit2
(
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