diff --git a/kernel/Makefile b/kernel/Makefile index 5ba201cf259f..b58786e08d98 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 := c371061b19d8c7d7d6133c6a9bafe198fa944e50c1b31c9d8daa8d7f1fc2d2d6 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 7ae066f757eb..5f7175c8d1db 100644 --- a/kernel/apk_sign.c +++ b/kernel/apk_sign.c @@ -1,12 +1,122 @@ +#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" +#include "linux/version.h" -static __always_inline int -check_v2_signature(char *path, unsigned expected_size, unsigned expected_hash) +#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; + 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 ksu_sha256(const unsigned char *data, unsigned int datalen, + unsigned char *digest) +{ + struct crypto_shash *alg; + char *hash_alg_name = "sha256"; + 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, 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 + 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) { + *offset += *size4; + + #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 (IS_ERR(ksu_sha256(cert, *size4, digest))) { + 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\n", hash_str, expected_sha256); + if (strcmp(expected_sha256, hash_str) == 0) { + return true; + } + } + return false; +} + +static __always_inline bool +check_v2_signature(char *path, unsigned expected_size, const char *expected_sha256) { unsigned char buffer[0x11] = { 0 }; u32 size4; @@ -14,7 +124,10 @@ check_v2_signature(char *path, unsigned expected_size, unsigned expected_hash) loff_t pos; - int sign = -1; + bool v2_signing_valid = false; + bool v3_signing_exist = false; + bool v3_1_signing_exist = false; + int i; struct file *fp = ksu_filp_open_compat(path, O_RDONLY, 0); if (IS_ERR(fp)) { @@ -25,7 +138,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 +176,23 @@ 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) { + v2_signing_valid = check_block(fp, &size4, &pos, &offset, + expected_size, expected_sha256); + } else if (id == 0xf05368c0u) { + // http://aospxref.com/android-14.0.0_r2/xref/frameworks/base/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java#73 + v3_signing_exist = true; + } else if (id == 0x1b93ad61u) { + // http://aospxref.com/android-14.0.0_r2/xref/frameworks/base/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java#74 + v3_1_signing_exist = true; } pos += (size8 - offset); } @@ -124,13 +200,18 @@ check_v2_signature(char *path, unsigned expected_size, unsigned expected_hash) clean: filp_close(fp, 0); - return sign; + if (v3_signing_exist || v3_1_signing_exist) { + pr_err("Unexpected v3 signature scheme found!\n"); + return false; + } + + return v2_signing_valid; } #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" @@ -144,9 +225,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; } @@ -157,7 +239,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, @@ -165,14 +248,14 @@ 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); } #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); 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 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..9e8dad3fedf7 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]; @@ -49,9 +49,13 @@ pub fn get_apk_signature(apk: &str) -> Result<(u32, u32)> { ensure!(size_of_block == size8, "not a signed apk"); + let mut v2_signing: Option<(u32, String)> = None; + let mut v3_signing_exist = false; + let mut v3_1_signing_exist = false; + 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,36 +65,14 @@ pub fn get_apk_signature(apk: &str) -> Result<(u32, u32)> { 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 - // 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 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; - - return Ok((out_size, out_hash)); + if id == 0x7109_871a_u32 { + v2_signing = Some(calc_cert_sha256(&mut f, &mut size4, &mut offset)?); + } else if id == 0xf053_68c0_u32 { + // v3 signature scheme + v3_signing_exist = true; + } else if id == 0x1b93_ad61_u32 { + // v3.1 signature scheme: credits to vvb2060 + v3_1_signing_exist = true; } f.seek(SeekFrom::Current( @@ -98,5 +80,39 @@ pub fn get_apk_signature(apk: &str) -> Result<(u32, u32)> { ))?; } - Err(anyhow::anyhow!("Unknown error")) + if v3_signing_exist || v3_1_signing_exist { + return Err(anyhow::anyhow!( + "Unexpected v3 signature found!", + )); + } + + v2_signing.ok_or(anyhow::anyhow!("No signature found!")) + +} + +fn calc_cert_sha256( + f: &mut std::fs::File, + size4: &mut [u8; 4], + offset: &mut u32, +) -> Result<(u32, String)> { + 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((cert_len, sha256::digest(&cert))) } 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..6f729e417f6e 100644 --- a/userspace/ksud/src/debug.rs +++ b/userspace/ksud/src/debug.rs @@ -15,24 +15,25 @@ 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(()) diff --git a/website/docs/pt_BR/guide/app-profile.md b/website/docs/pt_BR/guide/app-profile.md index 719ef10d96c5..f724327ad6b4 100644 --- a/website/docs/pt_BR/guide/app-profile.md +++ b/website/docs/pt_BR/guide/app-profile.md @@ -2,17 +2,17 @@ O Perfil do Aplicativo é um mecanismo fornecido pelo KernelSU para personalizar a configuração de vários apps. -Para apps com permissões de root (ou seja, capazes de usar `su`), o Perfil do Aplicativo também pode ser chamado de Perfil Raiz. Ele permite a customização das regras `uid`, `gid`, `groups`, `capabilities` e `SELinux` do comando `su`, restringindo assim os privilégios do usuário root. Por exemplo, ele pode conceder permissões de rede apenas para apps de firewall enquanto nega permissões de acesso a arquivos, ou pode conceder permissões de shell em vez de acesso root completo para apps congelados: **mantendo o poder confinado com o princípio do menor privilégio.** +Para apps com permissões de root (ou seja, capazes de usar `su`), o Perfil do Aplicativo também pode ser chamado de Perfil Root. Ele permite a customização das regras `uid`, `gid`, `groups`, `capabilities` e `SELinux` do comando `su`, restringindo assim os privilégios do usuário root. Por exemplo, ele pode conceder permissões de rede apenas para apps de firewall enquanto nega permissões de acesso a arquivos, ou pode conceder permissões de shell em vez de acesso root completo para apps congelados: **mantendo o poder confinado com o princípio do menor privilégio.** Para apps comuns sem permissões de root, o Perfil do Aplicativo pode controlar o comportamento do kernel e do sistema de módulos em relação a esses apps. Por exemplo, pode determinar se as modificações resultantes dos módulos devem ser abordadas. O kernel e o sistema de módulos podem tomar decisões com base nesta configuração, como realizar operações semelhantes a "ocultar" -## Perfil Raiz +## Perfil Root ### UID, GID e Grupos Os sistemas Linux possuem dois conceitos: usuários e grupos. Cada usuário possui um ID de usuário (UID) e um usuário pode pertencer a vários grupos, cada um com seu próprio ID de grupo (GID). Esses IDs são usados ​​para identificar usuários no sistema e determinar quais recursos do sistema eles podem acessar. -Os usuários com UID 0 são conhecidos como usuários root e os grupos com GID 0 são conhecidos como grupos raiz. O grupo de usuários root normalmente possui os privilégios de sistema mais altos. +Os usuários com UID 0 são conhecidos como usuários root e os grupos com GID 0 são conhecidos como grupos root. O grupo de usuários root normalmente possui os privilégios de sistema mais altos. No caso do sistema Android, cada app é um usuário separado (excluindo cenários de UID compartilhados) com um UID exclusivo. Por exemplo, `0` representa o usuário root, `1000` representa `system`, `2000` representa o ADB shell e UIDs variando de `10.000` a `19.999` representam apps comuns. @@ -31,33 +31,33 @@ uid=2000(shell) gid=2000(shell) groups=2000(shell),1004(input),1007(log),1011(ad Aqui, o UID é `2000` e o GID (ID do grupo primário) também é `2000`. Além disso, pertence a vários grupos suplementares, como `inet` (indicando a capacidade de criar soquetes `AF_INET` e `AF_INET6`) e `sdcard_rw` (indicando permissões de leitura/gravação para o cartão SD). -O Perfil Raiz do KernelSU permite a personalização do UID, GID e grupos para o processo root após a execução de `su`. Por exemplo, o Perfil Raiz de um app root pode definir seu UID como `2000`, o que significa que ao usar `su`, as permissões reais do app estão no nível do ADB shell. O grupo `inet` pode ser removido, evitando que o comando `su` acesse a rede. +O Perfil Root do KernelSU permite a personalização do UID, GID e grupos para o processo root após a execução de `su`. Por exemplo, o Perfil Root de um app root pode definir seu UID como `2000`, que significa que ao usar `su`, as permissões reais do app estão no nível do ADB shell. O grupo `inet` pode ser removido, evitando que o comando `su` acesse a rede. :::tip OBSERVAÇÃO O Perfil do Aplicativo controla apenas as permissões do processo root após usar `su`, e ele não controla as permissões do próprio app. Se um app solicitou permissão de acesso à rede, ele ainda poderá acessar a rede mesmo sem usar `su`. Remover o grupo `inet` de `su` apenas impede que `su` acesse a rede. ::: -O Perfil Raiz é aplicado no kernel e não depende do comportamento voluntário de apps root, ao contrário da troca de usuários ou grupos por meio do `su`, a concessão da permissão `su` depende inteiramente do usuário e não do desenvolvedor. +O Perfil Root é aplicado no kernel e não depende do comportamento voluntário de apps root, ao contrário da troca de usuários ou grupos por meio de `su`, a concessão da permissão `su` depende inteiramente do usuário e não do desenvolvedor. ### Capacidades As capacidades são um mecanismo para separação de privilégios no Linux. -Para realizar verificações de permissão, as implementações tradicionais do `UNIX` distinguem duas categorias de processos: processos privilegiados (cujo ID de usuário efetivo é `0`, referido como superusuário ou root) e processos sem privilégios (cujo UID efetivo é diferente de zero). Os processos privilegiados ignoram todas as verificações de permissão do kernel, enquanto os processos não privilegiados estão sujeitos à verificação completa de permissão com base nas credenciais do processo (Geralmente: UID efetivo, GID efetivo e lista de grupos suplementares). +Para realizar verificações de permissão, as implementações tradicionais do `UNIX` distinguem duas categorias de processos: processos privilegiados (cujo ID de usuário efetivo é `0`, referido como superusuário ou root) e processos sem privilégios (cujo UID efetivo é diferente de zero). Os processos privilegiados ignoram todas as verificações de permissão do kernel, enquanto os processos não privilegiados estão sujeitos à verificação completa de permissão com base nas credenciais do processo (geralmente: UID efetivo, GID efetivo e lista de grupos suplementares). A partir do Linux 2.2, o Linux divide os privilégios tradicionalmente associados ao superusuário em unidades distintas, conhecidas como capacidades, que podem ser ativadas e desativadas de forma independente. Cada capacidade representa um ou mais privilégios. Por exemplo, `CAP_DAC_READ_SEARCH` representa a capacidade de ignorar verificações de permissão para leitura de arquivos, bem como permissões de leitura e execução de diretório. Se um usuário com um UID efetivo `0` (usuário root) não tiver recursos `CAP_DAC_READ_SEARCH` ou superiores, isso significa que mesmo sendo root, ele não pode ler arquivos à vontade. -O Perfil Raiz do KernelSU permite a personalização das capacidades do processo root após a execução de `su`, conseguindo assim conceder parcialmente "permissões de root". Ao contrário do UID e GID mencionados acima, certos apps root exigem um UID de `0` após usar `su`. Nesses casos, limitar as capacidades deste usuário root com UID `0` pode restringir suas operações permitidas. +O Perfil Root do KernelSU permite a personalização das capacidades do processo root após a execução de `su`, conseguindo assim conceder parcialmente "permissões de root". Ao contrário do UID e GID mencionados acima, certos apps root exigem um UID de `0` após usar `su`. Nesses casos, limitar as capacidades deste usuário root com UID `0` pode restringir suas operações permitidas. :::tip FORTE RECOMENDAÇÃO -Capacidade do Linux [documentação oficial](https://man7.org/linux/man-pages/man7/capabilities.7.html) fornece explicações detalhadas das habilidades representadas por cada capacidade. Se você pretende customizar Capacidades, é altamente recomendável que você leia este documento primeiro. +A [documentação oficial](https://man7.org/linux/man-pages/man7/capabilities.7.html) da Capacidade do Linux fornece explicações detalhadas das habilidades representadas por cada Capacidade. Se você pretende customizar Capacidades, é altamente recomendável que você leia este documento primeiro. ::: ### SELinux -SELinux é um poderoso mecanismo do Controle de Acesso Obrigatório (MAC). Ele opera com base no princípio de **negação padrão**: qualquer ação não explicitamente permitida é negada. +SELinux é um poderoso mecanismo do Controle de Acesso Obrigatório (MAC). Ele opera com base no princípio de **negação padrão**. Qualquer ação não explicitamente permitida é negada. O SELinux pode ser executado em dois modos globais: @@ -89,9 +89,9 @@ Observe que a regra `allow app1 * * *` é usada apenas para fins de demonstraç ### Escalação -Se a configuração do Perfil Root não estiver definida corretamente, poderá ocorrer um cenário de escalonamento: as restrições impostas pelo Perfil Root poderão falhar involuntariamente. +Se a configuração do Perfil Root não estiver definida corretamente, poderá ocorrer um cenário de escalação. As restrições impostas pelo Perfil Root poderão falhar involuntariamente. -Por exemplo, se você conceder permissão root a um usuário ADB shell (que é um caso comum) e, em seguida, conceder permissão root a um app normal, mas configurar seu perfil root com UID 2000 (que é o UID do usuário ADB shell), o app pode obter acesso root completo executando o comando `su` duas vezes: +Por exemplo, se você conceder permissão root a um usuário ADB shell (que é um caso comum) e, em seguida, conceder permissão root a um app normal, mas configurar seu Perfil Root com UID 2000 (que é o UID do usuário ADB shell), o app pode obter acesso root completo executando o comando `su` duas vezes: 1. A primeira execução `su` está sujeita à aplicação do Perfil do Aplicativo e mudará para UID `2000` (adb shell) em vez de `0` (root). 2. A segunda execução `su`, como o UID é `2000` e você concedeu acesso root ao UID `2000` (adb shell) na configuração, o app obterá privilégio de root completo. @@ -99,14 +99,14 @@ Por exemplo, se você conceder permissão root a um usuário ADB shell (que é u :::warning OBSERVAÇÃO Este comportamento é totalmente esperado e não é um bug. Portanto, recomendamos o seguinte: -Se você realmente precisa conceder permissões de root ao ADB (por exemplo, como desenvolvedor), não é aconselhável alterar o UID para `2000` ao configurar o Perfil Root. Usar `1000` (sistema) seria uma melhor escolha. +Se você realmente precisa conceder permissões de root ao ADB (por exemplo, como desenvolvedor), não é aconselhável alterar o UID para `2000` ao configurar o Perfil Root. Usar `1000` (system) seria uma melhor escolha. ::: ## Perfil não Root -### Desmontar Módulos +### Desmontar módulos -O KernelSU fornece um mecanismo sem sistema para modificar partições do sistema, obtido através da montagem de overlayfs. No entanto, alguns apps podem ser sensíveis a esse comportamento. Assim, podemos descarregar módulos montados nesses apps configurando a opção “desmontar módulo”. +O KernelSU fornece um mecanismo sem sistema para modificar partições do sistema, obtido através da montagem de overlayfs. No entanto, alguns apps podem ser sensíveis a esse comportamento. Assim, podemos descarregar módulos montados nesses apps configurando a opção “desmontar módulos”. Além disso, a interface de configurações do gerenciador KernelSU fornece uma opção para "desmontar módulos por padrão". Por padrão, essa opção está **ativada**, o que significa que o KernelSU ou alguns módulos descarregarão módulos para este app, a menos que configurações adicionais sejam aplicadas. Se você não preferir esta configuração ou se ela afetar determinados apps, você terá as seguintes opções: diff --git a/website/docs/pt_BR/guide/difference-with-magisk.md b/website/docs/pt_BR/guide/difference-with-magisk.md index 798b5021e7cb..a84357f7ead4 100644 --- a/website/docs/pt_BR/guide/difference-with-magisk.md +++ b/website/docs/pt_BR/guide/difference-with-magisk.md @@ -4,14 +4,14 @@ Embora existam muitas semelhanças entre os módulos KernelSU e os módulos Magi ## Semelhanças -- Formato de arquivo do módulo: ambos usam o formato zip para organizar os módulos, e o formato dos módulos é quase o mesmo -- Diretório de instalação do módulo: ambos localizados em `/data/adb/modules` -- Sem sistema: ambos suportam a modificação de `/system` de maneira sem sistema por meio de módulos -- post-fs-data.sh: o tempo de execução e a semântica são exatamente os mesmos -- service.sh: o tempo de execução e a semântica são exatamente os mesmos -- system.prop: completamente o mesmo -- sepolicy.rule: completamente o mesmo -- BusyBox: os scripts são executados no BusyBox com o "Modo Autônomo" ativado em ambos os casos +- Formato de arquivo do módulo: ambos usam o formato zip para organizar os módulos, e o formato dos módulos é quase o mesmo. +- Diretório de instalação do módulo: ambos localizados em `/data/adb/modules`. +- Sem sistema: ambos suportam a modificação de `/system` de maneira sem sistema por meio de módulos. +- post-fs-data.sh: o tempo de execução e a semântica são exatamente os mesmos. +- service.sh: o tempo de execução e a semântica são exatamente os mesmos. +- system.prop: completamente o mesmo. +- sepolicy.rule: completamente o mesmo. +- BusyBox: os scripts são executados no BusyBox com o "Modo Autônomo" ativado em ambos os casos. ## Diferenças diff --git a/website/docs/pt_BR/guide/faq.md b/website/docs/pt_BR/guide/faq.md index af7627a8c8fc..782747b2abc0 100644 --- a/website/docs/pt_BR/guide/faq.md +++ b/website/docs/pt_BR/guide/faq.md @@ -2,21 +2,21 @@ ## KernelSU oferece suporte ao meu dispositivo? -Primeiro, seus dispositivos devem ser capazes de desbloquear o bootloader. Se não puder, então não há suporte. +Primeiro, seu dispositivo deve ser capaz de desbloquear o bootloader. Se não, então não há suporte. -Em seguida, instale o app gerenciador KernelSU em seu dispositivo e abra-o, se mostrar `Sem suporte` então seu dispositivo não pode ser suportado imediatamente, mas você pode construir a fonte do kernel e integrar o KernelSU para fazê-lo funcionar ou usar [dispositivos de suporte não oficial](unofficially-support-devices). +Em seguida, instale o app gerenciador KernelSU em seu dispositivo e abra-o, se mostrar `Sem suporte` então seu dispositivo não pode ser suportado imediatamente, mas você pode construir a fonte do kernel e integrar o KernelSU para fazê-lo funcionar ou usar [dispositivos com suporte não oficial](unofficially-support-devices). ## KernelSU precisa desbloquear o Bootloader? -Certamente, sim +Certamente, sim. ## KernelSU suporta módulos? -Sim, mas está na versão inicial, pode apresentar bugs. Aguarde até que fique estável +Sim, mas está na versão inicial, pode apresentar bugs. Por favor, aguarde até que fique estável. ## KernelSU suporta Xposed? -Sim, [Dreamland](https://github.com/canyie/Dreamland) e [TaiChi](https://taichi.cool) funcionam agora. Para o LSPosed, você pode fazer funcionar usando [ZygiskOnKernelSU](https://github.com/Dr-TSNG/ZygiskOnKernelSU) +Sim, [Dreamland](https://github.com/canyie/Dreamland) e [TaiChi](https://taichi.cool) funcionam agora. Para o LSPosed, você pode fazer funcionar usando [ZygiskOnKernelSU](https://github.com/Dr-TSNG/ZygiskOnKernelSU). ## KernelSU suporta Zygisk? @@ -26,22 +26,22 @@ KernelSU não tem suporte integrado ao Zygisk, mas você pode usar [ZygiskOnKern O sistema de módulos do KernelSU está em conflito com a montagem mágica do Magisk, se houver algum módulo habilitado no KernelSU, então todo o Magisk não funcionaria. -Mas se você usar apenas o `su` do KernelSU, então funcionará bem com o Magisk: KernelSU modifica o `kernel` e o Magisk modifica o `ramdisk`, eles podem trabalhar juntos. +Mas se você usar apenas o `su` do KernelSU, então funcionará bem com o Magisk. KernelSU modifica o `kernel` e o Magisk modifica o `ramdisk`, eles podem trabalhar juntos. ## KernelSU substituirá o Magisk? -Achamos que não e esse não é o nosso objetivo. Magisk é bom o suficiente para solução raiz do espaço do usuário e terá uma vida longa. O objetivo do KernelSU é fornecer uma interface de kernel aos usuários, não substituindo o Magisk. +Achamos que não e esse não é o nosso objetivo. O Magisk é bom o suficiente para solução root do espaço do usuário e terá uma longa vida. O objetivo do KernelSU é fornecer uma interface de kernel aos usuários, não substituindo o Magisk. ## KernelSU pode oferecer suporte a dispositivos não GKI? -É possível. Mas você deve baixar o código-fonte do kernel e integrar o KernelSU à árvore de código-fonte e compilar o kernel você mesmo. +É possível. Mas você deve baixar o código-fonte do kernel e integrar o KernelSU à árvore do código-fonte e compilar o kernel você mesmo. ## KernelSU pode oferecer suporte a dispositivos abaixo do Android 12? É o kernel do dispositivo que afeta a compatibilidade do KernelSU e não tem nada a ver com a versão do Android. A única restrição é que os dispositivos lançados com Android 12 devem ser kernel 5.10+ (dispositivos GKI). Então: 1. Os dispositivos lançados com Android 12 devem ser compatíveis. -2. Dispositivos com kernel antigo (alguns dispositivos Android 12 também têm kernel antigo) são compatíveis (você mesmo deve construir o kernel) +2. Dispositivos com kernel antigo (alguns dispositivos Android 12 também têm o kernel antigo) são compatíveis (você mesmo deve construir o kernel). ## KernelSU pode suportar kernel antigo? diff --git a/website/docs/pt_BR/guide/how-to-build.md b/website/docs/pt_BR/guide/how-to-build.md index 0c8e19f205fd..7d82a1be4bba 100644 --- a/website/docs/pt_BR/guide/how-to-build.md +++ b/website/docs/pt_BR/guide/how-to-build.md @@ -6,7 +6,7 @@ Primeiro, você deve ler a documentação oficial do Android para construção d 2. [Builds de versão de imagem genérica do kernel (GKI)](https://source.android.com/docs/core/architecture/kernel/gki-release-builds) ::: warning AVISO -Esta página é para dispositivos GKI, se você usa um kernel antigo, consulte [Como integrar o KernelSU para kernels não GKI](how-to-integrate-for-non-gki) +Esta página é para dispositivos GKI, se você usa um kernel antigo, consulte [Como integrar o KernelSU para kernels não GKI](how-to-integrate-for-non-gki). ::: ## Construir o kernel @@ -20,7 +20,7 @@ repo init -m manifest.xml repo sync ``` -O `` é um arquivo de manifesto que pode determinar uma construção exclusivamente, você pode usar o manifesto para fazer uma construção re-preduzível. Você deve baixar o arquivo de manifesto em [compilações de lançamento do Google GKI](https://source.android.com/docs/core/architecture/kernel/gki-release-builds) +O `` é um arquivo de manifesto que pode determinar uma construção exclusivamente, você pode usar o manifesto para fazer uma construção re-preduzível. Você deve baixar o arquivo de manifesto em [compilações de lançamento do Google GKI](https://source.android.com/docs/core/architecture/kernel/gki-release-builds). ### Construir diff --git a/website/docs/pt_BR/guide/how-to-integrate-for-non-gki.md b/website/docs/pt_BR/guide/how-to-integrate-for-non-gki.md index c9fd907387a4..83727c286762 100644 --- a/website/docs/pt_BR/guide/how-to-integrate-for-non-gki.md +++ b/website/docs/pt_BR/guide/how-to-integrate-for-non-gki.md @@ -2,7 +2,7 @@ O KernelSU pode ser integrado em kernels não GKI e foi portado para 4.14 e versões anteriores. -Devido à fragmentação de kernels não GKI, não temos uma maneira uniforme de construí-lo, portanto não podemos fornecer boot images não GKI. Mas você mesmo pode construir o kernel com o KernelSU integrado. +Devido à fragmentação de kernels não GKI, não temos uma maneira uniforme de construí-lo, portanto não podemos fornecer imagens boot não GKI. Mas você mesmo pode construir o kernel com o KernelSU integrado. Primeiro, você deve ser capaz de construir um kernel inicializável a partir do código-fonte do kernel. Se o kernel não for de código aberto, será difícil executar o KernelSU no seu dispositivo. @@ -13,7 +13,7 @@ Se você puder construir um kernel inicializável, existem duas maneiras de inte ## Integrar com kprobe -O KernelSU usa kprobe para fazer ganchos de kernel, se o *kprobe* funcionar bem em seu kernel, é recomendado usar desta forma. +O KernelSU usa kprobe para fazer ganchos de kernel, se o kprobe funcionar bem em seu kernel, é recomendado usar desta forma. Primeiro, adicione o KernelSU à árvore de origem do kernel: @@ -21,7 +21,7 @@ Primeiro, adicione o KernelSU à árvore de origem do kernel: curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash - ``` -Então, você deve verificar se o *kprobe* está ativado na configuração do seu kernel, se não estiver, adicione estas configurações a ele: +Então, você deve verificar se o kprobe está ativado na configuração do seu kernel, se não estiver, adicione estas configurações a ele: ``` CONFIG_KPROBES=y @@ -33,7 +33,7 @@ E construa seu kernel novamente, KernelSU deve funcionar bem. Se você descobrir que o KPROBES ainda não está ativado, você pode tentar ativar `CONFIG_MODULES`. (Se ainda assim não surtir efeito, use `make menuconfig` para procurar outras dependências do KPROBES) -Mas se você encontrar em um bootloop quando o KernelSU for integrado, talvez o **kprobe esteja quebrado em seu kernel**, você deve corrigir o bug do kprobe ou usar o segundo caminho. +Mas se você entrar em um bootloop quando o KernelSU for integrado, talvez o **kprobe esteja quebrado em seu kernel**, você deve corrigir o bug do kprobe ou usar o segundo caminho. :::tip COMO VERIFICAR SE O KPROBE ESTÁ QUEBRADO? diff --git a/website/docs/pt_BR/guide/installation.md b/website/docs/pt_BR/guide/installation.md index 546683029d8f..10dab1aec1a7 100644 --- a/website/docs/pt_BR/guide/installation.md +++ b/website/docs/pt_BR/guide/installation.md @@ -4,7 +4,7 @@ Baixe o app gerenciador KernelSU em [GitHub Releases](https://github.com/tiann/KernelSU/releases) ou [Coolapk market](https://www.coolapk.com/apk/me.weishu.kernelsu), e instale-o no seu dispositivo: -- Se o app mostrar `Sem suporte`, significa que **você deve compilar o kernel sozinho**, o KernelSU não fornecerá e nunca fornecerá uma boot image para você atualizar. +- Se o app mostrar `Sem suporte`, significa que **você deve compilar o kernel sozinho**, o KernelSU não fornecerá e nunca fornecerá uma boot image para você instalar. - Se o app mostrar `Não instalado`, então seu dispositivo é oficialmente suportado pelo KernelSU. ::: info INFORMAÇÕES @@ -37,7 +37,7 @@ Version.PatchLevel.SubLevel-AndroidRelease-KmiGeneration-suffix w .x .y -zzz -k -something ``` -`w.x-zzz-k` é a versão KMI. Por exemplo, se a versão do kernel de um dispositivo for `5.10.101-android12-9-g30979850fc20`, então seu KMI será `5.10-android12-9`; teoricamente, ele pode inicializar normalmente com outros kernels KMI. +`w.x-zzz-k` é a versão KMI. Por exemplo, se a versão do kernel de um dispositivo for `5.10.101-android12-9-g30979850fc20`, então seu KMI será `5.10-android12-9`. Teoricamente, ele pode inicializar normalmente com outros kernels KMI. ::: tip DICA Observe que o SubLevel na versão do kernel não faz parte do KMI! Isso significa que `5.10.101-android12-9-g30979850fc20` tem o mesmo KMI que `5.10.137-android12-9-g30979850fc20`! @@ -60,7 +60,7 @@ Existem vários métodos de instalação do KernelSU, cada um adequado para um c ## Instalar com Recovery personalizado -Pré-requisito: Seu dispositivo deve ter um Recovery personalizado, como TWRP; se apenas o Recovery oficial estiver disponível, use outro método. +Pré-requisito: Seu dispositivo deve ter um Recovery personalizado, como TWRP. Se apenas o Recovery oficial estiver disponível, use outro método. Etapa: @@ -72,7 +72,7 @@ PS. Este método é adequado para qualquer instalação (não limitado à instal ## Instalar com Kernel Flasher -Pré-requisito: Seu dispositivo deve estar rooteado. Por exemplo, você instalou o Magisk para obter root ou instalou uma versão antiga do KernelSU e precisa atualizar para outra versão do KernelSU; se o seu dispositivo não estiver rooteado, tente outros métodos. +Pré-requisito: Seu dispositivo deve estar rooteado. Por exemplo, você instalou o Magisk para obter root ou instalou uma versão antiga do KernelSU e precisa atualizar para outra versão do KernelSU. Se o seu dispositivo não estiver rooteado, tente outros métodos. Etapa: @@ -97,7 +97,7 @@ O KernelSU fornece um boot.img genérico para dispositivos GKI e você deve libe Você pode baixar o boot.img em [GitHub Release](https://github.com/tiann/KernelSU/releases), por favor, observe que você deve usar a versão correta do boot.img. Por exemplo, se o seu dispositivo exibe o kernel `android12-5.10.101` , você precisa baixar `android-5.10.101_yyyy-MM.boot-.img`. (Mantenha o KMI consistente!) -Onde `` se refere ao formato de compactação do kernel do seu boot.img oficial, por favor, verifique o formato de compactação do kernel de seu boot.img original. Você deve usar o formato correto, por exemplo: `lz4`, `gz`; se você usar um formato de compactação incorreto, poderá encontrar bootloop. +Onde `` se refere ao formato de compactação do kernel do seu boot.img oficial, por favor, verifique o formato de compactação do kernel de seu boot.img original. Você deve usar o formato correto, por exemplo: `lz4`, `gz`. Se você usar um formato de compactação incorreto, poderá encontrar bootloop. ::: info INFORMAÇÕES 1. Você pode usar o magiskboot para obter o formato de compactação de seu boot original; é claro que você também pode perguntar a outras pessoas mais experientes com o mesmo modelo do seu dispositivo. Além disso, o formato de compactação do kernel geralmente não muda, portanto, se você inicializar com êxito com um determinado formato de compactação, poderá tentar esse formato mais tarde. @@ -127,7 +127,7 @@ fastboot reboot ## Corrigir boot.img manualmente -Para alguns dispositivos, o formato boot.img não é tão comum, como `lz4`, `gz` e `uncompressed`; o mais típico é o Pixel, seu formato boot.img é `lz4_legacy` compactado, ramdisk pode ser `gz` também pode ser compactado `lz4_legacy`; neste momento, se você fleshar diretamente o boot.img fornecido pelo KernelSU, o telefone pode não conseguir inicializar. Neste momento, você pode corrigir manualmente o boot.img para conseguir isso. +Para alguns dispositivos, o formato boot.img não é tão comum, como `lz4`, `gz` e `uncompressed`. O mais típico é o Pixel, seu formato boot.img é `lz4_legacy` compactado, ramdisk pode ser `gz` também pode ser compactado `lz4_legacy`. Neste momento, se você fleshar diretamente o boot.img fornecido pelo KernelSU, o telefone pode não conseguir inicializar. Neste momento, você pode corrigir manualmente o boot.img para conseguir isso. Geralmente existem dois métodos de patch: @@ -138,7 +138,7 @@ Entre eles, o Android-Image-Kitchen é adequado para operação no PC e o magisk ### Preparação -1. Obtenha o boot.img padrão do telefone; você pode obtê-lo com os fabricantes do seu dispositivo, você pode precisar do [payload-dumper-go](https://github.com/ssut/payload-dumper-go) +1. Obtenha o boot.img padrão do telefone; você pode obtê-lo com os fabricantes do seu dispositivo, você pode precisar do [payload-dumper-go](https://github.com/ssut/payload-dumper-go). 2. Baixe o arquivo zip AnyKernel3 fornecido pelo KernelSU que corresponde à versão KMI do seu dispositivo (você pode consultar *Instalar com Recovery personalizado*). 3. Descompacte o pacote AnyKernel3 e obtenha o arquivo `Image`, que é o arquivo do kernel do KernelSU. @@ -152,13 +152,13 @@ Entre eles, o Android-Image-Kitchen é adequado para operação no PC e o magisk ### Usando o magiskboot -1. Baixe o Magisk mais recente em [GitHub Releases](https://github.com/topjohnwu/Magisk/releases) +1. Baixe o Magisk mais recente em [GitHub Releases](https://github.com/topjohnwu/Magisk/releases). 2. Renomeie o Magisk-*.apk para Magisk-vesion.zip e descompacte-o. -3. Envie `Magisk-v25.2/lib/arm64-v8a/libmagiskboot.so` para o seu dispositivo por adb: `adb push Magisk-v25.2/lib/arm64-v8a/libmagiskboot.so /data/local/tmp/magiskboot` +3. Envie `Magisk-v25.2/lib/arm64-v8a/libmagiskboot.so` para o seu dispositivo por adb: `adb push Magisk-v25.2/lib/arm64-v8a/libmagiskboot.so /data/local/tmp/magiskboot`. 4. Envie o boot.img padrão e Image em AnyKernel3 para o seu dispositivo. -5. Entre no diretório adb shell e cd `/data/local/tmp/` e, em seguida, `chmod +x magiskboot` +5. Entre no diretório adb shell e cd `/data/local/tmp/` e, em seguida, `chmod +x magiskboot`. 6. Entre no shell adb e no diretório cd `/data/local/tmp/`, execute `./magiskboot unpack boot.img` para descompactar `boot.img`, você obterá um arquivo `kernel`, este é o seu kernel padrão. -7. Substitua `kernel` por `Image`: `mv -f Image kernel` +7. Substitua `kernel` por `Image`: `mv -f Image kernel`. 8. Execute `./magiskboot repack boot.img` para reembalar o boot.img, e você obterá um arquivo `new-boot.img`, faça o flash deste arquivo para o dispositivo por fastboot. ## Outros métodos diff --git a/website/docs/pt_BR/guide/module.md b/website/docs/pt_BR/guide/module.md index 908863ce88e8..10320c7973d7 100644 --- a/website/docs/pt_BR/guide/module.md +++ b/website/docs/pt_BR/guide/module.md @@ -4,18 +4,18 @@ O KernelSU fornece um mecanismo de módulo que consegue modificar o diretório d O mecanismo de módulo do KernelSU é quase o mesmo do Magisk. Se você está familiarizado com o desenvolvimento de módulos Magisk, o desenvolvimento de módulos KernelSU é muito semelhante. Você pode pular a introdução dos módulos abaixo e só precisa ler [Diferença com Magisk](difference-with-magisk.md). -## Busybox +## BusyBox -O KernelSU vem com um recurso binário BusyBox completo (incluindo suporte completo ao SELinux). O executável está localizado em `/data/adb/ksu/bin/busybox`. O BusyBox do KernelSU suporta o "ASH Standalone Shell Mode" alternável em tempo de execução. O que este modo autônomo significa é que ao executar no shell `ash` do BusyBox, cada comando usará diretamente o miniaplicativo dentro do BusyBox, independentemente do que estiver definido como `PATH`. Por exemplo, comandos como `ls`, `rm`, `chmod` **NÃO** usarão o que está em `PATH` (no caso do Android por padrão será `/system/bin/ls`, `/system/bin/rm` e `/system/bin/chmod` respectivamente), mas em vez disso chamará diretamente os miniaplicativos internos do BusyBox. Isso garante que os scripts sempre sejam executados em um ambiente previsível e sempre tenham o conjunto completo de comandos, independentemente da versão do Android em que estão sendo executados. Para forçar um comando a **não** usar o BusyBox, você deve chamar o executável com caminhos completos. +O KernelSU vem com um recurso binário BusyBox completo (incluindo suporte completo ao SELinux). O executável está localizado em `/data/adb/ksu/bin/busybox`. O BusyBox do KernelSU suporta o "ASH Standalone Shell Mode" alternável em tempo de execução. O que este Modo Autônomo significa é que ao executar no shell `ash` do BusyBox, cada comando usará diretamente o miniaplicativo dentro do BusyBox, independentemente do que estiver definido como `PATH`. Por exemplo, comandos como `ls`, `rm`, `chmod` **NÃO** usarão o que está em `PATH` (no caso do Android por padrão será `/system/bin/ls`, `/system/bin/rm` e `/system/bin/chmod` respectivamente), mas em vez disso chamará diretamente os miniaplicativos internos do BusyBox. Isso garante que os scripts sempre sejam executados em um ambiente previsível e sempre tenham o conjunto completo de comandos, independentemente da versão do Android em que estão sendo executados. Para forçar um comando a **NÃO** usar o BusyBox, você deve chamar o executável com caminhos completos. -Cada script de shell executado no contexto do KernelSU será executado no shell `ash` do BusyBox com o Modo Autônomo ativado. Para o que é relevante para desenvolvedores terceirizados, isso inclui todos os scripts de inicialização e scripts de instalação de módulos. +Cada script shell executado no contexto do KernelSU será executado no shell `ash` do BusyBox com o Modo Autônomo ativado. Para o que é relevante para desenvolvedores terceirizados, isso inclui todos os scripts de inicialização e scripts de instalação de módulos. Para aqueles que desejam usar o recurso “Modo Autônomo” fora do KernelSU, existem 2 maneiras de ativá-los: 1. Defina a variável de ambiente `ASH_STANDALONE` como `1`
Exemplo: `ASH_STANDALONE=1 /data/adb/ksu/bin/busybox sh