Support FBE: read from DE

This commit is contained in:
topjohnwu 2017-09-15 18:01:31 +08:00
parent 8c52dfb804
commit 1a702b08b9
5 changed files with 42 additions and 49 deletions

View File

@ -52,9 +52,9 @@ static int setup_user(struct su_context *ctx, char* user) {
case MULTIUSER_MODE_OWNER_ONLY: /* Should already be denied if not owner */ case MULTIUSER_MODE_OWNER_ONLY: /* Should already be denied if not owner */
case MULTIUSER_MODE_OWNER_MANAGED: case MULTIUSER_MODE_OWNER_MANAGED:
sprintf(user, "%d", 0); sprintf(user, "%d", 0);
return ctx->user.android_user_id; return ctx->info->uid / 100000;
case MULTIUSER_MODE_USER: case MULTIUSER_MODE_USER:
sprintf(user, "%d", ctx->user.android_user_id); sprintf(user, "%d", ctx->info->uid / 100000);
break; break;
} }
return 0; return 0;
@ -135,7 +135,7 @@ void app_send_request(struct su_context *ctx) {
user, user,
"--es", "--es",
"socket", "socket",
ctx->sock_path, ctx->path.sock_path,
"--ez", "--ez",
"timeout", "timeout",
notify ? "false" : "true", notify ? "false" : "true",

14
db.c
View File

@ -69,13 +69,8 @@ void database_check(struct su_context *ctx) {
ctx->info->mnt_ns = NAMESPACE_MODE_REQUESTER; ctx->info->mnt_ns = NAMESPACE_MODE_REQUESTER;
ctx->info->policy = QUERY; ctx->info->policy = QUERY;
// First query the from app data
// Check if file is readable
if (access(APP_DATA_PATH REQUESTOR_DATABASE_PATH, R_OK) == -1)
return;
// Open database // Open database
ret = sqlite3_open_v2(APP_DATA_PATH REQUESTOR_DATABASE_PATH, &db, SQLITE_OPEN_READONLY, NULL); ret = sqlite3_open_v2(ctx->path.base_db, &db, SQLITE_OPEN_READONLY, NULL);
if (ret) { if (ret) {
LOGD("sqlite3 open failure: %s\n", sqlite3_errstr(ret)); LOGD("sqlite3 open failure: %s\n", sqlite3_errstr(ret));
sqlite3_close(db); sqlite3_close(db);
@ -88,14 +83,11 @@ void database_check(struct su_context *ctx) {
err = NULL; err = NULL;
if (ctx->user.android_user_id != 0 && ctx->info->multiuser_mode == MULTIUSER_MODE_USER) { if (ctx->info->uid / 100000 != 0 && ctx->info->multiuser_mode == MULTIUSER_MODE_USER) {
sqlite3_close(db); sqlite3_close(db);
// Check if file is readable
if (access(ctx->user.database_path, R_OK) == -1)
return;
// Open database // Open database
ret = sqlite3_open_v2(ctx->user.database_path, &db, SQLITE_OPEN_READONLY, NULL); ret = sqlite3_open_v2(ctx->path.multiuser_db, &db, SQLITE_OPEN_READONLY, NULL);
if (ret) { if (ret) {
LOGD("sqlite3 open failure: %s\n", sqlite3_errstr(ret)); LOGD("sqlite3 open failure: %s\n", sqlite3_errstr(ret));
sqlite3_close(db); sqlite3_close(db);

8
su.c
View File

@ -148,9 +148,9 @@ static __attribute__ ((noreturn)) void deny() {
} }
static void socket_cleanup() { static void socket_cleanup() {
if (su_ctx && su_ctx->sock_path[0]) { if (su_ctx && su_ctx->path.sock_path[0]) {
unlink(su_ctx->sock_path); unlink(su_ctx->path.sock_path);
su_ctx->sock_path[0] = 0; su_ctx->path.sock_path[0] = 0;
} }
} }
@ -368,7 +368,7 @@ int su_daemon_main(int argc, char **argv) {
if (seteuid(su_ctx->st.st_uid)) if (seteuid(su_ctx->st.st_uid))
PLOGE("seteuid (%u)", su_ctx->st.st_uid); PLOGE("seteuid (%u)", su_ctx->st.st_uid);
socket_serv_fd = socket_create_temp(su_ctx->sock_path, sizeof(su_ctx->sock_path)); socket_serv_fd = socket_create_temp(su_ctx->path.sock_path, sizeof(su_ctx->path.sock_path));
setup_sighandlers(cleanup_signal); setup_sighandlers(cleanup_signal);
// Start activity // Start activity

27
su.h
View File

@ -34,9 +34,6 @@
// DO NOT CHANGE LINE BELOW, java package name will always be the same // DO NOT CHANGE LINE BELOW, java package name will always be the same
#define JAVA_PACKAGE_NAME "com.topjohnwu.magisk" #define JAVA_PACKAGE_NAME "com.topjohnwu.magisk"
#define APP_DATA_PATH "/data/data/"
#define USER_DATA_PATH "/data/user"
// If --rename-manifest-package is used in AAPT, this // If --rename-manifest-package is used in AAPT, this
// must be changed to correspond to the new APK package name // must be changed to correspond to the new APK package name
// See the two Android.mk files for more details. // See the two Android.mk files for more details.
@ -45,10 +42,6 @@
// with classes in another package. // with classes in another package.
#define REQUESTOR_PREFIX JAVA_PACKAGE_NAME ".superuser" #define REQUESTOR_PREFIX JAVA_PACKAGE_NAME ".superuser"
#define REQUESTOR_CACHE_PATH "/dev/" REQUESTOR #define REQUESTOR_CACHE_PATH "/dev/" REQUESTOR
// there's no guarantee that the db or files are actually created named as such by
// SQLiteOpenHelper, etc. Though that is the behavior as of current.
// it is up to the Android application to symlink as appropriate.
#define REQUESTOR_DATABASE_PATH REQUESTOR "/databases/su.db"
#define DEFAULT_SHELL "/system/bin/sh" #define DEFAULT_SHELL "/system/bin/sh"
@ -85,31 +78,23 @@ struct su_request {
int argc; int argc;
}; };
struct su_user_info { struct su_path {
// the user in android userspace (multiuser)
// that invoked this action.
unsigned android_user_id;
// path to superuser directory. this is populated according
// to the multiuser mode.
// this is used to check uid/gid for protecting socket.
// this is used instead of database, as it is more likely
// to exist. db will not exist if su has never launched.
char base_path[PATH_MAX]; char base_path[PATH_MAX];
// path to su database. this is populated according char base_db[PATH_MAX];
// to the multiuser mode. char multiuser_path[PATH_MAX];
char database_path[PATH_MAX]; char multiuser_db[PATH_MAX];
char sock_path[PATH_MAX];
}; };
struct su_context { struct su_context {
struct su_info *info; struct su_info *info;
struct su_request to; struct su_request to;
struct su_user_info user; struct su_path path;
pid_t pid; pid_t pid;
int notify; int notify;
mode_t umask; mode_t umask;
char *cwd; char *cwd;
struct stat st; struct stat st;
char sock_path[PATH_MAX];
}; };
extern struct su_context *su_ctx; extern struct su_context *su_ctx;

View File

@ -90,6 +90,28 @@ static void *collector(void *args) {
} }
} }
#define BASE_FMT "/data/user%s/%d/" REQUESTOR
#define DB_FMT BASE_FMT "/databases/su.db"
#define CAT_PATH(dest, fmt, ...) snprintf(dest, sizeof(dest), fmt, __VA_ARGS__)
static void populate_paths(struct su_context *ctx) {
CAT_PATH(ctx->path.base_path, BASE_FMT, "_de", 0);
if (access(ctx->path.base_path, R_OK) == -1)
CAT_PATH(ctx->path.base_path, BASE_FMT, "", 0);
CAT_PATH(ctx->path.base_db, DB_FMT, "_de", 0);
if (access(ctx->path.base_db, R_OK) == -1)
CAT_PATH(ctx->path.base_db, DB_FMT, "", 0);
CAT_PATH(ctx->path.multiuser_path, BASE_FMT, "_de", ctx->info->uid / 100000);
if (access(ctx->path.multiuser_path, R_OK) == -1)
CAT_PATH(ctx->path.multiuser_path, BASE_FMT, "", ctx->info->uid / 100000);
CAT_PATH(ctx->path.multiuser_db, DB_FMT, "_de", ctx->info->uid / 100000);
if (access(ctx->path.multiuser_db, R_OK) == -1)
CAT_PATH(ctx->path.multiuser_db, DB_FMT, "", ctx->info->uid / 100000);
}
void su_daemon_receiver(int client) { void su_daemon_receiver(int client) {
LOGD("su: request from client: %d\n", client); LOGD("su: request from client: %d\n", client);
@ -144,20 +166,16 @@ void su_daemon_receiver(int client) {
.shell = DEFAULT_SHELL, .shell = DEFAULT_SHELL,
.command = NULL, .command = NULL,
}, },
.user = {
.android_user_id = info->uid / 100000,
},
.pid = credential.pid, .pid = credential.pid,
.umask = 022, .umask = 022,
.notify = new_request, .notify = new_request,
}; };
su_ctx = &ctx; su_ctx = &ctx;
snprintf(su_ctx->user.database_path, PATH_MAX, "%s/%d/%s", populate_paths(su_ctx);
USER_DATA_PATH, su_ctx->user.android_user_id, REQUESTOR_DATABASE_PATH);
// Check main Magisk Manager // Check main Magisk Manager
xstat(APP_DATA_PATH REQUESTOR, &su_ctx->st); xstat(su_ctx->path.base_path, &su_ctx->st);
if (su_ctx->st.st_gid != su_ctx->st.st_uid) { if (su_ctx->st.st_gid != su_ctx->st.st_uid) {
LOGE("Bad uid/gid %d/%d for Superuser Requestor application", su_ctx->st.st_uid, su_ctx->st.st_gid); LOGE("Bad uid/gid %d/%d for Superuser Requestor application", su_ctx->st.st_uid, su_ctx->st.st_gid);
info->policy = DENY; info->policy = DENY;
@ -172,10 +190,8 @@ void su_daemon_receiver(int client) {
database_check(su_ctx); database_check(su_ctx);
if (su_ctx->info->multiuser_mode == MULTIUSER_MODE_USER) { if (su_ctx->info->multiuser_mode == MULTIUSER_MODE_USER) {
snprintf(su_ctx->user.base_path, PATH_MAX, "%s/%d/%s",
USER_DATA_PATH, su_ctx->user.android_user_id, REQUESTOR);
// Check the user installed Magisk Manager // Check the user installed Magisk Manager
xstat(su_ctx->user.base_path, &su_ctx->st); xstat(su_ctx->path.multiuser_path, &su_ctx->st);
if (su_ctx->st.st_gid != su_ctx->st.st_uid) { if (su_ctx->st.st_gid != su_ctx->st.st_uid) {
LOGE("Bad uid/gid %d/%d for Superuser Requestor application", su_ctx->st.st_uid, su_ctx->st.st_gid); LOGE("Bad uid/gid %d/%d for Superuser Requestor application", su_ctx->st.st_uid, su_ctx->st.st_gid);
info->policy = DENY; info->policy = DENY;
@ -183,7 +199,7 @@ void su_daemon_receiver(int client) {
} }
// Handle multiuser denies // Handle multiuser denies
if (su_ctx->user.android_user_id && if (su_ctx->info->uid / 100000 &&
su_ctx->info->multiuser_mode == MULTIUSER_MODE_OWNER_ONLY) { su_ctx->info->multiuser_mode == MULTIUSER_MODE_OWNER_ONLY) {
info->policy = DENY; info->policy = DENY;
su_ctx->notify = 0; su_ctx->notify = 0;