kernel: Reworking Dynamic Manager Index Configuration
This commit is contained in:
@@ -30,7 +30,6 @@ static struct apk_sign_key {
|
|||||||
const char *sha256;
|
const char *sha256;
|
||||||
} apk_sign_keys[] = {
|
} apk_sign_keys[] = {
|
||||||
{EXPECTED_SIZE_SHIRKNEKO, EXPECTED_HASH_SHIRKNEKO}, // ShirkNeko/SukiSU
|
{EXPECTED_SIZE_SHIRKNEKO, EXPECTED_HASH_SHIRKNEKO}, // ShirkNeko/SukiSU
|
||||||
{EXPECTED_SIZE_OTHER, EXPECTED_HASH_OTHER}, // Dynamic Sign
|
|
||||||
#ifdef EXPECTED_SIZE
|
#ifdef EXPECTED_SIZE
|
||||||
{EXPECTED_SIZE, EXPECTED_HASH}, // Custom
|
{EXPECTED_SIZE, EXPECTED_HASH}, // Custom
|
||||||
#endif
|
#endif
|
||||||
@@ -82,6 +81,54 @@ static int ksu_sha256(const unsigned char *data, unsigned int datalen,
|
|||||||
crypto_free_shash(alg);
|
crypto_free_shash(alg);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct dynamic_sign_key dynamic_sign = DYNAMIC_SIGN_DEFAULT_CONFIG;
|
||||||
|
|
||||||
|
static bool check_dynamic_sign(struct file *fp, u32 size4, loff_t *pos, int *matched_index)
|
||||||
|
{
|
||||||
|
struct dynamic_sign_key current_dynamic_key = dynamic_sign;
|
||||||
|
|
||||||
|
if (ksu_get_dynamic_manager_config(¤t_dynamic_key.size, ¤t_dynamic_key.hash)) {
|
||||||
|
pr_debug("Using dynamic manager config: size=0x%x, hash=%.16s...\n",
|
||||||
|
current_dynamic_key.size, current_dynamic_key.hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size4 != current_dynamic_key.size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CERT_MAX_LENGTH 1024
|
||||||
|
char cert[CERT_MAX_LENGTH];
|
||||||
|
if (size4 > CERT_MAX_LENGTH) {
|
||||||
|
pr_info("cert length overlimit\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ksu_kernel_read_compat(fp, cert, size4, pos);
|
||||||
|
|
||||||
|
unsigned char digest[SHA256_DIGEST_SIZE];
|
||||||
|
if (ksu_sha256(cert, size4, digest) < 0) {
|
||||||
|
pr_info("sha256 error\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
char hash_str[SHA256_DIGEST_SIZE * 2 + 1];
|
||||||
|
hash_str[SHA256_DIGEST_SIZE * 2] = '\0';
|
||||||
|
bin2hex(hash_str, digest, SHA256_DIGEST_SIZE);
|
||||||
|
|
||||||
|
pr_info("sha256: %s, expected: %s, index: dynamic\n", hash_str, current_dynamic_key.hash);
|
||||||
|
|
||||||
|
if (strcmp(current_dynamic_key.hash, hash_str) == 0) {
|
||||||
|
if (matched_index) {
|
||||||
|
*matched_index = DYNAMIC_SIGN_INDEX;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool check_block(struct file *fp, u32 *size4, loff_t *pos, u32 *offset, int *matched_index)
|
static bool check_block(struct file *fp, u32 *size4, loff_t *pos, u32 *offset, int *matched_index)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -103,18 +150,18 @@ static bool check_block(struct file *fp, u32 *size4, loff_t *pos, u32 *offset, i
|
|||||||
ksu_kernel_read_compat(fp, size4, 0x4, pos); // certificate length
|
ksu_kernel_read_compat(fp, size4, 0x4, pos); // certificate length
|
||||||
*offset += 0x4 * 2;
|
*offset += 0x4 * 2;
|
||||||
|
|
||||||
|
if (ksu_is_dynamic_manager_enabled()) {
|
||||||
|
loff_t temp_pos = *pos;
|
||||||
|
if (check_dynamic_sign(fp, *size4, &temp_pos, matched_index)) {
|
||||||
|
*pos = temp_pos;
|
||||||
|
*offset += *size4;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(apk_sign_keys); i++) {
|
for (i = 0; i < ARRAY_SIZE(apk_sign_keys); i++) {
|
||||||
sign_key = apk_sign_keys[i];
|
sign_key = apk_sign_keys[i];
|
||||||
|
|
||||||
if (i == 1) { // Dynamic Sign indexing
|
|
||||||
unsigned int size;
|
|
||||||
const char *hash;
|
|
||||||
if (ksu_get_dynamic_manager_config(&size, &hash)) {
|
|
||||||
sign_key.size = size;
|
|
||||||
sign_key.sha256 = hash;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*size4 != sign_key.size)
|
if (*size4 != sign_key.size)
|
||||||
continue;
|
continue;
|
||||||
*offset += *size4;
|
*offset += *size4;
|
||||||
@@ -326,8 +373,8 @@ clean:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (check_multi_manager) {
|
if (check_multi_manager) {
|
||||||
// 0: ShirkNeko/SukiSU, 1: Dynamic Sign
|
// 0: ShirkNeko/SukiSU, DYNAMIC_SIGN_INDEX : Dynamic Sign
|
||||||
if (matched_index == 0 || matched_index == 1) {
|
if (matched_index == 0 || matched_index == DYNAMIC_SIGN_INDEX) {
|
||||||
pr_info("Multi-manager APK detected (dynamic_manager enabled): signature_index=%d\n", matched_index);
|
pr_info("Multi-manager APK detected (dynamic_manager enabled): signature_index=%d\n", matched_index);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ int ksu_get_manager_signature_index(uid_t uid)
|
|||||||
|
|
||||||
// Check traditional manager first
|
// Check traditional manager first
|
||||||
if (ksu_manager_uid != KSU_INVALID_UID && uid == ksu_manager_uid) {
|
if (ksu_manager_uid != KSU_INVALID_UID && uid == ksu_manager_uid) {
|
||||||
return 1;
|
return DYNAMIC_SIGN_INDEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ksu_is_dynamic_manager_enabled()) {
|
if (!ksu_is_dynamic_manager_enabled()) {
|
||||||
|
|||||||
@@ -7,6 +7,17 @@
|
|||||||
#define DYNAMIC_MANAGER_FILE_MAGIC 0x7f445347 // 'DSG', u32
|
#define DYNAMIC_MANAGER_FILE_MAGIC 0x7f445347 // 'DSG', u32
|
||||||
#define DYNAMIC_MANAGER_FILE_VERSION 1 // u32
|
#define DYNAMIC_MANAGER_FILE_VERSION 1 // u32
|
||||||
#define KERNEL_SU_DYNAMIC_MANAGER "/data/adb/ksu/.dynamic_manager"
|
#define KERNEL_SU_DYNAMIC_MANAGER "/data/adb/ksu/.dynamic_manager"
|
||||||
|
#define DYNAMIC_SIGN_INDEX 100
|
||||||
|
|
||||||
|
struct dynamic_sign_key {
|
||||||
|
unsigned int size;
|
||||||
|
const char *hash;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DYNAMIC_SIGN_DEFAULT_CONFIG { \
|
||||||
|
.size = 0x300, \
|
||||||
|
.hash = "0000000000000000000000000000000000000000000000000000000000000000" \
|
||||||
|
}
|
||||||
|
|
||||||
struct dynamic_manager_config {
|
struct dynamic_manager_config {
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ static inline bool ksu_is_manager_uid_valid()
|
|||||||
|
|
||||||
static inline bool is_manager()
|
static inline bool is_manager()
|
||||||
{
|
{
|
||||||
return unlikely(ksu_is_any_manager(current_uid().val) || ksu_manager_uid == current_uid().val);
|
return unlikely(ksu_is_any_manager(current_uid().val) ||
|
||||||
|
(ksu_manager_uid != KSU_INVALID_UID && ksu_manager_uid == current_uid().val));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uid_t ksu_get_manager_uid()
|
static inline uid_t ksu_get_manager_uid()
|
||||||
|
|||||||
@@ -88,7 +88,8 @@ static void crown_manager(const char *apk, struct list_head *uid_data, int signa
|
|||||||
if (strncmp(np->package, pkg, KSU_MAX_PACKAGE_NAME) == 0) {
|
if (strncmp(np->package, pkg, KSU_MAX_PACKAGE_NAME) == 0) {
|
||||||
pr_info("Crowning manager: %s(uid=%d, signature_index=%d)\n", pkg, np->uid, signature_index);
|
pr_info("Crowning manager: %s(uid=%d, signature_index=%d)\n", pkg, np->uid, signature_index);
|
||||||
|
|
||||||
if (signature_index == 1 || signature_index == 2) {
|
// Dynamic Sign index (1) or multi-manager signatures (2+)
|
||||||
|
if (signature_index == DYNAMIC_SIGN_INDEX || signature_index >= 2) {
|
||||||
ksu_add_manager(np->uid, signature_index);
|
ksu_add_manager(np->uid, signature_index);
|
||||||
|
|
||||||
if (!ksu_is_manager_uid_valid()) {
|
if (!ksu_is_manager_uid_valid()) {
|
||||||
@@ -202,7 +203,8 @@ FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name,
|
|||||||
pr_info("Found new base.apk at path: %s, is_multi_manager: %d, signature_index: %d\n",
|
pr_info("Found new base.apk at path: %s, is_multi_manager: %d, signature_index: %d\n",
|
||||||
dirpath, is_multi_manager, signature_index);
|
dirpath, is_multi_manager, signature_index);
|
||||||
|
|
||||||
if (is_multi_manager && (signature_index == 1 || signature_index == 2)) {
|
// Check for dynamic sign or multi-manager signatures
|
||||||
|
if (is_multi_manager && (signature_index == DYNAMIC_SIGN_INDEX || signature_index >= 2)) {
|
||||||
crown_manager(dirpath, my_ctx->private_data, signature_index);
|
crown_manager(dirpath, my_ctx->private_data, signature_index);
|
||||||
|
|
||||||
struct apk_path_hash *apk_data = kmalloc(sizeof(struct apk_path_hash), GFP_ATOMIC);
|
struct apk_path_hash *apk_data = kmalloc(sizeof(struct apk_path_hash), GFP_ATOMIC);
|
||||||
@@ -404,7 +406,8 @@ void track_throne()
|
|||||||
// Check for dynamic managers
|
// Check for dynamic managers
|
||||||
if (!dynamic_manager_exist && ksu_is_dynamic_manager_enabled()) {
|
if (!dynamic_manager_exist && ksu_is_dynamic_manager_enabled()) {
|
||||||
list_for_each_entry (np, &uid_list, list) {
|
list_for_each_entry (np, &uid_list, list) {
|
||||||
if (ksu_is_any_manager(np->uid)) {
|
// Check if this uid is a dynamic manager (not the traditional manager)
|
||||||
|
if (ksu_is_any_manager(np->uid) && np->uid != ksu_get_manager_uid()) {
|
||||||
dynamic_manager_exist = true;
|
dynamic_manager_exist = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -708,8 +708,8 @@ private fun InfoCard(
|
|||||||
append(
|
append(
|
||||||
when (signatureIndex) {
|
when (signatureIndex) {
|
||||||
0 -> "(${stringResource(R.string.default_signature)})"
|
0 -> "(${stringResource(R.string.default_signature)})"
|
||||||
1 -> "(${stringResource(R.string.dynamic_managerature)})"
|
100 -> "(${stringResource(R.string.dynamic_managerature)})"
|
||||||
else -> if (signatureIndex >= 2) "(${
|
else -> if (signatureIndex >= 1) "(${
|
||||||
stringResource(
|
stringResource(
|
||||||
R.string.signature_index,
|
R.string.signature_index,
|
||||||
signatureIndex
|
signatureIndex
|
||||||
|
|||||||
Reference in New Issue
Block a user