Adapt su to Magisk
This commit is contained in:
parent
ef1d1303f4
commit
e3a4a16507
36
daemon.c
36
daemon.c
@ -445,7 +445,7 @@ static int daemon_accept(int fd) {
|
||||
}
|
||||
|
||||
int run_daemon() {
|
||||
if (getuid() != 0 || getgid() != 0) {
|
||||
if (getuid() != AID_ROOT || getgid() != AID_ROOT) {
|
||||
PLOGE("daemon requires root. uid/gid not root");
|
||||
return -1;
|
||||
}
|
||||
@ -455,13 +455,19 @@ int run_daemon() {
|
||||
break;
|
||||
case -1:
|
||||
PLOGE("fork");
|
||||
return 1;
|
||||
return -1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (setsid() < 0 || setcon("u:r:su_daemon:s0") < 0)
|
||||
return 1;
|
||||
if (setsid() < 0) {
|
||||
PLOGE("setsid");
|
||||
return -1;
|
||||
}
|
||||
if (setcon("u:r:su_daemon:s0") < 0) {
|
||||
PLOGE("setcon");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int fd;
|
||||
struct sockaddr_un sun;
|
||||
@ -478,32 +484,17 @@ int run_daemon() {
|
||||
|
||||
memset(&sun, 0, sizeof(sun));
|
||||
sun.sun_family = AF_LOCAL;
|
||||
sprintf(sun.sun_path, "%s/server", REQUESTOR_DAEMON_PATH);
|
||||
strcpy(sun.sun_path, REQUESTOR_DAEMON_PATH);
|
||||
|
||||
/*
|
||||
* Delete the socket to protect from situations when
|
||||
* something bad occured previously and the kernel reused pid from that process.
|
||||
* Small probability, isn't it.
|
||||
*/
|
||||
unlink(sun.sun_path);
|
||||
unlink(REQUESTOR_DAEMON_PATH);
|
||||
|
||||
int previous_umask = umask(027);
|
||||
mkdir(REQUESTOR_DAEMON_PATH, 0777);
|
||||
|
||||
memset(sun.sun_path, 0, sizeof(sun.sun_path));
|
||||
memcpy(sun.sun_path, "\0" "SUPERUSER", strlen("SUPERUSER") + 1);
|
||||
|
||||
if (bind(fd, (struct sockaddr*)&sun, sizeof(sun)) < 0) {
|
||||
PLOGE("daemon bind");
|
||||
goto err;
|
||||
}
|
||||
|
||||
chmod(REQUESTOR_DAEMON_PATH, 0755);
|
||||
chmod(sun.sun_path, 0777);
|
||||
|
||||
umask(previous_umask);
|
||||
|
||||
if (listen(fd, 10) < 0) {
|
||||
PLOGE("daemon listen");
|
||||
goto err;
|
||||
@ -600,10 +591,7 @@ int connect_daemon(int argc, char *argv[], int ppid) {
|
||||
|
||||
memset(&sun, 0, sizeof(sun));
|
||||
sun.sun_family = AF_LOCAL;
|
||||
sprintf(sun.sun_path, "%s/server", REQUESTOR_DAEMON_PATH);
|
||||
|
||||
memset(sun.sun_path, 0, sizeof(sun.sun_path));
|
||||
memcpy(sun.sun_path, "\0" "SUPERUSER", strlen("SUPERUSER") + 1);
|
||||
strcpy(sun.sun_path, REQUESTOR_DAEMON_PATH);
|
||||
|
||||
if (0 != connect(socketfd, (struct sockaddr*)&sun, sizeof(sun))) {
|
||||
PLOGE("connect");
|
||||
|
47
db.c
47
db.c
@ -29,51 +29,31 @@ struct callback_data_t {
|
||||
|
||||
static int database_callback(void *v, int argc, char **argv, char **azColName){
|
||||
struct callback_data_t *data = (struct callback_data_t *)v;
|
||||
int command_match = 0;
|
||||
policy_t policy = DENY;
|
||||
policy_t policy = INTERACTIVE;
|
||||
int i;
|
||||
time_t until = 0;
|
||||
for(i = 0; i < argc; i++) {
|
||||
if (strcmp(azColName[i], "policy") == 0) {
|
||||
if (argv[i] == NULL) {
|
||||
policy = DENY;
|
||||
if (argv[i] != NULL) {
|
||||
policy = atoi(argv[i]);
|
||||
}
|
||||
if (strcmp(argv[i], "allow") == 0) {
|
||||
policy = ALLOW;
|
||||
}
|
||||
else if (strcmp(argv[i], "interactive") == 0) {
|
||||
policy = INTERACTIVE;
|
||||
}
|
||||
else {
|
||||
policy = DENY;
|
||||
}
|
||||
}
|
||||
else if (strcmp(azColName[i], "command") == 0) {
|
||||
// null or empty command means to match all commands (whitelist all from uid)
|
||||
command_match = argv[i] == NULL || strlen(argv[i]) == 0 || strcmp(argv[i], get_command(&(data->ctx->to))) == 0;
|
||||
}
|
||||
else if (strcmp(azColName[i], "until") == 0) {
|
||||
if (argv[i] != NULL) {
|
||||
until = atoi(argv[i]);
|
||||
until = atol(argv[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check for command match
|
||||
if (command_match) {
|
||||
// also make sure this policy has not expired
|
||||
if (until == 0 || until > time(NULL)) {
|
||||
if (policy == DENY) {
|
||||
data->policy = DENY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
data->policy = ALLOW;
|
||||
// even though we allow, continue, so we can see if there's another policy
|
||||
// that denies...
|
||||
}
|
||||
if (policy == DENY) {
|
||||
data->policy = DENY;
|
||||
return -1;
|
||||
} else if (policy == ALLOW && (until == 0 || until > time(NULL))) {
|
||||
data->policy = ALLOW;
|
||||
// even though we allow, continue, so we can see if there's another policy
|
||||
// that denies...
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -81,7 +61,7 @@ policy_t database_check(struct su_context *ctx) {
|
||||
sqlite3 *db = NULL;
|
||||
|
||||
char query[512];
|
||||
snprintf(query, sizeof(query), "select policy, until, command from uid_policy where uid=%d", ctx->from.uid);
|
||||
snprintf(query, sizeof(query), "select policy, until from policies where uid=%d", ctx->from.uid);
|
||||
int ret = sqlite3_open_v2(ctx->user.database_path, &db, SQLITE_OPEN_READONLY, NULL);
|
||||
if (ret) {
|
||||
LOGE("sqlite3 open failure: %d", ret);
|
||||
@ -89,7 +69,6 @@ policy_t database_check(struct su_context *ctx) {
|
||||
return INTERACTIVE;
|
||||
}
|
||||
|
||||
int result;
|
||||
char *err = NULL;
|
||||
struct callback_data_t data;
|
||||
data.ctx = ctx;
|
||||
|
23
su.c
23
su.c
@ -425,9 +425,6 @@ static int socket_send_request(int fd, const struct su_context *ctx) {
|
||||
write_token(fd, "from.uid", ctx->from.uid);
|
||||
write_token(fd, "to.uid", ctx->to.uid);
|
||||
write_string_data(fd, "from.bin", ctx->from.bin);
|
||||
write_string_data(fd, "bind.from", ctx->bind.from);
|
||||
write_string_data(fd, "bind.to", ctx->bind.to);
|
||||
write_string_data(fd, "init", ctx->init);
|
||||
// TODO: Fix issue where not using -c does not result a in a command
|
||||
write_string_data(fd, "command", get_command(&ctx->to));
|
||||
write_token(fd, "eof", PROTO_VERSION);
|
||||
@ -510,12 +507,6 @@ static __attribute__ ((noreturn)) void allow(struct su_context *ctx) {
|
||||
if (send_to_app)
|
||||
send_result(ctx, ALLOW);
|
||||
|
||||
// if(ctx->bind.from[0] && ctx->bind.to[0])
|
||||
// allow_bind(ctx);
|
||||
|
||||
// if(ctx->init[0])
|
||||
// allow_init(ctx);
|
||||
|
||||
char *binary;
|
||||
argc = ctx->to.optind;
|
||||
if (ctx->to.command) {
|
||||
@ -712,11 +703,6 @@ int su_main_nodaemon(int argc, char **argv) {
|
||||
.database_path = REQUESTOR_DATA_PATH REQUESTOR_DATABASE_PATH,
|
||||
.base_path = REQUESTOR_DATA_PATH REQUESTOR
|
||||
},
|
||||
.bind = {
|
||||
.from = "",
|
||||
.to = "",
|
||||
},
|
||||
.init = "",
|
||||
};
|
||||
struct stat st;
|
||||
int c, socket_serv_fd, fd;
|
||||
@ -756,7 +742,7 @@ int su_main_nodaemon(int argc, char **argv) {
|
||||
printf("%d\n", VERSION_CODE);
|
||||
exit(EXIT_SUCCESS);
|
||||
case 'v':
|
||||
printf("%s cm-su topjohnwu\n", VERSION);
|
||||
printf("%s\n", VERSION);
|
||||
exit(EXIT_SUCCESS);
|
||||
case 'u':
|
||||
switch (get_multiuser_mode()) {
|
||||
@ -851,12 +837,6 @@ int su_main_nodaemon(int argc, char **argv) {
|
||||
allow(&ctx);
|
||||
}
|
||||
|
||||
// autogrant shell at this point
|
||||
if (ctx.from.uid == AID_SHELL) {
|
||||
LOGD("Allowing shell.");
|
||||
allow(&ctx);
|
||||
}
|
||||
|
||||
// deny if this is a non owner request and owner mode only
|
||||
if (ctx.user.multiuser_mode == MULTIUSER_MODE_OWNER_ONLY && ctx.user.android_user_id != 0) {
|
||||
deny(&ctx);
|
||||
@ -883,7 +863,6 @@ int su_main_nodaemon(int argc, char **argv) {
|
||||
deny(&ctx);
|
||||
}
|
||||
|
||||
//TODO: Ignore database check for init and bind?
|
||||
dballow = database_check(&ctx);
|
||||
switch (dballow) {
|
||||
case INTERACTIVE:
|
||||
|
23
su.h
23
su.h
@ -46,29 +46,28 @@
|
||||
#define CM_ROOT_ACCESS_APPS_AND_ADB 3
|
||||
|
||||
// DO NOT CHANGE LINE BELOW, java package name will always be the same
|
||||
#define JAVA_PACKAGE_NAME "com.koushikdutta.superuser"
|
||||
#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.
|
||||
#ifndef REQUESTOR
|
||||
#define REQUESTOR "me.phh.superuser"
|
||||
#define REQUESTOR JAVA_PACKAGE_NAME
|
||||
#endif
|
||||
// This is used if wrapping the fragment classes and activities
|
||||
// with classes in another package. CM requirement.
|
||||
#ifndef REQUESTOR_PREFIX
|
||||
#define REQUESTOR_PREFIX JAVA_PACKAGE_NAME
|
||||
#define REQUESTOR_PREFIX JAVA_PACKAGE_NAME ".superuser"
|
||||
#endif
|
||||
#define REQUESTOR_DATA_PATH "/data/data/"
|
||||
#define REQUESTOR_FILES_PATH REQUESTOR_DATA_PATH REQUESTOR "/files"
|
||||
#define REQUESTOR_USER_PATH "/data/user/"
|
||||
#define REQUESTOR_CACHE_PATH "/dev/" REQUESTOR
|
||||
#define REQUESTOR_DAEMON_PATH REQUESTOR_CACHE_PATH ".daemon"
|
||||
|
||||
#define REQUESTOR_DAEMON_PATH "\0MAGISKSU"
|
||||
// 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.sqlite"
|
||||
#define REQUESTOR_DATABASE_PATH REQUESTOR "/databases/su.db"
|
||||
#define REQUESTOR_MULTIUSER_MODE REQUESTOR_FILES_PATH "/multiuser_mode"
|
||||
|
||||
#define DEFAULT_SHELL "/system/bin/sh"
|
||||
@ -77,10 +76,9 @@
|
||||
#define str(a) #a
|
||||
|
||||
#ifndef VERSION_CODE
|
||||
#define VERSION_CODE 17
|
||||
#define VERSION_CODE 1
|
||||
#endif
|
||||
#define VERSION xstr(VERSION_CODE) " " REQUESTOR
|
||||
// #define VERSION REQUESTOR " topjohnwu r1"
|
||||
#define VERSION "MAGISKSU:" xstr(VERSION_CODE)
|
||||
|
||||
#define PROTO_VERSION 1
|
||||
|
||||
@ -123,17 +121,10 @@ struct su_user_info {
|
||||
char database_path[PATH_MAX];
|
||||
};
|
||||
|
||||
struct su_bind {
|
||||
const char *from;
|
||||
const char *to;
|
||||
};
|
||||
|
||||
struct su_context {
|
||||
struct su_initiator from;
|
||||
struct su_request to;
|
||||
struct su_user_info user;
|
||||
struct su_bind bind;
|
||||
const char *init;
|
||||
mode_t umask;
|
||||
char sock_path[PATH_MAX];
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user