manager: Simplify kpm management by migrating to the ksud side.
This commit is contained in:
25
.github/workflows/build-manager.yml
vendored
25
.github/workflows/build-manager.yml
vendored
@@ -9,7 +9,6 @@ on:
|
|||||||
- 'kernel/**'
|
- 'kernel/**'
|
||||||
- 'userspace/ksud/**'
|
- 'userspace/ksud/**'
|
||||||
- 'userspace/susfs/**'
|
- 'userspace/susfs/**'
|
||||||
- 'userspace/kpmmgr/**'
|
|
||||||
- 'userspace/user_scanner/**'
|
- 'userspace/user_scanner/**'
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ "main" ]
|
branches: [ "main" ]
|
||||||
@@ -96,19 +95,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
target: ${{ matrix.target }}
|
target: ${{ matrix.target }}
|
||||||
os: ${{ matrix.os }}
|
os: ${{ matrix.os }}
|
||||||
|
|
||||||
build-kpmmgr:
|
|
||||||
if: ${{ always() }}
|
|
||||||
needs: [ check-build-lkm, build-lkm ]
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- target: aarch64-linux-android
|
|
||||||
os: ubuntu-latest
|
|
||||||
uses: ./.github/workflows/kpmmgr.yml
|
|
||||||
with:
|
|
||||||
target: ${{ matrix.target }}
|
|
||||||
os: ${{ matrix.os }}
|
|
||||||
|
|
||||||
build-user_scanner:
|
build-user_scanner:
|
||||||
if: ${{ always() }}
|
if: ${{ always() }}
|
||||||
@@ -202,12 +188,6 @@ jobs:
|
|||||||
name: susfs-aarch64-linux-android
|
name: susfs-aarch64-linux-android
|
||||||
path: .
|
path: .
|
||||||
|
|
||||||
- name: Download arm64 kpmmgr
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: kpmmgr-aarch64-linux-android
|
|
||||||
path: .
|
|
||||||
|
|
||||||
- name: Download arm64 ksud
|
- name: Download arm64 ksud
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
@@ -234,11 +214,6 @@ jobs:
|
|||||||
cp -f ../aarch64-linux-android/release/zakozako ../manager/app/src/main/jniLibs/arm64-v8a/libzakozako.so
|
cp -f ../aarch64-linux-android/release/zakozako ../manager/app/src/main/jniLibs/arm64-v8a/libzakozako.so
|
||||||
cp -f ../x86_64-linux-android/release/zakozako ../manager/app/src/main/jniLibs/x86_64/libzakozako.so
|
cp -f ../x86_64-linux-android/release/zakozako ../manager/app/src/main/jniLibs/x86_64/libzakozako.so
|
||||||
cp -f ../armv7-linux-androideabi/release/zakozako ../manager/app/src/main/jniLibs/armeabi-v7a/libzakozako.so
|
cp -f ../armv7-linux-androideabi/release/zakozako ../manager/app/src/main/jniLibs/armeabi-v7a/libzakozako.so
|
||||||
|
|
||||||
- name: Copy kpmmgr to app jniLibs
|
|
||||||
run: |
|
|
||||||
mkdir -p app/src/main/jniLibs/arm64-v8a
|
|
||||||
cp -f ../arm64-v8a/kpmmgr ../manager/app/src/main/jniLibs/arm64-v8a/libkpmmgr.so
|
|
||||||
|
|
||||||
- name: Copy susfs to app jniLibs
|
- name: Copy susfs to app jniLibs
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
40
.github/workflows/kpmmgr.yml
vendored
40
.github/workflows/kpmmgr.yml
vendored
@@ -1,40 +0,0 @@
|
|||||||
name: Build kpmmgr
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ "mian" ]
|
|
||||||
paths:
|
|
||||||
- '.github/workflows/kpmmgr.yml'
|
|
||||||
- 'userspace/kpmmgr/**'
|
|
||||||
workflow_dispatch:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
target:
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
os:
|
|
||||||
required: false
|
|
||||||
type: string
|
|
||||||
default: self-hosted
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-susfs:
|
|
||||||
name: Build userspace kpmmgr
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Build kpmmgr
|
|
||||||
working-directory: ./userspace/kpmmgr
|
|
||||||
run: |
|
|
||||||
$ANDROID_NDK_HOME/ndk-build
|
|
||||||
|
|
||||||
- name: Upload a Build Artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: kpmmgr-aarch64-linux-android
|
|
||||||
path: ./userspace/kpmmgr/libs
|
|
||||||
@@ -419,6 +419,69 @@ fun deleteAppProfileTemplate(id: String): Boolean {
|
|||||||
return shell.newJob().add("${getKsuDaemonPath()} profile delete-template '${id}'")
|
return shell.newJob().add("${getKsuDaemonPath()} profile delete-template '${id}'")
|
||||||
.to(ArrayList(), null).exec().isSuccess
|
.to(ArrayList(), null).exec().isSuccess
|
||||||
}
|
}
|
||||||
|
// KPM控制
|
||||||
|
fun loadKpmModule(path: String, args: String? = null): String {
|
||||||
|
val shell = getRootShell()
|
||||||
|
val cmd = "${getKsuDaemonPath()} kpm load $path ${args ?: ""}"
|
||||||
|
return ShellUtils.fastCmd(shell, cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun unloadKpmModule(name: String): String {
|
||||||
|
val shell = getRootShell()
|
||||||
|
val cmd = "${getKsuDaemonPath()} kpm unload $name"
|
||||||
|
return ShellUtils.fastCmd(shell, cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getKpmModuleCount(): Int {
|
||||||
|
val shell = getRootShell()
|
||||||
|
val cmd = "${getKsuDaemonPath()} kpm num"
|
||||||
|
val result = ShellUtils.fastCmd(shell, cmd)
|
||||||
|
return result.trim().toIntOrNull() ?: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun runCmd(shell: Shell, cmd: String): String {
|
||||||
|
return shell.newJob()
|
||||||
|
.add(cmd)
|
||||||
|
.to(mutableListOf<String>(), null)
|
||||||
|
.exec().out
|
||||||
|
.joinToString("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun listKpmModules(): String {
|
||||||
|
val shell = getRootShell()
|
||||||
|
val cmd = "${getKsuDaemonPath()} kpm list"
|
||||||
|
return try {
|
||||||
|
runCmd(shell, cmd).trim()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "Failed to list KPM modules", e)
|
||||||
|
""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getKpmModuleInfo(name: String): String {
|
||||||
|
val shell = getRootShell()
|
||||||
|
val cmd = "${getKsuDaemonPath()} kpm info $name"
|
||||||
|
return try {
|
||||||
|
runCmd(shell, cmd).trim()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "Failed to get KPM module info: $name", e)
|
||||||
|
""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun controlKpmModule(name: String, args: String? = null): Int {
|
||||||
|
val shell = getRootShell()
|
||||||
|
val cmd = """${getKsuDaemonPath()} kpm control $name "${args ?: ""}""""
|
||||||
|
val result = runCmd(shell, cmd)
|
||||||
|
return result.trim().toIntOrNull() ?: -1
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getKpmVersion(): String {
|
||||||
|
val shell = getRootShell()
|
||||||
|
val cmd = "${getKsuDaemonPath()} kpm version"
|
||||||
|
val result = ShellUtils.fastCmd(shell, cmd)
|
||||||
|
return result.trim()
|
||||||
|
}
|
||||||
|
|
||||||
fun forceStopApp(packageName: String) {
|
fun forceStopApp(packageName: String) {
|
||||||
val shell = getRootShell()
|
val shell = getRootShell()
|
||||||
@@ -487,74 +550,6 @@ fun susfsSUS_SU_Mode(): String {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getKpmmgrPath(): String {
|
|
||||||
return ksuApp.applicationInfo.nativeLibraryDir + File.separator + "libkpmmgr.so"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun loadKpmModule(path: String, args: String? = null): String {
|
|
||||||
val shell = getRootShell()
|
|
||||||
val cmd = "${getKpmmgrPath()} load $path ${args ?: ""}"
|
|
||||||
return ShellUtils.fastCmd(shell, cmd)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun unloadKpmModule(name: String): String {
|
|
||||||
val shell = getRootShell()
|
|
||||||
val cmd = "${getKpmmgrPath()} unload $name"
|
|
||||||
return ShellUtils.fastCmd(shell, cmd)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getKpmModuleCount(): Int {
|
|
||||||
val shell = getRootShell()
|
|
||||||
val cmd = "${getKpmmgrPath()} num"
|
|
||||||
val result = ShellUtils.fastCmd(shell, cmd)
|
|
||||||
return result.trim().toIntOrNull() ?: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
fun runCmd(shell: Shell, cmd: String): String {
|
|
||||||
return shell.newJob()
|
|
||||||
.add(cmd)
|
|
||||||
.to(mutableListOf<String>(), null)
|
|
||||||
.exec().out
|
|
||||||
.joinToString("\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun listKpmModules(): String {
|
|
||||||
val shell = getRootShell()
|
|
||||||
val cmd = "${getKpmmgrPath()} list"
|
|
||||||
return try {
|
|
||||||
runCmd(shell, cmd).trim()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.e(TAG, "Failed to list KPM modules", e)
|
|
||||||
""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getKpmModuleInfo(name: String): String {
|
|
||||||
val shell = getRootShell()
|
|
||||||
val cmd = "${getKpmmgrPath()} info $name"
|
|
||||||
return try {
|
|
||||||
runCmd(shell, cmd).trim()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.e(TAG, "Failed to get KPM module info: $name", e)
|
|
||||||
""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun controlKpmModule(name: String, args: String? = null): Int {
|
|
||||||
val shell = getRootShell()
|
|
||||||
val cmd = """${getKpmmgrPath()} control $name "${args ?: ""}""""
|
|
||||||
val result = runCmd(shell, cmd)
|
|
||||||
return result.trim().toIntOrNull() ?: -1
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getKpmVersion(): String {
|
|
||||||
val shell = getRootShell()
|
|
||||||
val cmd = "${getKpmmgrPath()} version"
|
|
||||||
val result = ShellUtils.fastCmd(shell, cmd)
|
|
||||||
return result.trim()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getZygiskImplement(): String {
|
fun getZygiskImplement(): String {
|
||||||
val shell = getRootShell()
|
val shell = getRootShell()
|
||||||
|
|
||||||
|
|||||||
@@ -4,16 +4,10 @@ import static com.sukisu.ultra.ui.util.KsuCliKt.*;
|
|||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
|
|
||||||
public class UltraToolInstall {
|
public class UltraToolInstall {
|
||||||
private static final String OUTSIDE_KPMMGR_PATH = "/data/adb/ksu/bin/kpmmgr";
|
|
||||||
private static final String OUTSIDE_SUSFSD_PATH = "/data/adb/ksu/bin/susfsd";
|
private static final String OUTSIDE_SUSFSD_PATH = "/data/adb/ksu/bin/susfsd";
|
||||||
|
|
||||||
@SuppressLint("SetWorldReadable")
|
@SuppressLint("SetWorldReadable")
|
||||||
public static void tryToInstall() {
|
public static void tryToInstall() {
|
||||||
String kpmmgrPath = getKpmmgrPath();
|
|
||||||
if (UltraShellHelper.isPathExists(OUTSIDE_KPMMGR_PATH)) {
|
|
||||||
UltraShellHelper.CopyFileTo(kpmmgrPath, OUTSIDE_KPMMGR_PATH);
|
|
||||||
UltraShellHelper.runCmd("chmod a+rx " + OUTSIDE_KPMMGR_PATH);
|
|
||||||
}
|
|
||||||
String SuSFSDaemonPath = getSuSFSDaemonPath();
|
String SuSFSDaemonPath = getSuSFSDaemonPath();
|
||||||
if (UltraShellHelper.isPathExists(OUTSIDE_SUSFSD_PATH)) {
|
if (UltraShellHelper.isPathExists(OUTSIDE_SUSFSD_PATH)) {
|
||||||
UltraShellHelper.CopyFileTo(SuSFSDaemonPath, OUTSIDE_SUSFSD_PATH);
|
UltraShellHelper.CopyFileTo(SuSFSDaemonPath, OUTSIDE_SUSFSD_PATH);
|
||||||
|
|||||||
2
userspace/kpmmgr/.gitignore
vendored
2
userspace/kpmmgr/.gitignore
vendored
@@ -1,2 +0,0 @@
|
|||||||
/obj
|
|
||||||
/libs
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
LOCAL_PATH := $(call my-dir)
|
|
||||||
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
LOCAL_MODULE := kpmmgr
|
|
||||||
LOCAL_SRC_FILES := kpmmgr.c
|
|
||||||
include $(BUILD_EXECUTABLE)
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
APP_ABI := arm64-v8a
|
|
||||||
APP_PLATFORM := android-24
|
|
||||||
APP_STL := none
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/prctl.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#define KERNEL_SU_OPTION 0xDEADBEEF
|
|
||||||
#define KSU_OPTIONS 0xdeadbeef
|
|
||||||
|
|
||||||
// KPM控制代码
|
|
||||||
#define CMD_KPM_CONTROL 28
|
|
||||||
#define CMD_KPM_CONTROL_MAX 7
|
|
||||||
|
|
||||||
// 控制代码
|
|
||||||
// prctl(xxx, 28, "PATH", "ARGS")
|
|
||||||
// success return 0, error return -N
|
|
||||||
#define SUKISU_KPM_LOAD 28
|
|
||||||
|
|
||||||
// prctl(xxx, 29, "NAME")
|
|
||||||
// success return 0, error return -N
|
|
||||||
#define SUKISU_KPM_UNLOAD 29
|
|
||||||
|
|
||||||
// num = prctl(xxx, 30)
|
|
||||||
// error return -N
|
|
||||||
// success return +num or 0
|
|
||||||
#define SUKISU_KPM_NUM 30
|
|
||||||
|
|
||||||
// prctl(xxx, 31, Buffer, BufferSize)
|
|
||||||
// success return +out, error return -N
|
|
||||||
#define SUKISU_KPM_LIST 31
|
|
||||||
|
|
||||||
// prctl(xxx, 32, "NAME", Buffer[256])
|
|
||||||
// success return +out, error return -N
|
|
||||||
#define SUKISU_KPM_INFO 32
|
|
||||||
|
|
||||||
// prctl(xxx, 33, "NAME", "ARGS")
|
|
||||||
// success return KPM's result value
|
|
||||||
// error return -N
|
|
||||||
#define SUKISU_KPM_CONTROL 33
|
|
||||||
|
|
||||||
// prctl(xxx, 34, buffer, bufferSize)
|
|
||||||
// success return KPM's result value
|
|
||||||
// error return -N
|
|
||||||
#define SUKISU_KPM_VERSION 34
|
|
||||||
|
|
||||||
#define CONTROL_CODE(n) (n)
|
|
||||||
|
|
||||||
void print_usage(const char *prog) {
|
|
||||||
printf("Usage: %s <command> [args]\n", prog);
|
|
||||||
printf("Commands:\n");
|
|
||||||
printf(" load <path> <args> Load a KPM module\n");
|
|
||||||
printf(" unload <name> Unload a KPM module\n");
|
|
||||||
printf(" num Get number of loaded modules\n");
|
|
||||||
printf(" list List loaded KPM modules\n");
|
|
||||||
printf(" info <name> Get info of a KPM module\n");
|
|
||||||
printf(" control <name> <args> Send control command to a KPM module\n");
|
|
||||||
printf(" version Print KPM Loader version\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
if (argc < 2) {
|
|
||||||
print_usage(argv[0]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ret = -1;
|
|
||||||
int out = -1; // 存储返回值
|
|
||||||
|
|
||||||
if (strcmp(argv[1], "load") == 0 && argc >= 3) {
|
|
||||||
// 加载 KPM 模块
|
|
||||||
ret = prctl(KSU_OPTIONS, CONTROL_CODE(SUKISU_KPM_LOAD), argv[2], (argc > 3 ? argv[3] : NULL), &out);
|
|
||||||
if(out > 0) {
|
|
||||||
printf("Success");
|
|
||||||
}
|
|
||||||
} else if (strcmp(argv[1], "unload") == 0 && argc >= 3) {
|
|
||||||
// 卸载 KPM 模块
|
|
||||||
ret = prctl(KSU_OPTIONS, CONTROL_CODE(SUKISU_KPM_UNLOAD), argv[2], NULL, &out);
|
|
||||||
} else if (strcmp(argv[1], "num") == 0) {
|
|
||||||
// 获取加载的 KPM 数量
|
|
||||||
ret = prctl(KSU_OPTIONS, CONTROL_CODE(SUKISU_KPM_NUM), NULL, NULL, &out);
|
|
||||||
printf("%d", out);
|
|
||||||
return 0;
|
|
||||||
} else if (strcmp(argv[1], "list") == 0) {
|
|
||||||
// 获取模块列表
|
|
||||||
char buffer[1024] = {0};
|
|
||||||
ret = prctl(KSU_OPTIONS, CONTROL_CODE(SUKISU_KPM_LIST), buffer, sizeof(buffer), &out);
|
|
||||||
if (out >= 0) {
|
|
||||||
printf("%s", buffer);
|
|
||||||
}
|
|
||||||
} else if (strcmp(argv[1], "info") == 0 && argc >= 3) {
|
|
||||||
// 获取指定模块信息
|
|
||||||
char buffer[256] = {0};
|
|
||||||
ret = prctl(KSU_OPTIONS, CONTROL_CODE(SUKISU_KPM_INFO), argv[2], buffer, &out);
|
|
||||||
if (out >= 0) {
|
|
||||||
printf("%s\n", buffer);
|
|
||||||
}
|
|
||||||
} else if (strcmp(argv[1], "control") == 0 && argc >= 4) {
|
|
||||||
// 控制 KPM 模块
|
|
||||||
ret = prctl(KSU_OPTIONS, CONTROL_CODE(SUKISU_KPM_CONTROL), argv[2], argv[3], &out);
|
|
||||||
} else if (strcmp(argv[1], "version") == 0) {
|
|
||||||
char buffer[1024] = {0};
|
|
||||||
ret = prctl(KSU_OPTIONS, CONTROL_CODE(SUKISU_KPM_VERSION), buffer, sizeof(buffer), &out);
|
|
||||||
if (out >= 0) {
|
|
||||||
printf("%s", buffer);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
print_usage(argv[0]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (out < 0) {
|
|
||||||
printf("Error: %s\n", strerror(-out));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -122,6 +122,14 @@ enum Commands {
|
|||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
command: BootInfo,
|
command: BootInfo,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// KPM module manager
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
Kpm {
|
||||||
|
#[command(subcommand)]
|
||||||
|
command: kpm_cmd::Kpm,
|
||||||
|
},
|
||||||
|
|
||||||
/// For developers
|
/// For developers
|
||||||
Debug {
|
Debug {
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
@@ -272,6 +280,33 @@ enum Profile {
|
|||||||
ListTemplates,
|
ListTemplates,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
mod kpm_cmd {
|
||||||
|
use clap::Subcommand;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
#[derive(Subcommand, Debug)]
|
||||||
|
pub enum Kpm {
|
||||||
|
/// Load a KPM module: load <path> [args]
|
||||||
|
Load {
|
||||||
|
path: PathBuf,
|
||||||
|
args: Option<String>,
|
||||||
|
},
|
||||||
|
/// Unload a KPM module: unload <name>
|
||||||
|
Unload { name: String },
|
||||||
|
/// Get number of loaded modules
|
||||||
|
Num,
|
||||||
|
/// List loaded KPM modules
|
||||||
|
List,
|
||||||
|
/// Get info of a KPM module: info <name>
|
||||||
|
Info { name: String },
|
||||||
|
/// Send control command to a KPM module: control <name> <args>
|
||||||
|
Control { name: String, args: String },
|
||||||
|
/// Print KPM Loader version
|
||||||
|
Version,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn run() -> Result<()> {
|
pub fn run() -> Result<()> {
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
android_logger::init_once(
|
android_logger::init_once(
|
||||||
@@ -381,6 +416,23 @@ pub fn run() -> Result<()> {
|
|||||||
magiskboot,
|
magiskboot,
|
||||||
flash,
|
flash,
|
||||||
} => crate::boot_patch::restore(boot, magiskboot, flash),
|
} => crate::boot_patch::restore(boot, magiskboot, flash),
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
Commands::Kpm { command } => {
|
||||||
|
use crate::cli::kpm_cmd::Kpm;
|
||||||
|
match command {
|
||||||
|
Kpm::Load { path, args } => crate::kpm::kpm_load(path.to_str().unwrap(), args.as_deref()),
|
||||||
|
Kpm::Unload { name } => crate::kpm::kpm_unload(&name),
|
||||||
|
Kpm::Num => crate::kpm::kpm_num().map(|_| ()),
|
||||||
|
Kpm::List => crate::kpm::kpm_list(),
|
||||||
|
Kpm::Info { name } => crate::kpm::kpm_info(&name),
|
||||||
|
Kpm::Control { name, args } => {
|
||||||
|
let ret = crate::kpm::kpm_control(&name, &args)?;
|
||||||
|
println!("{}", ret);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Kpm::Version => crate::kpm::kpm_version_loader(),
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(e) = &result {
|
if let Err(e) = &result {
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
use crate::defs::{KSU_MOUNT_SOURCE, NO_MOUNT_PATH, NO_TMPFS_PATH};
|
use crate::defs::{KSU_MOUNT_SOURCE, NO_MOUNT_PATH, NO_TMPFS_PATH};
|
||||||
use crate::module::{handle_updated_modules, prune_modules};
|
use crate::module::{handle_updated_modules, prune_modules};
|
||||||
use crate::{assets, defs, ksucalls, restorecon, utils, kpm, uid_scanner};
|
use crate::{assets, defs, ksucalls, restorecon, utils, uid_scanner};
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use rustix::fs::{MountFlags, mount};
|
use rustix::fs::{MountFlags, mount};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
use crate::kpm;
|
||||||
|
|
||||||
pub fn on_post_data_fs() -> Result<()> {
|
pub fn on_post_data_fs() -> Result<()> {
|
||||||
ksucalls::report_post_fs_data();
|
ksucalls::report_post_fs_data();
|
||||||
@@ -70,10 +72,12 @@ pub fn on_post_data_fs() -> Result<()> {
|
|||||||
warn!("apply root profile sepolicy failed: {e}");
|
warn!("apply root profile sepolicy failed: {e}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
if let Err(e) = kpm::start_kpm_watcher() {
|
if let Err(e) = kpm::start_kpm_watcher() {
|
||||||
warn!("KPM: Failed to start KPM watcher: {}", e);
|
warn!("KPM: Failed to start KPM watcher: {}", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
if let Err(e) = kpm::load_kpm_modules() {
|
if let Err(e) = kpm::load_kpm_modules() {
|
||||||
warn!("KPM: Failed to load KPM modules: {}", e);
|
warn!("KPM: Failed to load KPM modules: {}", e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,242 +1,236 @@
|
|||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, bail, Result};
|
||||||
use libc::{prctl, c_char, c_void, c_int};
|
use libc::{c_char, c_int, c_void, prctl};
|
||||||
use notify::{RecursiveMode, Watcher};
|
use notify::{RecursiveMode, Watcher};
|
||||||
use std::ffi::{CStr, CString, OsStr};
|
use std::ffi::{CStr, CString, OsStr};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::Path;
|
|
||||||
use std::ptr;
|
|
||||||
use std::os::unix::fs::PermissionsExt;
|
use std::os::unix::fs::PermissionsExt;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
pub const KPM_DIR: &str = "/data/adb/kpm";
|
pub const KPM_DIR: &str = "/data/adb/kpm";
|
||||||
|
|
||||||
const KSU_OPTIONS: u32 = 0xdeadbeef;
|
const KSU_OPTIONS: u32 = 0xdeadbeef;
|
||||||
const SUKISU_KPM_LOAD: i32 = 28;
|
const SUKISU_KPM_LOAD: i32 = 28;
|
||||||
const SUKISU_KPM_UNLOAD: i32 = 29;
|
const SUKISU_KPM_UNLOAD: i32 = 29;
|
||||||
const SUKISU_KPM_VERSION: i32 = 34;
|
const SUKISU_KPM_NUM: i32 = 30;
|
||||||
|
const SUKISU_KPM_LIST: i32 = 31;
|
||||||
|
const SUKISU_KPM_INFO: i32 = 32;
|
||||||
|
const SUKISU_KPM_CONTROL:i32 = 33;
|
||||||
|
const SUKISU_KPM_VERSION:i32 = 34;
|
||||||
|
|
||||||
pub fn check_kpm_version() -> Result<String> {
|
#[inline(always)]
|
||||||
let mut buffer: [u8; 1024] = [0; 1024];
|
unsafe fn kpm_prctl(
|
||||||
|
cmd: i32,
|
||||||
|
arg1: *const c_void,
|
||||||
|
arg2: *const c_void,
|
||||||
|
) -> Result<i32> {
|
||||||
let mut out: c_int = -1;
|
let mut out: c_int = -1;
|
||||||
|
let ret = unsafe {
|
||||||
let _ret = unsafe {
|
|
||||||
prctl(
|
prctl(
|
||||||
KSU_OPTIONS as c_int,
|
KSU_OPTIONS as c_int,
|
||||||
SUKISU_KPM_VERSION,
|
cmd as c_int,
|
||||||
buffer.as_mut_ptr() as *mut c_void,
|
arg1,
|
||||||
buffer.len() as *mut c_void,
|
arg2,
|
||||||
&mut out as *mut c_int as *mut c_void,
|
&mut out as *mut c_int as *mut c_void,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
if ret != 0 || out < 0 {
|
||||||
if out < 0 {
|
bail!("KPM prctl error: {}", std::io::Error::from_raw_os_error(-out));
|
||||||
return Err(anyhow!("KPM: prctl returned error: {}", out));
|
|
||||||
}
|
}
|
||||||
|
Ok(out)
|
||||||
let version_str = unsafe {
|
}
|
||||||
CStr::from_ptr(buffer.as_ptr() as *const c_char)
|
|
||||||
}.to_string_lossy().to_string();
|
fn str_to_cstr<R, F: FnOnce(*const c_char) -> R>(s: &str, f: F) -> Result<R> {
|
||||||
|
let cs = CString::new(s)?;
|
||||||
log::info!("KPM: Version check result: {}", version_str);
|
Ok(f(cs.as_ptr()))
|
||||||
|
}
|
||||||
// 检查版本是否有效(不为空且不以Error开头)
|
|
||||||
if version_str.is_empty() || version_str.starts_with("Error") {
|
fn cbuf_to_string(buf: &[u8]) -> String {
|
||||||
return Err(anyhow!("KPM: Invalid version response: {}", version_str));
|
unsafe { CStr::from_ptr(buf.as_ptr() as *const c_char) }
|
||||||
}
|
.to_string_lossy()
|
||||||
|
.into_owned()
|
||||||
Ok(version_str)
|
}
|
||||||
|
|
||||||
|
pub fn kpm_load(path: &str, args: Option<&str>) -> Result<()> {
|
||||||
|
str_to_cstr(path, |p_path| {
|
||||||
|
let _args_cstring;
|
||||||
|
let p_args = match args {
|
||||||
|
Some(a) => {
|
||||||
|
_args_cstring = CString::new(a)?;
|
||||||
|
_args_cstring.as_ptr()
|
||||||
|
}
|
||||||
|
None => ptr::null(),
|
||||||
|
};
|
||||||
|
unsafe { kpm_prctl(SUKISU_KPM_LOAD, p_path as _, p_args as _) }?;
|
||||||
|
println!("Success");
|
||||||
|
Ok(())
|
||||||
|
})?
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn kpm_unload(name: &str) -> Result<()> {
|
||||||
|
let _ = str_to_cstr(name, |p| unsafe {
|
||||||
|
kpm_prctl(SUKISU_KPM_UNLOAD, p as _, ptr::null())
|
||||||
|
})?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn kpm_num() -> Result<i32> {
|
||||||
|
let n = unsafe { kpm_prctl(SUKISU_KPM_NUM, ptr::null(), ptr::null())? };
|
||||||
|
println!("{}", n);
|
||||||
|
Ok(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn kpm_list() -> Result<()> {
|
||||||
|
let mut buf = vec![0u8; 1024];
|
||||||
|
unsafe {
|
||||||
|
kpm_prctl(
|
||||||
|
SUKISU_KPM_LIST,
|
||||||
|
buf.as_mut_ptr() as _,
|
||||||
|
buf.len() as *const c_void,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
print!("{}", cbuf_to_string(&buf));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn kpm_info(name: &str) -> Result<()> {
|
||||||
|
let mut buf = vec![0u8; 256];
|
||||||
|
let _ = str_to_cstr(name, |p| unsafe {
|
||||||
|
kpm_prctl(SUKISU_KPM_INFO, p as _, buf.as_mut_ptr() as _)
|
||||||
|
})?;
|
||||||
|
println!("{}", cbuf_to_string(&buf));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn kpm_control(name: &str, args: &str) -> Result<i32> {
|
||||||
|
str_to_cstr(name, |p_name| {
|
||||||
|
str_to_cstr(args, |p_args| unsafe {
|
||||||
|
kpm_prctl(SUKISU_KPM_CONTROL, p_name as _, p_args as _)
|
||||||
|
})?
|
||||||
|
})?
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn kpm_version_loader() -> Result<()> {
|
||||||
|
let mut buf = vec![0u8; 1024];
|
||||||
|
unsafe {
|
||||||
|
kpm_prctl(
|
||||||
|
SUKISU_KPM_VERSION,
|
||||||
|
buf.as_mut_ptr() as _,
|
||||||
|
buf.len() as *const c_void,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
print!("{}", cbuf_to_string(&buf));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check_kpm_version() -> Result<String> {
|
||||||
|
let mut buf = vec![0u8; 1024];
|
||||||
|
unsafe {
|
||||||
|
kpm_prctl(
|
||||||
|
SUKISU_KPM_VERSION,
|
||||||
|
buf.as_mut_ptr() as _,
|
||||||
|
buf.len() as *const c_void,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
let ver = cbuf_to_string(&buf);
|
||||||
|
if ver.is_empty() || ver.starts_with("Error") {
|
||||||
|
bail!("KPM: Invalid version response: {}", ver);
|
||||||
|
}
|
||||||
|
log::info!("KPM: Version check result: {}", ver);
|
||||||
|
Ok(ver)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 确保 KPM 目录存在,并设置777权限
|
|
||||||
pub fn ensure_kpm_dir() -> Result<()> {
|
pub fn ensure_kpm_dir() -> Result<()> {
|
||||||
let path = Path::new(KPM_DIR);
|
let path = Path::new(KPM_DIR);
|
||||||
|
if !path.exists() {
|
||||||
if path.exists() {
|
fs::create_dir_all(path)?;
|
||||||
let meta = fs::metadata(path)?;
|
}
|
||||||
let current = meta.permissions().mode() & 0o777;
|
let meta = fs::metadata(path)?;
|
||||||
if current != 0o777 {
|
if meta.permissions().mode() & 0o777 != 0o777 {
|
||||||
log::info!("KPM: Fixing permissions to 777 for {}", KPM_DIR);
|
fs::set_permissions(path, fs::Permissions::from_mode(0o777))?;
|
||||||
fs::set_permissions(path, fs::Permissions::from_mode(0o777))?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_kpm_watcher() -> Result<()> {
|
pub fn start_kpm_watcher() -> Result<()> {
|
||||||
match check_kpm_version() {
|
check_kpm_version()?;
|
||||||
Ok(version) => {
|
|
||||||
log::info!("KPM: Version check passed, version: {}", version);
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
log::warn!("KPM: Version check failed, skipping KPM functionality: {}", e);
|
|
||||||
return Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ensure_kpm_dir()?;
|
ensure_kpm_dir()?;
|
||||||
|
|
||||||
// 检查是否处于安全模式
|
|
||||||
if crate::utils::is_safe_mode() {
|
if crate::utils::is_safe_mode() {
|
||||||
log::warn!("KPM: System is in safe mode, removing all KPM modules");
|
log::warn!("KPM: Safe mode – removing all KPM modules");
|
||||||
if let Err(e) = remove_all_kpms() {
|
remove_all_kpms()?;
|
||||||
log::error!("KPM: Error removing all KPM modules: {}", e);
|
|
||||||
}
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut watcher = notify::recommended_watcher(|res| match res {
|
let mut watcher = notify::recommended_watcher(|res| match res {
|
||||||
Ok(event) => handle_kpm_event(event),
|
Ok(event) => handle_kpm_event(event),
|
||||||
Err(e) => log::error!("KPM: File monitoring error: {:?}", e),
|
Err(e) => log::error!("KPM: File monitor error: {:?}", e),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
watcher.watch(Path::new(KPM_DIR), RecursiveMode::NonRecursive)?;
|
watcher.watch(Path::new(KPM_DIR), RecursiveMode::NonRecursive)?;
|
||||||
log::info!("KPM: Started file watcher for directory: {}", KPM_DIR);
|
log::info!("KPM: File watcher started on {}", KPM_DIR);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理 KPM 事件
|
fn handle_kpm_event(event: notify::Event) {
|
||||||
pub fn handle_kpm_event(event: notify::Event) {
|
|
||||||
match event.kind {
|
match event.kind {
|
||||||
notify::EventKind::Create(_) => handle_create_event(event.paths),
|
notify::EventKind::Create(_) => {
|
||||||
notify::EventKind::Remove(_) => handle_remove_event(event.paths),
|
for p in event.paths {
|
||||||
notify::EventKind::Modify(_) => handle_modify_event(event.paths),
|
if p.extension() == Some(OsStr::new("kpm")) {
|
||||||
|
if let Err(e) = load_kpm(&p) {
|
||||||
|
log::warn!("KPM: Failed to load {}: {}", p.display(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
notify::EventKind::Modify(_) => {
|
||||||
|
for p in event.paths {
|
||||||
|
log::info!("KPM: Modified file: {}", p.display());
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_create_event(paths: Vec<std::path::PathBuf>) {
|
|
||||||
for path in paths {
|
|
||||||
if path.extension() == Some(OsStr::new("kpm")) {
|
|
||||||
log::info!("KPM: Detected new KPM file: {}", path.display());
|
|
||||||
if let Err(e) = load_kpm(&path) {
|
|
||||||
log::warn!("KPM: Failed to load {}: {}", path.display(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_remove_event(paths: Vec<std::path::PathBuf>) {
|
|
||||||
for path in paths {
|
|
||||||
if let Some(name) = path.file_stem().and_then(|s| s.to_str()) {
|
|
||||||
log::info!("KPM: Detected KPM file removal: {}", name);
|
|
||||||
if let Err(e) = unload_kpm(name) {
|
|
||||||
log::warn!("KPM: Failed to unload {}: {}", name, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_modify_event(paths: Vec<std::path::PathBuf>) {
|
|
||||||
for path in paths {
|
|
||||||
log::info!("KPM: Modified file detected: {}", path.display());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 加载 KPM 模块
|
|
||||||
pub fn load_kpm(path: &Path) -> Result<()> {
|
pub fn load_kpm(path: &Path) -> Result<()> {
|
||||||
let path_str = path
|
let path_str = path.to_str().ok_or_else(|| anyhow!("Invalid path"))?;
|
||||||
.to_str()
|
kpm_load(path_str, None)
|
||||||
.ok_or_else(|| anyhow!("KPM: Invalid path: {}", path.display()))?;
|
|
||||||
|
|
||||||
let path_cstring = CString::new(path_str)
|
|
||||||
.map_err(|e| anyhow!("KPM: Failed to convert path to CString: {}", e))?;
|
|
||||||
|
|
||||||
let mut out: c_int = -1;
|
|
||||||
|
|
||||||
let _ret = unsafe {
|
|
||||||
prctl(
|
|
||||||
KSU_OPTIONS as c_int,
|
|
||||||
SUKISU_KPM_LOAD,
|
|
||||||
path_cstring.as_ptr() as *mut c_void,
|
|
||||||
ptr::null_mut::<c_void>(),
|
|
||||||
&mut out as *mut c_int as *mut c_void,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
if out < 0 {
|
|
||||||
return Err(anyhow!("KPM: prctl returned error: {}", out));
|
|
||||||
}
|
|
||||||
|
|
||||||
if out > 0 {
|
|
||||||
log::info!("KPM: Successfully loaded module: {}", path.display());
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 卸载 KPM 模块
|
|
||||||
pub fn unload_kpm(name: &str) -> Result<()> {
|
pub fn unload_kpm(name: &str) -> Result<()> {
|
||||||
let name_cstring = CString::new(name)
|
kpm_unload(name)?;
|
||||||
.map_err(|e| anyhow!("KPM: Failed to convert name to CString: {}", e))?;
|
if let Some(p) = find_kpm_file(name)? {
|
||||||
|
fs::remove_file(&p).ok();
|
||||||
let mut out: c_int = -1;
|
log::info!("KPM: Deleted file {}", p.display());
|
||||||
|
|
||||||
let _ret = unsafe {
|
|
||||||
prctl(
|
|
||||||
KSU_OPTIONS as c_int,
|
|
||||||
SUKISU_KPM_UNLOAD,
|
|
||||||
name_cstring.as_ptr() as *mut c_void,
|
|
||||||
ptr::null_mut::<c_void>(),
|
|
||||||
&mut out as *mut c_int as *mut c_void,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
if out < 0 {
|
|
||||||
log::warn!("KPM: prctl returned error for unload: {}", out);
|
|
||||||
return Err(anyhow!("KPM: prctl returned error: {}", out));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 尝试删除对应的KPM文件
|
|
||||||
if let Ok(Some(path)) = find_kpm_file(name) {
|
|
||||||
if let Err(e) = fs::remove_file(&path) {
|
|
||||||
log::warn!("KPM: Failed to delete KPM file {}: {}", path.display(), e);
|
|
||||||
} else {
|
|
||||||
log::info!("KPM: Deleted KPM file: {}", path.display());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log::info!("KPM: Successfully unloaded module: {}", name);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// 通过名称查找 KPM 文件
|
fn find_kpm_file(name: &str) -> Result<Option<PathBuf>> {
|
||||||
fn find_kpm_file(name: &str) -> Result<Option<std::path::PathBuf>> {
|
let dir = Path::new(KPM_DIR);
|
||||||
let kpm_dir = Path::new(KPM_DIR);
|
if !dir.exists() {
|
||||||
if !kpm_dir.exists() {
|
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
for entry in fs::read_dir(dir)? {
|
||||||
for entry in fs::read_dir(kpm_dir)? {
|
let p = entry?.path();
|
||||||
let path = entry?.path();
|
if p.extension() == Some(OsStr::new("kpm"))
|
||||||
if let Some(file_name) = path.file_stem() {
|
&& p.file_stem().map_or(false, |s| s == name)
|
||||||
if let Some(file_name_str) = file_name.to_str() {
|
{
|
||||||
if file_name_str == name && path.extension() == Some(OsStr::new("kpm")) {
|
return Ok(Some(p));
|
||||||
return Ok(Some(path));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 安全模式下删除所有 KPM 模块
|
|
||||||
pub fn remove_all_kpms() -> Result<()> {
|
pub fn remove_all_kpms() -> Result<()> {
|
||||||
let kpm_dir = Path::new(KPM_DIR);
|
let dir = Path::new(KPM_DIR);
|
||||||
if !kpm_dir.exists() {
|
if !dir.exists() {
|
||||||
log::info!("KPM: KPM directory does not exist, nothing to remove");
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
for entry in fs::read_dir(dir)? {
|
||||||
for entry in fs::read_dir(KPM_DIR)? {
|
let p = entry?.path();
|
||||||
let path = entry?.path();
|
if p.extension() == Some(OsStr::new("kpm")) {
|
||||||
if path.extension().is_some_and(|ext| ext == "kpm") {
|
if let Some(name) = p.file_stem().and_then(|s| s.to_str()) {
|
||||||
if let Some(name) = path.file_stem() {
|
if let Err(e) = unload_kpm(name) {
|
||||||
let name_str = name.to_string_lossy();
|
log::error!("KPM: Failed to unload {}: {}", name, e);
|
||||||
log::info!("KPM: Removing module in safe mode: {}", name_str);
|
|
||||||
if let Err(e) = unload_kpm(&name_str) {
|
|
||||||
log::error!("KPM: Failed to remove module {}: {}", name_str, e);
|
|
||||||
}
|
|
||||||
if let Err(e) = fs::remove_file(&path) {
|
|
||||||
log::error!("KPM: Failed to delete file {}: {}", path.display(), e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -244,53 +238,26 @@ pub fn remove_all_kpms() -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载所有 KPM 模块
|
|
||||||
pub fn load_kpm_modules() -> Result<()> {
|
pub fn load_kpm_modules() -> Result<()> {
|
||||||
match check_kpm_version() {
|
check_kpm_version()?;
|
||||||
Ok(version) => {
|
|
||||||
log::info!("KPM: Version check passed before loading modules, version: {}", version);
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
log::warn!("KPM: Version check failed, skipping module loading: {}", e);
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ensure_kpm_dir()?;
|
ensure_kpm_dir()?;
|
||||||
|
let dir = Path::new(KPM_DIR);
|
||||||
let kpm_dir = Path::new(KPM_DIR);
|
if !dir.exists() {
|
||||||
if !kpm_dir.exists() {
|
|
||||||
log::info!("KPM: KPM directory does not exist, no modules to load");
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
let (mut ok, mut ng) = (0, 0);
|
||||||
let mut loaded_count = 0;
|
for entry in fs::read_dir(dir)? {
|
||||||
let mut failed_count = 0;
|
let p = entry?.path();
|
||||||
|
if p.extension() == Some(OsStr::new("kpm")) {
|
||||||
for entry in std::fs::read_dir(KPM_DIR)? {
|
match load_kpm(&p) {
|
||||||
let path = entry?.path();
|
Ok(_) => ok += 1,
|
||||||
if let Some(file_name) = path.file_stem() {
|
|
||||||
if let Some(file_name_str) = file_name.to_str() {
|
|
||||||
if file_name_str.is_empty() {
|
|
||||||
log::warn!("KPM: Invalid KPM file name: {}", path.display());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if path.extension().is_some_and(|ext| ext == "kpm") {
|
|
||||||
match load_kpm(&path) {
|
|
||||||
Ok(()) => {
|
|
||||||
log::info!("KPM: Successfully loaded module: {}", path.display());
|
|
||||||
loaded_count += 1;
|
|
||||||
}
|
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::warn!("KPM: Failed to load module {}: {}", path.display(), e);
|
log::warn!("KPM: Failed to load {}: {}", p.display(), e);
|
||||||
failed_count += 1;
|
ng += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
log::info!("KPM: Load done – ok: {}, failed: {}", ok, ng);
|
||||||
log::info!("KPM: Module loading completed - loaded: {}, failed: {}", loaded_count, failed_count);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ mod cli;
|
|||||||
mod debug;
|
mod debug;
|
||||||
mod defs;
|
mod defs;
|
||||||
mod init_event;
|
mod init_event;
|
||||||
mod kpm;
|
|
||||||
mod ksucalls;
|
mod ksucalls;
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
mod magic_mount;
|
mod magic_mount;
|
||||||
@@ -16,6 +15,8 @@ mod sepolicy;
|
|||||||
mod su;
|
mod su;
|
||||||
mod utils;
|
mod utils;
|
||||||
mod uid_scanner;
|
mod uid_scanner;
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
mod kpm;
|
||||||
|
|
||||||
fn main() -> anyhow::Result<()> {
|
fn main() -> anyhow::Result<()> {
|
||||||
cli::run()
|
cli::run()
|
||||||
|
|||||||
Reference in New Issue
Block a user