From 37860181d4f486964ee6c862a32df142429739f5 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Thu, 4 Oct 2018 14:41:48 -0400 Subject: [PATCH] Finish su implementation --- native/jni/su/su.c | 5 +++-- native/jni/su/su.h | 1 + native/jni/su/su_daemon.c | 26 +++++++++++--------------- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/native/jni/su/su.c b/native/jni/su/su.c index 781d4e976..0242adebb 100644 --- a/native/jni/su/su.c +++ b/native/jni/su/su.c @@ -105,6 +105,7 @@ int su_client_main(int argc, char *argv[]) { .uid = UID_ROOT, .login = 0, .keepenv = 0, + .mount_master = 0, .shell = DEFAULT_SHELL, .command = "", }; @@ -147,7 +148,7 @@ int su_client_main(int argc, char *argv[]) { // Do nothing, placed here for legacy support :) break; case 'M': - /* TODO */ + su_req.mount_master = 1; break; default: /* Bionic getopt_long doesn't terminate its error output by newline */ @@ -181,7 +182,7 @@ int su_client_main(int argc, char *argv[]) { write_int(fd, SUPERUSER); // Send su_request - xwrite(fd, &su_req, 3 * sizeof(unsigned)); + xwrite(fd, &su_req, 4 * sizeof(unsigned)); write_string(fd, su_req.shell); write_string(fd, su_req.command); diff --git a/native/jni/su/su.h b/native/jni/su/su.h index 705046fdb..e3a925193 100644 --- a/native/jni/su/su.h +++ b/native/jni/su/su.h @@ -40,6 +40,7 @@ struct su_request { unsigned uid; unsigned login; unsigned keepenv; + unsigned mount_master; char *shell; char *command; }; diff --git a/native/jni/su/su_daemon.c b/native/jni/su/su_daemon.c index f2aa38767..4bf1a2c45 100644 --- a/native/jni/su/su_daemon.c +++ b/native/jni/su/su_daemon.c @@ -126,18 +126,18 @@ static struct su_info *get_su_info(unsigned uid) { // Check su access settings switch (DB_SET(info, ROOT_ACCESS)) { case ROOT_ACCESS_DISABLED: - LOGE("Root access is disabled!\n"); + LOGW("Root access is disabled!\n"); info->access = NO_SU_ACCESS; break; case ROOT_ACCESS_ADB_ONLY: if (info->uid != UID_SHELL) { - LOGE("Root access limited to ADB only!\n"); + LOGW("Root access limited to ADB only!\n"); info->access = NO_SU_ACCESS; } break; case ROOT_ACCESS_APPS_ONLY: if (info->uid == UID_SHELL) { - LOGE("Root access is disabled for ADB!\n"); + LOGW("Root access is disabled for ADB!\n"); info->access = NO_SU_ACCESS; } break; @@ -282,7 +282,7 @@ void su_daemon_handler(int client, struct ucred *credential) { } // Read su_request - xxread(client, &ctx.req, 3 * sizeof(unsigned)); + xxread(client, &ctx.req, 4 * sizeof(unsigned)); ctx.req.shell = read_string(client); ctx.req.command = read_string(client); @@ -338,6 +338,8 @@ void su_daemon_handler(int client, struct ucred *credential) { close(client); // Handle namespaces + if (ctx.req.mount_master) + DB_SET(info, SU_MNT_NS) = NAMESPACE_MODE_GLOBAL; switch (DB_SET(info, SU_MNT_NS)) { case NAMESPACE_MODE_GLOBAL: LOGD("su: use global namespace\n"); @@ -355,13 +357,13 @@ void su_daemon_handler(int client, struct ucred *credential) { break; } - if (info->access.policy) { + if (info->access.notify || info->access.log) + app_log(&ctx); + + if (info->access.policy == ALLOW) { char* argv[] = { NULL, NULL, NULL, NULL }; - if (ctx.req.login) - argv[0] = "-"; - else - argv[0] = ctx.req.shell; + argv[0] = ctx.req.login ? "-" : ctx.req.shell; if (ctx.req.command[0]) { argv[1] = "-c"; @@ -373,17 +375,11 @@ void su_daemon_handler(int client, struct ucred *credential) { populate_environment(&ctx.req); set_identity(ctx.req.uid); - if (info->access.notify || info->access.log) - app_log(&ctx); - execvp(ctx.req.shell, argv); fprintf(stderr, "Cannot execute %s: %s\n", ctx.req.shell, strerror(errno)); PLOGE("exec"); exit(EXIT_FAILURE); } else { - if (info->access.notify || info->access.log) - app_log(&ctx); - LOGW("su: request rejected (%u->%u)", info->uid, ctx.req.uid); fprintf(stderr, "%s\n", strerror(EACCES)); exit(EXIT_FAILURE);