Fix SAR support for overlay.d

This commit is contained in:
topjohnwu 2020-04-25 23:19:36 -07:00
parent 2aede97754
commit c7ed0ef5eb
6 changed files with 48 additions and 19 deletions

View File

@ -1,7 +1,7 @@
#include <magisk.hpp>
#include <selinux.hpp>
constexpr char magiskrc[] =
constexpr char MAGISK_RC[] =
"\n"
"on post-fs-data\n"

View File

@ -20,7 +20,7 @@
using namespace std;
static vector<raw_data> rc_list;
static vector<string> rc_list;
static void patch_init_rc(const char *src, const char *dest, const char *tmp_dir) {
FILE *rc = xfopen(dest, "we");
@ -44,8 +44,11 @@ static void patch_init_rc(const char *src, const char *dest, const char *tmp_dir
fprintf(rc, "\n");
// Inject custom rc scripts
for (auto &d : rc_list)
fprintf(rc, "\n%s\n", d.buf);
for (auto &script : rc_list) {
// Replace template arguments of rc scripts with dynamic paths
replace_all(script, "${MAGISKTMP}", tmp_dir);
fprintf(rc, "\n%s\n", script.data());
}
rc_list.clear();
// Inject Magisk rc scripts
@ -54,7 +57,7 @@ static void patch_init_rc(const char *src, const char *dest, const char *tmp_dir
gen_rand_str(ls_svc, sizeof(ls_svc));
gen_rand_str(bc_svc, sizeof(bc_svc));
LOGD("Inject magisk services: [%s] [%s] [%s]\n", pfd_svc, ls_svc, bc_svc);
fprintf(rc, magiskrc, tmp_dir, pfd_svc, ls_svc, bc_svc);
fprintf(rc, MAGISK_RC, tmp_dir, pfd_svc, ls_svc, bc_svc);
fclose(rc);
clone_attr(src, dest);
@ -67,14 +70,12 @@ static void load_overlay_rc(const char *overlay) {
int dfd = dirfd(dir.get());
// Do not allow overwrite init.rc
unlinkat(dfd, "init.rc", 0);
for (dirent *entry; (entry = readdir(dir.get()));) {
for (dirent *entry; (entry = xreaddir(dir.get()));) {
if (strend(entry->d_name, ".rc") == 0) {
LOGD("Found rc script [%s]\n", entry->d_name);
int rc = xopenat(dfd, entry->d_name, O_RDONLY | O_CLOEXEC);
raw_data data;
fd_full_read(rc, data.buf, data.sz);
rc_list.push_back(fd_full_read(rc));
close(rc);
rc_list.push_back(std::move(data));
unlinkat(dfd, entry->d_name, 0);
}
}
@ -261,8 +262,7 @@ void SARBase::patch_rootdir() {
bool redirect = false;
int src = xopen("/init", O_RDONLY | O_CLOEXEC);
fd_full_read(src, init.buf, init.sz);
uint8_t *eof = init.buf + init.sz;
for (uint8_t *p = init.buf; p < eof;) {
for (uint8_t *p = init.buf, *eof = init.buf + init.sz; p < eof;) {
if (memcmp(p, SPLIT_PLAT_CIL, sizeof(SPLIT_PLAT_CIL)) == 0) {
LOGD("Remove from init: " SPLIT_PLAT_CIL "\n");
memset(p, 'x', sizeof(SPLIT_PLAT_CIL) - 1);
@ -287,8 +287,7 @@ void SARBase::patch_rootdir() {
// init is dynamically linked, need to patch libselinux
raw_data lib;
full_read(LIBSELINUX, lib.buf, lib.sz);
eof = lib.buf + lib.sz;
for (uint8_t *p = lib.buf; p < eof; ++p) {
for (uint8_t *p = lib.buf, *eof = lib.buf + lib.sz; p < eof; ++p) {
if (memcmp(p, MONOPOLICY, sizeof(MONOPOLICY)) == 0) {
LOGD("Patch libselinux.so [" MONOPOLICY "] -> [%s]\n", sepol);
strcpy(reinterpret_cast<char *>(p), sepol);
@ -305,7 +304,7 @@ void SARBase::patch_rootdir() {
// sepolicy
patch_sepolicy(sepol);
// Handle overlay
// Restore backup files
struct sockaddr_un sun;
int sockfd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
if (connect(sockfd, (struct sockaddr*) &sun, setup_sockaddr(&sun, INIT_SOCKET)) == 0) {
@ -321,12 +320,12 @@ void SARBase::patch_rootdir() {
overlays.clear();
}
close(sockfd);
// Handle overlay.d
load_overlay_rc(ROOTOVL);
if (access(ROOTOVL "/sbin", F_OK) == 0) {
file_attr a;
getattr("/sbin", &a);
cp_afc(ROOTOVL "/sbin", "/sbin");
rm_rf(ROOTOVL "/sbin");
setattr("/sbin", &a);
// Move files in overlay.d/sbin into Magisk's tmp_dir
mv_path(ROOTOVL "/sbin", tmp_dir);
}
// Patch init.rc

View File

@ -301,6 +301,21 @@ void full_read(const char *filename, void **buf, size_t *size) {
close(fd);
}
string fd_full_read(int fd) {
string str;
auto len = lseek(fd, 0, SEEK_END);
str.resize(len);
lseek(fd, 0, SEEK_SET);
xxread(fd, str.data(), len);
return str;
}
string full_read(const char *filename) {
int fd = xopen(filename, O_RDONLY | O_CLOEXEC);
run_finally f([=]{ close(fd); });
return fd < 0 ? "" : fd_full_read(fd);
}
void write_zero(int fd, size_t size) {
char buf[4096] = {0};
size_t len;

View File

@ -58,6 +58,8 @@ void fclone_attr(int src, int dest);
void clone_attr(const char *src, const char *dest);
void fd_full_read(int fd, void **buf, size_t *size);
void full_read(const char *filename, void **buf, size_t *size);
std::string fd_full_read(int fd);
std::string full_read(const char *filename);
void write_zero(int fd, size_t size);
void file_readline(bool trim, const char *file, const std::function<bool(std::string_view)> &fn);
static inline void file_readline(const char *file,

View File

@ -13,10 +13,13 @@
#include <unistd.h>
#include <syscall.h>
#include <random>
#include <string>
#include <logging.hpp>
#include <utils.hpp>
using namespace std;
int fork_dont_care() {
int pid = xfork();
if (pid) {
@ -214,3 +217,12 @@ int switch_mnt_ns(int pid) {
close(fd);
return ret;
}
string &replace_all(string &str, string_view from, string_view to) {
size_t pos = 0;
while((pos = str.find(from, pos)) != string::npos) {
str.replace(pos, from.length(), to);
pos += to.length();
}
return str;
}

View File

@ -106,3 +106,4 @@ void set_nice_name(const char *name);
uint32_t binary_gcd(uint32_t u, uint32_t v);
int switch_mnt_ns(int pid);
int gen_rand_str(char *buf, int len, bool varlen = true);
std::string &replace_all(std::string &str, std::string_view from, std::string_view to);