HN user

arielby

81 karma
Posts0
Comments86
View on HN
No posts found.

No. This is a subtle vulnerability that involves the flags in the x86 page table not matching the hypervisor's view of them - not a mere buffer overflow. Ordinary static analysis couldn't have fixed this. Safe languages couldn't have fixed this. Even a complete formal proof would have missed this without a good model.

This bug might also be considered an argument for the view of ditching of para-virtualized (PV) VMs, and switch to HVMs

It's not like Xen HVMs have a better security story than PVMs. The paravirtualization code should probably be more heavily audited than it is already.

BoringSSL 11 years ago

Not more difficult than C - you write the crypto functions in asm. You could use a C compiler to handle the ABI but the code isn't really C code.

The arithmetic operators in x86/x86-64 are certainly polymorphic (over word-length, plus integer vs. x87 vs. SSE).

I think the distinction is that #3b-types, which denote the "encoding" of a value, mapping it to its meaning, are often used as a basis for a #2-types system (to parametrize operations).

I would split use #3 into two parts: 3a) disambiguation for builtin operators - e.g. a float local needs to go in a float register, adding 16-bit integers uses 16-bit addition, a struct local needs to go in an appropriately-sized memory location. This is basically the same as #2. 3b) schema-ed data storage. This allows laying out structured data in a compact way in memory (e.g. `struct x { int a; int b; }` consists of 2 integers one after the other). This functionality is useful even in unityped code.

The problem with the original lottery is that most of its value is from high-EV tiny-probability events, e.g. the 2^{-50} probability of winning 2^50 dollars. The practical result of that event does not seem to be worth 2^50 utilons, to say the least. It is hard to think about events worth that many.

However, many perturbations of this lottery can actually be good bets.

For example, suppose you gain 3^n dollars with probability 2^{-n}. Then you have a 1/128 chance of winning $2187, a 1/256 change of winning $6561, and this game starts looking much nicer.

The "Pascal's Mugging" divergence is a different problem, where Solomonoff-style priors imply negative-exponential probabilities of Busy-Beaverish payoffs. Ordinary priors don't really have this problem.

This is the well-known CRT fault attack, nothing new. SSL implementations that don't verify their signatures leak the private key if their signature routine has a bug - this is essentially a hardware problem. Verifying your signatures is fast, though, so doing it is worthwhile hardening (NSA can potentially use cosmic rays for this attack, probably nobody else).

The findings are very similar to the classic "Ron was wrong, Whit is right" paper - if you scan the entire Internet, you will find broken hardware. You will also find SSH servers with their root password being `12345678`.

well C++11 strings are just "reallocate when you look at them funny". Or you use shared_ptr and are back to square 1.

Slicing Pascal-style strings is also easy and constant-time: just track the buffer, offset, and length of the slice of characters you want. Java used to do it implicitly whenever you called `substring`.

That's just coercing into a "modern C buffer" and slicing it. It has the disadvantage that coercion is not equality or subtyping - i.e. you will have to do lots of wrappings and unwrappings in mixed code.

Every C method that takes a character buffer either a) has a corresponding length parameter or b) is avoided because of the security risks. In practice this means that C also stores the length information, just on the side instead of combined into a struct with the buffer.

You are surely talking about the buffer's capacity, not the string's length. These are distinct concepts. Anyway, functions that only read strings, and structs that only store them read-only, aren't interested in the capacity of any buffer.

Anyway, C strings aren't responsible for the fixed-size buffers of Cold War-era code - that code uses fixed-size buffers for everything. Their main claim to fame is their popularity in parsing code, which is edge-case- and bug-prone.

NUL-terminated strings aren't that bad:

* unlike Pascal-style strings, they can be usefully sliced, especially if you can modify them strtok-style.

* unlike (ptr,len) "Modern C buffers"/Rust-style strings, references to them are pointer-sized, and they can be used as a serialization format.

This makes the kind of application that is based on cutting pieces of a string and passing them around a good measure faster, especially compared to say C++'s "atomically reference-counted, re-allocating at the slightest touch" std::string.

This style of programming is not particularly popular nowadays, so buffer-strings are better-fitting. Its main problem is its multitude of edge-cases, which tend to demonstrate C's "every bug is exploitable" problem well.

According to the paper, it simply makes everywhere outside of data structure code a quiescent state. This may be a big difference in practice through, because one of the appeals of RCU is being able to interact with data structures with no fear of following dangling pointers.

However, with both RCU and the epoch-based scheme, you can make quiescent states as fine- or coarse-grained as you desire.

Could someone explain the big difference between RCU and epoch-based reclamation? It seems that the only difference is that RCU has quiescent periods between reschedules and epoch-based has them when you don't have a Guard struct active. Seems like six of one, half a dozen of the other.

A pointer points to the start of its pointee - i.e. the point "just before" its pointee. That's how derived-to-base casts work. That's also how you can have "one-past-the-end" pointers, which are actually "just after" the relevant array.

for example, if you have the following structs

    typedef struct { void *key; } base;
    typedef struct { base b; int misc; int data[2]; } derived;
then derived is laid out as follows
    -----+------+---------+---------+---------+-----
     ... | base | derived | data[0] | data[1] | ...
    -----+------+---------+---------+---------+-----
         ^                ^                   ^
         |                |                   |
        base         derived.data      &derived.data[2]

Original reporter here. I was starting to worry when this will ever get fixed. I am not skilled in exploit development and I basically just found the bug by accident so I won't take the challenge.

Why the focus on context-sensitivity? You can perfectly well validate a (restricted subset of) HTML with a regex - regexes are in fact very good at input sanitization. Parsers are dangerous because formats have exponentially many edges for you to get cut on. This is the case for regular, context-free, and worse formats.

Rust in 2016 11 years ago

When the MIR work is done creating a new translator would certainly be easier.

Rust in 2016 11 years ago

The annoying thing is that (because of type inference) parts of the expression could be within different expressions:

    fn required_bytes(width: u16, height: u16) -> u64 {
        let size = width * height; // what's the type of size?
        size + 12
    }

I agree that "are you sure you want to proceed?" dialog boxes on a word processor are absolutely horrible, but not all dialog boxes are so bad - Firefox's unacceptable certificate page, is, for example, a decent solution for its problem.

There are many actions that could be very harmful under some situations, but occasionally required (e.g. dealing with websites that get a certificate for `www.mysite.net` instead of `mysite.net`). Much of safety engineering is ensuring these are not encountered in day-to-day routine, but these are never perfect, and much worse in open, dynamic environments (like the military, when this case occured).

Militaries do typically have radio protocols to reduce the risk of artillery targeting unintended locations. I agree that good testers should have caught this bug, but there are hundreds of corner cases and you will always miss some of them. Domestic electric equipment is designed to prevent live wires from being exposed, but RCD-s are still a thing.

lock-free data structures should have identical semantics (and uncontended performance) to lockful data structures with per-operation locks (up to performance), except for the temptation to hold the data structure lock for a long time.

The problem with locks is that people don't want one thread per object, and instead use one lock per object. This has the effect of making all object operations synchronous, which turns some potential race-conditions into deadlocks.

Don't you lose all of your performance gains in RPC overhead? How do you avoid latency in the data thread (do you have one thread per lockable object? won't that be more than 1 thread per core?) - these are the reasons lock-free is so popular.