5 ms·
MacOS on the M1 processor is the first to use, and require, the W^X bit in memory, meaning that pages of memory are either writable, or can be executed from, bu
by spijdar 5y ago
MacOS on the M1 processor is the first to use, and require, the W^X bit in memory, meaning that pages of memory are either writable, or can be executed from, but not both. MIT Scheme's front page says this is fundamentally incompatible with their design, and therefore it won't build. When running in the emulator, this requirement would be relaxed for compatibility reasons.
There is an escape hatch for writing JIT compilers (essentially what MIT Scheme is in this case), described here https://developer.apple.com/documentation/apple-silicon/porting-just-in-time-compilers-to-apple-silicon https://developer.apple.com/documentation/apple-silicon/port... although it's fairly cumbersome and would almost certainly require a lot of extra, MacOS specific code. I assume that's why no-one has bothered so far to port it.
- usmannk 5y agoWow really? A common intro to security exercise (think CTFs and university courses) is to write increasingly complicated C programs that leverage W&X. Classic buffer overflow into the stack kind of stuff. On M1 it’s now impossible to exploit even a self-compiled toy in this way?
- shepherdjerred 5y agoIt is possible using Rosetta 2
- spijdar 5y agoBasically, yeah. In addition, the usual way to bypass W^X memory, using ROP chains, is also mitigated by the pointer authentication the M1 implements. It's not bullet proof, but it prevents most of the old exploit methods from working at all. You'd need to throw up a VM on an M1 Mac to learn much this way (although that'd be ideal anyway, to get an environment without other protections like ASLR) I know at least OpenBSD also enforces W^X protection universally, anyone else? I know Linux can with the right SELinux policies, but not sure any distro ships with those by default.
- esprehn 5y agoWindows has had this enabled by default for a long time: https://docs.microsoft.com/en-us/windows/win32/memory/data-execution-prevention https://docs.microsoft.com/en-us/windows/win32/memory/data-e... There's a per program exception list to handle legacy programs though.
- nneonneo 5y agoWindows DEP only applies W^X (more accurately, !X) to the default stack and heap; programs can still freely allocate new memory as PAGE_EXECUTE_READWRITE if they want RWX memory. macOS W^X on Apple Silicon, however bans RWX memory outright, making it impossible to have a page in memory that is simultaneously writable and executable. Instead, if you want to be able to write instructions to a page and later execute them (e.g. for JIT compilation), you have to (1) have a special entitlement (or opt out of the Hardened Runtime), (2) map your memory with a special MAP_JIT flag, and (3) call special mprotect-like functions to toggle the protection between RW and RX every time you want to modify the code. There does, however, seem to be a bit of a loophole: the JIT protection flags are applied per thread meaning that in principle one thread could have the page RW while another has it RX.
- olliej 5y agoOn M1 CPUs you cannot ever have simultaneously writable and executable memory. Windows just makes default allocations write only, you have to explicitly request RWX, which is what every other OS has been doing basically since x86 actually added support for non executable memory :)
- deleted 5y ago[deleted]
- astrange 5y agoPointer authentication isn’t in 3rd party processes though, only system ones. (or maybe it’s available but optional, I forget)
- bigdict 5y agoOfftopic, but can you recommend such a course?
- usmannk 5y agoHey sorry, didn't check back on this comment for a while. I can't recommend any _courses_ in particular (unless you're a Georgia Tech student, in which case "CS 6265: Information Security Lab" is absolutely incredible). One really fun way to hone your skills is https://microcorruption.com/ https://microcorruption.com/, a ctf-style simulated hacking game originally made by Square and Matasano.
- fulafel 5y agoYou can do it in a Linux VM container, it's just MacOS processes, not the HW.
- usmannk 5y agoOhh that makes more sense, thanks.
- jeroenhd 5y agoAh, thank you. That explains the problem quite well. I suppose the wait is on for someone to rewrite the JIT engine to be compatible with Apple's implementation of ARM.
- nneonneo 5y agoFrom perusing the source of the MIT/GNU Scheme compiler, I suspect that “only” two changes are needed to support W^X: - Compiled code needs to be allocated separately from Scheme objects. It can still be garbage collected and such - they will probably need to make a separate set of allocation functions for code vs. data. The closure/function objects can be made to point to the code, or, if they don’t need to be written often, simply allocated wholly from the “code” pages. - Before modifying any of the code (e.g. to patch addresses after GC relocation), a system-specific hook function will need to be called to set the permissions to RW. They already call an I-cache flush function after each modification, so this shouldn’t be too bad. Some of the necessary changes are already sketched out in cmpint.txt. And, sooner or later, they’re going to have to make these changes: OpenBSD already enforces W^X (but provides a workaround), and MIT/GNU Scheme already applies a paxctl workaround to gain W|X on NetBSD.
- olliej 5y agoI mean if they pass the correct flags they get memory that can be toggled rapidly between X and W mode - or is MIT Scheme mixing data and code in the heap and so actually requiring RWX?