Fix booting into recovery with Android 13 GKI kernels

With Android 13 GKI kernels, the boot partition has no ramdisk, so
Magisk constructs one from scratch. In this scenario, there's no backup
init binary at /.backup/init. For normal boot, magiskinit will symlink
/init -> /system/bin/init if needed. This commit implements the same
for booting into recovery. Before, magiskinit would just exec itself
over and over again because it couldn't restore the backup init.

Signed-off-by: Andrew Gunnerson <chillermillerlong@hotmail.com>
This commit is contained in:
Andrew Gunnerson 2022-06-25 19:27:37 -04:00 committed by John Wu
parent 4874520d65
commit 1f8c063dc6
3 changed files with 18 additions and 12 deletions

View File

@ -59,6 +59,20 @@ static int dump_bin(const uint8_t *buf, size_t sz, const char *path, mode_t mode
return 0;
}
void restore_ramdisk_init() {
unlink("/init");
const char *orig_init = backup_init();
if (access(orig_init, F_OK) == 0) {
xrename(orig_init, "/init");
} else {
// If the backup init is missing, this means that the boot ramdisk
// was created from scratch, and the real init is in a separate CPIO,
// which is guaranteed to be placed at /system/bin/init.
xsymlink(INIT_PATH, "/init");
}
}
int dump_manager(const char *path, mode_t mode) {
return dump_bin(manager_xz, sizeof(manager_xz), path, mode);
}
@ -72,7 +86,7 @@ public:
using BaseInit::BaseInit;
void start() override {
LOGD("Ramdisk is recovery, abort\n");
rename(backup_init(), "/init");
restore_ramdisk_init();
rm_rf("/.backup");
exec_init();
}

View File

@ -24,6 +24,7 @@ struct BootConfig {
};
#define DEFAULT_DT_DIR "/proc/device-tree/firmware/android"
#define INIT_PATH "/system/bin/init"
extern std::vector<std::string> mount_list;
@ -33,6 +34,7 @@ void load_kernel_info(BootConfig *config);
bool check_two_stage();
void setup_klog();
const char *backup_init();
void restore_ramdisk_init();
int dump_manager(const char *path, mode_t mode);
int dump_preload(const char *path, mode_t mode);

View File

@ -8,7 +8,6 @@
using namespace std;
#define INIT_PATH "/system/bin/init"
#define REDIR_PATH "/data/magiskinit"
void FirstStageInit::prepare() {
@ -16,16 +15,7 @@ void FirstStageInit::prepare() {
xmount("tmpfs", "/data", "tmpfs", 0, "mode=755");
cp_afc("/init" /* magiskinit */, REDIR_PATH);
unlink("/init");
const char *orig_init = backup_init();
if (access(orig_init, F_OK) == 0) {
xrename(orig_init, "/init");
} else {
// If the backup init is missing, this means that the boot ramdisk
// was created from scratch, and the real init is in a separate CPIO,
// which is guaranteed to be placed at /system/bin/init.
xsymlink(INIT_PATH, "/init");
}
restore_ramdisk_init();
{
auto init = mmap_data("/init", true);