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);
|
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() {
|
int run_daemon() {
|
||||||
if (getuid() != 0 || getgid() != 0) {
|
if (getuid() != 0 || getgid() != 0) {
|
||||||
PLOGE("daemon requires root. uid/gid not root");
|
PLOGE("daemon requires root. uid/gid not root");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
prepare();
|
|
||||||
|
|
||||||
switch (fork()) {
|
switch (fork()) {
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
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),
|
arg0, PARG(0), PARG(1), PARG(2), PARG(3), PARG(4), PARG(5),
|
||||||
(ctx->to.optind + 6 < ctx->to.argc) ? " ..." : "");
|
(ctx->to.optind + 6 < ctx->to.argc) ? " ..." : "");
|
||||||
|
|
||||||
if(ctx->to.context && strcmp(ctx->to.context, "u:r:su_light:s0") == 0) {
|
if(ctx->to.context && strcmp(ctx->to.context, "u:r:su_light:s0") == 0) {
|
||||||
setexeccon(ctx->to.context);
|
setexeccon(ctx->to.context);
|
||||||
} else {
|
} else {
|
||||||
setexeccon("u:r:su:s0");
|
setexeccon("u:r:su:s0");
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->to.argv[--argc] = arg0;
|
ctx->to.argv[--argc] = arg0;
|
||||||
@ -610,7 +610,7 @@ static void fork_for_samsung(void)
|
|||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
if (argc == 2 && strcmp(argv[1], "--daemon") == 0) {
|
if (argc == 2 && strcmp(argv[1], "--daemon") == 0) {
|
||||||
//Everything we'll exec will be in su, not su_daemon
|
//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 run_daemon();
|
||||||
}
|
}
|
||||||
return su_main(argc, argv);
|
return su_main(argc, argv);
|
||||||
@ -618,15 +618,15 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
int su_main(int argc, char *argv[]) {
|
int su_main(int argc, char *argv[]) {
|
||||||
int ppid = getppid();
|
int ppid = getppid();
|
||||||
if ((geteuid() != AID_ROOT && getuid() != AID_ROOT) ||
|
if ((geteuid() != AID_ROOT && getuid() != AID_ROOT) ||
|
||||||
(get_api_version() >= 18 && getuid() == AID_SHELL) ||
|
(get_api_version() >= 18 && getuid() == AID_SHELL) ||
|
||||||
get_api_version() >= 19) {
|
get_api_version() >= 19) {
|
||||||
// attempt to connect to daemon...
|
// attempt to connect to daemon...
|
||||||
LOGD("starting daemon client %d %d", getuid(), geteuid());
|
LOGD("starting daemon client %d %d", getuid(), geteuid());
|
||||||
return connect_daemon(argc, argv, ppid);
|
return connect_daemon(argc, argv, ppid);
|
||||||
} else {
|
} else {
|
||||||
return su_main_nodaemon(argc, argv);
|
return su_main_nodaemon(argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -700,7 +700,7 @@ int su_main_nodaemon(int argc, char **argv) {
|
|||||||
.keepenv = 0,
|
.keepenv = 0,
|
||||||
.shell = NULL,
|
.shell = NULL,
|
||||||
.command = NULL,
|
.command = NULL,
|
||||||
.context = NULL,
|
.context = NULL,
|
||||||
.argv = argv,
|
.argv = argv,
|
||||||
.argc = argc,
|
.argc = argc,
|
||||||
.optind = 0,
|
.optind = 0,
|
||||||
@ -712,6 +712,11 @@ int su_main_nodaemon(int argc, char **argv) {
|
|||||||
.database_path = REQUESTOR_DATA_PATH REQUESTOR_DATABASE_PATH,
|
.database_path = REQUESTOR_DATA_PATH REQUESTOR_DATABASE_PATH,
|
||||||
.base_path = REQUESTOR_DATA_PATH REQUESTOR
|
.base_path = REQUESTOR_DATA_PATH REQUESTOR
|
||||||
},
|
},
|
||||||
|
.bind = {
|
||||||
|
.from = "",
|
||||||
|
.to = "",
|
||||||
|
},
|
||||||
|
.init = "",
|
||||||
};
|
};
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int c, socket_serv_fd, fd;
|
int c, socket_serv_fd, fd;
|
||||||
@ -751,7 +756,7 @@ int su_main_nodaemon(int argc, char **argv) {
|
|||||||
printf("%d\n", VERSION_CODE);
|
printf("%d\n", VERSION_CODE);
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
case 'v':
|
case 'v':
|
||||||
printf("%s (topjohnwu v1)\n", VERSION);
|
printf("%s\n", VERSION);
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
case 'u':
|
case 'u':
|
||||||
switch (get_multiuser_mode()) {
|
switch (get_multiuser_mode()) {
|
||||||
|
42
su.h
42
su.h
@ -79,7 +79,7 @@
|
|||||||
#ifndef VERSION_CODE
|
#ifndef VERSION_CODE
|
||||||
#define VERSION_CODE 1
|
#define VERSION_CODE 1
|
||||||
#endif
|
#endif
|
||||||
#define VERSION xstr(VERSION_CODE) " " REQUESTOR
|
#define VERSION REQUESTOR " topjohnwu r" xstr(VERSION_CODE)
|
||||||
|
|
||||||
#define PROTO_VERSION 1
|
#define PROTO_VERSION 1
|
||||||
|
|
||||||
@ -98,7 +98,7 @@ struct su_request {
|
|||||||
int login;
|
int login;
|
||||||
int keepenv;
|
int keepenv;
|
||||||
char *shell;
|
char *shell;
|
||||||
char *context;
|
char *context;
|
||||||
char *command;
|
char *command;
|
||||||
char **argv;
|
char **argv;
|
||||||
int argc;
|
int argc;
|
||||||
@ -123,29 +123,29 @@ struct su_user_info {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct su_bind {
|
struct su_bind {
|
||||||
const char *from;
|
const char *from;
|
||||||
const char *to;
|
const char *to;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct su_context {
|
struct su_context {
|
||||||
struct su_initiator from;
|
struct su_initiator from;
|
||||||
struct su_request to;
|
struct su_request to;
|
||||||
struct su_user_info user;
|
struct su_user_info user;
|
||||||
struct su_bind bind;
|
struct su_bind bind;
|
||||||
const char *init;
|
const char *init;
|
||||||
mode_t umask;
|
mode_t umask;
|
||||||
char sock_path[PATH_MAX];
|
char sock_path[PATH_MAX];
|
||||||
};
|
};
|
||||||
|
|
||||||
// multiuser su behavior
|
// multiuser su behavior
|
||||||
typedef enum {
|
typedef enum {
|
||||||
// only owner can su
|
// only owner can su
|
||||||
MULTIUSER_MODE_OWNER_ONLY = 0,
|
MULTIUSER_MODE_OWNER_ONLY = 0,
|
||||||
// owner gets a su prompt
|
// owner gets a su prompt
|
||||||
MULTIUSER_MODE_OWNER_MANAGED = 1,
|
MULTIUSER_MODE_OWNER_MANAGED = 1,
|
||||||
// user gets a su prompt
|
// user gets a su prompt
|
||||||
MULTIUSER_MODE_USER = 2,
|
MULTIUSER_MODE_USER = 2,
|
||||||
MULTIUSER_MODE_NONE = 3,
|
MULTIUSER_MODE_NONE = 3,
|
||||||
} multiuser_mode_t;
|
} multiuser_mode_t;
|
||||||
|
|
||||||
#define MULTIUSER_VALUE_OWNER_ONLY "owner"
|
#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)
|
static inline char *get_command(const struct su_request *to)
|
||||||
{
|
{
|
||||||
if (to->command)
|
if (to->command)
|
||||||
return to->command;
|
return to->command;
|
||||||
if (to->shell)
|
if (to->shell)
|
||||||
return to->shell;
|
return to->shell;
|
||||||
char* ret = to->argv[to->optind];
|
char* ret = to->argv[to->optind];
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
return DEFAULT_SHELL;
|
return DEFAULT_SHELL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void exec_loge(const char* fmt, ...);
|
void exec_loge(const char* fmt, ...);
|
||||||
|
Loading…
Reference in New Issue
Block a user