mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-11-27 20:15:29 +00:00
Use inotify to monitor files
This commit is contained in:
parent
687e3b13ea
commit
d15fff95b9
@ -31,6 +31,7 @@ LOCAL_SRC_FILES := \
|
|||||||
core/daemon.c \
|
core/daemon.c \
|
||||||
core/log_monitor.c \
|
core/log_monitor.c \
|
||||||
core/bootstages.c \
|
core/bootstages.c \
|
||||||
|
core/socket.c \
|
||||||
utils/misc.c \
|
utils/misc.c \
|
||||||
utils/vector.c \
|
utils/vector.c \
|
||||||
utils/xwrap.c \
|
utils/xwrap.c \
|
||||||
|
@ -575,9 +575,6 @@ void post_fs(int client) {
|
|||||||
write_int(client, 0);
|
write_int(client, 0);
|
||||||
close(client);
|
close(client);
|
||||||
|
|
||||||
// Allow magiskinit to full patch
|
|
||||||
close(creat(PATCHSTART, 0));
|
|
||||||
|
|
||||||
// Uninstall or core only mode
|
// Uninstall or core only mode
|
||||||
if (access(UNINSTALLER, F_OK) == 0 || access(DISABLEFILE, F_OK) == 0)
|
if (access(UNINSTALLER, F_OK) == 0 || access(DISABLEFILE, F_OK) == 0)
|
||||||
goto unblock;
|
goto unblock;
|
||||||
@ -744,9 +741,7 @@ void late_start(int client) {
|
|||||||
if (buf2 == NULL) buf2 = xmalloc(PATH_MAX);
|
if (buf2 == NULL) buf2 = xmalloc(PATH_MAX);
|
||||||
|
|
||||||
// Wait till the full patch is done
|
// Wait till the full patch is done
|
||||||
while (access(PATCHDONE, F_OK) == -1)
|
wait_till_exists(PATCHDONE);
|
||||||
usleep(500); /* Wait 0.5ms */
|
|
||||||
unlink(PATCHDONE);
|
|
||||||
|
|
||||||
// Run scripts after full patch, most reliable way to run scripts
|
// Run scripts after full patch, most reliable way to run scripts
|
||||||
LOGI("* Running service.d scripts\n");
|
LOGI("* Running service.d scripts\n");
|
||||||
|
@ -13,9 +13,6 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/mount.h>
|
|
||||||
#include <selinux/selinux.h>
|
#include <selinux/selinux.h>
|
||||||
|
|
||||||
#include "magisk.h"
|
#include "magisk.h"
|
||||||
@ -95,14 +92,6 @@ static void *request_handler(void *args) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Setup the address and return socket fd */
|
|
||||||
static int setup_socket(struct sockaddr_un *sun) {
|
|
||||||
int fd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
|
||||||
memset(sun, 0, sizeof(*sun));
|
|
||||||
sun->sun_family = AF_LOCAL;
|
|
||||||
memcpy(sun->sun_path, REQUESTOR_DAEMON_PATH, sizeof(REQUESTOR_DAEMON_PATH) - 1);
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *start_magisk_hide(void *args) {
|
static void *start_magisk_hide(void *args) {
|
||||||
launch_magiskhide(-1);
|
launch_magiskhide(-1);
|
||||||
@ -199,136 +188,3 @@ int connect_daemon() {
|
|||||||
}
|
}
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Receive a file descriptor from a Unix socket.
|
|
||||||
* Contributed by @mkasick
|
|
||||||
*
|
|
||||||
* Returns the file descriptor on success, or -1 if a file
|
|
||||||
* descriptor was not actually included in the message
|
|
||||||
*
|
|
||||||
* On error the function terminates by calling exit(-1)
|
|
||||||
*/
|
|
||||||
int recv_fd(int sockfd) {
|
|
||||||
// Need to receive data from the message, otherwise don't care about it.
|
|
||||||
char iovbuf;
|
|
||||||
|
|
||||||
struct iovec iov = {
|
|
||||||
.iov_base = &iovbuf,
|
|
||||||
.iov_len = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
char cmsgbuf[CMSG_SPACE(sizeof(int))];
|
|
||||||
|
|
||||||
struct msghdr msg = {
|
|
||||||
.msg_iov = &iov,
|
|
||||||
.msg_iovlen = 1,
|
|
||||||
.msg_control = cmsgbuf,
|
|
||||||
.msg_controllen = sizeof(cmsgbuf),
|
|
||||||
};
|
|
||||||
|
|
||||||
xrecvmsg(sockfd, &msg, MSG_WAITALL);
|
|
||||||
|
|
||||||
// Was a control message actually sent?
|
|
||||||
switch (msg.msg_controllen) {
|
|
||||||
case 0:
|
|
||||||
// No, so the file descriptor was closed and won't be used.
|
|
||||||
return -1;
|
|
||||||
case sizeof(cmsgbuf):
|
|
||||||
// Yes, grab the file descriptor from it.
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
|
|
||||||
|
|
||||||
if (cmsg == NULL ||
|
|
||||||
cmsg->cmsg_len != CMSG_LEN(sizeof(int)) ||
|
|
||||||
cmsg->cmsg_level != SOL_SOCKET ||
|
|
||||||
cmsg->cmsg_type != SCM_RIGHTS) {
|
|
||||||
error:
|
|
||||||
LOGE("unable to read fd");
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return *(int *)CMSG_DATA(cmsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Send a file descriptor through a Unix socket.
|
|
||||||
* Contributed by @mkasick
|
|
||||||
*
|
|
||||||
* On error the function terminates by calling exit(-1)
|
|
||||||
*
|
|
||||||
* fd may be -1, in which case the dummy data is sent,
|
|
||||||
* but no control message with the FD is sent.
|
|
||||||
*/
|
|
||||||
void send_fd(int sockfd, int fd) {
|
|
||||||
// Need to send some data in the message, this will do.
|
|
||||||
struct iovec iov = {
|
|
||||||
.iov_base = "",
|
|
||||||
.iov_len = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct msghdr msg = {
|
|
||||||
.msg_iov = &iov,
|
|
||||||
.msg_iovlen = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
char cmsgbuf[CMSG_SPACE(sizeof(int))];
|
|
||||||
|
|
||||||
if (fd != -1) {
|
|
||||||
// Is the file descriptor actually open?
|
|
||||||
if (fcntl(fd, F_GETFD) == -1) {
|
|
||||||
if (errno != EBADF) {
|
|
||||||
PLOGE("unable to send fd");
|
|
||||||
}
|
|
||||||
// It's closed, don't send a control message or sendmsg will EBADF.
|
|
||||||
} else {
|
|
||||||
// It's open, send the file descriptor in a control message.
|
|
||||||
msg.msg_control = cmsgbuf;
|
|
||||||
msg.msg_controllen = sizeof(cmsgbuf);
|
|
||||||
|
|
||||||
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
|
|
||||||
|
|
||||||
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
|
|
||||||
cmsg->cmsg_level = SOL_SOCKET;
|
|
||||||
cmsg->cmsg_type = SCM_RIGHTS;
|
|
||||||
|
|
||||||
*(int *)CMSG_DATA(cmsg) = fd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
xsendmsg(sockfd, &msg, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int read_int(int fd) {
|
|
||||||
int val;
|
|
||||||
xxread(fd, &val, sizeof(int));
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_int(int fd, int val) {
|
|
||||||
if (fd < 0) return;
|
|
||||||
xwrite(fd, &val, sizeof(int));
|
|
||||||
}
|
|
||||||
|
|
||||||
char* read_string(int fd) {
|
|
||||||
int len = read_int(fd);
|
|
||||||
if (len > PATH_MAX || len < 0) {
|
|
||||||
LOGE("invalid string length %d", len);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
char* val = xmalloc(sizeof(char) * (len + 1));
|
|
||||||
xxread(fd, val, len);
|
|
||||||
val[len] = '\0';
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_string(int fd, const char* val) {
|
|
||||||
if (fd < 0) return;
|
|
||||||
int len = strlen(val);
|
|
||||||
write_int(fd, len);
|
|
||||||
xwrite(fd, val, len);
|
|
||||||
}
|
|
||||||
|
@ -340,6 +340,17 @@ static int dump_magiskrc(const char *path, mode_t mode) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void magisk_init_daemon() {
|
||||||
|
// Fork a new process for full patch
|
||||||
|
setsid();
|
||||||
|
sepol_allow("su", ALL, ALL, ALL);
|
||||||
|
wait_till_exists("/dev/.coldboot_done");
|
||||||
|
dump_policydb(SELINUX_LOAD);
|
||||||
|
close(open(PATCHDONE, O_RDONLY | O_CREAT, 0));
|
||||||
|
destroy_policydb();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
umask(0);
|
umask(0);
|
||||||
|
|
||||||
@ -423,18 +434,8 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
umount("/vendor");
|
umount("/vendor");
|
||||||
|
|
||||||
if (fork() == 0) {
|
if (fork() == 0)
|
||||||
// Fork a new process for full patch
|
magisk_init_daemon();
|
||||||
setsid();
|
|
||||||
sepol_allow("su", ALL, ALL, ALL);
|
|
||||||
while (access(PATCHSTART, W_OK) == -1)
|
|
||||||
usleep(500); /* Wait 0.5ms */
|
|
||||||
unlink(PATCHSTART);
|
|
||||||
dump_policydb(SELINUX_LOAD);
|
|
||||||
close(open(PATCHDONE, O_RDONLY | O_CREAT, 0));
|
|
||||||
destroy_policydb();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finally, give control back!
|
// Finally, give control back!
|
||||||
execv("/init", argv);
|
execv("/init", argv);
|
||||||
|
152
jni/core/socket.c
Normal file
152
jni/core/socket.c
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
/* socket.c - All socket related operations
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include "daemon.h"
|
||||||
|
#include "logging.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "magisk.h"
|
||||||
|
|
||||||
|
/* Setup the address and return socket fd */
|
||||||
|
int setup_socket(struct sockaddr_un *sun) {
|
||||||
|
int fd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||||
|
memset(sun, 0, sizeof(*sun));
|
||||||
|
sun->sun_family = AF_LOCAL;
|
||||||
|
memcpy(sun->sun_path, REQUESTOR_DAEMON_PATH, sizeof(REQUESTOR_DAEMON_PATH) - 1);
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Receive a file descriptor from a Unix socket.
|
||||||
|
* Contributed by @mkasick
|
||||||
|
*
|
||||||
|
* Returns the file descriptor on success, or -1 if a file
|
||||||
|
* descriptor was not actually included in the message
|
||||||
|
*
|
||||||
|
* On error the function terminates by calling exit(-1)
|
||||||
|
*/
|
||||||
|
int recv_fd(int sockfd) {
|
||||||
|
// Need to receive data from the message, otherwise don't care about it.
|
||||||
|
char iovbuf;
|
||||||
|
|
||||||
|
struct iovec iov = {
|
||||||
|
.iov_base = &iovbuf,
|
||||||
|
.iov_len = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
char cmsgbuf[CMSG_SPACE(sizeof(int))];
|
||||||
|
|
||||||
|
struct msghdr msg = {
|
||||||
|
.msg_iov = &iov,
|
||||||
|
.msg_iovlen = 1,
|
||||||
|
.msg_control = cmsgbuf,
|
||||||
|
.msg_controllen = sizeof(cmsgbuf),
|
||||||
|
};
|
||||||
|
|
||||||
|
xrecvmsg(sockfd, &msg, MSG_WAITALL);
|
||||||
|
|
||||||
|
// Was a control message actually sent?
|
||||||
|
switch (msg.msg_controllen) {
|
||||||
|
case 0:
|
||||||
|
// No, so the file descriptor was closed and won't be used.
|
||||||
|
return -1;
|
||||||
|
case sizeof(cmsgbuf):
|
||||||
|
// Yes, grab the file descriptor from it.
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
|
||||||
|
|
||||||
|
if (cmsg == NULL ||
|
||||||
|
cmsg->cmsg_len != CMSG_LEN(sizeof(int)) ||
|
||||||
|
cmsg->cmsg_level != SOL_SOCKET ||
|
||||||
|
cmsg->cmsg_type != SCM_RIGHTS) {
|
||||||
|
error:
|
||||||
|
LOGE("unable to read fd");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *(int *)CMSG_DATA(cmsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send a file descriptor through a Unix socket.
|
||||||
|
* Contributed by @mkasick
|
||||||
|
*
|
||||||
|
* On error the function terminates by calling exit(-1)
|
||||||
|
*
|
||||||
|
* fd may be -1, in which case the dummy data is sent,
|
||||||
|
* but no control message with the FD is sent.
|
||||||
|
*/
|
||||||
|
void send_fd(int sockfd, int fd) {
|
||||||
|
// Need to send some data in the message, this will do.
|
||||||
|
struct iovec iov = {
|
||||||
|
.iov_base = "",
|
||||||
|
.iov_len = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct msghdr msg = {
|
||||||
|
.msg_iov = &iov,
|
||||||
|
.msg_iovlen = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
char cmsgbuf[CMSG_SPACE(sizeof(int))];
|
||||||
|
|
||||||
|
if (fd != -1) {
|
||||||
|
// Is the file descriptor actually open?
|
||||||
|
if (fcntl(fd, F_GETFD) == -1) {
|
||||||
|
if (errno != EBADF) {
|
||||||
|
PLOGE("unable to send fd");
|
||||||
|
}
|
||||||
|
// It's closed, don't send a control message or sendmsg will EBADF.
|
||||||
|
} else {
|
||||||
|
// It's open, send the file descriptor in a control message.
|
||||||
|
msg.msg_control = cmsgbuf;
|
||||||
|
msg.msg_controllen = sizeof(cmsgbuf);
|
||||||
|
|
||||||
|
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
|
||||||
|
|
||||||
|
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
|
||||||
|
cmsg->cmsg_level = SOL_SOCKET;
|
||||||
|
cmsg->cmsg_type = SCM_RIGHTS;
|
||||||
|
|
||||||
|
*(int *)CMSG_DATA(cmsg) = fd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xsendmsg(sockfd, &msg, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int read_int(int fd) {
|
||||||
|
int val;
|
||||||
|
xxread(fd, &val, sizeof(int));
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_int(int fd, int val) {
|
||||||
|
if (fd < 0) return;
|
||||||
|
xwrite(fd, &val, sizeof(int));
|
||||||
|
}
|
||||||
|
|
||||||
|
char* read_string(int fd) {
|
||||||
|
int len = read_int(fd);
|
||||||
|
if (len > PATH_MAX || len < 0) {
|
||||||
|
LOGE("invalid string length %d", len);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
char* val = xmalloc(sizeof(char) * (len + 1));
|
||||||
|
xxread(fd, val, len);
|
||||||
|
val[len] = '\0';
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_string(int fd, const char* val) {
|
||||||
|
if (fd < 0) return;
|
||||||
|
int len = strlen(val);
|
||||||
|
write_int(fd, len);
|
||||||
|
xwrite(fd, val, len);
|
||||||
|
}
|
@ -5,6 +5,7 @@
|
|||||||
#define _DAEMON_H_
|
#define _DAEMON_H_
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
|
||||||
extern pthread_t sepol_patch;
|
extern pthread_t sepol_patch;
|
||||||
extern int is_restart;
|
extern int is_restart;
|
||||||
@ -42,6 +43,10 @@ typedef enum {
|
|||||||
void start_daemon();
|
void start_daemon();
|
||||||
int connect_daemon();
|
int connect_daemon();
|
||||||
void auto_start_magiskhide();
|
void auto_start_magiskhide();
|
||||||
|
|
||||||
|
// socket.c
|
||||||
|
|
||||||
|
int setup_socket(struct sockaddr_un *sun);
|
||||||
int recv_fd(int sockfd);
|
int recv_fd(int sockfd);
|
||||||
void send_fd(int sockfd, int fd);
|
void send_fd(int sockfd, int fd);
|
||||||
int read_int(int fd);
|
int read_int(int fd);
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
#define LASTLOG "/cache/last_magisk.log"
|
#define LASTLOG "/cache/last_magisk.log"
|
||||||
#define DEBUG_LOG "/data/magisk_debug.log"
|
#define DEBUG_LOG "/data/magisk_debug.log"
|
||||||
#define UNBLOCKFILE "/dev/.magisk.unblock"
|
#define UNBLOCKFILE "/dev/.magisk.unblock"
|
||||||
#define PATCHSTART "/dev/.magisk.patch.start"
|
|
||||||
#define PATCHDONE "/dev/.magisk.patch.done"
|
#define PATCHDONE "/dev/.magisk.patch.done"
|
||||||
#define DISABLEFILE "/cache/.disable_magisk"
|
#define DISABLEFILE "/cache/.disable_magisk"
|
||||||
#define UNINSTALLER "/cache/magisk_uninstaller.sh"
|
#define UNINSTALLER "/cache/magisk_uninstaller.sh"
|
||||||
|
@ -89,6 +89,7 @@ int bind_mount(const char *from, const char *to);
|
|||||||
void get_client_cred(int fd, struct ucred *cred);
|
void get_client_cred(int fd, struct ucred *cred);
|
||||||
int switch_mnt_ns(int pid);
|
int switch_mnt_ns(int pid);
|
||||||
int fork_dont_care();
|
int fork_dont_care();
|
||||||
|
void wait_till_exists(const char *target);
|
||||||
|
|
||||||
// file.c
|
// file.c
|
||||||
|
|
||||||
|
@ -6,8 +6,10 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <libgen.h>
|
||||||
#include <sys/sendfile.h>
|
#include <sys/sendfile.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
#include <sys/inotify.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
|
|
||||||
#ifndef NO_SELINUX
|
#ifndef NO_SELINUX
|
||||||
@ -216,6 +218,23 @@ void clone_dir(int src, int dest) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wait_till_exists(const char *target) {
|
||||||
|
if (access(target, F_OK) == 0)
|
||||||
|
return;
|
||||||
|
int fd = inotify_init();
|
||||||
|
char *dir = dirname(target);
|
||||||
|
char crap[PATH_MAX];
|
||||||
|
inotify_add_watch(fd, dir, IN_CREATE);
|
||||||
|
while (1) {
|
||||||
|
struct inotify_event event;
|
||||||
|
read(fd, &event, sizeof(event));
|
||||||
|
read(fd, crap, event.len);
|
||||||
|
if (access(target, F_OK) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
int getattr(const char *path, struct file_attr *a) {
|
int getattr(const char *path, struct file_attr *a) {
|
||||||
if (xlstat(path, &a->st) == -1)
|
if (xlstat(path, &a->st) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
Loading…
Reference in New Issue
Block a user