Do not fork a new process for waiting

This commit is contained in:
topjohnwu 2017-05-08 03:08:34 +08:00
parent 16527ceaf6
commit 3904ca38c0
3 changed files with 23 additions and 26 deletions

4
su.c
View File

@ -197,8 +197,8 @@ int su_daemon_main(int argc, char **argv) {
// Default values // Default values
struct su_context ctx = { struct su_context ctx = {
.from = { .from = {
.pid = from_pid, .pid = su_credentials.pid,
.uid = from_uid, .uid = su_credentials.uid,
}, },
.to = { .to = {
.uid = UID_ROOT, .uid = UID_ROOT,

2
su.h
View File

@ -102,7 +102,7 @@ typedef enum {
ALLOW = 2, ALLOW = 2,
} policy_t; } policy_t;
extern int from_uid, from_pid; extern struct ucred su_credentials;
// su.c // su.c

View File

@ -25,7 +25,7 @@
#define ATTY_OUT 2 #define ATTY_OUT 2
#define ATTY_ERR 4 #define ATTY_ERR 4
int from_uid, from_pid; struct ucred su_credentials;
static void sighandler(int sig) { static void sighandler(int sig) {
restore_stdin(); restore_stdin();
@ -50,20 +50,15 @@ static void sighandler(int sig) {
} }
} }
void su_daemon_receiver(int client) { static void sigpipe_handler(int sig) {
LOGD("su: get request\n"); LOGD("su: Client killed unexpectedly\n");
if (fork_zero_fucks()) {
// Root daemon
close(client);
return;
} }
// Set the error handler back to normal void su_daemon_receiver(int client) {
err_handler = exit_proc; LOGD("su: get request from client: %d\n", client);
// Fork a new process, the child process will need to setsid, // Fork a new process, the child process will need to setsid,
// open a pseudo-terminal, and will eventually run exec // open a pseudo-terminal if needed, and will eventually run exec
// The parent process will wait for the result and // The parent process will wait for the result and
// send the return code back to our client // send the return code back to our client
int child = fork(); int child = fork();
@ -78,8 +73,11 @@ void su_daemon_receiver(int client) {
LOGD("su: wait_result waiting for %d\n", child); LOGD("su: wait_result waiting for %d\n", child);
int status, code; int status, code;
// Change to a fancy name // Handle SIGPIPE, since we don't want to crash our daemon
strcpy(argv0, "magisksu"); struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = sigpipe_handler;
sigaction(SIGPIPE, &act, NULL);
if (waitpid(child, &status, 0) > 0) if (waitpid(child, &status, 0) > 0)
code = WEXITSTATUS(status); code = WEXITSTATUS(status);
@ -91,7 +89,7 @@ void su_daemon_receiver(int client) {
LOGD("su: return code to client: %d\n", code); LOGD("su: return code to client: %d\n", code);
close(client); close(client);
exit(code); return;
} }
LOGD("su: child process started\n"); LOGD("su: child process started\n");
@ -102,12 +100,8 @@ void su_daemon_receiver(int client) {
// Become session leader // Become session leader
xsetsid(); xsetsid();
// Check the credentials // Get the credentials
struct ucred credentials; get_client_cred(client, &su_credentials);
get_client_cred(client, &credentials);
from_uid = credentials.uid;
from_pid = credentials.pid;
// Let's read some info from the socket // Let's read some info from the socket
int argc = read_int(client); int argc = read_int(client);
@ -138,6 +132,7 @@ void su_daemon_receiver(int client) {
int infd = recv_fd(client); int infd = recv_fd(client);
int outfd = recv_fd(client); int outfd = recv_fd(client);
int errfd = recv_fd(client); int errfd = recv_fd(client);
int ptsfd = -1;
// We no longer need the access to socket in the child, close it // We no longer need the access to socket in the child, close it
close(client); close(client);
@ -148,7 +143,7 @@ void su_daemon_receiver(int client) {
xstat(pts_slave, &stbuf); xstat(pts_slave, &stbuf);
//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(stbuf.st_uid != credentials.uid && credentials.uid != 0) { if(stbuf.st_uid != su_credentials.uid && su_credentials.uid != 0) {
LOGE("su: Wrong permission of pts_slave"); LOGE("su: Wrong permission of pts_slave");
exit(1); exit(1);
} }
@ -156,7 +151,7 @@ void su_daemon_receiver(int client) {
// Opening the TTY has to occur after the // Opening the TTY has to occur after the
// fork() and setsid() so that it becomes // fork() and setsid() so that it becomes
// our controlling TTY and not the daemon's // our controlling TTY and not the daemon's
int ptsfd = xopen(pts_slave, O_RDWR); ptsfd = xopen(pts_slave, O_RDWR);
if (infd < 0) { if (infd < 0) {
LOGD("su: stdin using PTY"); LOGD("su: stdin using PTY");
@ -179,6 +174,8 @@ void su_daemon_receiver(int client) {
xdup2(outfd, STDOUT_FILENO); xdup2(outfd, STDOUT_FILENO);
xdup2(errfd, STDERR_FILENO); xdup2(errfd, STDERR_FILENO);
close(ptsfd);
su_daemon_main(argc, argv); su_daemon_main(argc, argv);
} }