manager: Provide backward compatibility for legacy kernels
This commit is contained in:
@@ -10,6 +10,7 @@ add_library(kernelsu
|
||||
SHARED
|
||||
jni.c
|
||||
ksu.c
|
||||
legacy.c
|
||||
)
|
||||
|
||||
find_library(log-lib log)
|
||||
|
||||
@@ -90,29 +90,38 @@ uint32_t get_version() {
|
||||
return info.version;
|
||||
}
|
||||
|
||||
struct ksu_version_info legacy_get_info()
|
||||
{
|
||||
int32_t version = -1;
|
||||
int32_t flags = 0;
|
||||
ksuctl_prctl(CMD_GET_VERSION, &version, &flags);
|
||||
return (struct ksu_version_info){version, flags};
|
||||
bool get_allow_list(struct ksu_get_allow_list_cmd *cmd) {
|
||||
if (ksuctl(KSU_IOCTL_GET_ALLOW_LIST, cmd) == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool get_allow_list(struct ksu_get_allow_list_cmd *cmd) {
|
||||
return ksuctl(KSU_IOCTL_GET_ALLOW_LIST, cmd) == 0;
|
||||
// fallback to legacy
|
||||
int size = 0;
|
||||
int uids[1024];
|
||||
if (legacy_get_allow_list(uids, &size)) {
|
||||
cmd->count = size;
|
||||
memcpy(cmd->uids, uids, sizeof(int) * size);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_safe_mode() {
|
||||
struct ksu_check_safemode_cmd cmd = {};
|
||||
ksuctl(KSU_IOCTL_CHECK_SAFEMODE, &cmd);
|
||||
if (ksuctl(KSU_IOCTL_CHECK_SAFEMODE, &cmd) == 0) {
|
||||
return cmd.in_safe_mode;
|
||||
}
|
||||
// fallback
|
||||
return legacy_is_safe_mode();
|
||||
}
|
||||
|
||||
bool is_lkm_mode() {
|
||||
auto info = get_info();
|
||||
if (info.version > 0) {
|
||||
return (info.flags & 0x1) != 0;
|
||||
}
|
||||
// Legacy Compatible
|
||||
return (legacy_get_info().flags & 0x1) != 0;
|
||||
}
|
||||
|
||||
@@ -121,47 +130,56 @@ bool is_manager() {
|
||||
if (info.version > 0) {
|
||||
return (info.flags & 0x2) != 0;
|
||||
}
|
||||
// Legacy Compatible
|
||||
return legacy_get_info().version;
|
||||
}
|
||||
|
||||
bool uid_should_umount(int uid) {
|
||||
struct ksu_uid_should_umount_cmd cmd = {};
|
||||
cmd.uid = uid;
|
||||
ksuctl(KSU_IOCTL_UID_SHOULD_UMOUNT, &cmd);
|
||||
if (ksuctl(KSU_IOCTL_UID_SHOULD_UMOUNT, &cmd) == 0) {
|
||||
return cmd.should_umount;
|
||||
}
|
||||
return legacy_uid_should_umount(uid);
|
||||
}
|
||||
|
||||
bool set_app_profile(const struct app_profile *profile) {
|
||||
struct ksu_set_app_profile_cmd cmd = {};
|
||||
cmd.profile = *profile;
|
||||
return ksuctl(KSU_IOCTL_SET_APP_PROFILE, &cmd) == 0;
|
||||
if (ksuctl(KSU_IOCTL_SET_APP_PROFILE, &cmd) == 0) {
|
||||
return true;
|
||||
}
|
||||
return legacy_set_app_profile(profile);
|
||||
}
|
||||
|
||||
int get_app_profile(struct app_profile *profile) {
|
||||
struct ksu_get_app_profile_cmd cmd = {.profile = *profile};
|
||||
int ret = ksuctl(KSU_IOCTL_GET_APP_PROFILE, &cmd);
|
||||
if (ret == 0) {
|
||||
*profile = cmd.profile;
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
return legacy_get_app_profile(profile->key, profile) ? 0 : -1;
|
||||
}
|
||||
|
||||
bool set_su_enabled(bool enabled) {
|
||||
struct ksu_set_feature_cmd cmd = {};
|
||||
cmd.feature_id = KSU_FEATURE_SU_COMPAT;
|
||||
cmd.value = enabled ? 1 : 0;
|
||||
return ksuctl(KSU_IOCTL_SET_FEATURE, &cmd) == 0;
|
||||
if (ksuctl(KSU_IOCTL_SET_FEATURE, &cmd) == 0) {
|
||||
return true;
|
||||
}
|
||||
return legacy_set_su_enabled(enabled);
|
||||
}
|
||||
|
||||
bool is_su_enabled() {
|
||||
struct ksu_get_feature_cmd cmd = {};
|
||||
cmd.feature_id = KSU_FEATURE_SU_COMPAT;
|
||||
if (ksuctl(KSU_IOCTL_GET_FEATURE, &cmd) != 0) {
|
||||
return false;
|
||||
}
|
||||
if (!cmd.supported) {
|
||||
return false;
|
||||
}
|
||||
if (ksuctl(KSU_IOCTL_GET_FEATURE, &cmd) == 0 && cmd.supported) {
|
||||
return cmd.value != 0;
|
||||
}
|
||||
return legacy_is_su_enabled();
|
||||
}
|
||||
|
||||
static inline bool get_feature(uint32_t feature_id, uint64_t *out_value, bool *out_supported) {
|
||||
struct ksu_get_feature_cmd cmd = {};
|
||||
@@ -196,7 +214,7 @@ bool is_kernel_umount_enabled() {
|
||||
}
|
||||
return value != 0;
|
||||
}
|
||||
|
||||
// 1. 获取完整版本名称
|
||||
void get_full_version(char* buff) {
|
||||
struct ksu_get_full_version_cmd cmd = {0};
|
||||
if (ksuctl(KSU_IOCTL_GET_FULL_VERSION, &cmd) == 0) {
|
||||
@@ -207,24 +225,23 @@ void get_full_version(char* buff) {
|
||||
}
|
||||
}
|
||||
|
||||
void legacy_get_full_version(char* buff) {
|
||||
ksuctl_prctl(CMD_GET_VERSION_FULL, buff, NULL);
|
||||
}
|
||||
|
||||
bool is_KPM_enable(void)
|
||||
{
|
||||
// 2. 获取KPM启用状态
|
||||
bool is_KPM_enable(void) {
|
||||
struct ksu_enable_kpm_cmd cmd = {};
|
||||
return ksuctl(KSU_IOCTL_ENABLE_KPM, &cmd) == 0 && cmd.enabled;
|
||||
if (ksuctl(KSU_IOCTL_ENABLE_KPM, &cmd) == 0 && cmd.enabled) {
|
||||
return true;
|
||||
}
|
||||
return legacy_is_KPM_enable();
|
||||
}
|
||||
|
||||
void get_hook_type(char *buff)
|
||||
{
|
||||
// 3. 获取钩子类型
|
||||
void get_hook_type(char *buff) {
|
||||
struct ksu_hook_type_cmd cmd = {0};
|
||||
if (ksuctl(KSU_IOCTL_HOOK_TYPE, &cmd) == 0) {
|
||||
strncpy(buff, cmd.hook_type, 32 - 1);
|
||||
buff[32 - 1] = '\0';
|
||||
} else {
|
||||
strcpy(buff, "Unknown");
|
||||
legacy_get_hook_type(buff, 32);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,6 +289,34 @@ bool get_managers_list(struct manager_list_info *info)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is_uid_scanner_enabled(void)
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
struct ksu_enable_uid_scanner_cmd cmd = {
|
||||
.operation = UID_SCANNER_OP_GET_STATUS,
|
||||
.status_ptr = (__u64)(uintptr_t)&status
|
||||
};
|
||||
|
||||
return ksuctl(KSU_IOCTL_ENABLE_UID_SCANNER, &cmd) == 0 != 0 && status;
|
||||
}
|
||||
|
||||
bool set_uid_scanner_enabled(bool enabled)
|
||||
{
|
||||
struct ksu_enable_uid_scanner_cmd cmd = {
|
||||
.operation = UID_SCANNER_OP_TOGGLE,
|
||||
.enabled = enabled
|
||||
};
|
||||
return ksuctl(KSU_IOCTL_ENABLE_UID_SCANNER, &cmd);
|
||||
}
|
||||
|
||||
bool clear_uid_scanner_environment(void)
|
||||
{
|
||||
struct ksu_enable_uid_scanner_cmd cmd = {
|
||||
.operation = UID_SCANNER_OP_CLEAR_ENV
|
||||
};
|
||||
return ksuctl(KSU_IOCTL_ENABLE_UID_SCANNER, &cmd);
|
||||
}
|
||||
|
||||
bool verify_module_signature(const char* input) {
|
||||
#if defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM)
|
||||
@@ -329,32 +374,3 @@ bool verify_module_signature(const char* input) {
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool is_uid_scanner_enabled(void)
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
struct ksu_enable_uid_scanner_cmd cmd = {
|
||||
.operation = UID_SCANNER_OP_GET_STATUS,
|
||||
.status_ptr = (__u64)(uintptr_t)&status
|
||||
};
|
||||
|
||||
return ksuctl(KSU_IOCTL_ENABLE_UID_SCANNER, &cmd) == 0 != 0 && status;
|
||||
}
|
||||
|
||||
bool set_uid_scanner_enabled(bool enabled)
|
||||
{
|
||||
struct ksu_enable_uid_scanner_cmd cmd = {
|
||||
.operation = UID_SCANNER_OP_TOGGLE,
|
||||
.enabled = enabled
|
||||
};
|
||||
return ksuctl(KSU_IOCTL_ENABLE_UID_SCANNER, &cmd);
|
||||
}
|
||||
|
||||
bool clear_uid_scanner_environment(void)
|
||||
{
|
||||
struct ksu_enable_uid_scanner_cmd cmd = {
|
||||
.operation = UID_SCANNER_OP_CLEAR_ENV
|
||||
};
|
||||
return ksuctl(KSU_IOCTL_ENABLE_UID_SCANNER, &cmd);
|
||||
}
|
||||
@@ -12,40 +12,6 @@
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#define KERNEL_SU_OPTION 0xDEADBEEF
|
||||
|
||||
#define CMD_GRANT_ROOT 0
|
||||
|
||||
#define CMD_BECOME_MANAGER 1
|
||||
#define CMD_GET_VERSION 2
|
||||
#define CMD_ALLOW_SU 3
|
||||
#define CMD_DENY_SU 4
|
||||
#define CMD_GET_SU_LIST 5
|
||||
#define CMD_GET_DENY_LIST 6
|
||||
#define CMD_CHECK_SAFEMODE 9
|
||||
|
||||
#define CMD_GET_APP_PROFILE 10
|
||||
#define CMD_SET_APP_PROFILE 11
|
||||
|
||||
#define CMD_IS_UID_GRANTED_ROOT 12
|
||||
#define CMD_IS_UID_SHOULD_UMOUNT 13
|
||||
#define CMD_IS_SU_ENABLED 14
|
||||
#define CMD_ENABLE_SU 15
|
||||
|
||||
#define CMD_GET_VERSION_FULL 0xC0FFEE1A
|
||||
|
||||
#define CMD_ENABLE_KPM 100
|
||||
#define CMD_HOOK_TYPE 101
|
||||
#define CMD_DYNAMIC_MANAGER 103
|
||||
#define CMD_GET_MANAGERS 104
|
||||
#define CMD_ENABLE_UID_SCANNER 105
|
||||
|
||||
static inline bool ksuctl_prctl(int cmd, void* arg1, void* arg2) {
|
||||
int32_t result = 0;
|
||||
int32_t rtn = prctl(KERNEL_SU_OPTION, cmd, arg1, arg2, &result);
|
||||
return result == KERNEL_SU_OPTION && rtn == -1;
|
||||
}
|
||||
|
||||
#define KSU_FULL_VERSION_STRING 255
|
||||
|
||||
uint32_t get_version();
|
||||
@@ -59,7 +25,6 @@ bool is_lkm_mode();
|
||||
bool is_manager();
|
||||
|
||||
void get_full_version(char* buff);
|
||||
void legacy_get_full_version(char* buff);
|
||||
|
||||
#define KSU_APP_PROFILE_VER 2
|
||||
#define KSU_MAX_PACKAGE_NAME 256
|
||||
@@ -296,6 +261,7 @@ struct ksu_enable_uid_scanner_cmd {
|
||||
|
||||
bool get_allow_list(struct ksu_get_allow_list_cmd *);
|
||||
|
||||
// Legacy Compatible
|
||||
struct ksu_version_info legacy_get_info();
|
||||
|
||||
struct ksu_version_info {
|
||||
@@ -303,4 +269,22 @@ struct ksu_version_info {
|
||||
int32_t flags;
|
||||
};
|
||||
|
||||
bool legacy_get_allow_list(int *uids, int *size);
|
||||
bool legacy_is_safe_mode();
|
||||
bool legacy_uid_should_umount(int uid);
|
||||
bool legacy_set_app_profile(const struct app_profile* profile);
|
||||
bool legacy_get_app_profile(char* key, struct app_profile* profile);
|
||||
bool legacy_set_su_enabled(bool enabled);
|
||||
bool legacy_is_su_enabled();
|
||||
bool legacy_is_KPM_enable();
|
||||
bool legacy_get_hook_type(char* hook_type, size_t size);
|
||||
void legacy_get_full_version(char* buff);
|
||||
bool legacy_set_dynamic_manager(unsigned int size, const char* hash);
|
||||
bool legacy_get_dynamic_manager(struct dynamic_manager_user_config* config);
|
||||
bool legacy_clear_dynamic_manager();
|
||||
bool legacy_get_managers_list(struct manager_list_info* info);
|
||||
bool legacy_is_uid_scanner_enabled();
|
||||
bool legacy_set_uid_scanner_enabled(bool enabled);
|
||||
bool legacy_clear_uid_scanner_environment();
|
||||
|
||||
#endif //KERNELSU_KSU_H
|
||||
163
manager/app/src/main/cpp/legacy.c
Normal file
163
manager/app/src/main/cpp/legacy.c
Normal file
@@ -0,0 +1,163 @@
|
||||
//
|
||||
// Created by shirkneko on 2025/11/3.
|
||||
//
|
||||
// Legacy Compatible
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <android/log.h>
|
||||
#include <dirent.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "prelude.h"
|
||||
#include "ksu.h"
|
||||
|
||||
#define KERNEL_SU_OPTION 0xDEADBEEF
|
||||
|
||||
#define CMD_GRANT_ROOT 0
|
||||
|
||||
#define CMD_BECOME_MANAGER 1
|
||||
#define CMD_GET_VERSION 2
|
||||
#define CMD_ALLOW_SU 3
|
||||
#define CMD_DENY_SU 4
|
||||
#define CMD_GET_SU_LIST 5
|
||||
#define CMD_GET_DENY_LIST 6
|
||||
#define CMD_CHECK_SAFEMODE 9
|
||||
|
||||
#define CMD_GET_APP_PROFILE 10
|
||||
#define CMD_SET_APP_PROFILE 11
|
||||
|
||||
#define CMD_IS_UID_GRANTED_ROOT 12
|
||||
#define CMD_IS_UID_SHOULD_UMOUNT 13
|
||||
#define CMD_IS_SU_ENABLED 14
|
||||
#define CMD_ENABLE_SU 15
|
||||
|
||||
#define CMD_GET_VERSION_FULL 0xC0FFEE1A
|
||||
|
||||
#define CMD_ENABLE_KPM 100
|
||||
#define CMD_HOOK_TYPE 101
|
||||
#define CMD_DYNAMIC_MANAGER 103
|
||||
#define CMD_GET_MANAGERS 104
|
||||
#define CMD_ENABLE_UID_SCANNER 105
|
||||
|
||||
static bool ksuctl(int cmd, void* arg1, void* arg2) {
|
||||
int32_t result = 0;
|
||||
int32_t rtn = prctl(KERNEL_SU_OPTION, cmd, arg1, arg2, &result);
|
||||
return result == KERNEL_SU_OPTION && rtn == -1;
|
||||
}
|
||||
|
||||
struct ksu_version_info legacy_get_info()
|
||||
{
|
||||
int32_t version = -1;
|
||||
int32_t flags = 0;
|
||||
ksuctl(CMD_GET_VERSION, &version, &flags);
|
||||
return (struct ksu_version_info){version, flags};
|
||||
}
|
||||
|
||||
bool legacy_get_allow_list(int *uids, int *size) {
|
||||
return ksuctl(CMD_GET_SU_LIST, uids, size);
|
||||
}
|
||||
|
||||
bool legacy_is_safe_mode() {
|
||||
return ksuctl(CMD_CHECK_SAFEMODE, NULL, NULL);
|
||||
}
|
||||
|
||||
bool legacy_uid_should_umount(int uid) {
|
||||
int should;
|
||||
return ksuctl(CMD_IS_UID_SHOULD_UMOUNT, (void*) ((size_t) uid), &should) && should;
|
||||
}
|
||||
|
||||
bool legacy_set_app_profile(const struct app_profile* profile) {
|
||||
return ksuctl(CMD_SET_APP_PROFILE, (void*) profile, NULL);
|
||||
}
|
||||
|
||||
bool legacy_get_app_profile(char* key, struct app_profile* profile) {
|
||||
return ksuctl(CMD_GET_APP_PROFILE, profile, NULL);
|
||||
}
|
||||
|
||||
bool legacy_set_su_enabled(bool enabled) {
|
||||
return ksuctl(CMD_ENABLE_SU, (void*) enabled, NULL);
|
||||
}
|
||||
|
||||
bool legacy_is_su_enabled() {
|
||||
int enabled = true;
|
||||
// if ksuctl failed, we assume su is enabled, and it cannot be disabled.
|
||||
ksuctl(CMD_IS_SU_ENABLED, &enabled, NULL);
|
||||
return enabled;
|
||||
}
|
||||
|
||||
bool legacy_is_KPM_enable() {
|
||||
int enabled = false;
|
||||
ksuctl(CMD_ENABLE_KPM, &enabled, NULL);
|
||||
return enabled;
|
||||
}
|
||||
|
||||
bool legacy_get_hook_type(char* hook_type, size_t size) {
|
||||
if (hook_type == NULL || size == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static char cached_hook_type[16] = {0};
|
||||
if (cached_hook_type[0] == '\0') {
|
||||
if (!ksuctl(CMD_HOOK_TYPE, cached_hook_type, NULL)) {
|
||||
strcpy(cached_hook_type, "Unknown");
|
||||
}
|
||||
}
|
||||
|
||||
strncpy(hook_type, cached_hook_type, size - 1);
|
||||
hook_type[size - 1] = '\0';
|
||||
return true;
|
||||
}
|
||||
|
||||
void legacy_get_full_version(char* buff) {
|
||||
ksuctl(CMD_GET_VERSION_FULL, buff, NULL);
|
||||
}
|
||||
|
||||
bool legacy_set_dynamic_manager(unsigned int size, const char* hash) {
|
||||
if (hash == NULL) {
|
||||
return false;
|
||||
}
|
||||
struct dynamic_manager_user_config config;
|
||||
config.operation = DYNAMIC_MANAGER_OP_SET;
|
||||
config.size = size;
|
||||
strncpy(config.hash, hash, sizeof(config.hash) - 1);
|
||||
config.hash[sizeof(config.hash) - 1] = '\0';
|
||||
return ksuctl(CMD_DYNAMIC_MANAGER, &config, NULL);
|
||||
}
|
||||
|
||||
bool legacy_get_dynamic_manager(struct dynamic_manager_user_config* config) {
|
||||
if (config == NULL) {
|
||||
return false;
|
||||
}
|
||||
config->operation = DYNAMIC_MANAGER_OP_GET;
|
||||
return ksuctl(CMD_DYNAMIC_MANAGER, config, NULL);
|
||||
}
|
||||
|
||||
bool legacy_clear_dynamic_manager() {
|
||||
struct dynamic_manager_user_config config;
|
||||
config.operation = DYNAMIC_MANAGER_OP_CLEAR;
|
||||
return ksuctl(CMD_DYNAMIC_MANAGER, &config, NULL);
|
||||
}
|
||||
|
||||
bool legacy_get_managers_list(struct manager_list_info* info) {
|
||||
if (info == NULL) {
|
||||
return false;
|
||||
}
|
||||
return ksuctl(CMD_GET_MANAGERS, info, NULL);
|
||||
}
|
||||
|
||||
bool legacy_is_uid_scanner_enabled() {
|
||||
bool status = false;
|
||||
ksuctl(CMD_ENABLE_UID_SCANNER, (void*)0, &status);
|
||||
return status;
|
||||
}
|
||||
|
||||
bool legacy_set_uid_scanner_enabled(bool enabled) {
|
||||
return ksuctl(CMD_ENABLE_UID_SCANNER, (void*)1, (void*)enabled);
|
||||
}
|
||||
|
||||
bool legacy_clear_uid_scanner_environment() {
|
||||
return ksuctl(CMD_ENABLE_UID_SCANNER, (void*)2, NULL);
|
||||
}
|
||||
Reference in New Issue
Block a user