From 7785d2a3f836249c15d9eb922d8d974a6d4e1931 Mon Sep 17 00:00:00 2001 From: skbeh <60107333+skbeh@users.noreply.github.com> Date: Mon, 30 Jan 2023 12:57:25 +0800 Subject: [PATCH] ksud: replace some utils with rust libraries (#142) --- userspace/ksud/Cargo.lock | 408 ++++++++++++++++++++++++++++--- userspace/ksud/Cargo.toml | 7 +- userspace/ksud/src/debug.rs | 6 +- userspace/ksud/src/event.rs | 29 +-- userspace/ksud/src/installer.sh | 6 +- userspace/ksud/src/ksu.rs | 13 +- userspace/ksud/src/module.rs | 161 ++++++------ userspace/ksud/src/restorecon.rs | 29 ++- userspace/ksud/src/utils.rs | 44 ++-- 9 files changed, 525 insertions(+), 178 deletions(-) diff --git a/userspace/ksud/Cargo.lock b/userspace/ksud/Cargo.lock index 19c6f910..07662745 100644 --- a/userspace/ksud/Cargo.lock +++ b/userspace/ksud/Cargo.lock @@ -29,18 +29,49 @@ dependencies = [ "memchr", ] +[[package]] +name = "android-properties" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" + [[package]] name = "anyhow" version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + [[package]] name = "base64ct" version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" +[[package]] +name = "bindgen" +version = "0.59.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bd2a9a458e8f4304c52c43ebb0cfbd520289f8379a52e329a38afda99bf8eb8" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "peeking_take_while", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -64,9 +95,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bzip2" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6afcd980b5f3a45017c57e57a2fcccbb351cc43a356ce117ef760ef8052b89b0" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" dependencies = [ "bzip2-sys", "libc", @@ -85,13 +116,22 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" dependencies = [ "jobserver", ] +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -108,10 +148,21 @@ dependencies = [ ] [[package]] -name = "clap" -version = "4.0.32" +name = "clang-sys" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7db700bc935f9e43e88d00b0850dae18a63773cfbec6d8e070fccf7fef89a39" +checksum = "fa2e27ae6ab525c3d369ded447057bca5438d86dc3a68f6faafb8269ba82ebf3" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "4.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f13b9c79b5d1dd500d20ef541215a6423c75829ef43117e1b4d17fd8af0b5d76" dependencies = [ "bitflags", "clap_derive", @@ -124,9 +175,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.0.21" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014" +checksum = "684a277d672e91966334af371f1a7b5833f9aa00b07c84e92fbce95e00208ce8" dependencies = [ "heck", "proc-macro-error", @@ -137,9 +188,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8" +checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade" dependencies = [ "os_str_bytes", ] @@ -188,6 +239,64 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2801af0d36612ae591caa9568261fddce32ce6e08a7275ea334a06a4ad021a2c" +dependencies = [ + "cfg-if", + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.14" @@ -218,6 +327,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "either" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" + [[package]] name = "encoding" version = "0.2.33" @@ -316,6 +431,17 @@ dependencies = [ "libc", ] +[[package]] +name = "extattr" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b59f8a77817ff1b795adafc535941bdf664184f5f95e0b6d1d77dd6d12815dc" +dependencies = [ + "bitflags", + "errno", + "libc", +] + [[package]] name = "flate2" version = "1.0.25" @@ -347,6 +473,12 @@ dependencies = [ "wasi 0.11.0+wasi-snapshot-preview1", ] +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + [[package]] name = "heck" version = "0.4.0" @@ -388,9 +520,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "io-lifetimes" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c" +checksum = "e7d6c6f8c91b4b9ed43484ad1a938e393caf35960fce7f82a040497207bd8e9e" dependencies = [ "libc", "windows-sys", @@ -408,6 +540,15 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "is_executable" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa9acdc6d67b75e626ad644734e8bc6df893d9cd2a834129065d3dd6158ea9c8" +dependencies = [ + "winapi", +] + [[package]] name = "itoa" version = "1.0.5" @@ -434,17 +575,31 @@ dependencies = [ "libc", ] +[[package]] +name = "jwalk" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2735847566356cd2179a2a38264839308f7079fa96e6bd5a42d740460e003c56" +dependencies = [ + "crossbeam", + "rayon", +] + [[package]] name = "ksud" version = "0.1.0" dependencies = [ + "android-properties", "anyhow", "clap", "const_format", "encoding", "env_logger", + "extattr", "humansize", + "is_executable", "java-properties", + "jwalk", "libc", "log", "regex", @@ -452,6 +607,7 @@ dependencies = [ "serde", "serde_json", "subprocess", + "sys-mount", "zip 0.6.3", "zip-extensions", ] @@ -462,12 +618,28 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + [[package]] name = "libm" version = "0.2.6" @@ -489,12 +661,38 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "loopdev" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bfa0855b04611e38acaff718542e9e809cddfc16535d39f9d9c694ab19f7388" +dependencies = [ + "bindgen", + "errno", + "libc", +] + [[package]] name = "memchr" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.6.2" @@ -504,6 +702,26 @@ dependencies = [ "adler", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num_cpus" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +dependencies = [ + "hermit-abi", + "libc", +] + [[package]] name = "once_cell" version = "1.17.0" @@ -545,6 +763,18 @@ dependencies = [ "sha2", ] +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + [[package]] name = "pkg-config" version = "0.3.26" @@ -583,9 +813,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.49" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" +checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" dependencies = [ "unicode-ident", ] @@ -630,10 +860,32 @@ dependencies = [ ] [[package]] -name = "regex" -version = "1.7.0" +name = "rayon" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" +checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + +[[package]] +name = "regex" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" dependencies = [ "aho-corasick", "memchr", @@ -656,10 +908,16 @@ dependencies = [ ] [[package]] -name = "rustix" -version = "0.36.6" +name = "rustc-hash" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4feacf7db682c6c329c4ede12649cd36ecab0f3be5b7d74e6a20304725db4549" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustix" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fdebc4b395b7fbb9ab11e462e20ed9051e7b16e42d24042c776eca0ac81b03" dependencies = [ "bitflags", "errno", @@ -675,6 +933,12 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + [[package]] name = "serde" version = "1.0.152" @@ -714,6 +978,23 @@ dependencies = [ "digest", ] +[[package]] +name = "shlex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" + +[[package]] +name = "smart-default" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "133659a15339456eeeb07572eb02a91c91e9815e9cbc89566944d2c8d3efdbf6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "strsim" version = "0.10.0" @@ -748,10 +1029,24 @@ dependencies = [ ] [[package]] -name = "termcolor" -version = "1.1.3" +name = "sys-mount" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +checksum = "793d38aa916d55e979587ea7cf551106f5f091e548a91e89ee4f0698bc9cf289" +dependencies = [ + "bitflags", + "libc", + "loopdev", + "smart-default", + "thiserror", + "tracing", +] + +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ "winapi-util", ] @@ -814,6 +1109,38 @@ dependencies = [ "time-core", ] +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +dependencies = [ + "once_cell", +] + [[package]] name = "typenum" version = "1.16.0" @@ -898,45 +1225,45 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" [[package]] name = "windows_aarch64_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" [[package]] name = "windows_i686_gnu" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" [[package]] name = "windows_i686_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" [[package]] name = "windows_x86_64_gnu" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" [[package]] name = "windows_x86_64_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" [[package]] name = "zip" @@ -1002,10 +1329,11 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.4+zstd.1.5.2" +version = "2.0.5+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fa202f2ef00074143e219d15b62ffc317d17cc33909feac471c044087cad7b0" +checksum = "edc50ffce891ad571e9f9afe5039c4837bede781ac4bb13052ed7ae695518596" dependencies = [ "cc", "libc", + "pkg-config", ] diff --git a/userspace/ksud/Cargo.toml b/userspace/ksud/Cargo.toml index 8b087c08..125705ea 100644 --- a/userspace/ksud/Cargo.toml +++ b/userspace/ksud/Cargo.toml @@ -23,8 +23,13 @@ encoding = "0.2.33" retry = "2.0.0" humansize = "2.0.0" libc = "0.2" +sys-mount = "2.0.1" +android-properties = { version = "0.2.2", features = ["bionic-deprecated"] } +extattr = "1.0.0" +jwalk = "0.8.1" +is_executable = "1.0.1" [profile.release] strip = true opt-level = "z" -lto = true \ No newline at end of file +lto = true diff --git a/userspace/ksud/src/debug.rs b/userspace/ksud/src/debug.rs index b786cb43..6b40fe78 100644 --- a/userspace/ksud/src/debug.rs +++ b/userspace/ksud/src/debug.rs @@ -39,8 +39,8 @@ fn set_kernel_param(size: u32, hash: u32) -> Result<()> { } fn get_apk_path(package_name: &str) -> Result { - let cmd = format!("pm path {}", package_name); - let output = Command::new("sh").arg("-c").arg(cmd).output()?; + // `cmd package path` is not available below Android 9 + let output = Command::new("pm").args(["path", package_name]).output()?; // package:/data/app//base.apk let output = String::from_utf8_lossy(&output.stdout); @@ -54,7 +54,7 @@ pub fn set_manager(pkg: &str) -> Result<()> { "CONFIG_KSU_DEBUG is not enabled" ); - let path = get_apk_path(pkg).with_context(|| format!("{} not exist!", pkg))?; + let path = get_apk_path(pkg).with_context(|| format!("{pkg} does not exist!"))?; let sign = get_apk_signature(path.as_str())?; set_kernel_param(sign.0, sign.1)?; Ok(()) diff --git a/userspace/ksud/src/event.rs b/userspace/ksud/src/event.rs index 5183cda6..011b2521 100644 --- a/userspace/ksud/src/event.rs +++ b/userspace/ksud/src/event.rs @@ -5,11 +5,11 @@ use crate::{ utils::{ensure_clean_dir, mount_image}, }; use anyhow::{bail, Result}; -use subprocess::Exec; +use sys_mount::{FilesystemType, Mount, MountFlags}; fn mount_partition(partition: &str, lowerdir: &mut Vec) { if lowerdir.is_empty() { - println!("partition: {} lowerdir is empty", partition); + println!("partition: {partition} lowerdir is empty"); return; } @@ -19,22 +19,19 @@ fn mount_partition(partition: &str, lowerdir: &mut Vec) { return; } // add /partition as the lowerest dir - let lowest_dir = format!("/{}", partition); + let lowest_dir = format!("/{partition}"); lowerdir.push(lowest_dir.clone()); let lowerdir = lowerdir.join(":"); - println!("partition: {} lowerdir: {}", partition, lowerdir); + println!("partition: {partition} lowerdir: {lowerdir}"); - let mount_args = format!( - "mount -t overlay overlay -o ro,lowerdir={} {}", - lowerdir, lowest_dir - ); - if let Ok(result) = Exec::shell(mount_args).join() { - if !result.success() { - println!("mount partition: {} overlay failed", partition); - } - } else { - println!("mount partition: {} overlay failed", partition); + if let Err(err) = Mount::builder() + .fstype(FilesystemType::from("overlay")) + .flags(MountFlags::RDONLY) + .data(&format!("lowerdir={lowerdir}")) + .mount("overlay", lowest_dir) + { + println!("mount partition: {partition} overlay failed: {err}"); } } @@ -136,7 +133,7 @@ pub fn on_post_data_fs() -> Result<()> { } // module mounted, exec modules post-fs-data scripts - if !crate::utils::is_safe_mode().unwrap_or(false) { + if !crate::utils::is_safe_mode() { // todo: Add timeout let _ = crate::module::exec_post_fs_data(); let _ = crate::module::load_system_prop(); @@ -149,7 +146,7 @@ pub fn on_post_data_fs() -> Result<()> { pub fn on_services() -> Result<()> { // exec modules service.sh scripts - if !crate::utils::is_safe_mode().unwrap_or(false) { + if !crate::utils::is_safe_mode() { let _ = crate::module::exec_services(); } else { println!("safe mode, skip module service scripts"); diff --git a/userspace/ksud/src/installer.sh b/userspace/ksud/src/installer.sh index fc685c31..6f75ab9c 100644 --- a/userspace/ksud/src/installer.sh +++ b/userspace/ksud/src/installer.sh @@ -1,3 +1,4 @@ +#!/system/bin/sh ############################################ # KernelSU installer script # Credit to Magisk!!! @@ -89,14 +90,15 @@ setup_flashable() { } ensure_bb() { + : } recovery_actions() { - + : } recovery_cleanup() { - + : } ####################### diff --git a/userspace/ksud/src/ksu.rs b/userspace/ksud/src/ksu.rs index 4b8c2090..b65b21cc 100644 --- a/userspace/ksud/src/ksu.rs +++ b/userspace/ksud/src/ksu.rs @@ -1,7 +1,7 @@ #![allow(dead_code, unused_mut, unused_variables, unused_imports)] +use anyhow::{ensure, Result}; use std::os::unix::process::CommandExt; -use anyhow::{Result, ensure}; const KERNEL_SU_OPTION: u32 = 0xDEADBEEF; @@ -31,8 +31,7 @@ pub fn grant_root() -> Result<()> { } ensure!(result == KERNEL_SU_OPTION, "grant root failed"); - std::process::Command::new("/system/bin/sh").exec(); - Ok(()) + return Err(std::process::Command::new("sh").exec().into()); } #[cfg(not(target_os = "android"))] @@ -56,11 +55,7 @@ pub fn get_version() -> i32 { fn report_event(event: u64) { #[cfg(target_os = "android")] unsafe { - libc::prctl( - KERNEL_SU_OPTION as i32, - CMD_REPORT_EVENT, - event, - ); + libc::prctl(KERNEL_SU_OPTION as i32, CMD_REPORT_EVENT, event); } } @@ -70,4 +65,4 @@ pub fn report_post_fs_data() { pub fn report_boot_complete() { report_event(EVENT_BOOT_COMPLETED); -} \ No newline at end of file +} diff --git a/userspace/ksud/src/module.rs b/userspace/ksud/src/module.rs index 1e3c76ec..99fe9efb 100644 --- a/userspace/ksud/src/module.rs +++ b/userspace/ksud/src/module.rs @@ -1,20 +1,19 @@ +use crate::{defs, restorecon}; +use crate::{restorecon::setsyscon, utils::*}; + use const_format::concatcp; use java_properties::PropertiesIter; use log::{info, warn}; use std::{ collections::HashMap, fs::{create_dir_all, remove_dir_all, File, OpenOptions}, - io::{Cursor, Write}, + io::{Cursor, Read, Write}, os::unix::{prelude::PermissionsExt, process::CommandExt}, path::{Path, PathBuf}, process::{Command, Stdio}, str::FromStr, }; -use subprocess::Exec; -use zip_extensions::*; - -use crate::{defs, restorecon}; -use crate::{restorecon::setsyscon, utils::*}; +use zip_extensions::zip_extract_file_to_memory; use anyhow::{bail, ensure, Context, Result}; @@ -24,15 +23,15 @@ const INSTALL_MODULE_SCRIPT: &str = fn exec_install_script(module_file: &str) -> Result<()> { let realpath = std::fs::canonicalize(module_file) - .with_context(|| format!("realpath: {} failed", module_file))?; + .with_context(|| format!("realpath: {module_file} failed"))?; - let result = Command::new("/system/bin/sh") + let result = Command::new("sh") .args(["-c", INSTALL_MODULE_SCRIPT]) .env("OUTFD", "1") .env("ZIPFILE", realpath) .stderr(Stdio::null()) .status()?; - ensure!(result.success(), "install module script failed!"); + ensure!(result.success(), "Failed to install module script"); Ok(()) } @@ -41,13 +40,8 @@ fn exec_install_script(module_file: &str) -> Result<()> { // if someone(such as the module) install a module before the boot_completed // then it may cause some problems, just forbid it fn ensure_boot_completed() -> Result<()> { - // ensure getprop sys.boot_completed = 1 - let output = Command::new("getprop") - .arg("sys.boot_completed") - .stdout(Stdio::piped()) - .output()?; - let output = String::from_utf8_lossy(&output.stdout); - if output.trim() != "1" { + // ensure getprop sys.boot_completed == 1 + if getprop("sys.boot_completed").as_deref() != Some("1") { bail!("Android is Booting!"); } Ok(()) @@ -103,7 +97,7 @@ fn check_image(img: &str) -> Result<()> { .stdout(Stdio::null()) .stderr(Stdio::null()) .status() - .with_context(|| format!("Failed exec e2fsck {}", img))?; + .with_context(|| format!("Failed to exec e2fsck {img}"))?; let code = result.code(); // 0 or 1 is ok // 0: no error @@ -111,7 +105,7 @@ fn check_image(img: &str) -> Result<()> { // https://man7.org/linux/man-pages/man8/e2fsck.8.html ensure!( code == Some(0) || code == Some(1), - "check image e2fsck exec failed: {}", + "Failed to check image, e2fsck exit code: {}", code.unwrap_or(-1) ); Ok(()) @@ -130,12 +124,12 @@ fn grow_image_size(img: &str, extra_size: u64) -> Result<()> { ); let target_size = target_size / 1024 + 1; - let result = Exec::shell(format!("resize2fs {} {}K", img, target_size)) - .stdout(subprocess::NullFile) - .stderr(subprocess::Redirection::Merge) - .join() - .with_context(|| format!("Failed to resize2fs {}", img))?; - ensure!(result.success(), "resize2fs exec failed."); + let result = Command::new("resize2fs") + .args([img, &format!("{target_size}K")]) + .stdout(Stdio::null()) + .status() + .with_context(|| format!("Failed to exec resize2fs {img}"))?; + ensure!(result.success(), "Failed to resize2fs: {}", result); Ok(()) } @@ -148,20 +142,33 @@ fn switch_cgroup(grp: &str, pid: u32) { let fp = OpenOptions::new().append(true).open(path); if let Ok(mut fp) = fp { - let _ = writeln!(fp, "{}", pid); + let _ = writeln!(fp, "{pid}"); } } -fn switch_cgroups() -> Result<()> { +fn switch_cgroups() { let pid = std::process::id(); switch_cgroup("/acct", pid); switch_cgroup("/dev/cg2_bpf", pid); switch_cgroup("/sys/fs/cgroup", pid); - if getprop("ro.config.per_app_memcg")? != "false" { + + if getprop("ro.config.per_app_memcg") + .filter(|prop| prop == "false") + .is_none() + { switch_cgroup("/dev/memcg/apps", pid); } +} - Ok(()) +fn is_executable(path: &Path) -> bool { + let mut buffer: [u8; 2] = [0; 2]; + is_executable::is_executable(path) + && File::open(path).unwrap().read_exact(&mut buffer).is_ok() + && ( + buffer == [0x23, 0x21] // shebang #! + || buffer == [0x7f, 0x45] + // ELF magic number 0x7F 'E' + ) } /// execute every modules' post-fs-data.sh @@ -182,21 +189,30 @@ pub fn exec_post_fs_data() -> Result<()> { } println!("exec {} post-fs-data.sh", path.display()); - // pre_exec is unsafe! + let mut command_new; + let mut command; + if is_executable(&post_fs_data) { + command_new = Command::new("sh"); + command = command_new.arg(&post_fs_data); + } else { + command_new = Command::new(&post_fs_data); + command = &mut command_new; + }; + + command = command + .process_group(0) + .current_dir(path) + .env("KSU", "true"); unsafe { - Command::new("/system/bin/sh") - .arg(&post_fs_data) - .process_group(0) - .pre_exec(|| { - // ignore the error? - let _ = switch_cgroups(); - Ok(()) - }) - .current_dir(path) - .env("KSU", "true") - .status() - .with_context(|| format!("Failed to exec {}", post_fs_data.display()))?; + command = command.pre_exec(|| { + // ignore the error? + switch_cgroups(); + Ok(()) + }); } + command + .status() + .with_context(|| format!("Failed to exec {}", post_fs_data.display()))?; } Ok(()) @@ -220,21 +236,29 @@ pub fn exec_services() -> Result<()> { } println!("exec {} service.sh", path.display()); - // pre_exec is unsafe! + let mut command_new; + let mut command; + if is_executable(&service) { + command_new = Command::new("sh"); + command = command_new.arg(&service); + } else { + command_new = Command::new(&service); + command = &mut command_new; + }; + command = command + .process_group(0) + .current_dir(path) + .env("KSU", "true"); unsafe { - Command::new("/system/bin/sh") - .arg(&service) - .process_group(0) - .pre_exec(|| { - // ignore the error? - let _ = switch_cgroups(); - Ok(()) - }) - .current_dir(path) - .env("KSU", "true") - .spawn() // don't wait - .with_context(|| format!("Failed to exec {}", service.display()))?; + command = command.pre_exec(|| { + // ignore the error? + switch_cgroups(); + Ok(()) + }); } + command + .spawn() // don't wait + .with_context(|| format!("Failed to exec {}", service.display()))?; } Ok(()) @@ -271,7 +295,7 @@ pub fn load_system_prop() -> Result<()> { } println!("load {} system.prop", path.display()); - // resetprop --file system.prop + // resetprop -n --file system.prop Command::new(RESETPROP_PATH) .arg("-n") .arg("--file") @@ -335,7 +359,6 @@ pub fn install_module(zip: String) -> Result<()> { let default_reserve_size = 64 * 1024 * 1024; let zip_uncompressed_size = get_zip_uncompressed_size(&zip)?; let grow_size = default_reserve_size + zip_uncompressed_size; - let grow_size_per_m = grow_size / 1024 / 1024 + 1; println!("- Preparing image"); println!( @@ -346,21 +369,21 @@ pub fn install_module(zip: String) -> Result<()> { if !modules_img_exist && !modules_update_img_exist { // if no modules and modules_update, it is brand new installation, we should create a new img // create a tmp module img and mount it to modules_update - let result = Exec::shell(format!( - "dd if=/dev/zero of={} bs=1M count={}", - tmp_module_img, grow_size_per_m - )) - .stdout(subprocess::NullFile) - .stderr(subprocess::Redirection::Merge) - .join()?; - ensure!(result.success(), "create ext4 image failed!"); + File::create(tmp_module_img) + .context("Failed to create ext4 image file")? + .set_len(grow_size) + .context("Failed to extend ext4 image")?; // format the img to ext4 filesystem - let result = Exec::shell(format!("mkfs.ext4 {}", tmp_module_img)) - .stdout(subprocess::NullFile) - .stderr(subprocess::Redirection::Merge) - .join()?; - ensure!(result.success(), "format ext4 image failed!"); + let result = Command::new("mkfs.ext4") + .arg(tmp_module_img) + .stdout(Stdio::null()) + .output()?; + ensure!( + result.status.success(), + "Failed to format ext4 image: {}", + String::from_utf8(result.stderr).unwrap() + ); check_image(tmp_module_img)?; } else if modules_update_img_exist { diff --git a/userspace/ksud/src/restorecon.rs b/userspace/ksud/src/restorecon.rs index 20e653f4..81301b84 100644 --- a/userspace/ksud/src/restorecon.rs +++ b/userspace/ksud/src/restorecon.rs @@ -1,16 +1,13 @@ -use anyhow::ensure; -use anyhow::Ok; -use anyhow::Result; -use subprocess::Exec; +use anyhow::{Context, Ok, Result}; +use extattr::{setxattr, Flags as XattrFlags}; +use jwalk::{Parallelism::Serial, WalkDir}; const SYSTEM_CON: &str = "u:object_r:system_file:s0"; const _ADB_CON: &str = "u:object_r:adb_data_file:s0"; pub fn setcon(path: &str, con: &str) -> Result<()> { - // todo use libselinux directly - let cmd = format!("chcon {} {}", con, path); - let result = Exec::shell(cmd).join()?; - ensure!(result.success(), "chcon for: {} failed.", path); + setxattr(path, "security.selinux", con, XattrFlags::empty()) + .with_context(|| format!("Failed to change SELinux context for {path}"))?; Ok(()) } @@ -19,9 +16,17 @@ pub fn setsyscon(path: &str) -> Result<()> { } pub fn restore_syscon(dir: &str) -> Result<()> { - // todo use libselinux directly - let cmd = format!("chcon -R {} {}", SYSTEM_CON, dir); - let result = Exec::shell(cmd).join()?; - ensure!(result.success(), "chcon for: {} failed.", dir); + for dir_entry in WalkDir::new(dir).parallelism(Serial) { + if let Some(path) = dir_entry.ok().map(|dir_entry| dir_entry.path()) { + setxattr(&path, "security.selinux", SYSTEM_CON, XattrFlags::empty()).with_context( + || { + format!( + "Failed to change SELinux context for {}", + path.to_str().unwrap() + ) + }, + )?; + } + } Ok(()) } diff --git a/userspace/ksud/src/utils.rs b/userspace/ksud/src/utils.rs index 54f1efcd..09270f18 100644 --- a/userspace/ksud/src/utils.rs +++ b/userspace/ksud/src/utils.rs @@ -1,18 +1,14 @@ -use std::{ - path::Path, - process::{Command, Stdio}, -}; +use std::path::Path; -use anyhow::{ensure, Result}; +use anyhow::{ensure, Context, Result}; use retry::delay::NoDelay; -use subprocess::Exec; +use sys_mount::{unmount, FilesystemType, Mount, UnmountFlags}; fn do_mount_image(src: &str, target: &str) -> Result<()> { - let result = Exec::shell(format!("mount -t ext4 {} {}", src, target)) - .stdout(subprocess::NullFile) - .stderr(subprocess::Redirection::Merge) - .join()?; - ensure!(result.success(), "do mount: {} -> {} failed.", src, target); + Mount::builder() + .fstype(FilesystemType::from("ext4")) + .mount(src, target) + .with_context(|| format!("Failed to do mount: {src} -> {target}"))?; Ok(()) } @@ -20,16 +16,12 @@ pub fn mount_image(src: &str, target: &str) -> Result<()> { // umount target first. let _ = umount_dir(target); let result = retry::retry(NoDelay.take(3), || do_mount_image(src, target)); - ensure!(result.is_ok(), "mount: {} -> {} failed.", src, target); + ensure!(result.is_ok(), "Failed to mount {} -> {}", src, target); Ok(()) } pub fn umount_dir(src: &str) -> Result<()> { - let result = Exec::shell(format!("umount {}", src)) - .stdout(subprocess::NullFile) - .stderr(subprocess::Redirection::Merge) - .join()?; - ensure!(result.success(), "umount: {} failed", src); + unmount(src, UnmountFlags::empty()).with_context(|| format!("Failed to umount {src}"))?; Ok(()) } @@ -41,17 +33,17 @@ pub fn ensure_clean_dir(dir: &str) -> Result<()> { Ok(std::fs::create_dir_all(path)?) } -pub fn getprop(prop: &str) -> Result { - let output = Command::new("getprop") - .arg(prop) - .stdout(Stdio::piped()) - .output()?; - let output = String::from_utf8_lossy(&output.stdout); - Ok(output.trim().to_string()) +pub fn getprop(prop: &str) -> Option { + android_properties::getprop(prop).value() } -pub fn is_safe_mode() -> Result { - Ok(getprop("persist.sys.safemode")?.eq("1") || getprop("ro.sys.safemode")?.eq("1")) +pub fn is_safe_mode() -> bool { + getprop("persist.sys.safemode") + .filter(|prop| prop == "1") + .is_some() + || getprop("ro.sys.safemode") + .filter(|prop| prop == "1") + .is_some() } pub fn get_zip_uncompressed_size(zip_path: &str) -> Result {