Live data from Hacker News

A bug that doesn’t exist on x86: Exploiting an ARM-only race condition

github.com

31–40 of 141 posts

Re: A bug that doesn’t exist on x86: Exploiting an ARM-only race condition

#31
post #13

Have i told you about our lord and savior Rust? Anyways, https://github.com/tokio-rs/loom is used by any serious library doing atomic ops/synchronization and it blew me away with how fast it can catch most bugs like this.

Rust doesn't catch memory ordering errors, which can result in behavioral bugs in safe Rust and data races and memory unsafety in unsafe Rust. But Loom is an excellent tool for catching ordering errors, though its UnsafeCell API differs from std's (and worse yet, some people report Loom returns false positives/negatives in some cases: https://github.com/tokio-rs/loom/issues/180 , possibly https://github.com/tokio-rs/…

It doesn't catch all of them. But data-races on plain memory access are impossible in safe rust.

And atomics force you to specify an ordering on every access, which helps both the writer (forced to think about which ordering they need) and reviewer (by communicating intent).

Re: A bug that doesn’t exist on x86: Exploiting an ARM-only race condition

#33
The best part is that the original code is not safe even on x86 as the compiler can still reorder non-volatile accesses to the backing_buf around the volatile accesses to head and tails. Compiler barriers before the volatile stores and after volatile reads are required [1]. It would still be very questionable code, but it would at least have a chance to work on its intended target.

tl;dr: just use std::atomic.

[1] it is of course possible they are actually present in the original code and just omitted from the explanation for brevity

Re: A bug that doesn’t exist on x86: Exploiting an ARM-only race condition

#34
post #9

Earlier quoted context omitted.

Normally the code should have all the needed memory fences as if running on DEC Alpha, e.g. linux does that, and the compilers omit the unneeded ones.

And since the compiler omitted it on x86, an x86 emulator doesn't have access to where they're required as seen by the compiler.

emulator would have a zero issue, if it's a direct transfer for assembly (not an emulator), it'd need either hardware support - e.g. apple chips, or memory barriers.

The differences between arm and x86 are known for 15y+, there is nothing new about it. Also concurrency support is one of the major benefits of languages with proper memory model - java started it with JMM[0]

[0]: https://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedL...

Re: A bug that doesn’t exist on x86: Exploiting an ARM-only race condition

#35
post #34

Earlier quoted context omitted.

And since the compiler omitted it on x86, an x86 emulator doesn't have access to where they're required as seen by the compiler.

emulator would have a zero issue, if it's a direct transfer for assembly (not an emulator), it'd need either hardware support - e.g. apple chips, or memory barriers. The differences between arm and x86 are known for 15y+, there is nothing new about it. Also concurrency support is one of the major benefits of languages with proper memory model - java started it with JMM[0] [0]: https://www.cs.umd.edu/~pugh/java/memory…

Any emulator that wants to be remotely performance competitive will do dynamic translation (i.e JIT). In fact ahead-of-time translation is not really feasible.

Memory models and JVM are not really relevant when discussing running binaries for a different architecture.

Re: A bug that doesn’t exist on x86: Exploiting an ARM-only race condition

#37
For those interested in memory ordering, I have a few posts on my blog where I build a simulator capable of understanding reorderings and analyze examples with it:

https://www.reitzen.com/post/temporal-fuzzing-01/ https://www.reitzen.com/post/temporal-fuzzing-02/

Next step are some lock free queues, although I haven't gotten around to publishing them!

Re: A bug that doesn’t exist on x86: Exploiting an ARM-only race condition

#39

Great write-up! There may be a typo in section 3: > It will happily retire instruction 6 before instruction 5. If memory serves, although instructions can execute out-of-order, they retire in-order (hence the "re-order buffer").

You are correct. The retire unit ensures that all micro ops are retired in order

Re: A bug that doesn’t exist on x86: Exploiting an ARM-only race condition

#40
I spent some time trying to figure out why the lock-free read/write implementation is correct under x86, assuming a multiprocessor environment.

My read of the situation was that there's already potential for a double-read / double-write between when the spinlock returns and when the head/tail index is updated.

Turns out that I was missing something: there's only one producer thread, and only one consumer thread. If there were multiple of either, then this code would be more fundamentally broken.

That said: IMO the use of `new` in modern C++ (as is the case in the writer queue) is often a code smell, especially when std::make_unique would work just as well. Using a unique_ptr would obviate the first concern [0] about the copy constructor not being deleted.

(If we used unique_ptr consistently here, we might fix the scary platform-dependent leak in exchange for a likely segfault following a nullptr dereference.)

One other comment: the explanation in [1] is slightly incorrect:

> we receive back Result* pointers from the results queue rq, then wrap them in a std::unique_ptr and jam them into a vector.

We actually receive unique_ptrs from the results queue, then because, um, reasons (probably that we forgot that we made this a unique_ptr), we're wrapping them in another unique_ptr, which works because we're passing a temporary (well, prvalue in C++17) to unique_ptr's constructor -- while that looks like it might invoke the deleted copy-constructor, it's actually an instance of guaranteed copy elision. Also a bit weird to see, but not an issue of correctness.

[0] https://github.com/stong/how-to-exploit-a-double-free#0-inte...

[1] https://github.com/stong/how-to-exploit-a-double-free#2-rece...

Post reply on HN