fix lot (#518)
* refact: use feature subsystem * use 64bit feature * fix * add fixme * add feature max to get_info * use 32bit feature id * allow root to get/set feature * more clean perm_check functions * fix * add feature command to ksud kernel: do not expose perm checker * fix security_task_fix_setuid_handler_pre * add android16-6.12 ci * manager: add kernel_umount switch Co-authored-by: YuKongA <70465933+YuKongA@users.noreply.github.com> * manager: Reinstate the LKM selection function * kernel: add name and print command value - Optimise sulog log display Co-authored-by: Ylarod <me@ylarod.cn> Co-authored-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com> * fix * ksud: clippy --------- Co-authored-by: Ylarod <me@ylarod.cn> Co-authored-by: YuKongA <70465933+YuKongA@users.noreply.github.com> Co-authored-by: weishu <twsxtd@gmail.com>
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
#include <sys/prctl.h>
|
||||
#include <android/log.h>
|
||||
#include <string.h>
|
||||
#include <linux/capability.h>
|
||||
|
||||
NativeBridgeNP(getVersion, jint) {
|
||||
uint32_t version = get_version();
|
||||
@@ -300,6 +301,14 @@ NativeBridge(setSuEnabled, jboolean, jboolean enabled) {
|
||||
return set_su_enabled(enabled);
|
||||
}
|
||||
|
||||
NativeBridgeNP(isKernelUmountEnabled, jboolean) {
|
||||
return is_kernel_umount_enabled();
|
||||
}
|
||||
|
||||
NativeBridge(setKernelUmountEnabled, jboolean, jboolean enabled) {
|
||||
return set_kernel_umount_enabled(enabled);
|
||||
}
|
||||
|
||||
// Check if KPM is enabled
|
||||
NativeBridgeNP(isKPMEnabled, jboolean) {
|
||||
return is_KPM_enable();
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <android/log.h>
|
||||
#include <dirent.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <sys/syscall.h>
|
||||
|
||||
@@ -133,13 +134,56 @@ int get_app_profile(struct app_profile *profile) {
|
||||
}
|
||||
|
||||
bool set_su_enabled(bool enabled) {
|
||||
struct ksu_enable_su_cmd cmd = {.enable = enabled};
|
||||
return ksuctl(KSU_IOCTL_ENABLE_SU, &cmd) == 0;
|
||||
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;
|
||||
}
|
||||
|
||||
bool is_su_enabled() {
|
||||
struct ksu_is_su_enabled_cmd cmd = {};
|
||||
return ksuctl(KSU_IOCTL_IS_SU_ENABLED, &cmd) == 0 && cmd.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;
|
||||
}
|
||||
return cmd.value != 0;
|
||||
}
|
||||
|
||||
static inline bool get_feature(uint32_t feature_id, uint64_t *out_value, bool *out_supported) {
|
||||
struct ksu_get_feature_cmd cmd = {};
|
||||
cmd.feature_id = feature_id;
|
||||
if (ksuctl(KSU_IOCTL_GET_FEATURE, &cmd) != 0) {
|
||||
return false;
|
||||
}
|
||||
if (out_value) *out_value = cmd.value;
|
||||
if (out_supported) *out_supported = cmd.supported;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool set_feature(uint32_t feature_id, uint64_t value) {
|
||||
struct ksu_set_feature_cmd cmd = {};
|
||||
cmd.feature_id = feature_id;
|
||||
cmd.value = value;
|
||||
return ksuctl(KSU_IOCTL_SET_FEATURE, &cmd) == 0;
|
||||
}
|
||||
|
||||
bool set_kernel_umount_enabled(bool enabled) {
|
||||
return set_feature(KSU_FEATURE_KERNEL_UMOUNT, enabled ? 1 : 0);
|
||||
}
|
||||
|
||||
bool is_kernel_umount_enabled() {
|
||||
uint64_t value = 0;
|
||||
bool supported = false;
|
||||
if (!get_feature(KSU_FEATURE_KERNEL_UMOUNT, &value, &supported)) {
|
||||
return false;
|
||||
}
|
||||
if (!supported) {
|
||||
return false;
|
||||
}
|
||||
return value != 0;
|
||||
}
|
||||
|
||||
void get_full_version(char* buff) {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#define KERNELSU_KSU_H
|
||||
|
||||
#include "prelude.h"
|
||||
#include <linux/capability.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
@@ -105,10 +105,6 @@ bool set_app_profile(const struct app_profile* profile);
|
||||
|
||||
int get_app_profile(struct app_profile* profile);
|
||||
|
||||
bool set_su_enabled(bool enabled);
|
||||
|
||||
bool is_su_enabled();
|
||||
|
||||
bool is_KPM_enable();
|
||||
|
||||
void get_hook_type(char* hook_type);
|
||||
@@ -129,50 +125,69 @@ bool set_uid_scanner_enabled(bool enabled);
|
||||
|
||||
bool clear_uid_scanner_environment();
|
||||
|
||||
// Feature IDs
|
||||
enum ksu_feature_id {
|
||||
KSU_FEATURE_SU_COMPAT = 0,
|
||||
KSU_FEATURE_KERNEL_UMOUNT = 1,
|
||||
};
|
||||
|
||||
// Generic feature API
|
||||
struct ksu_get_feature_cmd {
|
||||
uint32_t feature_id; // Input: feature ID
|
||||
uint64_t value; // Output: feature value/state
|
||||
uint8_t supported; // Output: whether the feature is supported
|
||||
};
|
||||
|
||||
struct ksu_set_feature_cmd {
|
||||
uint32_t feature_id; // Input: feature ID
|
||||
uint64_t value; // Input: feature value/state to set
|
||||
};
|
||||
|
||||
struct ksu_become_daemon_cmd {
|
||||
__u8 token[65]; // Input: daemon token (null-terminated)
|
||||
uint8_t token[65]; // Input: daemon token (null-terminated)
|
||||
};
|
||||
|
||||
struct ksu_get_info_cmd {
|
||||
__u32 version; // Output: KERNEL_SU_VERSION
|
||||
__u32 flags; // Output: flags (bit 0: MODULE mode)
|
||||
uint32_t version; // Output: KERNEL_SU_VERSION
|
||||
uint32_t flags; // Output: flags (bit 0: MODULE mode)
|
||||
uint32_t features; // Output: max feature ID supported (KSU_FEATURE_MAX)
|
||||
};
|
||||
|
||||
struct ksu_report_event_cmd {
|
||||
__u32 event; // Input: EVENT_POST_FS_DATA, EVENT_BOOT_COMPLETED, etc.
|
||||
uint32_t event; // Input: EVENT_POST_FS_DATA, EVENT_BOOT_COMPLETED, etc.
|
||||
};
|
||||
|
||||
struct ksu_set_sepolicy_cmd {
|
||||
__u64 cmd; // Input: sepolicy command
|
||||
__aligned_u64 arg; // Input: sepolicy argument pointer
|
||||
uint64_t cmd; // Input: sepolicy command
|
||||
uint64_t arg; // Input: sepolicy argument pointer
|
||||
};
|
||||
|
||||
struct ksu_check_safemode_cmd {
|
||||
__u8 in_safe_mode; // Output: true if in safe mode, false otherwise
|
||||
uint8_t in_safe_mode; // Output: true if in safe mode, false otherwise
|
||||
};
|
||||
|
||||
struct ksu_get_allow_list_cmd {
|
||||
__u32 uids[128]; // Output: array of allowed/denied UIDs
|
||||
__u32 count; // Output: number of UIDs in array
|
||||
__u8 allow; // Input: true for allow list, false for deny list
|
||||
uint32_t uids[128]; // Output: array of allowed/denied UIDs
|
||||
uint32_t count; // Output: number of UIDs in array
|
||||
uint8_t allow; // Input: true for allow list, false for deny list
|
||||
};
|
||||
|
||||
struct ksu_uid_granted_root_cmd {
|
||||
__u32 uid; // Input: target UID to check
|
||||
__u8 granted; // Output: true if granted, false otherwise
|
||||
uint32_t uid; // Input: target UID to check
|
||||
uint8_t granted; // Output: true if granted, false otherwise
|
||||
};
|
||||
|
||||
struct ksu_uid_should_umount_cmd {
|
||||
__u32 uid; // Input: target UID to check
|
||||
__u8 should_umount; // Output: true if should umount, false otherwise
|
||||
uint32_t uid; // Input: target UID to check
|
||||
uint8_t should_umount; // Output: true if should umount, false otherwise
|
||||
};
|
||||
|
||||
struct ksu_get_manager_uid_cmd {
|
||||
__u32 uid; // Output: manager UID
|
||||
uint32_t uid; // Output: manager UID
|
||||
};
|
||||
|
||||
struct ksu_set_manager_uid_cmd {
|
||||
__u32 uid; // Input: new manager UID
|
||||
uint32_t uid; // Input: new manager UID
|
||||
};
|
||||
|
||||
struct ksu_get_app_profile_cmd {
|
||||
@@ -183,13 +198,13 @@ struct ksu_set_app_profile_cmd {
|
||||
struct app_profile profile; // Input: app profile structure
|
||||
};
|
||||
|
||||
struct ksu_is_su_enabled_cmd {
|
||||
__u8 enabled; // Output: true if su compat enabled
|
||||
};
|
||||
// Su compat
|
||||
bool set_su_enabled(bool enabled);
|
||||
bool is_su_enabled();
|
||||
|
||||
struct ksu_enable_su_cmd {
|
||||
__u8 enable; // Input: true to enable, false to disable
|
||||
};
|
||||
// Kernel umount
|
||||
bool set_kernel_umount_enabled(bool enabled);
|
||||
bool is_kernel_umount_enabled();
|
||||
|
||||
// Other command structures
|
||||
struct ksu_get_full_version_cmd {
|
||||
@@ -201,7 +216,7 @@ struct ksu_hook_type_cmd {
|
||||
};
|
||||
|
||||
struct ksu_enable_kpm_cmd {
|
||||
__u8 enabled; // Output: true if KPM is enabled
|
||||
uint8_t enabled; // Output: true if KPM is enabled
|
||||
};
|
||||
|
||||
struct ksu_dynamic_manager_cmd {
|
||||
@@ -213,9 +228,9 @@ struct ksu_get_managers_cmd {
|
||||
};
|
||||
|
||||
struct ksu_enable_uid_scanner_cmd {
|
||||
__u32 operation; // Input: operation type (UID_SCANNER_OP_GET_STATUS, UID_SCANNER_OP_TOGGLE, UID_SCANNER_OP_CLEAR_ENV)
|
||||
__u32 enabled; // Input: enable or disable (for UID_SCANNER_OP_TOGGLE)
|
||||
__u64 status_ptr; // Input: pointer to store status (for UID_SCANNER_OP_GET_STATUS)
|
||||
uint32_t operation; // Input: operation type (UID_SCANNER_OP_GET_STATUS, UID_SCANNER_OP_TOGGLE, UID_SCANNER_OP_CLEAR_ENV)
|
||||
uint32_t enabled; // Input: enable or disable (for UID_SCANNER_OP_TOGGLE)
|
||||
uint64_t status_ptr; // Input: pointer to store status (for UID_SCANNER_OP_GET_STATUS)
|
||||
};
|
||||
|
||||
// IOCTL command definitions
|
||||
@@ -231,8 +246,8 @@ struct ksu_enable_uid_scanner_cmd {
|
||||
#define KSU_IOCTL_GET_MANAGER_UID _IOR('K', 10, struct ksu_get_manager_uid_cmd)
|
||||
#define KSU_IOCTL_GET_APP_PROFILE _IOWR('K', 11, struct ksu_get_app_profile_cmd)
|
||||
#define KSU_IOCTL_SET_APP_PROFILE _IOW('K', 12, struct ksu_set_app_profile_cmd)
|
||||
#define KSU_IOCTL_IS_SU_ENABLED _IOR('K', 13, struct ksu_is_su_enabled_cmd)
|
||||
#define KSU_IOCTL_ENABLE_SU _IOW('K', 14, struct ksu_enable_su_cmd)
|
||||
#define KSU_IOCTL_GET_FEATURE _IOWR('K', 13, struct ksu_get_feature_cmd)
|
||||
#define KSU_IOCTL_SET_FEATURE _IOW('K', 14, struct ksu_set_feature_cmd)
|
||||
|
||||
// Other IOCTL command definitions
|
||||
#define KSU_IOCTL_GET_FULL_VERSION _IOR('K', 100, struct ksu_get_full_version_cmd)
|
||||
|
||||
@@ -98,7 +98,16 @@ object Natives {
|
||||
*/
|
||||
external fun isSuEnabled(): Boolean
|
||||
external fun setSuEnabled(enabled: Boolean): Boolean
|
||||
external fun grantRoot(): Boolean
|
||||
|
||||
/**
|
||||
* Kernel module umount can be disabled temporarily.
|
||||
* 0: disabled
|
||||
* 1: enabled
|
||||
* negative : error
|
||||
*/
|
||||
external fun isKernelUmountEnabled(): Boolean
|
||||
external fun setKernelUmountEnabled(enabled: Boolean): Boolean
|
||||
|
||||
external fun isKPMEnabled(): Boolean
|
||||
external fun getHookType(): String
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import androidx.compose.foundation.selection.selectable
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material.icons.automirrored.filled.Input
|
||||
import androidx.compose.material.icons.filled.AutoFixHigh
|
||||
import androidx.compose.material.icons.filled.FileUpload
|
||||
import androidx.compose.material.icons.filled.Security
|
||||
@@ -205,12 +206,29 @@ fun InstallScreen(
|
||||
}
|
||||
}
|
||||
|
||||
val selectLkmLauncher = rememberLauncherForActivityResult(
|
||||
contract = ActivityResultContracts.StartActivityForResult()
|
||||
) {
|
||||
if (it.resultCode == Activity.RESULT_OK) {
|
||||
it.data?.data?.let { uri ->
|
||||
lkmSelection = LkmSelection.LkmUri(uri)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val onLkmUpload = {
|
||||
selectLkmLauncher.launch(Intent(Intent.ACTION_GET_CONTENT).apply {
|
||||
type = "application/octet-stream"
|
||||
})
|
||||
}
|
||||
|
||||
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
TopBar(
|
||||
onBack = { navigator.popBackStack() },
|
||||
onLkmUpload = onLkmUpload,
|
||||
scrollBehavior = scrollBehavior
|
||||
)
|
||||
},
|
||||
@@ -934,6 +952,7 @@ fun rememberSelectKmiDialog(onSelected: (String?) -> Unit): DialogHandle {
|
||||
@Composable
|
||||
private fun TopBar(
|
||||
onBack: () -> Unit = {},
|
||||
onLkmUpload: () -> Unit = {},
|
||||
scrollBehavior: TopAppBarScrollBehavior? = null
|
||||
) {
|
||||
val colorScheme = MaterialTheme.colorScheme
|
||||
@@ -966,6 +985,17 @@ private fun TopBar(
|
||||
windowInsets = WindowInsets.safeDrawing.only(
|
||||
WindowInsetsSides.Top + WindowInsetsSides.Horizontal
|
||||
),
|
||||
actions = {
|
||||
IconButton(
|
||||
modifier = Modifier.padding(end = 16.dp),
|
||||
onClick = onLkmUpload
|
||||
) {
|
||||
Icon(
|
||||
Icons.AutoMirrored.Filled.Input,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
},
|
||||
scrollBehavior = scrollBehavior
|
||||
)
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.Undo
|
||||
import androidx.compose.material.icons.filled.*
|
||||
import androidx.compose.material.icons.rounded.FolderDelete
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
@@ -165,6 +166,23 @@ fun SettingScreen(navigator: DestinationsNavigator) {
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
var isKernelUmountDisabled by rememberSaveable {
|
||||
mutableStateOf(!Natives.isKernelUmountEnabled())
|
||||
}
|
||||
SwitchItem(
|
||||
icon = Icons.Rounded.FolderDelete,
|
||||
title = stringResource(id = R.string.settings_disable_kernel_umount),
|
||||
summary = stringResource(id = R.string.settings_disable_kernel_umount_summary),
|
||||
checked = isKernelUmountDisabled,
|
||||
onCheckedChange = { checked: Boolean ->
|
||||
val shouldEnable = !checked
|
||||
if (Natives.setKernelUmountEnabled(shouldEnable)) {
|
||||
isKernelUmountDisabled = !shouldEnable
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
// 强制签名验证开关
|
||||
var forceSignatureVerification by rememberSaveable {
|
||||
mutableStateOf(prefs.getBoolean("force_signature_verification", false))
|
||||
|
||||
@@ -164,6 +164,8 @@
|
||||
<string name="su_not_allowed">不允许授予 %s 超级用户权限</string>
|
||||
<string name="settings_disable_su">禁用 su 兼容性</string>
|
||||
<string name="settings_disable_su_summary">临时禁止任何应用程序通过 su 命令获取 Root 权限(现有的 Root 进程不受影响)</string>
|
||||
<string name="settings_disable_kernel_umount">关闭内核 umount</string>
|
||||
<string name="settings_disable_kernel_umount_summary">临时关闭 KernelSU 控制的内核级 umount 行为。</string>
|
||||
<string name="module_install_multiple_confirm_with_names">确定要安装以下 %1$d 个模块吗?\n\n%2$s</string>
|
||||
<string name="more_settings">更多设置</string>
|
||||
<string name="selinux">SELinux</string>
|
||||
|
||||
@@ -166,6 +166,8 @@
|
||||
<string name="su_not_allowed">Granting superuser to %s is not allowed</string>
|
||||
<string name="settings_disable_su">Disable su compatibility</string>
|
||||
<string name="settings_disable_su_summary">Temporarily disable any applications from obtaining root privileges via the su command (Existing root processes will not be affected)</string>
|
||||
<string name="settings_disable_kernel_umount">Disable kernel umount</string>
|
||||
<string name="settings_disable_kernel_umount_summary">Temporarily disable kernel-level umount behavior controlled by KernelSU.</string>
|
||||
<string name="module_install_multiple_confirm_with_names">Sure you want to install the following %1$d modules? \n\n%2$s</string>
|
||||
<string name="more_settings">More settings</string>
|
||||
<string name="selinux">SELinux</string>
|
||||
|
||||
Reference in New Issue
Block a user