Logic bug in debugserver's MachVMMemory::WriteRegion
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
https://github.com/llvm/llvm-project/blob/b025f5b75941fcf2e719535473c51b5e0617c4f9/lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp#L360
In `lldb/tools/debugserver/source/MacOSX/MachVMMemory.cpp`, `m_err` is first set to the result of `mach_vm_write`:
```c++
m_err =
::mach_vm_write(task, curr_addr, (pointer_t)curr_data, curr_data_count);
```
If it failed, there is a log message but the function/loop does not exit:
```c++
if (DNBLogCheckLogBit(LOG_MEMORY) || m_err.Fail())
m_err.LogThreaded("::mach_vm_write ( task = 0x%4.4x, addr = 0x%8.8llx, "
"data = %8.8p, dataCnt = %u )",
task, (uint64_t)curr_addr, curr_data, curr_data_count);
```
Then there is a cache flush that overwrites `m_err`:
```c++
#if !defined(__i386__) && !defined(__x86_64__)
vm_machine_attribute_val_t mattr_value = MATTR_VAL_CACHE_FLUSH;
m_err = ::vm_machine_attribute(task, curr_addr, curr_data_count,
MATTR_CACHE, &mattr_value);
if (DNBLogCheckLogBit(LOG_MEMORY) || m_err.Fail())
m_err.LogThreaded("::vm_machine_attribute ( task = 0x%4.4x, addr = "
"0x%8.8llx, size = %u, attr = MATTR_CACHE, mattr_value "
"=> MATTR_VAL_CACHE_FLUSH )",
task, (uint64_t)curr_addr, curr_data_count);
#endif
```
And finally `m_err` is checked:
```c++
if (m_err.Success()) {
total_bytes_written += curr_data_count;
curr_addr += curr_data_count;
curr_data += curr_data_count;
} else {
break;
}
```
If we are on Arm64 and the write failed but the cache flush did not, this function will act as if the write succeeded.
Found this investigating https://github.com/llvm/llvm-project/pull/216723, but I do not think it's the cause of that problem.
Contributor guide
Assessment
This issue has not been assessed yet.