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;
#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));

View File

@@ -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";

View File

@@ -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

View File

@@ -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

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;
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");

View File

@@ -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)
}

View File

@@ -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.

View File

@@ -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()
}