mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-25 02:57:38 +00:00
Move all xwrap to Rust
This commit is contained in:
parent
66a7ef5615
commit
c6646efe68
7
native/src/Cargo.lock
generated
7
native/src/Cargo.lock
generated
@ -6,6 +6,7 @@ version = 3
|
||||
name = "base"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cxx",
|
||||
"libc",
|
||||
]
|
||||
@ -16,6 +17,12 @@ version = "1.0.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cxx"
|
||||
version = "1.0.72"
|
||||
|
@ -14,7 +14,6 @@ LOCAL_SRC_FILES := \
|
||||
misc.cpp \
|
||||
selinux.cpp \
|
||||
logging.cpp \
|
||||
xwrap.cpp \
|
||||
stream.cpp \
|
||||
../external/cxx-rs/src/cxx.cc
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
@ -9,3 +9,4 @@ path = "lib.rs"
|
||||
[dependencies]
|
||||
cxx = { path = "../external/cxx-rs" }
|
||||
libc = "0.2"
|
||||
cfg-if = "1.0"
|
||||
|
@ -9,38 +9,12 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
ssize_t fd_path(int fd, char *path, size_t size) {
|
||||
ssprintf(path, size, "/proc/self/fd/%d", fd);
|
||||
return xreadlink(path, path, size);
|
||||
}
|
||||
|
||||
int fd_pathat(int dirfd, const char *name, char *path, size_t size) {
|
||||
if (fd_path(dirfd, path, size) < 0)
|
||||
if (fd_path(dirfd, byte_slice(path, size)) < 0)
|
||||
return -1;
|
||||
auto len = strlen(path);
|
||||
path[len] = '/';
|
||||
strlcpy(path + len + 1, name, size - len - 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mkdirs(const char *path, mode_t mode) {
|
||||
char buf[4096];
|
||||
strlcpy(buf, path, sizeof(buf));
|
||||
errno = 0;
|
||||
for (char *p = &buf[1]; *p; ++p) {
|
||||
if (*p == '/') {
|
||||
*p = '\0';
|
||||
if (mkdir(buf, mode) == -1) {
|
||||
if (errno != EEXIST)
|
||||
return -1;
|
||||
}
|
||||
*p = '/';
|
||||
}
|
||||
}
|
||||
if (mkdir(buf, mode) == -1) {
|
||||
if (errno != EEXIST)
|
||||
return -1;
|
||||
}
|
||||
strscpy(path + len + 1, name, size - len - 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -410,14 +384,14 @@ void parse_mnt(const char *file, const function<bool(mntent*)> &fn) {
|
||||
|
||||
void backup_folder(const char *dir, vector<raw_file> &files) {
|
||||
char path[PATH_MAX];
|
||||
xrealpath(dir, path);
|
||||
xcanonical_path(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);
|
||||
if (fd < 0)
|
||||
return SKIP;
|
||||
run_finally f([&]{ close(fd); });
|
||||
if (fd_path(fd, path, sizeof(path)) < 0)
|
||||
if (fd_path(fd, byte_slice(path, sizeof(path))) < 0)
|
||||
return SKIP;
|
||||
raw_file file;
|
||||
file.path = path + len + 1;
|
||||
|
@ -58,9 +58,16 @@ struct mmap_data : public byte_data {
|
||||
mmap_data& operator=(mmap_data &&other) { swap(other); return *this; }
|
||||
};
|
||||
|
||||
ssize_t fd_path(int fd, char *path, size_t size);
|
||||
int fd_pathat(int dirfd, const char *name, char *path, size_t size);
|
||||
extern "C" {
|
||||
|
||||
int mkdirs(const char *path, mode_t mode);
|
||||
ssize_t canonical_path(const char *path, char *buf, size_t bufsiz);
|
||||
ssize_t read_link(const char *pathname, char *buf, size_t bufsiz);
|
||||
|
||||
} // extern "C"
|
||||
|
||||
using rust::fd_path;
|
||||
int fd_pathat(int dirfd, const char *name, char *path, size_t size);
|
||||
void rm_rf(const char *path);
|
||||
void mv_path(const char *src, const char *dest);
|
||||
void mv_dir(int src, int dest);
|
||||
|
112
native/src/base/files.rs
Normal file
112
native/src/base/files.rs
Normal file
@ -0,0 +1,112 @@
|
||||
use std::ffi::CStr;
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, OwnedFd, RawFd};
|
||||
|
||||
use libc::{c_char, mode_t, EEXIST, ENOENT, O_CLOEXEC, O_PATH};
|
||||
|
||||
use crate::{bfmt_cstr, errno, xopen};
|
||||
|
||||
mod unsafe_impl {
|
||||
use std::ffi::CStr;
|
||||
use std::slice;
|
||||
|
||||
use libc::c_char;
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn read_link(path: *const c_char, buf: *mut u8, bufsz: usize) -> isize {
|
||||
let r = libc::readlink(path, buf.cast(), bufsz - 1);
|
||||
if r >= 0 {
|
||||
*buf.offset(r) = b'\0';
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
#[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_raw_parts_mut(buf, bufsz))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn __open_fd_impl(path: &CStr, flags: i32, mode: mode_t) -> Option<OwnedFd> {
|
||||
let fd = xopen(path.as_ptr(), flags, mode);
|
||||
if fd >= 0 {
|
||||
unsafe { Some(OwnedFd::from_raw_fd(fd)) }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! open_fd {
|
||||
($path:expr, $flags:expr) => {
|
||||
crate::__open_fd_impl($path, $flags, 0)
|
||||
};
|
||||
($path:expr, $flags:expr, $mode:expr) => {
|
||||
crate::__open_fd_impl($path, $flags, $mode)
|
||||
};
|
||||
}
|
||||
|
||||
pub fn readlink(path: &CStr, data: &mut [u8]) -> isize {
|
||||
unsafe { unsafe_impl::read_link(path.as_ptr(), data.as_mut_ptr(), data.len()) }
|
||||
}
|
||||
|
||||
pub fn fd_path(fd: RawFd, buf: &mut [u8]) -> isize {
|
||||
let mut fd_buf: [u8; 40] = [0; 40];
|
||||
let fd_path = bfmt_cstr!(&mut fd_buf, "/proc/self/fd/{}", fd);
|
||||
readlink(fd_path, buf)
|
||||
}
|
||||
|
||||
// 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) {
|
||||
let mut st1: libc::stat;
|
||||
let mut st2: libc::stat;
|
||||
unsafe {
|
||||
st1 = std::mem::zeroed();
|
||||
if libc::fstat(fd.as_raw_fd(), &mut st1) < 0 {
|
||||
*errno() = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
let len = fd_path(fd.as_raw_fd(), buf);
|
||||
unsafe {
|
||||
st2 = std::mem::zeroed();
|
||||
if libc::stat(buf.as_ptr().cast(), &mut st2) < 0
|
||||
|| st2.st_dev != st1.st_dev
|
||||
|| st2.st_ino != st1.st_ino
|
||||
{
|
||||
*errno() = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
} else {
|
||||
*errno() = ENOENT;
|
||||
-1
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn strscpy(dst: *mut c_char, src: *const c_char, size: usize) -> usize;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn mkdirs(path: *const c_char, mode: mode_t) -> i32 {
|
||||
unsafe {
|
||||
let mut buf = [0 as u8; 4096];
|
||||
let ptr: *mut c_char = buf.as_mut_ptr().cast();
|
||||
let len = strscpy(ptr, path, buf.len());
|
||||
let mut curr = &mut buf[1..len];
|
||||
while let Some(p) = curr.iter().position(|c| *c == b'/') {
|
||||
curr[p] = b'\0';
|
||||
if libc::mkdir(ptr, mode) < 0 && *errno() != EEXIST {
|
||||
return -1;
|
||||
}
|
||||
curr[p] = b'/';
|
||||
curr = &mut curr[(p + 1)..];
|
||||
}
|
||||
if libc::mkdir(ptr, mode) < 0 && *errno() != EEXIST {
|
||||
return -1;
|
||||
}
|
||||
0
|
||||
}
|
||||
}
|
@ -2,10 +2,12 @@
|
||||
|
||||
pub use libc;
|
||||
|
||||
pub use files::*;
|
||||
pub use logging::*;
|
||||
pub use misc::*;
|
||||
pub use xwrap::*;
|
||||
|
||||
mod files;
|
||||
mod logging;
|
||||
mod misc;
|
||||
mod xwrap;
|
||||
@ -31,9 +33,7 @@ pub mod ffi {
|
||||
#[cxx::bridge(namespace = "rust")]
|
||||
pub mod ffi2 {
|
||||
extern "Rust" {
|
||||
fn xwrite(fd: i32, data: &[u8]) -> isize;
|
||||
fn xread(fd: i32, data: &mut [u8]) -> isize;
|
||||
fn xxread(fd: i32, data: &mut [u8]) -> isize;
|
||||
fn xpipe2(fds: &mut [i32; 2], flags: i32) -> i32;
|
||||
fn fd_path(fd: i32, buf: &mut [u8]) -> isize;
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ extern "C" int magisk_log_print(int prio, const char *tag, const char *fmt, ...)
|
||||
}
|
||||
|
||||
char fmt_buf[4096];
|
||||
auto len = strlcpy(fmt_buf, tag, sizeof(fmt_buf) - 1);
|
||||
auto len = strscpy(fmt_buf, tag, sizeof(fmt_buf) - 1);
|
||||
// Prevent format specifications in the tag
|
||||
std::replace(fmt_buf, fmt_buf + len, '%', '_');
|
||||
len = ssprintf(fmt_buf + len, sizeof(fmt_buf) - len - 1, ": %s", fmt) + len;
|
||||
|
@ -130,7 +130,7 @@ void init_argv0(int argc, char **argv) {
|
||||
|
||||
void set_nice_name(const char *name) {
|
||||
memset(argv0, 0, name_len);
|
||||
strlcpy(argv0, name, name_len);
|
||||
strscpy(argv0, name, name_len);
|
||||
prctl(PR_SET_NAME, name);
|
||||
}
|
||||
|
||||
@ -224,3 +224,8 @@ int ssprintf(char *dest, size_t size, const char *fmt, ...) {
|
||||
va_end(va);
|
||||
return r;
|
||||
}
|
||||
|
||||
#undef strlcpy
|
||||
size_t strscpy(char *dest, const char *src, size_t size) {
|
||||
return std::min(strlcpy(dest, src, size), size - 1);
|
||||
}
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include <string_view>
|
||||
#include <bitset>
|
||||
|
||||
#include <base-rs.hpp>
|
||||
|
||||
#define DISALLOW_COPY_AND_MOVE(clazz) \
|
||||
clazz(const clazz &) = delete; \
|
||||
clazz(clazz &&) = delete;
|
||||
@ -118,6 +120,11 @@ struct StringCmp {
|
||||
bool operator()(std::string_view a, std::string_view b) const { return a < b; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
rust::Slice<uint8_t> byte_slice(T *buf, size_t sz) {
|
||||
return rust::Slice(reinterpret_cast<uint8_t *>(buf), sz);
|
||||
}
|
||||
|
||||
int parse_int(std::string_view s);
|
||||
|
||||
using thread_entry = void *(*)(void *);
|
||||
@ -160,10 +167,14 @@ std::vector<std::string_view> split_ro(std::string_view, std::string_view delims
|
||||
int vssprintf(char *dest, size_t size, const char *fmt, va_list ap);
|
||||
// Similar to snprintf, but the return value is the written number of bytes
|
||||
int ssprintf(char *dest, size_t size, const char *fmt, ...);
|
||||
// This is not actually the strscpy from the Linux kernel.
|
||||
// Silently truncates, and returns the number of bytes written.
|
||||
extern "C" size_t strscpy(char *dest, const char *src, size_t size);
|
||||
|
||||
// Ban usage of unsafe cstring functions
|
||||
#define vsnprintf __use_vssprintf_instead__
|
||||
#define snprintf __use_ssprintf_instead__
|
||||
#define strlcpy __use_strscpy_instead__
|
||||
|
||||
struct exec_t {
|
||||
bool err = false;
|
||||
|
@ -41,6 +41,21 @@ pub fn fmt_to_buf(buf: &mut [u8], args: Arguments) -> usize {
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! bfmt {
|
||||
($buf:expr, $($args:tt)*) => {
|
||||
$crate::fmt_to_buf($buf, format_args!($($args)*));
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! bfmt_cstr {
|
||||
($buf:expr, $($args:tt)*) => {{
|
||||
let len = $crate::fmt_to_buf($buf, format_args!($($args)*));
|
||||
unsafe { std::ffi::CStr::from_bytes_with_nul_unchecked(&$buf[..(len + 1)]) }
|
||||
}};
|
||||
}
|
||||
|
||||
// The cstr! macro is inspired by https://github.com/Nugine/const-str
|
||||
|
||||
macro_rules! const_assert {
|
||||
@ -88,19 +103,12 @@ macro_rules! cstr {
|
||||
($s:literal) => {{
|
||||
const LEN: usize = $crate::ToCStr($s).eval_len();
|
||||
const BUF: [u8; LEN] = $crate::ToCStr($s).eval_bytes();
|
||||
unsafe { CStr::from_bytes_with_nul_unchecked(&BUF) }
|
||||
unsafe { std::ffi::CStr::from_bytes_with_nul_unchecked(&BUF) }
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! r_cstr {
|
||||
($s:literal) => {
|
||||
cstr!($s).as_ptr()
|
||||
};
|
||||
}
|
||||
|
||||
pub unsafe fn ptr_to_str<'a, T>(ptr: *const T) -> &'a str {
|
||||
CStr::from_ptr(ptr.cast()).to_str().unwrap_or("")
|
||||
pub fn ptr_to_str<'a, T>(ptr: *const T) -> &'a str {
|
||||
unsafe { CStr::from_ptr(ptr.cast()) }.to_str().unwrap_or("")
|
||||
}
|
||||
|
||||
pub fn errno() -> &'static mut i32 {
|
||||
|
@ -1,119 +0,0 @@
|
||||
#include <sched.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/sendfile.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/inotify.h>
|
||||
|
||||
#include <base.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
ssize_t xwrite(int fd, const void *buf, size_t count) {
|
||||
return rust::xwrite(fd, rust::Slice(static_cast<const uint8_t *>(buf), count));
|
||||
}
|
||||
|
||||
ssize_t xread(int fd, void *buf, size_t count) {
|
||||
return rust::xread(fd, rust::Slice(static_cast<uint8_t *>(buf), count));
|
||||
}
|
||||
|
||||
ssize_t xxread(int fd, void *buf, size_t count) {
|
||||
return rust::xxread(fd, rust::Slice(static_cast<uint8_t *>(buf), count));
|
||||
}
|
||||
|
||||
dirent *xreaddir(DIR *dirp) {
|
||||
errno = 0;
|
||||
for (dirent *e;;) {
|
||||
e = readdir(dirp);
|
||||
if (e == nullptr) {
|
||||
if (errno)
|
||||
PLOGE("readdir");
|
||||
return nullptr;
|
||||
} else if (e->d_name == "."sv || e->d_name == ".."sv) {
|
||||
// Filter . and .. for users
|
||||
continue;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t xreadlink(const char *pathname, char *buf, size_t bufsiz) {
|
||||
ssize_t ret = readlink(pathname, buf, bufsiz);
|
||||
if (ret < 0) {
|
||||
PLOGE("readlink %s", pathname);
|
||||
} else {
|
||||
buf[ret] = '\0';
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t xreadlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz) {
|
||||
// readlinkat() may fail on x86 platform, returning random value
|
||||
// instead of number of bytes placed in buf (length of link)
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
memset(buf, 0, bufsiz);
|
||||
ssize_t ret = readlinkat(dirfd, pathname, buf, bufsiz);
|
||||
if (ret < 0) {
|
||||
PLOGE("readlinkat %s", pathname);
|
||||
}
|
||||
return ret;
|
||||
#else
|
||||
ssize_t ret = readlinkat(dirfd, pathname, buf, bufsiz);
|
||||
if (ret < 0) {
|
||||
PLOGE("readlinkat %s", pathname);
|
||||
} else {
|
||||
buf[ret] = '\0';
|
||||
}
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
int xmkdirs(const char *pathname, mode_t mode) {
|
||||
int ret = mkdirs(pathname, mode);
|
||||
if (ret < 0) {
|
||||
PLOGE("mkdirs %s", pathname);
|
||||
}
|
||||
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);
|
||||
if (ret == MAP_FAILED) {
|
||||
PLOGE("mmap");
|
||||
return nullptr;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t xsendfile(int out_fd, int in_fd, off_t *offset, size_t count) {
|
||||
ssize_t ret = sendfile(out_fd, in_fd, offset, count);
|
||||
if (ret < 0) {
|
||||
PLOGE("sendfile");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int xpoll(struct pollfd *fds, nfds_t nfds, int timeout) {
|
||||
int ret = poll(fds, nfds, timeout);
|
||||
if (ret < 0) {
|
||||
PLOGE("poll");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *xrealpath(const char *path, char *resolved_path) {
|
||||
char buf[PATH_MAX];
|
||||
char *ret = realpath(path, buf);
|
||||
if (ret == nullptr) {
|
||||
PLOGE("xrealpath");
|
||||
} else {
|
||||
strcpy(resolved_path, buf);
|
||||
}
|
||||
return ret;
|
||||
}
|
@ -57,8 +57,8 @@ 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);
|
||||
pid_t xfork();
|
||||
int xpoll(struct pollfd *fds, nfds_t nfds, int timeout);
|
||||
char *xrealpath(const char *path, char *resolved_path);
|
||||
int xpoll(pollfd *fds, nfds_t nfds, int timeout);
|
||||
ssize_t xcanonical_path(const char *path, char *buf, size_t bufsiz);
|
||||
int xmknod(const char *pathname, mode_t mode, dev_t dev);
|
||||
|
||||
} // extern "C"
|
||||
|
@ -1,11 +1,100 @@
|
||||
use std::ffi::CStr;
|
||||
use std::os::unix::io::RawFd;
|
||||
use std::ptr;
|
||||
|
||||
use libc::{
|
||||
c_char, c_uint, c_ulong, c_void, dev_t, mode_t, sockaddr, socklen_t, ssize_t, SYS_dup3,
|
||||
c_char, c_uint, c_ulong, c_void, dev_t, mode_t, nfds_t, off_t, pollfd, sockaddr, socklen_t,
|
||||
ssize_t, SYS_dup3,
|
||||
};
|
||||
|
||||
use crate::{errno, error, perror, ptr_to_str};
|
||||
use crate::{canonical_path, cstr, errno, error, mkdirs, perror, ptr_to_str, readlink};
|
||||
|
||||
mod unsafe_impl {
|
||||
use std::ffi::CStr;
|
||||
use std::os::unix::io::RawFd;
|
||||
use std::slice;
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
use libc::{c_char, nfds_t, off_t, pollfd};
|
||||
|
||||
use crate::{perror, ptr_to_str};
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn xwrite(fd: RawFd, buf: *const u8, bufsz: usize) -> isize {
|
||||
super::xwrite(fd, slice::from_raw_parts(buf, bufsz))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn xread(fd: RawFd, buf: *mut u8, bufsz: usize) -> isize {
|
||||
super::xread(fd, slice::from_raw_parts_mut(buf, bufsz))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn xxread(fd: RawFd, buf: *mut u8, bufsz: usize) -> isize {
|
||||
super::xxread(fd, slice::from_raw_parts_mut(buf, bufsz))
|
||||
}
|
||||
|
||||
#[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_raw_parts_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_raw_parts_mut(buf, bufsz))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn xreadlinkat(
|
||||
dirfd: RawFd,
|
||||
path: *const c_char,
|
||||
buf: *mut u8,
|
||||
bufsz: usize,
|
||||
) -> isize {
|
||||
// readlinkat() may fail on x86 platform, returning random value
|
||||
// instead of number of bytes placed in buf (length of link)
|
||||
cfg_if! {
|
||||
if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
|
||||
libc::memset(buf.cast(), 0, bufsz);
|
||||
let r = libc::readlinkat(dirfd, path, buf.cast(), bufsz - 1);
|
||||
if r < 0 {
|
||||
perror!("readlinkat {}", ptr_to_str(path))
|
||||
}
|
||||
} else {
|
||||
let r = libc::readlinkat(dirfd, path, buf.cast(), bufsz - 1);
|
||||
if r < 0 {
|
||||
perror!("readlinkat {}", ptr_to_str(path))
|
||||
} else {
|
||||
*buf.offset(r) = b'\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn xpoll(fds: *mut pollfd, nfds: nfds_t, timeout: i32) -> i32 {
|
||||
let r = libc::poll(fds, nfds, timeout);
|
||||
if r < 0 {
|
||||
perror!("poll");
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn xsendfile(
|
||||
out_fd: RawFd,
|
||||
in_fd: RawFd,
|
||||
offset: *mut off_t,
|
||||
count: usize,
|
||||
) -> isize {
|
||||
let r = libc::sendfile(out_fd, in_fd, offset, count);
|
||||
if r < 0 {
|
||||
perror!("sendfile");
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn xfopen(path: *const c_char, mode: *const c_char) -> *mut libc::FILE {
|
||||
@ -194,6 +283,29 @@ pub extern "C" fn xfdopendir(fd: RawFd) -> *mut libc::DIR {
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn xreaddir(dirp: *mut libc::DIR) -> *mut libc::dirent {
|
||||
#[allow(unused_unsafe)]
|
||||
unsafe {
|
||||
*errno() = 0;
|
||||
loop {
|
||||
let e = libc::readdir(dirp);
|
||||
if e.is_null() {
|
||||
if *errno() != 0 {
|
||||
perror!("readdir")
|
||||
}
|
||||
} else {
|
||||
// Filter out . and ..
|
||||
let s = CStr::from_ptr((*e).d_name.as_ptr());
|
||||
if s == cstr!(".") || s == cstr!("..") {
|
||||
continue;
|
||||
}
|
||||
};
|
||||
return e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn xsetsid() -> i32 {
|
||||
unsafe {
|
||||
@ -386,21 +498,15 @@ pub extern "C" fn xdup3(oldfd: RawFd, newfd: RawFd, flags: i32) -> RawFd {
|
||||
}
|
||||
|
||||
pub fn xreadlink(path: &CStr, data: &mut [u8]) -> isize {
|
||||
mod e {
|
||||
extern "C" {
|
||||
pub fn xreadlink(path: *const u8, buf: *mut u8, bufsz: usize) -> isize;
|
||||
}
|
||||
let r = readlink(path, data);
|
||||
if r < 0 {
|
||||
perror!("readlink {}", path.to_str().unwrap_or(""))
|
||||
}
|
||||
unsafe { e::xreadlink(path.as_ptr().cast(), data.as_mut_ptr(), data.len()) }
|
||||
return r;
|
||||
}
|
||||
|
||||
pub fn xreadlinkat(dirfd: RawFd, path: &CStr, data: &mut [u8]) -> isize {
|
||||
mod e {
|
||||
extern "C" {
|
||||
pub fn xreadlinkat(dirfd: i32, path: *const u8, buf: *mut u8, bufsz: usize) -> isize;
|
||||
}
|
||||
}
|
||||
unsafe { e::xreadlinkat(dirfd, path.as_ptr().cast(), data.as_mut_ptr(), data.len()) }
|
||||
unsafe { unsafe_impl::xreadlinkat(dirfd, path.as_ptr(), data.as_mut_ptr(), data.len()) }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@ -507,6 +613,15 @@ pub extern "C" fn xmkdir(path: *const c_char, mode: mode_t) -> i32 {
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn xmkdirs(path: *const c_char, mode: mode_t) -> i32 {
|
||||
let r = mkdirs(path, mode);
|
||||
if r < 0 {
|
||||
perror!("mkdirs {}", ptr_to_str(path));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn xmkdirat(dirfd: RawFd, path: *const c_char, mode: mode_t) -> i32 {
|
||||
unsafe {
|
||||
@ -518,6 +633,32 @@ pub extern "C" fn xmkdirat(dirfd: RawFd, path: *const c_char, mode: mode_t) -> i
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
unsafe_impl::xsendfile(out_fd, in_fd, p, count)
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn xmmap(
|
||||
addr: *mut c_void,
|
||||
len: usize,
|
||||
prot: i32,
|
||||
flags: i32,
|
||||
fd: RawFd,
|
||||
offset: off_t,
|
||||
) -> *mut c_void {
|
||||
unsafe {
|
||||
let r = libc::mmap(addr, len, prot, flags, fd, offset);
|
||||
if r == libc::MAP_FAILED {
|
||||
perror!("mmap");
|
||||
return ptr::null_mut();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn xfork() -> i32 {
|
||||
unsafe {
|
||||
@ -529,6 +670,18 @@ pub extern "C" fn xfork() -> i32 {
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
if r < 0 {
|
||||
perror!("canonical_path {}", path.to_str().unwrap_or(""))
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn xmknod(pathname: *const c_char, mode: mode_t, dev: dev_t) -> i32 {
|
||||
unsafe {
|
||||
|
@ -124,7 +124,7 @@ extern "C" void klog_write(const char *msg, int len) {
|
||||
|
||||
static int klog_with_rs(LogLevel level, const char *fmt, va_list ap) {
|
||||
char buf[4096];
|
||||
strlcpy(buf, "magiskinit: ", sizeof(buf));
|
||||
strscpy(buf, "magiskinit: ", sizeof(buf));
|
||||
int len = vssprintf(buf + 12, sizeof(buf) - 12, fmt, ap) + 12;
|
||||
log_with_rs(level, rust::Str(buf, len));
|
||||
return len;
|
||||
@ -174,10 +174,10 @@ void BootConfig::set(const kv_pairs &kv) {
|
||||
LOGW("Skip invalid androidboot.slot_suffix=[normal]\n");
|
||||
continue;
|
||||
}
|
||||
strlcpy(slot, value.data(), sizeof(slot));
|
||||
strscpy(slot, value.data(), sizeof(slot));
|
||||
} else if (key == "androidboot.slot") {
|
||||
slot[0] = '_';
|
||||
strlcpy(slot + 1, value.data(), sizeof(slot) - 1);
|
||||
strscpy(slot + 1, value.data(), sizeof(slot) - 1);
|
||||
} else if (key == "skip_initramfs") {
|
||||
skip_initramfs = true;
|
||||
} else if (key == "androidboot.force_normal_boot") {
|
||||
@ -185,13 +185,13 @@ void BootConfig::set(const kv_pairs &kv) {
|
||||
} else if (key == "rootwait") {
|
||||
rootwait = true;
|
||||
} else if (key == "androidboot.android_dt_dir") {
|
||||
strlcpy(dt_dir, value.data(), sizeof(dt_dir));
|
||||
strscpy(dt_dir, value.data(), sizeof(dt_dir));
|
||||
} else if (key == "androidboot.hardware") {
|
||||
strlcpy(hardware, value.data(), sizeof(hardware));
|
||||
strscpy(hardware, value.data(), sizeof(hardware));
|
||||
} else if (key == "androidboot.hardware.platform") {
|
||||
strlcpy(hardware_plat, value.data(), sizeof(hardware_plat));
|
||||
strscpy(hardware_plat, value.data(), sizeof(hardware_plat));
|
||||
} else if (key == "androidboot.fstab_suffix") {
|
||||
strlcpy(fstab_suffix, value.data(), sizeof(fstab_suffix));
|
||||
strscpy(fstab_suffix, value.data(), sizeof(fstab_suffix));
|
||||
} else if (key == "qemu") {
|
||||
emulator = true;
|
||||
}
|
||||
@ -216,7 +216,7 @@ if (access(file_name, R_OK) == 0) { \
|
||||
string data = full_read(file_name); \
|
||||
if (!data.empty()) { \
|
||||
data.pop_back(); \
|
||||
strlcpy(config->key, data.data(), sizeof(config->key)); \
|
||||
strscpy(config->key, data.data(), sizeof(config->key)); \
|
||||
} \
|
||||
}
|
||||
|
||||
@ -245,7 +245,7 @@ void load_kernel_info(BootConfig *config) {
|
||||
});
|
||||
|
||||
if (config->dt_dir[0] == '\0')
|
||||
strlcpy(config->dt_dir, DEFAULT_DT_DIR, sizeof(config->dt_dir));
|
||||
strscpy(config->dt_dir, DEFAULT_DT_DIR, sizeof(config->dt_dir));
|
||||
|
||||
char file_name[128];
|
||||
read_dt("fstab_suffix", fstab_suffix)
|
||||
|
@ -118,8 +118,8 @@ static void switch_root(const string &path) {
|
||||
|
||||
void MagiskInit::mount_rules_dir() {
|
||||
char path[128];
|
||||
xrealpath(BLOCKDIR, blk_info.block_dev);
|
||||
xrealpath(MIRRDIR, path);
|
||||
xcanonical_path(BLOCKDIR, blk_info.block_dev, sizeof(blk_info.block_dev));
|
||||
xcanonical_path(MIRRDIR, path, sizeof(path));
|
||||
char *b = blk_info.block_dev + strlen(blk_info.block_dev);
|
||||
char *p = path + strlen(path);
|
||||
|
||||
@ -206,7 +206,7 @@ success:
|
||||
// Create symlink with relative path
|
||||
char s[128];
|
||||
s[0] = '.';
|
||||
strlcpy(s + 1, rel + sizeof(MIRRDIR) - 1, sizeof(s) - 1);
|
||||
strscpy(s + 1, rel + sizeof(MIRRDIR) - 1, sizeof(s) - 1);
|
||||
xsymlink(s, path);
|
||||
} else {
|
||||
xsymlink(custom_rules_dir.data(), path);
|
||||
|
@ -123,7 +123,7 @@ static void exec_cmd(const char *action, vector<Extra> &data,
|
||||
ssprintf(exe, sizeof(exe), "/proc/self/fd/%d", app_process_32);
|
||||
#endif
|
||||
} else {
|
||||
strlcpy(exe, "/system/bin/app_process", sizeof(exe));
|
||||
strscpy(exe, "/system/bin/app_process", sizeof(exe));
|
||||
}
|
||||
|
||||
// First try content provider call method
|
||||
@ -158,7 +158,7 @@ static void exec_cmd(const char *action, vector<Extra> &data,
|
||||
};
|
||||
|
||||
// Then try start activity without package name
|
||||
strlcpy(target, info->mgr_pkg.data(), sizeof(target));
|
||||
strscpy(target, info->mgr_pkg.data(), sizeof(target));
|
||||
exec_command_sync(exec);
|
||||
if (check_no_error(exec.fd))
|
||||
return;
|
||||
|
@ -142,7 +142,7 @@ void prune_su_access() {
|
||||
vector<bool> app_no_list = get_app_no_list();
|
||||
vector<int> rm_uids;
|
||||
char query[256], *err;
|
||||
strlcpy(query, "SELECT uid FROM policies", sizeof(query));
|
||||
strscpy(query, "SELECT uid FROM policies", sizeof(query));
|
||||
err = db_exec(query, [&](db_row &row) -> bool {
|
||||
int uid = parse_int(row["uid"]);
|
||||
int app_id = to_app_id(uid);
|
||||
@ -412,7 +412,7 @@ void su_daemon_handler(int client, const sock_cred *cred) {
|
||||
char path[32];
|
||||
ssprintf(path, sizeof(path), "/proc/%d/cwd", ctx.pid);
|
||||
char cwd[PATH_MAX];
|
||||
if (realpath(path, cwd))
|
||||
if (canonical_path(path, cwd, sizeof(cwd)))
|
||||
chdir(cwd);
|
||||
ssprintf(path, sizeof(path), "/proc/%d/environ", ctx.pid);
|
||||
auto env = full_read(path);
|
||||
|
Loading…
x
Reference in New Issue
Block a user