Upload source files to complete submission of history changes

Co-authored-by:Shirkneko <Shirkneko@2773800761@qq.com>
This commit is contained in:
ShirkNeko
2025-03-22 14:37:14 +08:00
parent 3121eb0f9a
commit 7b7fff91a6
14 changed files with 1 additions and 631 deletions

View File

@@ -1,62 +0,0 @@
name: Build ksud_magic
on:
workflow_call:
inputs:
target:
required: true
type: string
os:
required: false
type: string
default: ubuntu-latest
pack_lkm:
required: false
type: boolean
default: true
use_cache:
required: false
type: boolean
default: true
jobs:
build:
runs-on: ${{ inputs.os }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download artifacts
uses: actions/download-artifact@v4
- name: Prepare LKM fies
if: ${{ inputs.pack_lkm }}
run: |
cp android*-lkm/*_kernelsu.ko ./userspace/ksud_magic/bin/aarch64/
- name: Import susfsd lib
run: |
cp susfsd-aarch64-linux-android/arm64-v8a/susfsd ./userspace/ksud_magic/bin/aarch64/
- name: Setup rustup
run: |
rustup update stable
rustup target add x86_64-apple-darwin
rustup target add aarch64-apple-darwin
- uses: Swatinem/rust-cache@v2
with:
workspaces: userspace/ksud_magic
cache-targets: false
- name: Install cross
run: |
cargo install cross --git https://github.com/cross-rs/cross --rev 66845c1 --force
- name: Build ksud_magic
run: CROSS_NO_WARNINGS=0 cross build --target ${{ inputs.target }} --release --manifest-path ./userspace/ksud_magic/Cargo.toml
- name: Upload ksud_magic artifact
uses: actions/upload-artifact@v4
with:
name: ksud_magic-${{ inputs.target }}
path: userspace/ksud_magic/target/**/release/ksud*

View File

@@ -1,62 +0,0 @@
name: Build ksud_overlayfs
on:
workflow_call:
inputs:
target:
required: true
type: string
os:
required: false
type: string
default: ubuntu-latest
pack_lkm:
required: false
type: boolean
default: true
use_cache:
required: false
type: boolean
default: true
jobs:
build:
runs-on: ${{ inputs.os }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download artifacts
uses: actions/download-artifact@v4
- name: Prepare LKM fies
if: ${{ inputs.pack_lkm }}
run: |
cp android*-lkm/*_kernelsu.ko ./userspace/ksud_overlayfs/bin/aarch64/
- name: Import susfsd lib
run: |
cp susfsd-aarch64-linux-android/arm64-v8a/susfsd ./userspace/ksud_overlayfs/bin/aarch64/
- name: Setup rustup
run: |
rustup update stable
rustup target add x86_64-apple-darwin
rustup target add aarch64-apple-darwin
- uses: Swatinem/rust-cache@v2
with:
workspaces: userspace/ksud_overlayfs
cache-targets: false
- name: Install cross
run: |
cargo install cross --git https://github.com/cross-rs/cross --rev 66845c1 --force
- name: Build ksud_overlayfs
run: CROSS_NO_WARNINGS=0 cross build --target ${{ inputs.target }} --release --manifest-path ./userspace/ksud_overlayfs/Cargo.toml
- name: Upload ksud_overlayfs artifact
uses: actions/upload-artifact@v4
with:
name: ksud_overlayfs-${{ inputs.target }}
path: userspace/ksud_overlayfs/target/**/release/ksud*

View File

@@ -1,34 +0,0 @@
name: Build susfsd
on:
push:
branches: [ "next" ]
paths:
- '.github/workflows/susfsd.yml'
- 'userspace/susfsd/**'
workflow_dispatch:
workflow_call:
inputs:
target:
required: true
type: string
os:
required: false
type: string
default: ubuntu-latest
jobs:
build-susfs:
name: Build userspace susfsd
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Build susfsd
working-directory: ./userspace/susfsd
run: $ANDROID_NDK/ndk-build
- name: Upload a Build Artifact
uses: actions/upload-artifact@v4
with:
name: susfsd-aarch64-linux-android
path: ./userspace/susfsd/libs

View File

@@ -3,19 +3,15 @@ package shirkneko.zako.sukisu.ui.screen
import android.app.Activity
import android.app.AlertDialog
import android.content.Context
import android.app.AlertDialog
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.widget.Toast
import android.widget.Toast
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.StringRes
import androidx.compose.foundation.LocalIndication
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.selection.toggleable
import androidx.compose.foundation.verticalScroll
@@ -24,19 +20,15 @@ import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.FileUpload
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.documentfile.provider.DocumentFile
import androidx.documentfile.provider.DocumentFile
import com.maxkeppeker.sheets.core.models.base.Header
import com.maxkeppeker.sheets.core.models.base.rememberUseCaseState
import com.maxkeppeler.sheets.list.ListDialog
@@ -57,12 +49,6 @@ import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import shirkneko.zako.sukisu.ui.util.*
import shirkneko.zako.sukisu.utils.AssetsUtil
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
/**
* @author weishu
@@ -82,33 +68,6 @@ fun InstallScreen(navigator: DestinationsNavigator) {
showRebootDialog = true
}
if (showRebootDialog) {
RebootDialog(
show = true,
onDismiss = { showRebootDialog = false },
onConfirm = {
showRebootDialog = false
try {
val process = Runtime.getRuntime().exec("su")
process.outputStream.bufferedWriter().use { writer ->
writer.write("svc power reboot\n")
writer.write("exit\n")
}
} catch (e: Exception) {
Toast.makeText(context, R.string.failed_reboot, Toast.LENGTH_SHORT).show()
}
}
)
var installMethod by remember { mutableStateOf<InstallMethod?>(null) }
var lkmSelection by remember { mutableStateOf<LkmSelection>(LkmSelection.KmiNone) }
val context = LocalContext.current
var showRebootDialog by remember { mutableStateOf(false) }
val onFlashComplete = {
showRebootDialog = true
}
if (showRebootDialog) {
RebootDialog(
show = true,
@@ -149,32 +108,9 @@ fun InstallScreen(navigator: DestinationsNavigator) {
}
}
}
Unit
when (method) {
is InstallMethod.HorizonKernel -> {
method.uri?.let { uri ->
val worker = HorizonKernelWorker(context)
worker.uri = uri
worker.setOnFlashCompleteListener(onFlashComplete)
worker.start()
}
}
else -> {
val flashIt = FlashIt.FlashBoot(
boot = if (method is InstallMethod.SelectFile) method.uri else null,
lkm = lkmSelection,
ota = method is InstallMethod.DirectInstallToInactiveSlot
)
navigator.navigate(FlashScreenDestination(flashIt))
}
}
}
Unit
}
val currentKmi by produceState(initialValue = "") {
value = getCurrentKmi()
}
val currentKmi by produceState(initialValue = "") {
value = getCurrentKmi()
}
@@ -193,18 +129,8 @@ fun InstallScreen(navigator: DestinationsNavigator) {
onInstall()
}
Unit
Unit
}
val selectLkmLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult()
) {
if (it.resultCode == Activity.RESULT_OK) {
it.data?.data?.let { uri ->
lkmSelection = LkmSelection.LkmUri(uri)
}
}
}
val selectLkmLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult()
) {
@@ -226,7 +152,6 @@ fun InstallScreen(navigator: DestinationsNavigator) {
Scaffold(
topBar = {
TopBar(
onBack = { navigator.popBackStack() },
onBack = { navigator.popBackStack() },
onLkmUpload = onLkmUpload,
scrollBehavior = scrollBehavior
@@ -235,9 +160,6 @@ fun InstallScreen(navigator: DestinationsNavigator) {
contentWindowInsets = WindowInsets.safeDrawing.only(
WindowInsetsSides.Top + WindowInsetsSides.Horizontal
)
contentWindowInsets = WindowInsets.safeDrawing.only(
WindowInsetsSides.Top + WindowInsetsSides.Horizontal
)
) { innerPadding ->
Column(
modifier = Modifier
@@ -262,14 +184,10 @@ fun InstallScreen(navigator: DestinationsNavigator) {
)
)
}
Button(
modifier = Modifier.fillMaxWidth(),
Button(
modifier = Modifier.fillMaxWidth(),
enabled = installMethod != null,
onClick = onClickNext
) {
onClick = onClickNext
) {
Text(
stringResource(id = R.string.install_next),
@@ -464,12 +382,6 @@ sealed class InstallMethod {
override val summary: String? = null
) : InstallMethod()
data class HorizonKernel(
val uri: Uri? = null,
@StringRes override val label: Int = R.string.horizon_kernel,
override val summary: String? = null
) : InstallMethod()
abstract val label: Int
open val summary: String? = null
}
@@ -481,15 +393,8 @@ private fun SelectInstallMethod(onSelected: (InstallMethod) -> Unit = {}) {
val selectFileTip = stringResource(
id = R.string.select_file_tip,
if (isInitBoot()) "init_boot" else "boot"
id = R.string.select_file_tip,
if (isInitBoot()) "init_boot" else "boot"
)
val radioOptions = mutableListOf<InstallMethod>(
InstallMethod.SelectFile(summary = selectFileTip)
)
val radioOptions = mutableListOf<InstallMethod>(
InstallMethod.SelectFile(summary = selectFileTip)
)
@@ -500,14 +405,11 @@ private fun SelectInstallMethod(onSelected: (InstallMethod) -> Unit = {}) {
radioOptions.add(InstallMethod.DirectInstallToInactiveSlot)
}
radioOptions.add(InstallMethod.HorizonKernel(summary = "Flashing the Anykernel3 Kernel"))
radioOptions.add(InstallMethod.HorizonKernel(summary = "Flashing the Anykernel3 Kernel"))
}
var selectedOption by remember { mutableStateOf<InstallMethod?>(null) }
var currentSelectingMethod by remember { mutableStateOf<InstallMethod?>(null) }
var currentSelectingMethod by remember { mutableStateOf<InstallMethod?>(null) }
val selectImageLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult()
) {
@@ -523,17 +425,6 @@ private fun SelectInstallMethod(onSelected: (InstallMethod) -> Unit = {}) {
onSelected(it)
}
}
}
val option = when (currentSelectingMethod) {
is InstallMethod.SelectFile -> InstallMethod.SelectFile(uri, summary = selectFileTip)
is InstallMethod.HorizonKernel -> InstallMethod.HorizonKernel(uri, summary = " Flashing the Anykernel3 Kernel")
else -> null
}
option?.let {
selectedOption = it
onSelected(it)
}
}
}
}
@@ -545,22 +436,12 @@ private fun SelectInstallMethod(onSelected: (InstallMethod) -> Unit = {}) {
onDismiss = null
)
val confirmDialog = rememberConfirmDialog(
onConfirm = {
selectedOption = InstallMethod.DirectInstallToInactiveSlot
onSelected(InstallMethod.DirectInstallToInactiveSlot)
},
onDismiss = null
)
val dialogTitle = stringResource(id = android.R.string.dialog_alert_title)
val dialogContent = stringResource(id = R.string.install_inactive_slot_warning)
val onClick = { option: InstallMethod ->
currentSelectingMethod = option
currentSelectingMethod = option
when (option) {
is InstallMethod.SelectFile, is InstallMethod.HorizonKernel -> {
is InstallMethod.SelectFile, is InstallMethod.HorizonKernel -> {
selectImageLauncher.launch(Intent(Intent.ACTION_GET_CONTENT).apply {
type = "application/*"
@@ -587,7 +468,6 @@ private fun SelectInstallMethod(onSelected: (InstallMethod) -> Unit = {}) {
.toggleable(
value = option.javaClass == selectedOption?.javaClass,
onValueChange = { onClick(option) },
onValueChange = { onClick(option) },
role = Role.RadioButton,
indication = LocalIndication.current,
interactionSource = interactionSource
@@ -596,7 +476,6 @@ private fun SelectInstallMethod(onSelected: (InstallMethod) -> Unit = {}) {
RadioButton(
selected = option.javaClass == selectedOption?.javaClass,
onClick = { onClick(option) },
onClick = { onClick(option) },
interactionSource = interactionSource
)
Column(
@@ -630,10 +509,8 @@ fun rememberSelectKmiDialog(onSelected: (String?) -> Unit): DialogHandle {
value = getSupportedKmis()
}
val options = supportedKmi.map { value ->
ListOption(titleText = value)
ListOption(titleText = value)
}
var selection by remember { mutableStateOf<String?>(null) }
@@ -658,27 +535,6 @@ fun rememberSelectKmiDialog(onSelected: (String?) -> Unit): DialogHandle {
selection = option.titleText
}
)
ListDialog(
state = rememberUseCaseState(
visible = true,
onFinishedRequest = {
onSelected(selection)
},
onCloseRequest = {
dismiss()
}
),
header = Header.Default(
title = stringResource(R.string.select_kmi),
),
selection = ListSelection.Single(
showRadioButtons = true,
options = options,
) { _, option ->
selection = option.titleText
}
)
}
}
@@ -690,13 +546,6 @@ private fun TopBar(
scrollBehavior: TopAppBarScrollBehavior? = null
) {
TopAppBar(
title = { Text(stringResource(R.string.install)) },
navigationIcon = {
IconButton(onClick = onBack) {
Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null)
}
},
actions = {
title = { Text(stringResource(R.string.install)) },
navigationIcon = {
IconButton(onClick = onBack) {
@@ -711,14 +560,10 @@ private fun TopBar(
windowInsets = WindowInsets.safeDrawing.only(
WindowInsetsSides.Top + WindowInsetsSides.Horizontal
),
windowInsets = WindowInsets.safeDrawing.only(
WindowInsetsSides.Top + WindowInsetsSides.Horizontal
),
scrollBehavior = scrollBehavior
)
}
@Preview
@Preview
@Composable
fun SelectInstallPreview() {

File diff suppressed because one or more lines are too long

View File

@@ -66,8 +66,6 @@
<string name="failed_to_update_app_profile">Gagal membarui Profil pada %s</string>
<string name="settings_umount_modules_default">Melepas Modul secara bawaan</string>
<string name="settings_umount_modules_default_summary">Menggunakan \"Umount Modul\" secara universal pada Profil Aplikasi. Jika diaktifkan, akan menghapus semua modifikasi sistem untuk aplikasi yang tidak memiliki set profil.</string>
<string name="settings_susfs_toggle">Sembunyikan hook kprobe</string>
<string name="settings_susfs_toggle_summary">Ini menonaktifkan hook kprobe yang dibuat oleh ksu, dan sebagai gantinya, hook inline non-kprobe akan diaktifkan, sama seperti implementasi untuk kernel non-gki yang tidak mendukung kprobe.</string>
<string name="profile_umount_modules_summary">Aktifkan opsi ini agar KernelSU dapat memulihkan kembali berkas termodifikasi oleh modul pada aplikasi ini.</string>
<string name="profile_selinux_domain">Domain</string>
<string name="profile_selinux_rules">Aturan</string>

View File

@@ -1,2 +1 @@
**/*.ko
susfsd
**/*.ko

View File

@@ -8,7 +8,6 @@ use crate::{defs::BINARY_DIR, utils};
pub const RESETPROP_PATH: &str = concatcp!(BINARY_DIR, "resetprop");
pub const BUSYBOX_PATH: &str = concatcp!(BINARY_DIR, "busybox");
pub const BOOTCTL_PATH: &str = concatcp!(BINARY_DIR, "bootctl");
pub const SUSFSD_PATH: &str = concatcp!(BINARY_DIR, "susfsd");
#[cfg(all(target_arch = "x86_64", target_os = "android"))]
#[derive(RustEmbed)]

View File

@@ -1,2 +0,0 @@
**/*.ko
susfsd

View File

@@ -1,52 +0,0 @@
use anyhow::Result;
use const_format::concatcp;
use rust_embed::RustEmbed;
use std::path::Path;
use crate::{defs::BINARY_DIR, utils};
pub const RESETPROP_PATH: &str = concatcp!(BINARY_DIR, "resetprop");
pub const BUSYBOX_PATH: &str = concatcp!(BINARY_DIR, "busybox");
pub const BOOTCTL_PATH: &str = concatcp!(BINARY_DIR, "bootctl");
pub const SUSFSD_PATH: &str = concatcp!(BINARY_DIR, "susfsd");
#[cfg(all(target_arch = "x86_64", target_os = "android"))]
#[derive(RustEmbed)]
#[folder = "bin/x86_64"]
struct Asset;
// IF NOT x86_64 ANDROID, ie. macos, linux, windows, always use aarch64
#[cfg(not(all(target_arch = "x86_64", target_os = "android")))]
#[derive(RustEmbed)]
#[folder = "bin/aarch64"]
struct Asset;
pub fn ensure_binaries(ignore_if_exist: bool) -> Result<()> {
for file in Asset::iter() {
if file == "ksuinit" || file.ends_with(".ko") {
// don't extract ksuinit and kernel modules
continue;
}
let asset = Asset::get(&file).ok_or(anyhow::anyhow!("asset not found: {}", file))?;
utils::ensure_binary(format!("{BINARY_DIR}{file}"), &asset.data, ignore_if_exist)?
}
Ok(())
}
pub fn copy_assets_to_file(name: &str, dst: impl AsRef<Path>) -> Result<()> {
let asset = Asset::get(name).ok_or(anyhow::anyhow!("asset not found: {}", name))?;
std::fs::write(dst, asset.data)?;
Ok(())
}
pub fn list_supported_kmi() -> Result<Vec<String>> {
let mut list = Vec::new();
for file in Asset::iter() {
// kmi_name = "xxx_kernelsu.ko"
if let Some(kmi) = file.strip_suffix("_kernelsu.ko") {
list.push(kmi.to_string());
}
}
Ok(list)
}

View File

@@ -1,2 +0,0 @@
/obj
/libs

View File

@@ -1,6 +0,0 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := susfsd
LOCAL_SRC_FILES := susfsd.c
include $(BUILD_EXECUTABLE)

View File

@@ -1,3 +0,0 @@
APP_ABI := arm64-v8a
APP_PLATFORM := android-24
APP_STL := none

View File

@@ -1,239 +0,0 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/prctl.h>
#include <stdbool.h>
#include <errno.h>
#include <unistd.h>
#define KERNEL_SU_OPTION 0xDEADBEEF
#define CMD_SUSFS_SHOW_VERSION 0x555e1
#define CMD_SUSFS_SHOW_ENABLED_FEATURES 0x555e2
#define CMD_SUSFS_SHOW_VARIANT 0x555e3
#define CMD_SUSFS_SHOW_SUS_SU_WORKING_MODE 0x555e4
#define CMD_SUSFS_IS_SUS_SU_READY 0x555f0
#define CMD_SUSFS_SUS_SU 0x60000
#define SUS_SU_DISABLED 0
#define SUS_SU_WITH_HOOKS 2
struct st_sus_su {
int mode;
};
int enable_sus_su(int last_working_mode, int target_working_mode) {
struct st_sus_su info;
int error = -1;
if (target_working_mode == SUS_SU_WITH_HOOKS) {
info.mode = SUS_SU_WITH_HOOKS;
prctl(KERNEL_SU_OPTION, CMD_SUSFS_SUS_SU, &info, NULL, &error);
if (error) {
if (error == 1) {
} else if (error == 2) {
}
return error;
}
printf("[+] sus_su mode 2 is enabled\n");
} else if (target_working_mode == SUS_SU_DISABLED) {
info.mode = SUS_SU_DISABLED;
prctl(KERNEL_SU_OPTION, CMD_SUSFS_SUS_SU, &info, NULL, &error);
if (error) {
if (error == 1) {
}
return error;
}
printf("[+] sus_su mode 0 is enabled\n");
} else {
return 1;
}
return 0;
}
int main(int argc, char *argv[]) {
int error = -1;
char support[16];
char version[16];
char variant[16];
// Check for arguments
if (argc < 2) {
fprintf(stderr, "Usage: %s <support|version|variant|features|sus_su <0|2|mode>|>\n", argv[0]);
return 1;
}
if (strcmp(argv[1], "version") == 0) {
prctl(KERNEL_SU_OPTION, CMD_SUSFS_SHOW_VERSION, version, NULL, &error);
if (!error) {
printf("%s\n", version);
} else {
printf("Invalid\n");
}
} else if (strcmp(argv[1], "variant") == 0) {
prctl(KERNEL_SU_OPTION, CMD_SUSFS_SHOW_VARIANT, variant, NULL, &error);
if (!error) {
printf("%s\n", variant);
} else {
printf("Invalid\n");
}
} else if (strcmp(argv[1], "features") == 0) {
char *enabled_features_buf = malloc(getpagesize() * 2);
char *ptr_buf;
unsigned long enabled_features;
int str_len;
if (!enabled_features_buf) {
perror("malloc");
return -ENOMEM;
}
ptr_buf = enabled_features_buf;
prctl(KERNEL_SU_OPTION, CMD_SUSFS_SHOW_ENABLED_FEATURES, &enabled_features, NULL, &error);
if (!error) {
if (enabled_features & (1 << 0)) {
str_len = strlen("CONFIG_KSU_SUSFS_SUS_PATH\n");
strncpy(ptr_buf, "CONFIG_KSU_SUSFS_SUS_PATH\n", str_len);
ptr_buf += str_len;
}
if (enabled_features & (1 << 1)) {
str_len = strlen("CONFIG_KSU_SUSFS_SUS_MOUNT\n");
strncpy(ptr_buf, "CONFIG_KSU_SUSFS_SUS_MOUNT\n", str_len);
ptr_buf += str_len;
}
if (enabled_features & (1 << 2)) {
str_len = strlen("CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT\n");
strncpy(ptr_buf, "CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT\n", str_len);
ptr_buf += str_len;
}
if (enabled_features & (1 << 3)) {
str_len = strlen("CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT\n");
strncpy(ptr_buf, "CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT\n", str_len);
ptr_buf += str_len;
}
if (enabled_features & (1 << 4)) {
str_len = strlen("CONFIG_KSU_SUSFS_SUS_KSTAT\n");
strncpy(ptr_buf, "CONFIG_KSU_SUSFS_SUS_KSTAT\n", str_len);
ptr_buf += str_len;
}
if (enabled_features & (1 << 5)) {
str_len = strlen("CONFIG_KSU_SUSFS_SUS_OVERLAYFS\n");
strncpy(ptr_buf, "CONFIG_KSU_SUSFS_SUS_OVERLAYFS\n", str_len);
ptr_buf += str_len;
}
if (enabled_features & (1 << 6)) {
str_len = strlen("CONFIG_KSU_SUSFS_TRY_UMOUNT\n");
strncpy(ptr_buf, "CONFIG_KSU_SUSFS_TRY_UMOUNT\n", str_len);
ptr_buf += str_len;
}
if (enabled_features & (1 << 7)) {
str_len = strlen("CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT\n");
strncpy(ptr_buf, "CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT\n", str_len);
ptr_buf += str_len;
}
if (enabled_features & (1 << 8)) {
str_len = strlen("CONFIG_KSU_SUSFS_SPOOF_UNAME\n");
strncpy(ptr_buf, "CONFIG_KSU_SUSFS_SPOOF_UNAME\n", str_len);
ptr_buf += str_len;
}
if (enabled_features & (1 << 9)) {
str_len = strlen("CONFIG_KSU_SUSFS_ENABLE_LOG\n");
strncpy(ptr_buf, "CONFIG_KSU_SUSFS_ENABLE_LOG\n", str_len);
ptr_buf += str_len;
}
if (enabled_features & (1 << 10)) {
str_len = strlen("CONFIG_KSU_SUSFS_HIDE_KSU_SUSFS_SYMBOLS\n");
strncpy(ptr_buf, "CONFIG_KSU_SUSFS_HIDE_KSU_SUSFS_SYMBOLS\n", str_len);
ptr_buf += str_len;
}
if (enabled_features & (1 << 11)) {
str_len = strlen("CONFIG_KSU_SUSFS_SPOOF_BOOTCONFIG\n");
strncpy(ptr_buf, "CONFIG_KSU_SUSFS_SPOOF_BOOTCONFIG\n", str_len);
ptr_buf += str_len;
}
if (enabled_features & (1 << 12)) {
str_len = strlen("CONFIG_KSU_SUSFS_OPEN_REDIRECT\n");
strncpy(ptr_buf, "CONFIG_KSU_SUSFS_OPEN_REDIRECT\n", str_len);
ptr_buf += str_len;
}
if (enabled_features & (1 << 13)) {
str_len = strlen("CONFIG_KSU_SUSFS_SUS_SU\n");
strncpy(ptr_buf, "CONFIG_KSU_SUSFS_SUS_SU\n", str_len);
ptr_buf += str_len;
}
printf("%s", enabled_features_buf);
free(enabled_features_buf);
} else {
printf("Invalid\n");
}
} else if (strcmp(argv[1], "support") == 0) {
unsigned long enabled_features;
int any_feature_enabled = 0;
prctl(KERNEL_SU_OPTION, CMD_SUSFS_SHOW_ENABLED_FEATURES, &enabled_features, NULL, &error);
if (!error) {
if (enabled_features & ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) |
(1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) |
(1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) |
(1 << 12) | (1 << 13))) {
any_feature_enabled = 1;
}
if (any_feature_enabled) {
printf("Supported\n");
} else {
printf("Unsupported\n");
}
} else {
printf("Unsupported\n");
}
} else if (argc == 3 && !strcmp(argv[1], "sus_su")) {
int last_working_mode = 0;
int target_working_mode;
char* endptr;
prctl(KERNEL_SU_OPTION, CMD_SUSFS_SHOW_SUS_SU_WORKING_MODE, &last_working_mode, NULL, &error);
if (error)
return error;
if (!strcmp(argv[2], "mode")) {
printf("%d\n", last_working_mode);
return 0;
}
target_working_mode = strtol(argv[2], &endptr, 10);
if (*endptr != '\0') {
return 1;
}
if (target_working_mode == SUS_SU_WITH_HOOKS) {
bool is_sus_su_ready;
prctl(KERNEL_SU_OPTION, CMD_SUSFS_IS_SUS_SU_READY, &is_sus_su_ready, NULL, &error);
if (error)
return error;
if (!is_sus_su_ready) {
printf("[-] sus_su mode %d has to be run during or after service stage\n", SUS_SU_WITH_HOOKS);
return 1;
}
if (last_working_mode == SUS_SU_DISABLED) {
error = enable_sus_su(last_working_mode, SUS_SU_WITH_HOOKS);
} else if (last_working_mode == SUS_SU_WITH_HOOKS) {
printf("[-] sus_su is already in mode %d\n", last_working_mode);
return 1;
} else {
error = enable_sus_su(last_working_mode, SUS_SU_DISABLED);
if (!error)
error = enable_sus_su(last_working_mode, SUS_SU_WITH_HOOKS);
}
} else if (target_working_mode == SUS_SU_DISABLED) {
if (last_working_mode == SUS_SU_DISABLED) {
printf("[-] sus_su is already in mode %d\n", last_working_mode);
return 1;
}
error = enable_sus_su(last_working_mode, SUS_SU_DISABLED);
}
} else {
fprintf(stderr, "Invalid argument: %s\n", argv[1]);
return 1;
}
return 0;
}