diff --git a/native/src/base/files.cpp b/native/src/base/files.cpp index 417c4751f..f6a87cb1a 100644 --- a/native/src/base/files.cpp +++ b/native/src/base/files.cpp @@ -384,7 +384,7 @@ void parse_mnt(const char *file, const function &fn) { void backup_folder(const char *dir, vector &files) { char path[PATH_MAX]; - xcanonical_path(dir, path, sizeof(path)); + xrealpath(dir, path, sizeof(path)); int len = strlen(path); pre_order_walk(xopen(dir, O_RDONLY), [&](int dfd, dirent *entry) -> walk_result { int fd = xopenat(dfd, entry->d_name, O_RDONLY); diff --git a/native/src/base/files.hpp b/native/src/base/files.hpp index 708cdb110..dbcb96b78 100644 --- a/native/src/base/files.hpp +++ b/native/src/base/files.hpp @@ -74,6 +74,9 @@ void mv_dir(int src, int dest); void cp_afc(const char *src, const char *dest); void link_path(const char *src, const char *dest); void link_dir(int src, int dest); +static inline ssize_t realpath(const char *path, char *buf, size_t bufsiz) { + return canonical_path(path, buf, bufsiz); +} int getattr(const char *path, file_attr *a); int getattrat(int dirfd, const char *name, file_attr *a); int fgetattr(int fd, file_attr *a); diff --git a/native/src/base/files.rs b/native/src/base/files.rs index 75d28aee5..8f79f86c5 100644 --- a/native/src/base/files.rs +++ b/native/src/base/files.rs @@ -5,7 +5,7 @@ use libc::{c_char, mode_t, EEXIST, ENOENT, O_CLOEXEC, O_PATH}; use crate::{bfmt_cstr, errno, xopen}; -mod unsafe_impl { +pub mod unsafe_impl { use std::ffi::CStr; use libc::c_char; @@ -23,11 +23,11 @@ mod unsafe_impl { #[no_mangle] unsafe extern "C" fn canonical_path(path: *const c_char, buf: *mut u8, bufsz: usize) -> isize { - super::canonical_path(CStr::from_ptr(path), slice_from_ptr_mut(buf, bufsz)) + super::realpath(CStr::from_ptr(path), slice_from_ptr_mut(buf, bufsz)) } } -pub fn __open_fd_impl(path: &CStr, flags: i32, mode: mode_t) -> Option { +pub fn __xopen_fd_impl(path: &CStr, flags: i32, mode: mode_t) -> Option { let fd = xopen(path.as_ptr(), flags, mode); if fd >= 0 { unsafe { Some(OwnedFd::from_raw_fd(fd)) } @@ -37,12 +37,12 @@ pub fn __open_fd_impl(path: &CStr, flags: i32, mode: mode_t) -> Option } #[macro_export] -macro_rules! open_fd { +macro_rules! xopen_fd { ($path:expr, $flags:expr) => { - crate::__open_fd_impl($path, $flags, 0) + crate::__xopen_fd_impl($path, $flags, 0) }; ($path:expr, $flags:expr, $mode:expr) => { - crate::__open_fd_impl($path, $flags, $mode) + crate::__xopen_fd_impl($path, $flags, $mode) }; } @@ -57,8 +57,8 @@ pub fn fd_path(fd: RawFd, buf: &mut [u8]) -> isize { } // Inspired by https://android.googlesource.com/platform/bionic/+/master/libc/bionic/realpath.cpp -pub fn canonical_path(path: &CStr, buf: &mut [u8]) -> isize { - if let Some(fd) = open_fd!(path, O_PATH | O_CLOEXEC) { +pub fn realpath(path: &CStr, buf: &mut [u8]) -> isize { + if let Some(fd) = xopen_fd!(path, O_PATH | O_CLOEXEC) { let mut st1: libc::stat; let mut st2: libc::stat; unsafe { diff --git a/native/src/base/xwrap.hpp b/native/src/base/xwrap.hpp index 9be6e9d50..c902454a2 100644 --- a/native/src/base/xwrap.hpp +++ b/native/src/base/xwrap.hpp @@ -58,7 +58,7 @@ 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); pid_t xfork(); int xpoll(pollfd *fds, nfds_t nfds, int timeout); -ssize_t xcanonical_path(const char *path, char *buf, size_t bufsiz); +ssize_t xrealpath(const char *path, char *buf, size_t bufsiz); int xmknod(const char *pathname, mode_t mode, dev_t dev); } // extern "C" diff --git a/native/src/base/xwrap.rs b/native/src/base/xwrap.rs index 910796003..bdc914688 100644 --- a/native/src/base/xwrap.rs +++ b/native/src/base/xwrap.rs @@ -7,7 +7,7 @@ use libc::{ ssize_t, SYS_dup3, }; -use crate::{canonical_path, cstr, errno, error, mkdirs, perror, ptr_to_str, readlink}; +use crate::{cstr, errno, error, mkdirs, perror, ptr_to_str, realpath}; mod unsafe_impl { use std::ffi::CStr; @@ -16,6 +16,7 @@ mod unsafe_impl { use cfg_if::cfg_if; use libc::{c_char, nfds_t, off_t, pollfd}; + use crate::unsafe_impl::read_link; use crate::{perror, ptr_to_str, slice_from_ptr, slice_from_ptr_mut}; #[no_mangle] @@ -34,13 +35,17 @@ mod unsafe_impl { } #[no_mangle] - unsafe extern "C" fn xcanonical_path(path: *const c_char, buf: *mut u8, bufsz: usize) -> isize { - super::xcanonical_path(CStr::from_ptr(path), slice_from_ptr_mut(buf, bufsz)) + unsafe extern "C" fn xrealpath(path: *const c_char, buf: *mut u8, bufsz: usize) -> isize { + super::xrealpath(CStr::from_ptr(path), slice_from_ptr_mut(buf, bufsz)) } #[no_mangle] - unsafe extern "C" fn xreadlink(path: *const c_char, buf: *mut u8, bufsz: usize) -> isize { - super::xreadlink(CStr::from_ptr(path), slice_from_ptr_mut(buf, bufsz)) + pub unsafe extern "C" fn xreadlink(path: *const c_char, buf: *mut u8, bufsz: usize) -> isize { + let r = read_link(path, buf, bufsz); + if r < 0 { + perror!("readlink"); + } + return r; } #[no_mangle] @@ -139,16 +144,6 @@ pub extern "C" fn xopenat(dirfd: RawFd, path: *const c_char, flags: i32, mode: m } } -#[macro_export] -macro_rules! xopen { - ($path:expr, $flags:expr) => { - xopen($path, $flags, 0) - }; - ($path:expr, $flags:expr, $mode:expr) => { - xopen($path, $flags, $mode) - }; -} - // Fully write data slice pub fn xwrite(fd: RawFd, data: &[u8]) -> isize { unsafe { @@ -496,14 +491,12 @@ pub extern "C" fn xdup3(oldfd: RawFd, newfd: RawFd, flags: i32) -> RawFd { } } +#[inline] pub fn xreadlink(path: &CStr, data: &mut [u8]) -> isize { - let r = readlink(path, data); - if r < 0 { - perror!("readlink {}", path.to_str().unwrap_or("")) - } - return r; + unsafe { unsafe_impl::xreadlink(path.as_ptr(), data.as_mut_ptr(), data.len()) } } +#[inline] pub fn xreadlinkat(dirfd: RawFd, path: &CStr, data: &mut [u8]) -> isize { unsafe { unsafe_impl::xreadlinkat(dirfd, path.as_ptr(), data.as_mut_ptr(), data.len()) } } @@ -632,6 +625,7 @@ pub extern "C" fn xmkdirat(dirfd: RawFd, path: *const c_char, mode: mode_t) -> i } } +#[inline] pub fn xsendfile(out_fd: RawFd, in_fd: RawFd, offset: Option<&mut off_t>, count: usize) -> isize { unsafe { let p = offset.map_or(ptr::null_mut(), |it| it); @@ -669,14 +663,15 @@ pub extern "C" fn xfork() -> i32 { } } +#[inline] pub fn xpoll(fds: &mut [pollfd], timeout: i32) -> i32 { unsafe { unsafe_impl::xpoll(fds.as_mut_ptr(), fds.len() as nfds_t, timeout) } } -pub fn xcanonical_path(path: &CStr, buf: &mut [u8]) -> isize { - let r = canonical_path(path, buf); +pub fn xrealpath(path: &CStr, buf: &mut [u8]) -> isize { + let r = realpath(path, buf); if r < 0 { - perror!("canonical_path {}", path.to_str().unwrap_or("")) + perror!("realpath {}", path.to_str().unwrap_or("")) } return r; } diff --git a/native/src/init/mount.cpp b/native/src/init/mount.cpp index ff5ea7f9e..82c60dbff 100644 --- a/native/src/init/mount.cpp +++ b/native/src/init/mount.cpp @@ -118,8 +118,8 @@ static void switch_root(const string &path) { void MagiskInit::mount_rules_dir() { char path[128]; - xcanonical_path(BLOCKDIR, blk_info.block_dev, sizeof(blk_info.block_dev)); - xcanonical_path(MIRRDIR, path, sizeof(path)); + xrealpath(BLOCKDIR, blk_info.block_dev, sizeof(blk_info.block_dev)); + xrealpath(MIRRDIR, path, sizeof(path)); char *b = blk_info.block_dev + strlen(blk_info.block_dev); char *p = path + strlen(path); diff --git a/native/src/su/su_daemon.cpp b/native/src/su/su_daemon.cpp index 3470c65f7..659782e11 100644 --- a/native/src/su/su_daemon.cpp +++ b/native/src/su/su_daemon.cpp @@ -411,8 +411,8 @@ void su_daemon_handler(int client, const sock_cred *cred) { umask(022); char path[32]; ssprintf(path, sizeof(path), "/proc/%d/cwd", ctx.pid); - char cwd[PATH_MAX]; - if (canonical_path(path, cwd, sizeof(cwd))) + char cwd[4096]; + if (realpath(path, cwd, sizeof(cwd)) > 0) chdir(cwd); ssprintf(path, sizeof(path), "/proc/%d/environ", ctx.pid); auto env = full_read(path);