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

Write memory #41

Merged
merged 13 commits into from Aug 23, 2020
Merged

Write memory #41

merged 13 commits into from Aug 23, 2020

Conversation

nbaksalyar
Copy link
Member

@nbaksalyar nbaksalyar commented Jul 24, 2020

Implements #7

  • Write memory using process_vm_write on Linux.
  • Write memory using ptrace on Linux.
  • Automatically choose mem write strategy on Linux.
  • Write memory using mach_vm_write on macOS.
  • Add tests for writing to write-protected pages.

@nbaksalyar nbaksalyar changed the title Write memory Write memory [WIP] Jul 24, 2020
src/target/linux/mod.rs Outdated Show resolved Hide resolved
}

/// Executes the memory write operation.
pub unsafe fn apply(self) -> Result<(), Box<dyn std::error::Error>> {
Copy link
Contributor

Choose a reason for hiding this comment

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

This is safe as it can only crash the remote process, right?

@JJendryka
Copy link
Contributor

I can help with adding test for writing to write-protected pages if you want?

@nbaksalyar
Copy link
Member Author

I can help with adding test for writing to write-protected pages if you want?

No worries, I should finish this today. :) Thanks!

nbaksalyar and others added 9 commits August 19, 2020 00:17
- Use immutable ref for lifetime invariance in WriteMemory
- Allow to pass slices to write

Co-authored-by: bjorn3 <bjorn3@users.noreply.github.com>
- Use ptr::read_volatile for volatile read operations
- Simpler capacity calc expression

Co-authored-by: bjorn3 <bjorn3@users.noreply.github.com>
Co-authored-by: bjorn3 <bjorn3@users.noreply.github.com>
Memory write operations are split into those which are applicable
to memory pages which are writable, and those which need to resort to ptrace for
writing to write-protected memory pages.
Use a single type for both writing and reading memory instead of a trait.
This approach simplifies generic memory operations (like splitting memory ops
based on page permissions or splitting memory ops on page boundary), while
still leaving place for introducing write- or read- specific functions in the
future.

This commit also changes the approach used for splitting write operations into
word-sized groups. Instead of allocating a new vector, we now use a custom iterator.
This should reduce a number of unnecessary allocations.

Finally, this commit also introduces a delay before reading written values in
ptrace writing tests.
- Add `LinuxTarget::write()`
- Also make `WriteMem::apply` safe as it operates only on the debuggee process.
@nbaksalyar nbaksalyar changed the title Write memory [WIP] Write memory Aug 22, 2020
src/target/linux/memory.rs Outdated Show resolved Hide resolved
src/target/linux/memory.rs Outdated Show resolved Hide resolved
src/target/linux/writemem.rs Outdated Show resolved Hide resolved
src/target/linux/writemem.rs Outdated Show resolved Hide resolved
src/target/linux/writemem.rs Outdated Show resolved Hide resolved
src/target/macos/writemem.rs Outdated Show resolved Hide resolved
src/target/macos/writemem.rs Outdated Show resolved Hide resolved
- Reduce `linux::MemoryOp` visibility to `pub(crate)`
- Improve doc comments.
- Make macOS `WriteMem` conforming to Linux API.

Co-authored-by: bjorn3 <bjorn3@users.noreply.github.com>
@nbaksalyar
Copy link
Member Author

nbaksalyar commented Aug 22, 2020

Hmm, writemem tests fail sporadically. This seems to be caused by fork deadlock (pthread_cond_wait originating in LinuxTarget::memory_maps -> procfs -> lazy_static). I'm fixing this.

Edit:
This is caused by std::sync::Once being fork-unsafe, ref: rust-lang/rust#43448

lazy_static can fail if it's used in a forked process, so this commit uses
an explicit apply_ptrace() instead of reading debuggee memory maps and determining
what memory write operation to use.
This is a temporary workaround until we find a better approach.
@nbaksalyar
Copy link
Member Author

This is caused by std::sync::Once being fork-unsafe

It looks like there's no quick fix for this. I've used a workaround - the test that was failing now uses an explicit apply_ptrace() instead of reading memory maps to determine which memory write operation to use. This is a bit fragile though, and we should keep an eye on this. Probably, a better long-term solution would be not to rely on fork for tests.

@bjorn3 bjorn3 merged commit 8222149 into headcrab-rs:master Aug 23, 2020
@nbaksalyar nbaksalyar deleted the writemem branch August 23, 2020 11:15
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.

None yet

3 participants