mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-10-27 17:40:36 +00:00
Make Utf8CStr a first class citizen in C++ codebase
Utf8CStr is in many cases a better string view class than std::string_view, because it provides "view" access to a string buffer that is guaranteed to be null terminated. It also has the additional benefit of being UTF-8 verified and can seemlessly cross FFI boundaries. We would want to start use more Utf8CStr in our existing C++ codebase.
This commit is contained in:
@@ -273,7 +273,7 @@ static int fmt_and_log_with_rs(LogLevel level, const char *fmt, va_list ap) {
|
||||
buf[0] = '\0';
|
||||
// Fortify logs when a fatal error occurs. Do not run through fortify again
|
||||
int len = std::min(__call_bypassing_fortify(vsnprintf)(buf, sz, fmt, ap), sz - 1);
|
||||
log_with_rs(level, rust::Utf8CStr(buf, len + 1));
|
||||
log_with_rs(level, Utf8CStr(buf, len + 1));
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -415,18 +415,18 @@ string resolve_preinit_dir(const char *base_dir) {
|
||||
|
||||
// FFI for Utf8CStr
|
||||
|
||||
extern "C" void cxx$utf8str$new(rust::Utf8CStr *self, const void *s, size_t len);
|
||||
extern "C" const char *cxx$utf8str$ptr(const rust::Utf8CStr *self);
|
||||
extern "C" size_t cxx$utf8str$len(const rust::Utf8CStr *self);
|
||||
extern "C" void cxx$utf8str$new(Utf8CStr *self, const void *s, size_t len);
|
||||
extern "C" const char *cxx$utf8str$ptr(const Utf8CStr *self);
|
||||
extern "C" size_t cxx$utf8str$len(const Utf8CStr *self);
|
||||
|
||||
rust::Utf8CStr::Utf8CStr(const char *s, size_t len) {
|
||||
Utf8CStr::Utf8CStr(const char *s, size_t len) {
|
||||
cxx$utf8str$new(this, s, len);
|
||||
}
|
||||
|
||||
const char *rust::Utf8CStr::data() const {
|
||||
const char *Utf8CStr::data() const {
|
||||
return cxx$utf8str$ptr(this);
|
||||
}
|
||||
|
||||
size_t rust::Utf8CStr::length() const {
|
||||
size_t Utf8CStr::length() const {
|
||||
return cxx$utf8str$len(this);
|
||||
}
|
||||
|
||||
@@ -369,7 +369,7 @@ impl AsRef<Utf8CStr> for Utf8CStr {
|
||||
|
||||
// Notice that we only implement ExternType on Utf8CStr *reference*
|
||||
unsafe impl ExternType for &Utf8CStr {
|
||||
type Id = type_id!("rust::Utf8CStr");
|
||||
type Id = type_id!("Utf8CStr");
|
||||
type Kind = cxx::kind::Trivial;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ use std::os::fd::{BorrowedFd, FromRawFd, OwnedFd, RawFd};
|
||||
use cfg_if::cfg_if;
|
||||
use libc::{O_RDONLY, c_char, mode_t};
|
||||
|
||||
use crate::ffi::{FnBoolStrStr, FnBoolString};
|
||||
use crate::ffi::{FnBoolStr, FnBoolStrStr};
|
||||
use crate::files::map_file_at;
|
||||
pub(crate) use crate::xwrap::*;
|
||||
use crate::{
|
||||
@@ -183,7 +183,7 @@ pub(crate) fn parse_prop_file_rs(name: &Utf8CStr, f: &FnBoolStrStr) {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn file_readline_rs(fd: RawFd, f: &FnBoolString) {
|
||||
pub(crate) fn file_readline_for_cxx(fd: RawFd, f: &FnBoolStr) {
|
||||
let mut fd = ManuallyDrop::new(unsafe { File::from_raw_fd(fd) });
|
||||
BufReader::new(fd.deref_mut()).for_each_line(|line| f.call(line));
|
||||
BufReader::new(fd.deref_mut()).for_each_line(|line| f.call(Utf8CStr::from_string(line)));
|
||||
}
|
||||
|
||||
@@ -38,22 +38,18 @@ std::string full_read(const char *filename);
|
||||
void write_zero(int fd, size_t size);
|
||||
std::string resolve_preinit_dir(const char *base_dir);
|
||||
|
||||
// Functor = function<bool(string_view)>
|
||||
template <typename Functor>
|
||||
void file_readline(int fd, Functor &&fn) {
|
||||
file_readline_rs(fd, [&](rust::String &line) -> bool {
|
||||
return fn(std::string_view(line.c_str(), line.size()));
|
||||
});
|
||||
}
|
||||
|
||||
// Functor = function<bool(string_view, string_view)>
|
||||
// Functor = function<bool(Utf8CStr, Utf8CStr)>
|
||||
template <typename Functor>
|
||||
void parse_prop_file(const char *file, Functor &&fn) {
|
||||
parse_prop_file_rs(file, [&](rust::Str key, rust::Str val) -> bool {
|
||||
// Null terminate all strings
|
||||
// We perform the null termination here in C++ because it's very difficult to do it
|
||||
// right in Rust due to pointer provenance. Trying to dereference a pointer without
|
||||
// the correct provenance in Rust, even in unsafe code, is undefined behavior.
|
||||
// However on the C++ side, there are fewer restrictions on pointers, so the const_cast here
|
||||
// will not trigger UB in the compiler.
|
||||
*(const_cast<char *>(key.data()) + key.size()) = '\0';
|
||||
*(const_cast<char *>(val.data()) + val.size()) = '\0';
|
||||
return fn(std::string_view(key.data(), key.size()), std::string_view(val.data(), val.size()));
|
||||
return fn(Utf8CStr(key.data(), key.size() + 1), Utf8CStr(val.data(), val.size() + 1));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,6 @@ pub mod ffi {
|
||||
unsafe extern "C++" {
|
||||
include!("misc.hpp");
|
||||
|
||||
#[namespace = "rust"]
|
||||
#[cxx_name = "Utf8CStr"]
|
||||
type Utf8CStrRef<'a> = &'a crate::cstr::Utf8CStr;
|
||||
|
||||
@@ -51,8 +50,8 @@ pub mod ffi {
|
||||
type FnBoolStrStr;
|
||||
fn call(self: &FnBoolStrStr, key: &str, value: &str) -> bool;
|
||||
|
||||
type FnBoolString;
|
||||
fn call(self: &FnBoolString, key: &mut String) -> bool;
|
||||
type FnBoolStr;
|
||||
fn call(self: &FnBoolStr, key: Utf8CStrRef) -> bool;
|
||||
}
|
||||
|
||||
extern "Rust" {
|
||||
@@ -63,7 +62,8 @@ pub mod ffi {
|
||||
fn exit_on_error(b: bool);
|
||||
fn cmdline_logging();
|
||||
fn parse_prop_file_rs(name: Utf8CStrRef, f: &FnBoolStrStr);
|
||||
fn file_readline_rs(fd: i32, f: &FnBoolString);
|
||||
#[cxx_name = "file_readline"]
|
||||
fn file_readline_for_cxx(fd: i32, f: &FnBoolStr);
|
||||
}
|
||||
|
||||
#[namespace = "rust"]
|
||||
|
||||
@@ -136,21 +136,6 @@ int parse_int(std::string_view s);
|
||||
using thread_entry = void *(*)(void *);
|
||||
extern "C" int new_daemon_thread(thread_entry entry, void *arg = nullptr);
|
||||
|
||||
static inline bool str_contains(std::string_view s, std::string_view ss) {
|
||||
return s.find(ss) != std::string::npos;
|
||||
}
|
||||
static inline bool str_starts(std::string_view s, std::string_view ss) {
|
||||
return s.size() >= ss.size() && s.compare(0, ss.size(), ss) == 0;
|
||||
}
|
||||
static inline bool str_ends(std::string_view s, std::string_view ss) {
|
||||
return s.size() >= ss.size() && s.compare(s.size() - ss.size(), std::string::npos, ss) == 0;
|
||||
}
|
||||
static inline std::string ltrim(std::string &&s) {
|
||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) {
|
||||
return !std::isspace(ch);
|
||||
}));
|
||||
return std::move(s);
|
||||
}
|
||||
static inline std::string rtrim(std::string &&s) {
|
||||
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
|
||||
return !std::isspace(ch) && ch != '\0';
|
||||
@@ -222,8 +207,6 @@ constexpr auto operator+(T e) noexcept ->
|
||||
return static_cast<std::underlying_type_t<T>>(e);
|
||||
}
|
||||
|
||||
namespace rust {
|
||||
|
||||
struct Utf8CStr {
|
||||
const char *data() const;
|
||||
size_t length() const;
|
||||
@@ -236,8 +219,9 @@ struct Utf8CStr {
|
||||
const char *c_str() const { return this->data(); }
|
||||
size_t size() const { return this->length(); }
|
||||
bool empty() const { return this->length() == 0 ; }
|
||||
operator std::string_view() const { return {data(), length()}; }
|
||||
bool operator==(std::string_view rhs) const { return std::string_view{data(), length()} == rhs; }
|
||||
std::string_view sv() const { return {data(), length()}; }
|
||||
operator std::string_view() const { return sv(); }
|
||||
bool operator==(std::string_view rhs) const { return sv() == rhs; }
|
||||
|
||||
private:
|
||||
#pragma clang diagnostic push
|
||||
@@ -246,8 +230,6 @@ private:
|
||||
#pragma clang diagnostic pop
|
||||
};
|
||||
|
||||
} // namespace rust
|
||||
|
||||
// Bindings for std::function to be callable from Rust
|
||||
|
||||
using CxxFnBoolStrStr = std::function<bool(rust::Str, rust::Str)>;
|
||||
@@ -257,10 +239,10 @@ struct FnBoolStrStr : public CxxFnBoolStrStr {
|
||||
return operator()(a, b);
|
||||
}
|
||||
};
|
||||
using CxxFnBoolString = std::function<bool(rust::String&)>;
|
||||
struct FnBoolString : public CxxFnBoolString {
|
||||
using CxxFnBoolString::function;
|
||||
bool call(rust::String &s) const {
|
||||
using CxxFnBoolStr = std::function<bool(Utf8CStr)>;
|
||||
struct FnBoolStr : public CxxFnBoolStr {
|
||||
using CxxFnBoolStr::function;
|
||||
bool call(Utf8CStr s) const {
|
||||
return operator()(s);
|
||||
}
|
||||
};
|
||||
@@ -156,7 +156,7 @@ void dyn_img_hdr::dump_hdr_file() const {
|
||||
}
|
||||
|
||||
void dyn_img_hdr::load_hdr_file() {
|
||||
parse_prop_file(HEADER_FILE, [=, this](string_view key, string_view value) -> bool {
|
||||
parse_prop_file(HEADER_FILE, [=, this](Utf8CStr key, Utf8CStr value) -> bool {
|
||||
if (key == "name" && name()) {
|
||||
memset(name(), 0, 16);
|
||||
memcpy(name(), value.data(), value.length() > 15 ? 15 : value.length());
|
||||
@@ -166,7 +166,7 @@ void dyn_img_hdr::load_hdr_file() {
|
||||
if (value.length() > BOOT_ARGS_SIZE) {
|
||||
memcpy(cmdline(), value.data(), BOOT_ARGS_SIZE);
|
||||
auto len = std::min(value.length() - BOOT_ARGS_SIZE, (size_t) BOOT_EXTRA_ARGS_SIZE);
|
||||
memcpy(extra_cmdline(), &value[BOOT_ARGS_SIZE], len);
|
||||
memcpy(extra_cmdline(), value.data() + BOOT_ARGS_SIZE, len);
|
||||
} else {
|
||||
memcpy(cmdline(), value.data(), value.length());
|
||||
}
|
||||
@@ -583,7 +583,7 @@ bool boot_img::parse_image(const uint8_t *p, FileFormat type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int split_image_dtb(rust::Utf8CStr filename, bool skip_decomp) {
|
||||
int split_image_dtb(Utf8CStr filename, bool skip_decomp) {
|
||||
mmap_data img(filename.data());
|
||||
|
||||
if (size_t off = find_dtb_offset(img.data(), img.size()); off > 0) {
|
||||
@@ -603,7 +603,7 @@ int split_image_dtb(rust::Utf8CStr filename, bool skip_decomp) {
|
||||
}
|
||||
}
|
||||
|
||||
int unpack(rust::Utf8CStr image, bool skip_decomp, bool hdr) {
|
||||
int unpack(Utf8CStr image, bool skip_decomp, bool hdr) {
|
||||
const boot_img boot(image.data());
|
||||
|
||||
if (hdr)
|
||||
@@ -688,7 +688,7 @@ write_zero(fd, align_padding(lseek(fd, 0, SEEK_CUR) - off.header, page_size))
|
||||
|
||||
#define file_align() file_align_with(boot.hdr->page_size())
|
||||
|
||||
void repack(rust::Utf8CStr src_img, rust::Utf8CStr out_img, bool skip_comp) {
|
||||
void repack(Utf8CStr src_img, Utf8CStr out_img, bool skip_comp) {
|
||||
const boot_img boot(src_img.data());
|
||||
fprintf(stderr, "Repack to boot image: [%s]\n", out_img.data());
|
||||
|
||||
|
||||
@@ -685,7 +685,7 @@ struct boot_img {
|
||||
std::pair<const uint8_t *, dyn_img_hdr *> create_hdr(const uint8_t *addr, FileFormat type);
|
||||
|
||||
// Rust FFI
|
||||
static std::unique_ptr<boot_img> create(rust::Utf8CStr name) { return std::make_unique<boot_img>(name.c_str()); }
|
||||
static std::unique_ptr<boot_img> create(Utf8CStr name) { return std::make_unique<boot_img>(name.c_str()); }
|
||||
rust::Slice<const uint8_t> get_payload() const { return payload; }
|
||||
rust::Slice<const uint8_t> get_tail() const { return tail; }
|
||||
bool is_signed() const { return flags[AVB1_SIGNED_FLAG]; }
|
||||
|
||||
@@ -49,15 +49,11 @@ pub mod ffi {
|
||||
}
|
||||
|
||||
unsafe extern "C++" {
|
||||
include!("../base/include/base.hpp");
|
||||
include!("magiskboot.hpp");
|
||||
|
||||
#[namespace = "rust"]
|
||||
#[cxx_name = "Utf8CStr"]
|
||||
type Utf8CStrRef<'a> = base::ffi::Utf8CStrRef<'a>;
|
||||
}
|
||||
|
||||
unsafe extern "C++" {
|
||||
include!("magiskboot.hpp");
|
||||
fn cleanup();
|
||||
fn unpack(image: Utf8CStrRef, skip_decomp: bool, hdr: bool) -> i32;
|
||||
fn repack(src_img: Utf8CStrRef, out_img: Utf8CStrRef, skip_comp: bool);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <base.hpp>
|
||||
|
||||
#define HEADER_FILE "header"
|
||||
#define KERNEL_FILE "kernel"
|
||||
#define RAMDISK_FILE "ramdisk.cpio"
|
||||
@@ -47,11 +49,11 @@
|
||||
#define AVB_MAGIC "AVB0"
|
||||
#define ZIMAGE_MAGIC "\x18\x28\x6f\x01"
|
||||
|
||||
enum class FileFormat : ::std::uint8_t;
|
||||
enum class FileFormat : uint8_t;
|
||||
|
||||
int unpack(rust::Utf8CStr image, bool skip_decomp = false, bool hdr = false);
|
||||
void repack(rust::Utf8CStr src_img, rust::Utf8CStr out_img, bool skip_comp = false);
|
||||
int split_image_dtb(rust::Utf8CStr filename, bool skip_decomp = false);
|
||||
int unpack(Utf8CStr image, bool skip_decomp = false, bool hdr = false);
|
||||
void repack(Utf8CStr src_img, Utf8CStr out_img, bool skip_comp = false);
|
||||
int split_image_dtb(Utf8CStr filename, bool skip_decomp = false);
|
||||
void cleanup();
|
||||
FileFormat check_fmt(const void *buf, size_t len);
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ int main(int argc, char *argv[]) {
|
||||
cmdline_logging();
|
||||
init_argv0(argc, argv);
|
||||
|
||||
string_view argv0 = basename(argv[0]);
|
||||
Utf8CStr argv0 = basename(argv[0]);
|
||||
|
||||
umask(0);
|
||||
|
||||
@@ -63,6 +63,6 @@ int main(int argc, char *argv[]) {
|
||||
return app.fn(argc, argv);
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "%s: applet not found\n", argv0.data());
|
||||
fprintf(stderr, "%s: applet not found\n", argv0.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -389,7 +389,7 @@ int connect_daemon(int req, bool create) {
|
||||
|
||||
char buf[64];
|
||||
xreadlink("/proc/self/exe", buf, sizeof(buf));
|
||||
if (tmp[0] == '\0' || !str_starts(buf, tmp)) {
|
||||
if (tmp[0] == '\0' || !string_view(buf).starts_with(tmp)) {
|
||||
LOGE("Start daemon on magisk tmpfs\n");
|
||||
close(fd);
|
||||
return -1;
|
||||
|
||||
@@ -90,9 +90,10 @@ static void crawl_procfs(const F &fn) {
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool str_eql(string_view a, string_view b) { return a == b; }
|
||||
static bool str_eql(string_view a, string_view b) { return a == b; }
|
||||
static bool str_starts_with(string_view a, string_view b) { return a.starts_with(b); }
|
||||
|
||||
template<bool str_op(string_view, string_view) = &str_eql>
|
||||
template<bool str_op(string_view, string_view) = str_eql>
|
||||
static bool proc_name_match(int pid, string_view name) {
|
||||
char buf[4019];
|
||||
sprintf(buf, "/proc/%d/cmdline", pid);
|
||||
@@ -111,7 +112,7 @@ bool proc_context_match(int pid, string_view context) {
|
||||
|
||||
sprintf(buf, "/proc/%d", pid);
|
||||
if (lgetfilecon(buf, byte_data{ con, sizeof(con) })) {
|
||||
return str_starts(con, context);
|
||||
return string_view(con).starts_with(context);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -173,7 +174,7 @@ static bool add_hide_set(const char *pkg, const char *proc) {
|
||||
return true;
|
||||
if (str_eql(pkg, ISOLATED_MAGIC)) {
|
||||
// Kill all matching isolated processes
|
||||
kill_process<&proc_name_match<str_starts>>(proc, true);
|
||||
kill_process<&proc_name_match<str_starts_with>>(proc, true);
|
||||
} else {
|
||||
kill_process(proc);
|
||||
}
|
||||
@@ -411,7 +412,7 @@ bool is_deny_target(int uid, string_view process) {
|
||||
if (app_id >= 90000) {
|
||||
if (auto it = pkg_to_procs.find(ISOLATED_MAGIC); it != pkg_to_procs.end()) {
|
||||
for (const auto &s : it->second) {
|
||||
if (str_starts(process, s))
|
||||
if (process.starts_with(s))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,10 +88,10 @@ void exec_task(std::function<void()> &&task);
|
||||
void denylist_handler(int client, const sock_cred *cred);
|
||||
|
||||
// Scripting
|
||||
void install_apk(rust::Utf8CStr apk);
|
||||
void uninstall_pkg(rust::Utf8CStr pkg);
|
||||
void exec_common_scripts(rust::Utf8CStr stage);
|
||||
void exec_module_scripts(rust::Utf8CStr stage, const rust::Vec<ModuleInfo> &module_list);
|
||||
void install_apk(Utf8CStr apk);
|
||||
void uninstall_pkg(Utf8CStr pkg);
|
||||
void exec_common_scripts(Utf8CStr stage);
|
||||
void exec_module_scripts(Utf8CStr stage, const rust::Vec<ModuleInfo> &module_list);
|
||||
void exec_script(const char *script);
|
||||
void clear_pkg(const char *pkg, int user_id);
|
||||
[[noreturn]] void install_module(const char *file);
|
||||
@@ -109,8 +109,8 @@ void update_deny_flags(int uid, rust::Str process, uint32_t &flags);
|
||||
void exec_root_shell(int client, int pid, SuRequest &req, MntNsMode mode);
|
||||
|
||||
// Rust bindings
|
||||
static inline rust::Utf8CStr get_magisk_tmp_rs() { return get_magisk_tmp(); }
|
||||
static inline rust::String resolve_preinit_dir_rs(rust::Utf8CStr base_dir) {
|
||||
static inline Utf8CStr get_magisk_tmp_rs() { return get_magisk_tmp(); }
|
||||
static inline rust::String resolve_preinit_dir_rs(Utf8CStr base_dir) {
|
||||
return resolve_preinit_dir(base_dir.c_str());
|
||||
}
|
||||
static inline void exec_script_rs(rust::Utf8CStr script) { exec_script(script.data()); }
|
||||
static inline void exec_script_rs(Utf8CStr script) { exec_script(script.data()); }
|
||||
|
||||
@@ -26,13 +26,13 @@ int set_prop(const char *name, const char *value, bool skip_svc = false);
|
||||
void load_prop_file(const char *filename, bool skip_svc = false);
|
||||
|
||||
// Rust bindings
|
||||
rust::String get_prop_rs(rust::Utf8CStr name, bool persist);
|
||||
static inline int set_prop_rs(rust::Utf8CStr name, rust::Utf8CStr value, bool skip_svc) {
|
||||
rust::String get_prop_rs(Utf8CStr name, bool persist);
|
||||
static inline int set_prop_rs(Utf8CStr name, Utf8CStr value, bool skip_svc) {
|
||||
return set_prop(name.data(), value.data(), skip_svc);
|
||||
}
|
||||
static inline void load_prop_file_rs(rust::Utf8CStr filename, bool skip_svc) {
|
||||
static inline void load_prop_file_rs(Utf8CStr filename, bool skip_svc) {
|
||||
load_prop_file(filename.data(), skip_svc);
|
||||
}
|
||||
static inline void prop_cb_exec(prop_cb &cb, rust::Utf8CStr name, rust::Utf8CStr value, uint32_t serial) {
|
||||
static inline void prop_cb_exec(prop_cb &cb, Utf8CStr name, Utf8CStr value, uint32_t serial) {
|
||||
cb.exec(name.data(), value.data(), serial);
|
||||
}
|
||||
@@ -127,7 +127,6 @@ pub mod ffi {
|
||||
}
|
||||
|
||||
unsafe extern "C++" {
|
||||
#[namespace = "rust"]
|
||||
#[cxx_name = "Utf8CStr"]
|
||||
type Utf8CStrRef<'a> = base::ffi::Utf8CStrRef<'a>;
|
||||
#[cxx_name = "ucred"]
|
||||
|
||||
@@ -143,6 +143,10 @@ template<> void prop_to_string<rust::String>::exec(const char *, const char *val
|
||||
serial = s;
|
||||
}
|
||||
|
||||
static bool str_starts(std::string_view s, std::string_view ss) {
|
||||
return s.starts_with(ss);
|
||||
}
|
||||
|
||||
static int set_prop(const char *name, const char *value, PropFlags flags) {
|
||||
if (!check_legal_property_name(name))
|
||||
return 1;
|
||||
@@ -429,7 +433,7 @@ static StringType get_prop_impl(const char *name, bool persist) {
|
||||
return get_prop<StringType>(name, flags);
|
||||
}
|
||||
|
||||
rust::String get_prop_rs(rust::Utf8CStr name, bool persist) {
|
||||
rust::String get_prop_rs(Utf8CStr name, bool persist) {
|
||||
return get_prop_impl<rust::String>(name.data(), persist);
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ if (pfs) { \
|
||||
exit(0); \
|
||||
}
|
||||
|
||||
void exec_common_scripts(rust::Utf8CStr stage) {
|
||||
void exec_common_scripts(Utf8CStr stage) {
|
||||
LOGI("* Running %s.d scripts\n", stage.c_str());
|
||||
char path[4096];
|
||||
char *name = path + sprintf(path, SECURE_DIR "/%s.d", stage.c_str());
|
||||
@@ -116,12 +116,12 @@ static bool operator>(const timespec &a, const timespec &b) {
|
||||
return a.tv_nsec > b.tv_nsec;
|
||||
}
|
||||
|
||||
void exec_module_scripts(rust::Utf8CStr stage, const rust::Vec<ModuleInfo> &module_list) {
|
||||
void exec_module_scripts(Utf8CStr stage, const rust::Vec<ModuleInfo> &module_list) {
|
||||
LOGI("* Running module %s scripts\n", stage.c_str());
|
||||
if (module_list.empty())
|
||||
return;
|
||||
|
||||
bool pfs = (string_view) stage == "post-fs-data";
|
||||
bool pfs = stage == "post-fs-data";
|
||||
if (pfs) {
|
||||
timespec now{};
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
@@ -157,7 +157,7 @@ appops set %s REQUEST_INSTALL_PACKAGES allow
|
||||
rm -f $APK
|
||||
)EOF";
|
||||
|
||||
void install_apk(rust::Utf8CStr apk) {
|
||||
void install_apk(Utf8CStr apk) {
|
||||
setfilecon(apk.c_str(), MAGISK_FILE_CON);
|
||||
char cmds[sizeof(install_script) + 4096];
|
||||
ssprintf(cmds, sizeof(cmds), install_script, apk.c_str(), JAVA_PACKAGE_NAME);
|
||||
@@ -170,7 +170,7 @@ log -t Magisk "pm_uninstall: $PKG"
|
||||
log -t Magisk "pm_uninstall: $(pm uninstall $PKG 2>&1)"
|
||||
)EOF";
|
||||
|
||||
void uninstall_pkg(rust::Utf8CStr pkg) {
|
||||
void uninstall_pkg(Utf8CStr pkg) {
|
||||
char cmds[sizeof(uninstall_script) + 256];
|
||||
ssprintf(cmds, sizeof(cmds), uninstall_script, pkg.c_str());
|
||||
exec_command_async("/system/bin/sh", "-c", cmds);
|
||||
|
||||
@@ -301,7 +301,8 @@ static bool proc_is_restricted(pid_t pid) {
|
||||
uint32_t data[_LINUX_CAPABILITY_U32S_3] = {};
|
||||
ssprintf(buf, sizeof(buf), "/proc/%d/status", pid);
|
||||
owned_fd status_fd = xopen(buf, O_RDONLY | O_CLOEXEC);
|
||||
file_readline(status_fd, [&](string_view line) -> bool {
|
||||
file_readline(status_fd, [&](Utf8CStr s) -> bool {
|
||||
string_view line = s;
|
||||
if (line.starts_with(bnd)) {
|
||||
auto p = line.begin();
|
||||
advance(p, bnd.size());
|
||||
|
||||
@@ -15,23 +15,23 @@
|
||||
#include "init-rs.hpp"
|
||||
|
||||
int magisk_proxy_main(int, char *argv[]);
|
||||
rust::Utf8CStr backup_init();
|
||||
Utf8CStr backup_init();
|
||||
|
||||
// Expose some constants to Rust
|
||||
|
||||
static inline rust::Utf8CStr split_plat_cil() {
|
||||
static inline Utf8CStr split_plat_cil() {
|
||||
return SPLIT_PLAT_CIL;
|
||||
};
|
||||
|
||||
static inline rust::Utf8CStr preload_lib() {
|
||||
static inline Utf8CStr preload_lib() {
|
||||
return PRELOAD_LIB;
|
||||
}
|
||||
|
||||
static inline rust::Utf8CStr preload_policy() {
|
||||
static inline Utf8CStr preload_policy() {
|
||||
return PRELOAD_POLICY;
|
||||
}
|
||||
|
||||
static inline rust::Utf8CStr preload_ack() {
|
||||
static inline Utf8CStr preload_ack() {
|
||||
return PRELOAD_ACK;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,6 @@ pub mod ffi {
|
||||
unsafe extern "C++" {
|
||||
include!("init.hpp");
|
||||
|
||||
#[namespace = "rust"]
|
||||
#[cxx_name = "Utf8CStr"]
|
||||
type Utf8CStrRef<'a> = base::ffi::Utf8CStrRef<'a>;
|
||||
|
||||
|
||||
@@ -30,15 +30,15 @@ static void parse_device(devinfo *dev, const char *uevent) {
|
||||
dev->devpath[0] = '\0';
|
||||
dev->dmname[0] = '\0';
|
||||
dev->devname[0] = '\0';
|
||||
parse_prop_file(uevent, [=](string_view key, string_view value) -> bool {
|
||||
parse_prop_file(uevent, [=](Utf8CStr key, Utf8CStr value) -> bool {
|
||||
if (key == "MAJOR")
|
||||
dev->major = parse_int(value.data());
|
||||
dev->major = parse_int(value);
|
||||
else if (key == "MINOR")
|
||||
dev->minor = parse_int(value.data());
|
||||
dev->minor = parse_int(value);
|
||||
else if (key == "DEVNAME")
|
||||
strscpy(dev->devname, value.data(), sizeof(dev->devname));
|
||||
strscpy(dev->devname, value.c_str(), sizeof(dev->devname));
|
||||
else if (key == "PARTNAME")
|
||||
strscpy(dev->partname, value.data(), sizeof(dev->devname));
|
||||
strscpy(dev->partname, value.c_str(), sizeof(dev->devname));
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
@@ -67,26 +67,26 @@ static bool patch_rc_scripts(const char *src_path, const char *tmp_path, bool wr
|
||||
xopenat(dest_fd, INIT_RC, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0), "we");
|
||||
if (!dest_rc) return false;
|
||||
LOGD("Patching " INIT_RC " in %s\n", src_path);
|
||||
file_readline(src_rc, [&dest_rc](string_view line) -> bool {
|
||||
file_readline(src_rc, [&dest_rc](Utf8CStr line) -> bool {
|
||||
// Do not start vaultkeeper
|
||||
if (str_contains(line, "start vaultkeeper")) {
|
||||
if (line.sv().contains("start vaultkeeper")) {
|
||||
LOGD("Remove vaultkeeper\n");
|
||||
return true;
|
||||
}
|
||||
// Do not run flash_recovery
|
||||
if (line.starts_with("service flash_recovery")) {
|
||||
if (line.sv().starts_with("service flash_recovery")) {
|
||||
LOGD("Remove flash_recovery\n");
|
||||
fprintf(dest_rc.get(), "service flash_recovery /system/bin/true\n");
|
||||
return true;
|
||||
}
|
||||
// Samsung's persist.sys.zygote.early will cause Zygote to start before post-fs-data
|
||||
if (line.starts_with("on property:persist.sys.zygote.early=")) {
|
||||
if (line.sv().starts_with("on property:persist.sys.zygote.early=")) {
|
||||
LOGD("Invalidate persist.sys.zygote.early\n");
|
||||
fprintf(dest_rc.get(), "on property:persist.sys.zygote.early.xxxxx=true\n");
|
||||
return true;
|
||||
}
|
||||
// Else just write the line
|
||||
fprintf(dest_rc.get(), "%s", line.data());
|
||||
fprintf(dest_rc.get(), "%s", line.c_str());
|
||||
return true;
|
||||
});
|
||||
|
||||
@@ -108,24 +108,26 @@ static bool patch_rc_scripts(const char *src_path, const char *tmp_path, bool wr
|
||||
|
||||
// Then patch init.zygote*.rc
|
||||
for (dirent *entry; (entry = readdir(src_dir.get()));) {
|
||||
auto name = std::string_view(entry->d_name);
|
||||
if (!name.starts_with("init.zygote") || !name.ends_with(".rc")) continue;
|
||||
owned_fd src_rc = xopenat(src_fd, name.data(), O_RDONLY | O_CLOEXEC, 0);
|
||||
{
|
||||
auto name = std::string_view(entry->d_name);
|
||||
if (!name.starts_with("init.zygote") || !name.ends_with(".rc")) continue;
|
||||
}
|
||||
owned_fd src_rc = xopenat(src_fd, entry->d_name, O_RDONLY | O_CLOEXEC, 0);
|
||||
if (src_rc < 0) continue;
|
||||
if (writable) unlinkat(src_fd, name.data(), 0);
|
||||
if (writable) unlinkat(src_fd, entry->d_name, 0);
|
||||
auto dest_rc = xopen_file(
|
||||
xopenat(dest_fd, name.data(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0), "we");
|
||||
xopenat(dest_fd, entry->d_name, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0), "we");
|
||||
if (!dest_rc) continue;
|
||||
LOGD("Patching %s in %s\n", name.data(), src_path);
|
||||
file_readline(src_rc, [&dest_rc, &tmp_path](string_view line) -> bool {
|
||||
if (line.starts_with("service zygote ")) {
|
||||
LOGD("Patching %s in %s\n", entry->d_name, src_path);
|
||||
file_readline(src_rc, [&dest_rc, &tmp_path](Utf8CStr line) -> bool {
|
||||
if (line.sv().starts_with("service zygote ")) {
|
||||
LOGD("Inject zygote restart\n");
|
||||
fprintf(dest_rc.get(), "%s", line.data());
|
||||
fprintf(dest_rc.get(), "%s", line.c_str());
|
||||
fprintf(dest_rc.get(),
|
||||
" onrestart exec " MAGISK_PROC_CON " 0 0 -- %s/magisk --zygote-restart\n", tmp_path);
|
||||
return true;
|
||||
}
|
||||
fprintf(dest_rc.get(), "%s", line.data());
|
||||
fprintf(dest_rc.get(), "%s", line.c_str());
|
||||
return true;
|
||||
});
|
||||
fclone_attr(src_rc, fileno(dest_rc.get()));
|
||||
@@ -184,7 +186,7 @@ static void load_overlay_rc(const char *overlay) {
|
||||
char buf[NAME_MAX + 2];
|
||||
buf[0] = '/';
|
||||
for (dirent *entry; (entry = xreaddir(dir.get()));) {
|
||||
if (!str_ends(entry->d_name, ".rc")) {
|
||||
if (!string_view(entry->d_name).ends_with(".rc")) {
|
||||
continue;
|
||||
}
|
||||
strscpy(buf + 1, entry->d_name, sizeof(buf) - 1);
|
||||
@@ -407,7 +409,7 @@ static void unxz_init(const char *init_xz, const char *init) {
|
||||
unlink(init_xz);
|
||||
}
|
||||
|
||||
rust::Utf8CStr backup_init() {
|
||||
Utf8CStr backup_init() {
|
||||
if (access("/.backup/init.xz", F_OK) == 0)
|
||||
unxz_init("/.backup/init.xz", "/.backup/init");
|
||||
return "/.backup/init";
|
||||
|
||||
@@ -30,7 +30,6 @@ pub mod ffi {
|
||||
include!("policy.hpp");
|
||||
include!("../base/include/base.hpp");
|
||||
|
||||
#[namespace = "rust"]
|
||||
#[cxx_name = "Utf8CStr"]
|
||||
type Utf8CStrRef<'a> = base::ffi::Utf8CStrRef<'a>;
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ SePolicy SePolicy::from_data(rust::Slice<const uint8_t> data) noexcept {
|
||||
return {std::make_unique<sepol_impl>(db)};
|
||||
}
|
||||
|
||||
SePolicy SePolicy::from_file(::rust::Utf8CStr file) noexcept {
|
||||
SePolicy SePolicy::from_file(::Utf8CStr file) noexcept {
|
||||
LOGD("Load policy from: %.*s\n", static_cast<int>(file.size()), file.data());
|
||||
|
||||
policy_file_t pf;
|
||||
@@ -235,7 +235,7 @@ static int vec_write(void *v, const char *buf, int len) {
|
||||
return len;
|
||||
}
|
||||
|
||||
bool SePolicy::to_file(::rust::Utf8CStr file) const noexcept {
|
||||
bool SePolicy::to_file(::Utf8CStr file) const noexcept {
|
||||
// No partial writes are allowed to /sys/fs/selinux/load, thus the reason why we
|
||||
// first dump everything into memory, then directly call write system call
|
||||
vector<char> out;
|
||||
|
||||
Reference in New Issue
Block a user