diff --git a/.github/workflows/build-manager.yml b/.github/workflows/build-manager.yml index c40a756f..212a7194 100644 --- a/.github/workflows/build-manager.yml +++ b/.github/workflows/build-manager.yml @@ -33,6 +33,17 @@ jobs: with: os: ${{ matrix.os }} + build-kpmmgr: + needs: build-lkm + strategy: + matrix: + include: + - target: aarch64-linux-android + os: ubuntu-latest + uses: ./.github/workflows/kpmmgr.yml + with: + os: ${{ matrix.os }} + build-ksud: needs: build-susfsd strategy: @@ -109,6 +120,16 @@ jobs: mkdir -p app/src/main/jniLibs/x86_64 cp -f ../x86_64/susfsd ../manager/app/src/main/jniLibs/x86_64/libsusfsd.so + - name: Download arm64 kpmmgr + uses: actions/download-artifact@v4 + with: + name: kpmmgr-aarch64-linux-android + path: . + + - 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: Download arm64 ksud_overlayfs uses: actions/download-artifact@v4 diff --git a/.github/workflows/kpmmgr.yml b/.github/workflows/kpmmgr.yml new file mode 100644 index 00000000..18ba4513 --- /dev/null +++ b/.github/workflows/kpmmgr.yml @@ -0,0 +1,40 @@ +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 diff --git a/userspace/kpmmgr/.gitignore b/userspace/kpmmgr/.gitignore new file mode 100644 index 00000000..4b4ce0f2 --- /dev/null +++ b/userspace/kpmmgr/.gitignore @@ -0,0 +1,2 @@ +/obj +/libs \ No newline at end of file diff --git a/userspace/kpmmgr/jni/Android.mk b/userspace/kpmmgr/jni/Android.mk new file mode 100644 index 00000000..a278158f --- /dev/null +++ b/userspace/kpmmgr/jni/Android.mk @@ -0,0 +1,6 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := kpmmgr +LOCAL_SRC_FILES := kpmmgr.c +include $(BUILD_EXECUTABLE) diff --git a/userspace/kpmmgr/jni/Application.mk b/userspace/kpmmgr/jni/Application.mk new file mode 100644 index 00000000..61d31236 --- /dev/null +++ b/userspace/kpmmgr/jni/Application.mk @@ -0,0 +1,3 @@ +APP_ABI := arm64-v8a +APP_PLATFORM := android-24 +APP_STL := none diff --git a/userspace/kpmmgr/jni/kpmmgr.c b/userspace/kpmmgr/jni/kpmmgr.c new file mode 100644 index 00000000..7c4d9a7f --- /dev/null +++ b/userspace/kpmmgr/jni/kpmmgr.c @@ -0,0 +1,118 @@ +#include +#include +#include +#include +#include +#include + +#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 [args]\n", prog); + printf("Commands:\n"); + printf(" load Load a KPM module\n"); + printf(" unload Unload a KPM module\n"); + printf(" num Get number of loaded modules\n"); + printf(" list List loaded KPM modules\n"); + printf(" info Get info of a KPM module\n"); + printf(" control 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; +}