mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-11-27 12:05:30 +00:00
Embed version info in prop format
This commit is contained in:
parent
db1f5b0397
commit
3c75f474c6
@ -138,7 +138,7 @@ private fun Project.setupAppCommon() {
|
|||||||
val apkDir = if (properties["android.injected.invoked.from.ide"] == "true")
|
val apkDir = if (properties["android.injected.invoked.from.ide"] == "true")
|
||||||
"intermediates" else "outputs"
|
"intermediates" else "outputs"
|
||||||
val apk = File(buildDir, "${apkDir}/apk/${variant}/$projectName-${variant}.apk")
|
val apk = File(buildDir, "${apkDir}/apk/${variant}/$projectName-${variant}.apk")
|
||||||
val comment = "${Config.versionCode}"
|
val comment = "version=${Config.version}\nversionCode=${Config.versionCode}"
|
||||||
addComment(apk, signingConfig, android.defaultConfig.minSdk!!, comment)
|
addComment(apk, signingConfig, android.defaultConfig.minSdk!!, comment)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -338,12 +338,19 @@ void file_readline(bool trim, FILE *fp, const function<bool(string_view)> &fn) {
|
|||||||
if (!fn(start))
|
if (!fn(start))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fclose(fp);
|
|
||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_prop_file(const char *file, const function<bool(string_view, string_view)> &fn) {
|
void file_readline(bool trim, const char *file, const function<bool(string_view)> &fn) {
|
||||||
file_readline(true, file, [&](string_view line_view) -> bool {
|
if (auto fp = open_file(file, "re"))
|
||||||
|
file_readline(trim, fp.get(), fn);
|
||||||
|
}
|
||||||
|
void file_readline(const char *file, const function<bool(string_view)> &fn) {
|
||||||
|
file_readline(false, file, fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_prop_file(FILE *fp, const function<bool(string_view, string_view)> &fn) {
|
||||||
|
file_readline(true, fp, [&](string_view line_view) -> bool {
|
||||||
char *line = (char *) line_view.data();
|
char *line = (char *) line_view.data();
|
||||||
if (line[0] == '#')
|
if (line[0] == '#')
|
||||||
return true;
|
return true;
|
||||||
@ -355,6 +362,11 @@ void parse_prop_file(const char *file, const function<bool(string_view, string_v
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void parse_prop_file(const char *file, const function<bool(string_view, string_view)> &fn) {
|
||||||
|
if (auto fp = open_file(file, "re"))
|
||||||
|
parse_prop_file(fp.get(), fn);
|
||||||
|
}
|
||||||
|
|
||||||
// Original source: https://android.googlesource.com/platform/bionic/+/master/libc/bionic/mntent.cpp
|
// Original source: https://android.googlesource.com/platform/bionic/+/master/libc/bionic/mntent.cpp
|
||||||
// License: AOSP, full copyright notice please check original source
|
// License: AOSP, full copyright notice please check original source
|
||||||
static struct mntent *compat_getmntent_r(FILE *fp, struct mntent *e, char *buf, int buf_len) {
|
static struct mntent *compat_getmntent_r(FILE *fp, struct mntent *e, char *buf, int buf_len) {
|
||||||
|
@ -81,17 +81,9 @@ std::string full_read(int fd);
|
|||||||
std::string full_read(const char *filename);
|
std::string full_read(const char *filename);
|
||||||
void write_zero(int fd, size_t size);
|
void write_zero(int fd, size_t size);
|
||||||
void file_readline(bool trim, FILE *fp, const std::function<bool(std::string_view)> &fn);
|
void file_readline(bool trim, FILE *fp, const std::function<bool(std::string_view)> &fn);
|
||||||
static inline void file_readline(
|
void file_readline(bool trim, const char *file, const std::function<bool(std::string_view)> &fn);
|
||||||
bool trim, const char *file, const std::function<bool(std::string_view)> &fn) {
|
void file_readline(const char *file, const std::function<bool(std::string_view)> &fn);
|
||||||
FILE *fp = xfopen(file, "re");
|
void parse_prop_file(FILE *fp, const std::function<bool(std::string_view, std::string_view)> &fn);
|
||||||
if (fp == nullptr)
|
|
||||||
return;
|
|
||||||
file_readline(trim, fp, fn);
|
|
||||||
}
|
|
||||||
static inline void file_readline(const char *file,
|
|
||||||
const std::function<bool(std::string_view)> &fn) {
|
|
||||||
file_readline(false, file, fn);
|
|
||||||
}
|
|
||||||
void parse_prop_file(const char *file,
|
void parse_prop_file(const char *file,
|
||||||
const std::function<bool(std::string_view, std::string_view)> &fn);
|
const std::function<bool(std::string_view, std::string_view)> &fn);
|
||||||
void frm_rf(int dirfd);
|
void frm_rf(int dirfd);
|
||||||
|
@ -111,6 +111,14 @@ ssize_t xxread(int fd, void *buf, size_t count) {
|
|||||||
return read_sz;
|
return read_sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
off_t xlseek(int fd, off_t offset, int whence) {
|
||||||
|
off_t ret = lseek(fd, offset, whence);
|
||||||
|
if (ret < 0) {
|
||||||
|
PLOGE("lseek");
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int xpipe2(int pipefd[2], int flags) {
|
int xpipe2(int pipefd[2], int flags) {
|
||||||
int ret = pipe2(pipefd, flags);
|
int ret = pipe2(pipefd, flags);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
@ -14,6 +14,7 @@ int xopenat(int dirfd, const char *pathname, int flags, mode_t mode);
|
|||||||
ssize_t xwrite(int fd, const void *buf, size_t count);
|
ssize_t xwrite(int fd, const void *buf, size_t count);
|
||||||
ssize_t xread(int fd, void *buf, size_t count);
|
ssize_t xread(int fd, void *buf, size_t count);
|
||||||
ssize_t xxread(int fd, void *buf, size_t count);
|
ssize_t xxread(int fd, void *buf, size_t count);
|
||||||
|
off_t xlseek(int fd, off_t offset, int whence);
|
||||||
int xpipe2(int pipefd[2], int flags);
|
int xpipe2(int pipefd[2], int flags);
|
||||||
int xsetns(int fd, int nstype);
|
int xsetns(int fd, int nstype);
|
||||||
int xunshare(int flags);
|
int xunshare(int flags);
|
||||||
|
@ -96,26 +96,27 @@ struct EOCD {
|
|||||||
* within the APK v2 signature block.
|
* within the APK v2 signature block.
|
||||||
*/
|
*/
|
||||||
string read_certificate(int fd, int version) {
|
string read_certificate(int fd, int version) {
|
||||||
uint32_t size4;
|
uint32_t u32;
|
||||||
uint64_t size8;
|
uint64_t u64;
|
||||||
|
|
||||||
// Find EOCD
|
// Find EOCD
|
||||||
for (int i = 0;; i++) {
|
for (int i = 0;; i++) {
|
||||||
// i is the absolute offset to end of file
|
// i is the absolute offset to end of file
|
||||||
uint16_t comment_sz = 0;
|
uint16_t comment_sz = 0;
|
||||||
lseek(fd, -((off_t) sizeof(comment_sz)) - i, SEEK_END);
|
xlseek(fd, -static_cast<off_t>(sizeof(comment_sz)) - i, SEEK_END);
|
||||||
read(fd, &comment_sz, sizeof(comment_sz));
|
xxread(fd, &comment_sz, sizeof(comment_sz));
|
||||||
if (comment_sz == i) {
|
if (comment_sz == i) {
|
||||||
// Double check if we actually found the structure
|
// Double check if we actually found the structure
|
||||||
lseek(fd, -((off_t) sizeof(EOCD)), SEEK_CUR);
|
xlseek(fd, -static_cast<off_t>(sizeof(EOCD)), SEEK_CUR);
|
||||||
uint32_t magic = 0;
|
uint32_t magic = 0;
|
||||||
read(fd, &magic, sizeof(magic));
|
xxread(fd, &magic, sizeof(magic));
|
||||||
if (magic == EOCD_MAGIC) {
|
if (magic == EOCD_MAGIC) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (i == 0xffff) {
|
if (i == 0xffff) {
|
||||||
// Comments cannot be longer than 0xffff (overflow), abort
|
// Comments cannot be longer than 0xffff (overflow), abort
|
||||||
|
LOGE("cert: invalid APK format\n");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -125,19 +126,25 @@ string read_certificate(int fd, int version) {
|
|||||||
uint32_t central_dir_off = 0;
|
uint32_t central_dir_off = 0;
|
||||||
{
|
{
|
||||||
constexpr off_t off = offsetof(EOCD, central_dir_off) - sizeof(EOCD::magic);
|
constexpr off_t off = offsetof(EOCD, central_dir_off) - sizeof(EOCD::magic);
|
||||||
lseek(fd, off, SEEK_CUR);
|
xlseek(fd, off, SEEK_CUR);
|
||||||
}
|
}
|
||||||
read(fd, ¢ral_dir_off, sizeof(central_dir_off));
|
xxread(fd, ¢ral_dir_off, sizeof(central_dir_off));
|
||||||
|
|
||||||
// Read comment
|
// Parse APK comment to get version code
|
||||||
if (version >= 0) {
|
if (version >= 0) {
|
||||||
uint16_t comment_sz = 0;
|
xlseek(fd, sizeof(EOCD::comment_sz), SEEK_CUR);
|
||||||
read(fd, &comment_sz, sizeof(comment_sz));
|
FILE *fp = fdopen(fd, "r"); // DO NOT close this file pointer
|
||||||
string comment;
|
int apk_ver = -1;
|
||||||
comment.resize(comment_sz);
|
parse_prop_file(fp, [&](string_view key, string_view value) -> bool {
|
||||||
read(fd, comment.data(), comment_sz);
|
if (key == "versionCode") {
|
||||||
if (version > parse_int(comment)) {
|
apk_ver = parse_int(value);
|
||||||
// Older version of magisk app is not supported
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
if (version > apk_ver) {
|
||||||
|
// Enforce the magisk app to always be newer than magiskd
|
||||||
|
LOGE("cert: APK version too low\n");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -145,55 +152,57 @@ string read_certificate(int fd, int version) {
|
|||||||
// Next, find the start of the APK signing block
|
// Next, find the start of the APK signing block
|
||||||
{
|
{
|
||||||
constexpr int off = sizeof(signing_block::block_sz_) + sizeof(signing_block::magic);
|
constexpr int off = sizeof(signing_block::block_sz_) + sizeof(signing_block::magic);
|
||||||
lseek(fd, (off_t) (central_dir_off - off), SEEK_SET);
|
xlseek(fd, (off_t) (central_dir_off - off), SEEK_SET);
|
||||||
}
|
}
|
||||||
read(fd, &size8, sizeof(size8)); // size8 = block_sz_
|
xxread(fd, &u64, sizeof(u64)); // u64 = block_sz_
|
||||||
char magic[sizeof(signing_block::magic)] = {0};
|
char magic[sizeof(signing_block::magic)] = {0};
|
||||||
read(fd, magic, sizeof(magic));
|
xxread(fd, magic, sizeof(magic));
|
||||||
if (memcmp(magic, APK_SIGNING_BLOCK_MAGIC, sizeof(magic)) != 0) {
|
if (memcmp(magic, APK_SIGNING_BLOCK_MAGIC, sizeof(magic)) != 0) {
|
||||||
// Invalid signing block magic, abort
|
// Invalid signing block magic, abort
|
||||||
|
LOGE("cert: invalid signing block magic\n");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
uint64_t signing_blk_sz = 0;
|
uint64_t signing_blk_sz = 0;
|
||||||
lseek(fd, (off_t) (central_dir_off - size8 - sizeof(signing_blk_sz)), SEEK_SET);
|
xlseek(fd, -static_cast<off_t>(u64 + sizeof(signing_blk_sz)), SEEK_CUR);
|
||||||
read(fd, &signing_blk_sz, sizeof(signing_blk_sz));
|
xxread(fd, &signing_blk_sz, sizeof(signing_blk_sz));
|
||||||
if (signing_blk_sz != size8) {
|
if (signing_blk_sz != u64) {
|
||||||
// block_sz != block_sz_, invalid signing block format, abort
|
// block_sz != block_sz_, invalid signing block format, abort
|
||||||
|
LOGE("cert: invalid signing block format\n");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, we are now at the beginning of the id-value pair sequence
|
// Finally, we are now at the beginning of the id-value pair sequence
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
read(fd, &size8, sizeof(size8)); // id-value pair length
|
xxread(fd, &u64, sizeof(u64)); // id-value pair length
|
||||||
if (size8 == signing_blk_sz) {
|
if (u64 == signing_blk_sz) {
|
||||||
// Outside of the id-value pair sequence; actually reading block_sz_
|
// Outside of the id-value pair sequence; actually reading block_sz_
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
read(fd, &id, sizeof(id));
|
xxread(fd, &id, sizeof(id));
|
||||||
if (id == SIGNATURE_SCHEME_V2_MAGIC) {
|
if (id == SIGNATURE_SCHEME_V2_MAGIC) {
|
||||||
read(fd, &size4, sizeof(size4)); // signer sequence length
|
// Skip [signer sequence length] + [1st signer length] + [signed data length]
|
||||||
|
xlseek(fd, sizeof(uint32_t) * 3, SEEK_CUR);
|
||||||
|
|
||||||
read(fd, &size4, sizeof(size4)); // signer length
|
xxread(fd, &u32, sizeof(u32)); // digest sequence length
|
||||||
read(fd, &size4, sizeof(size4)); // signed data length
|
xlseek(fd, u32, SEEK_CUR); // skip all digests
|
||||||
|
|
||||||
read(fd, &size4, sizeof(size4)); // digest sequence length
|
xlseek(fd, sizeof(uint32_t), SEEK_CUR); // cert sequence length
|
||||||
lseek(fd, (off_t) (size4), SEEK_CUR); // skip all digests
|
xxread(fd, &u32, sizeof(u32)); // 1st cert length
|
||||||
|
|
||||||
read(fd, &size4, sizeof(size4)); // cert sequence length
|
|
||||||
read(fd, &size4, sizeof(size4)); // cert length
|
|
||||||
|
|
||||||
string cert;
|
string cert;
|
||||||
cert.resize(size4);
|
cert.resize(u32);
|
||||||
read(fd, cert.data(), size4);
|
xxread(fd, cert.data(), u32);
|
||||||
|
|
||||||
return cert;
|
return cert;
|
||||||
} else {
|
} else {
|
||||||
// Skip this id-value pair
|
// Skip this id-value pair
|
||||||
lseek(fd, (off_t) (size8 - sizeof(id)), SEEK_CUR);
|
xlseek(fd, u64 - sizeof(id), SEEK_CUR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOGE("cert: cannot find certificate\n");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user