Skip to content

Commit

Permalink
fix 18.0b5 setup fakefs
Browse files Browse the repository at this point in the history
  • Loading branch information
asdfugil committed Aug 9, 2024
1 parent df3bc1f commit 84213cf
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 49 deletions.
5 changes: 4 additions & 1 deletion include/payload/payload.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,12 @@ void reload_launchd_env(void);
void perform_reboot3(xpc_object_t peer, xpc_object_t xreply, xpc_object_t request, struct paleinfo* pinfo_p);
void runcmd(xpc_object_t xrequest, xpc_object_t xreply, struct paleinfo* __unused pinfo);
int bootscreend_main(void);
kern_return_t enter_recovery();
kern_return_t nvram(char* key, char* value);
kern_return_t nvram_read(const char *key, CFTypeRef *valueRef);
ssize_t write_fdout(int fd, void* buf, size_t len);
_Noreturn void _panic(char* fmt, ...);
const char* volume_prefix(void);
const char* container_name(void);
extern bool panic_did_enter;

enum {
Expand Down
4 changes: 0 additions & 4 deletions src/fakedyld/main/pinfo_check.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,5 @@ void pinfo_check(struct paleinfo* pinfo_p) {
)) != 0) {
panic("ramdisk should never be booted with the options specified");
}

if ((pinfo_p->flags & palerain_option_rootful) && pinfo_p->rootdev[0] == '\0') {
panic("rootful requires rootdev to be set");
}
return;
}
2 changes: 1 addition & 1 deletion src/payload/loader/launchdaemons.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ void* force_revert_notif_thread(__unused void* arg) {
if ((cfres & 0x3) == kCFUserNotificationDefaultResponse) {
reboot3(RB2_FULLREBOOT);
} else if ((cfres & 0x3) == kCFUserNotificationAlternateResponse) {
enter_recovery();
nvram("auto-boot", "false");
reboot3(RB2_FULLREBOOT);
}
CFRelease(force_revert_notif);
Expand Down
34 changes: 29 additions & 5 deletions src/payload/loader/prelaunchd.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,24 +52,48 @@ int prelaunchd(uint32_t payload_options, struct paleinfo* pinfo_p) {
}
}

char dev_rootdev[32];
snprintf(dev_rootdev, 32, "/dev/%s", pinfo_p->rootdev);
if ((pinfo_p->flags & (palerain_option_rootful | palerain_option_force_revert)) == (palerain_option_rootful | palerain_option_force_revert)) {
if (pinfo_p->flags & palerain_option_ssv) {
printf("will delete %s\n", dev_rootdev);
if (access(dev_rootdev, F_OK) == 0) {
char dev_rootdev[32];
CFMutableArrayRef fsArray;
int retval = APFSVolumeRoleFind(container_name(), APFS_VOL_ROLE_RECOVERY, &fsArray);
if (retval && retval != 49245) {
_panic("APFSVolumeRoleFind failed: %d: %s\n", retval, mach_error_string(retval));
}

if (!retval) {
CFStringGetCString(CFArrayGetValueAtIndex(fsArray, 0), dev_rootdev, 32, kCFStringEncodingUTF8);
CFRelease(fsArray);
}

if (!retval && access(dev_rootdev, F_OK) == 0) {
printf("will delete %s\n", dev_rootdev);
int16_t role = 0;
// 49154 = container not found, 49254 = volume with role not found
CHECK_ERROR(APFSVolumeRole(dev_rootdev, &role, NULL), 0, "APFSVolumeRole(%s) Failed", dev_rootdev);
printf("found apfs volume role: 0x%04x\n", role);
if (role != APFS_VOL_ROLE_RECOVERY) {
_panic("BUG: SAFETY: deleting non-recovery volume is not allowed\n");
} else {
CHECK_ERROR(errno = APFSVolumeDelete(pinfo_p->rootdev), 1, "failed to delete fakefs");
CHECK_ERROR(errno = APFSVolumeDelete(&dev_rootdev[5]), 1, "failed to delete fakefs");
nvram(kIONVRAMDeletePropertyKey, "p1-fakefs-rootdev");
}
}
}
}

if ((pinfo_p->flags & (palerain_option_rootful | palerain_option_ssv)) == (palerain_option_rootful | palerain_option_ssv)) {
if ((pinfo_p->flags & (palerain_option_force_revert | palerain_option_setup_rootful)) == 0) {
CFTypeRef fakefs_var;
int retval = nvram_read("p1-fakefs-rootdev", &fakefs_var);
if (retval == kIOReturnNotFound) {
nvram("p1-fakefs-rootdev", pinfo_p->rootdev);
} else if (retval == 0) {
CFRelease(fakefs_var);
}
}
}

#define ELLEKIT_ACTUAL_PATH "/cores/binpack/usr/lib/libellekit.dylib"
void* ellekit_handle = dlopen(ELLEKIT_ACTUAL_PATH, RTLD_NOW);

Expand Down
145 changes: 107 additions & 38 deletions src/payload/loader/setup_fakefs.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,85 @@ void notch_clear(char* machine) {
}
}

kern_return_t enter_recovery(void) {
kern_return_t nvram(char* key, char* value) {
CFStringRef cfKey = CFStringCreateWithCString(kCFAllocatorDefault, key, kCFStringEncodingUTF8);
CFStringRef cfValue = CFStringCreateWithCString(kCFAllocatorDefault, value, kCFStringEncodingUTF8);
io_registry_entry_t nvram = IORegistryEntryFromPath(kIOMasterPortDefault, kIODeviceTreePlane ":/options");
kern_return_t ret = IORegistryEntrySetCFProperty(nvram, CFSTR("auto-boot"), CFSTR("false"));
printf("set nvram auto-boot=false ret: %d\n",ret);
ret = IORegistryEntrySetCFProperty(nvram, CFSTR(kIONVRAMForceSyncNowPropertyKey), CFSTR("auto-boot"));
kern_return_t ret = IORegistryEntrySetCFProperty(nvram, cfKey, cfValue);
printf("Set nvram %s=%s ret: %d\n", key, value, ret);
ret = IORegistryEntrySetCFProperty(nvram, CFSTR(kIONVRAMForceSyncNowPropertyKey), cfKey);
printf("sync nvram ret: %d\n",ret);
IOObjectRelease(nvram);
if (cfValue) CFRelease(cfValue);
CFRelease(cfKey);
return ret;
}

kern_return_t nvram_read(const char *key, CFTypeRef *valueRef) {
io_registry_entry_t nvram = IORegistryEntryFromPath(kIOMasterPortDefault, kIODeviceTreePlane ":/options");
CFStringRef cfKey = CFStringCreateWithCString(kCFAllocatorDefault, key, kCFStringEncodingUTF8);

*valueRef = IORegistryEntryCreateCFProperty(nvram, cfKey, 0, 0);
IOObjectRelease(nvram);
if (*valueRef == 0) return kIOReturnNotFound;

return KERN_SUCCESS;
}

const char* volume_prefix(void) {
static char prefix[32] = {'\0'};
if (prefix[0] != '\0') return prefix;
struct statfs rootfs_st;
CHECK_ERROR(statfs("/", &rootfs_st), 1, "statfs / failed");
if (strcmp(rootfs_st.f_fstypename, "apfs")) {
_panic("unexpected filesystem type of /");
}

char* pBSDName;
if ((pBSDName = strstr(rootfs_st.f_mntfromname, "@/dev/"))) {
pBSDName = &pBSDName[6];
} else {
pBSDName = rootfs_st.f_mntfromname;
}

char* suffix = pBSDName;
for (size_t i = 0; pBSDName[i] != '\0'; i++) {
if (pBSDName[i] == 's') {
suffix = &pBSDName[i+1];
}
}
suffix[0] = '\0';
snprintf(prefix, 32, "%s", pBSDName);
return prefix;
}

const char* container_name(void) {
static char prefix[32] = {'\0'};
if (prefix[0] != '\0') return prefix;
struct statfs rootfs_st;
CHECK_ERROR(statfs("/", &rootfs_st), 1, "statfs / failed");
if (strcmp(rootfs_st.f_fstypename, "apfs")) {
_panic("unexpected filesystem type of /");
}

char* pBSDName;
if ((pBSDName = strstr(rootfs_st.f_mntfromname, "@/dev/"))) {
pBSDName = &pBSDName[6];
} else {
pBSDName = rootfs_st.f_mntfromname;
}

char* suffix = pBSDName;
for (size_t i = 4; pBSDName[i] != '\0'; i++) {
if (pBSDName[i] == 's') {
pBSDName[i] = '\0';
break;
}
}
snprintf(prefix, 32, "%s", pBSDName);
return prefix;
}

int copyfile_fakefs_cb(int what, int __unused stage, copyfile_state_t __unused state, const char * src, const char * __unused dst, void * ctx) {
char basename_buf[PATH_MAX];
struct paleinfo* pinfo_p = ((struct cb_context*)ctx)->pinfo_p;
Expand Down Expand Up @@ -95,7 +164,7 @@ int copyfile_fakefs_cb(int what, int __unused stage, copyfile_state_t __unused s
strcmp(src, "/cores/fs/real/./System/Library/PrivateFrameworks") == 0 ||
strcmp(src, "/cores/fs/real/./System/Library/Caches") == 0
)
&& strncmp(pinfo_p->rootdev, "disk0s1s", 8) == 0)
&& strcmp(volume_prefix(), "disk0s1s") == 0)
{
if (access(src, F_OK) != 0) CHECK_ERROR(mkdir(src, 0755), 1, "bindfs mkdir failed");
printf("skip %s\n", src);
Expand All @@ -119,16 +188,32 @@ int setup_fakefs(uint32_t __unused payload_options, struct paleinfo* pinfo_p) {
struct statfs rootfs_st;
CHECK_ERROR(statfs("/", &rootfs_st), 1, "statfs / failed");
if (strcmp(rootfs_st.f_fstypename, "apfs")) {
panic("unexpected filesystem type of /");
_panic("unexpected filesystem type of /");
}

const char* container = container_name();

char fakefs_mntfromname[50];
snprintf(fakefs_mntfromname, 50, "/dev/%s", pinfo_p->rootdev);

if (access(fakefs_mntfromname, F_OK) == 0) {
panic("fakefs already exists");
printf("container=%s\n", container);
printf("volume prefix=%s\n", volume_prefix());

printf("checking for fakefs\n");
CFMutableArrayRef fsArray = NULL;
int retval = APFSVolumeRoleFind(container, APFS_VOL_ROLE_RECOVERY, &fsArray);
if (retval && retval != 49245) {
_panic("APFSVolumeRoleFind failed: %d: %s\n", retval, mach_error_string(retval));
} else if (retval == 0) {
CFIndex recoveryVolumesCount = CFArrayGetCount(fsArray);
for (CFIndex i = 0; i < recoveryVolumesCount; i++) {
CFStringRef cfVolumePath = CFArrayGetValueAtIndex(fsArray, i);
char volume_path[PATH_MAX];
CFStringGetCString(cfVolumePath, volume_path, PATH_MAX, kCFStringEncodingUTF8);
printf("fakefs %s found!\n", volume_path);
}
CFRelease(fsArray);
_panic("fakefs already exists");
}

printf("fakefs does not exist\n");

struct cb_context context = { .pinfo_p = pinfo_p, .bytesToCopy = 0 };

if ((pinfo_p->flags & palerain_option_setup_partial_root) == 0) {
Expand All @@ -142,7 +227,7 @@ int setup_fakefs(uint32_t __unused payload_options, struct paleinfo* pinfo_p) {

context.bytesToCopy = attrbuf.spaceused;
if ((attrbuf.spaceused + MINIMUM_EXTRA_SPACE) > (rootfs_st.f_bavail * rootfs_st.f_bsize)) {
panic("Not enough space! need %lld bytes (%d bytes buffer), have %lld bytes.`", (attrbuf.spaceused + MINIMUM_EXTRA_SPACE), MINIMUM_EXTRA_SPACE, (rootfs_st.f_bavail * rootfs_st.f_bsize));
_panic("Not enough space! need %lld bytes (%d bytes buffer), have %lld bytes.`", (attrbuf.spaceused + MINIMUM_EXTRA_SPACE), MINIMUM_EXTRA_SPACE, (rootfs_st.f_bavail * rootfs_st.f_bsize));
}
}

Expand All @@ -155,19 +240,9 @@ int setup_fakefs(uint32_t __unused payload_options, struct paleinfo* pinfo_p) {
CFDictionaryAddValue(dict, kAPFSVolumeNameKey, CFSTR("Xystem"));
CFDictionaryAddValue(dict, kAPFSVolumeCaseSensitiveKey, kCFBooleanTrue);

const char* container = "disk0s1";
char container_impl[16];
if (strncmp(pinfo_p->rootdev, "disk0", 5) != 0) {
strncpy(container_impl, pinfo_p->rootdev, 5);
container_impl[5] = '\0';
container = container_impl;
}

printf("container=%s\n", container);

int retval = APFSVolumeCreate(container, dict);
retval = APFSVolumeCreate(container, dict);
if (retval) {
panic("APFSVolumeCreate failed: %d: %s\n", retval, mach_error_string(retval));
_panic("APFSVolumeCreate failed: %d: %s\n", retval, mach_error_string(retval));
}

char actual_fakefs_mntfromname[50];
Expand All @@ -176,19 +251,13 @@ int setup_fakefs(uint32_t __unused payload_options, struct paleinfo* pinfo_p) {
CFRelease(volumeRole);
CFRelease(dict);

if (strstr(rootfs_st.f_mntfromname, "/dev/disk0s1s") != NULL) {
snprintf(actual_fakefs_mntfromname, 50, "/dev/disk0s1s%d", fsindex+1);
} else if (strstr(rootfs_st.f_mntfromname, "/dev/disk1s") != NULL) {
snprintf(actual_fakefs_mntfromname, 50, "/dev/disk1s%d", fsindex+1);
} else {
panic("unexpected rootfs f_mntfromname %s", rootfs_st.f_mntfromname);
}
if (strcmp(actual_fakefs_mntfromname, fakefs_mntfromname)) {
panic("unexpected fakefs name %s (expected %s)", actual_fakefs_mntfromname, fakefs_mntfromname);
}
snprintf(actual_fakefs_mntfromname, 50, "/dev/%s%d", volume_prefix(), fsindex+1);

nvram("p1-fakefs-rootdev", &actual_fakefs_mntfromname[5]);

sleep(2);
struct apfs_mount_args args = {
fakefs_mntfromname, 0, APFS_MOUNT_FILESYSTEM, 0, 0, { "" }, NULL, 0, 0, NULL, 0, 0, 0, 0, 0, 0 };
actual_fakefs_mntfromname, 0, APFS_MOUNT_FILESYSTEM, 0, 0, { "" }, NULL, 0, 0, NULL, 0, 0, 0, 0, 0, 0 };
CHECK_ERROR(mount("apfs", "/cores/fs/fake", 0, &args), 1, "mount fakefs failed");

struct utsname name;
Expand All @@ -215,7 +284,7 @@ int setup_fakefs(uint32_t __unused payload_options, struct paleinfo* pinfo_p) {

int fd_fakefs = open("/cores/fs/fake", O_RDONLY | O_DIRECTORY);
if (fd_fakefs == -1) {
panic("cannot open fakefs fd");
_panic("cannot open fakefs fd");
}

CHECK_ERROR(fs_snapshot_create(fd_fakefs, "orig-fs", 0), 1, "cannot create orig-fs snapshot on fakefs");
Expand All @@ -241,7 +310,7 @@ int setup_fakefs(uint32_t __unused payload_options, struct paleinfo* pinfo_p) {
if (access("/sbin/umount", F_OK) == 0)
runCommand((char*[]){ "/sbin/umount", "-a", NULL });

enter_recovery();
nvram("auto-boot", "false");
sync();
return 0;
}

0 comments on commit 84213cf

Please sign in to comment.