kernel, ksud: collect binaries into /data/adb/ksu (#161)
This commit is contained in:
@@ -21,7 +21,7 @@ struct perm_data {
|
||||
|
||||
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_load_work;
|
||||
@@ -159,7 +159,7 @@ void do_load_allow_list(struct work_struct *work)
|
||||
u32 magic;
|
||||
u32 version;
|
||||
|
||||
fp = filp_open("/data/adb/", O_RDONLY, 0);
|
||||
fp = filp_open("/data/adb", O_RDONLY, 0);
|
||||
if (IS_ERR(fp)) {
|
||||
int errno = PTR_ERR(fp);
|
||||
pr_err("load_allow_list open '/data/adb': %d\n", PTR_ERR(fp));
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "allowlist.h"
|
||||
#include "arch.h"
|
||||
#include "klog.h" // IWYU pragma: keep
|
||||
#include "ksud.h"
|
||||
#include "selinux/selinux.h"
|
||||
|
||||
static const char KERNEL_SU_RC[] =
|
||||
@@ -20,19 +21,19 @@ static const char KERNEL_SU_RC[] =
|
||||
|
||||
"on post-fs-data\n"
|
||||
// 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"
|
||||
|
||||
"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"
|
||||
|
||||
"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"
|
||||
|
||||
"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";
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef __KSU_H_KSUD
|
||||
#define __KSU_H_KSUD
|
||||
|
||||
#define KSUD_PATH "/data/adb/ksud"
|
||||
|
||||
void on_post_fs_data(void);
|
||||
|
||||
#endif
|
||||
@@ -59,7 +59,7 @@ void apply_kernelsu_rules()
|
||||
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", "file", ALL);
|
||||
// we may need to do mount on shell
|
||||
|
||||
BIN
userspace/ksud/bin/aarch64/busybox
Executable file
BIN
userspace/ksud/bin/aarch64/busybox
Executable file
Binary file not shown.
BIN
userspace/ksud/bin/aarch64/resetprop
Normal file
BIN
userspace/ksud/bin/aarch64/resetprop
Normal file
Binary file not shown.
BIN
userspace/ksud/bin/x86_64/busybox
Normal file
BIN
userspace/ksud/bin/x86_64/busybox
Normal file
Binary file not shown.
BIN
userspace/ksud/bin/x86_64/resetprop
Normal file
BIN
userspace/ksud/bin/x86_64/resetprop
Normal file
Binary file not shown.
@@ -1,7 +1,11 @@
|
||||
use const_format::concatcp;
|
||||
|
||||
pub const DAEMON_PATH: &str = "/data/adb/ksud";
|
||||
pub const WORKING_DIR: &str = "/data/adb/ksu/";
|
||||
pub const ADB_DIR: &str = "/data/adb/";
|
||||
|
||||
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_IMG: &str = concatcp!(WORKING_DIR, "modules.img");
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::{collections::HashMap, path::Path};
|
||||
|
||||
use crate::{
|
||||
defs,
|
||||
utils::{ensure_clean_dir, mount_image},
|
||||
utils::{ensure_clean_dir, ensure_dir_exists, mount_image},
|
||||
};
|
||||
use anyhow::{bail, Result};
|
||||
use sys_mount::{FilesystemType, Mount, MountFlags};
|
||||
@@ -176,9 +176,8 @@ pub fn daemon() -> Result<()> {
|
||||
}
|
||||
|
||||
pub fn install() -> Result<()> {
|
||||
let src = "/proc/self/exe";
|
||||
let dst = defs::DAEMON_PATH;
|
||||
|
||||
std::fs::copy(src, dst)?;
|
||||
Ok(())
|
||||
ensure_dir_exists(defs::ADB_DIR)?;
|
||||
std::fs::copy("/proc/self/exe", defs::DAEMON_PATH)
|
||||
.map(|_| ())
|
||||
.map_err(anyhow::Error::from)
|
||||
}
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
use crate::{defs, restorecon, sepolicy};
|
||||
use crate::{restorecon::setsyscon, utils::*};
|
||||
use crate::{
|
||||
defs,
|
||||
restorecon::{restore_syscon, setsyscon},
|
||||
sepolicy,
|
||||
utils::*,
|
||||
};
|
||||
|
||||
use const_format::concatcp;
|
||||
use java_properties::PropertiesIter;
|
||||
use log::{info, warn};
|
||||
use std::{
|
||||
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},
|
||||
os::unix::{prelude::PermissionsExt, process::CommandExt},
|
||||
os::unix::process::CommandExt,
|
||||
path::{Path, PathBuf},
|
||||
process::{Command, Stdio},
|
||||
str::FromStr,
|
||||
@@ -27,6 +32,10 @@ fn exec_install_script(module_file: &str) -> Result<()> {
|
||||
|
||||
let result = Command::new("sh")
|
||||
.args(["-c", INSTALL_MODULE_SCRIPT])
|
||||
.env(
|
||||
"PATH",
|
||||
format!("{}:{}", env_var("PATH").unwrap(), defs::MODULE_DIR),
|
||||
)
|
||||
.env("OUTFD", "1")
|
||||
.env("ZIPFILE", realpath)
|
||||
.stderr(Stdio::null())
|
||||
@@ -48,30 +57,19 @@ fn ensure_boot_completed() -> Result<()> {
|
||||
}
|
||||
|
||||
fn mark_update() -> Result<()> {
|
||||
let update_file = Path::new(defs::WORKING_DIR).join(defs::UPDATE_FILE_NAME);
|
||||
if update_file.exists() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
std::fs::File::create(update_file)?;
|
||||
Ok(())
|
||||
ensure_file_exists(concatcp!(defs::WORKING_DIR, defs::UPDATE_FILE_NAME))
|
||||
}
|
||||
|
||||
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);
|
||||
if create_or_delete {
|
||||
if module_state_file.exists() {
|
||||
return Ok(());
|
||||
}
|
||||
std::fs::File::create(module_state_file)?;
|
||||
ensure_file_exists(module_state_file)
|
||||
} else {
|
||||
if !module_state_file.exists() {
|
||||
return Ok(());
|
||||
if module_state_file.exists() {
|
||||
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> {
|
||||
@@ -84,8 +82,8 @@ fn get_minimal_image_size(img: &str) -> Result<u64> {
|
||||
println!("- {}", output.trim());
|
||||
let regex = regex::Regex::new(r"filesystem: (\d+)")?;
|
||||
let result = regex
|
||||
.captures(output.as_ref())
|
||||
.ok_or_else(|| anyhow::anyhow!("regex not match"))?;
|
||||
.captures(&output)
|
||||
.ok_or(anyhow::anyhow!("regex not match"))?;
|
||||
let result = &result[1];
|
||||
let result = u64::from_str(result)?;
|
||||
Ok(result)
|
||||
@@ -161,7 +159,7 @@ fn switch_cgroups() {
|
||||
}
|
||||
|
||||
fn is_executable(path: &Path) -> bool {
|
||||
let mut buffer: [u8; 2] = [0; 2];
|
||||
let mut buffer = [0u8; 2];
|
||||
is_executable::is_executable(path)
|
||||
&& File::open(path).unwrap().read_exact(&mut buffer).is_ok()
|
||||
&& (
|
||||
@@ -227,6 +225,10 @@ pub fn exec_post_fs_data() -> Result<()> {
|
||||
command = command
|
||||
.process_group(0)
|
||||
.current_dir(path)
|
||||
.env(
|
||||
"PATH",
|
||||
format!("{}:{}", env_var("PATH").unwrap(), defs::MODULE_DIR),
|
||||
)
|
||||
.env("KSU", "true");
|
||||
unsafe {
|
||||
command = command.pre_exec(|| {
|
||||
@@ -273,6 +275,10 @@ pub fn exec_services() -> Result<()> {
|
||||
command = command
|
||||
.process_group(0)
|
||||
.current_dir(path)
|
||||
.env(
|
||||
"PATH",
|
||||
format!("{}:{}", env_var("PATH").unwrap(), defs::MODULE_DIR),
|
||||
)
|
||||
.env("KSU", "true");
|
||||
unsafe {
|
||||
command = command.pre_exec(|| {
|
||||
@@ -289,20 +295,21 @@ pub fn exec_services() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
const RESETPROP: &[u8] = include_bytes!("./resetprop");
|
||||
const RESETPROP_PATH: &str = concatcp!(defs::WORKING_DIR, "/resetprop");
|
||||
const RESETPROP_PATH: &str = concatcp!(defs::BINARY_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<()> {
|
||||
if Path::new(RESETPROP_PATH).exists() {
|
||||
return Ok(());
|
||||
}
|
||||
std::fs::write(RESETPROP_PATH, RESETPROP)?;
|
||||
std::fs::set_permissions(RESETPROP_PATH, std::fs::Permissions::from_mode(0o755))?;
|
||||
Ok(())
|
||||
}
|
||||
const BUSYBOX_PATH: &str = concatcp!(defs::BINARY_DIR, "busybox");
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
const BUSYBOX: &[u8] = include_bytes!("../bin/aarch64/busybox");
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
const BUSYBOX: &[u8] = include_bytes!("../bin/x86_64/busybox");
|
||||
|
||||
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 dir = std::fs::read_dir(modules_dir)?;
|
||||
@@ -339,15 +346,8 @@ pub fn install_module(zip: String) -> Result<()> {
|
||||
println!(include_str!("banner"));
|
||||
|
||||
// first check if workding dir is usable
|
||||
let working_dir = Path::new(defs::WORKING_DIR);
|
||||
if !working_dir.exists() {
|
||||
create_dir_all(working_dir)?;
|
||||
}
|
||||
|
||||
ensure!(
|
||||
working_dir.is_dir(),
|
||||
"working dir exists but it is not a regular directory!"
|
||||
);
|
||||
ensure_dir_exists(defs::WORKING_DIR)?;
|
||||
ensure_dir_exists(defs::BINARY_DIR)?;
|
||||
|
||||
// read the module_id from zip, if faild if will return early.
|
||||
let mut buffer: Vec<u8> = Vec::new();
|
||||
@@ -460,8 +460,8 @@ pub fn install_module(zip: String) -> Result<()> {
|
||||
module_system_dir.push("system");
|
||||
let module_system_dir = module_system_dir.as_path();
|
||||
if module_system_dir.exists() {
|
||||
let path = format!("{}", module_system_dir.display());
|
||||
restorecon::restore_syscon(&path)?;
|
||||
let path = module_system_dir.to_str().unwrap();
|
||||
restore_syscon(&path)?;
|
||||
}
|
||||
|
||||
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())
|
||||
})?;
|
||||
}
|
||||
} else if !disable_path.exists() {
|
||||
std::fs::File::create(disable_path)?;
|
||||
} else {
|
||||
ensure_file_exists(disable_path)?;
|
||||
}
|
||||
|
||||
let _ = mark_module_state(mid, defs::DISABLE_FILE_NAME, !enable);
|
||||
|
||||
Binary file not shown.
@@ -1,7 +1,11 @@
|
||||
use std::path::Path;
|
||||
|
||||
use anyhow::{ensure, Context, Result};
|
||||
use anyhow::{bail, ensure, Context, Error, Ok, Result};
|
||||
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};
|
||||
|
||||
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)?)
|
||||
}
|
||||
|
||||
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> {
|
||||
android_properties::getprop(prop).value()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user