On Thu, Jul 20, 2017 at 1:05 PM, Thomas Leonard <tal...@gmail.com> wrote:
> I did start off trying to implement it that way, but then I realised > that questions don't usually hang around long anyway, so it didn't > seem worth the effort. > Yes, that's probably the right decision. > >> Maybe I got this bit wrong. I attached the "used" flags to the > >> question, but maybe I should be tagging the reference to the question > >> instead. Can different references to the same question need different > >> disembargoes? e.g. should forwarding a message mark the promised > >> answer as needing a disembargo or not? > > > > Sorry, I don't understand your question here. > > Maybe it doesn't make sense, or only with my implementation, but it > seems we have two objects for a question/export: > > - a proxy that always sends to the remote peer > - a switchable proxy that forwards to the previous object until the > question returns, and then sends to the new target (possibly after a > disembargo) > > I was just wondering which proxy should track whether it has been used > (and, therefore, whether it needs a disembargo). > > If we had the implementor's guide that was mentioned earlier, it could > probably cover this. My current implementation muddles these two up, > which is why it's delivering things out of order, so my question is > probably muddled up too. I'll need to think about this a bit more. > OK, makes sense. > > Nice example! > > > > It looks like the C++ implementation today will decide b = q1.x, and > never > > allow it to further resolve to client_bs. This "works" but is clearly > > suboptimal. > > > > For a correct solution, we need to recognize that Disembargo messages can > > "bounce" multiple times: > > Does it alternate between being a disembargo request and a disembargo > response as this happens? > It alternates between `senderLoopback` and `receiverLoopback`, yes. > Does the 3-vat case complicate things? > Always. :) (But I haven't thought it through lately...) -Kenton > > On another note, you say you found this with AFL, which is amazing. Could > > your fuzzing strategy be applied to the C++ implementation as well? > > Maybe. Here's how it works: > > To simplify things, my OCaml capnp-rpc library is in two parts. One > provides the RPC logic over abstract message types, and the other > provides an implementation using the Cap'n Proto serialisation for the > messages. Most of the unit-tests check the core logic directly, using > a simpler message type where a payload is just a test string and an > array of capability pointers. The fuzz tests use a mutable struct with > things useful for checking for violations. > > The fuzz tests set up some vats (two or three) in a single process and > then have them perform operations based on input from the fuzzer. > Each step selects one vat and performs a random (fuzzer-chosen) > operation out of: > > 1. Request a bootstrap capability from a random peer. > 2. Handle one message on the incoming queue. > 3. Call a random capability, passing randomly-selected capabilities as > arguments. > 4. Finish a random question. > 5. Release a random capability. > 6. Add a capability to a newly-created local service. > 7. Answer a random question, passing random-selected capabilities as > the response. > > When it runs out of input data from the fuzzer it releases all > capabilities, answers all questions and allows the system to become > idle. > > The fuzz tests include in the call's payload contents a sequence > number and a (mutable) struct containing the source reference's > counters: > > type cap_ref_counters = { > mutable next_to_send : int; > mutable next_expected : int; > } > > When the message arrives, the target service checks that the counter > in the content matches the current value of `next_expected` and > increments it. > So, it should always detect if messages arrive out of order. > > Another way it takes advantage of everything running in one process is > that it maintains a second reference graph, but one which doesn't use > CapTP. When it requests a bootstrap capability over CapTP, it also > returns a direct pointer to the target service. So, it's a copy of the > reference graph but with all vat-spanning links replaced with direct > pointers. Then, it checks that every message is delivered to the > service it would have been delivered to if there were no network in > the way. > > I leave AFL running my binary for a while with the --fuzz option > (which disables logging to keep things fast). > When it finds a violation it leaves it in the crash directory. Then I > run the fuzz binary on it manually without --fuzz, which turns on > logging and runs a load of sanity checks at each step, as well as > dumping the state of the system at each step. It also outputs an OCaml > unit-test, which can be cut-and-pasted into the test-suite. The > unit-tests look like this, after being cleaned up a bit: > > https://github.com/mirage/capnp-rpc/blob/f5a32455c41056eaa40 > b3074f1cfb33741854e69/test/test.ml#L462 > > If the test-case is too long, afl-tmin can often shorten it. > > There are plenty of other things it could be made to check, e.g. that > forked references can't access anything before their parent, that > messages to valid targets are always eventually delivered, that after > letting the system become idle all references point directly to the > vat containing their target in the direct reference graph, that > malicious vats can't cause protocol violations in connections between > good vats, etc. However, I have enough bugs to fix with the current > tests ;-) > > I don't know if that's any use to you - I'm not sure how the C++ code > is structured. > > > -- > talex5 (GitHub/Twitter) http://roscidus.com/blog/ > GPG: 5DD5 8D70 899C 454A 966D 6A51 7513 3C8F 94F6 E0CC > -- You received this message because you are subscribed to the Google Groups "Cap'n Proto" group. To unsubscribe from this group and stop receiving emails from it, send an email to capnproto+unsubscr...@googlegroups.com. Visit this group at https://groups.google.com/group/capnproto.