diff --git a/jni/daemon/bootstages.c b/jni/daemon/bootstages.c index 3755ccad2..9a27ce592 100644 --- a/jni/daemon/bootstages.c +++ b/jni/daemon/bootstages.c @@ -145,7 +145,7 @@ static void exec_common_script(const char* stage) { struct dirent *entry; snprintf(buf, PATH_MAX, "%s/%s.d", COREDIR, stage); - if (!(dir = opendir(buf))) + if (!(dir = xopendir(buf))) return; while ((entry = xreaddir(dir))) { @@ -190,7 +190,7 @@ static void construct_tree(const char *module, struct node_entry *parent) { char *parent_path = get_full_path(parent); snprintf(buf, PATH_MAX, "%s/%s%s", MOUNTPOINT, module, parent_path); - if (!(dir = opendir(buf))) + if (!(dir = xopendir(buf))) goto cleanup; while ((entry = xreaddir(dir))) { @@ -258,7 +258,7 @@ static void clone_skeleton(struct node_entry *node) { // Clone the structure char *full_path = get_full_path(node); snprintf(buf, PATH_MAX, "%s%s", MIRRDIR, full_path); - if (!(dir = opendir(buf))) + if (!(dir = xopendir(buf))) goto cleanup; while ((entry = xreaddir(dir))) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) @@ -278,7 +278,7 @@ static void clone_skeleton(struct node_entry *node) { xstat(full_path, &s); getfilecon(full_path, &con); LOGI("tmpfs: %s\n", full_path); - mount("tmpfs", full_path, "tmpfs", 0, NULL); + xmount("tmpfs", full_path, "tmpfs", 0, NULL); chmod(full_path, s.st_mode & 0777); chown(full_path, s.st_uid, s.st_gid); setfilecon(full_path, con); @@ -405,11 +405,11 @@ static void daemon_init() { // Setup links under /sbin xmount(NULL, "/", NULL, MS_REMOUNT, NULL); xmkdir("/root", 0755); - xchmod("/root", 0755); + chmod("/root", 0755); root = xopen("/root", O_RDONLY | O_CLOEXEC); sbin = xopen("/sbin", O_RDONLY | O_CLOEXEC); - dir = fdopendir(sbin); - while((entry = readdir(dir))) { + dir = xfdopendir(sbin); + while((entry = xreaddir(dir))) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; linkat(sbin, entry->d_name, root, entry->d_name, 0); if (strcmp(entry->d_name, "magisk") == 0) @@ -420,16 +420,16 @@ static void daemon_init() { sbin = xopen("/sbin", O_RDONLY | O_CLOEXEC); fchmod(sbin, 0755); fsetfilecon(sbin, "u:object_r:rootfs:s0"); - dir = fdopendir(root); - while((entry = readdir(dir))) { + dir = xfdopendir(root); + while((entry = xreaddir(dir))) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; snprintf(target, sizeof(target), "/root/%s", entry->d_name); snprintf(linkpath, sizeof(linkpath), "/sbin/%s", entry->d_name); - symlink(target, linkpath); + xsymlink(target, linkpath); } for (int i = 0; applet[i]; ++i) { snprintf(linkpath, sizeof(linkpath), "/sbin/%s", applet[i]); - symlink("/root/magisk", linkpath); + xsymlink("/root/magisk", linkpath); } xmkdir("/magisk", 0755); xmount(NULL, "/", NULL, MS_REMOUNT | MS_RDONLY, NULL); @@ -476,20 +476,20 @@ static void daemon_init() { } vec_deep_destroy(&mounts); if (!seperate_vendor) { - symlink(MIRRDIR "/system/vendor", MIRRDIR "/vendor"); + xsymlink(MIRRDIR "/system/vendor", MIRRDIR "/vendor"); #ifdef MAGISK_DEBUG LOGI("link: %s -> %s\n", MIRRDIR "/system/vendor", MIRRDIR "/vendor"); #else LOGI("link: %s\n", MIRRDIR "/vendor"); #endif } - mkdir_p(MIRRDIR "/bin", 0755); + xmkdir_p(MIRRDIR "/bin", 0755); bind_mount(DATABIN, MIRRDIR "/bin"); LOGI("* Setting up internal busybox"); - mkdir_p(BBPATH, 0755); + xmkdir_p(BBPATH, 0755); exec_command_sync(MIRRDIR "/bin/busybox", "--install", "-s", BBPATH, NULL); - symlink(MIRRDIR "/bin/busybox", BBPATH "/busybox"); + xsymlink(MIRRDIR "/bin/busybox", BBPATH "/busybox"); } static int prepare_img() { @@ -569,7 +569,7 @@ void fix_filecon() { ****************/ static void unblock_boot_process() { - close(open(UNBLOCKFILE, O_RDONLY | O_CREAT)); + close(xopen(UNBLOCKFILE, O_RDONLY | O_CREAT)); pthread_exit(NULL); } @@ -689,7 +689,7 @@ void post_fs_data(int client) { if (access(buf, F_OK) == 0) { snprintf(buf2, PATH_MAX, "%s/%s/vendor", MOUNTPOINT, module); unlink(buf2); - symlink(buf, buf2); + xsymlink(buf, buf2); } construct_tree(module, sys_root); } @@ -729,7 +729,6 @@ core_only: auto_start_magiskhide(); - unblock: unblock_boot_process(); } diff --git a/jni/daemon/daemon.c b/jni/daemon/daemon.c index d73fffb69..bff8478d1 100644 --- a/jni/daemon/daemon.c +++ b/jni/daemon/daemon.c @@ -155,7 +155,7 @@ void start_daemon() { dump_policydb(SELINUX_LOAD); // Continue the larger patch in another thread, we will join later - pthread_create(&sepol_patch, NULL, large_sepol_patch, NULL); + xpthread_create(&sepol_patch, NULL, large_sepol_patch, NULL); struct sockaddr_un sun; fd = setup_socket(&sun); @@ -170,7 +170,7 @@ void start_daemon() { unlock_blocks(); // Notifiy init the daemon is started - close(open(UNBLOCKFILE, O_RDONLY)); + close(xopen(UNBLOCKFILE, O_RDONLY)); // Loop forever to listen for requests while(1) { @@ -187,25 +187,19 @@ void start_daemon() { int connect_daemon() { struct sockaddr_un sun; int fd = setup_socket(&sun); - if (connect(fd, (struct sockaddr*) &sun, sizeof(sun))) { + if (xconnect(fd, (struct sockaddr*) &sun, sizeof(sun))) { // If we cannot access the daemon, we start a daemon in the child process if possible if (getuid() != UID_ROOT || getgid() != UID_ROOT) { - fprintf(stderr, "Starting daemon requires root: %s\n", strerror(errno)); - PLOGE("start daemon"); + fprintf(stderr, "No daemon is currently running!\n"); + exit(1); } - switch (fork()) { - case -1: - PLOGE("fork"); - case 0: + if (xfork() == 0) { LOGD("client: connect fail, try launching new daemon process\n"); close(fd); xsetsid(); start_daemon(); - break; - default: - break; } do { diff --git a/jni/include/utils.h b/jni/include/utils.h index b79eed609..c22d93a10 100644 --- a/jni/include/utils.h +++ b/jni/include/utils.h @@ -24,12 +24,14 @@ FILE *xfdopen(int fd, const char *mode); #define xopen(...) GET_MACRO(__VA_ARGS__, xopen3, xopen2)(__VA_ARGS__) int xopen2(const char *pathname, int flags); int xopen3(const char *pathname, int flags, mode_t mode); +int xopenat(int dirfd, const char *pathname, int flags); ssize_t xwrite(int fd, const void *buf, size_t count); ssize_t xread(int fd, void *buf, size_t count); ssize_t xxread(int fd, void *buf, size_t count); int xpipe2(int pipefd[2], int flags); int xsetns(int fd, int nstype); DIR *xopendir(const char *name); +DIR *xfdopendir(int fd); struct dirent *xreaddir(DIR *dirp); pid_t xsetsid(); int xsocket(int domain, int type, int protocol); @@ -49,19 +51,21 @@ int xstat(const char *pathname, struct stat *buf); int xlstat(const char *pathname, struct stat *buf); int xdup2(int oldfd, int newfd); ssize_t xreadlink(const char *pathname, char *buf, size_t bufsiz); +ssize_t xreadlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz); int xsymlink(const char *target, const char *linkpath); int xmount(const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, const void *data); int xumount(const char *target); int xumount2(const char *target, int flags); -int xchmod(const char *pathname, mode_t mode); int xrename(const char *oldpath, const char *newpath); int xmkdir(const char *pathname, mode_t mode); +int xmkdir_p(const char *pathname, mode_t mode); +int xmkdirat(int dirfd, const char *pathname, mode_t mode); void *xmmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); ssize_t xsendfile(int out_fd, int in_fd, off_t *offset, size_t count); -int xmkdir_p(const char *pathname, mode_t mode); +pid_t xfork(); // misc.c diff --git a/jni/utils/file.c b/jni/utils/file.c index 88d573f1d..e50d25d30 100644 --- a/jni/utils/file.c +++ b/jni/utils/file.c @@ -50,16 +50,16 @@ void rm_rf(const char *path) { void frm_rf(int dirfd) { struct dirent *entry; int newfd; - DIR *dir = fdopendir(dirfd); + DIR *dir = xfdopendir(dirfd); - while ((entry = readdir(dir))) { + while ((entry = xreaddir(dir))) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; if (is_excl(entry->d_name)) continue; switch (entry->d_type) { case DT_DIR: - newfd = openat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC); + newfd = xopenat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC); frm_rf(newfd); close(newfd); unlinkat(dirfd, entry->d_name, AT_REMOVEDIR); @@ -88,7 +88,7 @@ void mv_f(const char *source, const char *destination) { close(dest); } else{ getattr(source, &a); - rename(source, destination); + xrename(source, destination); setattr(destination, &a); } rmdir(source); @@ -101,8 +101,8 @@ void mv_dir(int src, int dest) { int newsrc, newdest; struct file_attr a; - dir = fdopendir(src); - while ((entry = readdir(dir))) { + dir = xfdopendir(src); + while ((entry = xreaddir(dir))) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; if (is_excl(entry->d_name)) @@ -110,9 +110,9 @@ void mv_dir(int src, int dest) { getattrat(src, entry->d_name, &a); switch (entry->d_type) { case DT_DIR: - mkdirat(dest, entry->d_name, a.st.st_mode & 0777); - newsrc = openat(src, entry->d_name, O_RDONLY | O_CLOEXEC); - newdest = openat(dest, entry->d_name, O_RDONLY | O_CLOEXEC); + xmkdirat(dest, entry->d_name, a.st.st_mode & 0777); + newsrc = xopenat(src, entry->d_name, O_RDONLY | O_CLOEXEC); + newdest = xopenat(dest, entry->d_name, O_RDONLY | O_CLOEXEC); fsetattr(newdest, &a); mv_dir(newsrc, newdest); close(newsrc); @@ -164,11 +164,10 @@ void clone_dir(int src, int dest) { DIR *dir; int srcfd, destfd, newsrc, newdest; char buf[PATH_MAX]; - ssize_t size; struct file_attr a; - dir = fdopendir(src); - while ((entry = readdir(dir))) { + dir = xfdopendir(src); + while ((entry = xreaddir(dir))) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; if (is_excl(entry->d_name)) @@ -176,25 +175,24 @@ void clone_dir(int src, int dest) { getattrat(src, entry->d_name, &a); switch (entry->d_type) { case DT_DIR: - mkdirat(dest, entry->d_name, a.st.st_mode & 0777); + xmkdirat(dest, entry->d_name, a.st.st_mode & 0777); setattrat(dest, entry->d_name, &a); - newsrc = openat(src, entry->d_name, O_RDONLY | O_CLOEXEC); - newdest = openat(dest, entry->d_name, O_RDONLY | O_CLOEXEC); + newsrc = xopenat(src, entry->d_name, O_RDONLY | O_CLOEXEC); + newdest = xopenat(dest, entry->d_name, O_RDONLY | O_CLOEXEC); clone_dir(newsrc, newdest); close(newsrc); close(newdest); break; case DT_REG: - destfd = openat(dest, entry->d_name, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, a.st.st_mode & 0777); - srcfd = openat(src, entry->d_name, O_RDONLY | O_CLOEXEC); - sendfile(destfd, srcfd, 0, a.st.st_size); + destfd = xopenat(dest, entry->d_name, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC); + srcfd = xopenat(src, entry->d_name, O_RDONLY | O_CLOEXEC); + xsendfile(destfd, srcfd, 0, a.st.st_size); fsetattr(destfd, &a); close(destfd); close(srcfd); break; case DT_LNK: - size = readlinkat(src, entry->d_name, buf, sizeof(buf)); - buf[size] = '\0'; + xreadlinkat(src, entry->d_name, buf, sizeof(buf)); symlinkat(buf, dest, entry->d_name); setattrat(dest, entry->d_name, &a); break; @@ -285,15 +283,15 @@ void restorecon(int dirfd, int force) { fsetfilecon(dirfd, SYSTEM_CON); freecon(con); - dir = fdopendir(dirfd); - while ((entry = readdir(dir))) { + dir = xfdopendir(dirfd); + while ((entry = xreaddir(dir))) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; if (entry->d_type == DT_DIR) { - fd = openat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC); + fd = xopenat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC); restorecon(fd, force); } else { - fd = openat(dirfd, entry->d_name, O_PATH | O_NOFOLLOW | O_CLOEXEC); + fd = xopenat(dirfd, entry->d_name, O_PATH | O_NOFOLLOW | O_CLOEXEC); fgetfilecon(fd, &con); if (force || strlen(con) == 0 || strcmp(con, UNLABEL_CON) == 0) fsetfilecon(fd, SYSTEM_CON); diff --git a/jni/utils/img.c b/jni/utils/img.c index 761c9c1a0..11fafea21 100644 --- a/jni/utils/img.c +++ b/jni/utils/img.c @@ -164,7 +164,7 @@ int merge_img(const char *source, const char *target) { if (access(source, F_OK) == -1) return 0; if (access(target, F_OK) == -1) { - rename(source, target); + xrename(source, target); return 0; } @@ -188,7 +188,7 @@ int merge_img(const char *source, const char *target) { DIR *dir; struct dirent *entry; - if (!(dir = opendir(SOURCE_TMP))) + if (!(dir = xopendir(SOURCE_TMP))) return 1; while ((entry = xreaddir(dir))) { if (entry->d_type == DT_DIR) { diff --git a/jni/utils/misc.c b/jni/utils/misc.c index b2bfe0cd4..8840db55c 100644 --- a/jni/utils/misc.c +++ b/jni/utils/misc.c @@ -140,12 +140,12 @@ static void proc_name_filter(int pid) { char buf[64]; int fd; snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid); - if ((fd = open(buf, O_RDONLY)) == -1) + if (access(buf, R_OK) == -1 || (fd = xopen(buf, O_RDONLY)) == -1) return; if (fdgets(buf, sizeof(buf), fd) == 0) { snprintf(buf, sizeof(buf), "/proc/%d/comm", pid); close(fd); - if ((fd = open(buf, O_RDONLY)) == -1) + if (access(buf, R_OK) == -1 || (fd = xopen(buf, O_RDONLY)) == -1) return; fdgets(buf, sizeof(buf), fd); } @@ -169,7 +169,7 @@ void unlock_blocks() { if ((dev = xopen("/dev/block", O_RDONLY | O_CLOEXEC)) < 0) return; - dir = fdopendir(dev); + dir = xfdopendir(dev); while((entry = readdir(dir))) { if (entry->d_type == DT_BLK) { @@ -231,7 +231,7 @@ static int v_exec_command(int err, int *fd, void (*setupenv)(struct vector*), co envp = environ; } - int pid = fork(); + int pid = xfork(); if (pid != 0) { if (fd && *fd < 0) { // Give the read end and close write end @@ -308,11 +308,11 @@ int switch_mnt_ns(int pid) { } int fork_dont_care() { - int pid = fork(); + int pid = xfork(); if (pid) { waitpid(pid, NULL, 0); return pid; - } else if ((pid = fork())) { + } else if ((pid = xfork())) { exit(0); } return 0; diff --git a/jni/utils/xwrap.c b/jni/utils/xwrap.c index a2544d98d..cdc6373aa 100644 --- a/jni/utils/xwrap.c +++ b/jni/utils/xwrap.c @@ -1,8 +1,8 @@ /* xwrap.c - wrappers around existing library functions. * - * Functions with the x prefix are wrappers that either succeed or kill the - * program with an error message, but never return failure. They usually have - * the same arguments and return value as the function they wrap. + * Functions with the x prefix are wrappers that either succeed or log the + * error message. They usually have the same arguments and return value + * as the function they wrap. * */ @@ -57,6 +57,14 @@ int xopen3(const char *pathname, int flags, mode_t mode) { return fd; } +int xopenat(int dirfd, const char *pathname, int flags) { + int fd = openat(dirfd, pathname, flags); + if (fd < 0) { + PLOGE("openat: %s", pathname); + } + return fd; +} + ssize_t xwrite(int fd, const void *buf, size_t count) { int ret = write(fd, buf, count); if (count != ret) { @@ -107,6 +115,14 @@ DIR *xopendir(const char *name) { return d; } +DIR *xfdopendir(int fd) { + DIR *d = fdopendir(fd); + if (d == NULL) { + PLOGE("fdopendir"); + } + return d; +} + struct dirent *xreaddir(DIR *dirp) { errno = 0; struct dirent *e = readdir(dirp); @@ -251,7 +267,16 @@ ssize_t xreadlink(const char *pathname, char *buf, size_t bufsiz) { PLOGE("readlink %s", pathname); } else { buf[ret] = '\0'; - ++ret; + } + return ret; +} + +ssize_t xreadlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz) { + ssize_t ret = readlinkat(dirfd, pathname, buf, bufsiz); + if (ret == -1) { + PLOGE("readlinkat %s", pathname); + } else { + buf[ret] = '\0'; } return ret; } @@ -290,14 +315,6 @@ int xumount2(const char *target, int flags) { return ret; } -int xchmod(const char *pathname, mode_t mode) { - int ret = chmod(pathname, mode); - if (ret == -1) { - PLOGE("chmod %s %u", pathname, mode); - } - return ret; -} - int xrename(const char *oldpath, const char *newpath) { int ret = rename(oldpath, newpath); if (ret == -1) { @@ -314,6 +331,22 @@ int xmkdir(const char *pathname, mode_t mode) { return ret; } +int xmkdir_p(const char *pathname, mode_t mode) { + int ret = mkdir_p(pathname, mode); + if (ret == -1) { + PLOGE("mkdir_p %s", pathname); + } + return ret; +} + +int xmkdirat(int dirfd, const char *pathname, mode_t mode) { + int ret = mkdirat(dirfd, pathname, mode); + if (ret == -1 && errno != EEXIST) { + PLOGE("mkdirat %s %u", pathname, mode); + } + return ret; +} + void *xmmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) { void *ret = mmap(addr, length, prot, flags, fd, offset); @@ -331,10 +364,10 @@ ssize_t xsendfile(int out_fd, int in_fd, off_t *offset, size_t count) { return ret; } -int xmkdir_p(const char *pathname, mode_t mode) { - int ret = mkdir_p(pathname, mode); +pid_t xfork() { + int ret = fork(); if (ret == -1) { - PLOGE("mkdir_p %s", pathname); + PLOGE("fork"); } return ret; }