diff --git a/native/src/Cargo.lock b/native/src/Cargo.lock index ae84faeb8..90e6ba8de 100644 --- a/native/src/Cargo.lock +++ b/native/src/Cargo.lock @@ -4,9 +4,10 @@ version = 3 [[package]] name = "base" -version = "0.1.0" +version = "0.0.0" dependencies = [ "cxx", + "libc", ] [[package]] @@ -37,9 +38,15 @@ dependencies = [ "syn", ] +[[package]] +name = "libc" +version = "0.2.127" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b" + [[package]] name = "magisk" -version = "0.1.0" +version = "0.0.0" dependencies = [ "base", "cxx", @@ -47,14 +54,14 @@ dependencies = [ [[package]] name = "magiskboot" -version = "0.1.0" +version = "0.0.0" dependencies = [ "base", ] [[package]] name = "magiskinit" -version = "0.1.0" +version = "0.0.0" dependencies = [ "base", "cxx", @@ -62,7 +69,7 @@ dependencies = [ [[package]] name = "magiskpolicy" -version = "0.1.0" +version = "0.0.0" dependencies = [ "base", ] diff --git a/native/src/base/Cargo.toml b/native/src/base/Cargo.toml index ff3ba5880..ea0bc7099 100644 --- a/native/src/base/Cargo.toml +++ b/native/src/base/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "base" -version = "0.1.0" +version = "0.0.0" edition = "2021" [lib] @@ -8,3 +8,4 @@ path = "lib.rs" [dependencies] cxx = { path = "../external/cxx-rs" } +libc = "0.2" diff --git a/native/src/base/lib.rs b/native/src/base/lib.rs index 445277458..710cd6c36 100644 --- a/native/src/base/lib.rs +++ b/native/src/base/lib.rs @@ -1,10 +1,13 @@ #![feature(format_args_nl)] +pub use libc; pub use logging::*; pub use misc::*; +pub use xwrap::*; mod logging; mod misc; +mod xwrap; #[cxx::bridge] pub mod ffi { diff --git a/native/src/base/logging.rs b/native/src/base/logging.rs index a9415c172..25373adc4 100644 --- a/native/src/base/logging.rs +++ b/native/src/base/logging.rs @@ -7,11 +7,11 @@ use crate::ffi::LogLevel; // Ugly hack to avoid using enum #[allow(non_snake_case, non_upper_case_globals)] mod LogFlag { - pub const DisableError: u32 = 0x1; - pub const DisableWarn: u32 = 0x2; - pub const DisableInfo: u32 = 0x4; - pub const DisableDebug: u32 = 0x8; - pub const ExitOnError: u32 = 0x10; + pub const DisableError: u32 = 1 << 0; + pub const DisableWarn: u32 = 1 << 1; + pub const DisableInfo: u32 = 1 << 2; + pub const DisableDebug: u32 = 1 << 3; + pub const ExitOnError: u32 = 1 << 4; } // We don't need to care about thread safety, because all @@ -92,7 +92,6 @@ pub fn cmdline_logging() { eprint!("{}", args); } } - fn write(level: LogLevel, msg: &[u8]) { if level == LogLevel::Info { stdout().write_all(msg).ok(); @@ -111,29 +110,48 @@ pub fn cmdline_logging() { } } +#[macro_export] +macro_rules! perror { + ($fmt:expr) => { + $crate::log_impl($crate::ffi::LogLevel::Error, format_args_nl!( + concat!($fmt, " failed with {}: {}"), + crate::errno(), + crate::error_str() + )) + }; + ($fmt:expr, $($args:tt)*) => { + $crate::log_impl($crate::ffi::LogLevel::Error, format_args_nl!( + concat!($fmt, " failed with {}: {}"), + $($args)*, + crate::errno(), + crate::error_str() + )) + }; +} + #[macro_export] macro_rules! error { - ($($arg:tt)+) => ($crate::log_impl($crate::ffi::LogLevel::Error, format_args_nl!($($arg)+))) + ($($args:tt)+) => ($crate::log_impl($crate::ffi::LogLevel::Error, format_args_nl!($($args)+))) } #[macro_export] macro_rules! warn { - ($($arg:tt)+) => ($crate::log_impl($crate::ffi::LogLevel::Warn, format_args_nl!($($arg)+))) + ($($args:tt)+) => ($crate::log_impl($crate::ffi::LogLevel::Warn, format_args_nl!($($args)+))) } #[macro_export] macro_rules! info { - ($($arg:tt)+) => ($crate::log_impl($crate::ffi::LogLevel::Info, format_args_nl!($($arg)+))) + ($($args:tt)+) => ($crate::log_impl($crate::ffi::LogLevel::Info, format_args_nl!($($args)+))) } #[cfg(debug_assertions)] #[macro_export] macro_rules! debug { - ($($arg:tt)+) => ($crate::log_impl($crate::ffi::LogLevel::Debug, format_args_nl!($($arg)+))) + ($($args:tt)+) => ($crate::log_impl($crate::ffi::LogLevel::Debug, format_args_nl!($($args)+))) } #[cfg(not(debug_assertions))] #[macro_export] macro_rules! debug { - ($($arg:tt)+) => {}; + ($($args:tt)+) => {}; } diff --git a/native/src/base/misc.rs b/native/src/base/misc.rs index 9f2fb2b0d..89936c98c 100644 --- a/native/src/base/misc.rs +++ b/native/src/base/misc.rs @@ -1,4 +1,5 @@ use std::cmp::min; +use std::ffi::CStr; use std::fmt; use std::fmt::Arguments; @@ -39,3 +40,77 @@ pub fn fmt_to_buf(buf: &mut [u8], args: Arguments) -> usize { 0 } } + +// The cstr! macro is inspired by https://github.com/Nugine/const-str + +macro_rules! const_assert { + ($s: expr) => { + assert!($s) + }; +} + +pub struct ToCStr<'a>(pub &'a str); + +impl ToCStr<'_> { + const fn assert_no_nul(&self) { + let bytes = self.0.as_bytes(); + let mut i = 0; + while i < bytes.len() { + const_assert!(bytes[i] != 0); + i += 1; + } + } + + pub const fn eval_len(&self) -> usize { + self.assert_no_nul(); + self.0.as_bytes().len() + 1 + } + + pub const fn eval_bytes(&self) -> [u8; N] { + let mut buf = [0; N]; + let mut pos = 0; + let bytes = self.0.as_bytes(); + let mut i = 0; + while i < bytes.len() { + const_assert!(bytes[i] != 0); + buf[pos] = bytes[i]; + pos += 1; + i += 1; + } + pos += 1; + const_assert!(pos == N); + buf + } +} + +#[macro_export] +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) } + }}; +} + +#[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 errno() -> &'static mut i32 { + // On Android, errno is obtained through the __errno function for thread local storage + extern "C" { + fn __errno() -> *mut i32; + } + unsafe { &mut *__errno() } +} + +pub fn error_str() -> &'static str { + unsafe { ptr_to_str(libc::strerror(*errno())) } +} diff --git a/native/src/base/stream.cpp b/native/src/base/stream.cpp index ce1188590..dcde87ec4 100644 --- a/native/src/base/stream.cpp +++ b/native/src/base/stream.cpp @@ -219,7 +219,7 @@ void byte_stream::resize(size_t new_pos, bool zero) { resize = true; } if (resize) { - _buf = (uint8_t *) xrealloc(_buf, _cap); + _buf = (uint8_t *) realloc(_buf, _cap); if (zero) memset(_buf + old_cap, 0, _cap - old_cap); } diff --git a/native/src/base/xwrap.cpp b/native/src/base/xwrap.cpp index d9cdfe8c3..6253acd2a 100644 --- a/native/src/base/xwrap.cpp +++ b/native/src/base/xwrap.cpp @@ -14,54 +14,6 @@ using namespace std; -FILE *xfopen(const char *pathname, const char *mode) { - FILE *fp = fopen(pathname, mode); - if (fp == nullptr) { - PLOGE("fopen: %s", pathname); - } - return fp; -} - -FILE *xfdopen(int fd, const char *mode) { - FILE *fp = fdopen(fd, mode); - if (fp == nullptr) { - PLOGE("fopen"); - } - return fp; -} - -int xopen(const char *pathname, int flags) { - int fd = open(pathname, flags); - if (fd < 0) { - PLOGE("open: %s", pathname); - } - return fd; -} - -int xopen(const char *pathname, int flags, mode_t mode) { - int fd = open(pathname, flags, mode); - if (fd < 0) { - PLOGE("open: %s", pathname); - } - 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; -} - -int xopenat(int dirfd, const char *pathname, int flags, mode_t mode) { - int fd = openat(dirfd, pathname, flags, mode); - if (fd < 0) { - PLOGE("openat: %s", pathname); - } - return fd; -} - // Write exact same size as count ssize_t xwrite(int fd, const void *buf, size_t count) { size_t write_sz = 0; @@ -215,30 +167,6 @@ int xaccept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) { return fd; } -void *xmalloc(size_t size) { - void *p = malloc(size); - if (p == nullptr) { - PLOGE("malloc"); - } - return p; -} - -void *xcalloc(size_t nmemb, size_t size) { - void *p = calloc(nmemb, size); - if (p == nullptr) { - PLOGE("calloc"); - } - return p; -} - -void *xrealloc(void *ptr, size_t size) { - void *p = realloc(ptr, size); - if (p == nullptr) { - PLOGE("realloc"); - } - return p; -} - ssize_t xsendmsg(int sockfd, const struct msghdr *msg, int flags) { int sent = sendmsg(sockfd, msg, flags); if (sent < 0) { @@ -515,10 +443,3 @@ int xmknod(const char *pathname, mode_t mode, dev_t dev) { } return ret; } - -long xptrace(int request, pid_t pid, void *addr, void *data) { - long ret = ptrace(request, pid, addr, data); - if (ret < 0) - PLOGE("ptrace %d", pid); - return ret; -} diff --git a/native/src/base/xwrap.hpp b/native/src/base/xwrap.hpp index 7c899c2a4..85b7bd478 100644 --- a/native/src/base/xwrap.hpp +++ b/native/src/base/xwrap.hpp @@ -5,12 +5,12 @@ #include #include +extern "C" { + FILE *xfopen(const char *pathname, const char *mode); FILE *xfdopen(int fd, const char *mode); -int xopen(const char *pathname, int flags); -int xopen(const char *pathname, int flags, mode_t mode); -int xopenat(int dirfd, const char *pathname, int flags); -int xopenat(int dirfd, const char *pathname, int flags, mode_t mode); +int xopen(const char *pathname, int flags, mode_t mode = 0); +int xopenat(int dirfd, const char *pathname, int flags, mode_t mode = 0); 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); @@ -24,16 +24,12 @@ struct dirent *xreaddir(DIR *dirp); pid_t xsetsid(); int xsocket(int domain, int type, int protocol); int xbind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); -int xconnect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); int xlisten(int sockfd, int backlog); int xaccept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags); -void *xmalloc(size_t size); -void *xcalloc(size_t nmemb, size_t size); -void *xrealloc(void *ptr, size_t size); ssize_t xsendmsg(int sockfd, const struct msghdr *msg, int flags); ssize_t xrecvmsg(int sockfd, struct msghdr *msg, int flags); int xpthread_create(pthread_t *thread, const pthread_attr_t *attr, - void *(*start_routine) (void *), void *arg); + void *(*start_routine)(void *), void *arg); int xaccess(const char *path, int mode); int xstat(const char *pathname, struct stat *buf); int xlstat(const char *pathname, struct stat *buf); @@ -64,8 +60,5 @@ int xpoll(struct pollfd *fds, nfds_t nfds, int timeout); int xinotify_init1(int flags); char *xrealpath(const char *path, char *resolved_path); int xmknod(const char *pathname, mode_t mode, dev_t dev); -long xptrace(int request, pid_t pid, void *addr = nullptr, void *data = nullptr); -static inline long xptrace(int request, pid_t pid, void *addr, uintptr_t data) { - return xptrace(request, pid, addr, reinterpret_cast(data)); -} -#define WEVENT(s) (((s) & 0xffff0000) >> 16) + +} // extern "C" diff --git a/native/src/base/xwrap.rs b/native/src/base/xwrap.rs new file mode 100644 index 000000000..797fa7048 --- /dev/null +++ b/native/src/base/xwrap.rs @@ -0,0 +1,57 @@ +use libc::{c_char, c_uint, mode_t}; + +use crate::{perror, ptr_to_str}; + +#[no_mangle] +pub extern "C" fn xfopen(path: *const c_char, mode: *const c_char) -> *mut libc::FILE { + unsafe { + let fp = libc::fopen(path, mode); + if fp.is_null() { + perror!("fopen: {}", ptr_to_str(path)); + } + return fp; + } +} + +#[no_mangle] +pub extern "C" fn xfdopen(fd: i32, mode: *const c_char) -> *mut libc::FILE { + unsafe { + let fp = libc::fdopen(fd, mode); + if fp.is_null() { + perror!("fdopen"); + } + return fp; + } +} + +#[no_mangle] +pub extern "C" fn xopen(path: *const c_char, flags: i32, mode: mode_t) -> i32 { + unsafe { + let r = libc::open(path, flags, mode as c_uint); + if r < 0 { + perror!("open: {}", ptr_to_str(path)); + } + return r; + } +} + +#[no_mangle] +pub extern "C" fn xopenat(dirfd: i32, path: *const c_char, flags: i32, mode: mode_t) -> i32 { + unsafe { + let r = libc::openat(dirfd, path, flags, mode as c_uint); + if r < 0 { + perror!("openat: {}", ptr_to_str(path)); + } + return r; + } +} + +#[macro_export] +macro_rules! xopen { + ($path:expr, $flags:expr) => { + xopen($path, $flags, 0) + }; + ($path:expr, $flags:expr, $mode:expr) => { + xopen($path, $flags, $mode) + }; +} diff --git a/native/src/boot/Cargo.toml b/native/src/boot/Cargo.toml index b640674d7..1a0a0ffc4 100644 --- a/native/src/boot/Cargo.toml +++ b/native/src/boot/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "magiskboot" -version = "0.1.0" +version = "0.0.0" edition = "2021" [lib] diff --git a/native/src/boot/bootimg.hpp b/native/src/boot/bootimg.hpp index cc3d1d80e..938c495eb 100644 --- a/native/src/boot/bootimg.hpp +++ b/native/src/boot/bootimg.hpp @@ -408,7 +408,7 @@ private: protected: name() = default; \ public: \ name(void *ptr) { \ - raw = xmalloc(sizeof(hdr)); \ + raw = malloc(sizeof(hdr)); \ memcpy(raw, ptr, sizeof(hdr)); \ } \ size_t hdr_size() override { \ diff --git a/native/src/boot/cpio.cpp b/native/src/boot/cpio.cpp index e2f9696bb..079cb1088 100644 --- a/native/src/boot/cpio.cpp +++ b/native/src/boot/cpio.cpp @@ -176,7 +176,7 @@ void cpio::add(mode_t mode, const char *name, const char *file) { auto m = mmap_data(file); auto e = new cpio_entry(S_IFREG | mode); e->filesize = m.sz; - e->data = xmalloc(m.sz); + e->data = malloc(m.sz); memcpy(e->data, m.buf, m.sz); insert(name, e); fprintf(stderr, "Add entry [%s] (%04o)\n", name, mode); @@ -236,7 +236,7 @@ void cpio::load_cpio(const char *buf, size_t sz) { continue; } auto entry = new cpio_entry(hdr); - entry->data = xmalloc(entry->filesize); + entry->data = malloc(entry->filesize); memcpy(entry->data, buf + pos, entry->filesize); pos += entry->filesize; insert(name, entry); diff --git a/native/src/boot/dtb.cpp b/native/src/boot/dtb.cpp index e0bed432a..fb5193492 100644 --- a/native/src/boot/dtb.cpp +++ b/native/src/boot/dtb.cpp @@ -265,7 +265,7 @@ static bool dt_table_patch(const Header *hdr, const char *out) { if (dtb_map.count(offset) == 0) { auto blob = buf + offset; uint32_t size = fdt_totalsize(blob); - auto fdt = xmalloc(size + MAX_FDT_GROWTH); + auto fdt = malloc(size + MAX_FDT_GROWTH); memcpy(fdt, blob, size); fdt_open_into(fdt, fdt, size + MAX_FDT_GROWTH); dtb_map[offset] = { fdt, offset }; @@ -345,7 +345,7 @@ static bool blob_patch(uint8_t *dtb, size_t dtb_sz, const char *out) { if (curr == nullptr) break; auto len = fdt_totalsize(curr); - auto fdt = static_cast(xmalloc(len + MAX_FDT_GROWTH)); + auto fdt = static_cast(malloc(len + MAX_FDT_GROWTH)); memcpy(fdt, curr, len); fdt_pack(fdt); uint32_t padding = len - fdt_totalsize(fdt); diff --git a/native/src/boot/ramdisk.cpp b/native/src/boot/ramdisk.cpp index e5f58d8be..c94c0a833 100644 --- a/native/src/boot/ramdisk.cpp +++ b/native/src/boot/ramdisk.cpp @@ -221,7 +221,7 @@ void magisk_cpio::backup(const char *orig) { if (!rm_list.empty()) { auto rm_list_file = new cpio_entry(S_IFREG); rm_list_file->filesize = rm_list.length(); - rm_list_file->data = xmalloc(rm_list.length()); + rm_list_file->data = malloc(rm_list.length()); memcpy(rm_list_file->data, rm_list.data(), rm_list.length()); backups.emplace(".backup/.rmlist", rm_list_file); } diff --git a/native/src/core/Cargo.toml b/native/src/core/Cargo.toml index 941fdd7c4..bd7422be2 100644 --- a/native/src/core/Cargo.toml +++ b/native/src/core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "magisk" -version = "0.1.0" +version = "0.0.0" edition = "2021" [lib] diff --git a/native/src/init/Cargo.toml b/native/src/init/Cargo.toml index a90f3554a..19cebe69b 100644 --- a/native/src/init/Cargo.toml +++ b/native/src/init/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "magiskinit" -version = "0.1.0" +version = "0.0.0" edition = "2021" [lib] diff --git a/native/src/sepolicy/Cargo.toml b/native/src/sepolicy/Cargo.toml index 3b1ecaecf..e07df6d49 100644 --- a/native/src/sepolicy/Cargo.toml +++ b/native/src/sepolicy/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "magiskpolicy" -version = "0.1.0" +version = "0.0.0" edition = "2021" [lib] diff --git a/native/src/sepolicy/policydb.cpp b/native/src/sepolicy/policydb.cpp index 32b1a2764..3852c73b4 100644 --- a/native/src/sepolicy/policydb.cpp +++ b/native/src/sepolicy/policydb.cpp @@ -87,7 +87,7 @@ sepolicy *sepolicy::from_data(char *data, size_t len) { pf.len = len; pf.type = PF_USE_MEMORY; - auto db = static_cast(xmalloc(sizeof(policydb_t))); + auto db = static_cast(malloc(sizeof(policydb_t))); if (policydb_init(db) || policydb_read(db, &pf, 0)) { LOGE("Fail to load policy from data\n"); free(db); @@ -107,7 +107,7 @@ sepolicy *sepolicy::from_file(const char *file) { pf.fp = fp.get(); pf.type = PF_USE_STDIO; - auto db = static_cast(xmalloc(sizeof(policydb_t))); + auto db = static_cast(malloc(sizeof(policydb_t))); if (policydb_init(db) || policydb_read(db, &pf, 0)) { LOGE("Fail to load policy from %s\n", file); free(db); diff --git a/native/src/sepolicy/sepolicy.cpp b/native/src/sepolicy/sepolicy.cpp index cec2c913f..59d4aa077 100644 --- a/native/src/sepolicy/sepolicy.cpp +++ b/native/src/sepolicy/sepolicy.cpp @@ -291,7 +291,7 @@ void sepol_impl::add_xperm_rule(type_datum_t *src, type_datum_t *tgt, datum = &get_avtab_node(&key, &xperms)->datum; if (datum->xperms == nullptr) - datum->xperms = auto_cast(xmalloc(sizeof(xperms))); + datum->xperms = auto_cast(malloc(sizeof(xperms))); memcpy(datum->xperms, &xperms, sizeof(xperms)); } @@ -425,7 +425,7 @@ bool sepol_impl::add_filename_trans(const char *s, const char *t, const char *c, } if (trans == nullptr) { - trans = auto_cast(xcalloc(sizeof(*trans), 1)); + trans = auto_cast(calloc(sizeof(*trans), 1)); filename_trans_key_t *new_key = auto_cast(malloc(sizeof(*new_key))); *new_key = key; new_key->name = strdup(key.name); @@ -447,7 +447,7 @@ bool sepol_impl::add_genfscon(const char *fs_name, const char *path, const char } // Allocate genfs context - ocontext_t *newc = auto_cast(xcalloc(sizeof(*newc), 1)); + ocontext_t *newc = auto_cast(calloc(sizeof(*newc), 1)); newc->u.name = strdup(path); memcpy(&newc->context[0], ctx, sizeof(*ctx)); free(ctx); @@ -463,7 +463,7 @@ bool sepol_impl::add_genfscon(const char *fs_name, const char *path, const char last_gen = node; } if (newfs == nullptr) { - newfs = auto_cast(xcalloc(sizeof(*newfs), 1)); + newfs = auto_cast(calloc(sizeof(*newfs), 1)); newfs->fstype = strdup(fs_name); // Insert if (last_gen) @@ -505,7 +505,7 @@ bool sepol_impl::add_type(const char *type_name, uint32_t flavor) { return true; } - type = auto_cast(xmalloc(sizeof(type_datum_t))); + type = auto_cast(malloc(sizeof(type_datum_t))); type_datum_init(type); type->primary = 1; type->flavor = flavor; @@ -517,8 +517,8 @@ bool sepol_impl::add_type(const char *type_name, uint32_t flavor) { ebitmap_set_bit(&db->global->branch_list->declared.p_types_scope, value - 1, 1); auto new_size = sizeof(ebitmap_t) * db->p_types.nprim; - db->type_attr_map = auto_cast(xrealloc(db->type_attr_map, new_size)); - db->attr_type_map = auto_cast(xrealloc(db->attr_type_map, new_size)); + db->type_attr_map = auto_cast(realloc(db->type_attr_map, new_size)); + db->attr_type_map = auto_cast(realloc(db->attr_type_map, new_size)); ebitmap_init(&db->type_attr_map[value - 1]); ebitmap_init(&db->attr_type_map[value - 1]); ebitmap_set_bit(&db->type_attr_map[value - 1], value - 1, 1);