Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(probably not the most mergable) *reliable* M1 iPad Pro support #49

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

TheMasterOfMike
Copy link

@TheMasterOfMike TheMasterOfMike commented Oct 22, 2023

I honestly doubt that this is mergable for two main reasons:

  • The fixes being made cause us to use over 4GB of RAM, which pretty much every device besides the M1 iPad Pro's will not be happy with whatsoever
  • The fixes being made, even ignoring that bit, cause exploitation time to balloon to over 3 minutes with kfd (which no other device should suffer through)

Thanks @opa334 and @verygenericname for various fixes in helping me to make this a thing.

@verygenericname
Copy link

You're gonna need to make it check which device it's running on, for it to be atleast somewhat mergeable, I guess

TheMasterOfMike added a commit to cfw-guide/ios.cfw.guide that referenced this pull request Oct 23, 2023
To simplify this, basically due to various factors, the implementation of kfd in the official latest release of Taurine is, at best, extremely unreliable with M1 iPad Pro's, and generally tends to outright not work for people.

Due to my interesting purchasing decisions, I happened to acquire an M1 iPad Pro on 14.6, and ended up modifying the kfd exploit and building a modified Taurine ipa that works fairly reliably for M1 iPad Pro's.

Am I trying to get this merged into mainline? Yes (Odyssey-Team/Taurine#49) but I don't have a lot of hope in it being merged, due to how the changes needed are impractical to implement for non-M1 devices.

Oh, and before anybody asks, yes, somebody else besides me tested this, it works fine.
Copy link

@0xilis 0xilis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should detect if the device is an M1 iPad and only do the changes if so, it'll make this much more mergeable. Probably can be improved (but should work fine for now): See below changes.

Copy link

@0xilis 0xilis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Detect M1.

@@ -262,7 +262,7 @@ class ViewController: UIViewController, ElectraUI {
case .kfdPhysPuppet:
print("Selecting kfd [physpuppet] for iOS 14.0 - 14.8.1")
LogStream.shared.pause()
let ret = do_kopen(0x800, 0x0, 0x2, 0x2)
let ret = do_kopen(0x20000, 0x0, 0x2, 0x2)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let ret = do_kopen(0x20000, 0x0, 0x2, 0x2)
var systemInfo = utsname()
uname(&systemInfo)
let machineMirror = Mirror(reflecting: systemInfo.machine)
let deviceModel = kernelMirror.children.reduce("") { identifier, element in
guard let value = element.value as? Int8, value != 0 else { return identifier }
return identifier + String(UnicodeScalar(UInt8(value)))
}
let ret;
if (deviceModel.contains("iPad13") && deviceModel != "iPad13,1" && deviceModel != "iPad13,2") {
// M1 iPad Pro
ret = do_kopen(0x20000, 0x0, 0x2, 0x2)
} else {
ret = do_kopen(0x800, 0x0, 0x2, 0x2)
}

detect M1.

Sorry I don't know how to make reviews for multiple files so making multiple reviews for them :P

@@ -272,7 +272,7 @@ class ViewController: UIViewController, ElectraUI {
case .kfdSmith:
print("Selecting kfd [smith] for iOS 14.0 - 14.8.1")
LogStream.shared.pause()
let ret = do_kopen(0x800, 0x1, 0x2, 0x2)
let ret = do_kopen(0x20000, 0x1, 0x2, 0x2)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let ret = do_kopen(0x20000, 0x1, 0x2, 0x2)
var systemInfo = utsname()
uname(&systemInfo)
let machineMirror = Mirror(reflecting: systemInfo.machine)
let deviceModel = kernelMirror.children.reduce("") { identifier, element in
guard let value = element.value as? Int8, value != 0 else { return identifier }
return identifier + String(UnicodeScalar(UInt8(value)))
}
let ret;
if (deviceModel.contains("iPad13") && deviceModel != "iPad13,1" && deviceModel != "iPad13,2") {
// M1 iPad Pro
ret = do_kopen(0x20000, 0x1, 0x2, 0x2)
} else {
ret = do_kopen(0x800, 0x1, 0x2, 0x2)
}

detect M1

Comment on lines +211 to +214

uint32_t magicToSearch = 0x1EA5CACE;
void *res = memmem((void *)kfd->puaf.puaf_pages_uaddr[i], 0x4000, &magicToSearch, sizeof(magicToSearch));
assert(res == NULL);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

@@ -25,7 +25,7 @@ u32 kread_IOSurface_kread_u32(struct kfd* kfd, u64 kaddr);

void kread_IOSurface_init(struct kfd* kfd)
{
kfd->kread.krkw_maximum_id = 0x4000;
kfd->kread.krkw_maximum_id = 0x1000;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
kfd->kread.krkw_maximum_id = 0x1000;
struct utsname systemInfo;
uname(&systemInfo);
if (strncmp(systemInfo.machine, "iPad13",6) == 0 && strcmp(systemInfo.machine, "iPad13,1") != 0 && strcmp(systemInfo.machine, "iPad13,2") != 0) {
kfd->kread.krkw_maximum_id = 0x1000; //M1 iPad Pro
} else {
kfd->kread.krkw_maximum_id = 0x4000; //All other devices
}

detect M1

Comment on lines +39 to +40
#ifdef ENABLE_XPC
#include <xpc/xpc.h>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#ifdef ENABLE_XPC
#include <xpc/xpc.h>
#ifdef ENABLE_XPC
#include <xpc/xpc.h>

remove accidental indent

@@ -176,7 +176,7 @@ u64 kopen(u64 puaf_pages, u64 puaf_method, u64 kread_method, u64 kwrite_method)
timer_start();

const u64 puaf_pages_min = 16;
const u64 puaf_pages_max = 2048;
const u64 puaf_pages_max = 131072;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const u64 puaf_pages_max = 131072;
const u64 puaf_pages_max = 2048;
struct utsname systemInfo;
uname(&systemInfo);
if (strncmp(systemInfo.machine, "iPad13",6) == 0 && strcmp(systemInfo.machine, "iPad13,1") != 0 && strcmp(systemInfo.machine, "iPad13,2") != 0) {
puaf_pages_max = 131072; // M1 iPad Pro
}

detect M1

Comment on lines +211 to +214

uint32_t magicToSearch = 0x1EA5CACE;
void *res = memmem((void *)kfd->puaf.puaf_pages_uaddr[i], 0x4000, &magicToSearch, sizeof(magicToSearch));
assert(res == NULL);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

@0xilis
Copy link

0xilis commented Oct 23, 2023

Detect M1.

Fixed an accidental wrong change to the wrong file, now this should work :P. If anyone has any more suggestions, feel free to say them.

Copy link

@0xilis 0xilis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

optimize M1 check

Comment on lines 208 to +214
for (u64 i = 0; i < kfd->puaf.number_of_puaf_pages; i++) {
u64 puaf_page_uaddr = kfd->puaf.puaf_pages_uaddr[i];
print_buffer(puaf_page_uaddr, 64);

uint32_t magicToSearch = 0x1EA5CACE;
void *res = memmem((void *)kfd->puaf.puaf_pages_uaddr[i], 0x4000, &magicToSearch, sizeof(magicToSearch));
assert(res == NULL);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
for (u64 i = 0; i < kfd->puaf.number_of_puaf_pages; i++) {
u64 puaf_page_uaddr = kfd->puaf.puaf_pages_uaddr[i];
print_buffer(puaf_page_uaddr, 64);
uint32_t magicToSearch = 0x1EA5CACE;
void *res = memmem((void *)kfd->puaf.puaf_pages_uaddr[i], 0x4000, &magicToSearch, sizeof(magicToSearch));
assert(res == NULL);
struct utsname systemInfo;
uname(&systemInfo);
if (strncmp(systemInfo.machine, "iPad13",6) == 0 && strcmp(systemInfo.machine, "iPad13,1") != 0 && strcmp(systemInfo.machine, "iPad13,2") != 0) {
for (u64 i = 0; i < kfd->puaf.number_of_puaf_pages; i++) {
u64 puaf_page_uaddr = kfd->puaf.puaf_pages_uaddr[i];
print_buffer(puaf_page_uaddr, 64);
uint32_t magicToSearch = 0x1EA5CACE;
void *res = memmem((void *)kfd->puaf.puaf_pages_uaddr[i], 0x4000, &magicToSearch, sizeof(magicToSearch));
assert(res == NULL);
}
} else {
for (u64 i = 0; i < kfd->puaf.number_of_puaf_pages; i++) {
u64 puaf_page_uaddr = kfd->puaf.puaf_pages_uaddr[i];
print_buffer(puaf_page_uaddr, 64);
}
}

not completely sure if this would break M1, but just to be sure for now I'm keeping the check in.

@opa334
Copy link

opa334 commented Oct 25, 2023

Tbh the proper way to do this would be to determine the exact RAM size at runtime and then choose an appropriate page count based on that.

@TheMasterOfMike
Copy link
Author

Tbh the proper way to do this would be to determine the exact RAM size at runtime and then choose an appropriate page count based on that.

This probably is the cleanest solution, but at the same token, we'd want to limit any changes to just devices with 8GB or 16GB of RAM (which - on iPadOS 14 - only includes the M1 iPad Pro's) else we risk detrimental effects with exploit time on other devices.

(We'd probably also want to do the RAM size check to determine the number of IOSurface's as well - since making any alterations outside of what we need to do on the M1 iPad Pro's will reduce success rate on other devices - which we obviously want to avoid)

@opa334
Copy link

opa334 commented Oct 25, 2023

Tbh the proper way to do this would be to determine the exact RAM size at runtime and then choose an appropriate page count based on that.

This probably is the cleanest solution, but at the same token, we'd want to limit any changes to just devices with 8GB or 16GB of RAM (which - on iPadOS 14 - only includes the M1 iPad Pro's) else we risk detrimental effects with exploit time on other devices.

(We'd probably also want to do the RAM size check to determine the number of IOSurface's as well - since making any alterations outside of what we need to do on the M1 iPad Pro's will reduce success rate on other devices - which we obviously want to avoid)

I think the fact one device has a limit means we would want to reduce the amount of IOSurfaces on all of them to make sure we're not hitting that threshold. Or the exploit could be modified to just use as many IOSurface's as possible until it starts failing.

@TheMasterOfMike
Copy link
Author

TheMasterOfMike commented Oct 25, 2023

Tbh the proper way to do this would be to determine the exact RAM size at runtime and then choose an appropriate page count based on that.

This probably is the cleanest solution, but at the same token, we'd want to limit any changes to just devices with 8GB or 16GB of RAM (which - on iPadOS 14 - only includes the M1 iPad Pro's) else we risk detrimental effects with exploit time on other devices.
(We'd probably also want to do the RAM size check to determine the number of IOSurface's as well - since making any alterations outside of what we need to do on the M1 iPad Pro's will reduce success rate on other devices - which we obviously want to avoid)

I think the fact one device has a limit means we would want to reduce the amount of IOSurfaces on all of them to make sure we're not hitting that threshold. Or the exploit could be modified to just use as many IOSurface's as possible until it starts failing.

As for the former, the problem I see with doing that is that we're either:

  • hurting exploit reliability for the same exploit time
  • hurting exploit time for the same exploit reliability

(mind you: this assumes that 8192 puaf pages with 4096 IOSurface's has the same reliability as 2048 puaf pages with 16384 IOSurface's, which is something I'd have to check when I get the chance to in a few hours)

As for the latter, the only sign that I've observed that we could potentially utilize is that console will say that we are approaching a limit at both 50% and 75% of the IOSurface limit - if we can use those, then that's probably the better way, but if we can't, then I'm not aware of any better indicators.

@opa334
Copy link

opa334 commented Oct 25, 2023

I mean, the sign here is that the surface allocate method fails with an error code after 4096, when we hit that we could just remove the assert and just use the surfaces that have been allocated until then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants