Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

comms doesn't set up reverse mapping for promises correctly #1404

Closed
warner opened this issue Aug 9, 2020 · 1 comment
Closed

comms doesn't set up reverse mapping for promises correctly #1404

warner opened this issue Aug 9, 2020 · 1 comment
Assignees
Labels
bug Something isn't working security SwingSet package: SwingSet

Comments

@warner
Copy link
Member

warner commented Aug 9, 2020

Describe the bug

While investigating #1400, I noticed a problem in mapInbound. For objects, we correctly populate the per-remote table with to/from entries that flip the remote identifier's ownership polarity:

if (allocatedByRecipient) {
throw new Error(`I don't remember giving ${s} to ${remoteID}`);
}
// this must be a new import. Allocate a new vat object for it, which
// will be the local machine's proxy for use by all other local vats
const localSlot = makeVatSlot(type, true, state.nextObjectIndex);
state.nextObjectIndex += 1;
// they sent us ro-NN
remote.fromRemote.set(s, localSlot);
// when we send it back, we'll send ro+NN
remote.toRemote.set(localSlot, flipRemoteSlot(s));
// and remember how to route this later
state.objectTable.set(localSlot, remoteID);

to honor the specification:

// The keys of the fromRemote table will have the opposite allocator flag
// as the corresponding value of the toRemote table. The only time we must
// reverse the polarity of the flag is when we add a new entry to the
// clist.
// fromRemote has:
// ro-NN -> o+NN (imported/importing from remote machine)
// ro+NN -> o-NN (previously exported to remote machine)
const fromRemote = new Map(); // {ro/rp/rr+-NN} -> o+-NN/p+-NN/r+-NN
// toRemote has:
// o+NN -> ro+NN (previously imported from remote machine)
// o-NN -> ro-NN (exported/exporting to remote machine)
const toRemote = new Map(); // o/p/r+-NN -> ro/rp/rr+-NN

however when we allocate a new promise, we fail to flip the toRemote side:

} else if (type === 'promise') {
if (allocatedByRecipient) {
throw new Error(`I don't remember giving ${s} to ${remoteID}`);
} else {
const promiseID = allocateUnresolvedPromise(state, remoteID);
remote.fromRemote.set(s, promiseID);
remote.toRemote.set(promiseID, s);
// console.debug(`inbound promise ${s} mapped to ${promiseID}`);
}

When the inbound promise appeared as a result, we fix it up in mapInboundResult:

export function mapInboundResult(state, remoteID, result) {
insistRemoteType('promise', result);
assert(!parseRemoteSlot(result).allocatedByRecipient, details`${result}`); // temp?
const r = mapInbound(state, remoteID, result);
insistVatType('promise', r);
insistPromiseIsUnresolved(state, r);
insistPromiseDeciderIs(state, r, remoteID);
insistPromiseSubscriberIsNotDifferent(state, r, remoteID);
setPromiseDecider(state, r, null); // (local kernel / other local vat) now decides
setPromiseSubscriber(state, r, remoteID); // auto-subscribe the sender
const remote = getRemote(state, remoteID);
remote.fromRemote.set(result, r);
remote.toRemote.set(r, flipRemoteSlot(result));
return r;
}

but we'll fail to do that for promises that appear anywhere else, like in arguments of an inbound message, or in a record used to resolve some other promise to data.

The consequence is that when we try to send these objects back to the sender, we'll give them an identifier with the wrong polarity. At best, they'll refuse the message because they don't recognize the promise ID. At worst, it will map to some unrelated promise, which would be an exciting security bug.

TODO items for me:

  • add test (to message-patterns, the "comms" flavor) of a new argument promise being sent back to the sender
  • add test of a new resolve-to-data promise being sent back to the sender
  • change mapInbound to flip the direction of the remote identifier we use in toRemote
  • change mapInboundResult to not modify toRemote/fromRemote at all
@warner warner added bug Something isn't working SwingSet package: SwingSet security labels Aug 9, 2020
@warner warner self-assigned this Aug 9, 2020
warner added a commit that referenced this issue Aug 28, 2020
This overhauls the comms vat to use a new reference-tracking model. It should
fix a number of gaps where the previous code would throw an error:

* pass an already-resolved Promise through any message, this would make
  the comms vat re-use a retired VPID, which is a vat-fatal error
* resolve a remotely-sourced promise to a local object (rather than a remote
  one), then pipeline a message to it (so the message should be reflected back
  into the kernel)
* resolve a local promise to a remote object, then the remote pipelines a
  message to it (so the message should be reflected back out to the remote)
* passing one remote's references to a different remote

The last case is the "three-party handoff". The full solution (with
shortening, grant-matching, and automatic connection establishment) is quite
a ways off, but this change ought to implement "three-party forwarding". In
this form, when A sends B a reference to C, what B gets is effectively an
object on A that automatically forwards all messages off to C. This "object"
is hidden inside the comms vat and is not reified as a real object.

Three-party forwarding is not tested yet.

refs #1535
refs #1404
warner added a commit that referenced this issue Aug 28, 2020
This overhauls the comms vat to use a new reference-tracking model. It should
fix a number of gaps where the previous code would throw an error:

* pass an already-resolved Promise through any message, this would make
  the comms vat re-use a retired VPID, which is a vat-fatal error
* resolve a remotely-sourced promise to a local object (rather than a remote
  one), then pipeline a message to it (so the message should be reflected back
  into the kernel)
* resolve a local promise to a remote object, then the remote pipelines a
  message to it (so the message should be reflected back out to the remote)
* passing one remote's references to a different remote

The last case is the "three-party handoff". The full solution (with
shortening, grant-matching, and automatic connection establishment) is quite
a ways off, but this change ought to implement "three-party forwarding". In
this form, when A sends B a reference to C, what B gets is effectively an
object on A that automatically forwards all messages off to C. This "object"
is hidden inside the comms vat and is not reified as a real object.

Three-party forwarding is not tested yet.

refs #1535
refs #1404
warner added a commit that referenced this issue Aug 28, 2020
This overhauls the comms vat to use a new reference-tracking model. It should
fix a number of gaps where the previous code would throw an error:

* pass an already-resolved Promise through any message, this would make
  the comms vat re-use a retired VPID, which is a vat-fatal error
* resolve a remotely-sourced promise to a local object (rather than a remote
  one), then pipeline a message to it (so the message should be reflected back
  into the kernel)
* resolve a local promise to a remote object, then the remote pipelines a
  message to it (so the message should be reflected back out to the remote)
* passing one remote's references to a different remote

The last case is the "three-party handoff". The full solution (with
shortening, grant-matching, and automatic connection establishment) is quite
a ways off, but this change ought to implement "three-party forwarding". In
this form, when A sends B a reference to C, what B gets is effectively an
object on A that automatically forwards all messages off to C. This "object"
is hidden inside the comms vat and is not reified as a real object.

Three-party forwarding is not tested yet.

refs #1535
refs #1404
@warner
Copy link
Member Author

warner commented Aug 28, 2020

I ended up fixing this (and a slew of other problems) by rewriting the comms vat entirely, in PR #1635

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working security SwingSet package: SwingSet
Projects
None yet
Development

No branches or pull requests

1 participant