From c4d8c49e5c88532407d80e0be99ca282b7222af3 Mon Sep 17 00:00:00 2001 From: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com> Date: Sun, 16 Nov 2025 16:53:55 +0800 Subject: [PATCH] kernel/manager/ksud: Add switch functionality to sulog Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com> --- kernel/feature.h | 1 + kernel/manual_su.c | 1 + kernel/sulog.c | 30 ++++++++- manager/app/src/main/cpp/jni.c | 8 +++ manager/app/src/main/cpp/ksu.c | 16 +++++ manager/app/src/main/cpp/ksu.h | 6 +- .../src/main/java/com/sukisu/ultra/Natives.kt | 9 +++ .../com/sukisu/ultra/ui/screen/Settings.kt | 62 ++++++++++++++++--- .../src/main/res/values-zh-rCN/strings.xml | 2 + manager/app/src/main/res/values/strings.xml | 2 + userspace/ksud/src/feature.rs | 9 +++ 11 files changed, 135 insertions(+), 11 deletions(-) diff --git a/kernel/feature.h b/kernel/feature.h index d9cbc92a..9b63a0b2 100644 --- a/kernel/feature.h +++ b/kernel/feature.h @@ -7,6 +7,7 @@ enum ksu_feature_id { KSU_FEATURE_SU_COMPAT = 0, KSU_FEATURE_KERNEL_UMOUNT = 1, KSU_FEATURE_ENHANCED_SECURITY = 2, + KSU_FEATURE_SULOG = 3, KSU_FEATURE_MAX }; diff --git a/kernel/manual_su.c b/kernel/manual_su.c index 578c1497..dfb3a251 100644 --- a/kernel/manual_su.c +++ b/kernel/manual_su.c @@ -8,6 +8,7 @@ #include #include #include + #include "manual_su.h" #include "ksu.h" #include "allowlist.h" diff --git a/kernel/sulog.c b/kernel/sulog.c index ce00d7c2..55232ce8 100644 --- a/kernel/sulog.c +++ b/kernel/sulog.c @@ -17,6 +17,7 @@ #include "sulog.h" #include "ksu.h" +#include "feature.h" #if __SULOG_GATE @@ -25,7 +26,28 @@ static DEFINE_SPINLOCK(dedup_lock); static LIST_HEAD(sulog_queue); static struct workqueue_struct *sulog_workqueue; static struct work_struct sulog_work; -static bool sulog_enabled = true; +static bool sulog_enabled __read_mostly = true; + +static int sulog_feature_get(u64 *value) +{ + *value = sulog_enabled ? 1 : 0; + return 0; +} + +static int sulog_feature_set(u64 value) +{ + bool enable = value != 0; + sulog_enabled = enable; + pr_info("sulog: set to %d\n", enable); + return 0; +} + +static const struct ksu_feature_handler sulog_handler = { + .feature_id = KSU_FEATURE_SULOG, + .name = "sulog", + .get_handler = sulog_feature_get, + .set_handler = sulog_feature_set, +}; static void get_timestamp(char *buf, size_t len) { @@ -304,6 +326,10 @@ void ksu_sulog_report_syscall(uid_t uid, const char *comm, const char *syscall, int ksu_sulog_init(void) { + if (ksu_register_feature_handler(&sulog_handler)) { + pr_err("Failed to register su_compat feature handler\n"); + } + sulog_workqueue = alloc_workqueue("ksu_sulog", WQ_UNBOUND | WQ_HIGHPRI, 1); if (!sulog_workqueue) { pr_err("sulog: failed to create workqueue\n"); @@ -320,6 +346,8 @@ void ksu_sulog_exit(void) struct sulog_entry *entry, *tmp; unsigned long flags; + ksu_unregister_feature_handler(KSU_FEATURE_SULOG); + sulog_enabled = false; if (sulog_workqueue) { diff --git a/manager/app/src/main/cpp/jni.c b/manager/app/src/main/cpp/jni.c index 57153002..95818d6e 100644 --- a/manager/app/src/main/cpp/jni.c +++ b/manager/app/src/main/cpp/jni.c @@ -319,6 +319,14 @@ NativeBridge(setEnhancedSecurityEnabled, jboolean, jboolean enabled) { return set_enhanced_security_enabled(enabled); } +NativeBridgeNP(isSuLogEnabled, jboolean) { + return is_sulog_enabled(); +} + +NativeBridge(setSuLogEnabled, jboolean, jboolean enabled) { + return set_sulog_enabled(enabled); +} + NativeBridge(getUserName, jstring, jint uid) { struct passwd *pw = getpwuid((uid_t) uid); if (pw && pw->pw_name && pw->pw_name[0] != '\0') { diff --git a/manager/app/src/main/cpp/ksu.c b/manager/app/src/main/cpp/ksu.c index f3d1c133..0fc8866a 100644 --- a/manager/app/src/main/cpp/ksu.c +++ b/manager/app/src/main/cpp/ksu.c @@ -231,6 +231,22 @@ bool is_enhanced_security_enabled() { return value != 0; } +bool set_sulog_enabled(bool enabled) { + return set_feature(KSU_FEATURE_SULOG, enabled ? 1 : 0); +} + +bool is_sulog_enabled() { + uint64_t value = 0; + bool supported = false; + if (!get_feature(KSU_FEATURE_SULOG, &value, &supported)) { + return false; + } + if (!supported) { + return false; + } + return value != 0; +} + void get_full_version(char* buff) { struct ksu_get_full_version_cmd cmd = {0}; if (ksuctl(KSU_IOCTL_GET_FULL_VERSION, &cmd) == 0) { diff --git a/manager/app/src/main/cpp/ksu.h b/manager/app/src/main/cpp/ksu.h index dd46e04c..efcaa051 100644 --- a/manager/app/src/main/cpp/ksu.h +++ b/manager/app/src/main/cpp/ksu.h @@ -132,6 +132,7 @@ enum ksu_feature_id { KSU_FEATURE_SU_COMPAT = 0, KSU_FEATURE_KERNEL_UMOUNT = 1, KSU_FEATURE_ENHANCED_SECURITY = 2, + KSU_FEATURE_SULOG = 3, }; // Generic feature API @@ -211,9 +212,12 @@ bool is_kernel_umount_enabled(); // Enhanced security bool set_enhanced_security_enabled(bool enabled); - bool is_enhanced_security_enabled(); +// Su log +bool set_sulog_enabled(bool enabled); +bool is_sulog_enabled(); + // Other command structures struct ksu_get_full_version_cmd { char version_full[KSU_FULL_VERSION_STRING]; // Output: full version string diff --git a/manager/app/src/main/java/com/sukisu/ultra/Natives.kt b/manager/app/src/main/java/com/sukisu/ultra/Natives.kt index 2f8aa33e..db891dab 100644 --- a/manager/app/src/main/java/com/sukisu/ultra/Natives.kt +++ b/manager/app/src/main/java/com/sukisu/ultra/Natives.kt @@ -118,6 +118,15 @@ object Natives { external fun isEnhancedSecurityEnabled(): Boolean external fun setEnhancedSecurityEnabled(enabled: Boolean): Boolean + /** + * Su Log can be enabled/disabled. + * 0: disabled + * 1: enabled + * negative : error + */ + external fun isSuLogEnabled(): Boolean + external fun setSuLogEnabled(enabled: Boolean): Boolean + external fun isKPMEnabled(): Boolean external fun getHookType(): String diff --git a/manager/app/src/main/java/com/sukisu/ultra/ui/screen/Settings.kt b/manager/app/src/main/java/com/sukisu/ultra/ui/screen/Settings.kt index 2828e3ad..6fd56a61 100644 --- a/manager/app/src/main/java/com/sukisu/ultra/ui/screen/Settings.kt +++ b/manager/app/src/main/java/com/sukisu/ultra/ui/screen/Settings.kt @@ -270,6 +270,49 @@ fun SettingScreen(navigator: DestinationsNavigator) { } ) + var kernelSuLogMode by rememberSaveable { + mutableIntStateOf( + run { + val currentEnabled = Natives.isSuLogEnabled() + val savedPersist = prefs.getInt("kernel_sulog_mode", 0) + if (savedPersist == 2) 2 else if (!currentEnabled) 1 else 0 + } + ) + } + SuperDropdown( + icon = Icons.Rounded.RemoveCircle, + title = stringResource(id = R.string.settings_disable_sulog), + summary = stringResource(id = R.string.settings_disable_sulog_summary), + items = modeItems, + selectedIndex = kernelSuLogMode, + onSelectedIndexChange = { index -> + when (index) { + // Default: enable and save to persist + 0 -> if (Natives.setSuLogEnabled(true)) { + execKsud("feature save", true) + prefs.edit { putInt("kernel_sulog_mode", 0) } + kernelSuLogMode = 0 + } + + // Temporarily disable: save enabled state first, then disable + 1 -> if (Natives.setSuLogEnabled(true)) { + execKsud("feature save", true) + if (Natives.setSuLogEnabled(false)) { + prefs.edit { putInt("kernel_sulog_mode", 0) } + kernelSuLogMode = 1 + } + } + + // Permanently disable: disable and save + 2 -> if (Natives.setSuLogEnabled(false)) { + execKsud("feature save", true) + prefs.edit { putInt("kernel_sulog_mode", 2) } + kernelSuLogMode = 2 + } + } + } + ) + // 卸载模块开关 var umountChecked by rememberSaveable { mutableStateOf(Natives.isDefaultUmountModules()) } SwitchItem( @@ -284,7 +327,6 @@ fun SettingScreen(navigator: DestinationsNavigator) { } ) - // 强制签名验证开关 var forceSignatureVerification by rememberSaveable { mutableStateOf(prefs.getBoolean("force_signature_verification", false)) @@ -403,14 +445,16 @@ fun SettingScreen(navigator: DestinationsNavigator) { // 查看使用日志 KsuIsValid { - SettingItem( - icon = Icons.Filled.Visibility, - title = stringResource(R.string.log_viewer_view_logs), - summary = stringResource(R.string.log_viewer_view_logs_summary), - onClick = { - navigator.navigate(LogViewerScreenDestination) - } - ) + if (Natives.isSuLogEnabled()) { + SettingItem( + icon = Icons.Filled.Visibility, + title = stringResource(R.string.log_viewer_view_logs), + summary = stringResource(R.string.log_viewer_view_logs_summary), + onClick = { + navigator.navigate(LogViewerScreenDestination) + } + ) + } } val lkmMode = Natives.isLkmMode KsuIsValid { diff --git a/manager/app/src/main/res/values-zh-rCN/strings.xml b/manager/app/src/main/res/values-zh-rCN/strings.xml index 7cba39f8..6015de70 100644 --- a/manager/app/src/main/res/values-zh-rCN/strings.xml +++ b/manager/app/src/main/res/values-zh-rCN/strings.xml @@ -751,4 +751,6 @@ 应用配置 配置已应用到内核 包含 %1$d 个应用 + 禁用 KernelSU 超级用户访问日志记录 + 禁用超级用户日志记录功能 diff --git a/manager/app/src/main/res/values/strings.xml b/manager/app/src/main/res/values/strings.xml index 89836d7c..ccafbb1b 100644 --- a/manager/app/src/main/res/values/strings.xml +++ b/manager/app/src/main/res/values/strings.xml @@ -761,4 +761,6 @@ Important Note:\n Configuration applied to kernel MNT_DETACH Contains %d apps + Disable KernelSU superuser access logging +Disable superuser logging functionality diff --git a/userspace/ksud/src/feature.rs b/userspace/ksud/src/feature.rs index f6903f1f..da449e6f 100644 --- a/userspace/ksud/src/feature.rs +++ b/userspace/ksud/src/feature.rs @@ -17,6 +17,7 @@ pub enum FeatureId { SuCompat = 0, KernelUmount = 1, EnhancedSecurity = 2, + SuLog = 3, } impl FeatureId { @@ -25,6 +26,7 @@ impl FeatureId { 0 => Some(FeatureId::SuCompat), 1 => Some(FeatureId::KernelUmount), 2 => Some(FeatureId::EnhancedSecurity), + 3 => Some(FeatureId::SuLog), _ => None, } } @@ -34,6 +36,7 @@ impl FeatureId { FeatureId::SuCompat => "su_compat", FeatureId::KernelUmount => "kernel_umount", FeatureId::EnhancedSecurity => "enhanced_security", + FeatureId::SuLog => "sulog", } } @@ -48,6 +51,9 @@ impl FeatureId { FeatureId::EnhancedSecurity => { "Enhanced Security - disable non‑KSU root elevation and unauthorized UID downgrades" } + FeatureId::SuLog => { + "SU Log - enables logging of SU command usage to kernel log for auditing purposes" + } } } } @@ -57,6 +63,7 @@ fn parse_feature_id(name: &str) -> Result { "su_compat" | "0" => Ok(FeatureId::SuCompat), "kernel_umount" | "1" => Ok(FeatureId::KernelUmount), "enhanced_security" | "2" => Ok(FeatureId::EnhancedSecurity), + "sulog" | "3" => Ok(FeatureId::SuLog), _ => bail!("Unknown feature: {}", name), } } @@ -234,6 +241,7 @@ pub fn list_features() -> Result<()> { FeatureId::SuCompat, FeatureId::KernelUmount, FeatureId::EnhancedSecurity, + FeatureId::SuLog, ]; for feature_id in all_features.iter() { @@ -297,6 +305,7 @@ pub fn save_config() -> Result<()> { FeatureId::SuCompat, FeatureId::KernelUmount, FeatureId::EnhancedSecurity, + FeatureId::SuLog, ]; for feature_id in all_features.iter() {