ksud: make it compilable for non-android
This commit is contained in:
4
userspace/ksud/Cargo.lock
generated
4
userspace/ksud/Cargo.lock
generated
@@ -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",
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -9,6 +9,7 @@ mod restorecon;
|
||||
mod utils;
|
||||
mod sepolicy;
|
||||
mod assets;
|
||||
mod mount;
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
cli::run()
|
||||
|
||||
@@ -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)?;
|
||||
|
||||
58
userspace/ksud/src/mount.rs
Normal file
58
userspace/ksud/src/mount.rs
Normal 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!()
|
||||
}
|
||||
@@ -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!(
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user