kernel, ksud: collect binaries into /data/adb/ksu (#161)

This commit is contained in:
skbeh
2023-02-01 05:58:58 -04:00
committed by GitHub
parent b7ff6b1a51
commit 46913671a8
13 changed files with 121 additions and 65 deletions

View File

@@ -21,7 +21,7 @@ struct perm_data {
static struct list_head allow_list; static struct list_head allow_list;
#define KERNEL_SU_ALLOWLIST "/data/adb/.ksu_allowlist" #define KERNEL_SU_ALLOWLIST "/data/adb/ksu/.allowlist"
static struct work_struct ksu_save_work; static struct work_struct ksu_save_work;
static struct work_struct ksu_load_work; static struct work_struct ksu_load_work;
@@ -159,7 +159,7 @@ void do_load_allow_list(struct work_struct *work)
u32 magic; u32 magic;
u32 version; u32 version;
fp = filp_open("/data/adb/", O_RDONLY, 0); fp = filp_open("/data/adb", O_RDONLY, 0);
if (IS_ERR(fp)) { if (IS_ERR(fp)) {
int errno = PTR_ERR(fp); int errno = PTR_ERR(fp);
pr_err("load_allow_list open '/data/adb': %d\n", PTR_ERR(fp)); pr_err("load_allow_list open '/data/adb': %d\n", PTR_ERR(fp));

View File

@@ -13,6 +13,7 @@
#include "allowlist.h" #include "allowlist.h"
#include "arch.h" #include "arch.h"
#include "klog.h" // IWYU pragma: keep #include "klog.h" // IWYU pragma: keep
#include "ksud.h"
#include "selinux/selinux.h" #include "selinux/selinux.h"
static const char KERNEL_SU_RC[] = static const char KERNEL_SU_RC[] =
@@ -20,19 +21,19 @@ static const char KERNEL_SU_RC[] =
"on post-fs-data\n" "on post-fs-data\n"
// We should wait for the post-fs-data finish // We should wait for the post-fs-data finish
" exec u:r:su:s0 root -- /data/adb/ksud post-fs-data\n" " exec u:r:su:s0 root -- "KSUD_PATH" post-fs-data\n"
"\n" "\n"
"on nonencrypted\n" "on nonencrypted\n"
" exec u:r:su:s0 root -- /data/adb/ksud services\n" " exec u:r:su:s0 root -- "KSUD_PATH" services\n"
"\n" "\n"
"on property:vold.decrypt=trigger_restart_framework\n" "on property:vold.decrypt=trigger_restart_framework\n"
" exec u:r:su:s0 root -- /data/adb/ksud services\n" " exec u:r:su:s0 root -- "KSUD_PATH" services\n"
"\n" "\n"
"on property:sys.boot_completed=1\n" "on property:sys.boot_completed=1\n"
" exec u:r:su:s0 root -- /data/adb/ksud boot-completed\n" " exec u:r:su:s0 root -- "KSUD_PATH" boot-completed\n"
"\n" "\n"
"\n"; "\n";

View File

@@ -1,6 +1,8 @@
#ifndef __KSU_H_KSUD #ifndef __KSU_H_KSUD
#define __KSU_H_KSUD #define __KSU_H_KSUD
#define KSUD_PATH "/data/adb/ksud"
void on_post_fs_data(void); void on_post_fs_data(void);
#endif #endif

View File

@@ -59,7 +59,7 @@ void apply_kernelsu_rules()
ksu_allowxperm(db, KERNEL_SU_DOMAIN, ALL, "chr_file", ALL); ksu_allowxperm(db, KERNEL_SU_DOMAIN, ALL, "chr_file", ALL);
} }
// we need to save allowlist in /data/adb // we need to save allowlist in /data/adb/ksu
ksu_allow(db, "kernel", "adb_data_file", "dir", ALL); ksu_allow(db, "kernel", "adb_data_file", "dir", ALL);
ksu_allow(db, "kernel", "adb_data_file", "file", ALL); ksu_allow(db, "kernel", "adb_data_file", "file", ALL);
// we may need to do mount on shell // we may need to do mount on shell

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,7 +1,11 @@
use const_format::concatcp; use const_format::concatcp;
pub const DAEMON_PATH: &str = "/data/adb/ksud"; pub const ADB_DIR: &str = "/data/adb/";
pub const WORKING_DIR: &str = "/data/adb/ksu/";
pub const DAEMON_PATH: &str = concatcp!(ADB_DIR, "ksud");
pub const WORKING_DIR: &str = concatcp!(ADB_DIR, "ksu/");
pub const BINARY_DIR: &str = concatcp!(WORKING_DIR, "bin/");
pub const MODULE_DIR: &str = concatcp!(WORKING_DIR, "modules/"); pub const MODULE_DIR: &str = concatcp!(WORKING_DIR, "modules/");
pub const MODULE_IMG: &str = concatcp!(WORKING_DIR, "modules.img"); pub const MODULE_IMG: &str = concatcp!(WORKING_DIR, "modules.img");

View File

@@ -2,7 +2,7 @@ use std::{collections::HashMap, path::Path};
use crate::{ use crate::{
defs, defs,
utils::{ensure_clean_dir, mount_image}, utils::{ensure_clean_dir, ensure_dir_exists, mount_image},
}; };
use anyhow::{bail, Result}; use anyhow::{bail, Result};
use sys_mount::{FilesystemType, Mount, MountFlags}; use sys_mount::{FilesystemType, Mount, MountFlags};
@@ -176,9 +176,8 @@ pub fn daemon() -> Result<()> {
} }
pub fn install() -> Result<()> { pub fn install() -> Result<()> {
let src = "/proc/self/exe"; ensure_dir_exists(defs::ADB_DIR)?;
let dst = defs::DAEMON_PATH; std::fs::copy("/proc/self/exe", defs::DAEMON_PATH)
.map(|_| ())
std::fs::copy(src, dst)?; .map_err(anyhow::Error::from)
Ok(())
} }

View File

@@ -1,14 +1,19 @@
use crate::{defs, restorecon, sepolicy}; use crate::{
use crate::{restorecon::setsyscon, utils::*}; defs,
restorecon::{restore_syscon, setsyscon},
sepolicy,
utils::*,
};
use const_format::concatcp; use const_format::concatcp;
use java_properties::PropertiesIter; use java_properties::PropertiesIter;
use log::{info, warn}; use log::{info, warn};
use std::{ use std::{
collections::HashMap, collections::HashMap,
fs::{create_dir_all, remove_dir_all, File, OpenOptions}, env::var as env_var,
fs::{remove_dir_all, File, OpenOptions},
io::{Cursor, Read, Write}, io::{Cursor, Read, Write},
os::unix::{prelude::PermissionsExt, process::CommandExt}, os::unix::process::CommandExt,
path::{Path, PathBuf}, path::{Path, PathBuf},
process::{Command, Stdio}, process::{Command, Stdio},
str::FromStr, str::FromStr,
@@ -27,6 +32,10 @@ fn exec_install_script(module_file: &str) -> Result<()> {
let result = Command::new("sh") let result = Command::new("sh")
.args(["-c", INSTALL_MODULE_SCRIPT]) .args(["-c", INSTALL_MODULE_SCRIPT])
.env(
"PATH",
format!("{}:{}", env_var("PATH").unwrap(), defs::MODULE_DIR),
)
.env("OUTFD", "1") .env("OUTFD", "1")
.env("ZIPFILE", realpath) .env("ZIPFILE", realpath)
.stderr(Stdio::null()) .stderr(Stdio::null())
@@ -48,30 +57,19 @@ fn ensure_boot_completed() -> Result<()> {
} }
fn mark_update() -> Result<()> { fn mark_update() -> Result<()> {
let update_file = Path::new(defs::WORKING_DIR).join(defs::UPDATE_FILE_NAME); ensure_file_exists(concatcp!(defs::WORKING_DIR, defs::UPDATE_FILE_NAME))
if update_file.exists() {
return Ok(());
}
std::fs::File::create(update_file)?;
Ok(())
} }
fn mark_module_state(module: &str, flag_file: &str, create_or_delete: bool) -> Result<()> { fn mark_module_state(module: &str, flag_file: &str, create_or_delete: bool) -> Result<()> {
let module_state_file = Path::new(defs::MODULE_DIR).join(module).join(flag_file); let module_state_file = Path::new(defs::MODULE_DIR).join(module).join(flag_file);
if create_or_delete { if create_or_delete {
if module_state_file.exists() { ensure_file_exists(module_state_file)
return Ok(());
}
std::fs::File::create(module_state_file)?;
} else { } else {
if !module_state_file.exists() { if module_state_file.exists() {
return Ok(()); std::fs::remove_file(module_state_file)?;
} }
std::fs::remove_file(module_state_file)?; Ok(())
} }
Ok(())
} }
fn get_minimal_image_size(img: &str) -> Result<u64> { fn get_minimal_image_size(img: &str) -> Result<u64> {
@@ -84,8 +82,8 @@ fn get_minimal_image_size(img: &str) -> Result<u64> {
println!("- {}", output.trim()); println!("- {}", output.trim());
let regex = regex::Regex::new(r"filesystem: (\d+)")?; let regex = regex::Regex::new(r"filesystem: (\d+)")?;
let result = regex let result = regex
.captures(output.as_ref()) .captures(&output)
.ok_or_else(|| anyhow::anyhow!("regex not match"))?; .ok_or(anyhow::anyhow!("regex not match"))?;
let result = &result[1]; let result = &result[1];
let result = u64::from_str(result)?; let result = u64::from_str(result)?;
Ok(result) Ok(result)
@@ -161,7 +159,7 @@ fn switch_cgroups() {
} }
fn is_executable(path: &Path) -> bool { fn is_executable(path: &Path) -> bool {
let mut buffer: [u8; 2] = [0; 2]; let mut buffer = [0u8; 2];
is_executable::is_executable(path) is_executable::is_executable(path)
&& File::open(path).unwrap().read_exact(&mut buffer).is_ok() && File::open(path).unwrap().read_exact(&mut buffer).is_ok()
&& ( && (
@@ -227,6 +225,10 @@ pub fn exec_post_fs_data() -> Result<()> {
command = command command = command
.process_group(0) .process_group(0)
.current_dir(path) .current_dir(path)
.env(
"PATH",
format!("{}:{}", env_var("PATH").unwrap(), defs::MODULE_DIR),
)
.env("KSU", "true"); .env("KSU", "true");
unsafe { unsafe {
command = command.pre_exec(|| { command = command.pre_exec(|| {
@@ -273,6 +275,10 @@ pub fn exec_services() -> Result<()> {
command = command command = command
.process_group(0) .process_group(0)
.current_dir(path) .current_dir(path)
.env(
"PATH",
format!("{}:{}", env_var("PATH").unwrap(), defs::MODULE_DIR),
)
.env("KSU", "true"); .env("KSU", "true");
unsafe { unsafe {
command = command.pre_exec(|| { command = command.pre_exec(|| {
@@ -289,20 +295,21 @@ pub fn exec_services() -> Result<()> {
Ok(()) Ok(())
} }
const RESETPROP: &[u8] = include_bytes!("./resetprop"); const RESETPROP_PATH: &str = concatcp!(defs::BINARY_DIR, "resetprop");
const RESETPROP_PATH: &str = concatcp!(defs::WORKING_DIR, "/resetprop"); #[cfg(target_arch = "aarch64")]
const RESETPROP: &[u8] = include_bytes!("../bin/aarch64/resetprop");
#[cfg(target_arch = "x86_64")]
const RESETPROP: &[u8] = include_bytes!("../bin/x86_64/resetprop");
fn ensure_resetprop() -> Result<()> { const BUSYBOX_PATH: &str = concatcp!(defs::BINARY_DIR, "busybox");
if Path::new(RESETPROP_PATH).exists() { #[cfg(target_arch = "aarch64")]
return Ok(()); const BUSYBOX: &[u8] = include_bytes!("../bin/aarch64/busybox");
} #[cfg(target_arch = "x86_64")]
std::fs::write(RESETPROP_PATH, RESETPROP)?; const BUSYBOX: &[u8] = include_bytes!("../bin/x86_64/busybox");
std::fs::set_permissions(RESETPROP_PATH, std::fs::Permissions::from_mode(0o755))?;
Ok(())
}
pub fn load_system_prop() -> Result<()> { pub fn load_system_prop() -> Result<()> {
ensure_resetprop()?; ensure_binary(RESETPROP_PATH, RESETPROP)?;
ensure_binary(BUSYBOX_PATH, BUSYBOX)?;
let modules_dir = Path::new(defs::MODULE_DIR); let modules_dir = Path::new(defs::MODULE_DIR);
let dir = std::fs::read_dir(modules_dir)?; let dir = std::fs::read_dir(modules_dir)?;
@@ -339,15 +346,8 @@ pub fn install_module(zip: String) -> Result<()> {
println!(include_str!("banner")); println!(include_str!("banner"));
// first check if workding dir is usable // first check if workding dir is usable
let working_dir = Path::new(defs::WORKING_DIR); ensure_dir_exists(defs::WORKING_DIR)?;
if !working_dir.exists() { ensure_dir_exists(defs::BINARY_DIR)?;
create_dir_all(working_dir)?;
}
ensure!(
working_dir.is_dir(),
"working dir exists but it is not a regular directory!"
);
// read the module_id from zip, if faild if will return early. // read the module_id from zip, if faild if will return early.
let mut buffer: Vec<u8> = Vec::new(); let mut buffer: Vec<u8> = Vec::new();
@@ -460,8 +460,8 @@ pub fn install_module(zip: String) -> Result<()> {
module_system_dir.push("system"); module_system_dir.push("system");
let module_system_dir = module_system_dir.as_path(); let module_system_dir = module_system_dir.as_path();
if module_system_dir.exists() { if module_system_dir.exists() {
let path = format!("{}", module_system_dir.display()); let path = module_system_dir.to_str().unwrap();
restorecon::restore_syscon(&path)?; restore_syscon(&path)?;
} }
exec_install_script(&zip) exec_install_script(&zip)
@@ -589,8 +589,8 @@ fn do_enable_module(module_dir: &str, mid: &str, enable: bool) -> Result<()> {
format!("Failed to remove disable file: {}", &disable_path.display()) format!("Failed to remove disable file: {}", &disable_path.display())
})?; })?;
} }
} else if !disable_path.exists() { } else {
std::fs::File::create(disable_path)?; ensure_file_exists(disable_path)?;
} }
let _ = mark_module_state(mid, defs::DISABLE_FILE_NAME, !enable); let _ = mark_module_state(mid, defs::DISABLE_FILE_NAME, !enable);

Binary file not shown.

View File

@@ -1,7 +1,11 @@
use std::path::Path; use anyhow::{bail, ensure, Context, Error, Ok, Result};
use anyhow::{ensure, Context, Result};
use retry::delay::NoDelay; use retry::delay::NoDelay;
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}; use sys_mount::{unmount, FilesystemType, Mount, UnmountFlags};
fn do_mount_image(src: &str, target: &str) -> Result<()> { fn do_mount_image(src: &str, target: &str) -> Result<()> {
@@ -33,6 +37,52 @@ pub fn ensure_clean_dir(dir: &str) -> Result<()> {
Ok(std::fs::create_dir_all(path)?) Ok(std::fs::create_dir_all(path)?)
} }
pub fn ensure_file_exists<T: AsRef<Path>>(file: T) -> Result<()> {
match File::options().write(true).create_new(true).open(&file) {
std::result::Result::Ok(_) => Ok(()),
Err(err) => {
if err.kind() == AlreadyExists && file.as_ref().is_file() {
Ok(())
} else {
Err(Error::from(err)).with_context(|| {
format!("{} is not a regular file", file.as_ref().to_str().unwrap())
})
}
}
}
}
pub fn ensure_dir_exists<T: AsRef<Path>>(dir: T) -> Result<()> {
let result = create_dir_all(&dir).map_err(Error::from);
if dir.as_ref().is_dir() {
result
} else if result.is_ok() {
bail!(
"{} is not a regular directory",
dir.as_ref().to_str().unwrap()
)
} else {
result
}
}
pub fn ensure_binary<T: AsRef<Path>>(path: T, contents: &[u8]) -> Result<()> {
if path.as_ref().exists() {
return Ok(());
}
ensure_dir_exists(path.as_ref().parent().ok_or_else(|| {
anyhow::anyhow!(
"{} does not have parent directory",
path.as_ref().to_string_lossy()
)
})?)?;
write(&path, contents)?;
set_permissions(&path, Permissions::from_mode(0o755))?;
Ok(())
}
pub fn getprop(prop: &str) -> Option<String> { pub fn getprop(prop: &str) -> Option<String> {
android_properties::getprop(prop).value() android_properties::getprop(prop).value()
} }