mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-11-28 20:45:24 +00:00
Read certificate in Rust
Co-authored-by: topjohnwu <topjohnwu@gmail.com>
This commit is contained in:
parent
d2eaa6e6c1
commit
a9c89cbbbb
@ -25,7 +25,6 @@ LOCAL_SRC_FILES := \
|
|||||||
core/socket.cpp \
|
core/socket.cpp \
|
||||||
core/db.cpp \
|
core/db.cpp \
|
||||||
core/package.cpp \
|
core/package.cpp \
|
||||||
core/cert.cpp \
|
|
||||||
core/scripting.cpp \
|
core/scripting.cpp \
|
||||||
core/restorecon.cpp \
|
core/restorecon.cpp \
|
||||||
core/module.cpp \
|
core/module.cpp \
|
||||||
|
@ -288,27 +288,30 @@ pub unsafe fn slice_from_ptr_mut<'a, T>(buf: *mut T, len: usize) -> &'a mut [T]
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait FlatData {
|
pub trait FlatData
|
||||||
fn as_raw_bytes(&self) -> &[u8]
|
where
|
||||||
where
|
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
|
fn as_raw_bytes(&self) -> &[u8] {
|
||||||
unsafe {
|
unsafe {
|
||||||
let self_ptr = self as *const Self as *const u8;
|
let self_ptr = self as *const Self as *const u8;
|
||||||
slice::from_raw_parts(self_ptr, std::mem::size_of::<Self>())
|
slice::from_raw_parts(self_ptr, std::mem::size_of::<Self>())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn as_raw_bytes_mut(&mut self) -> &mut [u8]
|
fn as_raw_bytes_mut(&mut self) -> &mut [u8] {
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let self_ptr = self as *mut Self as *mut u8;
|
let self_ptr = self as *mut Self as *mut u8;
|
||||||
slice::from_raw_parts_mut(self_ptr, std::mem::size_of::<Self>())
|
slice::from_raw_parts_mut(self_ptr, std::mem::size_of::<Self>())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bytes_size(&self) -> usize {
|
||||||
|
std::mem::size_of::<Self>()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: Copy> FlatData for T {}
|
||||||
|
|
||||||
// Check libc return value and map errors to Result
|
// Check libc return value and map errors to Result
|
||||||
pub trait LibcReturn: Copy {
|
pub trait LibcReturn: Copy {
|
||||||
fn is_error(&self) -> bool;
|
fn is_error(&self) -> bool;
|
||||||
|
@ -1,208 +0,0 @@
|
|||||||
#include <base.hpp>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#define APK_SIGNING_BLOCK_MAGIC "APK Sig Block 42"
|
|
||||||
#define SIGNATURE_SCHEME_V2_MAGIC 0x7109871a
|
|
||||||
#define EOCD_MAGIC 0x6054b50
|
|
||||||
|
|
||||||
// Top-level block container
|
|
||||||
struct signing_block {
|
|
||||||
uint64_t block_sz;
|
|
||||||
|
|
||||||
struct id_value_pair {
|
|
||||||
uint64_t len;
|
|
||||||
struct /* v2_signature */ {
|
|
||||||
uint32_t id;
|
|
||||||
uint8_t value[0]; // size = (len - 4)
|
|
||||||
};
|
|
||||||
} id_value_pair_sequence[0];
|
|
||||||
|
|
||||||
uint64_t block_sz_; // *MUST* be same as block_sz
|
|
||||||
char magic[16]; // "APK Sig Block 42"
|
|
||||||
};
|
|
||||||
|
|
||||||
struct len_prefixed {
|
|
||||||
uint32_t len;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Generic length prefixed raw data
|
|
||||||
struct len_prefixed_value : public len_prefixed {
|
|
||||||
uint8_t value[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
// V2 Signature Block
|
|
||||||
struct v2_signature {
|
|
||||||
uint32_t id; // 0x7109871a
|
|
||||||
uint32_t signer_sequence_len;
|
|
||||||
struct signer : public len_prefixed {
|
|
||||||
struct signed_data : public len_prefixed {
|
|
||||||
uint32_t digest_sequence_len;
|
|
||||||
struct : public len_prefixed {
|
|
||||||
uint32_t algorithm;
|
|
||||||
len_prefixed_value digest;
|
|
||||||
} digest_sequence[0];
|
|
||||||
|
|
||||||
uint32_t certificate_sequence_len;
|
|
||||||
len_prefixed_value certificate_sequence[0];
|
|
||||||
|
|
||||||
uint32_t attribute_sequence_len;
|
|
||||||
struct attribute : public len_prefixed {
|
|
||||||
uint32_t id;
|
|
||||||
uint8_t value[0]; // size = (len - 4)
|
|
||||||
} attribute_sequence[0];
|
|
||||||
} signed_data;
|
|
||||||
|
|
||||||
uint32_t signature_sequence_len;
|
|
||||||
struct : public len_prefixed {
|
|
||||||
uint32_t id;
|
|
||||||
len_prefixed_value signature;
|
|
||||||
} signature_sequence[0];
|
|
||||||
|
|
||||||
len_prefixed_value public_key;
|
|
||||||
} signer_sequence[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
// End of central directory record
|
|
||||||
struct EOCD {
|
|
||||||
uint32_t magic; // 0x6054b50
|
|
||||||
uint8_t pad[8]; // 8 bytes of irrelevant data
|
|
||||||
uint32_t central_dir_sz; // size of central directory
|
|
||||||
uint32_t central_dir_off; // offset of central directory
|
|
||||||
uint16_t comment_sz; // size of comment
|
|
||||||
char comment[0];
|
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A v2/v3 signed APK has the format as following
|
|
||||||
*
|
|
||||||
* +---------------+
|
|
||||||
* | zip content |
|
|
||||||
* +---------------+
|
|
||||||
* | signing block |
|
|
||||||
* +---------------+
|
|
||||||
* | central dir |
|
|
||||||
* +---------------+
|
|
||||||
* | EOCD |
|
|
||||||
* +---------------+
|
|
||||||
*
|
|
||||||
* Scan from end of file to find EOCD, and figure our way back to the
|
|
||||||
* offset of the signing block. Next, directly extract the certificate
|
|
||||||
* from the v2 signature block.
|
|
||||||
*
|
|
||||||
* All structures above are mostly just for documentation purpose.
|
|
||||||
*
|
|
||||||
* This method extracts the first certificate of the first signer
|
|
||||||
* within the APK v2 signature block.
|
|
||||||
*/
|
|
||||||
string read_certificate(int fd, int version) {
|
|
||||||
uint32_t u32;
|
|
||||||
uint64_t u64;
|
|
||||||
|
|
||||||
// Find EOCD
|
|
||||||
for (int i = 0;; i++) {
|
|
||||||
// i is the absolute offset to end of file
|
|
||||||
uint16_t comment_sz = 0;
|
|
||||||
xlseek64(fd, -static_cast<off64_t>(sizeof(comment_sz)) - i, SEEK_END);
|
|
||||||
xxread(fd, &comment_sz, sizeof(comment_sz));
|
|
||||||
if (comment_sz == i) {
|
|
||||||
// Double check if we actually found the structure
|
|
||||||
xlseek64(fd, -static_cast<off64_t>(sizeof(EOCD)), SEEK_CUR);
|
|
||||||
uint32_t magic = 0;
|
|
||||||
xxread(fd, &magic, sizeof(magic));
|
|
||||||
if (magic == EOCD_MAGIC) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i == 0xffff) {
|
|
||||||
// Comments cannot be longer than 0xffff (overflow), abort
|
|
||||||
LOGE("cert: invalid APK format\n");
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We are now at EOCD + sizeof(magic)
|
|
||||||
// Seek and read central_dir_off to find start of central directory
|
|
||||||
uint32_t central_dir_off = 0;
|
|
||||||
{
|
|
||||||
constexpr off64_t off = offsetof(EOCD, central_dir_off) - sizeof(EOCD::magic);
|
|
||||||
xlseek64(fd, off, SEEK_CUR);
|
|
||||||
}
|
|
||||||
xxread(fd, ¢ral_dir_off, sizeof(central_dir_off));
|
|
||||||
|
|
||||||
// Parse APK comment to get version code
|
|
||||||
if (version >= 0) {
|
|
||||||
xlseek64(fd, sizeof(EOCD::comment_sz), SEEK_CUR);
|
|
||||||
FILE *fp = fdopen(fd, "r"); // DO NOT close this file pointer
|
|
||||||
int apk_ver = -1;
|
|
||||||
parse_prop_file(fp, [&](string_view key, string_view value) -> bool {
|
|
||||||
if (key == "versionCode") {
|
|
||||||
apk_ver = parse_int(value);
|
|
||||||
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 {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next, find the start of the APK signing block
|
|
||||||
{
|
|
||||||
constexpr int off = sizeof(signing_block::block_sz_) + sizeof(signing_block::magic);
|
|
||||||
xlseek64(fd, (off64_t) (central_dir_off - off), SEEK_SET);
|
|
||||||
}
|
|
||||||
xxread(fd, &u64, sizeof(u64)); // u64 = block_sz_
|
|
||||||
char magic[sizeof(signing_block::magic)] = {0};
|
|
||||||
xxread(fd, magic, sizeof(magic));
|
|
||||||
if (memcmp(magic, APK_SIGNING_BLOCK_MAGIC, sizeof(magic)) != 0) {
|
|
||||||
// Invalid signing block magic, abort
|
|
||||||
LOGE("cert: invalid signing block magic\n");
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
uint64_t signing_blk_sz = 0;
|
|
||||||
xlseek64(fd, -static_cast<off64_t>(u64 + sizeof(signing_blk_sz)), SEEK_CUR);
|
|
||||||
xxread(fd, &signing_blk_sz, sizeof(signing_blk_sz));
|
|
||||||
if (signing_blk_sz != u64) {
|
|
||||||
// block_sz != block_sz_, invalid signing block format, abort
|
|
||||||
LOGE("cert: invalid signing block format\n");
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finally, we are now at the beginning of the id-value pair sequence
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
xxread(fd, &u64, sizeof(u64)); // id-value pair length
|
|
||||||
if (u64 == signing_blk_sz) {
|
|
||||||
// Outside of the id-value pair sequence; actually reading block_sz_
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t id;
|
|
||||||
xxread(fd, &id, sizeof(id));
|
|
||||||
if (id == SIGNATURE_SCHEME_V2_MAGIC) {
|
|
||||||
// Skip [signer sequence length] + [1st signer length] + [signed data length]
|
|
||||||
xlseek64(fd, sizeof(uint32_t) * 3, SEEK_CUR);
|
|
||||||
|
|
||||||
xxread(fd, &u32, sizeof(u32)); // digest sequence length
|
|
||||||
xlseek64(fd, u32, SEEK_CUR); // skip all digests
|
|
||||||
|
|
||||||
xlseek64(fd, sizeof(uint32_t), SEEK_CUR); // cert sequence length
|
|
||||||
xxread(fd, &u32, sizeof(u32)); // 1st cert length
|
|
||||||
|
|
||||||
string cert;
|
|
||||||
cert.resize(u32);
|
|
||||||
xxread(fd, cert.data(), u32);
|
|
||||||
|
|
||||||
return cert;
|
|
||||||
} else {
|
|
||||||
// Skip this id-value pair
|
|
||||||
xlseek64(fd, u64 - sizeof(id), SEEK_CUR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LOGE("cert: cannot find certificate\n");
|
|
||||||
return {};
|
|
||||||
}
|
|
144
native/src/core/cert.rs
Normal file
144
native/src/core/cert.rs
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
use std::fs::File;
|
||||||
|
use std::io;
|
||||||
|
use std::io::{Read, Seek, SeekFrom};
|
||||||
|
use std::os::fd::{FromRawFd, RawFd};
|
||||||
|
|
||||||
|
use base::*;
|
||||||
|
|
||||||
|
const EOCD_MAGIC: u32 = 0x06054B50;
|
||||||
|
const APK_SIGNING_BLOCK_MAGIC: [u8; 16] = *b"APK Sig Block 42";
|
||||||
|
const SIGNATURE_SCHEME_V2_MAGIC: u32 = 0x7109871A;
|
||||||
|
|
||||||
|
macro_rules! bad_apk {
|
||||||
|
($msg:literal) => {
|
||||||
|
io::Error::new(io::ErrorKind::InvalidData, concat!("cert: ", $msg))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A v2/v3 signed APK has the format as following
|
||||||
|
*
|
||||||
|
* +---------------+
|
||||||
|
* | zip content |
|
||||||
|
* +---------------+
|
||||||
|
* | signing block |
|
||||||
|
* +---------------+
|
||||||
|
* | central dir |
|
||||||
|
* +---------------+
|
||||||
|
* | EOCD |
|
||||||
|
* +---------------+
|
||||||
|
*
|
||||||
|
* Scan from end of file to find EOCD, and figure our way back to the
|
||||||
|
* offset of the signing block. Next, directly extract the certificate
|
||||||
|
* from the v2 signature block.
|
||||||
|
*
|
||||||
|
* All structures above are mostly just for documentation purpose.
|
||||||
|
*
|
||||||
|
* This method extracts the first certificate of the first signer
|
||||||
|
* within the APK v2 signature block.
|
||||||
|
*/
|
||||||
|
pub fn read_certificate(fd: RawFd, version: i32) -> Vec<u8> {
|
||||||
|
fn inner(apk: &mut File, version: i32) -> Result<Vec<u8>, io::Error> {
|
||||||
|
let mut u32_value = 0u32;
|
||||||
|
let mut u64_value = 0u64;
|
||||||
|
|
||||||
|
// Find EOCD
|
||||||
|
for i in 0u16.. {
|
||||||
|
let mut comment_sz = 0u16;
|
||||||
|
apk.seek(SeekFrom::End(-(comment_sz.bytes_size() as i64) - i as i64))?;
|
||||||
|
apk.read_exact(comment_sz.as_raw_bytes_mut())?;
|
||||||
|
|
||||||
|
if comment_sz == i {
|
||||||
|
apk.seek(SeekFrom::Current(-22))?;
|
||||||
|
let mut magic = 0u32;
|
||||||
|
apk.read_exact(magic.as_raw_bytes_mut())?;
|
||||||
|
if magic == EOCD_MAGIC {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if i == 0xffff {
|
||||||
|
return Err(bad_apk!("invalid APK format"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We are now at EOCD + sizeof(magic)
|
||||||
|
// Seek and read central_dir_off to find the start of the central directory
|
||||||
|
let mut central_dir_off = 0u32;
|
||||||
|
apk.seek(SeekFrom::Current(12))?;
|
||||||
|
|
||||||
|
apk.read_exact(central_dir_off.as_raw_bytes_mut())?;
|
||||||
|
|
||||||
|
// Code for parse APK comment to get version code
|
||||||
|
if version >= 0 {
|
||||||
|
let mut comment_sz = 0u16;
|
||||||
|
apk.read_exact(comment_sz.as_raw_bytes_mut())?;
|
||||||
|
let mut comment = vec![0u8; comment_sz as usize];
|
||||||
|
apk.read_exact(&mut comment)?;
|
||||||
|
let mut comment = io::Cursor::new(&comment);
|
||||||
|
let mut apk_ver = 0;
|
||||||
|
comment.foreach_props(|k, v| {
|
||||||
|
if k == "versionCode" {
|
||||||
|
apk_ver = v.trim().parse::<i32>().unwrap_or(0);
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if version > apk_ver {
|
||||||
|
return Err(bad_apk!("APK version too low"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next, find the start of the APK signing block
|
||||||
|
apk.seek(SeekFrom::Start((central_dir_off - 24) as u64))?;
|
||||||
|
apk.read_exact(u64_value.as_raw_bytes_mut())?; // u64_value = block_sz_
|
||||||
|
let mut magic = [0u8; 16];
|
||||||
|
apk.read_exact(magic.as_raw_bytes_mut())?;
|
||||||
|
if magic != APK_SIGNING_BLOCK_MAGIC {
|
||||||
|
return Err(bad_apk!("invalid signing block magic"));
|
||||||
|
}
|
||||||
|
let mut signing_blk_sz = 0u64;
|
||||||
|
apk.seek(SeekFrom::Current(
|
||||||
|
-(u64_value as i64) - (signing_blk_sz.bytes_size() as i64),
|
||||||
|
))?;
|
||||||
|
apk.read_exact(signing_blk_sz.as_raw_bytes_mut())?;
|
||||||
|
if signing_blk_sz != u64_value {
|
||||||
|
return Err(bad_apk!("invalid signing block size"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, we are now at the beginning of the id-value pair sequence
|
||||||
|
loop {
|
||||||
|
apk.read_exact(u64_value.as_raw_bytes_mut())?; // id-value pair length
|
||||||
|
if u64_value == signing_blk_sz {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut id = 0u32;
|
||||||
|
apk.read_exact(id.as_raw_bytes_mut())?;
|
||||||
|
if id == SIGNATURE_SCHEME_V2_MAGIC {
|
||||||
|
// Skip [signer sequence length] + [1st signer length] + [signed data length]
|
||||||
|
apk.seek(SeekFrom::Current((u32_value.bytes_size() * 3) as i64))?;
|
||||||
|
|
||||||
|
apk.read_exact(u32_value.as_raw_bytes_mut())?; // digest sequence length
|
||||||
|
apk.seek(SeekFrom::Current(u32_value as i64))?; // skip all digests
|
||||||
|
|
||||||
|
apk.seek(SeekFrom::Current(u32_value.bytes_size() as i64))?; // cert sequence length
|
||||||
|
apk.read_exact(u32_value.as_raw_bytes_mut())?; // 1st cert length
|
||||||
|
|
||||||
|
let mut cert = vec![0; u32_value as usize];
|
||||||
|
apk.read_exact(cert.as_mut())?;
|
||||||
|
return Ok(cert);
|
||||||
|
} else {
|
||||||
|
// Skip this id-value pair
|
||||||
|
apk.seek(SeekFrom::Current(
|
||||||
|
u64_value as i64 - (id.bytes_size() as i64),
|
||||||
|
))?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(bad_apk!("cannot find certificate"))
|
||||||
|
}
|
||||||
|
inner(unsafe { &mut File::from_raw_fd(libc::dup(fd)) }, version)
|
||||||
|
.log()
|
||||||
|
.unwrap_or(vec![])
|
||||||
|
}
|
@ -12,7 +12,6 @@ extern std::atomic<ino_t> pkg_xml_ino;
|
|||||||
std::string find_preinit_device();
|
std::string find_preinit_device();
|
||||||
void unlock_blocks();
|
void unlock_blocks();
|
||||||
void reboot();
|
void reboot();
|
||||||
std::string read_certificate(int fd, int version = -1);
|
|
||||||
|
|
||||||
// Module stuffs
|
// Module stuffs
|
||||||
void handle_modules();
|
void handle_modules();
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
|
#![feature(format_args_nl)]
|
||||||
#![allow(clippy::missing_safety_doc)]
|
#![allow(clippy::missing_safety_doc)]
|
||||||
|
|
||||||
use base::Utf8CStr;
|
use base::Utf8CStr;
|
||||||
|
use cert::*;
|
||||||
use daemon::*;
|
use daemon::*;
|
||||||
use logging::*;
|
use logging::*;
|
||||||
|
|
||||||
|
mod cert;
|
||||||
#[path = "../include/consts.rs"]
|
#[path = "../include/consts.rs"]
|
||||||
mod consts;
|
mod consts;
|
||||||
mod daemon;
|
mod daemon;
|
||||||
@ -28,6 +31,7 @@ pub mod ffi {
|
|||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
fn daemon_entry();
|
fn daemon_entry();
|
||||||
fn zygisk_entry();
|
fn zygisk_entry();
|
||||||
|
fn read_certificate(fd: i32, version: i32) -> Vec<u8>;
|
||||||
|
|
||||||
type MagiskD;
|
type MagiskD;
|
||||||
fn get_magiskd() -> &'static MagiskD;
|
fn get_magiskd() -> &'static MagiskD;
|
||||||
|
@ -25,6 +25,11 @@ static string *mgr_cert;
|
|||||||
static int stub_apk_fd = -1;
|
static int stub_apk_fd = -1;
|
||||||
static const string *default_cert;
|
static const string *default_cert;
|
||||||
|
|
||||||
|
static string read_certificate(int fd, int version) {
|
||||||
|
auto cert = rust::read_certificate(fd, version);
|
||||||
|
return string{cert.begin(), cert.end()};
|
||||||
|
}
|
||||||
|
|
||||||
void check_pkg_refresh() {
|
void check_pkg_refresh() {
|
||||||
struct stat st{};
|
struct stat st{};
|
||||||
if (stat("/data/system/packages.xml", &st) == 0 &&
|
if (stat("/data/system/packages.xml", &st) == 0 &&
|
||||||
@ -71,7 +76,9 @@ void preserve_stub_apk() {
|
|||||||
string stub_path = MAGISKTMP + "/stub.apk";
|
string stub_path = MAGISKTMP + "/stub.apk";
|
||||||
stub_apk_fd = xopen(stub_path.data(), O_RDONLY | O_CLOEXEC);
|
stub_apk_fd = xopen(stub_path.data(), O_RDONLY | O_CLOEXEC);
|
||||||
unlink(stub_path.data());
|
unlink(stub_path.data());
|
||||||
default_cert = new string(read_certificate(stub_apk_fd));
|
auto cert = read_certificate(stub_apk_fd, -1);
|
||||||
|
if (!cert.empty())
|
||||||
|
default_cert = new string(std::move(cert));
|
||||||
lseek(stub_apk_fd, 0, SEEK_SET);
|
lseek(stub_apk_fd, 0, SEEK_SET);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +114,8 @@ int get_manager(int user_id, string *pkg, bool install) {
|
|||||||
LOGW("pkg: no dyn APK, ignore\n");
|
LOGW("pkg: no dyn APK, ignore\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool mismatch = default_cert && read_certificate(dyn, MAGISK_VER_CODE) != *default_cert;
|
auto cert = read_certificate(dyn, MAGISK_VER_CODE);
|
||||||
|
bool mismatch = default_cert && cert != *default_cert;
|
||||||
close(dyn);
|
close(dyn);
|
||||||
if (mismatch) {
|
if (mismatch) {
|
||||||
LOGE("pkg: dyn APK signature mismatch: %s\n", app_path);
|
LOGE("pkg: dyn APK signature mismatch: %s\n", app_path);
|
||||||
@ -172,12 +180,12 @@ int get_manager(int user_id, string *pkg, bool install) {
|
|||||||
byte_array<PATH_MAX> apk;
|
byte_array<PATH_MAX> apk;
|
||||||
find_apk_path(byte_view(str[SU_MANAGER]), apk);
|
find_apk_path(byte_view(str[SU_MANAGER]), apk);
|
||||||
int fd = xopen((const char *) apk.buf(), O_RDONLY | O_CLOEXEC);
|
int fd = xopen((const char *) apk.buf(), O_RDONLY | O_CLOEXEC);
|
||||||
string cert = read_certificate(fd);
|
auto cert = read_certificate(fd, -1);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
// Verify validity
|
// Verify validity
|
||||||
if (str[SU_MANAGER] == *mgr_pkg) {
|
if (str[SU_MANAGER] == *mgr_pkg) {
|
||||||
if (app_id != mgr_app_id || cert != *mgr_cert) {
|
if (app_id != mgr_app_id || cert.empty() || cert != *mgr_cert) {
|
||||||
// app ID or cert should never change
|
// app ID or cert should never change
|
||||||
LOGE("pkg: repackaged APK signature invalid: %s\n", apk.buf());
|
LOGE("pkg: repackaged APK signature invalid: %s\n", apk.buf());
|
||||||
uninstall_pkg(mgr_pkg->data());
|
uninstall_pkg(mgr_pkg->data());
|
||||||
@ -226,7 +234,7 @@ int get_manager(int user_id, string *pkg, bool install) {
|
|||||||
byte_array<PATH_MAX> apk;
|
byte_array<PATH_MAX> apk;
|
||||||
find_apk_path(byte_view(JAVA_PACKAGE_NAME), apk);
|
find_apk_path(byte_view(JAVA_PACKAGE_NAME), apk);
|
||||||
int fd = xopen((const char *) apk.buf(), O_RDONLY | O_CLOEXEC);
|
int fd = xopen((const char *) apk.buf(), O_RDONLY | O_CLOEXEC);
|
||||||
string cert = read_certificate(fd, MAGISK_VER_CODE);
|
auto cert = read_certificate(fd, MAGISK_VER_CODE);
|
||||||
close(fd);
|
close(fd);
|
||||||
if (default_cert && cert != *default_cert) {
|
if (default_cert && cert != *default_cert) {
|
||||||
// Found APK with invalid signature, force replace with stub
|
// Found APK with invalid signature, force replace with stub
|
||||||
|
Loading…
Reference in New Issue
Block a user