Support changing requester in DB
This commit is contained in:
parent
6b7b71b1f8
commit
84ca8e1f3e
88
activity.c
88
activity.c
@ -18,9 +18,8 @@
|
|||||||
#include "su.h"
|
#include "su.h"
|
||||||
|
|
||||||
/* intent actions */
|
/* intent actions */
|
||||||
#define ACTION_REQUEST "start", "-n", REQUESTOR "/" REQUESTOR_PREFIX ".RequestActivity"
|
#define ACTION_REQUEST "%s/" REQUESTOR_PREFIX ".RequestActivity"
|
||||||
#define ACTION_NOTIFY "start", "-n", REQUESTOR "/" REQUESTOR_PREFIX ".NotifyActivity"
|
#define ACTION_RESULT "%s/" REQUESTOR_PREFIX ".SuReceiver"
|
||||||
#define ACTION_RESULT "broadcast", "-n", REQUESTOR "/" REQUESTOR_PREFIX ".SuReceiver"
|
|
||||||
|
|
||||||
#define AM_PATH "/system/bin/app_process", "/system/bin", "com.android.commands.am.Am"
|
#define AM_PATH "/system/bin/app_process", "/system/bin", "com.android.commands.am.Am"
|
||||||
|
|
||||||
@ -73,30 +72,20 @@ void app_send_result(struct su_context *ctx, policy_t policy) {
|
|||||||
char user[16];
|
char user[16];
|
||||||
int notify = setup_user(ctx, user);
|
int notify = setup_user(ctx, user);
|
||||||
|
|
||||||
|
char activity[128];
|
||||||
|
sprintf(activity, ACTION_RESULT, ctx->path.pkg_name);
|
||||||
|
|
||||||
// Send notice to manager, enable logging
|
// Send notice to manager, enable logging
|
||||||
char *result_command[] = {
|
char *result_command[] = {
|
||||||
AM_PATH,
|
AM_PATH, "broadcast", "-n",
|
||||||
ACTION_RESULT,
|
activity,
|
||||||
"--user",
|
"--user", user,
|
||||||
user,
|
"--ei", "mode", "0",
|
||||||
"--ei",
|
"--ei", "from.uid", fromUid,
|
||||||
"mode",
|
"--ei", "to.uid", toUid,
|
||||||
"0",
|
"--ei", "pid", pid,
|
||||||
"--ei",
|
"--es", "command", get_command(&ctx->to),
|
||||||
"from.uid",
|
"--es", "action", policy == ALLOW ? "allow" : "deny",
|
||||||
fromUid,
|
|
||||||
"--ei",
|
|
||||||
"to.uid",
|
|
||||||
toUid,
|
|
||||||
"--ei",
|
|
||||||
"pid",
|
|
||||||
pid,
|
|
||||||
"--es",
|
|
||||||
"command",
|
|
||||||
get_command(&ctx->to),
|
|
||||||
"--es",
|
|
||||||
"action",
|
|
||||||
policy == ALLOW ? "allow" : "deny",
|
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
silent_run(result_command);
|
silent_run(result_command);
|
||||||
@ -105,19 +94,12 @@ void app_send_result(struct su_context *ctx, policy_t policy) {
|
|||||||
if (notify) {
|
if (notify) {
|
||||||
sprintf(user, "%d", notify);
|
sprintf(user, "%d", notify);
|
||||||
char *notify_command[] = {
|
char *notify_command[] = {
|
||||||
AM_PATH,
|
AM_PATH, "broadcast", "-n",
|
||||||
ACTION_RESULT,
|
activity,
|
||||||
"--user",
|
"--user", user,
|
||||||
user,
|
"--ei", "mode", "1",
|
||||||
"--ei",
|
"--ei", "from.uid", fromUid,
|
||||||
"mode",
|
"--es", "action", policy == ALLOW ? "allow" : "deny",
|
||||||
"1",
|
|
||||||
"--ei",
|
|
||||||
"from.uid",
|
|
||||||
fromUid,
|
|
||||||
"--es",
|
|
||||||
"action",
|
|
||||||
policy == ALLOW ? "allow" : "deny",
|
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
silent_run(notify_command);
|
silent_run(notify_command);
|
||||||
@ -128,17 +110,15 @@ void app_send_request(struct su_context *ctx) {
|
|||||||
char user[16];
|
char user[16];
|
||||||
int notify = setup_user(ctx, user);
|
int notify = setup_user(ctx, user);
|
||||||
|
|
||||||
|
char activity[128];
|
||||||
|
sprintf(activity, ACTION_REQUEST, ctx->path.pkg_name);
|
||||||
|
|
||||||
char *request_command[] = {
|
char *request_command[] = {
|
||||||
AM_PATH,
|
AM_PATH, "start", "-n",
|
||||||
ACTION_REQUEST,
|
activity,
|
||||||
"--user",
|
"--user", user,
|
||||||
user,
|
"--es", "socket", ctx->path.sock_path,
|
||||||
"--es",
|
"--ez", "timeout", notify ? "false" : "true",
|
||||||
"socket",
|
|
||||||
ctx->path.sock_path,
|
|
||||||
"--ez",
|
|
||||||
"timeout",
|
|
||||||
notify ? "false" : "true",
|
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
silent_run(request_command);
|
silent_run(request_command);
|
||||||
@ -146,14 +126,12 @@ void app_send_request(struct su_context *ctx) {
|
|||||||
// Send notice to user to tell them root is managed by owner
|
// Send notice to user to tell them root is managed by owner
|
||||||
if (notify) {
|
if (notify) {
|
||||||
sprintf(user, "%d", notify);
|
sprintf(user, "%d", notify);
|
||||||
|
sprintf(activity, ACTION_RESULT, ctx->path.pkg_name);
|
||||||
char *notify_command[] = {
|
char *notify_command[] = {
|
||||||
AM_PATH,
|
AM_PATH, "broadcast", "-n",
|
||||||
ACTION_RESULT,
|
activity,
|
||||||
"--user",
|
"--user", user,
|
||||||
user,
|
"--ei", "mode", "2",
|
||||||
"--ei",
|
|
||||||
"mode",
|
|
||||||
"2",
|
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
silent_run(notify_command);
|
silent_run(notify_command);
|
||||||
|
95
db.c
95
db.c
@ -58,60 +58,109 @@ static int settings_callback(void *v, int argc, char **argv, char **azColName) {
|
|||||||
return 0;
|
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->path.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#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) {
|
void database_check(struct su_context *ctx) {
|
||||||
sqlite3 *db = NULL;
|
sqlite3 *db = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
char query[512], *err = NULL;
|
char buffer[PATH_MAX], *err = NULL;
|
||||||
|
|
||||||
// Set default values
|
// Set default values
|
||||||
ctx->info->root_access = ROOT_ACCESS_APPS_AND_ADB;
|
ctx->info->root_access = ROOT_ACCESS_APPS_AND_ADB;
|
||||||
ctx->info->multiuser_mode = MULTIUSER_MODE_OWNER_ONLY;
|
ctx->info->multiuser_mode = MULTIUSER_MODE_OWNER_ONLY;
|
||||||
ctx->info->mnt_ns = NAMESPACE_MODE_REQUESTER;
|
ctx->info->mnt_ns = NAMESPACE_MODE_REQUESTER;
|
||||||
ctx->info->policy = QUERY;
|
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);
|
||||||
|
|
||||||
// Open database
|
// Open database
|
||||||
ret = sqlite3_open_v2(ctx->path.base_db, &db, SQLITE_OPEN_READONLY, NULL);
|
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);
|
||||||
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);
|
||||||
return;
|
goto stat_requester;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check multiuser mode settings
|
// Check multiuser mode settings
|
||||||
snprintf(query, sizeof(query), "SELECT key, value FROM settings WHERE key='%s'", MULTIUSER_MODE_ENTRY);
|
sprintf(buffer, "SELECT key, value FROM settings WHERE key='%s'", MULTIUSER_MODE_ENTRY);
|
||||||
sqlite3_exec(db, query, settings_callback, ctx, &err);
|
sqlite3_exec(db, buffer, settings_callback, ctx, &err);
|
||||||
|
if (err != NULL)
|
||||||
|
LOGE("sqlite3_exec: %s\n", err);
|
||||||
err = NULL;
|
err = NULL;
|
||||||
|
|
||||||
if (ctx->info->uid / 100000 != 0 && ctx->info->multiuser_mode == MULTIUSER_MODE_USER) {
|
// Open database based on multiuser settings
|
||||||
|
if (USE_MULTI(ctx->info)) {
|
||||||
sqlite3_close(db);
|
sqlite3_close(db);
|
||||||
|
sprintf(buffer, "%s/magisk.db", ctx->path.multiuser_path);
|
||||||
// Open database
|
LOGD("su_db: open %s", buffer);
|
||||||
ret = sqlite3_open_v2(ctx->path.multiuser_db, &db, SQLITE_OPEN_READONLY, NULL);
|
ret = sqlite3_open_v2(buffer, &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);
|
||||||
return;
|
goto stat_requester;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query for policy
|
// Read PKG name from DB
|
||||||
snprintf(query, sizeof(query), "SELECT policy, until FROM policies WHERE uid=%d", ctx->info->uid % 100000);
|
strcpy(buffer, "SELECT key, value FROM strings");
|
||||||
sqlite3_exec(db, query, policy_callback, ctx, &err);
|
sqlite3_exec(db, buffer, strings_callback, ctx, &err);
|
||||||
if (err != NULL) {
|
if (err != NULL)
|
||||||
LOGE("sqlite3_exec: %s\n", err);
|
LOGE("sqlite3_exec: %s\n", err);
|
||||||
return;
|
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)
|
||||||
|
LOGE("sqlite3_exec: %s\n", err);
|
||||||
err = NULL;
|
err = NULL;
|
||||||
|
|
||||||
// Query for settings
|
// Query for settings
|
||||||
snprintf(query, sizeof(query), "SELECT key, value FROM settings WHERE key!='%s'", MULTIUSER_MODE_ENTRY);
|
sprintf(buffer, "SELECT key, value FROM settings WHERE key!='%s'", MULTIUSER_MODE_ENTRY);
|
||||||
sqlite3_exec(db, query, settings_callback, ctx, &err);
|
sqlite3_exec(db, buffer, settings_callback, ctx, &err);
|
||||||
if (err != NULL) {
|
if (err != NULL)
|
||||||
LOGE("sqlite3_exec: %s\n", err);
|
LOGE("sqlite3_exec: %s\n", err);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sqlite3_close(db);
|
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);
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
25
su.c
25
su.c
@ -162,9 +162,9 @@ static void cleanup_signal(int sig) {
|
|||||||
__attribute__ ((noreturn)) void exit2(int status) {
|
__attribute__ ((noreturn)) void exit2(int status) {
|
||||||
// Handle the pipe, or the daemon will get stuck
|
// Handle the pipe, or the daemon will get stuck
|
||||||
if (su_ctx->info->policy == QUERY) {
|
if (su_ctx->info->policy == QUERY) {
|
||||||
xwrite(pipefd[1], &su_ctx->info->policy, sizeof(su_ctx->info->policy));
|
xwrite(su_ctx->pipefd[1], &su_ctx->info->policy, sizeof(su_ctx->info->policy));
|
||||||
close(pipefd[0]);
|
close(su_ctx->pipefd[0]);
|
||||||
close(pipefd[1]);
|
close(su_ctx->pipefd[1]);
|
||||||
}
|
}
|
||||||
exit(status);
|
exit(status);
|
||||||
}
|
}
|
||||||
@ -352,19 +352,6 @@ int su_daemon_main(int argc, char **argv) {
|
|||||||
|
|
||||||
// New request or no db exist, notify user for response
|
// New request or no db exist, notify user for response
|
||||||
if (su_ctx->info->policy == QUERY) {
|
if (su_ctx->info->policy == QUERY) {
|
||||||
mkdir(REQUESTOR_CACHE_PATH, 0770);
|
|
||||||
if (chown(REQUESTOR_CACHE_PATH, su_ctx->st.st_uid, su_ctx->st.st_gid))
|
|
||||||
PLOGE("chown (%s, %u, %u)", REQUESTOR_CACHE_PATH, su_ctx->st.st_uid, su_ctx->st.st_gid);
|
|
||||||
|
|
||||||
if (setgroups(0, NULL))
|
|
||||||
PLOGE("setgroups");
|
|
||||||
|
|
||||||
if (setegid(su_ctx->st.st_gid))
|
|
||||||
PLOGE("setegid (%u)", su_ctx->st.st_gid);
|
|
||||||
|
|
||||||
if (seteuid(su_ctx->st.st_uid))
|
|
||||||
PLOGE("seteuid (%u)", su_ctx->st.st_uid);
|
|
||||||
|
|
||||||
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->path.sock_path, sizeof(su_ctx->path.sock_path));
|
||||||
setup_sighandlers(cleanup_signal);
|
setup_sighandlers(cleanup_signal);
|
||||||
|
|
||||||
@ -387,9 +374,9 @@ int su_daemon_main(int argc, char **argv) {
|
|||||||
su_ctx->info->policy = DENY;
|
su_ctx->info->policy = DENY;
|
||||||
|
|
||||||
// Report the policy to main daemon
|
// Report the policy to main daemon
|
||||||
xwrite(pipefd[1], &su_ctx->info->policy, sizeof(su_ctx->info->policy));
|
xwrite(su_ctx->pipefd[1], &su_ctx->info->policy, sizeof(su_ctx->info->policy));
|
||||||
close(pipefd[0]);
|
close(su_ctx->pipefd[0]);
|
||||||
close(pipefd[1]);
|
close(su_ctx->pipefd[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (su_ctx->info->policy == ALLOW)
|
if (su_ctx->info->policy == ALLOW)
|
||||||
|
14
su.h
14
su.h
@ -31,17 +31,14 @@
|
|||||||
#define NAMESPACE_MODE_REQUESTER 1
|
#define NAMESPACE_MODE_REQUESTER 1
|
||||||
#define NAMESPACE_MODE_ISOLATE 2
|
#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
|
// 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"
|
||||||
|
|
||||||
// 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.
|
|
||||||
#define REQUESTOR JAVA_PACKAGE_NAME
|
|
||||||
// This is used if wrapping the fragment classes and activities
|
// This is used if wrapping the fragment classes and activities
|
||||||
// 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 DEFAULT_SHELL "/system/bin/sh"
|
#define DEFAULT_SHELL "/system/bin/sh"
|
||||||
|
|
||||||
@ -80,9 +77,8 @@ struct su_request {
|
|||||||
|
|
||||||
struct su_path {
|
struct su_path {
|
||||||
char base_path[PATH_MAX];
|
char base_path[PATH_MAX];
|
||||||
char base_db[PATH_MAX];
|
|
||||||
char multiuser_path[PATH_MAX];
|
char multiuser_path[PATH_MAX];
|
||||||
char multiuser_db[PATH_MAX];
|
char pkg_name[PATH_MAX];
|
||||||
char sock_path[PATH_MAX];
|
char sock_path[PATH_MAX];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -95,10 +91,10 @@ struct su_context {
|
|||||||
mode_t umask;
|
mode_t umask;
|
||||||
char *cwd;
|
char *cwd;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
int pipefd[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct su_context *su_ctx;
|
extern struct su_context *su_ctx;
|
||||||
extern int pipefd[2];
|
|
||||||
|
|
||||||
// su.c
|
// su.c
|
||||||
|
|
||||||
|
83
su_daemon.c
83
su_daemon.c
@ -90,28 +90,6 @@ 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);
|
||||||
|
|
||||||
@ -170,16 +148,6 @@ void su_daemon_receiver(int client) {
|
|||||||
.umask = 022,
|
.umask = 022,
|
||||||
.notify = new_request,
|
.notify = new_request,
|
||||||
};
|
};
|
||||||
su_ctx = &ctx;
|
|
||||||
|
|
||||||
populate_paths(su_ctx);
|
|
||||||
|
|
||||||
// Check main Magisk Manager
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lock before the policy is determined
|
// Lock before the policy is determined
|
||||||
LOCK_UID();
|
LOCK_UID();
|
||||||
@ -187,41 +155,38 @@ void su_daemon_receiver(int client) {
|
|||||||
// Not cached, do the checks
|
// Not cached, do the checks
|
||||||
if (info->policy == QUERY) {
|
if (info->policy == QUERY) {
|
||||||
// Get data from database
|
// Get data from database
|
||||||
database_check(su_ctx);
|
database_check(&ctx);
|
||||||
|
|
||||||
if (su_ctx->info->multiuser_mode == MULTIUSER_MODE_USER) {
|
|
||||||
// Check the user installed Magisk Manager
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle multiuser denies
|
// Handle multiuser denies
|
||||||
if (su_ctx->info->uid / 100000 &&
|
if (info->uid / 100000 &&
|
||||||
su_ctx->info->multiuser_mode == MULTIUSER_MODE_OWNER_ONLY) {
|
info->multiuser_mode == MULTIUSER_MODE_OWNER_ONLY) {
|
||||||
info->policy = DENY;
|
info->policy = DENY;
|
||||||
su_ctx->notify = 0;
|
ctx.notify = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// always allow if this is Magisk Manager
|
// Check requester
|
||||||
if (info->policy == QUERY && (info->uid % 100000) == (su_ctx->st.st_uid % 100000)) {
|
if (info->policy == QUERY) {
|
||||||
info->policy = ALLOW;
|
if (ctx.st.st_gid != ctx.st.st_uid) {
|
||||||
info->root_access = ROOT_ACCESS_APPS_AND_ADB;
|
LOGE("Bad uid/gid %d/%d for Superuser Requestor", ctx.st.st_uid, ctx.st.st_gid);
|
||||||
su_ctx->notify = 0;
|
info->policy = DENY;
|
||||||
|
ctx.notify = 0;
|
||||||
|
} else if ((info->uid % 100000) == (ctx.st.st_uid % 100000)) {
|
||||||
|
info->policy = ALLOW;
|
||||||
|
info->root_access = ROOT_ACCESS_APPS_AND_ADB;
|
||||||
|
ctx.notify = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// always allow if it's root
|
// always allow if it's root
|
||||||
if (info->uid == UID_ROOT) {
|
if (info->uid == UID_ROOT) {
|
||||||
info->policy = ALLOW;
|
info->policy = ALLOW;
|
||||||
info->root_access = ROOT_ACCESS_APPS_AND_ADB;
|
info->root_access = ROOT_ACCESS_APPS_AND_ADB;
|
||||||
su_ctx->notify = 0;
|
ctx.notify = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If still not determined, open a pipe and wait for results
|
// If still not determined, open a pipe and wait for results
|
||||||
if (info->policy == QUERY)
|
if (info->policy == QUERY)
|
||||||
xpipe2(pipefd, O_CLOEXEC);
|
xpipe2(ctx.pipefd, O_CLOEXEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fork a new process, the child process will need to setsid,
|
// Fork a new process, the child process will need to setsid,
|
||||||
@ -235,9 +200,9 @@ void su_daemon_receiver(int client) {
|
|||||||
if (child) {
|
if (child) {
|
||||||
// Wait for results
|
// Wait for results
|
||||||
if (info->policy == QUERY) {
|
if (info->policy == QUERY) {
|
||||||
xxread(pipefd[0], &info->policy, sizeof(info->policy));
|
xxread(ctx.pipefd[0], &info->policy, sizeof(info->policy));
|
||||||
close(pipefd[0]);
|
close(ctx.pipefd[0]);
|
||||||
close(pipefd[1]);
|
close(ctx.pipefd[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The policy is determined, unlock
|
// The policy is determined, unlock
|
||||||
@ -308,8 +273,8 @@ void su_daemon_receiver(int client) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get cwd
|
// Get cwd
|
||||||
su_ctx->cwd = read_string(client);
|
ctx.cwd = read_string(client);
|
||||||
LOGD("su: cwd=[%s]\n", su_ctx->cwd);
|
LOGD("su: cwd=[%s]\n", ctx.cwd);
|
||||||
|
|
||||||
// Get pts_slave
|
// Get pts_slave
|
||||||
char *pts_slave = read_string(client);
|
char *pts_slave = read_string(client);
|
||||||
@ -330,7 +295,7 @@ void su_daemon_receiver(int client) {
|
|||||||
xstat(pts_slave, &stbuf);
|
xstat(pts_slave, &stbuf);
|
||||||
|
|
||||||
//If caller is not root, ensure the owner of pts_slave is the caller
|
//If caller is not root, ensure the owner of pts_slave is the caller
|
||||||
if(stbuf.st_uid != credential.uid && credential.uid != 0) {
|
if(stbuf.st_uid != info->uid && info->uid != 0) {
|
||||||
LOGE("su: Wrong permission of pts_slave");
|
LOGE("su: Wrong permission of pts_slave");
|
||||||
exit2(1);
|
exit2(1);
|
||||||
}
|
}
|
||||||
@ -363,6 +328,8 @@ void su_daemon_receiver(int client) {
|
|||||||
|
|
||||||
close(ptsfd);
|
close(ptsfd);
|
||||||
|
|
||||||
|
// Give main the reference
|
||||||
|
su_ctx = &ctx;
|
||||||
su_daemon_main(argc, argv);
|
su_daemon_main(argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
11
su_socket.c
11
su_socket.c
@ -29,21 +29,22 @@ int socket_create_temp(char *path, size_t len) {
|
|||||||
|
|
||||||
memset(&sun, 0, sizeof(sun));
|
memset(&sun, 0, sizeof(sun));
|
||||||
sun.sun_family = AF_LOCAL;
|
sun.sun_family = AF_LOCAL;
|
||||||
snprintf(path, len, "%s/.socket%d", REQUESTOR_CACHE_PATH, (int) syscall(SYS_gettid));
|
snprintf(path, len, "/dev/.socket%d", (int) syscall(SYS_gettid));
|
||||||
snprintf(sun.sun_path, sizeof(sun.sun_path), "%s", path);
|
strcpy(sun.sun_path, path);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Delete the socket to protect from situations when
|
* Delete the socket to protect from situations when
|
||||||
* something bad occured previously and the kernel reused pid from that process.
|
* something bad occured previously and the kernel reused pid from that process.
|
||||||
* Small probability, isn't it.
|
* Small probability, isn't it.
|
||||||
*/
|
*/
|
||||||
unlink(sun.sun_path);
|
unlink(path);
|
||||||
|
|
||||||
xbind(fd, (struct sockaddr*) &sun, sizeof(sun));
|
xbind(fd, (struct sockaddr*) &sun, sizeof(sun));
|
||||||
xlisten(fd, 1);
|
xlisten(fd, 1);
|
||||||
|
|
||||||
// Set context to su_device, so apps can access it
|
// Set attributes so requester can access it
|
||||||
setfilecon(sun.sun_path, "u:object_r:su_device:s0");
|
setfilecon(path, "u:object_r:su_device:s0");
|
||||||
|
chown(path, su_ctx->st.st_uid, su_ctx->st.st_gid);
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user