From 257308d5db5e4ab8118945f28d94e41c84381c47 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Tue, 12 Dec 2017 03:03:05 +0800 Subject: [PATCH] Change database location and implementation --- activity.c | 16 +++++---- db.c | 101 ++++++++++++++++++++++------------------------------ su.c | 9 +++-- su.h | 71 +++++++++++++++++------------------- su_daemon.c | 13 ++----- su_socket.c | 2 +- 6 files changed, 91 insertions(+), 121 deletions(-) diff --git a/activity.c b/activity.c index 6071b21ab..29ce86b87 100644 --- a/activity.c +++ b/activity.c @@ -10,9 +10,7 @@ #include #include #include -#include #include -#include #include "magisk.h" #include "su.h" @@ -61,7 +59,10 @@ static int setup_user(struct su_context *ctx, char* user) { void app_send_result(struct su_context *ctx, policy_t policy) { char fromUid[16]; - sprintf(fromUid, "%d", ctx->info->uid); + if (ctx->info->multiuser_mode == MULTIUSER_MODE_OWNER_MANAGED) + sprintf(fromUid, "%d", ctx->info->uid % 100000); + else + sprintf(fromUid, "%d", ctx->info->uid); char toUid[16]; sprintf(toUid, "%d", ctx->to.uid); @@ -73,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->path.pkg_name); + sprintf(activity, ACTION_RESULT, ctx->pkg_name); // Send notice to manager, enable logging char *result_command[] = { @@ -92,6 +93,7 @@ void app_send_result(struct su_context *ctx, policy_t policy) { // Send notice to user (if needed) to create toasts if (notify) { + sprintf(fromUid, "%d", ctx->info->uid); sprintf(user, "%d", notify); char *notify_command[] = { AM_PATH, "broadcast", "-n", @@ -111,13 +113,13 @@ void app_send_request(struct su_context *ctx) { int notify = setup_user(ctx, user); char activity[128]; - sprintf(activity, ACTION_REQUEST, ctx->path.pkg_name); + sprintf(activity, ACTION_REQUEST, ctx->pkg_name); char *request_command[] = { AM_PATH, "start", "-n", activity, "--user", user, - "--es", "socket", ctx->path.sock_path, + "--es", "socket", ctx->sock_path, "--ez", "timeout", notify ? "false" : "true", NULL }; @@ -126,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->path.pkg_name); + sprintf(activity, ACTION_RESULT, ctx->pkg_name); char *notify_command[] = { AM_PATH, "broadcast", "-n", activity, diff --git a/db.c b/db.c index dd392df43..9152265bb 100644 --- a/db.c +++ b/db.c @@ -6,7 +6,6 @@ #include #include -#include #include #include #include @@ -64,7 +63,7 @@ static int strings_callback(void *v, int argc, char **argv, char **azColName) { for (int i = 0; i < argc; ++i) { if (strcmp(azColName[i], "key") == 0) { if (strcmp(argv[i], REQUESTER_ENTRY) == 0) - target = ctx->path.pkg_name; + target = ctx->pkg_name; entry = argv[i]; } else if (strcmp(azColName[i], "value") == 0) { value = argv[i]; @@ -75,92 +74,76 @@ static int strings_callback(void *v, int argc, char **argv, char **azColName) { return 0; } -#define BASE_FMT "/data/user%s/%d" -#define USE_MULTI(info) (info->uid / 100000 != 0 && info->multiuser_mode == MULTIUSER_MODE_USER) - 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->path.pkg_name, "???"); /* bad string so it doesn't exist */ - - // Populate paths - sprintf(ctx->path.base_path, BASE_FMT, "_de", 0); - if (access(ctx->path.base_path, R_OK) == -1) - sprintf(ctx->path.base_path, BASE_FMT, "", 0); - - sprintf(ctx->path.multiuser_path, BASE_FMT, "_de", ctx->info->uid / 100000); - if (access(ctx->path.multiuser_path, R_OK) == -1) - sprintf(ctx->path.multiuser_path, BASE_FMT, "", ctx->info->uid / 100000); + strcpy(ctx->pkg_name, "???"); /* bad string so it doesn't exist */ // Open database - sprintf(buffer, "%s/magisk.db", ctx->path.base_path); - LOGD("su_db: open %s", buffer); - ret = sqlite3_open_v2(buffer, &db, SQLITE_OPEN_READONLY, NULL); + ret = sqlite3_open_v2(DATABASE_PATH, &db, SQLITE_OPEN_READONLY, NULL); if (ret) { - LOGD("sqlite3 open failure: %s\n", sqlite3_errstr(ret)); + LOGE("sqlite3 open failure: %s\n", sqlite3_errstr(ret)); sqlite3_close(db); goto stat_requester; } - // Check multiuser mode settings - sprintf(buffer, "SELECT key, value FROM settings WHERE key='%s'", MULTIUSER_MODE_ENTRY); - sqlite3_exec(db, buffer, settings_callback, ctx, &err); - if (err != NULL) - LOGE("sqlite3_exec: %s\n", err); - err = NULL; - - // Open database based on multiuser settings - if (USE_MULTI(ctx->info)) { - sqlite3_close(db); - sprintf(buffer, "%s/magisk.db", ctx->path.multiuser_path); - LOGD("su_db: open %s", buffer); - ret = sqlite3_open_v2(buffer, &db, SQLITE_OPEN_READONLY, NULL); - if (ret) { - LOGD("sqlite3 open failure: %s\n", sqlite3_errstr(ret)); - sqlite3_close(db); - goto stat_requester; - } - } - - // Read PKG name from DB - strcpy(buffer, "SELECT key, value FROM strings"); - sqlite3_exec(db, buffer, strings_callback, ctx, &err); - if (err != NULL) - LOGE("sqlite3_exec: %s\n", err); - err = NULL; - - // Query for policy - sprintf(buffer, "SELECT policy, until FROM policies WHERE uid=%d", ctx->info->uid % 100000); - sqlite3_exec(db, buffer, policy_callback, ctx, &err); - if (err != NULL) + // 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 - sprintf(buffer, "SELECT key, value FROM settings WHERE key!='%s'", MULTIUSER_MODE_ENTRY); - sqlite3_exec(db, buffer, settings_callback, ctx, &err); - if (err != NULL) + 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 orignal name - sprintf(buffer, "%s/%s", USE_MULTI(ctx->info) ? ctx->path.multiuser_path : ctx->path.base_path, JAVA_PACKAGE_NAME); - if (stat(buffer, &ctx->st) == -1) { - sprintf(buffer, "%s/%s", USE_MULTI(ctx->info) ? ctx->path.multiuser_path : ctx->path.base_path, ctx->path.pkg_name); + // We prefer the original name + sprintf(buffer, "%s/0/" JAVA_PACKAGE_NAME, base); + if (stat(buffer, &ctx->st) == 0) { + strcpy(ctx->pkg_name, JAVA_PACKAGE_NAME); + } else { + sprintf(buffer, "%s/0/%s", base, ctx->pkg_name); if (stat(buffer, &ctx->st) == -1) { LOGE("su: cannot find requester"); ctx->info->policy = DENY; ctx->notify = 0; } - } else { - strcpy(ctx->path.pkg_name, JAVA_PACKAGE_NAME); } } diff --git a/su.c b/su.c index afd3a3b9a..a12fdf55a 100644 --- a/su.c +++ b/su.c @@ -26,7 +26,6 @@ #include "magisk.h" #include "utils.h" -#include "resetprop.h" #include "su.h" struct su_context *su_ctx; @@ -148,9 +147,9 @@ static __attribute__ ((noreturn)) void deny() { } static void socket_cleanup() { - if (su_ctx && su_ctx->path.sock_path[0]) { - unlink(su_ctx->path.sock_path); - su_ctx->path.sock_path[0] = 0; + if (su_ctx && su_ctx->sock_path[0]) { + unlink(su_ctx->sock_path); + su_ctx->sock_path[0] = 0; } } @@ -352,7 +351,7 @@ int su_daemon_main(int argc, char **argv) { // New request or no db exist, notify user for response if (su_ctx->info->policy == QUERY) { - socket_serv_fd = socket_create_temp(su_ctx->path.sock_path, sizeof(su_ctx->path.sock_path)); + socket_serv_fd = socket_create_temp(su_ctx->sock_path, sizeof(su_ctx->sock_path)); setup_sighandlers(cleanup_signal); // Start activity diff --git a/su.h b/su.h index ab9782971..29b6d220f 100644 --- a/su.h +++ b/su.h @@ -41,57 +41,52 @@ #define REQUESTOR_PREFIX JAVA_PACKAGE_NAME ".superuser" #define DEFAULT_SHELL "/system/bin/sh" +#define DATABASE_PATH "/data/adb/magisk.db" typedef enum { - QUERY = 0, - DENY = 1, - ALLOW = 2, + QUERY = 0, + DENY = 1, + ALLOW = 2, } policy_t; struct su_info { - unsigned uid; /* Key to find su_info */ - pthread_mutex_t lock; /* Internal lock */ - int count; /* Just a count for debugging purpose */ + 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; - int multiuser_mode; - int root_access; - int mnt_ns; + /* These values should be guarded with internal lock */ + policy_t policy; + int multiuser_mode; + int root_access; + int mnt_ns; - /* These should be guarded with global list lock */ - struct list_head pos; - int ref; - int clock; + /* These should be guarded with global list lock */ + struct list_head pos; + int ref; + int clock; }; struct su_request { - unsigned uid; - int login; - int keepenv; - char *shell; - char *command; - char **argv; - int argc; -}; - -struct su_path { - char base_path[PATH_MAX]; - char multiuser_path[PATH_MAX]; - char pkg_name[PATH_MAX]; - char sock_path[PATH_MAX]; + unsigned uid; + int login; + int keepenv; + char *shell; + char *command; + char **argv; + int argc; }; struct su_context { - struct su_info *info; - struct su_request to; - struct su_path path; - pid_t pid; - int notify; - mode_t umask; - char *cwd; - struct stat st; - int pipefd[2]; + struct su_info *info; + struct su_request to; + char pkg_name[PATH_MAX]; + char sock_path[PATH_MAX]; + pid_t pid; + int notify; + mode_t umask; + char *cwd; + struct stat st; + int pipefd[2]; }; extern struct su_context *su_ctx; diff --git a/su_daemon.c b/su_daemon.c index 3f6cfb6a0..be4736eb0 100644 --- a/su_daemon.c +++ b/su_daemon.c @@ -1,4 +1,4 @@ -/* su_client.c - The entrypoint for su, connect to daemon and send correct info +/* su_daemon.c - The entrypoint for su, connect to daemon and send correct info */ #define _GNU_SOURCE @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -17,7 +16,6 @@ #include "magisk.h" #include "daemon.h" -#include "resetprop.h" #include "utils.h" #include "su.h" #include "pts.h" @@ -104,7 +102,7 @@ void su_daemon_receiver(int client) { xpthread_create(&su_collector, NULL, collector, NULL); } - // Get client credntial + // Get client credential struct ucred credential; get_client_cred(client, &credential); @@ -157,13 +155,6 @@ void su_daemon_receiver(int client) { // Get data from database database_check(&ctx); - // Handle multiuser denies - if (info->uid / 100000 && - info->multiuser_mode == MULTIUSER_MODE_OWNER_ONLY) { - info->policy = DENY; - ctx.notify = 0; - } - // Check requester if (info->policy == QUERY) { if (ctx.st.st_gid != ctx.st.st_uid) { diff --git a/su_socket.c b/su_socket.c index 755668fde..cc6e1261f 100644 --- a/su_socket.c +++ b/su_socket.c @@ -42,7 +42,7 @@ int socket_create_temp(char *path, size_t len) { xlisten(fd, 1); // Set attributes so requester can access it - setfilecon(path, "u:object_r:su_device:s0"); + setfilecon(path, "u:object_r:su_file:s0"); chown(path, su_ctx->st.st_uid, su_ctx->st.st_gid); return fd;