mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-22 16:07:39 +00:00
Create custom cxx binding to Utf8CStr
This commit is contained in:
parent
062e498bdd
commit
65207f96c8
@ -6,10 +6,12 @@ use std::path::Path;
|
|||||||
use std::str::{Utf8Chunks, Utf8Error};
|
use std::str::{Utf8Chunks, Utf8Error};
|
||||||
use std::{fmt, mem, slice, str};
|
use std::{fmt, mem, slice, str};
|
||||||
|
|
||||||
use crate::slice_from_ptr_mut;
|
use cxx::{type_id, ExternType};
|
||||||
use libc::c_char;
|
use libc::c_char;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
use crate::slice_from_ptr_mut;
|
||||||
|
|
||||||
// Utf8CStr types are UTF-8 validated and null terminated strings.
|
// Utf8CStr types are UTF-8 validated and null terminated strings.
|
||||||
//
|
//
|
||||||
// Several Utf8CStr types:
|
// Several Utf8CStr types:
|
||||||
@ -380,6 +382,22 @@ impl DerefMut for Utf8CStr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notice that we only implement ExternType on Utf8CStr *reference*
|
||||||
|
unsafe impl ExternType for &Utf8CStr {
|
||||||
|
type Id = type_id!("rust::Utf8CStr");
|
||||||
|
type Kind = cxx::kind::Trivial;
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! const_assert_eq {
|
||||||
|
($left:expr, $right:expr $(,)?) => {
|
||||||
|
const _: [(); $left] = [(); $right];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assert ABI layout
|
||||||
|
const_assert_eq!(mem::size_of::<&Utf8CStr>(), mem::size_of::<[usize; 2]>());
|
||||||
|
const_assert_eq!(mem::align_of::<&Utf8CStr>(), mem::align_of::<[usize; 2]>());
|
||||||
|
|
||||||
// File system path extensions types
|
// File system path extensions types
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
|
@ -10,7 +10,8 @@ use libc::mode_t;
|
|||||||
use crate::logging::CxxResultExt;
|
use crate::logging::CxxResultExt;
|
||||||
pub(crate) use crate::xwrap::*;
|
pub(crate) use crate::xwrap::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
clone_attr, fclone_attr, fd_path, map_fd, map_file, Directory, FsPath, Utf8CStr, Utf8CStrBufRef,
|
clone_attr, cstr, fclone_attr, fd_path, map_fd, map_file, slice_from_ptr, Directory, FsPath,
|
||||||
|
Utf8CStr, Utf8CStrBufRef,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) fn fd_path_for_cxx(fd: RawFd, buf: &mut [u8]) -> isize {
|
pub(crate) fn fd_path_for_cxx(fd: RawFd, buf: &mut [u8]) -> isize {
|
||||||
@ -57,12 +58,8 @@ unsafe extern "C" fn frm_rf(fd: OwnedFd) -> bool {
|
|||||||
inner(fd).is_ok()
|
inner(fd).is_ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn map_file_for_cxx(path: &[u8], rw: bool) -> &'static mut [u8] {
|
pub(crate) fn map_file_for_cxx(path: &Utf8CStr, rw: bool) -> &'static mut [u8] {
|
||||||
unsafe {
|
map_file(path, rw).log_cxx().unwrap_or(&mut [])
|
||||||
map_file(Utf8CStr::from_bytes_unchecked(path), rw)
|
|
||||||
.log_cxx()
|
|
||||||
.unwrap_or(&mut [])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn map_fd_for_cxx(fd: RawFd, sz: usize, rw: bool) -> &'static mut [u8] {
|
pub(crate) fn map_fd_for_cxx(fd: RawFd, sz: usize, rw: bool) -> &'static mut [u8] {
|
||||||
@ -171,3 +168,18 @@ unsafe extern "C" fn fclone_attr_for_cxx(a: RawFd, b: RawFd) -> bool {
|
|||||||
.log_cxx_with_msg(|w| w.write_str("fclone_attr failed"))
|
.log_cxx_with_msg(|w| w.write_str("fclone_attr failed"))
|
||||||
.is_ok()
|
.is_ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[export_name = "cxx$utf8str$new"]
|
||||||
|
unsafe extern "C" fn str_new(this: &mut &Utf8CStr, s: *const u8, len: usize) {
|
||||||
|
*this = Utf8CStr::from_bytes(slice_from_ptr(s, len)).unwrap_or(cstr!(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[export_name = "cxx$utf8str$ptr"]
|
||||||
|
unsafe extern "C" fn str_ptr(this: &&Utf8CStr) -> *const u8 {
|
||||||
|
this.as_ptr().cast()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[export_name = "cxx$utf8str$len"]
|
||||||
|
unsafe extern "C" fn str_len(this: &&Utf8CStr) -> usize {
|
||||||
|
this.len()
|
||||||
|
}
|
||||||
|
@ -189,7 +189,7 @@ sFILE make_file(FILE *fp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mmap_data::mmap_data(const char *name, bool rw) {
|
mmap_data::mmap_data(const char *name, bool rw) {
|
||||||
auto slice = rust::map_file(byte_view(name), rw);
|
auto slice = rust::map_file(name, rw);
|
||||||
if (!slice.empty()) {
|
if (!slice.empty()) {
|
||||||
_buf = slice.data();
|
_buf = slice.data();
|
||||||
_sz = slice.size();
|
_sz = slice.size();
|
||||||
|
@ -34,12 +34,17 @@ pub mod ffi {
|
|||||||
|
|
||||||
unsafe extern "C++" {
|
unsafe extern "C++" {
|
||||||
include!("misc.hpp");
|
include!("misc.hpp");
|
||||||
|
|
||||||
|
#[namespace = "rust"]
|
||||||
|
#[cxx_name = "Utf8CStr"]
|
||||||
|
type Utf8CStrRef<'a> = &'a crate::cstr::Utf8CStr;
|
||||||
|
|
||||||
fn mut_u8_patch(buf: &mut [u8], from: &[u8], to: &[u8]) -> Vec<usize>;
|
fn mut_u8_patch(buf: &mut [u8], from: &[u8], to: &[u8]) -> Vec<usize>;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
#[cxx_name = "log_with_rs"]
|
#[cxx_name = "log_with_rs"]
|
||||||
fn log_from_cxx(level: LogLevelCxx, msg: &[u8]);
|
fn log_from_cxx(level: LogLevelCxx, msg: Utf8CStrRef);
|
||||||
#[cxx_name = "set_log_level_state"]
|
#[cxx_name = "set_log_level_state"]
|
||||||
fn set_log_level_state_cxx(level: LogLevelCxx, enabled: bool);
|
fn set_log_level_state_cxx(level: LogLevelCxx, enabled: bool);
|
||||||
fn exit_on_error(b: bool);
|
fn exit_on_error(b: bool);
|
||||||
@ -53,7 +58,7 @@ pub mod ffi {
|
|||||||
#[cxx_name = "fd_path"]
|
#[cxx_name = "fd_path"]
|
||||||
fn fd_path_for_cxx(fd: i32, buf: &mut [u8]) -> isize;
|
fn fd_path_for_cxx(fd: i32, buf: &mut [u8]) -> isize;
|
||||||
#[cxx_name = "map_file"]
|
#[cxx_name = "map_file"]
|
||||||
fn map_file_for_cxx(path: &[u8], rw: bool) -> &'static mut [u8];
|
fn map_file_for_cxx(path: Utf8CStrRef, rw: bool) -> &'static mut [u8];
|
||||||
#[cxx_name = "map_fd"]
|
#[cxx_name = "map_fd"]
|
||||||
fn map_fd_for_cxx(fd: i32, sz: usize, rw: bool) -> &'static mut [u8];
|
fn map_fd_for_cxx(fd: i32, sz: usize, rw: bool) -> &'static mut [u8];
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ static int fmt_and_log_with_rs(LogLevel level, const char *fmt, va_list ap) {
|
|||||||
buf[0] = '\0';
|
buf[0] = '\0';
|
||||||
// Fortify logs when a fatal error occurs. Do not run through fortify again
|
// 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);
|
int len = std::min(__call_bypassing_fortify(vsnprintf)(buf, sz, fmt, ap), sz - 1);
|
||||||
log_with_rs(level, byte_view(buf, len + 1));
|
log_with_rs(level, rust::Utf8CStr(buf, len + 1));
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,10 +101,8 @@ fn log_with_writer<F: FnOnce(LogWriter)>(level: LogLevel, f: F) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn log_from_cxx(level: LogLevelCxx, msg: &[u8]) {
|
pub fn log_from_cxx(level: LogLevelCxx, msg: &Utf8CStr) {
|
||||||
if let Some(level) = LogLevel::from_i32(level.repr) {
|
if let Some(level) = LogLevel::from_i32(level.repr) {
|
||||||
// SAFETY: The null termination is handled on the C++ side
|
|
||||||
let msg = unsafe { Utf8CStr::from_bytes_unchecked(msg) };
|
|
||||||
log_with_writer(level, |write| write(level, msg));
|
log_with_writer(level, |write| write(level, msg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -274,3 +274,19 @@ int ssprintf(char *dest, size_t size, const char *fmt, ...) {
|
|||||||
size_t strscpy(char *dest, const char *src, size_t size) {
|
size_t strscpy(char *dest, const char *src, size_t size) {
|
||||||
return std::min(strlcpy(dest, src, size), size - 1);
|
return std::min(strlcpy(dest, src, size), size - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
rust::Utf8CStr::Utf8CStr(const char *s, size_t len) {
|
||||||
|
cxx$utf8str$new(this, s, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *rust::Utf8CStr::data() const {
|
||||||
|
return cxx$utf8str$ptr(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t rust::Utf8CStr::length() const {
|
||||||
|
return cxx$utf8str$len(this);
|
||||||
|
}
|
||||||
|
@ -331,3 +331,30 @@ constexpr auto operator+(T e) noexcept ->
|
|||||||
std::enable_if_t<std::is_enum<T>::value, std::underlying_type_t<T>> {
|
std::enable_if_t<std::is_enum<T>::value, std::underlying_type_t<T>> {
|
||||||
return static_cast<std::underlying_type_t<T>>(e);
|
return static_cast<std::underlying_type_t<T>>(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace rust {
|
||||||
|
|
||||||
|
struct Utf8CStr {
|
||||||
|
const char *data() const;
|
||||||
|
size_t length() const;
|
||||||
|
Utf8CStr(const char *s, size_t len);
|
||||||
|
|
||||||
|
Utf8CStr() : Utf8CStr("", 1) {};
|
||||||
|
Utf8CStr(const Utf8CStr &o) = default;
|
||||||
|
Utf8CStr(Utf8CStr &&o) = default;
|
||||||
|
Utf8CStr(const char *s) : Utf8CStr(s, strlen(s) + 1) {};
|
||||||
|
Utf8CStr(std::string_view s) : Utf8CStr(s.data(), s.length() + 1) {};
|
||||||
|
Utf8CStr(std::string s) : Utf8CStr(s.data(), s.length() + 1) {};
|
||||||
|
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() { return {data(), length()}; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wunused-private-field"
|
||||||
|
std::array<std::uintptr_t, 2> repr;
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace rust
|
||||||
|
@ -9,7 +9,7 @@ use base::{
|
|||||||
Utf8CStrBufArr, Utf8CStrBufRef, WalkResult,
|
Utf8CStrBufArr, Utf8CStrBufRef, WalkResult,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::ffi::{CxxMagiskD, RequestCode};
|
use crate::ffi::{get_magisk_tmp, CxxMagiskD, RequestCode};
|
||||||
use crate::logging::magisk_logging;
|
use crate::logging::magisk_logging;
|
||||||
use crate::{get_prop, MAIN_CONFIG};
|
use crate::{get_prop, MAIN_CONFIG};
|
||||||
|
|
||||||
@ -97,10 +97,6 @@ impl MagiskD {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_magisk_tmp() -> &'static Utf8CStr {
|
|
||||||
unsafe { Utf8CStr::from_ptr(super::ffi::get_magisk_tmp()).unwrap_unchecked() }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn daemon_entry() {
|
pub fn daemon_entry() {
|
||||||
let mut qemu = get_prop(cstr!("ro.kernel.qemu"), false);
|
let mut qemu = get_prop(cstr!("ro.kernel.qemu"), false);
|
||||||
if qemu.is_empty() {
|
if qemu.is_empty() {
|
||||||
@ -170,13 +166,9 @@ pub fn get_magiskd() -> &'static MagiskD {
|
|||||||
unsafe { MAGISKD.get().unwrap_unchecked() }
|
unsafe { MAGISKD.get().unwrap_unchecked() }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_apk_path(pkg: &[u8], data: &mut [u8]) -> usize {
|
pub fn find_apk_path(pkg: &Utf8CStr, data: &mut [u8]) -> usize {
|
||||||
use WalkResult::*;
|
use WalkResult::*;
|
||||||
fn inner(pkg: &[u8], buf: &mut dyn Utf8CStrBuf) -> io::Result<usize> {
|
fn inner(pkg: &Utf8CStr, buf: &mut dyn Utf8CStrBuf) -> io::Result<usize> {
|
||||||
let pkg = match Utf8CStr::from_bytes(pkg) {
|
|
||||||
Ok(pkg) => pkg,
|
|
||||||
Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
|
|
||||||
};
|
|
||||||
Directory::open(cstr!("/data/app"))?.pre_order_walk(|e| {
|
Directory::open(cstr!("/data/app"))?.pre_order_walk(|e| {
|
||||||
if !e.is_dir() {
|
if !e.is_dir() {
|
||||||
return Ok(Skip);
|
return Ok(Skip);
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <base.hpp>
|
||||||
|
|
||||||
namespace rust {
|
namespace rust {
|
||||||
struct MagiskD;
|
struct MagiskD;
|
||||||
}
|
}
|
||||||
@ -24,3 +26,4 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
const char *get_magisk_tmp();
|
const char *get_magisk_tmp();
|
||||||
|
static inline rust::Utf8CStr get_magisk_tmp_rs() { return get_magisk_tmp(); }
|
||||||
|
@ -58,9 +58,14 @@ pub mod ffi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "C++" {
|
unsafe extern "C++" {
|
||||||
|
#[namespace = "rust"]
|
||||||
|
#[cxx_name = "Utf8CStr"]
|
||||||
|
type Utf8CStrRef<'a> = base::ffi::Utf8CStrRef<'a>;
|
||||||
|
|
||||||
include!("include/daemon.hpp");
|
include!("include/daemon.hpp");
|
||||||
|
|
||||||
fn get_magisk_tmp() -> *const c_char;
|
#[cxx_name = "get_magisk_tmp_rs"]
|
||||||
|
fn get_magisk_tmp() -> Utf8CStrRef<'static>;
|
||||||
|
|
||||||
#[cxx_name = "MagiskD"]
|
#[cxx_name = "MagiskD"]
|
||||||
type CxxMagiskD;
|
type CxxMagiskD;
|
||||||
@ -76,12 +81,12 @@ pub mod ffi {
|
|||||||
fn zygisk_logging();
|
fn zygisk_logging();
|
||||||
fn zygisk_close_logd();
|
fn zygisk_close_logd();
|
||||||
fn zygisk_get_logd() -> i32;
|
fn zygisk_get_logd() -> i32;
|
||||||
fn find_apk_path(pkg: &[u8], data: &mut [u8]) -> usize;
|
fn find_apk_path(pkg: Utf8CStrRef, data: &mut [u8]) -> usize;
|
||||||
fn read_certificate(fd: i32, version: i32) -> Vec<u8>;
|
fn read_certificate(fd: i32, version: i32) -> Vec<u8>;
|
||||||
unsafe fn persist_get_prop(name: *const c_char, prop_cb: Pin<&mut PropCb>);
|
unsafe fn persist_get_prop(name: Utf8CStrRef, prop_cb: Pin<&mut PropCb>);
|
||||||
unsafe fn persist_get_props(prop_cb: Pin<&mut PropCb>);
|
unsafe fn persist_get_props(prop_cb: Pin<&mut PropCb>);
|
||||||
unsafe fn persist_delete_prop(name: *const c_char) -> bool;
|
unsafe fn persist_delete_prop(name: Utf8CStrRef) -> bool;
|
||||||
unsafe fn persist_set_prop(name: *const c_char, value: *const c_char) -> bool;
|
unsafe fn persist_set_prop(name: Utf8CStrRef, value: Utf8CStrRef) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[namespace = "rust"]
|
#[namespace = "rust"]
|
||||||
|
@ -19,7 +19,8 @@ use base::libc::{
|
|||||||
};
|
};
|
||||||
use base::*;
|
use base::*;
|
||||||
|
|
||||||
use crate::daemon::{get_magisk_tmp, MagiskD, MAGISKD};
|
use crate::daemon::{MagiskD, MAGISKD};
|
||||||
|
use crate::ffi::get_magisk_tmp;
|
||||||
use crate::logging::LogFile::{Actual, Buffer};
|
use crate::logging::LogFile::{Actual, Buffer};
|
||||||
use crate::{LOGFILE, LOG_PIPE};
|
use crate::{LOGFILE, LOG_PIPE};
|
||||||
|
|
||||||
|
@ -176,7 +176,7 @@ int get_manager(int user_id, string *pkg, bool install) {
|
|||||||
int app_id = to_app_id(st.st_uid);
|
int app_id = to_app_id(st.st_uid);
|
||||||
|
|
||||||
byte_array<PATH_MAX> apk;
|
byte_array<PATH_MAX> apk;
|
||||||
find_apk_path(byte_view(str[SU_MANAGER]), apk);
|
find_apk_path(str[SU_MANAGER], apk);
|
||||||
int fd = xopen((const char *) apk.buf(), O_RDONLY | O_CLOEXEC);
|
int fd = xopen((const char *) apk.buf(), O_RDONLY | O_CLOEXEC);
|
||||||
auto cert = read_certificate(fd, -1);
|
auto cert = read_certificate(fd, -1);
|
||||||
close(fd);
|
close(fd);
|
||||||
@ -230,7 +230,7 @@ int get_manager(int user_id, string *pkg, bool install) {
|
|||||||
if (stat(app_path, &st) == 0) {
|
if (stat(app_path, &st) == 0) {
|
||||||
#if ENFORCE_SIGNATURE
|
#if ENFORCE_SIGNATURE
|
||||||
byte_array<PATH_MAX> apk;
|
byte_array<PATH_MAX> apk;
|
||||||
find_apk_path(byte_view(JAVA_PACKAGE_NAME), apk);
|
find_apk_path(JAVA_PACKAGE_NAME, apk);
|
||||||
int fd = xopen((const char *) apk.buf(), O_RDONLY | O_CLOEXEC);
|
int fd = xopen((const char *) apk.buf(), O_RDONLY | O_CLOEXEC);
|
||||||
auto cert = read_certificate(fd, MAGISK_VER_CODE);
|
auto cert = read_certificate(fd, MAGISK_VER_CODE);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
use core::ffi::c_char;
|
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::{
|
use std::{
|
||||||
fs::File,
|
fs::File,
|
||||||
@ -142,9 +141,8 @@ fn proto_write_props(props: &PersistentProperties) -> LoggedResult<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn persist_get_prop(name: *const c_char, prop_cb: Pin<&mut PropCb>) {
|
pub unsafe fn persist_get_prop(name: &Utf8CStr, prop_cb: Pin<&mut PropCb>) {
|
||||||
fn inner(name: *const c_char, mut prop_cb: Pin<&mut PropCb>) -> LoggedResult<()> {
|
fn inner(name: &Utf8CStr, mut prop_cb: Pin<&mut PropCb>) -> LoggedResult<()> {
|
||||||
let name = unsafe { Utf8CStr::from_ptr(name)? };
|
|
||||||
if check_proto() {
|
if check_proto() {
|
||||||
let mut props = proto_read_props()?;
|
let mut props = proto_read_props()?;
|
||||||
let prop = props.find(name)?;
|
let prop = props.find(name)?;
|
||||||
@ -197,9 +195,8 @@ pub unsafe fn persist_get_props(prop_cb: Pin<&mut PropCb>) {
|
|||||||
inner(prop_cb).ok();
|
inner(prop_cb).ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn persist_delete_prop(name: *const c_char) -> bool {
|
pub unsafe fn persist_delete_prop(name: &Utf8CStr) -> bool {
|
||||||
fn inner(name: *const c_char) -> LoggedResult<()> {
|
fn inner(name: &Utf8CStr) -> LoggedResult<()> {
|
||||||
let name = unsafe { Utf8CStr::from_ptr(name)? };
|
|
||||||
if check_proto() {
|
if check_proto() {
|
||||||
let mut props = proto_read_props()?;
|
let mut props = proto_read_props()?;
|
||||||
let idx = props.find_index(name).no_log()?;
|
let idx = props.find_index(name).no_log()?;
|
||||||
@ -212,10 +209,8 @@ pub unsafe fn persist_delete_prop(name: *const c_char) -> bool {
|
|||||||
inner(name).is_ok()
|
inner(name).is_ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn persist_set_prop(name: *const c_char, value: *const c_char) -> bool {
|
pub unsafe fn persist_set_prop(name: &Utf8CStr, value: &Utf8CStr) -> bool {
|
||||||
unsafe fn inner(name: *const c_char, value: *const c_char) -> LoggedResult<()> {
|
unsafe fn inner(name: &Utf8CStr, value: &Utf8CStr) -> LoggedResult<()> {
|
||||||
let name = Utf8CStr::from_ptr(name)?;
|
|
||||||
let value = Utf8CStr::from_ptr(value)?;
|
|
||||||
if check_proto() {
|
if check_proto() {
|
||||||
let mut props = proto_read_props()?;
|
let mut props = proto_read_props()?;
|
||||||
match props.find_index(name) {
|
match props.find_index(name) {
|
||||||
|
@ -105,7 +105,7 @@ bool sepolicy::exists(const char *type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void sepolicy::load_rule_file(const char *file) {
|
void sepolicy::load_rule_file(const char *file) {
|
||||||
rust::load_rule_file(*this, byte_view(file, false));
|
rust::load_rule_file(*this, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sepolicy::load_rules(const std::string &rules) {
|
void sepolicy::load_rules(const std::string &rules) {
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include <base.hpp>
|
||||||
|
|
||||||
// sepolicy paths
|
// sepolicy paths
|
||||||
#define PLAT_POLICY_DIR "/system/etc/selinux/"
|
#define PLAT_POLICY_DIR "/system/etc/selinux/"
|
||||||
#define VEND_POLICY_DIR "/vendor/etc/selinux/"
|
#define VEND_POLICY_DIR "/vendor/etc/selinux/"
|
||||||
@ -38,8 +40,7 @@ struct sepolicy {
|
|||||||
|
|
||||||
// External APIs
|
// External APIs
|
||||||
bool to_file(c_str file);
|
bool to_file(c_str file);
|
||||||
void parse_statement(c_str stmt, int len);
|
void parse_statement(rust::Str stmt);
|
||||||
void parse_statement(c_str stmt) { parse_statement(stmt, strlen(stmt)); }
|
|
||||||
void load_rules(const std::string &rules);
|
void load_rules(const std::string &rules);
|
||||||
void load_rule_file(c_str file);
|
void load_rule_file(c_str file);
|
||||||
void print_rules();
|
void print_rules();
|
||||||
|
@ -1,33 +1,37 @@
|
|||||||
use io::Cursor;
|
use io::Cursor;
|
||||||
use std::fs::File;
|
use std::io;
|
||||||
use std::io::{BufRead, BufReader};
|
use std::io::{BufRead, BufReader};
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::{io, str};
|
|
||||||
|
|
||||||
pub use base;
|
pub use base;
|
||||||
use base::*;
|
use base::libc::{O_CLOEXEC, O_RDONLY};
|
||||||
|
use base::{BufReadExt, FsPath, LoggedResult, Utf8CStr};
|
||||||
|
|
||||||
use crate::ffi::sepolicy;
|
use crate::ffi::sepolicy;
|
||||||
|
|
||||||
#[cxx::bridge]
|
#[cxx::bridge]
|
||||||
mod ffi {
|
mod ffi {
|
||||||
unsafe extern "C++" {
|
unsafe extern "C++" {
|
||||||
|
#[namespace = "rust"]
|
||||||
|
#[cxx_name = "Utf8CStr"]
|
||||||
|
type Utf8CStrRef<'a> = base::ffi::Utf8CStrRef<'a>;
|
||||||
|
|
||||||
include!("include/sepolicy.hpp");
|
include!("include/sepolicy.hpp");
|
||||||
|
|
||||||
type sepolicy;
|
type sepolicy;
|
||||||
unsafe fn parse_statement(self: Pin<&mut sepolicy>, stmt: *const c_char, len: i32);
|
fn parse_statement(self: Pin<&mut sepolicy>, stmt: &str);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[namespace = "rust"]
|
#[namespace = "rust"]
|
||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
fn load_rules(sepol: Pin<&mut sepolicy>, rules: &[u8]);
|
fn load_rules(sepol: Pin<&mut sepolicy>, rules: &[u8]);
|
||||||
fn load_rule_file(sepol: Pin<&mut sepolicy>, filename: &[u8]);
|
fn load_rule_file(sepol: Pin<&mut sepolicy>, filename: Utf8CStrRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait SepolicyExt {
|
trait SepolicyExt {
|
||||||
fn load_rules(self: Pin<&mut Self>, rules: &[u8]);
|
fn load_rules(self: Pin<&mut Self>, rules: &[u8]);
|
||||||
fn load_rule_file(self: Pin<&mut Self>, filename: &[u8]);
|
fn load_rule_file(self: Pin<&mut Self>, filename: &Utf8CStr);
|
||||||
fn load_rules_from_reader<T: BufRead>(self: Pin<&mut Self>, reader: &mut T);
|
fn load_rules_from_reader<T: BufRead>(self: Pin<&mut Self>, reader: &mut T);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,10 +41,10 @@ impl SepolicyExt for sepolicy {
|
|||||||
self.load_rules_from_reader(&mut cursor);
|
self.load_rules_from_reader(&mut cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_rule_file(self: Pin<&mut sepolicy>, filename: &[u8]) {
|
fn load_rule_file(self: Pin<&mut sepolicy>, filename: &Utf8CStr) {
|
||||||
fn inner(sepol: Pin<&mut sepolicy>, filename: &[u8]) -> LoggedResult<()> {
|
fn inner(sepol: Pin<&mut sepolicy>, filename: &Utf8CStr) -> LoggedResult<()> {
|
||||||
let filename = str::from_utf8(filename)?;
|
let file = FsPath::from(filename).open(O_RDONLY | O_CLOEXEC)?;
|
||||||
let mut reader = BufReader::new(File::open(filename)?);
|
let mut reader = BufReader::new(file);
|
||||||
sepol.load_rules_from_reader(&mut reader);
|
sepol.load_rules_from_reader(&mut reader);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -49,17 +53,14 @@ impl SepolicyExt for sepolicy {
|
|||||||
|
|
||||||
fn load_rules_from_reader<T: BufRead>(mut self: Pin<&mut sepolicy>, reader: &mut T) {
|
fn load_rules_from_reader<T: BufRead>(mut self: Pin<&mut sepolicy>, reader: &mut T) {
|
||||||
reader.foreach_lines(|line| {
|
reader.foreach_lines(|line| {
|
||||||
let bytes = line.trim().as_bytes();
|
let line = line.trim();
|
||||||
unsafe {
|
self.as_mut().parse_statement(line);
|
||||||
self.as_mut()
|
|
||||||
.parse_statement(bytes.as_ptr().cast(), bytes.len() as i32);
|
|
||||||
}
|
|
||||||
true
|
true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_rule_file(sepol: Pin<&mut sepolicy>, filename: &[u8]) {
|
pub fn load_rule_file(sepol: Pin<&mut sepolicy>, filename: &Utf8CStr) {
|
||||||
sepol.load_rule_file(filename);
|
sepol.load_rule_file(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,19 +417,19 @@ static bool parse_pattern_9(const Func &fn, const char *action, char *stmt) {
|
|||||||
else if (strcmp(name, action) == 0) { \
|
else if (strcmp(name, action) == 0) { \
|
||||||
auto __fn = [&](auto && ...args){ return (fn)(args...); }; \
|
auto __fn = [&](auto && ...args){ return (fn)(args...); }; \
|
||||||
if (!parse_pattern_##type(__fn, name, remain)) \
|
if (!parse_pattern_##type(__fn, name, remain)) \
|
||||||
LOGW("Syntax error in '%.*s'\n\n%s\n", len, stmt, type_msg_##type); \
|
LOGW("Syntax error in '%.*s'\n\n%s\n", (int) stmt.length(), stmt.data(), type_msg_##type); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define add_action(act, type) add_action_func(#act, type, act)
|
#define add_action(act, type) add_action_func(#act, type, act)
|
||||||
|
|
||||||
void sepolicy::parse_statement(const char *stmt, int len) {
|
void sepolicy::parse_statement(rust::Str stmt) {
|
||||||
// strtok modify strings, create a copy
|
// strtok modify strings, create a copy
|
||||||
string cpy(stmt, len);
|
string cpy(stmt.data(), stmt.length());
|
||||||
|
|
||||||
char *remain;
|
char *remain;
|
||||||
char *action = strtok_r(cpy.data(), " ", &remain);
|
char *action = strtok_r(cpy.data(), " ", &remain);
|
||||||
if (remain == nullptr) {
|
if (remain == nullptr) {
|
||||||
LOGW("Syntax error in '%.*s'\n\n", len, stmt);
|
LOGW("Syntax error in '%.*s'\n\n", (int) stmt.length(), stmt.data());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user