diff --git a/native/jni/core/cert.cpp b/native/jni/core/cert.cpp index 81e7547b6..dec5c4233 100644 --- a/native/jni/core/cert.cpp +++ b/native/jni/core/cert.cpp @@ -1,4 +1,5 @@ #include +#include using namespace std; @@ -95,7 +96,7 @@ struct EOCD { * This method extracts the first certificate of the first signer * within the APK v2 signature block. */ -string read_certificate(int fd) { +string read_certificate(int fd, bool check_version) { uint32_t size4; uint64_t size8; @@ -129,6 +130,19 @@ string read_certificate(int fd) { } read(fd, ¢ral_dir_off, sizeof(central_dir_off)); + // Read comment + if (check_version) { + uint16_t comment_sz = 0; + read(fd, &comment_sz, sizeof(comment_sz)); + string comment; + comment.resize(comment_sz); + read(fd, comment.data(), comment_sz); + if (MAGISK_VER_CODE > parse_int(comment)) { + // Older version of magisk app is not supported + return {}; + } + } + // Next, find the start of the APK signing block { constexpr int off = sizeof(signing_block::block_sz_) + sizeof(signing_block::magic); diff --git a/native/jni/core/core.hpp b/native/jni/core/core.hpp index b07b0bd8c..4492d52dd 100644 --- a/native/jni/core/core.hpp +++ b/native/jni/core/core.hpp @@ -21,7 +21,7 @@ void reboot(); void start_log_daemon(); void setup_logfile(bool reset); void magisk_logging(); -std::string read_certificate(int fd); +std::string read_certificate(int fd, bool check_version = false); // Module stuffs void handle_modules(); diff --git a/native/jni/core/package.cpp b/native/jni/core/package.cpp index 8fa0c28f7..1b6e1cda6 100644 --- a/native/jni/core/package.cpp +++ b/native/jni/core/package.cpp @@ -105,7 +105,7 @@ int get_manager(int user_id, string *pkg, bool install) { int dyn = open(app_path, O_RDONLY | O_CLOEXEC); if (dyn < 0) return false; - bool mismatch = default_cert && read_certificate(dyn) != *default_cert; + bool mismatch = default_cert && read_certificate(dyn, true) != *default_cert; close(dyn); if (mismatch) { LOGE("pkg: dyn APK signature mismatch: %s\n", app_path); @@ -226,7 +226,7 @@ int get_manager(int user_id, string *pkg, bool install) { #if ENFORCE_SIGNATURE string apk = find_apk_path(JAVA_PACKAGE_NAME); int fd = xopen(apk.data(), O_RDONLY | O_CLOEXEC); - string cert = read_certificate(fd); + string cert = read_certificate(fd, true); close(fd); if (default_cert && cert != *default_cert) { // Found APK with invalid signature, force replace with stub