ksud: make it compilable for non-android

This commit is contained in:
tiann
2023-02-01 19:04:33 +08:00
parent 1cd18a643d
commit 619dd1ace1
10 changed files with 97 additions and 51 deletions

View File

@@ -1032,9 +1032,9 @@ dependencies = [
[[package]]
name = "sys-mount"
version = "2.0.1"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "793d38aa916d55e979587ea7cf551106f5f091e548a91e89ee4f0698bc9cf289"
checksum = "d8b080a2fff4d267282506b4d5f2efe0dfa732fb2a5715f30662eed1c4f13390"
dependencies = [
"bitflags",
"libc",

View File

@@ -22,14 +22,16 @@ encoding = "0.2.33"
retry = "2.0.0"
humansize = "2.0.0"
libc = "0.2"
sys-mount = "2.0.1"
android-properties = { version = "0.2.2", features = ["bionic-deprecated"] }
extattr = "1.0.0"
jwalk = "0.8.1"
is_executable = "1.0.1"
nom = "7"
derive-new = "0.5"
[target.'cfg(target_os = "android")'.dependencies]
sys-mount = "2.0.1"
android-properties = { version = "0.2.2", features = ["bionic-deprecated"] }
[profile.release]
strip = true
opt-level = "z"

View File

@@ -23,7 +23,7 @@ pub fn get_apk_signature(apk: &str) -> Result<(u32, u32)> {
if u32::from_le_bytes(size4) ^ 0xcafebabeu32 == 0xccfbf1eeu32 {
if i > 0 {
println!("warning: comment length is {}", i);
println!("warning: comment length is {i}");
}
break;
}

View File

@@ -1,22 +1,21 @@
use std::{collections::HashMap, path::Path};
use crate::{
assets, defs,
utils::{ensure_clean_dir, ensure_dir_exists, mount_image},
assets, defs, mount,
utils::{ensure_clean_dir, ensure_dir_exists},
};
use anyhow::{bail, Context, Result};
use sys_mount::{FilesystemType, Mount, MountFlags};
fn mount_partition(partition: &str, lowerdir: &mut Vec<String>) {
fn mount_partition(partition: &str, lowerdir: &mut Vec<String>) -> Result<()> {
if lowerdir.is_empty() {
println!("partition: {partition} lowerdir is empty");
return;
return Ok(());
}
// if /partition is a symlink and linked to /system/partition, then we don't need to overlay it separately
if Path::new(&format!("/{}", partition)).read_link().is_ok() {
println!("partition: {} is a symlink", partition);
return;
return Ok(());
}
// add /partition as the lowerest dir
let lowest_dir = format!("/{partition}");
@@ -25,14 +24,7 @@ fn mount_partition(partition: &str, lowerdir: &mut Vec<String>) {
let lowerdir = lowerdir.join(":");
println!("partition: {partition} lowerdir: {lowerdir}");
if let Err(err) = Mount::builder()
.fstype(FilesystemType::from("overlay"))
.flags(MountFlags::RDONLY)
.data(&format!("lowerdir={lowerdir}"))
.mount("overlay", lowest_dir)
{
println!("mount partition: {partition} overlay failed: {err}");
}
mount::mount_overlay(&lowerdir, &lowest_dir)
}
pub fn do_systemless_mount(module_dir: &str) -> Result<()> {
@@ -82,11 +74,11 @@ pub fn do_systemless_mount(module_dir: &str) -> Result<()> {
}
// mount /system first
mount_partition("system", &mut system_lowerdir);
let _ = mount_partition("system", &mut system_lowerdir);
// mount other partitions
for (k, mut v) in partition_lowerdir {
mount_partition(&k, &mut v);
let _ = mount_partition(&k, &mut v);
}
Ok(())
@@ -127,7 +119,7 @@ pub fn on_post_data_fs() -> Result<()> {
}
println!("mount {} to {}", target_update_img, module_dir);
mount_image(target_update_img, module_dir)?;
mount::mount_ext4(target_update_img, module_dir)?;
// load sepolicy.rule
if crate::module::load_sepolicy_rule().is_err() {

View File

@@ -9,6 +9,7 @@ mod restorecon;
mod utils;
mod sepolicy;
mod assets;
mod mount;
fn main() -> anyhow::Result<()> {
cli::run()

View File

@@ -4,6 +4,7 @@ use crate::{
sepolicy,
utils::*,
assets,
mount,
};
use const_format::concatcp;
@@ -430,7 +431,7 @@ pub fn install_module(zip: String) -> Result<()> {
// mount the modules_update.img to mountpoint
println!("- Mounting image");
mount_image(tmp_module_img, module_update_tmp_dir)?;
mount::mount_ext4(tmp_module_img, module_update_tmp_dir)?;
setsyscon(module_update_tmp_dir)?;
@@ -457,7 +458,7 @@ pub fn install_module(zip: String) -> Result<()> {
};
// umount the modules_update.img
let _ = umount_dir(module_update_tmp_dir);
let _ = mount::umount_dir(module_update_tmp_dir);
// remove modules_update dir, ignore the error
let _ = remove_dir_all(module_update_tmp_dir);
@@ -506,13 +507,13 @@ where
ensure_clean_dir(update_dir)?;
// mount the modules_update img
mount_image(defs::MODULE_UPDATE_TMP_IMG, update_dir)?;
mount::mount_ext4(defs::MODULE_UPDATE_TMP_IMG, update_dir)?;
// call the operation func
let result = func(id, update_dir);
// umount modules_update.img
let _ = umount_dir(update_dir);
let _ = mount::umount_dir(update_dir);
let _ = remove_dir_all(update_dir);
std::fs::rename(modules_update_tmp_img, defs::MODULE_UPDATE_IMG)?;

View File

@@ -0,0 +1,58 @@
use anyhow::Result;
#[cfg(target_os = "android")]
use anyhow::{ensure, Context, Ok};
#[cfg(target_os = "android")]
use retry::delay::NoDelay;
#[cfg(target_os = "android")]
use sys_mount::{unmount, FilesystemType, Mount, MountFlags, UnmountFlags};
#[cfg(target_os = "android")]
fn do_mount_image(src: &str, target: &str) -> Result<()> {
Mount::builder()
.fstype(FilesystemType::from("ext4"))
.mount(src, target)
.with_context(|| format!("Failed to do mount: {src} -> {target}"))?;
Ok(())
}
#[cfg(target_os = "android")]
pub fn mount_ext4(src: &str, target: &str) -> Result<()> {
// umount target first.
let _ = umount_dir(target);
let result = retry::retry(NoDelay.take(3), || do_mount_image(src, target));
ensure!(result.is_ok(), "Failed to mount {} -> {}", src, target);
Ok(())
}
#[cfg(target_os = "android")]
pub fn umount_dir(src: &str) -> Result<()> {
unmount(src, UnmountFlags::empty()).with_context(|| format!("Failed to umount {src}"))?;
Ok(())
}
#[cfg(target_os = "android")]
pub fn mount_overlay(lowerdir: &str, mnt: &str) -> Result<()> {
Mount::builder()
.fstype(FilesystemType::from("overlay"))
.flags(MountFlags::RDONLY)
.data(&format!("lowerdir={lowerdir}"))
.mount("overlay", mnt)
.map(|_| ())
.map_err(|e| anyhow::anyhow!("mount partition: {mnt} overlay failed: {e}"))
}
#[cfg(not(target_os = "android"))]
pub fn mount_ext4(src: &str, target: &str) -> Result<()> {
unimplemented!()
}
#[cfg(not(target_os = "android"))]
pub fn umount_dir(src: &str) -> Result<()> {
unimplemented!()
}
#[cfg(not(target_os = "android"))]
pub fn mount_overlay(lowerdir: &str, mnt: &str) -> Result<()> {
unimplemented!()
}

View File

@@ -1,4 +1,5 @@
use anyhow::{Context, Ok, Result};
#[cfg(target_os = "android")]
use extattr::{setxattr, Flags as XattrFlags};
use jwalk::{Parallelism::Serial, WalkDir};
@@ -6,6 +7,7 @@ const SYSTEM_CON: &str = "u:object_r:system_file:s0";
const _ADB_CON: &str = "u:object_r:adb_data_file:s0";
pub fn setcon(path: &str, con: &str) -> Result<()> {
#[cfg(target_os = "android")]
setxattr(path, "security.selinux", con, XattrFlags::empty())
.with_context(|| format!("Failed to change SELinux context for {path}"))?;
Ok(())
@@ -18,6 +20,7 @@ pub fn setsyscon(path: &str) -> Result<()> {
pub fn restore_syscon(dir: &str) -> Result<()> {
for dir_entry in WalkDir::new(dir).parallelism(Serial) {
if let Some(path) = dir_entry.ok().map(|dir_entry| dir_entry.path()) {
#[cfg(target_os = "android")]
setxattr(&path, "security.selinux", SYSTEM_CON, XattrFlags::empty()).with_context(
|| {
format!(

View File

@@ -11,7 +11,7 @@ use nom::{
sequence::Tuple,
IResult, Parser,
};
use std::{vec, path::Path};
use std::{path::Path, vec};
type SeObject<'a> = Vec<&'a str>;
@@ -692,6 +692,7 @@ impl From<AtomicStatement> for FfiPolicy {
}
}
#[cfg(target_os = "android")]
fn apply_one_rule<'a>(statement: &'a PolicyStatement<'a>) -> Result<()> {
let policies: Vec<AtomicStatement> = statement.try_into()?;
@@ -716,6 +717,11 @@ fn apply_one_rule<'a>(statement: &'a PolicyStatement<'a>) -> Result<()> {
Ok(())
}
#[cfg(not(target_os = "android"))]
fn apply_one_rule<'a>(statement: &'a PolicyStatement<'a>) -> Result<()> {
unimplemented!()
}
pub fn live_patch(policy: &str) -> Result<()> {
let result = parse_sepolicy(policy.trim())?;
for statement in result {

View File

@@ -1,33 +1,10 @@
use anyhow::{bail, ensure, Context, Error, Ok, Result};
use retry::delay::NoDelay;
use anyhow::{bail, Context, Error, Ok, Result};
use std::{
fs::{create_dir_all, set_permissions, write, File, Permissions},
io::ErrorKind::AlreadyExists,
os::unix::prelude::PermissionsExt,
path::Path,
};
use sys_mount::{unmount, FilesystemType, Mount, UnmountFlags};
fn do_mount_image(src: &str, target: &str) -> Result<()> {
Mount::builder()
.fstype(FilesystemType::from("ext4"))
.mount(src, target)
.with_context(|| format!("Failed to do mount: {src} -> {target}"))?;
Ok(())
}
pub fn mount_image(src: &str, target: &str) -> Result<()> {
// umount target first.
let _ = umount_dir(target);
let result = retry::retry(NoDelay.take(3), || do_mount_image(src, target));
ensure!(result.is_ok(), "Failed to mount {} -> {}", src, target);
Ok(())
}
pub fn umount_dir(src: &str) -> Result<()> {
unmount(src, UnmountFlags::empty()).with_context(|| format!("Failed to umount {src}"))?;
Ok(())
}
pub fn ensure_clean_dir(dir: &str) -> Result<()> {
let path = Path::new(dir);
@@ -83,10 +60,16 @@ pub fn ensure_binary<T: AsRef<Path>>(path: T, contents: &[u8]) -> Result<()> {
Ok(())
}
#[cfg(target_os = "android")]
pub fn getprop(prop: &str) -> Option<String> {
android_properties::getprop(prop).value()
}
#[cfg(not(target_os = "android"))]
pub fn getprop(prop: &str) -> Option<String> {
unimplemented!()
}
pub fn is_safe_mode() -> bool {
getprop("persist.sys.safemode")
.filter(|prop| prop == "1")