Skip to content

Commit 56ef554

Browse files
committed
try to fix the write memory crash on macos
1 parent 2367b4d commit 56ef554

File tree

2 files changed

+41
-17
lines changed

2 files changed

+41
-17
lines changed

src/target/DarwinTarget.cpp

+37-17
Original file line numberDiff line numberDiff line change
@@ -54,28 +54,40 @@ geode::Result<uint32_t> DarwinTarget::getProtection(void* address) {
5454
return geode::Ok(info.protection);
5555
}
5656

57+
void DarwinTarget::internalProtectMemory(void* address, size_t size, uint32_t protection, int& errorCode) {
58+
errorCode = vm_protect(
59+
mach_task_self(),
60+
reinterpret_cast<vm_address_t>(address),
61+
size,
62+
false,
63+
protection
64+
);
65+
}
66+
void DarwinTarget::internalWriteMemory(void* destination, void const* source, size_t size, int& errorCode) {
67+
errorCode = vm_write(
68+
mach_task_self(),
69+
reinterpret_cast<vm_address_t>(destination),
70+
reinterpret_cast<vm_offset_t>(source),
71+
static_cast<mach_msg_type_number_t>(size)
72+
);
73+
}
74+
5775
geode::Result<> DarwinTarget::protectMemory(void* address, size_t size, uint32_t protection) {
5876
kern_return_t status;
5977

60-
status = vm_protect(mach_task_self(), reinterpret_cast<vm_address_t>(address), size, false, protection);
61-
78+
this->internalProtectMemory(address, size, protection, status);
6279
if (status != KERN_SUCCESS) {
63-
return geode::Err("Couldn't protect memory");
80+
return geode::Err("Couldn't protect memory: " + std::to_string(status));
6481
}
6582
return geode::Ok();
6683
}
6784

6885
geode::Result<> DarwinTarget::rawWriteMemory(void* destination, void const* source, size_t size) {
6986
kern_return_t status;
7087

71-
status = vm_write(
72-
mach_task_self(),
73-
reinterpret_cast<vm_address_t>(destination),
74-
reinterpret_cast<vm_offset_t>(source),
75-
static_cast<mach_msg_type_number_t>(size)
76-
);
88+
this->internalWriteMemory(destination, source, size, status);
7789
if (status != KERN_SUCCESS) {
78-
return geode::Err("Couldn't write memory, status: " + std::to_string(status));
90+
return geode::Err("Couldn't write memory: " + std::to_string(status));
7991
}
8092
return geode::Ok();
8193
}
@@ -85,16 +97,24 @@ geode::Result<> DarwinTarget::writeMemory(void* destination, void const* source,
8597

8698
// with no wx pages, we run into the risk of accidentally marking our code as rw
8799
// (this causes a crash in the result destructor, which is not very good)
100+
// should be fixed now i think
88101

89-
auto r1 = this->protectMemory(destination, size, this->getWritableProtection());
90-
auto r2 = r1.and_(this->rawWriteMemory(destination, source, size));
91-
auto r3 = r2.and_(this->protectMemory(destination, size, oldProtection));
102+
kern_return_t s1, s2, s3;
103+
this->internalProtectMemory(destination, size, this->getWritableProtection(), s1);
104+
if (s1 != KERN_SUCCESS) {
105+
return geode::Err("Couldn't protect memory to rwc: " + std::to_string(s1));
106+
}
92107

93-
// permissions restored, it's safe to do result stuff now
94-
if (r3.isErr()) {
95-
// return the first error
96-
return geode::Err(r3.unwrapErr());
108+
this->internalWriteMemory(destination, source, size, s2);
109+
if (s2 != KERN_SUCCESS) {
110+
return geode::Err("Couldn't write memory: " + std::to_string(s2));
97111
}
112+
113+
this->internalProtectMemory(destination, size, oldProtection, s3);
114+
if (s3 != KERN_SUCCESS) {
115+
return geode::Err("Couldn't protect memory back: " + std::to_string(s3));
116+
}
117+
98118
return geode::Ok();
99119
}
100120

src/target/DarwinTarget.hpp

+4
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ namespace tulip::hook {
1818
uint32_t getWritableProtection() override;
1919

2020
geode::Result<> writeMemory(void* destination, void const* source, size_t size) override;
21+
22+
private:
23+
void internalProtectMemory(void* address, size_t size, uint32_t protection, int& errorCode);
24+
void internalWriteMemory(void* destination, void const* source, size_t size, int& errorCode);
2125
};
2226
}
2327

0 commit comments

Comments
 (0)