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,
.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);

View File

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

View File

@ -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);