Is it possible to obtain a value from another process? - pointers

I have this script written in rust that grabs the raw pointer of an initialized u8 value, prints the address of that pointer, then basically goes on pause waiting for a user input.
fn main() {
// Initialize `x` as raw pointer of `u8` value `43`
let x = &mut (43 as u8) as *mut u8;
println!("{:?}", x);
// Wait for user input so that `x` stays in place
drop(std::io::stdin().read_line(&mut String::new()));
}
The script above runs, prints the address of where x is being stored, then goes to "sleep", leaving x at that specific memory location. I was wondering if it were possible to run another process and use that specific memory address to grab the value of x. I used the following script that I wrote:
unsafe fn read<T>(addr: i64) -> &'static T {
&*(addr as *mut T)
}
fn main() {
unsafe {
println!("{}", read::<u8>(0xe1110ff9ef))
}
}
But it would always result with this error:
error: process didn't exit successfully: target\debug\t3.exe (exit code: 0xc0000005, STATUS_ACCESS_VIOLATION)
Is this possible?

Related

How to pass a Reference / Pointer to a Rust Struct to a C ffi interface?

What I am trying to do
I have built a Rust interface, with which I want to interact via C (or C# but it does not really matter for the sake of the question). Because it does not seem to be possible to make a Rust Struct accessible to C I am trying to build some wrapper functions that I can call and that will create the Struct in Rust, call functions of the struct and eventually free the Struct from memory manually.
In order to do this I thought I would pass the pointer to the Struct instance that I create in the init function back to C (or C# and temporary store it as an IntPtr). Then when I call the other functions I would pass the pointer to Rust again, dereference it and call the appropriate functions on the dereferenced Struct, mutating it in the process.
I know that I will have to use unsafe code to do this and I am fine with that. I should probably also point out, that I don't know a lot about life-time management in Rust and it might very well be, that what I am trying to is impossible, because it is quite easy to produce a loose pointer somewhere. In that case, I would wonder how I would need to adjust my approach, because I think I am not the first person who is trying to mutate some sort of state from C inside Rust.
What I tried first
So first of all I made sure to output the correct library and add my native functions to it. In the Cargo.toml I set the lib type to:
[lib]
crate-type = ["cdylib"]
Then I created some functions to interact with the struct and exposed them like this:
#[no_mangle]
pub extern fn init() -> *mut MyStruct {
let mut struct_instance = MyStruct::default();
struct_instance.init();
let raw_pointer_mut = &mut struct_instance as *mut MyStruct;
return raw_pointer_mut;
}
#[no_mangle]
pub extern fn add_item(struct_instance_ref: *mut MyStruct) {
unsafe {
let struct_instance = &mut *struct_instance_ref;
struct_instance.add_item();
}
}
As you can see in the init function I am creating the struct and then I return the (mutable) pointer.
I then take the pointer in the add_item function and use it.
Now I tried to test this implementation, because I had some doubts about the pointer still beeing valid. In another Rust module I loaded the .dll and .lib files (I am on Windows, but that should not matter for the question) and then called the functions accordingly like so:
fn main() {
unsafe {
let struct_pointer = init();
add_item(struct_pointer);
println!("The pointer adress: {:?}", struct_pointer);
}
}
#[link(name = "my_library.dll")]
extern {
fn init() -> *mut u32;
fn add_item(struct_ref: *mut u32);
}
What happened: I did get some memory adress output and (because I am actually creating a file in the real implementation) I could also see that the functions were executed as planned. However the Struct's fields seem to be not mutated. They were basically all empty, what they should not have been after I called the add_item function (and also not after I called the init function).
What I tried after that
I read a bit on life-time management in Rust and therefore tried to allocate the Struct on the heap by using a Box like so:
#[no_mangle]
pub extern fn init() -> *mut Box<MyStruct> {
let mut struct_instance = MyStruct::default();
struct_instance.init();
let raw_pointer_mut = &mut Box::new(struct_instance) as *mut Box<MyStruct>;
return raw_pointer_mut;
}
#[no_mangle]
pub extern fn add_box(struct_instance_ref: *mut Box<MyStruct>) {
unsafe {
let struct_instance = &mut *struct_instance_ref;
struct_instance.add_box();
}
}
unfortunately the result was the same as above.
Additional Information
I figured it might be good to also include how the Struct is made up in principle:
#[derive(Default)]
#[repr(C)]
pub struct MyStruct{
// Some fields...
}
impl MyStruct{
/// Initializes a new struct.
pub fn init(&mut self) {
self.some_field = whatever;
}
/// Adds an item to the struct.
pub fn add_item(
&mut self,
maybe_more_data: of_type // Obviously the call in the external function would need to be adjusted to accomodate for that...
){
some_other_function(self); // Calls another function in Rust, that will take the struct instance as an argument and mutate it.
}
}
Rust has a strong notion of ownership. Ask yourself: who owns the MyStruct instance? It's the struct_instance variable, whose lifetime is the scope of the init() function. So after init() returns, the instance is dropped and an invalid pointer is returned.
Allocating the MyStruct on the heap would be the solution, but not in the way you tried: the instance is moved to the heap, but then the Box wrapper tied to the same problematic lifetime, so it destroys the heap-allocated object.
A solution is to use Box::into_raw to take the heap-allocated value back out of the box before the box is dropped:
#[no_mangle]
pub extern fn init() -> *mut MyStruct {
let mut struct_instance = MyStruct::default();
struct_instance.init();
let box = Box::new(struct_instance);
Box::into_raw(box)
}
To destroy the value later, use Box::from_raw to create a new Box that owns it, then let that box deallocate its contained value when it goes out of scope:
#[no_mangle]
pub extern fn destroy(struct_instance: *mut MyStruct) {
unsafe { Box::from_raw(struct_instance); }
}
This seems like a common problem, so there might be a more idiomatic solution. Hopefully someone more experienced will chime in.
I'm adding a simple answer for anyone who comes across this question but doesn't need to box - &mut struct_instance as *mut _ is the correct syntax to get a mutable pointer to a struct on the stack. This syntax is a bit tricky to find documented anywhere, it's easy to miss the initial mut.
Notably, this does not solve the original poster's issue, as returning a pointer to a local is undefined behavior. However, this is the correct solution for calling something via FFI (for which there don't seem to be any better results on Google).

Does casting pointers in Rust have the same behavior as reinterpret_cast in C++?

I have this struct defined in my code:
#[repr(align(4))]
struct MetaDataDefn {
cncVersion: i32,
toDriverBufferLength: i32,
toClientsBufferLength: i32,
counterMetadataBufferLength: i32,
counterValuesBuferLength: i32,
clientLivenessTimeout: i64,
startTimestamp: i64,
pid: i64
}
I have a function that takes a raw pointer to a chunk of memory, where the first bytes correspond to a struct with the same layout.
I thought that if I cast the u8 pointer to a struct pointer, I'd get the same result as if I did a reinterpret_cast in C++. However, I think that's not the case, and I'm a bit confused about what's going on here. This is the body of the function (the pointer that the function receives is cncFilePtr):
let metadata = unsafe { cncFilePtr as *mut MetaDataDefn };
// This works
let cncVersion = unsafe { (*(cncFilePtr as *mut i32)) };
println!("CNC Version: {}", cncVersion);
//This prints a different number than the previous code
println!("CNC version (other way): {}", unsafe { (*metadata).cncVersion });
As you can see, casting the first 4 bytes to a i32 and then printing the result gives a different result than casting the whole thing to MetaDataDefn and accessing the first member, which is of type i32 (my understanding is that both approaches should give the same result)
My question is: why it's not the same result? is casting pointers in Rust not the same as reinterpret_cast in C++ (I come from a C++ background)?
Normally, Rust makes no guarantees about the way that a struct is represented in memory. It can reorder fields to make them pack more tightly, and could theoretically even optimise the field order based on how your application actually accesses them.
You can fix the order, to behave like C, by adding the #[repr(C)] attribute:
#[repr(C)]
#[repr(align(4))]
struct MetaDataDefn { ... }
With that, both pointers will give the same result because this guarantees that cncVersion appears first.

Dereferencing raw pointer with explicit annotation in Rust

I was writing unsafe snippet of code to emulate how C would have allocated a memory for an int. The code allocates memory for an isize type, assign 0 to the pointer variable, then infinitely increment the value at the address every second
use std::process;
use std::{thread, time};
use std::alloc::{alloc, Layout};
fn main() {
unsafe {
let layout = Layout::new::<isize>();
let p = alloc(layout);
println!("({}) address pointed to by p: {:p}", process::id(), p);
*(p as *mut isize) = 0;
loop {
thread::sleep(time::Duration::from_millis(1000));
*(p as *mut isize) += 1;
println!("({}) p: {}", process::id(), *(p as *mut isize));
}
}
}
However, for each *(p as *mut size) I could have replaced with just *p without the compiler complaining (i.e. *p = 0;), thus I assumed it was correctly inferred. I need help explaining the difference and in which case the explicit type annotation may be required.
It's not correctly inferred. alloc returns a pointer to u8, which can be set to 0 or incremented, so the compiler doesn't complain. However it will wrap at 255 instead of wrapping at 4G (or whatever if you're on a 64-bit system).

Lifetime of function behaves differently in function pointer assignment and initialization

See the below example
fn fx(x: i32) -> i32
{
x
}
fn test_Functor()
{
// case 1. Initialization
let myFunctor: &Fn(i32) -> i32 = &fx ;
// case 2. Assignment
//let myFunctor: &Fn(i32) -> i32;
//myFunctor= &fx ;
}
This can compile.
If I comment case 1 and uncomment case 2. I got an error
Compiling study_rust v0.0.1 (main.rs)
src/main.rs:45:17: 45:19 error: borrowed value does not live long enough
src/main.rs:45 myFunctor= &fx ;
^~
src/main.rs:44:36: 47:2 note: reference must be valid for the block suffix following statement 0 at 44:35...
src/main.rs:44 let myFunctor: &Fn(i32) -> i32;
src/main.rs:45 myFunctor= &fx ;
src/main.rs:46
src/main.rs:47 }
src/main.rs:45:5: 45:21 note: ...but borrowed value is only valid for the statement at 45:4
src/main.rs:45 myFunctor= &fx ;
^~~~~~~~~~~~~~~~
src/main.rs:45:5: 45:21 help: consider using a `let` binding to increase its lifetime
src/main.rs:45 myFunctor= &fx ;
^~~~~~~~~~~~~~~~
error: aborting due to previous error
Could not compile `study_rust`.
Why? Is it a bug?
I am using rustc 1.5.0
rustc 1.5.0 (3d7cd77e4 2015-12-04)
I think it is not a bug. Note that it is also producing the same error without function pointers.
// this compiles
let a: &i32 = &3;
vs
let a: &i32;
a = &3;
//^ error: borrowed value does not live long enough
The two pieces of code above are not equivalent. A lifetime starts at the point where you bind a variable (let a: &32), not where you assign it (a = &3). If you split the two, like in the second case, you're saying that the lifetime for the &i32 is expected to start at the let a: &i32 line, which the compiler can't guarantee in the general case.
For instance, imagine if you did:
// does not compile
let a: &i32;
{
let b = 3;
a = &b;
} // b is out of scope, so a can't still contain a live reference here
you CAN make this work, but you explicitly need to tell the compiler that b is static (the static lifetime outlives everything), like this:
let a: &i32;
static b: i32 = 3;
a = &b;
or (in your original case):
let myFunctor: &Fn(i32) -> i32;
static F: fn(i32) -> i32 = fx;
myFunctor= &F;
Can it be linked to const vs static?
static i:usize = 0usize;
fn test_Functor()
{
// case 2. Assignment
let myFunctor: &usize;
myFunctor= &i ;
}
It compiles when i is static but not when i is const.
From the book, it is said that static aren't inlined ...

How to allocate space for a Vec<T> in Rust?

I want to create a Vec<T> and make some room for it, but I don't know how to do it, and, to my surprise, there is almost nothing in the official documentation about this basic type.
let mut v: Vec<i32> = Vec<i32>(SIZE); // How do I do this ?
for i in 0..SIZE {
v[i] = i;
}
I know I can create an empty Vec<T> and fill it with pushes, but I don't want to do that since I don't always know, when writing a value at index i, if a value was already inserted there yet. I don't want to write, for obvious performance reasons, something like :
if i >= len(v) {
v.push(x);
} else {
v[i] = x;
}
And, of course, I can't use the vec! syntax either.
While vec![elem; count] from the accepted answer is sufficient to create a vector with all elements equal to the same value, there are other convenience functions.
Vec::with_capacity() creates a vector with the given capacity but with zero length. It means that until this capacity is reached, push() calls won't reallocate the vector, making push() essentially free:
fn main() {
let mut v = Vec::with_capacity(10);
for i in 0..10 {
v.push(i);
}
println!("{:?}", v);
}
You can also easily collect() a vector from an iterator. Example:
fn main() {
let v: Vec<_> = (1..10).collect();
println!("{:?}", v);
}
And finally, sometimes your vector contains values of primitive type and is supposed to be used as a buffer (e.g. in network communication). In this case you can use Vec::with_capacity() + set_len() unsafe method:
fn main() {
let mut v = Vec::with_capacity(10);
unsafe { v.set_len(10); }
for i in 0..10 {
v[i] = i;
}
println!("{:?}", v);
}
Note that you have to be extra careful if your vector contains values with destructors or references - it's easy to get a destructor run over a uninitialized piece of memory or to get an invalid reference this way. It will also work right if you only use initialized part of the vector (you have to track it yourself now). To read about all the possible dangers of uninitialized memory, you can read the documentation of mem::uninitialized().
You can use the first syntax of the vec! macro, specifically vec![elem; count]. For example:
vec![1; 10]
will create a Vec<_> containing 10 1s (the type _ will be determined later or default to i32). The elem given to the macro must implement Clone. The count can be a variable, too.
There is the Vec::resize method:
fn resize(&mut self, new_len: usize, value: T)
This code resizes an empty vector to 1024 elements by filling with the value 7:
let mut vec: Vec<i32> = Vec::new();
vec.resize(1024, 7);

Resources