Finish su implementation

This commit is contained in:
topjohnwu 2018-10-04 14:41:48 -04:00
parent d119dd9a0c
commit 37860181d4
3 changed files with 15 additions and 17 deletions

View File

@ -105,6 +105,7 @@ int su_client_main(int argc, char *argv[]) {
.uid = UID_ROOT, .uid = UID_ROOT,
.login = 0, .login = 0,
.keepenv = 0, .keepenv = 0,
.mount_master = 0,
.shell = DEFAULT_SHELL, .shell = DEFAULT_SHELL,
.command = "", .command = "",
}; };
@ -147,7 +148,7 @@ int su_client_main(int argc, char *argv[]) {
// Do nothing, placed here for legacy support :) // Do nothing, placed here for legacy support :)
break; break;
case 'M': case 'M':
/* TODO */ su_req.mount_master = 1;
break; break;
default: default:
/* Bionic getopt_long doesn't terminate its error output by newline */ /* 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); write_int(fd, SUPERUSER);
// Send su_request // 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.shell);
write_string(fd, su_req.command); write_string(fd, su_req.command);

View File

@ -40,6 +40,7 @@ struct su_request {
unsigned uid; unsigned uid;
unsigned login; unsigned login;
unsigned keepenv; unsigned keepenv;
unsigned mount_master;
char *shell; char *shell;
char *command; char *command;
}; };

View File

@ -126,18 +126,18 @@ static struct su_info *get_su_info(unsigned uid) {
// Check su access settings // Check su access settings
switch (DB_SET(info, ROOT_ACCESS)) { switch (DB_SET(info, ROOT_ACCESS)) {
case ROOT_ACCESS_DISABLED: case ROOT_ACCESS_DISABLED:
LOGE("Root access is disabled!\n"); LOGW("Root access is disabled!\n");
info->access = NO_SU_ACCESS; info->access = NO_SU_ACCESS;
break; break;
case ROOT_ACCESS_ADB_ONLY: case ROOT_ACCESS_ADB_ONLY:
if (info->uid != UID_SHELL) { 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; info->access = NO_SU_ACCESS;
} }
break; break;
case ROOT_ACCESS_APPS_ONLY: case ROOT_ACCESS_APPS_ONLY:
if (info->uid == UID_SHELL) { 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; info->access = NO_SU_ACCESS;
} }
break; break;
@ -282,7 +282,7 @@ void su_daemon_handler(int client, struct ucred *credential) {
} }
// Read su_request // 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.shell = read_string(client);
ctx.req.command = read_string(client); ctx.req.command = read_string(client);
@ -338,6 +338,8 @@ void su_daemon_handler(int client, struct ucred *credential) {
close(client); close(client);
// Handle namespaces // Handle namespaces
if (ctx.req.mount_master)
DB_SET(info, SU_MNT_NS) = NAMESPACE_MODE_GLOBAL;
switch (DB_SET(info, SU_MNT_NS)) { switch (DB_SET(info, SU_MNT_NS)) {
case NAMESPACE_MODE_GLOBAL: case NAMESPACE_MODE_GLOBAL:
LOGD("su: use global namespace\n"); LOGD("su: use global namespace\n");
@ -355,13 +357,13 @@ void su_daemon_handler(int client, struct ucred *credential) {
break; 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 }; char* argv[] = { NULL, NULL, NULL, NULL };
if (ctx.req.login) argv[0] = ctx.req.login ? "-" : ctx.req.shell;
argv[0] = "-";
else
argv[0] = ctx.req.shell;
if (ctx.req.command[0]) { if (ctx.req.command[0]) {
argv[1] = "-c"; argv[1] = "-c";
@ -373,17 +375,11 @@ void su_daemon_handler(int client, struct ucred *credential) {
populate_environment(&ctx.req); populate_environment(&ctx.req);
set_identity(ctx.req.uid); set_identity(ctx.req.uid);
if (info->access.notify || info->access.log)
app_log(&ctx);
execvp(ctx.req.shell, argv); execvp(ctx.req.shell, argv);
fprintf(stderr, "Cannot execute %s: %s\n", ctx.req.shell, strerror(errno)); fprintf(stderr, "Cannot execute %s: %s\n", ctx.req.shell, strerror(errno));
PLOGE("exec"); PLOGE("exec");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} else { } else {
if (info->access.notify || info->access.log)
app_log(&ctx);
LOGW("su: request rejected (%u->%u)", info->uid, ctx.req.uid); LOGW("su: request rejected (%u->%u)", info->uid, ctx.req.uid);
fprintf(stderr, "%s\n", strerror(EACCES)); fprintf(stderr, "%s\n", strerror(EACCES));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);