Move part of libbase to Rust

This commit is contained in:
topjohnwu 2022-08-08 22:53:37 -07:00
parent dd565a11ea
commit 4c0f72f68f
19 changed files with 205 additions and 130 deletions

17
native/src/Cargo.lock generated
View File

@ -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",
]

View File

@ -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"

View File

@ -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 {

View File

@ -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)+) => {};
}

View File

@ -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<const N: usize>(&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())) }
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -5,12 +5,12 @@
#include <poll.h>
#include <fcntl.h>
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<void *>(data));
}
#define WEVENT(s) (((s) & 0xffff0000) >> 16)
} // extern "C"

57
native/src/base/xwrap.rs Normal file
View File

@ -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)
};
}

View File

@ -1,6 +1,6 @@
[package]
name = "magiskboot"
version = "0.1.0"
version = "0.0.0"
edition = "2021"
[lib]

View File

@ -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 { \

View File

@ -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);

View File

@ -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<uint8_t *>(xmalloc(len + MAX_FDT_GROWTH));
auto fdt = static_cast<uint8_t *>(malloc(len + MAX_FDT_GROWTH));
memcpy(fdt, curr, len);
fdt_pack(fdt);
uint32_t padding = len - fdt_totalsize(fdt);

View File

@ -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);
}

View File

@ -1,6 +1,6 @@
[package]
name = "magisk"
version = "0.1.0"
version = "0.0.0"
edition = "2021"
[lib]

View File

@ -1,6 +1,6 @@
[package]
name = "magiskinit"
version = "0.1.0"
version = "0.0.0"
edition = "2021"
[lib]

View File

@ -1,6 +1,6 @@
[package]
name = "magiskpolicy"
version = "0.1.0"
version = "0.0.0"
edition = "2021"
[lib]

View File

@ -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<policydb_t *>(xmalloc(sizeof(policydb_t)));
auto db = static_cast<policydb_t *>(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<policydb_t *>(xmalloc(sizeof(policydb_t)));
auto db = static_cast<policydb_t *>(malloc(sizeof(policydb_t)));
if (policydb_init(db) || policydb_read(db, &pf, 0)) {
LOGE("Fail to load policy from %s\n", file);
free(db);

View File

@ -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);