diff --git a/activity.c b/activity.c index 4af414122..507d197fc 100644 --- a/activity.c +++ b/activity.c @@ -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_MANAGED: sprintf(user, "%d", 0); - return ctx->user.android_user_id; + return ctx->info->uid / 100000; case MULTIUSER_MODE_USER: - sprintf(user, "%d", ctx->user.android_user_id); + sprintf(user, "%d", ctx->info->uid / 100000); break; } return 0; @@ -135,7 +135,7 @@ void app_send_request(struct su_context *ctx) { user, "--es", "socket", - ctx->sock_path, + ctx->path.sock_path, "--ez", "timeout", notify ? "false" : "true", diff --git a/db.c b/db.c index 0b284beec..1f65a3cca 100644 --- a/db.c +++ b/db.c @@ -69,13 +69,8 @@ void database_check(struct su_context *ctx) { ctx->info->mnt_ns = NAMESPACE_MODE_REQUESTER; 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 - 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) { LOGD("sqlite3 open failure: %s\n", sqlite3_errstr(ret)); sqlite3_close(db); @@ -88,14 +83,11 @@ void database_check(struct su_context *ctx) { 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); - // Check if file is readable - if (access(ctx->user.database_path, R_OK) == -1) - return; // 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) { LOGD("sqlite3 open failure: %s\n", sqlite3_errstr(ret)); sqlite3_close(db); diff --git a/su.c b/su.c index 44dd8fc42..24d643078 100644 --- a/su.c +++ b/su.c @@ -148,9 +148,9 @@ 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; + if (su_ctx && su_ctx->path.sock_path[0]) { + unlink(su_ctx->path.sock_path); + 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)) 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); // Start activity diff --git a/su.h b/su.h index 8f3edb268..731100431 100644 --- a/su.h +++ b/su.h @@ -34,9 +34,6 @@ // DO NOT CHANGE LINE BELOW, java package name will always be the same #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 // must be changed to correspond to the new APK package name // See the two Android.mk files for more details. @@ -45,10 +42,6 @@ // with classes in another package. #define REQUESTOR_PREFIX JAVA_PACKAGE_NAME ".superuser" #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" @@ -85,31 +78,23 @@ struct su_request { int argc; }; -struct su_user_info { - // 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. +struct su_path { char base_path[PATH_MAX]; - // path to su database. this is populated according - // to the multiuser mode. - char database_path[PATH_MAX]; + char base_db[PATH_MAX]; + char multiuser_path[PATH_MAX]; + char multiuser_db[PATH_MAX]; + char sock_path[PATH_MAX]; }; struct su_context { struct su_info *info; struct su_request to; - struct su_user_info user; + struct su_path path; pid_t pid; int notify; mode_t umask; char *cwd; struct stat st; - char sock_path[PATH_MAX]; }; extern struct su_context *su_ctx; diff --git a/su_daemon.c b/su_daemon.c index 0fa10dff5..a0f34d765 100644 --- a/su_daemon.c +++ b/su_daemon.c @@ -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) { LOGD("su: request from client: %d\n", client); @@ -144,20 +166,16 @@ void su_daemon_receiver(int client) { .shell = DEFAULT_SHELL, .command = NULL, }, - .user = { - .android_user_id = info->uid / 100000, - }, .pid = credential.pid, .umask = 022, .notify = new_request, }; su_ctx = &ctx; - snprintf(su_ctx->user.database_path, PATH_MAX, "%s/%d/%s", - USER_DATA_PATH, su_ctx->user.android_user_id, REQUESTOR_DATABASE_PATH); + populate_paths(su_ctx); // 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) { LOGE("Bad uid/gid %d/%d for Superuser Requestor application", su_ctx->st.st_uid, su_ctx->st.st_gid); info->policy = DENY; @@ -172,10 +190,8 @@ void su_daemon_receiver(int client) { database_check(su_ctx); 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 - 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) { LOGE("Bad uid/gid %d/%d for Superuser Requestor application", su_ctx->st.st_uid, su_ctx->st.st_gid); info->policy = DENY; @@ -183,7 +199,7 @@ void su_daemon_receiver(int client) { } // 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) { info->policy = DENY; su_ctx->notify = 0;