Apple’s Memory Integrity Enforcement

Apple’s Memory Integrity Enforcement

Apple announced its new suite of memory security improvements from the top of the stack all the way to the bottom, so we dug through what they did and how they did it (performantly).

Watch on YouTube: https://www.youtube.com/watch?v=9FJwOI2PliU

Links:


This rough transcript has not been edited and may have errors.

Deirdre: Iiiiin the trust zone.

David: Exactly.

Deirdre: With white curtains. No, it’s the other way around. In the white room with black curtains.

Thomas: I have nothing to do with any of what you guys are talking about.

Deirdre: Hello. Welcome to Security Cryptography Whatever. I’m Deirdre.

David: I’m David.

Thomas: I don’t know what I’m talking about in this episode.

Deirdre: That’s Thomas.

David: Thomas says that every episode. And yet I. Everyone keeps coming back.

Deirdre: Yeah. We tried really hard to get a special guest for today’s episode on Apple’s Memory Integrity Enforcement and no one from Apple would come on our podcast. So we are talking about it.

David: This should be surprising to nobody.

Deirdre: Yeah, no, like this is a fool’s errand, but we are trying to dig through this very cool innovation in low level operating system security, or system security. And all we have to go on is basically their long blog post. And so we’re trying to go through what the hell is memory integrity enforcement and how is it different than all this other stuff that’s been deployed in, say, Android or arm? So that’s what we’re trying to do.

David: And just know Apple people. We know you’re listening. We know you know who you are. We know that you know that we know who you are. And when we say things that are slightly inaccurate. You could have fixed this, huh?

Deirdre: Okay, so this is the post that Apple released, put out back in September. This is an improvement that’s getting actually.

David: Shipped in iPhone 17, available now.

Deirdre: Okay.

David: I bought one for myself, but I accidentally shipped it to an address I don’t live at anymore and then had to cancel and refund it and I haven’t gotten replaced. Replacement. Yeah, sense.

Deirdre: Very good, Very good. Opsec or something. Okay, so this is. This whole memory integrity enforcement is like a suite of things. Basically. It seems to be a bunch of improvements that they’ve already shipped to their kernel allocators and to their user land allocators, but also how they’re actually managing memory much farther down in the stack. And some of these are becoming available to previous iPod’s and Mac OSes and I assume vision OSes or whatever. But some of them are explicitly because of the hardware and improvements in the chips and the memory integrity and things like that are specifically to the hardware that’s actually getting shipped from iPhone 17 and forward.

And this is explicitly to try to improve the security posture of the entire system against memory attacks, which tend to be some of the most dangerous, costly in terms of the impact and the blast radius, but also are difficult a lot of times on our Podcast we’ve talked about, you know, write your code in a memory safe language and a lot of these vulnerabilities are addressed by writing code in a memory safe language. But you know, there’s a lot of OS code that’s still written in non memory safe languages for very, for one there’s just been a lot of investment in there. You can’t just like throw the baby out with the bathwater and rewriting everything in a memory safe language or the most important things in memory safe language is you know, either impossible, difficult, takes a long time or you know, you have to pick and choose what those things are. But also there are things that you do in your and at like the lower than the OS level, like in your kernel and like at your bootloader level and further down you really need to like get your, your hands grubby in and you can’t just, you have to be doing weird things with memory and stuff like that so you can’t rewrite the world in rust. This is a lot of stuff that’s trying to address that sort of security posture, like deep, deep, deep in the stack in a way that when you have full control tip to tail, top to bottom of your system, they seem to be uniquely positioned to do okay. So we’re just basically going to plow through this post and just branch out from there. IOS attacks, mercenary software, blah, blah, blah. Yes, very important and common denominator targeting, using iOS, Windows and Android. They exploit memory safety vulnerabilities which are interchangeable, powerful and exist throughout the industry.

Thomas: I think the interchangeable thing is actually.

David: A really big deal.

Thomas: Like I think that, I think like it’s a thing I think people are probably not gonna talk about enough. Right.

Deirdre: So are you saying that like if you have your kind of spyware as a service service stack, you basically have something that you can deploy cross platform and then you’re like cool, I’m on iOS, I’m going to plug in this, but if I’m on Android I’m going to plug in this exploit and if.

Thomas: I’m on Windows I think it’s lower level than that. Now I’m talking out of my ass and extrapolating things that we like talk to Mark doubt about and things like that. Right. But I have no inside knowledge into how these shops are organized. But my impression is you’ve got like, you know, you’ve got individual vulnerabilities and then you have a whole stack of enabling software around the individual vulnerabilities in kind of the same way that you would have multiple sandbox breaks in Chrome. Like to get from one area of the Chrome architecture to another. Right. It’s weird to call them components, or maybe they are components, I don’t know.

But there’s techniques that people use to pivot from one kind of exploit primitive to the next exploit primitive. And I think a lot of modern exploit development depends on kind of plugging and playing techniques, right? Like you’ve built code that takes like a write what where primitive from you know, point X to point Y or this kind of type confusion to point X and point Y. Right. And in addition to just trying to solve those, to break those primitives directly, it’s also valuable to make it so that every time you have a new vulnerability, you have to rebuild the whole stack of enablement stuff around it. Right. So that path from the primitive to actually doing something useful has to be built uniquely for every one of these things.

Deirdre: Yeah, that makes sense.

David: It also may be the case that like that path is like the individual components within that path are also operating specific and not just in the like obvious location where like, you know, the part that gives you control of the Windows kernel is going to be dependent on Windows. But like in a browser renderer process, if you can find like a privilege escalation through some syscall that is exposed to the renderer process, then you can like skip the step or you do like a browser sandbox escape. If you can go straight from say a renderer process to the operating system. But how your mechanism for doing that is going to vary platform to platform.

Deirdre: Okay, that makes sense. I wasn’t sure what’s the specifics were about interchangeable, but yeah, that makes sense. Apple improving memory safety Swift blah blah blah. In iOS 15 we introduced K Alloctype, a secure memory allocator for the kernel. Followed in iOS 17 with its user level counterpart Xzone Malloc Secure Allocators take advantage of knowing the type or purpose of allocation so that memory can be organized with it. It makes exploiting most memory corruption vulnerabilities inherently difficult. So I think this is the stuff that’s like getting backported to earlier devices if they can support 15 and iOS 15 and 17.

David: Well it already exists in those devices, so it’s not really getting K. Alloctype is basically an allocator that like looks at the structures that are used in the kernel and then generates a type signature basically based off of the the layout of the various fields in the struct itself.

Deirdre: That’s cool.

David: And then only like then you have like various buckets that are used at the like page level allocation and then you only put objects of the same type signature in the same bucket so that like, you can’t ever say like, have a object that has like an integer in the first eight bytes, then be in the same bucket as an object that has a pointer in the first eight bytes and then a bunch of like stuff to make that actually work in practice. So the idea is that like in a use after free situation, you’d only ever be replacing the object with an object of the same type, which is presumably harder to exploit than an object of a completely different type. Thomas, can you explain what a use after free vulnerability is?

Thomas: You all know what a use after free vulnerability is.

Deirdre: Please explain to our audience.

David: Well, I mean the name is pretty self explanatory, but like, why is it a vulnerability? I actually like didn’t understand this until I worked on Chrome.

Thomas: I mean, I think the type confusion thing might be the simple like you just kind of laid out the obvious case, right? So like, especially in like complicated C and C code bases, like you’re allocating memory and then explicitly freeing memory, and that happens in totally different places on the call chain sometimes, like you might have something fire in response to a timer or something like that, right? So like this is a really pernicious class of bugs. Not even necessarily vulnerabilities, just bugs, right? Like you freed something when you didn’t expect to free something and you held onto a pointer for it. If you induce those bugs deliberately, you wind up with this dangling pointer. And in the best case, like the dangling pointer gets used and the program crashes because it’s no longer mapped to anything. That’s what you want to have happen, right? But an attacker inducing this will set it up so that you freed the memory, you held the dangling pointer, and then it made a whole bunch of other allocations and like really strategically with the allocation pattern picked what your dangling pointer will now point to. So in that situation, like David was just saying, right, you had a struct, it had like two integers in the front of it, and now it has a pointer in the front of it, right? And like the code path that’s holding that dangling pointer somehow responds to user input. You write to the integer, and by writing to that integer, you’re writing a pointer instead of, you know, just the integer. So like you’re kind of, you’re using that piece of, you’re using that piece of memory as two different types in two different locations in the code.

Like the code is confused about what the type it is. Right. And you are now rewriting a pointer out from underneath the code and you can have it write to a location of your choosing.

Deirdre: And this is extremely valuable to an adversary who’s able to just be like, you thought you were doing this, but I’m going to twiddle it and I get to make you do something you weren’t expecting, like execute this piece of code when you weren’t supposed to. And then you can leverage that however you like.

Thomas: Yeah, it’s a way of getting a write what where primitive. Right. Usually a pretty constrained write what where primitive. I get to pick what you’re going to write and where it’s going to be written to. And that usually historically is game over. And making that not be game over. I’m saying it’s game over. And it was probably game over in like 2011.

And it’s been not game over ever since then. But whatever. Kind of one of the big things about MIE is making that not be game over anymore.

Deirdre: Oh yeah, making it not be game over. It’s game over for the attacker. Ha ha ha. Cool. So K Alloc did its nice little thing inside the kernel and then we have Exon Malloc that’s used by user lancode.

David: I would just add that even if you magically do this in the allocator, like doing this can cause weird shit to happen because sometimes you just might want to treat some memory as a different memory and there’s two pointers that are different types that happen to point at the same spot and then like stuff gets weird. Right. Or maybe you want to change something out for something else because it’s the kernel and you’re fundamentally doing unsafe things.

Deirdre: Yep.

David: Like if someone does crap like that and just like a user land C program, it’s, you know, it’s 2025, you have permission to just go slap them. But in the kernel, like that’s just kind of the way the world is sometimes. So just because you have the allocator actually using it can be fairly complicated. Which interesting Apple talks a lot about in their massive KL post from a.

Deirdre: Couple years ago, which I’m just. I keep scrolling through because this is like the first time I’m looking at it. This is in fact ginormous. And I am not a kernel hacker.

Thomas: So I feel like type specific, like general purpose type specific Allocator was new. Right. Like not a super Commodore building program. Primitive. Right. So you have like.

David: Yeah.

Thomas: You have protections on like a page based Level based mostly on allocation sizes. Right. Like you could be strategic about whether you know. And I guess you could put things in different arenas and manually in your code, pick which area things are coming out of. All with the intent of trying to avoid that situation where the struct with the integer and the struck with the pointer at the beginning don’t ever share the same memory. And then like doing that at the level of a type thing. Which requires compiler help, right? I think it requires compiler. Yeah, that’s, that’s, that’s newish.

David: Yeah. So Apple gives a lot of benefit here from basically controlling their own Clang implementation which they rely on to be able to do this in the kernel. There is a recent actual Clang and like C extension typed operator new that I believe. I don’t remember if LLVM like directly or if Apple or Google added it or some combination thereof. But like in C, instead of just overloading operator new which takes a size T and like gives back some bytes or whatever, it lets you overload operator new like a size T and then a type T which is like a 128 bit integer or something. And it just like, like hey, you know, here’s random type information. Don’t ask questions about it. Right.

I think there might be a way to provide it, to define it yourself in code. But the idea is to make like a type aware global allocator. Something you could do in userland C code, but it relies on like C semantics of operating new.

Deirdre: That’s nice. I didn’t know any of this. Okay. I think that’s like the first chunk of memory integrity enforcement which is like stuff they already shipped basically. And it’s the user land updates to Exon Malloc or introduction of Exxon Malloc and the kernel Land chaotic type.

David: Keep in mind the total number of buckets here is limited. The whole point of the way they score the like structs is to try to minimize like impact of where like one thing’s a name and one thing’s a pointer. But there’s an arbitrarily large number, at least in userland of types that you can encounter. And like at some point you have to start reusing buckets.

Deirdre: So in 2018 we were the first to deploy pointer authentication codes in the A12 chip to protect code flow integrity in the presence of memory corruption. This was very successful with Pack behind us.

David: Pack is like a goofy thing because really. Well, I mean it’s not like I.

Deirdre: Know nothing about pac.

David: It’s really hard to describe specifically what Pack does because it can be used as a primitive to just build like your regular control flow integrity. Like forwards edge, backwards edge or only one of the edges. I never remember which one is which. And like basically it boils down to like you replace like the function header in assembly with like a pack aware, jump and return.

Deirdre: Okay.

David: And you’re supposed to get CFI out of it. And then there’s like broader. But the like base concept behind pointer auth is just somehow that like there is a signature in the semi cryptographic sense and every pointer and like that signature needs to be valid for the pointer to be valid. So if you’re just dinking around with pointers like your signature is probably not valid, but I mean or it’s like not valid in the right location. But I don’t actually understand how it works specifically other than like there are people posting pack bypasses. Like there’s at least one pack bypass on Apple hardware submitted to Black Hat like every year, which is the same thing as cet. The like intel control flow integrity. It helps but like at the end of the day like you can usually find a way around it.

Deirdre: Okay.

Thomas: Brandon Azad had a talk about this in 2020 blackout CET or PAC PAC bypasses.

David: Okay, so that brings us to MTE itself or memory tagging extension, which is an ARM specification that is technically in more things than just Apple devices.

Deirdre: Memory tagging extension MTE is from arm. It’s independent of Apple. It’s just a thing anyone can use for ARM chips.

David: Or I believe it’s mandatory to implement an ARM 11 or ARM 10 or something like that. But like nice or it’s not mandatory to implement. You know, it’s a sign, not a cop. Right?

Deirdre: I can’t make you do anything. Yeah, Memory tagging and tag checking system. Every memory allocation is tagged with a secret. This is sort of similar to the pack signatures, except in the cryptographic sense they’re probably closer to max or whatever.

Thomas: Well, hold on. Yeah, MTE tags are tiny, right?

David: Yeah, MTE tags is the 4 bit number. So you’ve got your 64 bit pointer and then somewhere else there is a 4 bit number associated with that pointer and that’s your tag.

Deirdre: Okay.

Thomas: PAC signatures are larger I thought. Right. Like one of the, like one of the, like the model PAC bypasses is finding a gadget that will resign. You know, pointers. Right.

Deirdre: I just don’t know anything about PAC signatures or whatever they’re called.

Thomas: Yeah, they’re signatures.

Deirdre: Okay, cool.

David: I believe PACK is just using some of the High bits in the pointer, it’s not actually making the pointers wider because that would, like, totally screw up everybody’s code. Right. It’s supposed to be transparent. So I think you get like 16 to 24 bits of your 64 bits on an Apple machine or reserve for pack, and then the virtual address space is like, 48 bits.

Deirdre: That’s neat. Okay, so unlike that, MT has four bits that have to be kept secret.

David: But they are kept secret in the sense that they’re, like, not in the pointer. Right. They are somewhere else. They are associated with a pointer, but they are fundamentally like four bits of entropy associated with every pointer that, in theory, like, you do not have access to.

Thomas: And, like, the security model here is more like graph coloring than, like, setting things right. What you care about is a diversity of different tags within the locality of a piece of memory. Like, if you, you know, write. You know, write off the end of one thing to the next thing, you need the tags to be different and you need to not leak the tags rather than signatures.

David: Yeah. The idea is that if you access. When you allocate some piece of memory, it will have some tag. If you then free it, but the point end gets used for a new allocation, it will have a new tag, and the used after freeptr will still have the old tag. And when you go to do something with it, the processor will compare the expected tag to the actual tag and then be like, oh, no, crash your program. It’ll crash your program if it’s in synchronous mode, and if it’s in asynchronous mode, it’ll keep running your program and then crash it later.

Deirdre: Hmm. Okay.

David: Yeah. It will continue execution until there’s a context switch.

Deirdre: I mean, I guess.

David: Interrupt.

Deirdre: Yeah, I guess that’s part of the whole async thing.

David: Yes.

Deirdre: Okay.

David: Much more performant because you can delay the check till later and, like, keep executing the code and probably do the checks less. Because, like, imagine you use the same pointer like, eight times in a row to do something. Like, you really only need to, like, check it the first time.

Deirdre: Oh, okay.

Thomas: Async is, like, effectively free, right?

David: It’s not. I mean, it’s like a one. A little over 1% impact, I think.

Deirdre: Okay.

David: So this has been something that’s been around for a while, but, like, in the sense that it’s been defined, but it just hasn’t really existed in chips much. It’s in pixel phones. I think it’s in, like, Pixel starting in 10 or something like that. Pixel 8.

Thomas: It’s Pixel 8.

David: And so you can actually go into Android Settings somewhere and enable this and apps that are like aware of it can leverage it. So if you turn MTE on in a Pixel phone like Chrome will run itself in Async MTE mode. And in fact this will happen automatically. If you’re in like the Android Advanced Protection mode on your device and your device supports mte, it will get turned on in like Chrome, for example, will start using MTE in Async mode.

Deirdre: Oh, this is a developer option.

David: Yeah, so otherwise it’s in developer option, but it’s not on by default because like it’s a battery hit, just like a performance hit.

Thomas: So, and then synchronous classically has been very expensive.

David: Yeah. Then synchronous has been like double digit percentage expenses.

Thomas: But like, so graphene for instance. Graphene does synchronous in the kernel and Async out of the kernel. And then I’m guessing that the intuition there is you spend most of your time in userland, not in the kernel. So like a double digit percentage hit to a place where you’re only spending a small percentage of your time is not that big of a thing. So you can be. And also there are much more fun vulnerabilities in the kernel. So there’s a higher payoff.

David: Yes. A 1% performance hit on the latest high end phone is not the same thing as a 1% performance hit on an older phone or even a higher percentage hit on an older phone. That’s probably a more realistic comparison. It’s like, okay, it’s a 1% performance hit here, but on an older phone it’s actually a 5 to 10% performance hit. It can be easy to like, be like, oh, I have a MacBook Pro or I have a high end Chromebook, or I have a Pixel. So I’ll just take a couple percent here and there and trade it off when, like when you’re not on the highest end devices, that can actually be much more impactful.

Deirdre: I could definitely see that. Yeah, I just confirmed that if you are enrolled in Advanced Protection and you’re logged into your Google account on an Android phone that supports it, it enables MTE for you. Because I was like, I don’t remember turning this on on my phone. I was like, no, you did. Bye. Bye.

David: You can enable it on an individual device without enabling it on your account, but if you enable it on your account and sign in, it will get enabled on that device.

Deirdre: Yes. Yeah, that’s how it happened. Cool. Okay. I’M going back, that’s general MTE that’s been available to like broad arm devices in general?

David: Well, I wouldn’t say broad arm devices. Right. There was like a spec for this, but it really didn’t exist in hardware for a while. It’s never been in server software. Like Google jammed it into Pixel. We learned that, you know, Apple put it into some of their devices but like it is not cheap. It is like a large percentage of the die area to put MTE into a chip and it is not fast. Like there are other, there are other like things in this vein like CHERI for example that take like much less die area.

It’s like a very small number of gates to add CHERI. But you have to like do a code rewrite where you like. All my pointers are 128 bits. Now let’s see what happens first.

Deirdre: CHERI is also a bare performance hit, right?

David: I’m not sure actually, I think it’s smaller actually. It’s just like really you. To make use it effectively, you have to kind of define pointer domains and code yourself and at some point it’s just like dude, just rewrite it in rust.

Deirdre: Well, you know, CHERI is supposed to. Isn’t CHERI also supposed to help mitigate like Spectre micro architectural attacks to a degree as well? It’s not just about the memory safety stuff.

David: I didn’t think so, but I’m not sure. Okay, I can feel Ben Laurie getting upset listening to this.

Deirdre: CHERI is supposed to be trying to address a whole host of up and down the stack like CPU design vulnerabilities, not just the sort of memory safety stuff that I guess the MIE stuff is trying to address. So anyway, MT has core memory tagging check, memory tagging and tag checking system. This got deployed on Pixel. It’s been available in some places, but there’s costs. Apple conducted a deep evaluation and research process to determine whether MTV is designed with meter goals or.

Thomas: Okay, we don’t need to read, we don’t need to read these parts of the book.

Deirdre: Well, I’m getting back into it.

David: We went to Apple, applied the faman method to MTE and came thought real hard about the problem and came up with emte. Yes, Apple never.

Thomas: The iPhone, which has never been compromised before, now has groundbreaking new protections for the things that was.

David: Never mind the fact that there’s no malfunctor at all on iPhone. Anyway, here’s an entire post explaining how we’re patching security holes on the iPhone. Apple doesn’t really say what EMTE does. Beyond like, it’s just MTE in synchronous mode and fast. I don’t know.

Thomas: My understanding is that Emte is just another name for MTE4, right? Which is a set of like four MTE extensions. It’s canonical pack checking. It’s the one they list in the blog post. The one they list in the blog post is like your global variables or I guess your tech, your BSS or whatever the data segment is or whatever, right? Like you have variables that are not tagged regions.

David: Right?

Thomas: And in standard MTE there’s no checking for that. And in MTE4, I don’t totally understand how this works, but there is checking for memory accesses that transition from a tagged memory region to an untagged memory region. So in theory it should automatically detect, right? If you’re running off the end of a tagged memory region into untagged memory, then the tag has changed even though the new tag is nil. And I guess that wasn’t checked before. And now it is with MTE4.

Deirdre: So this is the ARM docs that Apple linked. Canonical tag checking, reporting all non address bits on a fault. Store only tag checking and memory tagging with address tagging disabled.

Thomas: I thought we already had store only tag checking. Or maybe I just don’t know what store only tag checking is. But I was saying earlier that graphene does like the kernel, asynchronous and then the usual end is asynchronous. But there’s also a thing with them where like reads are synchronous and writes are asynchronous, which I thought that might have been what store only tag checking is. I don’t. I don’t know. Fuck do I know.

David: So we have a few more capabilities around MTE itself with MTE4EMTE and then more importantly, whatever they did on their chips in conjunction with the capabilities in MTE4 coming up, Apple claimed they have done fast.

Thomas: We’re coming up on my favorite section of this post or my favorite sentence in the post, it was like, consider that you could do either async or synchronous mode. Synchronous is the good mode and asynchronous is the bad mode. We could have implemented asynchronous. We would not implement such a mechanism. Apple, please run these things by me.

David: No, the copy speculated the writing. You know, as someone Apple who’s like been making their own chips for years, you could imagine that presumably they didn’t. This isn’t their first iteration of, you know, mte, right? They’ve presumably been experimenting with this and just like not turning it on, like I can’t imagine this is the first time they ever taped out some of the chip that is required for mte. Which suggests to me that at some point someone might have implemented such a mechanism. They just didn’t tell us about it.

Thomas: All they had to do is use a different verb there. They could have just said we didn’t implement such a mechanism and it would have read fine, but they wrote we wouldn’t, which reads so weird.

Deirdre: Depends what you mean by implement. Which in this very, very massaged public facing text might mean implement and deploy and ship.

Thomas: I want to call out here that the graphene project, who by the way, if a graphene person listens to this, we would very much love to get you on and have you go through a dramatic reading of this with us and then call out because look, you hear us, we don’t know what we’re talking. David knows a little bit about what he’s talking about, but I don’t. Right. We could use the help. I want to call out though that the graphene project. There’s an angry thread that responded to this thing. I won’t read that whole thread, but it’s worth reading. And they say that there’s basically no difference that they’ve seen in terms of breaking exploits by having async versus synchronous.

Thomas: Like to them, async is enough.

Deirdre: Okay.

Thomas: Depends on how much you care about what graphene thinks. I want to say I care a lot about what graphene thinks because I.

David: Would research from Project Zero suggests otherwise. Depending on the setup that you’re in, it is what it is. The thing about MTE generally and then particularly about Async, right, Is that like, so you have four bits of entropy with the pointer. And in some cases, like let’s say you’re a web browser that runs like arbitrary JavaScript depending on what the behavior is. When like in the failure case, like if you can just run your exploit 16 times and then, you know, have a more likely than expected value of having it be successful one of those times, if all of the other 15 times are like a huge disaster and you can’t actually write that loop, like maybe that’s a problem. Like if you’re able to just do it in the background and like no one’s really the wiser somehow by like having some JavaScript that then like loads another page that tries it 16 times. So that like that process that you never see is the one that dies because it’s whatever. Then then suddenly like, you know, MTE is not like this be all, end all.

It’s much more useful in a situation where you only get one shot at it or a limited number of tries or a limited reaction time to it. And the more shots you get at it, or the more instructions you get after it fails, like the more likely it is that you’ll be able to concoct a situation in which you can get a tag match and then can do something bad. But that’s all going to depend on like you know what your program is. And of course like web browsers are stuck with the hardest mode of the problem because they’re like, let’s just run a bunch of code from arbitrary sites and like isolate some of it per process and some of it like within the process.

Deirdre: Yeah, for web browsers.

David: And it can all change dynamically. You don’t even get a canonical version of the code to download before you run it.

Deirdre: Downloaded that webpage two minutes ago. Fuck you. You don’t get to rely on that at all. Apple says that always on synchronous MTE across key attack surfaces while preserving a great high performance user experience is extremely demanding on hardware. Well, lucky Apple that they seem to be very good at designing fresh brand spanking new hardware to do everything they need to do. For MTE to provide memory safety in an adversarial context, we need to finely tune the OS to define new semantics and the confidentiality of memory tags on which MTE relies to do what we think we need to do, we would carry out a massive engineering effort spending all of I love Apple, Apple silicon operating systems and software frameworks. Excuse me, I think there’s some computers in Apple that run in the cloud, the Apple cloud, but they were not listed in that list there. So citation needed.

Okay. With the highly successful secure memory allocator work that we’ve talked about before, transform MTE from a debugging tool into a new security feature. And so the thing that they’re calling memory integrity enforcement includes the new memory allocators in the kernel and in user land, enhanced memory tagging extension in synchronous mode and extensive tag confidential enforcement policies. We haven’t talked about that at all and I think that’s down at the bottom. We have to get to that. And it’s built into Apple hardware and software and all models of iPhone 17, iPhone Air, and I think they said in their announcement that it’s going to come to either the next MacBook or the latest MacBook I forget which one soon. Cool. And it seems like the real win here is doing all of these things together.

And the quote novel thing that they did is updating their M chips or their A chips or whatever to be able to do all of this and not like crawl on all the time, synchronously always and not crawl the OS to a halt. They were able to make all these improvements, to do all this stuff all the time. And it’s still a performant iPhone and it’s not killing your battery basically. And that’s the thing that Apple is in a unique position to do to do.

David: Well, I think that like that’s the. Actually the big takeaway is that they’re doing it fast. Like all of this stuff has existed for a while and is like good, it’s effective, but it’s not like 100% effective. And it’s been in stuff for a while like not just Apple. Right. Like Chrome has had partition alloc for a number of years now, which is another user land allocator that basically does ref counting and then zaps the memory once the ref goes to zero in such a way that if it is used after freed, you end up with a crash that only works for key pointers, it doesn’t work for all pointers. And you have to make source level changes that can be automated, but it can be done. You have that stuff in other places.

David: You have had asynchronous MTE on other devices. The real takeaway is that like they bundled all of this together and made it fast such that they like turn it all on by default. Everywhere. Now look is on in like most of Chrome, but it’s not on like everywhere. Everywhere for example.

Deirdre: Okay. Yep. So they’re reviewing the memory allocators. Are you familiar with Lib pass webkits? Leadpass?

David: I believe it’s just their way of basically doing like per object heaps at like the type level.

Deirdre: Okay.

David: Yeah, it’s just like a C E version of doing the type based allocations.

Deirdre: I’ll use type information to decide how to organize memory allocations. So if those are all C, which is not strongly typed, Lib passes C. Okay.

David: All right.

Deirdre: The other two are passing more information about types to the compiler to actually be able to use the type information to do the layout and allocations and all that sort of stuff.

David: Yeah, I mean I think all of these required like some amount of compiler extensions to work in practice.

Deirdre: Use after free. Yeah, the bounds bugs overlap. Yeah, go ahead.

David: I’ll say. Speaking of compiler extensions, I Don’t think they cover this in here at all. But there’s a couple other compiler extensions that Apple has driven and LLVM have been adopted outside of Apple, including Chrome for basically tagging like in C a common pattern as you pass a pointer in a size parameter and basically at the compiler level ensuring that that size parameter is in fact enforced and that there are checks just like you would if you’re using like STD array or STD vector in C that you annotate the function call and then the compiler puts the bounds checks on the pointer axis to make sure that you don’t have spatial memory on safety. And then also like corresponding compiler passes if you don’t want to enforce that just for detecting when it happens. So you can like ban new uses of just like unsafe pointer accesses in C also very effective and can be like slowly rolled out over a code base on like a file by file basis. Like no more raw pointer accesses in this directory aside from the existing ones.

Deirdre: That’s nice. I haven’t heard about bad at all, but I’m not paying very close attention to that side of the world.

David: F bound safety or something like that is the flag for clang.

Deirdre: Cool. And so like this is sort of stuff that’s been kind of going on for years and they’re taking advantage of it for this. And then they’ve already rolled out these improved allocators.

David: Yeah. And to their credit they were driving a lot of it too. Right. Like they have a lot of Clang developers.

Deirdre: Yeah, well, I’m not surprised.

David: And they used to have. What’s this name who like created llvm? Chris Latner.

Deirdre: Cool. Yeah, that’s a. That makes a lot of sense. Okay. Type aware placement policies over secure memory allocators help to work memory corruption. Okay. Yes. Does not hit performance.

Performance is either as the same or better. Allocators can apply protections only at the granularity of memory pages. 16 kilobytes on iOS for smaller allocations. Secure allocators can use page level protections to help prevent memory corruption attacks across different type buckets. However, page level protections are too coarse defending as attacks within the same type bucket. And we use memory tagging to close this gap. So it’s not just like cool, we do stuff at the allocators and then we do memory tagging as well. It’s like no, no, no.

We have to cover the page level and cross page stuff. We via our kernel level and user land level memory allocators. And then we also have to do the Memory tagging stuff because like there’s fine grained stuff that is not covered by the page level memory allocation protection. Cool. All right. And that’s where the EMT is comes in.

David: And to be fair, that’s like most.

Deirdre: Objects, most objects are smaller than the full 16 kilobyte page.

David: We’re not out here allocating pages.

Deirdre: EMT protects against two of the most common types of memory corruption. Buffer overflows in use after free, which we talked about. Buffer overflows Allocator is responsible for using different tags for namering allocations. If a request to access memory spills over to adjacent memory and has a different tag, the hardware blocks it and the operating system can take action and terminate the process.

Thomas: Yeah, this is the easiest one to.

David: Get your head around. Or they diagram it and we covered it earlier. They have a nice diagram with emoji and colors to show how MTE works. It’s not very complicated to understand the core concept. We will save you from explaining the diagrams.

Deirdre: Yes. Wait, that’s. Yeah, that’s the buffer overflow where you’re just going over the type over the area. And this is the one where you’re using after free.

David: They diagram both bound safety and spatial safety and then temporal safety, which would.

Thomas: Be user for free, which, like my intuition for the use after free MTE story is just. It’s like you can free the pointer along with the actual memory.

Deirdre: Nice.

David: More or less.

Thomas: Yeah.

David: I would also just say in modern projects there can be spatial memory safety errors, like when you first learn about memory and safety. I feel like buffer overflow is the main thing everyone learns. But like, in practice, it’s not that hard to mitigate the like 99% plus of your spatial safety things by like using containers in C, using F bound safety, writing sane C code without like limits where you access things like having a span class or a span struct or whatever you call it. Like is fairly common and like enforcing, everybody uses that. Like, you get pretty close to very high coverage of like your spatial memory safety, at least when it comes to containers. Not necessarily like a crap on the stack or whatever.

Thomas: But life cycle is a nightmare.

David: Yeah, life cycle is a nightmare. So in practice, like the most memory safety vulnerabilities that matter, they’re all used after freeze because like we understand how to write a container these days and make it fast.

Deirdre: It’s the ones where it’s like, okay, we’ve handled all of those. It’s like, okay, later in the lifetime of this piece of memory or whatever. It either got used to when it was supposed to be already freed or something to that effect. Because you can’t just like write a container around it.

Thomas: There are intrinsically inter procedural lifecycle vulnerabilities where spatial ones aren’t necessarily. All you have to do is store enough information with the data so that whatever loop you’re doing or whatever write you’re doing into it can just check to see if you’re within bounds or whatever. Yeah, but a lifecycle vulnerability could span 15 different functions called at different times.

David: Yeah, okay, you can enable like hardened Lib C I think with a pound def or maybe a compiler flag or both. That just like puts checks everywhere in like the C standard Lib for example, because like by default only some of the methods actually like do checked accesses. It was less so that like we didn’t know how to do this for years. It was just like, oh, well, the performance impact of putting the checks everywhere is too high, so we can’t do it. We’ll assume the programmer put it in the right spot. But like, what actually happened? Like, it’s like some people got hardened LIBC into LIBC Chrome enabled that like years ago at this point. And then eventually like some other people followed as well. And like, that got the compiler people looking at it.

Then the compiler people were like, oh, actually we can write a ton of optimizations for this because like most of the time that you insert checks, like you can like deterministically prove you don’t need to do the check because you did the check earlier. This happens a lot in like Rust with iterators and stuff. Like the vast majority of the checks end up getting optimized out by the computer compiler because they’re redundant. And so like, once you actually put it the effort into writing those optimizations, then the hardened mode gets faster. But we had like this chicken and egg problem for a while where people are like, we can’t use hardened mode because compiler doesn’t know how to optimize it. And the compiler people were like, we’re not optimizing that because no one’s using it. And it was just like, oh well, actually with like a modicum of effort, like a year of effort from a compiler team at a big tech company, like you can reclaim like the FAST like 1% performance loss or whatever you got for hardened C.

Deirdre: Yeah, okay, we’re trying to zoom through this so we can wrap up before we all have to disappear. Weakness of original MTE access to non tag memory global variables not check by hardware this is nice for attackers. Yep.

Thomas: I don’t get this.

Deirdre: Okay.

Thomas: There’s a thing I don’t get about this.

Deirdre: Okay.

Thomas: Right. Which is like, so the mitigation here is that attackers have to know the tag of the regions they’re coming from. Now, to do this, we’re talking about writing into untagged memory, right? So what is the actual pattern here? This is just a thing where, like, I’m sure this is obvious if you’ve looked at the next point or whatever, but, like, what does it mean to know the region’s tag from like you’re writing from an untagged to a tagged region. What does it mean to know the tag of the tagged region? Do any of us know?

David: I mean, it’s presumably that when you’re accessing the global variable, you’re doing so from some location in code and that location has the tag and you need to, like, know it yourself. I don’t know what it would mean to actually tag the like, instruction segment or like, what that means over. Like, is it. Is it all sent through a function pointer, then that function pointer as a tag? Because the function pointer is in the. Whatever the non data segment is called. I don’t remember.

Thomas: It’s like the centerpiece of how they’re describing ente.

David: Well, I don’t believe in reading assembly. So beyond global variables, they also talk about trying to mitigate SPECTRE or the other common bypass for MTEs to use some sort of speculative execution side channel to read out whatever the tag is. And then on your first attempt still, like, overwrite. You just use the correct value.

Deirdre: This is the tag.

David: They say they mitigate this?

Deirdre: Yeah.

David: Yes, with tag confidentiality enforcement, which they back using their secure page table monitor, which I think is something along the lines of an ARM trust zone or intel sdx.

Deirdre: Is this all we know about?

Thomas: No, we know a lot.

Deirdre: No, we know a lot about the.

David: Secured page table monitor.

Thomas: There’s a paper about it that kind of unwinds the whole thing works out what all the function calls are, all that stuff.

Deirdre: This one?

Thomas: Yeah.

Deirdre: We’ll throw this in the notes.

David: And great job to the authors of this paper whose names will slaughter.

Thomas: Did I find that paper? Was that paper released like seven days ago, maybe?

David: 10Th of October 2025? Current revision?

Thomas: Hell yes.

Deirdre: 12 days ago. Oh, yeah.

David: And that’s V1.

Deirdre: Hell yeah.

David: So I guess they were. We were not the only people intrigued by. Intrigued by this blog post and reference perhaps.

Deirdre: Although this looks like it’s also a master’s thesis. So Maybe they were starting long before.

Thomas: The vibe is that you’re running a big chunk of the virtual memory subsystem of the kernel in like an enclave, I guess. So my understanding was the driving purpose for this originally was kernel exploits that would bounce off of gadgets that would change the page tables and stuff. Like you just. You’ve got control over memory and the kernel. You can bounce around. You can just flip things to be executable or not executable, whatever.

David: Whenever anyone mentions a trust zone, I just immediately think of it to the tune of the song White Room. In the white room. But I want to say cream. But anyway.

Deirdre: In the trust zone.

David: Exactly.

Deirdre: With white curtains. Now it’s the other way around. In the white room with black curtains.

Thomas: I have nothing to do with any of what you guys are talking about.

Deirdre: We need to educate you on your classic proto metal Proto.

David: We need to educate the oldest person in the chat on music that came out before we were.

Deirdre: All right, okay, so those are the three main pieces. Then we’ve got the improved type informed allocate secure allocators. We’ve got the enhanced extended memory tagging extension, whatever. And we’ve got this whatever tag confidentially enforcement, which is basically. They’re storing all this stuff in their trust zone type of dealy that they already had the secure page table monitor and that’s it. That’s memory integrity enforcement or whatever. Cool. Let’s see.

And then they probably. They of course aren’t going to say the specifics of how they made all of this fast enough. But that is like the secret sauce of like how they’re able to ship all of it in the first place. Evaluating pointer authentication instructions speculatively. Yeah, that’s. That’s Spectre v1, right?

David: Yes, that’s Vector v1, which was basically never fully mitigated. We just kind of were like, eh, it’s probably fine. We’ll split stuff at the. Like the kernel will deal with it. If you care about it at a per process level and if you know you care about it within a process, well, just split your stuff into multiple processes. Right. Like that’s what the usual mitigation is, is like figure out what your security boundary is and then, you know, cut it.

Deirdre: Yep.

David: This is why like Chrome has site isolation. Well, there’s a number of reasons why Chrome has site isolation. But the best mitigation for one site can speculatively read private data from another site in the same process is to simply not put two sites in the same process.

Deirdre: Yep. And this is like if you really care about Spectre V1, just run that process on like a core that you trust, that you don’t share with other processes from people you don’t trust and you’re good to go. That’s a bit expensive and getting that isolation is, is kind of difficult if you like to run things on a cloud hypervisor. Oh, sorry. Money please. Let’s see if we can cover the rest of this real quick.

David: Okay, I don’t think there’s much left to cover.

Deirdre: No solution to this problem. Blah, blah, blah.

David: They addressed her with the secure page table thing that we just discussed and then they’re protecting their users with memory integrity enforcement. And that user does not involve me because of my aforementioned inability to input the correct address when ordering a phone.

Deirdre: Protect all users by default. And yeah, Google took a great first step last year when they offered mte. Those are often good for them, but.

David: You technically can opt into MTE without opting into the program for at risk users. But yes, yes, it’s been on the phone for a number of years at this point.

Deirdre: You just have to go in and you have to tap the version number of Android like 15 times and turn on dev options and flick a bit. But you have to opt into it unless you are in the advanced protection program, but even so limited by lack of integration the operating systems. Blah, blah, blah.

David: Well, Deirdre figures out if there’s anything left in this blog post, which I don’t think there is. The other thing that I would add is that this is all ARM stuff, which brings us to the elephant in the room of x64. So like x64, right, is like AMD and Intel and they have some sort of like intra company board that like sets what the instruction set is. Right. Because it was basically an instruction set written by AMD to look like Intel. They are still discussing what the instructions for MTE would even look like on x64. So for all intents and purposes in the like near to medium future you should not expect like mte on any x64 devices. So this is really like an arm64 thing and a subset of arm64 thing.

And so like it’s not clear like these are good hardware features to leverage when you have them. But I don’t think they take away from the need to like write things in memory safe languages as much as possible to like fully mitigate the underlying, the underlying problems where possible. Right. There’s still edge cases with that. Like what happens is your program writes out other code into the process is legit. And that has logic bugs where it writes out the wrong code. Right. Like memory safe languages don’t help Rust, it doesn’t help you there.

But hopefully these are all things that can happen in parallel and should all combine to build a better system. Yes, but in no world can you assume that your software will only run on a device that will have mte, unless maybe you’re Apple in five years or something.

Deirdre: Yeah, and even we’ll see if they even do like emulation stuff still, because they still have the old stuff and they still have a bunch of Apple silicon. So yeah, you won’t even have that even if you’re Apple for a long, long, long, long time.

David: And like we said it is. There is a probabilistic element to all of this. It’s not deterministic. And so it may be the case that we figure out ways to make that 1 in 16 chance your exploit works to be much higher or the.

Deirdre: Lower the chance that it works.

David: The chance that it works to be much higher. Right, like. Oh, right. It could be the case that we figure out like, okay, oh, it turns out there’s this one cool trick to double your likelihood of guessing the tag on the first try.

Deirdre: Okay, so basically the lowest chances for the attacker are right now because this.

David: Is 1 in 16.

Deirdre: Yeah, they could only get better. Yeah. Okay. Use the secure allocators first. Use extended MTE to protect smaller individual allocations within a type bucket. And then knowing where and how we should deploy emte, we could accurately model the tag checking demand of the OS and designer silicon to satisfy it. So yeah, knowing being able to bleed through or look through all these layers of abstraction and control it, control your designs on both sides allows you to optimize our hardware implementation, influence additional software design decisions, reducing overhead of tag structs even further. And like, this is the power that you get by having a full vertically integrated system like this is that you can do all of that optimization work to make all of this work on by default and ship it.

And it isn’t a performance cost, it’s actually like it’s. I don’t know if they have any numbers, but it’s definitely not slower. And I don’t know if it is slightly faster than the previous generation, but it’s definitely not slower, which is not for all the other instances. It is not the case or equivalent deployments of MTE so far that are not Apple that we’re aware.

Thomas: Aware about.

Deirdre: Okay. And then checking how secure it is, any developer can begin Testing the protection including EMT on hardware that supports it using enhanced security settings next code. So if you’re a dev you still have to opt in.

David: But I would also note that it’s kind of when it comes to web browsers, it’s basically Safari only because Safari is the only. The WebKit is the only underlying browsing engine on iOS. But why don’t we. They have a. A diagram or a table further down describing how it breaks various real world exploit changes chains. I have a big diagram here for three iMessages change a Safari chain and some kernel stuff about where it gets either blocked by a secure allocator blocked by EMTE or somehow blocked by both. That’s like I, I think some of the secure. Like it’s not clear to me like this isn’t necessarily a fair way of looking at things.

And yes that like all of these exploits work. Like no one’s doing extra work to get around a mitigation that doesn’t exist at the time they wrote it. Yeah, like you can be like, okay, you know, we reversed this chain from whenever and determined that like nowadays this would be broken in like four or five of eight steps. But like what does that, what does that really mean? And so I think the notable thing for me more in this graph is just like how far to the right is the EMTE circle or icon indicator in each of these chains and the further to the left it is, I suspect that more. More effective EMTE is Right.

Deirdre: And so we’ve got one kernel LPE where it’s very far left and then we’ve got a message imessages chain or messages chain and that’s it. It’s pretty far right for the rest of us.

David: Whereas like the allocators things I almost look at like the opposite direction or like if an allocator change block something very early on it’s just like okay, well they weren’t thinking about it at all.

Deirdre: Yeah.

David: Versus like something like EMTE is more likely to kind of like cut off the base concept but who knows.

Deirdre: Yeah. Cool. I like this. It’s informative. It’s. Yeah cool. Nice stuff.

David: Apple, Apple I think has a team that’s called SEER and a team that’s called Sphere and they’re both on the security team and I find it confusing.

Deirdre: Yeah. And this post was by seer. I don’t know what SPEAR stands for. Platform Software Platform.

David: I don’t know what either of them stand for. All I know is people join them and then you never hear from them again. Disappear.

Deirdre: SEER is Security Engineering and architecture.

David: I assume eventually what happens is everyone that joins either of those teams eventually accidentally walks in a glass exterior wall at the Apple UFO building that they like didn’t see because the wall is glass and clean and it like gives them amnesia and they forget how to interact with the rest of industry.

Deirdre: Apple’s doing its damnedest to be like, no, really, we’re a very, very secure phone. You buy our phones.

David: So we’ll see if anyone introduces some sort of hardware fallout isolation for securing things like jets in the future.

Deirdre: But that’d be nice. Cool.

David: I have a whole blog post about that if you’re interested.

Thomas: Security Cryptography Whatever is a…

Deirdre: oh yeah! Cool.