Commit 2c400138 authored by topjohnwu's avatar topjohnwu

Several adjustments

parent caa39474
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
#include <libgen.h> #include <libgen.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/auxv.h>
#include <selinux/selinux.h> #include <selinux/selinux.h>
#include "magisk.h" #include "magisk.h"
...@@ -160,42 +159,6 @@ __attribute__ ((noreturn)) void exit2(int status) { ...@@ -160,42 +159,6 @@ __attribute__ ((noreturn)) void exit2(int status) {
} }
int su_daemon_main(int argc, char **argv) { int su_daemon_main(int argc, char **argv) {
// Sanitize all secure environment variables (from linker_environ.c in AOSP linker).
/* The same list than GLibc at this point */
static const char* const unsec_vars[] = {
"GCONV_PATH",
"GETCONF_DIR",
"HOSTALIASES",
"LD_AUDIT",
"LD_DEBUG",
"LD_DEBUG_OUTPUT",
"LD_DYNAMIC_WEAK",
"LD_LIBRARY_PATH",
"LD_ORIGIN_PATH",
"LD_PRELOAD",
"LD_PROFILE",
"LD_SHOW_AUXV",
"LD_USE_LOAD_BIAS",
"LOCALDOMAIN",
"LOCPATH",
"MALLOC_TRACE",
"MALLOC_CHECK_",
"NIS_PATH",
"NLSPATH",
"RESOLV_HOST_CONF",
"RES_OPTIONS",
"TMPDIR",
"TZDIR",
"LD_AOUT_LIBRARY_PATH",
"LD_AOUT_PRELOAD",
// not listed in linker, used due to system() call
"IFS",
NULL
};
if (getauxval(AT_SECURE))
for (int i = 0; unsec_vars[i]; ++i)
unsetenv(unsec_vars[i]);
int c, socket_serv_fd, fd; int c, socket_serv_fd, fd;
char result[64]; char result[64];
struct option long_opts[] = { struct option long_opts[] = {
......
...@@ -197,85 +197,8 @@ static struct su_info *get_su_info(unsigned uid) { ...@@ -197,85 +197,8 @@ static struct su_info *get_su_info(unsigned uid) {
return info; return info;
} }
void su_daemon_receiver(int client, struct ucred *credential) { static void su_executor(int client) {
LOGD("su: request from client: %d\n", client); LOGD("su: executor started\n");
// Default values
struct su_context ctx = {
.info = get_su_info(credential->uid),
.to = {
.uid = UID_ROOT,
.login = 0,
.keepenv = 0,
.shell = DEFAULT_SHELL,
.command = NULL,
},
.pid = credential->pid,
.pipefd = { -1, -1 }
};
// Fail fast
if (ctx.info->access.policy == DENY && !ctx.info->access.log && !ctx.info->access.notify) {
UNLOCK_UID();
write_int(client, DENY);
return;
}
// If still not determined, open a pipe and wait for results
if (ctx.info->access.policy == QUERY)
xpipe2(ctx.pipefd, O_CLOEXEC);
/* Fork a new process, the child process will need to setsid,
* open a pseudo-terminal if needed, and will eventually run exec
* The parent process will wait for the result and
* send the return code back to our client
*/
int child = xfork();
if (child) {
// Wait for results
if (ctx.pipefd[0] >= 0) {
xxread(ctx.pipefd[0], &ctx.info->access.policy, sizeof(policy_t));
close(ctx.pipefd[0]);
close(ctx.pipefd[1]);
}
// The policy is determined, unlock
UNLOCK_UID();
// Info is now useless to us, decrement reference count
--ctx.info->ref;
// Wait result
LOGD("su: waiting child: [%d]\n", child);
int status, code;
if (waitpid(child, &status, 0) > 0)
code = WEXITSTATUS(status);
else
code = -1;
/* Passing the return code back to the client:
* The client might be closed unexpectedly (e.g. swipe a root app out of recents)
* In that case, writing to the client (which doesn't exist) will result in SIGPIPE
* Here we simply just ignore the situation.
*/
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &act, NULL);
LOGD("su: return code: [%d]\n", code);
write(client, &code, sizeof(code));
close(client);
// Restore default handler for SIGPIPE
act.sa_handler = SIG_DFL;
sigaction(SIGPIPE, &act, NULL);
return;
}
LOGD("su: child process started\n");
// ack // ack
write_int(client, 0); write_int(client, 0);
...@@ -285,9 +208,9 @@ void su_daemon_receiver(int client, struct ucred *credential) { ...@@ -285,9 +208,9 @@ void su_daemon_receiver(int client, struct ucred *credential) {
// Migrate environment from client // Migrate environment from client
char path[32], buf[4096]; char path[32], buf[4096];
snprintf(path, sizeof(path), "/proc/%d/cwd", ctx.pid); snprintf(path, sizeof(path), "/proc/%d/cwd", su_ctx->pid);
xreadlink(path, ctx.cwd, sizeof(ctx.cwd)); xreadlink(path, su_ctx->cwd, sizeof(su_ctx->cwd));
snprintf(path, sizeof(path), "/proc/%d/environ", ctx.pid); snprintf(path, sizeof(path), "/proc/%d/environ", su_ctx->pid);
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
int fd = open(path, O_RDONLY); int fd = open(path, O_RDONLY);
read(fd, buf, sizeof(buf)); read(fd, buf, sizeof(buf));
...@@ -319,7 +242,6 @@ void su_daemon_receiver(int client, struct ucred *credential) { ...@@ -319,7 +242,6 @@ void su_daemon_receiver(int client, struct ucred *credential) {
// Get pts_slave // Get pts_slave
char *pts_slave = read_string(client); char *pts_slave = read_string(client);
LOGD("su: pts_slave=[%s]\n", pts_slave);
// The FDs for each of the streams // The FDs for each of the streams
int infd = recv_fd(client); int infd = recv_fd(client);
...@@ -331,13 +253,15 @@ void su_daemon_receiver(int client, struct ucred *credential) { ...@@ -331,13 +253,15 @@ void su_daemon_receiver(int client, struct ucred *credential) {
close(client); close(client);
if (pts_slave[0]) { if (pts_slave[0]) {
LOGD("su: pts_slave=[%s]\n", pts_slave);
// Check pts_slave file is owned by daemon_from_uid // Check pts_slave file is owned by daemon_from_uid
struct stat st; struct stat st;
xstat(pts_slave, &st); xstat(pts_slave, &st);
// If caller is not root, ensure the owner of pts_slave is the caller // If caller is not root, ensure the owner of pts_slave is the caller
if(st.st_uid != credential->uid && credential->uid != 0) { if(st.st_uid != su_ctx->info->uid && su_ctx->info->uid != 0) {
LOGE("su: Wrong permission of pts_slave"); LOGE("su: Wrong permission of pts_slave");
su_ctx->info->access.policy = DENY;
exit2(1); exit2(1);
} }
...@@ -369,11 +293,92 @@ void su_daemon_receiver(int client, struct ucred *credential) { ...@@ -369,11 +293,92 @@ void su_daemon_receiver(int client, struct ucred *credential) {
close(ptsfd); close(ptsfd);
// Give main the reference // Run the actual main
su_ctx = &ctx;
su_daemon_main(argc, argv); su_daemon_main(argc, argv);
} }
void su_daemon_receiver(int client, struct ucred *credential) {
LOGD("su: request from client: %d\n", client);
// Default values
struct su_context ctx = {
.info = get_su_info(credential->uid),
.to = {
.uid = UID_ROOT,
.login = 0,
.keepenv = 0,
.shell = DEFAULT_SHELL,
.command = NULL,
},
.pid = credential->pid,
.pipefd = { -1, -1 }
};
// Fail fast
if (ctx.info->access.policy == DENY && !ctx.info->access.log && !ctx.info->access.notify) {
UNLOCK_UID();
write_int(client, DENY);
return;
}
// If still not determined, open a pipe and wait for results
if (ctx.info->access.policy == QUERY)
xpipe2(ctx.pipefd, O_CLOEXEC);
/* Fork a new process, the child process will need to setsid,
* open a pseudo-terminal if needed, and will eventually run exec
* The parent process will wait for the result and
* send the return code back to our client
*/
int child = xfork();
if (child == 0) {
su_ctx = &ctx;
su_executor(client);
}
// Wait for results
if (ctx.pipefd[0] >= 0) {
xxread(ctx.pipefd[0], &ctx.info->access.policy, sizeof(policy_t));
close(ctx.pipefd[0]);
close(ctx.pipefd[1]);
}
// The policy is determined, unlock
UNLOCK_UID();
// Info is now useless to us, decrement reference count
--ctx.info->ref;
// Wait result
LOGD("su: waiting child: [%d]\n", child);
int status, code;
if (waitpid(child, &status, 0) > 0)
code = WEXITSTATUS(status);
else
code = -1;
/* Passing the return code back to the client:
* The client might be closed unexpectedly (e.g. swipe a root app out of recents)
* In that case, writing to the client (which doesn't exist) will result in SIGPIPE
* Here we simply just ignore the situation.
*/
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &act, NULL);
LOGD("su: return code: [%d]\n", code);
write(client, &code, sizeof(code));
close(client);
// Restore default handler for SIGPIPE
act.sa_handler = SIG_DFL;
sigaction(SIGPIPE, &act, NULL);
return;
}
/* /*
* Connect daemon, send argc, argv, cwd, pts slave * Connect daemon, send argc, argv, cwd, pts slave
*/ */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment