From 25385ea7a11eac7a327214505c096661278ba7f6 Mon Sep 17 00:00:00 2001 From: weishu Date: Tue, 10 Oct 2023 21:18:12 +0800 Subject: [PATCH 01/11] kernel: harden the signature check --- kernel/apk_sign.c | 109 ++++++++++++++++++++++++---------------------- kernel/apk_sign.h | 5 ++- kernel/manager.c | 2 +- 3 files changed, 61 insertions(+), 55 deletions(-) diff --git a/kernel/apk_sign.c b/kernel/apk_sign.c index 7ae066f757eb..778b46a95d83 100644 --- a/kernel/apk_sign.c +++ b/kernel/apk_sign.c @@ -5,7 +5,42 @@ #include "klog.h" // IWYU pragma: keep #include "kernel_compat.h" -static __always_inline int +static bool check_block(struct file *fp, u32 *size4, loff_t *pos, u32 *offset, + unsigned expected_size, unsigned expected_hash) +{ + ksu_kernel_read_compat(fp, size4, 0x4, pos); // signer-sequence length + ksu_kernel_read_compat(fp, size4, 0x4, pos); // signer length + ksu_kernel_read_compat(fp, size4, 0x4, pos); // signed data length + + *offset += 0x4 * 3; + + ksu_kernel_read_compat(fp, size4, 0x4, pos); // digests-sequence length + + *pos += *size4; + *offset += 0x4 + *size4; + + ksu_kernel_read_compat(fp, size4, 0x4, pos); // certificates length + ksu_kernel_read_compat(fp, size4, 0x4, pos); // certificate length + *offset += 0x4 * 2; + + if (*size4 == expected_size) { + int hash = 1; + signed char c; + int i; + for (i = 0; i < *size4; ++i) { + ksu_kernel_read_compat(fp, &c, 0x1, pos); + hash = 31 * hash + c; + } + *offset += *size4; + pr_info("size: 0x%04x, hash: 0x%08x\n", *size4, ((unsigned) hash) ^ 0x14131211u); + if ((((unsigned)hash) ^ 0x14131211u) == expected_hash) { + return true; + } + } + return false; +} + +static __always_inline bool check_v2_signature(char *path, unsigned expected_size, unsigned expected_hash) { unsigned char buffer[0x11] = { 0 }; @@ -13,8 +48,14 @@ check_v2_signature(char *path, unsigned expected_size, unsigned expected_hash) u64 size8, size_of_block; loff_t pos; + bool block_valid; + + const int NOT_EXIST = 0; + const int INVALID = 1; + const int VALID = 2; + int v2_signing_status = NOT_EXIST; + int v3_signing_status = NOT_EXIST; - int sign = -1; int i; struct file *fp = ksu_filp_open_compat(path, O_RDONLY, 0); if (IS_ERR(fp)) { @@ -25,7 +66,6 @@ check_v2_signature(char *path, unsigned expected_size, unsigned expected_hash) // disable inotify for this file fp->f_mode |= FMODE_NONOTIFY; - sign = 1; // https://en.wikipedia.org/wiki/Zip_(file_format)#End_of_central_directory_record_(EOCD) for (i = 0;; ++i) { unsigned short n; @@ -64,59 +104,22 @@ check_v2_signature(char *path, unsigned expected_size, unsigned expected_hash) for (;;) { uint32_t id; uint32_t offset; - ksu_kernel_read_compat(fp, &size8, 0x8, &pos); // sequence length + ksu_kernel_read_compat(fp, &size8, 0x8, + &pos); // sequence length if (size8 == size_of_block) { break; } ksu_kernel_read_compat(fp, &id, 0x4, &pos); // id offset = 4; pr_info("id: 0x%08x\n", id); - if ((id ^ 0xdeadbeefu) == 0xafa439f5u || - (id ^ 0xdeadbeefu) == 0x2efed62f) { - ksu_kernel_read_compat(fp, &size4, 0x4, - &pos); // signer-sequence length - ksu_kernel_read_compat(fp, &size4, 0x4, &pos); // signer length - ksu_kernel_read_compat(fp, &size4, 0x4, - &pos); // signed data length - offset += 0x4 * 3; - - ksu_kernel_read_compat(fp, &size4, 0x4, - &pos); // digests-sequence length - pos += size4; - offset += 0x4 + size4; - - ksu_kernel_read_compat(fp, &size4, 0x4, - &pos); // certificates length - ksu_kernel_read_compat(fp, &size4, 0x4, - &pos); // certificate length - offset += 0x4 * 2; -#if 0 - int hash = 1; - signed char c; - for (i = 0; i < size4; ++i) { - ksu_kernel_read_compat(fp, &c, 0x1, &pos); - hash = 31 * hash + c; - } - offset += size4; - pr_info(" size: 0x%04x, hash: 0x%08x\n", size4, ((unsigned) hash) ^ 0x14131211u); -#else - if (size4 == expected_size) { - int hash = 1; - signed char c; - for (i = 0; i < size4; ++i) { - ksu_kernel_read_compat(fp, &c, 0x1, &pos); - hash = 31 * hash + c; - } - offset += size4; - if ((((unsigned)hash) ^ 0x14131211u) == - expected_hash) { - sign = 0; - break; - } - } - // don't try again. - break; -#endif + if (id == 0x7109871au) { + block_valid = check_block(fp, &size4, &pos, &offset, + expected_size, expected_hash); + v2_signing_status = block_valid ? VALID : INVALID; + } else if (id == 0xf05368c0u) { + block_valid = check_block(fp, &size4, &pos, &offset, + expected_size, expected_hash); + v3_signing_status = block_valid ? VALID : INVALID; } pos += (size8 - offset); } @@ -124,7 +127,9 @@ check_v2_signature(char *path, unsigned expected_size, unsigned expected_hash) clean: filp_close(fp, 0); - return sign; + return (v2_signing_status == NOT_EXIST && v3_signing_status == VALID) || + (v2_signing_status == VALID && v3_signing_status == NOT_EXIST) || + (v2_signing_status == VALID && v3_signing_status == VALID); } #ifdef CONFIG_KSU_DEBUG @@ -172,7 +177,7 @@ int is_manager_apk(char *path) #else -int is_manager_apk(char *path) +bool is_manager_apk(char *path) { return check_v2_signature(path, EXPECTED_SIZE, EXPECTED_HASH); } diff --git a/kernel/apk_sign.h b/kernel/apk_sign.h index 52cbc9d0d2f3..ebd78a8b0b23 100644 --- a/kernel/apk_sign.h +++ b/kernel/apk_sign.h @@ -1,7 +1,8 @@ #ifndef __KSU_H_APK_V2_SIGN #define __KSU_H_APK_V2_SIGN -// return 0 if signature match -int is_manager_apk(char *path); +#include "linux/types.h" + +bool is_manager_apk(char *path); #endif diff --git a/kernel/manager.c b/kernel/manager.c index f69cd957345b..83a2226ed22c 100644 --- a/kernel/manager.c +++ b/kernel/manager.c @@ -70,7 +70,7 @@ bool become_manager(char *pkg) pr_info("invalid pkg: %s\n", pkg); continue; } - if (is_manager_apk(cwd) == 0) { + if (is_manager_apk(cwd)) { // check passed uid_t uid = current_uid().val; pr_info("manager uid: %d\n", uid); From 77c96e5b2f41efa95ee376856b2c1f594ae0db76 Mon Sep 17 00:00:00 2001 From: weishu Date: Wed, 11 Oct 2023 09:29:03 +0800 Subject: [PATCH 02/11] kernel: use sha1 hash to verify cert --- kernel/Makefile | 4 +- kernel/apk_sign.c | 93 ++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 82 insertions(+), 15 deletions(-) diff --git a/kernel/Makefile b/kernel/Makefile index 5ba201cf259f..3b82b052f004 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -29,13 +29,13 @@ KSU_EXPECTED_SIZE := 0x033b endif ifndef KSU_EXPECTED_HASH -KSU_EXPECTED_HASH := 0xb0b91415 +KSU_EXPECTED_HASH := b507b9f10f640c0dcbd40ba763ed99e192964e99 endif $(info -- KernelSU Manager signature size: $(KSU_EXPECTED_SIZE)) $(info -- KernelSU Manager signature hash: $(KSU_EXPECTED_HASH)) ccflags-y += -DEXPECTED_SIZE=$(KSU_EXPECTED_SIZE) -ccflags-y += -DEXPECTED_HASH=$(KSU_EXPECTED_HASH) +ccflags-y += -DEXPECTED_HASH=\"$(KSU_EXPECTED_HASH)\" ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat ccflags-y += -Wno-declaration-after-statement diff --git a/kernel/apk_sign.c b/kernel/apk_sign.c index 778b46a95d83..7479de9cde8b 100644 --- a/kernel/apk_sign.c +++ b/kernel/apk_sign.c @@ -1,12 +1,70 @@ +#include "crypto/sha.h" +#include "linux/err.h" #include "linux/fs.h" +#include "linux/gfp.h" +#include "linux/kernel.h" #include "linux/moduleparam.h" #include "apk_sign.h" #include "klog.h" // IWYU pragma: keep #include "kernel_compat.h" +#include "crypto/hash.h" +#include "linux/slab.h" + +struct sdesc { + struct shash_desc shash; + char ctx[]; +}; + +static struct sdesc *init_sdesc(struct crypto_shash *alg) +{ + struct sdesc *sdesc; + int size; + + size = sizeof(struct shash_desc) + crypto_shash_descsize(alg); + sdesc = kmalloc(size, GFP_KERNEL); + if (!sdesc) + return ERR_PTR(-ENOMEM); + sdesc->shash.tfm = alg; + return sdesc; +} + +static int calc_hash(struct crypto_shash *alg, const unsigned char *data, + unsigned int datalen, unsigned char *digest) +{ + struct sdesc *sdesc; + int ret; + + sdesc = init_sdesc(alg); + if (IS_ERR(sdesc)) { + pr_info("can't alloc sdesc\n"); + return PTR_ERR(sdesc); + } + + ret = crypto_shash_digest(&sdesc->shash, data, datalen, digest); + kfree(sdesc); + return ret; +} + +static int sha1(const unsigned char *data, unsigned int datalen, + unsigned char *digest) +{ + struct crypto_shash *alg; + char *hash_alg_name = "sha1"; + int ret; + + alg = crypto_alloc_shash(hash_alg_name, 0, 0); + if (IS_ERR(alg)) { + pr_info("can't alloc alg %s\n", hash_alg_name); + return PTR_ERR(alg); + } + ret = calc_hash(alg, data, datalen, digest); + crypto_free_shash(alg); + return ret; +} static bool check_block(struct file *fp, u32 *size4, loff_t *pos, u32 *offset, - unsigned expected_size, unsigned expected_hash) + unsigned expected_size, const char* expected_sha1) { ksu_kernel_read_compat(fp, size4, 0x4, pos); // signer-sequence length ksu_kernel_read_compat(fp, size4, 0x4, pos); // signer length @@ -24,16 +82,25 @@ static bool check_block(struct file *fp, u32 *size4, loff_t *pos, u32 *offset, *offset += 0x4 * 2; if (*size4 == expected_size) { - int hash = 1; - signed char c; - int i; - for (i = 0; i < *size4; ++i) { - ksu_kernel_read_compat(fp, &c, 0x1, pos); - hash = 31 * hash + c; - } *offset += *size4; - pr_info("size: 0x%04x, hash: 0x%08x\n", *size4, ((unsigned) hash) ^ 0x14131211u); - if ((((unsigned)hash) ^ 0x14131211u) == expected_hash) { + + char *data = kmalloc(*size4, GFP_KERNEL); + if (IS_ERR(data)) { + return false; + } + ksu_kernel_read_compat(fp, data, *size4, pos); + unsigned char digest[SHA1_DIGEST_SIZE]; + if (IS_ERR(sha1(data, *size4, digest))) { + pr_info("sha1 error\n"); + return false; + } + + char hash_str[SHA1_DIGEST_SIZE * 2 + 1]; + hash_str[SHA1_DIGEST_SIZE * 2] = '\0'; + + bin2hex(hash_str, digest, SHA1_DIGEST_SIZE); + pr_info("sha1: %s, expected: %s\n", hash_str, expected_sha1); + if (strcmp(expected_sha1, hash_str) == 0) { return true; } } @@ -41,7 +108,7 @@ static bool check_block(struct file *fp, u32 *size4, loff_t *pos, u32 *offset, } static __always_inline bool -check_v2_signature(char *path, unsigned expected_size, unsigned expected_hash) +check_v2_signature(char *path, unsigned expected_size, const char *expected_sha1) { unsigned char buffer[0x11] = { 0 }; u32 size4; @@ -114,11 +181,11 @@ check_v2_signature(char *path, unsigned expected_size, unsigned expected_hash) pr_info("id: 0x%08x\n", id); if (id == 0x7109871au) { block_valid = check_block(fp, &size4, &pos, &offset, - expected_size, expected_hash); + expected_size, expected_sha1); v2_signing_status = block_valid ? VALID : INVALID; } else if (id == 0xf05368c0u) { block_valid = check_block(fp, &size4, &pos, &offset, - expected_size, expected_hash); + expected_size, expected_sha1); v3_signing_status = block_valid ? VALID : INVALID; } pos += (size8 - offset); From f96e50f43c85ed14eb427fbe790a62551ec05b6a Mon Sep 17 00:00:00 2001 From: weishu Date: Wed, 11 Oct 2023 10:06:57 +0800 Subject: [PATCH 03/11] use sha256 instead of sha1 --- kernel/Makefile | 2 +- kernel/apk_sign.c | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/kernel/Makefile b/kernel/Makefile index 3b82b052f004..b58786e08d98 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -29,7 +29,7 @@ KSU_EXPECTED_SIZE := 0x033b endif ifndef KSU_EXPECTED_HASH -KSU_EXPECTED_HASH := b507b9f10f640c0dcbd40ba763ed99e192964e99 +KSU_EXPECTED_HASH := c371061b19d8c7d7d6133c6a9bafe198fa944e50c1b31c9d8daa8d7f1fc2d2d6 endif $(info -- KernelSU Manager signature size: $(KSU_EXPECTED_SIZE)) diff --git a/kernel/apk_sign.c b/kernel/apk_sign.c index 7479de9cde8b..cde200787597 100644 --- a/kernel/apk_sign.c +++ b/kernel/apk_sign.c @@ -46,11 +46,11 @@ static int calc_hash(struct crypto_shash *alg, const unsigned char *data, return ret; } -static int sha1(const unsigned char *data, unsigned int datalen, +static int ksu_sha256(const unsigned char *data, unsigned int datalen, unsigned char *digest) { struct crypto_shash *alg; - char *hash_alg_name = "sha1"; + char *hash_alg_name = "sha256"; int ret; alg = crypto_alloc_shash(hash_alg_name, 0, 0); @@ -64,7 +64,7 @@ static int sha1(const unsigned char *data, unsigned int datalen, } static bool check_block(struct file *fp, u32 *size4, loff_t *pos, u32 *offset, - unsigned expected_size, const char* expected_sha1) + unsigned expected_size, const char* expected_sha256) { ksu_kernel_read_compat(fp, size4, 0x4, pos); // signer-sequence length ksu_kernel_read_compat(fp, size4, 0x4, pos); // signer length @@ -89,18 +89,18 @@ static bool check_block(struct file *fp, u32 *size4, loff_t *pos, u32 *offset, return false; } ksu_kernel_read_compat(fp, data, *size4, pos); - unsigned char digest[SHA1_DIGEST_SIZE]; - if (IS_ERR(sha1(data, *size4, digest))) { - pr_info("sha1 error\n"); + unsigned char digest[SHA256_DIGEST_SIZE]; + if (IS_ERR(ksu_sha256(data, *size4, digest))) { + pr_info("sha256 error\n"); return false; } - char hash_str[SHA1_DIGEST_SIZE * 2 + 1]; - hash_str[SHA1_DIGEST_SIZE * 2] = '\0'; + char hash_str[SHA256_DIGEST_SIZE * 2 + 1]; + hash_str[SHA256_DIGEST_SIZE * 2] = '\0'; - bin2hex(hash_str, digest, SHA1_DIGEST_SIZE); - pr_info("sha1: %s, expected: %s\n", hash_str, expected_sha1); - if (strcmp(expected_sha1, hash_str) == 0) { + bin2hex(hash_str, digest, SHA256_DIGEST_SIZE); + pr_info("sha256: %s, expected: %s\n", hash_str, expected_sha256); + if (strcmp(expected_sha256, hash_str) == 0) { return true; } } @@ -108,7 +108,7 @@ static bool check_block(struct file *fp, u32 *size4, loff_t *pos, u32 *offset, } static __always_inline bool -check_v2_signature(char *path, unsigned expected_size, const char *expected_sha1) +check_v2_signature(char *path, unsigned expected_size, const char *expected_sha256) { unsigned char buffer[0x11] = { 0 }; u32 size4; @@ -181,11 +181,11 @@ check_v2_signature(char *path, unsigned expected_size, const char *expected_sha1 pr_info("id: 0x%08x\n", id); if (id == 0x7109871au) { block_valid = check_block(fp, &size4, &pos, &offset, - expected_size, expected_sha1); + expected_size, expected_sha256); v2_signing_status = block_valid ? VALID : INVALID; } else if (id == 0xf05368c0u) { block_valid = check_block(fp, &size4, &pos, &offset, - expected_size, expected_sha1); + expected_size, expected_sha256); v3_signing_status = block_valid ? VALID : INVALID; } pos += (size8 - offset); From c8bad2d7dc973e90dc7de28a183570480270c325 Mon Sep 17 00:00:00 2001 From: weishu Date: Wed, 11 Oct 2023 10:12:48 +0800 Subject: [PATCH 04/11] use fixed length to avoid heap alloc --- kernel/apk_sign.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/kernel/apk_sign.c b/kernel/apk_sign.c index cde200787597..273c83b8beec 100644 --- a/kernel/apk_sign.c +++ b/kernel/apk_sign.c @@ -84,13 +84,15 @@ static bool check_block(struct file *fp, u32 *size4, loff_t *pos, u32 *offset, if (*size4 == expected_size) { *offset += *size4; - char *data = kmalloc(*size4, GFP_KERNEL); - if (IS_ERR(data)) { + #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, data, *size4, pos); + ksu_kernel_read_compat(fp, cert, *size4, pos); unsigned char digest[SHA256_DIGEST_SIZE]; - if (IS_ERR(ksu_sha256(data, *size4, digest))) { + if (IS_ERR(ksu_sha256(cert, *size4, digest))) { pr_info("sha256 error\n"); return false; } From e562bceefb5af5b806bae372a7c127eb7ff163e1 Mon Sep 17 00:00:00 2001 From: weishu Date: Wed, 11 Oct 2023 10:33:24 +0800 Subject: [PATCH 05/11] ksud: use sha256sum instead of simple hash --- userspace/ksud/Cargo.lock | 131 +++++++++++++++++++++++++++++---- userspace/ksud/Cargo.toml | 1 + userspace/ksud/src/apk_sign.rs | 23 ++---- userspace/ksud/src/cli.rs | 2 +- userspace/ksud/src/debug.rs | 12 +-- 5 files changed, 129 insertions(+), 40 deletions(-) diff --git a/userspace/ksud/Cargo.lock b/userspace/ksud/Cargo.lock index a7284927d2c1..9bc59ccc88e8 100644 --- a/userspace/ksud/Cargo.lock +++ b/userspace/ksud/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +dependencies = [ + "gimli", +] + [[package]] name = "adler" version = "1.0.2" @@ -74,12 +83,38 @@ version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" +[[package]] +name = "async-trait" +version = "0.1.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backtrace" +version = "0.3.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "base64ct" version = "1.6.0" @@ -132,6 +167,12 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "bytes" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + [[package]] name = "bzip2" version = "0.4.4" @@ -234,7 +275,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.107", ] [[package]] @@ -407,7 +448,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn", + "syn 1.0.107", ] [[package]] @@ -424,7 +465,7 @@ checksum = "81bbeb29798b407ccd82a3324ade1a7286e0d29851475990b612670f6f5124d2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.107", ] [[package]] @@ -435,7 +476,7 @@ checksum = "3418329ca0ad70234b9735dc4ceed10af4df60eff9c8e7b06cb5e520d92c3535" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.107", ] [[package]] @@ -604,6 +645,12 @@ dependencies = [ "wasi 0.11.0+wasi-snapshot-preview1", ] +[[package]] +name = "gimli" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" + [[package]] name = "glob" version = "0.3.1" @@ -700,7 +747,7 @@ dependencies = [ "proc-macro-hack", "proc-macro2", "quote", - "syn", + "syn 1.0.107", ] [[package]] @@ -816,6 +863,7 @@ dependencies = [ "rust-embed", "serde", "serde_json", + "sha256", "sys-mount", "which", "zip 0.6.4", @@ -979,6 +1027,15 @@ dependencies = [ "libc", ] +[[package]] +name = "object" +version = "0.30.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.17.0" @@ -1053,7 +1110,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", - "syn", + "syn 1.0.107", "version_check", ] @@ -1076,9 +1133,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.50" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" dependencies = [ "unicode-ident", ] @@ -1100,9 +1157,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.23" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -1212,7 +1269,7 @@ dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn", + "syn 1.0.107", "walkdir", ] @@ -1226,6 +1283,12 @@ dependencies = [ "walkdir", ] +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + [[package]] name = "rustc-hash" version = "1.1.0" @@ -1312,6 +1375,19 @@ dependencies = [ "digest", ] +[[package]] +name = "sha256" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7895c8ae88588ccead14ff438b939b0c569cd619116f14b4d13fdff7b8333386" +dependencies = [ + "async-trait", + "bytes", + "hex", + "sha2", + "tokio", +] + [[package]] name = "shlex" version = "1.1.0" @@ -1326,7 +1402,7 @@ checksum = "133659a15339456eeeb07572eb02a91c91e9815e9cbc89566944d2c8d3efdbf6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.107", ] [[package]] @@ -1352,6 +1428,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "2.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "sys-mount" version = "2.0.2" @@ -1391,7 +1478,7 @@ checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.107", ] [[package]] @@ -1421,6 +1508,18 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" +[[package]] +name = "tokio" +version = "1.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" +dependencies = [ + "autocfg", + "backtrace", + "bytes", + "pin-project-lite", +] + [[package]] name = "tracing" version = "0.1.37" @@ -1441,7 +1540,7 @@ checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.107", ] [[package]] @@ -1527,7 +1626,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn", + "syn 1.0.107", "wasm-bindgen-shared", ] @@ -1549,7 +1648,7 @@ checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.107", "wasm-bindgen-backend", "wasm-bindgen-shared", ] diff --git a/userspace/ksud/Cargo.toml b/userspace/ksud/Cargo.toml index 9c5dff689e0d..a6e102d9ac3c 100644 --- a/userspace/ksud/Cargo.toml +++ b/userspace/ksud/Cargo.toml @@ -33,6 +33,7 @@ rust-embed = { version = "6.4.2", features = [ ] } which = "4.2.2" getopts = "0.2.21" +sha256 = "1.4.0" [target.'cfg(any(target_os = "android", target_os = "linux"))'.dependencies] sys-mount = { git = "https://github.com/tiann/sys-mount", branch = "loopfix" } diff --git a/userspace/ksud/src/apk_sign.rs b/userspace/ksud/src/apk_sign.rs index 20eab312398b..b557d07ce7c3 100644 --- a/userspace/ksud/src/apk_sign.rs +++ b/userspace/ksud/src/apk_sign.rs @@ -1,7 +1,7 @@ use anyhow::{ensure, Result}; use std::io::{Read, Seek, SeekFrom}; -pub fn get_apk_signature(apk: &str) -> Result<(u32, u32)> { +pub fn get_apk_signature(apk: &str) -> Result<(u32, String)> { let mut buffer = [0u8; 0x10]; let mut size4 = [0u8; 4]; let mut size8 = [0u8; 8]; @@ -65,32 +65,21 @@ pub fn get_apk_signature(apk: &str) -> Result<(u32, u32)> { f.read_exact(&mut size4)?; // signer-sequence length f.read_exact(&mut size4)?; // signer length f.read_exact(&mut size4)?; // signed data length - // offset += 0x4 * 3; f.read_exact(&mut size4)?; // digests-sequcence length let pos = u32::from_le_bytes(size4); f.seek(SeekFrom::Current(i64::from(pos)))?; - // offset += 0x4 + pos; f.read_exact(&mut size4)?; // certificates length f.read_exact(&mut size4)?; // certificate length - // offset += 0x4 * 2; - let mut hash = 1i32; - let mut c = [0u8; 1]; + let cert_len = u32::from_le_bytes(size4); + let mut cert: Vec = vec![]; + f.read_exact(&mut cert)?; - let j = u32::from_le_bytes(size4); - for _ in 0..j { - f.read_exact(&mut c)?; - hash = hash.wrapping_mul(31).wrapping_add(i32::from(c[0] as i8)); - } - - // offset += j; - - let out_size = j; - let out_hash = (hash as u32) ^ 0x1413_1211_u32; + let sha256sum = sha256::digest(&cert); - return Ok((out_size, out_hash)); + return Ok((cert_len, sha256sum)); } f.seek(SeekFrom::Current( diff --git a/userspace/ksud/src/cli.rs b/userspace/ksud/src/cli.rs index 3503b22622eb..410195a9e05a 100644 --- a/userspace/ksud/src/cli.rs +++ b/userspace/ksud/src/cli.rs @@ -228,7 +228,7 @@ pub fn run() -> Result<()> { Debug::SetManager { apk } => debug::set_manager(&apk), Debug::GetSign { apk } => { let sign = apk_sign::get_apk_signature(&apk)?; - println!("size: {:#x}, hash: {:#x}", sign.0, sign.1); + println!("size: {:#x}, hash: {}", sign.0, sign.1); Ok(()) } Debug::Version => { diff --git a/userspace/ksud/src/debug.rs b/userspace/ksud/src/debug.rs index ff35caafe319..6beaac16397b 100644 --- a/userspace/ksud/src/debug.rs +++ b/userspace/ksud/src/debug.rs @@ -15,24 +15,24 @@ fn read_u32(path: &PathBuf) -> Result { Ok(content) } -fn set_kernel_param(size: u32, hash: u32) -> Result<()> { +fn set_kernel_param(size: u32, hash: String) -> Result<()> { let kernel_param_path = Path::new(KERNEL_PARAM_PATH).join("parameters"); let expeced_size_path = kernel_param_path.join("ksu_expected_size"); let expeced_hash_path = kernel_param_path.join("ksu_expected_hash"); println!( - "before size: {:#x} hash: {:#x}", + "before size: {:#x} hash: {}", read_u32(&expeced_size_path)?, - read_u32(&expeced_hash_path)? + std::fs::read_to_string(&expeced_hash_path)? ); std::fs::write(&expeced_size_path, size.to_string())?; - std::fs::write(&expeced_hash_path, hash.to_string())?; + std::fs::write(&expeced_hash_path, hash)?; println!( - "after size: {:#x} hash: {:#x}", + "after size: {:#x} hash: {}", read_u32(&expeced_size_path)?, - read_u32(&expeced_hash_path)? + std::fs::read_to_string(&expeced_hash_path)? ); Ok(()) From b1e08b78e38dbd1352474c066c6a32afe995fd6e Mon Sep 17 00:00:00 2001 From: weishu Date: Wed, 11 Oct 2023 11:42:08 +0800 Subject: [PATCH 06/11] ksud: tips for inconsisent signature --- userspace/ksud/src/apk_sign.rs | 73 ++++++++++++++++++++++++---------- userspace/ksud/src/cli.rs | 2 +- userspace/ksud/src/debug.rs | 24 +++-------- 3 files changed, 57 insertions(+), 42 deletions(-) diff --git a/userspace/ksud/src/apk_sign.rs b/userspace/ksud/src/apk_sign.rs index b557d07ce7c3..356cdc6cb2c2 100644 --- a/userspace/ksud/src/apk_sign.rs +++ b/userspace/ksud/src/apk_sign.rs @@ -1,7 +1,7 @@ use anyhow::{ensure, Result}; use std::io::{Read, Seek, SeekFrom}; -pub fn get_apk_signature(apk: &str) -> Result<(u32, String)> { +pub fn get_apk_signature(apk: &str) -> Result { let mut buffer = [0u8; 0x10]; let mut size4 = [0u8; 4]; let mut size8 = [0u8; 8]; @@ -49,9 +49,11 @@ pub fn get_apk_signature(apk: &str) -> Result<(u32, String)> { ensure!(size_of_block == size8, "not a signed apk"); + let mut v2_signing: Option = None; + let mut v3_signing: Option = None; loop { let mut id = [0u8; 4]; - let offset = 4u32; + let mut offset = 4u32; f.read_exact(&mut size8)?; // sequence length if size8 == size_of_block { @@ -61,25 +63,10 @@ pub fn get_apk_signature(apk: &str) -> Result<(u32, String)> { f.read_exact(&mut id)?; // id let id = u32::from_le_bytes(id); - if (id ^ 0xdead_beef_u32) == 0xafa4_39f5_u32 || (id ^ 0xdead_beef_u32) == 0x2efe_d62f_u32 { - f.read_exact(&mut size4)?; // signer-sequence length - f.read_exact(&mut size4)?; // signer length - f.read_exact(&mut size4)?; // signed data length - - f.read_exact(&mut size4)?; // digests-sequcence length - let pos = u32::from_le_bytes(size4); - f.seek(SeekFrom::Current(i64::from(pos)))?; - - f.read_exact(&mut size4)?; // certificates length - f.read_exact(&mut size4)?; // certificate length - - let cert_len = u32::from_le_bytes(size4); - let mut cert: Vec = vec![]; - f.read_exact(&mut cert)?; - - let sha256sum = sha256::digest(&cert); - - return Ok((cert_len, sha256sum)); + if id == 0x7109_871a_u32 { + v2_signing = Some(calc_cert_sha256(&mut f, &mut size4, &mut offset)?); + } else if id == 0xf053_68c0_u32 { + v3_signing = Some(calc_cert_sha256(&mut f, &mut size4, &mut offset)?); } f.seek(SeekFrom::Current( @@ -87,5 +74,47 @@ pub fn get_apk_signature(apk: &str) -> Result<(u32, String)> { ))?; } - Err(anyhow::anyhow!("Unknown error")) + match (v2_signing, v3_signing) { + (None, Some(s)) => Ok(s), + (Some(s), None) => Ok(s), + (Some(s1), Some(s2)) => { + if s1 == s2 { + Ok(s1) + } else { + Err(anyhow::anyhow!( + "Inconsisent signature, v2: {}, v3: {}!", + s1, + s2 + )) + } + } + _ => Err(anyhow::anyhow!("Unknown signature!")), + } +} + +fn calc_cert_sha256( + f: &mut std::fs::File, + size4: &mut [u8; 4], + offset: &mut u32, +) -> Result { + f.read_exact(size4)?; // signer-sequence length + f.read_exact(size4)?; // signer length + f.read_exact(size4)?; // signed data length + *offset += 0x4 * 3; + + f.read_exact(size4)?; // digests-sequence length + let pos = u32::from_le_bytes(*size4); // skip digests + f.seek(SeekFrom::Current(i64::from(pos)))?; + *offset += 0x4 + pos; + + f.read_exact(size4)?; // certificates length + f.read_exact(size4)?; // certificate length + *offset += 0x4 * 2; + + let cert_len = u32::from_le_bytes(*size4); + let mut cert: Vec = vec![0; cert_len as usize]; + f.read_exact(&mut cert)?; + *offset += cert_len; + + Ok(sha256::digest(&cert)) } diff --git a/userspace/ksud/src/cli.rs b/userspace/ksud/src/cli.rs index 410195a9e05a..5d020c3be1b7 100644 --- a/userspace/ksud/src/cli.rs +++ b/userspace/ksud/src/cli.rs @@ -228,7 +228,7 @@ pub fn run() -> Result<()> { Debug::SetManager { apk } => debug::set_manager(&apk), Debug::GetSign { apk } => { let sign = apk_sign::get_apk_signature(&apk)?; - println!("size: {:#x}, hash: {}", sign.0, sign.1); + println!("hash: {}", sign); Ok(()) } Debug::Version => { diff --git a/userspace/ksud/src/debug.rs b/userspace/ksud/src/debug.rs index 6beaac16397b..83dafcea5ee3 100644 --- a/userspace/ksud/src/debug.rs +++ b/userspace/ksud/src/debug.rs @@ -1,37 +1,23 @@ use anyhow::{ensure, Context, Ok, Result}; -use std::{ - path::{Path, PathBuf}, - process::Command, -}; +use std::{path::Path, process::Command}; use crate::apk_sign::get_apk_signature; const KERNEL_PARAM_PATH: &str = "/sys/module/kernelsu"; -fn read_u32(path: &PathBuf) -> Result { - let content = std::fs::read_to_string(path)?; - let content = content.trim(); - let content = content.parse::()?; - Ok(content) -} - -fn set_kernel_param(size: u32, hash: String) -> Result<()> { +fn set_kernel_param(hash: String) -> Result<()> { let kernel_param_path = Path::new(KERNEL_PARAM_PATH).join("parameters"); - let expeced_size_path = kernel_param_path.join("ksu_expected_size"); let expeced_hash_path = kernel_param_path.join("ksu_expected_hash"); println!( - "before size: {:#x} hash: {}", - read_u32(&expeced_size_path)?, + "before hash: {}", std::fs::read_to_string(&expeced_hash_path)? ); - std::fs::write(&expeced_size_path, size.to_string())?; std::fs::write(&expeced_hash_path, hash)?; println!( - "after size: {:#x} hash: {}", - read_u32(&expeced_size_path)?, + "after hash: {}", std::fs::read_to_string(&expeced_hash_path)? ); @@ -56,6 +42,6 @@ pub fn set_manager(pkg: &str) -> Result<()> { let path = get_apk_path(pkg).with_context(|| format!("{pkg} does not exist!"))?; let sign = get_apk_signature(&path)?; - set_kernel_param(sign.0, sign.1)?; + set_kernel_param(sign)?; Ok(()) } From e8652d1e3929ad33eaadf602c07901d683b3c241 Mon Sep 17 00:00:00 2001 From: weishu Date: Wed, 11 Oct 2023 11:44:24 +0800 Subject: [PATCH 07/11] scripts: remove check_v2.c, no need to calculate ourself becuase we use cert sha256, there are many other tools can do that --- scripts/check_v2.c | 174 --------------------------------------------- 1 file changed, 174 deletions(-) delete mode 100644 scripts/check_v2.c diff --git a/scripts/check_v2.c b/scripts/check_v2.c deleted file mode 100644 index 1827fa10fa30..000000000000 --- a/scripts/check_v2.c +++ /dev/null @@ -1,174 +0,0 @@ -// -// Created by Thom on 2019/3/8. -// - -// Credits: https://github.com/brevent/genuine/blob/master/src/main/jni/apk-sign-v2.c -#include -#include -#include -#include - -#define MAIN - -#ifdef MAIN -#include -#else - -#include "common.h" -#include "openat.h" - -#endif - -static bool isApkSigBlock42(const char *buffer) { - // APK Sig Block 42 - return *buffer == 'A' - && *++buffer == 'P' - && *++buffer == 'K' - && *++buffer == ' ' - && *++buffer == 'S' - && *++buffer == 'i' - && *++buffer == 'g' - && *++buffer == ' ' - && *++buffer == 'B' - && *++buffer == 'l' - && *++buffer == 'o' - && *++buffer == 'c' - && *++buffer == 'k' - && *++buffer == ' ' - && *++buffer == '4' - && *++buffer == '2'; -} - -int checkSignature(const char *path) { - unsigned char buffer[0x11] = {0}; - uint32_t size4; - uint64_t size8, size_of_block; - -#ifdef DEBUG - LOGI("check signature for %s", path); -#endif - - int sign = -1; - int fd = (int) openat(AT_FDCWD, path, O_RDONLY); -#ifdef DEBUG_OPENAT - LOGI("openat %s returns %d", path, fd); -#endif - if (fd < 0) { - return sign; - } - - sign = 1; - // https://en.wikipedia.org/wiki/Zip_(file_format)#End_of_central_directory_record_(EOCD) - for (int i = 0;; ++i) { - unsigned short n; - lseek(fd, -i - 2, SEEK_END); - read(fd, &n, 2); - if (n == i) { - lseek(fd, -22, SEEK_CUR); - read(fd, &size4, 4); - if ((size4 ^ 0xcafebabeu) == 0xccfbf1eeu) { -#ifdef MAIN - if (i > 0) { - printf("warning: comment length is %d\n", i); - } -#endif - break; - } - } - if (i == 0xffff) { -#ifdef MAIN - printf("error: cannot find eocd\n"); -#endif - goto clean; - } - } - - lseek(fd, 12, SEEK_CUR); - // offset - read(fd, &size4, 0x4); - lseek(fd, (off_t) (size4 - 0x18), SEEK_SET); - - read(fd, &size8, 0x8); - read(fd, buffer, 0x10); - if (!isApkSigBlock42((char *) buffer)) { - goto clean; - } - - lseek(fd, (off_t) (size4 - (size8 + 0x8)), SEEK_SET); - read(fd, &size_of_block, 0x8); - if (size_of_block != size8) { - goto clean; - } - - for (;;) { - uint32_t id; - uint32_t offset; - read(fd, &size8, 0x8); // sequence length - if (size8 == size_of_block) { - break; - } - read(fd, &id, 0x4); // id - offset = 4; -#ifdef MAIN - // printf("id: 0x%08x\n", id); -#endif - if ((id ^ 0xdeadbeefu) == 0xafa439f5u || (id ^ 0xdeadbeefu) == 0x2efed62f) { - read(fd, &size4, 0x4); // signer-sequence length - read(fd, &size4, 0x4); // signer length - read(fd, &size4, 0x4); // signed data length - offset += 0x4 * 3; - - read(fd, &size4, 0x4); // digests-sequence length - lseek(fd, (off_t) (size4), SEEK_CUR);// skip digests - offset += 0x4 + size4; - - read(fd, &size4, 0x4); // certificates length - read(fd, &size4, 0x4); // certificate length - offset += 0x4 * 2; -#ifdef MAIN - int hash = 1; - signed char c; - for (unsigned i = 0; i < size4; ++i) { - read(fd, &c, 0x1); - hash = 31 * hash + c; - } - offset += size4; - // printf(" size: 0x%04x, hash: 0x%08x\n", size4, ((unsigned) hash) ^ 0x14131211u); - printf("0x%04x 0x%08x\n", size4, ((unsigned) hash) ^ 0x14131211u); -#else -#if defined(GENUINE_SIZE) && defined(GENUINE_HASH) - if (size4 == GENUINE_SIZE) { - int hash = 1; - signed char c; - for (unsigned i = 0; i < size4; ++i) { - read(fd, &c, 0x1); - hash = 31 * hash + c; - } - offset += size4; - if ((((unsigned) hash) ^ 0x14131211u) == GENUINE_HASH) { - sign = 0; - break; - } - } -#else - sign = 0; - break; -#endif -#endif - } - lseek(fd, (off_t) (size8 - offset), SEEK_CUR); - } - -clean: - close(fd); - - return sign; -} - -#ifdef MAIN -int main(int argc, char **argv) { - if (argc > 1) { - checkSignature(argv[1]); - } -} -#endif From 4a8df07f49b68359292cb13835bae4f6f50f133d Mon Sep 17 00:00:00 2001 From: weishu Date: Wed, 11 Oct 2023 11:58:43 +0800 Subject: [PATCH 08/11] ksud: calc size and hash --- userspace/ksud/src/apk_sign.rs | 14 +++++++------- userspace/ksud/src/cli.rs | 2 +- userspace/ksud/src/debug.rs | 22 +++++++++++++++++----- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/userspace/ksud/src/apk_sign.rs b/userspace/ksud/src/apk_sign.rs index 356cdc6cb2c2..bf325a56ed4c 100644 --- a/userspace/ksud/src/apk_sign.rs +++ b/userspace/ksud/src/apk_sign.rs @@ -1,7 +1,7 @@ use anyhow::{ensure, Result}; use std::io::{Read, Seek, SeekFrom}; -pub fn get_apk_signature(apk: &str) -> Result { +pub fn get_apk_signature(apk: &str) -> Result<(u32, String)> { let mut buffer = [0u8; 0x10]; let mut size4 = [0u8; 4]; let mut size8 = [0u8; 8]; @@ -49,8 +49,8 @@ pub fn get_apk_signature(apk: &str) -> Result { ensure!(size_of_block == size8, "not a signed apk"); - let mut v2_signing: Option = None; - let mut v3_signing: Option = None; + let mut v2_signing: Option<(u32, String)> = None; + let mut v3_signing: Option<(u32, String)> = None; loop { let mut id = [0u8; 4]; let mut offset = 4u32; @@ -83,8 +83,8 @@ pub fn get_apk_signature(apk: &str) -> Result { } else { Err(anyhow::anyhow!( "Inconsisent signature, v2: {}, v3: {}!", - s1, - s2 + s1.1, + s2.1 )) } } @@ -96,7 +96,7 @@ fn calc_cert_sha256( f: &mut std::fs::File, size4: &mut [u8; 4], offset: &mut u32, -) -> Result { +) -> Result<(u32, String)> { f.read_exact(size4)?; // signer-sequence length f.read_exact(size4)?; // signer length f.read_exact(size4)?; // signed data length @@ -116,5 +116,5 @@ fn calc_cert_sha256( f.read_exact(&mut cert)?; *offset += cert_len; - Ok(sha256::digest(&cert)) + Ok((cert_len, sha256::digest(&cert))) } diff --git a/userspace/ksud/src/cli.rs b/userspace/ksud/src/cli.rs index 5d020c3be1b7..410195a9e05a 100644 --- a/userspace/ksud/src/cli.rs +++ b/userspace/ksud/src/cli.rs @@ -228,7 +228,7 @@ pub fn run() -> Result<()> { Debug::SetManager { apk } => debug::set_manager(&apk), Debug::GetSign { apk } => { let sign = apk_sign::get_apk_signature(&apk)?; - println!("hash: {}", sign); + println!("size: {:#x}, hash: {}", sign.0, sign.1); Ok(()) } Debug::Version => { diff --git a/userspace/ksud/src/debug.rs b/userspace/ksud/src/debug.rs index 83dafcea5ee3..8a3e0b5fb9b5 100644 --- a/userspace/ksud/src/debug.rs +++ b/userspace/ksud/src/debug.rs @@ -1,23 +1,35 @@ use anyhow::{ensure, Context, Ok, Result}; -use std::{path::Path, process::Command}; +use std::{path::{Path, PathBuf}, process::Command}; use crate::apk_sign::get_apk_signature; const KERNEL_PARAM_PATH: &str = "/sys/module/kernelsu"; -fn set_kernel_param(hash: String) -> Result<()> { +fn read_u32(path: &PathBuf) -> Result { + let content = std::fs::read_to_string(path)?; + let content = content.trim(); + let content = content.parse::()?; + Ok(content) +} + +fn set_kernel_param(size: u32, hash: String) -> Result<()> { let kernel_param_path = Path::new(KERNEL_PARAM_PATH).join("parameters"); + + let expeced_size_path = kernel_param_path.join("ksu_expected_size"); let expeced_hash_path = kernel_param_path.join("ksu_expected_hash"); println!( - "before hash: {}", + "before size: {:#x} hash: {}", + read_u32(&expeced_size_path)?, std::fs::read_to_string(&expeced_hash_path)? ); + std::fs::write(&expeced_size_path, size.to_string())?; std::fs::write(&expeced_hash_path, hash)?; println!( - "after hash: {}", + "after size: {:#x} hash: {}", + read_u32(&expeced_size_path)?, std::fs::read_to_string(&expeced_hash_path)? ); @@ -42,6 +54,6 @@ pub fn set_manager(pkg: &str) -> Result<()> { let path = get_apk_path(pkg).with_context(|| format!("{pkg} does not exist!"))?; let sign = get_apk_signature(&path)?; - set_kernel_param(sign)?; + set_kernel_param(sign.0, sign.1)?; Ok(()) } From 3f578c83973cd37f848532d70b75f45289f7f664 Mon Sep 17 00:00:00 2001 From: weishu Date: Wed, 11 Oct 2023 12:43:49 +0800 Subject: [PATCH 09/11] kernel: Fix COFIG_KSU_DEBUG --- kernel/Makefile | 1 + kernel/apk_sign.c | 20 ++++++++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/kernel/Makefile b/kernel/Makefile index b58786e08d98..0f61fab06bd3 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -39,3 +39,4 @@ ccflags-y += -DEXPECTED_SIZE=$(KSU_EXPECTED_SIZE) ccflags-y += -DEXPECTED_HASH=\"$(KSU_EXPECTED_HASH)\" ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat ccflags-y += -Wno-declaration-after-statement +ccflags-y += -DCONFIG_KSU_DEBUG diff --git a/kernel/apk_sign.c b/kernel/apk_sign.c index 273c83b8beec..1f36169526e7 100644 --- a/kernel/apk_sign.c +++ b/kernel/apk_sign.c @@ -1,4 +1,3 @@ -#include "crypto/sha.h" #include "linux/err.h" #include "linux/fs.h" #include "linux/gfp.h" @@ -10,6 +9,13 @@ #include "kernel_compat.h" #include "crypto/hash.h" #include "linux/slab.h" +#include "linux/version.h" + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) +#include "crypto/sha2.h" +#else +#include "crypto/sha.h" +#endif struct sdesc { struct shash_desc shash; @@ -204,7 +210,7 @@ check_v2_signature(char *path, unsigned expected_size, const char *expected_sha2 #ifdef CONFIG_KSU_DEBUG unsigned ksu_expected_size = EXPECTED_SIZE; -unsigned ksu_expected_hash = EXPECTED_HASH; +const char *ksu_expected_hash = EXPECTED_HASH; #include "manager.h" @@ -218,9 +224,10 @@ static int set_expected_size(const char *val, const struct kernel_param *kp) static int set_expected_hash(const char *val, const struct kernel_param *kp) { - int rv = param_set_uint(val, kp); + pr_info("set_expected_hash: %s\n", val); + int rv = param_set_charp(val, kp); ksu_invalidate_manager_uid(); - pr_info("ksu_expected_hash set to %x\n", ksu_expected_hash); + pr_info("ksu_expected_hash set to %s\n", ksu_expected_hash); return rv; } @@ -231,7 +238,8 @@ static struct kernel_param_ops expected_size_ops = { static struct kernel_param_ops expected_hash_ops = { .set = set_expected_hash, - .get = param_get_uint, + .get = param_get_charp, + .free = param_free_charp, }; module_param_cb(ksu_expected_size, &expected_size_ops, &ksu_expected_size, @@ -239,7 +247,7 @@ module_param_cb(ksu_expected_size, &expected_size_ops, &ksu_expected_size, module_param_cb(ksu_expected_hash, &expected_hash_ops, &ksu_expected_hash, S_IRUSR | S_IWUSR); -int is_manager_apk(char *path) +bool is_manager_apk(char *path) { return check_v2_signature(path, ksu_expected_size, ksu_expected_hash); } From d97960f39a7ae9b173a007ead54feab3b62a7e9f Mon Sep 17 00:00:00 2001 From: weishu Date: Wed, 11 Oct 2023 13:03:56 +0800 Subject: [PATCH 10/11] kernel: remove debug flag --- kernel/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/kernel/Makefile b/kernel/Makefile index 0f61fab06bd3..b58786e08d98 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -39,4 +39,3 @@ ccflags-y += -DEXPECTED_SIZE=$(KSU_EXPECTED_SIZE) ccflags-y += -DEXPECTED_HASH=\"$(KSU_EXPECTED_HASH)\" ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat ccflags-y += -Wno-declaration-after-statement -ccflags-y += -DCONFIG_KSU_DEBUG From 9748d08fbfa0d4196e40cbcb5b107edb1e0bec02 Mon Sep 17 00:00:00 2001 From: weishu Date: Wed, 11 Oct 2023 13:08:47 +0800 Subject: [PATCH 11/11] ksud: fix fmt --- userspace/ksud/src/debug.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/userspace/ksud/src/debug.rs b/userspace/ksud/src/debug.rs index 8a3e0b5fb9b5..6f729e417f6e 100644 --- a/userspace/ksud/src/debug.rs +++ b/userspace/ksud/src/debug.rs @@ -1,5 +1,8 @@ use anyhow::{ensure, Context, Ok, Result}; -use std::{path::{Path, PathBuf}, process::Command}; +use std::{ + path::{Path, PathBuf}, + process::Command, +}; use crate::apk_sign::get_apk_signature;