Skip to content

Commit

Permalink
Add multiuser support
Browse files Browse the repository at this point in the history
  • Loading branch information
topjohnwu committed May 26, 2017
1 parent 28fe87c commit b76adde
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 172 deletions.
115 changes: 20 additions & 95 deletions activity.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,8 @@

static void silent_run(char* const args[]) {
set_identity(0);
pid_t pid;
pid = fork();
/* Parent */
if (pid < 0) {
PLOGE("fork");
}
else if (pid > 0) {
if (fork())
return;
}
int zero = open("/dev/zero", O_RDONLY | O_CLOEXEC);
dup2(zero, 0);
int null = open("/dev/null", O_WRONLY | O_CLOEXEC);
Expand All @@ -46,79 +39,37 @@ static void silent_run(char* const args[]) {
_exit(EXIT_FAILURE);
}

static int get_owner_login_user_args(struct su_context *ctx, char* user, int user_len) {
int needs_owner_login_prompt = 0;

if (ctx->user.multiuser_mode == MULTIUSER_MODE_OWNER_MANAGED) {
if (0 != ctx->user.android_user_id) {
needs_owner_login_prompt = 1;
}
snprintf(user, user_len, "0");
}
else if (ctx->user.multiuser_mode == MULTIUSER_MODE_USER) {
snprintf(user, user_len, "%d", ctx->user.android_user_id);
}
else if (ctx->user.multiuser_mode == MULTIUSER_MODE_NONE) {
user[0] = '\0';
static void setup_user(struct su_context *ctx, char* user) {
switch (ctx->user.multiuser_mode) {
case MULTIUSER_MODE_OWNER_ONLY: /* Should already be denied if not owner */
case MULTIUSER_MODE_OWNER_MANAGED:
sprintf(user, "%d", 0);
break;
case MULTIUSER_MODE_USER:
sprintf(user, "%d", ctx->user.android_user_id);
break;
}
else {
snprintf(user, user_len, "0");
}

return needs_owner_login_prompt;
}

void app_send_result(struct su_context *ctx, policy_t policy) {
// char binary_version[256];
// sprintf(binary_version, "%d", VERSION_CODE);

char uid[256];
sprintf(uid, "%d", ctx->from.uid);
char fromUid[16];
sprintf(fromUid, "%d", ctx->from.uid);

char toUid[256];
char toUid[16];
sprintf(toUid, "%d", ctx->to.uid);

char pid[256];
char pid[16];
sprintf(pid, "%d", ctx->from.pid);

char user[64];
get_owner_login_user_args(ctx, user, sizeof(user));

if (0 != ctx->user.android_user_id) {
char android_user_id[256];
sprintf(android_user_id, "%d", ctx->user.android_user_id);

char *user_result_command[] = {
AM_PATH,
ACTION_RESULT,
"--ei",
"from.uid",
uid,
"--ei",
"to.uid",
toUid,
"--ei",
"pid",
pid,
"--es",
"command",
get_command(&ctx->to),
"--es",
"action",
policy == ALLOW ? "allow" : "deny",
user[0] ? "--user" : NULL,
android_user_id,
NULL
};
silent_run(user_result_command);
}
char user[16];
setup_user(ctx, user);

char *result_command[] = {
AM_PATH,
ACTION_RESULT,
"--ei",
"from.uid",
uid,
fromUid,
"--ei",
"to.uid",
toUid,
Expand All @@ -131,50 +82,24 @@ void app_send_result(struct su_context *ctx, policy_t policy) {
"--es",
"action",
policy == ALLOW ? "allow" : "deny",
user[0] ? "--user" : NULL,
"--user",
user,
NULL
};
silent_run(result_command);
}

void app_send_request(struct su_context *ctx) {
// if su is operating in MULTIUSER_MODEL_OWNER,
// and the user requestor is not the owner,
// the owner needs to be notified of the request.
// so there will be two activities shown.
char user[64];
int needs_owner_login_prompt = get_owner_login_user_args(ctx, user, sizeof(user));

if (needs_owner_login_prompt) {
char uid[256];
sprintf(uid, "%d", ctx->from.uid);

char android_user_id[256];
sprintf(android_user_id, "%d", ctx->user.android_user_id);

// in multiuser mode, the owner gets the su prompt
char *notify_command[] = {
AM_PATH,
ACTION_NOTIFY,
"--ei",
"caller_uid",
uid,
"--user",
android_user_id,
NULL
};

silent_run(notify_command);
}
setup_user(ctx, user);

char *request_command[] = {
AM_PATH,
ACTION_REQUEST,
"--es",
"socket",
ctx->sock_path,
user[0] ? "--user" : NULL,
"--user",
user,
NULL
};
Expand Down
53 changes: 28 additions & 25 deletions su.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,13 @@ static char *concat_commands(int argc, char *argv[]) {
}

static int get_multiuser_mode() {
// TODO: Multiuser support
return MULTIUSER_MODE_NONE;
char *prop = getprop(MULTIUSER_MODE_PROP);
if (prop) {
int ret = atoi(prop);
free(prop);
return ret;
}
return MULTIUSER_MODE_OWNER_ONLY;
}

static void populate_environment(const struct su_context *ctx) {
Expand Down Expand Up @@ -212,8 +217,8 @@ int su_daemon_main(int argc, char **argv) {
.user = {
.android_user_id = 0,
.multiuser_mode = get_multiuser_mode(),
.database_path = APPLICATION_DATA_PATH REQUESTOR_DATABASE_PATH,
.base_path = APPLICATION_DATA_PATH REQUESTOR
.database_path = APP_DATA_PATH REQUESTOR_DATABASE_PATH,
.base_path = APP_DATA_PATH REQUESTOR
},
.umask = 022,
};
Expand Down Expand Up @@ -262,16 +267,13 @@ int su_daemon_main(int argc, char **argv) {
case 'u':
switch (ctx.user.multiuser_mode) {
case MULTIUSER_MODE_USER:
printf("%s\n", MULTIUSER_VALUE_USER);
printf("Owner only: Only owner has root access\n");
break;
case MULTIUSER_MODE_OWNER_MANAGED:
printf("%s\n", MULTIUSER_VALUE_OWNER_MANAGED);
printf("Owner managed: Only owner can manage root access and receive request prompts\n");
break;
case MULTIUSER_MODE_OWNER_ONLY:
printf("%s\n", MULTIUSER_VALUE_OWNER_ONLY);
break;
case MULTIUSER_MODE_NONE:
printf("%s\n", MULTIUSER_VALUE_NONE);
printf("User independent: The user has its own separate root rules\n");
break;
}
exit(EXIT_SUCCESS);
Expand Down Expand Up @@ -318,15 +320,20 @@ int su_daemon_main(int argc, char **argv) {
// It's in multiuser mode
if (ctx.from.uid > 99999) {
ctx.user.android_user_id = ctx.from.uid / 100000;
if (ctx.user.multiuser_mode == MULTIUSER_MODE_USER) {
ctx.from.uid %= 100000;
switch (ctx.user.multiuser_mode) {
case MULTIUSER_MODE_OWNER_ONLY:
deny();
case MULTIUSER_MODE_USER:
snprintf(ctx.user.database_path, PATH_MAX, "%s/%d/%s",
USER_DATA_PATH, ctx.user.android_user_id, REQUESTOR_DATABASE_PATH);
snprintf(ctx.user.base_path, PATH_MAX, "%s/%d/%s",
USER_DATA_PATH, ctx.user.android_user_id, REQUESTOR);
break;
}
}

// verify superuser is installed
// verify if Magisk Manager is installed
xstat(ctx.user.base_path, &st);

// odd perms on superuser data dir
Expand All @@ -336,12 +343,6 @@ int su_daemon_main(int argc, char **argv) {
deny();
}

// always allow if this is the superuser uid
// superuser needs to be able to reenable itself when disabled...
if (ctx.from.uid == st.st_uid) {
allow();
}

// Check property of root configuration
char *root_prop = getprop(ROOT_ACCESS_PROP);
if (root_prop) {
Expand All @@ -361,19 +362,21 @@ int su_daemon_main(int argc, char **argv) {
default:
break;
}
free(root_prop);
} else {
exit(EXIT_FAILURE);
// Not initialized yet, set the prop to allow everything by default
setprop(ROOT_ACCESS_PROP, xstr(ROOT_ACCESS_APPS_AND_ADB));
}
free(root_prop);

// Allow root to start root
if (ctx.from.uid == UID_ROOT) {
// always allow if this is the superuser uid
// superuser needs to be able to reenable itself when disabled...
if (ctx.from.uid == st.st_uid) {
allow();
}

// 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();
// Allow root to start root
if (ctx.from.uid == UID_ROOT) {
allow();
}

mkdir(REQUESTOR_CACHE_PATH, 0770);
Expand Down
Loading

0 comments on commit b76adde

Please sign in to comment.