From 04fcb33d7e65b392c061a5668183d8ef4b4a7ec0 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Sat, 31 Dec 2016 01:05:20 +0800 Subject: [PATCH] Fix app request issue --- daemon.c | 121 ------------------------------------------------------- su.c | 37 +++++++++-------- su.h | 42 +++++++++---------- 3 files changed, 42 insertions(+), 158 deletions(-) diff --git a/daemon.c b/daemon.c index 5718d7300..7b0f719eb 100644 --- a/daemon.c +++ b/daemon.c @@ -444,133 +444,12 @@ static int daemon_accept(int fd) { return run_daemon_child(infd, outfd, errfd, argc, argv); } -static int copy_file(const char* src, const char* dst, int mode) { - int ifd = open(src, O_RDONLY); - if(ifd<0) - return 1; - if(mode == 0) { - struct stat stbuf; - if(fstat(ifd, &stbuf)) - return 1; - mode = stbuf.st_mode & 0777; - LOGE("File %s found mode %o", src, mode); - - } - int ofd = open(dst, O_WRONLY|O_CREAT, mode); - if(ofd<0) - return 1; - size_t s = lseek(ifd, 0, SEEK_END); - if(s<0) - return 1; - lseek(ifd, 0, SEEK_SET); - int ret = sendfile(ofd, ifd, NULL, s); - if(ret<0) - return 1; - close(ofd); - close(ifd); - return 0; -} - -static void prepare_su_bind() { - int ret = 0; - - //Check if there is a use to mount bind - if(access("/system/xbin/su", R_OK) != 0) - return; - - ret = copy_file("/sbin/su", "/dev/su/su", 0755); - if(ret) { - PLOGE("Failed to copy su"); - return; - } - chmod("/dev/su/su", 0755); - - ret = setfilecon("/dev/su/su", "u:object_r:system_file:s0"); - if(ret) { - LOGE("Failed to set file context"); - return; - } - - ret = mount("/dev/su/su", "/system/xbin/su", "", MS_BIND, NULL); - if(ret) { - LOGE("Failed to mount bind"); - return; - } -} - -static void bind_cb_func(void *arg, int uid, const char *src, const char *dst) { - int ret = 0, i = 0; - - char *tmpfile = NULL; - asprintf(&tmpfile, "/dev/su/bind%d", i++); - struct stat stbuf; - ret = stat(src, &stbuf); - if(ret) { - free(tmpfile); - LOGE("Failed to stat src %s file", src); - return; - } - - //Only shell uid is allowed to bind files not his own - if(uid != 2000 && uid != stbuf.st_uid) { - LOGE("File %s has wrong owner: %d vs %d", src, uid, stbuf.st_uid); - return; - } - - ret = copy_file(src, tmpfile, 0); - if(ret) { - free(tmpfile); - PLOGE("Failed to copy su"); - return; - } - chmod(tmpfile, stbuf.st_mode); - - ret = setfilecon(tmpfile, "u:object_r:system_file:s0"); - if(ret) { - LOGE("Failed to set file context"); - return; - } - - ret = mount(tmpfile, dst, "", MS_BIND, NULL); - if(ret) { - LOGE("Failed to mount bind"); - return; - } -} - -static void init_cb_func(void *arg, int uid, const char *path) { - int ret = 0; - - int p = fork(); - if(p) - return; - - while(access("/system/bin/sh", R_OK)) sleep(1); - ret = setexeccon("u:r:su:s0"); - execl(path, path, NULL); - LOGE("Failed to execute %s. Trying as shell script, ret = %d", path, ret); - - ret = setexeccon("u:r:su:s0"); - execl("/system/bin/sh", "/system/bin/sh", path, NULL); - LOGE("Failed to execute %s as shell script", path); - _exit(1); -} - -static void prepare() { - setfscreatecon("u:object_r:su_daemon:s0"); - mkdir("/dev/su", 0700); - prepare_su_bind(); - setfscreatecon(NULL); -} - int run_daemon() { if (getuid() != 0 || getgid() != 0) { PLOGE("daemon requires root. uid/gid not root"); return -1; } - prepare(); - switch (fork()) { case 0: break; diff --git a/su.c b/su.c index ab8d95dbc..add682e1b 100644 --- a/su.c +++ b/su.c @@ -562,10 +562,10 @@ static __attribute__ ((noreturn)) void allow(struct su_context *ctx) { arg0, PARG(0), PARG(1), PARG(2), PARG(3), PARG(4), PARG(5), (ctx->to.optind + 6 < ctx->to.argc) ? " ..." : ""); - if(ctx->to.context && strcmp(ctx->to.context, "u:r:su_light:s0") == 0) { - setexeccon(ctx->to.context); - } else { - setexeccon("u:r:su:s0"); + if(ctx->to.context && strcmp(ctx->to.context, "u:r:su_light:s0") == 0) { + setexeccon(ctx->to.context); + } else { + setexeccon("u:r:su:s0"); } ctx->to.argv[--argc] = arg0; @@ -610,7 +610,7 @@ static void fork_for_samsung(void) int main(int argc, char *argv[]) { if (argc == 2 && strcmp(argv[1], "--daemon") == 0) { //Everything we'll exec will be in su, not su_daemon - setexeccon("u:r:su:s0"); + setexeccon("u:r:su:s0"); return run_daemon(); } return su_main(argc, argv); @@ -618,15 +618,15 @@ int main(int argc, char *argv[]) { int su_main(int argc, char *argv[]) { int ppid = getppid(); - if ((geteuid() != AID_ROOT && getuid() != AID_ROOT) || - (get_api_version() >= 18 && getuid() == AID_SHELL) || - get_api_version() >= 19) { - // attempt to connect to daemon... - LOGD("starting daemon client %d %d", getuid(), geteuid()); - return connect_daemon(argc, argv, ppid); - } else { - return su_main_nodaemon(argc, argv); - } + if ((geteuid() != AID_ROOT && getuid() != AID_ROOT) || + (get_api_version() >= 18 && getuid() == AID_SHELL) || + get_api_version() >= 19) { + // attempt to connect to daemon... + LOGD("starting daemon client %d %d", getuid(), geteuid()); + return connect_daemon(argc, argv, ppid); + } else { + return su_main_nodaemon(argc, argv); + } } @@ -700,7 +700,7 @@ int su_main_nodaemon(int argc, char **argv) { .keepenv = 0, .shell = NULL, .command = NULL, - .context = NULL, + .context = NULL, .argv = argv, .argc = argc, .optind = 0, @@ -712,6 +712,11 @@ int su_main_nodaemon(int argc, char **argv) { .database_path = REQUESTOR_DATA_PATH REQUESTOR_DATABASE_PATH, .base_path = REQUESTOR_DATA_PATH REQUESTOR }, + .bind = { + .from = "", + .to = "", + }, + .init = "", }; struct stat st; int c, socket_serv_fd, fd; @@ -751,7 +756,7 @@ int su_main_nodaemon(int argc, char **argv) { printf("%d\n", VERSION_CODE); exit(EXIT_SUCCESS); case 'v': - printf("%s (topjohnwu v1)\n", VERSION); + printf("%s\n", VERSION); exit(EXIT_SUCCESS); case 'u': switch (get_multiuser_mode()) { diff --git a/su.h b/su.h index 5aaa28f6f..a727c9d61 100644 --- a/su.h +++ b/su.h @@ -79,7 +79,7 @@ #ifndef VERSION_CODE #define VERSION_CODE 1 #endif -#define VERSION xstr(VERSION_CODE) " " REQUESTOR +#define VERSION REQUESTOR " topjohnwu r" xstr(VERSION_CODE) #define PROTO_VERSION 1 @@ -98,7 +98,7 @@ struct su_request { int login; int keepenv; char *shell; - char *context; + char *context; char *command; char **argv; int argc; @@ -123,29 +123,29 @@ struct su_user_info { }; struct su_bind { - const char *from; - const char *to; + const char *from; + const char *to; }; struct su_context { struct su_initiator from; struct su_request to; struct su_user_info user; - struct su_bind bind; - const char *init; + struct su_bind bind; + const char *init; mode_t umask; char sock_path[PATH_MAX]; }; // multiuser su behavior typedef enum { - // only owner can su - MULTIUSER_MODE_OWNER_ONLY = 0, - // owner gets a su prompt - MULTIUSER_MODE_OWNER_MANAGED = 1, - // user gets a su prompt - MULTIUSER_MODE_USER = 2, - MULTIUSER_MODE_NONE = 3, + // only owner can su + MULTIUSER_MODE_OWNER_ONLY = 0, + // owner gets a su prompt + MULTIUSER_MODE_OWNER_MANAGED = 1, + // user gets a su prompt + MULTIUSER_MODE_USER = 2, + MULTIUSER_MODE_NONE = 3, } multiuser_mode_t; #define MULTIUSER_VALUE_OWNER_ONLY "owner" @@ -166,14 +166,14 @@ extern int send_result(struct su_context *ctx, policy_t policy); static inline char *get_command(const struct su_request *to) { - if (to->command) - return to->command; - if (to->shell) - return to->shell; - char* ret = to->argv[to->optind]; - if (ret) - return ret; - return DEFAULT_SHELL; + if (to->command) + return to->command; + if (to->shell) + return to->shell; + char* ret = to->argv[to->optind]; + if (ret) + return ret; + return DEFAULT_SHELL; } void exec_loge(const char* fmt, ...);