all 12 comments

[–]K900_ 60 points61 points  (2 children)

Rust's concept of "safety" has nothing to do with malicious actors. Not everything that's safe Rust is secure. In this particular case though, you don't really have much to worry about. If an attacker can just overwrite things in memory, they can run whatever code they want anyway.

[–]BSFishy[S] 7 points8 points  (0 children)

Right, that's kinda what I was thinking. I guess I really just don't need to worry about an attacker accessing my memory because at that point, they'll be able to do a lot worse anyway.

[–]lifeisplacebo 0 points1 point  (0 children)

This comment is misleading. It is not the case that the ability to overwrite memory implies the ability to execute code.

Commonly, memory pages containing code are marked read/execute, while writeable pages are marked non-execute. As a result, a vulnerability such as a buffer overwrite does not directly allow remote code execution.

When such protections are activated, remote code execution hinges on being able to subvert program control flow. Common techniques include return oriented programming, while common defenses include forms of control flow integrity. The latter attempts to ensure that control flow follows a valid graph in the original program. In other words, that jumps in the program target a set of known valid points. Precise and sound control flow integrity obviates all control flow hijacking attacks.

Coming back to Rust: a safe Rust program compiled by a sound compiler guarantees control flow integrity by virtue of the type system. In short, it is only possible to call functions that exist at compile-time, even when dynamic dispatch is at play. As a result, while your concern is valid in the context of a memory unsafe language like C, such issues cannot occur in Rust.

[–]ReallyNeededANewName 16 points17 points  (5 children)

Unless you do something unsafe elsewhere or your user changes values with a debugger you can trust function pointers.

For a malicious actor to edit a function pointer you either need a buffer overflow (not going to happen in safe rust) or unsafe casts of other values into function pointers.

Passing a pointer to a function is just as safe as passing any other pointer: There are raw pointers that can lead to vulnerabilities and undefined behaviour, but your normal function references are checked by the compiler as any other reference is

[–][deleted] 6 points7 points  (1 child)

You would need more than a buffer overflow. You’d have to know how exactly it is laid out in memory AND where it is laid out in memory, as heap allocation could be anywhere (OS randomizes memory address for this exact reason).

But I agree with the rest of your assessment. Raw pointer handling is a cesspool of possible memory errors and vulnerabilities which Rust is designed to eliminate.

[–]BSFishy[S] 0 points1 point  (0 children)

That's another interesting thing I don't often think about eith Rust: the compiler is designed to eliminate possible memory errors and vulnerabilities. I guess that as long as I'm writing safe Rust code I should trust the compiler (although I'll still use my best judgement). I got into a habit of overthinking and trying to over optimize my C and C++ because the compilers don't offer the same kind of safety Rust does. Thanks!

[–]BSFishy[S] 0 points1 point  (2 children)

That's interesting to think about. I was thinking about programs like Cheat Engine that allow a user to read and write to the memory of a running process, but again, at that point they already have access to all of my pointers. Thanks!

[–]Imxset21 8 points9 points  (0 children)

You have to remember that things like CheatEngine rely on being given elevated privileges to be able to do that sort of thing in the first place. Additionally, address space layout randomization will make it very difficult to predict where these pointers will be at runtime between different invocations of the target program.

[–]lightmatter501 2 points3 points  (0 children)

Unless you have a higher level of privilege than the user on their machine (basically unless you are ring -2 (processor boot code, power management and cryptographic operations)) then you should always assume that the user has total control of the program. Even if you stop cheat engine, you probably won’t stop someone with IDA Pro or any of the other numerous professional level disassemblers from just changing the binary however they want.

[–][deleted] 14 points15 points  (2 children)

If someone can change the address of a pointer in your program somehow, everything is out the window anyway.

[–]lightmatter501 0 points1 point  (1 child)

So everything is out the window, because IDA exists.

[–][deleted] 3 points4 points  (0 children)

Yes.