From f2064a84ed6f68839addabb0b7cb724bba941fe8 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Wed, 13 Jun 2018 04:34:05 +0800 Subject: [PATCH] Move database logic outside of MagiskSU --- native/jni/Android.mk | 2 +- native/jni/core/db.c | 152 ++++++++++++++++++++++++++++++++++++ native/jni/include/db.h | 122 +++++++++++++++++++++++++++++ native/jni/include/magisk.h | 1 + native/jni/su | 2 +- 5 files changed, 277 insertions(+), 2 deletions(-) create mode 100644 native/jni/core/db.c create mode 100644 native/jni/include/db.h diff --git a/native/jni/Android.mk b/native/jni/Android.mk index 90d7bc63e..133e1747d 100644 --- a/native/jni/Android.mk +++ b/native/jni/Android.mk @@ -43,6 +43,7 @@ LOCAL_SRC_FILES := \ core/log_monitor.c \ core/bootstages.c \ core/socket.c \ + core/db.c \ magiskhide/magiskhide.c \ magiskhide/proc_monitor.c \ magiskhide/hide_utils.c \ @@ -51,7 +52,6 @@ LOCAL_SRC_FILES := \ resetprop/system_properties.cpp \ su/su.c \ su/activity.c \ - su/db.c \ su/pts.c \ su/su_daemon.c \ su/su_socket.c \ diff --git a/native/jni/core/db.c b/native/jni/core/db.c new file mode 100644 index 000000000..9db9027c6 --- /dev/null +++ b/native/jni/core/db.c @@ -0,0 +1,152 @@ +#include +#include +#include +#include +#include +#include + +#include "magisk.h" +#include "db.h" + +void INIT_DB_STRINGS(struct db_strings *str) { + for (int i = 0; i < DB_STRING_NUM; ++i) + str->s[i][0] = '\0'; +} + +static int policy_cb(void *v, int col_num, char **data, char **col_name) { + struct su_access *su = v; + for (int i = 0; i < col_num; i++) { + if (strcmp(col_name[i], "policy") == 0) + su->policy = (policy_t) atoi(data[i]); + else if (strcmp(col_name[i], "logging") == 0) + su->log = atoi(data[i]); + else if (strcmp(col_name[i], "notification") == 0) + su->notify = atoi(data[i]); + } + LOGD("su_db: query policy=[%d] log=[%d] notify=[%d]\n", su->policy, su->log, su->notify); + return 0; +} + +static int settings_cb(void *v, int col_num, char **data, char **col_name) { + struct db_settings *dbs = v; + int key = -1, value; + for (int i = 0; i < col_num; ++i) { + if (strcmp(col_name[i], "key") == 0) { + for (int k = 0; k < DB_SETTINGS_NUM; ++k) { + if (strcmp(data[i], DB_SETTING_KEYS[k]) == 0) + key = k; + } + } else if (strcmp(col_name[i], "value") == 0) { + value = atoi(data[i]); + } + } + if (key >= 0) { + dbs->v[key] = value; + LOGD("su_db: query %s=[%d]\n", DB_SETTING_KEYS[key], value); + } + return 0; +} + +static int strings_cb(void *v, int col_num, char **data, char **col_name) { + struct db_strings *dbs = v; + int key = -1; + char *value; + for (int i = 0; i < col_num; ++i) { + if (strcmp(col_name[i], "key") == 0) { + for (int k = 0; k < DB_STRING_NUM; ++k) { + if (strcmp(data[i], DB_STRING_KEYS[k]) == 0) + key = k; + } + } else if (strcmp(col_name[i], "value") == 0) { + value = data[i]; + } + } + if (key >= 0) { + strcpy(dbs->s[key], value); + LOGD("su_db: query %s=[%s]\n", DB_SETTING_KEYS[key], value); + } + return 0; +} + +sqlite3 *get_magiskdb() { + sqlite3 *db = NULL; + if (access(MAGISKDB, R_OK) == 0) { + // Open database + int ret = sqlite3_open_v2(MAGISKDB, &db, SQLITE_OPEN_READONLY, NULL); + if (ret) { + LOGE("sqlite3 open failure: %s\n", sqlite3_errstr(ret)); + sqlite3_close(db); + db = NULL; + } + } + return db; +} + +int get_db_settings(sqlite3 *db, int key, struct db_settings *dbs) { + char *err; + if (key > 0) { + char query[128]; + sprintf(query, "SELECT key, value FROM settings WHERE key=%d", key); + sqlite3_exec(db, query, settings_cb, dbs, &err); + } else { + sqlite3_exec(db, "SELECT key, value FROM settings", settings_cb, dbs, &err); + } + if (err) { + LOGE("sqlite3_exec: %s\n", err); + return 1; + } + return 0; +} + +int get_db_strings(sqlite3 *db, int key, struct db_strings *str) { + char *err; + if (key > 0) { + char query[128]; + sprintf(query, "SELECT key, value FROM strings WHERE key=%d", key); + sqlite3_exec(db, query, strings_cb, str, &err); + } else { + sqlite3_exec(db, "SELECT key, value FROM strings", strings_cb, str, &err); + } + if (err) { + LOGE("sqlite3_exec: %s\n", err); + return 1; + } + return 0; +} + +int get_uid_policy(sqlite3 *db, int uid, struct su_access *su) { + char query[256], *err; + sprintf(query, "SELECT policy, logging, notification FROM policies " + "WHERE uid=%d AND (until=0 OR until>%li)", uid, time(NULL)); + sqlite3_exec(db, query, policy_cb, su, &err); + if (err) { + LOGE("sqlite3_exec: %s\n", err); + return 1; + } + return 0; +} + +int validate_manager(char *pkg, int userid, struct stat *st) { + if (st == NULL) { + struct stat stat; + st = &stat; + } + // Prefer DE storage + const char *base = access("/data/user_de", F_OK) == 0 ? "/data/user_de" : "/data/user"; + char app_path[128]; + sprintf(app_path, "%s/%d/%s", base, userid, pkg[0] ? pkg : "xxx"); + if (stat(app_path, st)) { + // Check the official package name + sprintf(app_path, "%s/%d/"JAVA_PACKAGE_NAME, base, userid); + if (stat(app_path, st)) { + LOGE("su: cannot find manager"); + memset(st, 0, sizeof(*st)); + pkg[0] = '\0'; + return 1; + } else { + // Switch to official package if exists + strcpy(pkg, JAVA_PACKAGE_NAME); + } + } + return 0; +} diff --git a/native/jni/include/db.h b/native/jni/include/db.h new file mode 100644 index 000000000..a3a1f880e --- /dev/null +++ b/native/jni/include/db.h @@ -0,0 +1,122 @@ +#ifndef DB_H +#define DB_H + +#include + +/*************** + * DB Settings * + ***************/ + +#define DB_SETTING_KEYS ((char *[]) { \ +"root_access", \ +"multiuser_mode", \ +"mnt_ns" \ +}) + +#define DB_SETTINGS_NUM (sizeof(DB_SETTING_KEYS) / sizeof(char*)) + +// Settings indices +enum { + ROOT_ACCESS = 0, + SU_MULTIUSER_MODE, + SU_MNT_NS +}; + +// Values for root_access +enum { + ROOT_ACCESS_DISABLED = 0, + ROOT_ACCESS_APPS_ONLY, + ROOT_ACCESS_ADB_ONLY, + ROOT_ACCESS_APPS_AND_ADB +}; + +// Values for multiuser_mode +enum { + MULTIUSER_MODE_OWNER_ONLY = 0, + MULTIUSER_MODE_OWNER_MANAGED, + MULTIUSER_MODE_USER +}; + +// Values for mnt_ns +enum { + NAMESPACE_MODE_GLOBAL = 0, + NAMESPACE_MODE_REQUESTER, + NAMESPACE_MODE_ISOLATE +}; + +struct db_settings { + int v[DB_SETTINGS_NUM]; +}; + +#define DEFAULT_DB_SETTINGS (struct db_settings) { .v = {\ +ROOT_ACCESS_APPS_AND_ADB, \ +MULTIUSER_MODE_OWNER_ONLY, \ +NAMESPACE_MODE_REQUESTER \ +}} + +/************** + * DB Strings * + **************/ + +#define DB_STRING_KEYS ((char *[]) { \ +"requester" \ +}) + +#define DB_STRING_NUM (sizeof(DB_STRING_KEYS) / sizeof(char*)) + +// Strings indices +enum { + SU_REQUESTER = 0 +}; + +struct db_strings { + char s[DB_STRING_NUM][128]; +}; + +void INIT_DB_STRINGS(struct db_strings *str); + +/************* + * SU Access * + *************/ + +typedef enum { + QUERY = 0, + DENY = 1, + ALLOW = 2, +} policy_t; + +struct su_access { + policy_t policy; + int log; + int notify; +}; + +#define DEFAULT_SU_ACCESS (struct su_access) { \ +.policy = QUERY, \ +.log = 1, \ +.notify = 1 \ +} + +#define SILENT_SU_ACCESS (struct su_access) { \ +.policy = ALLOW, \ +.log = 0, \ +.notify = 0 \ +} + +#define NO_SU_ACCESS (struct su_access) { \ +.policy = DENY, \ +.log = 0, \ +.notify = 0 \ +} + +/******************** + * Public Functions * + ********************/ + +sqlite3 *get_magiskdb(); +int get_db_settings(sqlite3 *db, int key, struct db_settings *dbs); +int get_db_strings(sqlite3 *db, int key, struct db_strings *str); +int get_uid_policy(sqlite3 *db, int uid, struct su_access *su); +int validate_manager(char *pkg, int userid, struct stat *st); + +#endif //DB_H diff --git a/native/jni/include/magisk.h b/native/jni/include/magisk.h index 098d49729..7607858e5 100644 --- a/native/jni/include/magisk.h +++ b/native/jni/include/magisk.h @@ -8,6 +8,7 @@ #define MAGISK_VER_STR xstr(MAGISK_VERSION) ":MAGISK" #define SOCKET_NAME "d30138f2310a9fb9c54a3e0c21f58591" +#define JAVA_PACKAGE_NAME "com.topjohnwu.magisk" #ifndef ARG_MAX #define ARG_MAX 4096 diff --git a/native/jni/su b/native/jni/su index 42eab87ed..a56fb9d86 160000 --- a/native/jni/su +++ b/native/jni/su @@ -1 +1 @@ -Subproject commit 42eab87edc319747a1b04cd6df2972a138efc1d1 +Subproject commit a56fb9d869dd809c7339119459bfdc88c2dd8404