Fix app request issue
This commit is contained in:
parent
f31d2486c9
commit
04fcb33d7e
121
daemon.c
121
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;
|
||||
|
37
su.c
37
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()) {
|
||||
|
42
su.h
42
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, ...);
|
||||
|
Loading…
Reference in New Issue
Block a user