-
Notifications
You must be signed in to change notification settings - Fork 71
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
fix(ses)!: Withdraw support for muli-lockdown #921
Conversation
60e6264
to
139ac27
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks fine by me.
Reviewer nit: I usually try to review commit-by-commit, so when code is moved from one file to another, I prefer to have that as a separate commit if new code is added or left behind in the remaining file. For remain behind, I usually try to temporarily rename the source file if most of the content is extracted to another file so that the large moving content appears as a rename in git, and the small remaining content a new file.
packages/ses/NEWS.md
Outdated
- *BREAKING CHANGE*: Lockdown may no longer be called more than once. | ||
Lockdown no longer returns a boolean to indicate whether it was effective | ||
(true) or redundant (false). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this mention an error is thrown if trying to lockdown twice? Seems weird to be explicit about former behavior, but not about new one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Explicated this. Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume we should update the PR description too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
packages/ses/src/lockdown-shim.js
Outdated
@@ -53,7 +53,8 @@ import { makeCompartmentConstructor } from './compartment-shim.js'; | |||
|
|||
const { details: d, quote: q } = assert; | |||
|
|||
let firstOptions; | |||
/** @type {Error?} */ | |||
let priorLockdown = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why null
rather than undefined
?
let priorLockdown = null; | |
let priorLockdown; |
I don't have any strong reason for preferring one over the other. But when there is no other reason, I generally default to undefined
.
## Related | ||
|
||
This error is distinct from `SES_MULTIPLE_INSTANCES`, which attempts to | ||
distinguish the case where multiple Lockdown functions have been initialized. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The phrasing here is that the other error happens when "multiple Lockdown functions have been initialized", which might be a fine condition to detect and consider an error. However, the explanation in SES_MULTIPLE_INSTANCES.md below explains that error as indicating that multiple calls to lockdown occurred, where the calls were to different instances. From that text I would guess that multiple initializations, where only one is called, would not be an error.
packages/ses/src/lockdown-shim.js
Outdated
if (priorLockdown !== null) { | ||
const error = new TypeError( | ||
`Already lockded down (SES_ALREADY_LOCKED_DOWN)`, | ||
); | ||
// eslint-disable-next-line @endo/no-polymorphic-call | ||
assert.note(error, assert.details`Prior call ${priorLockdown}`); | ||
throw error; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggested simplification. Use only the parts, if any, that you agree are an improvement
if (priorLockdown !== null) { | |
const error = new TypeError( | |
`Already lockded down (SES_ALREADY_LOCKED_DOWN)`, | |
); | |
// eslint-disable-next-line @endo/no-polymorphic-call | |
assert.note(error, assert.details`Prior call ${priorLockdown}`); | |
throw error; | |
} | |
assert( | |
priorLockdown === null, | |
X`Already locked down at ${priorLockdown} (SES_ALREADY_LOCKED_DOWN)`, | |
TypeError, | |
); |
assuming an earlier
const { details: X } = assert;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Btw, I really like this technique of capturing the earlier non-erroneous stack trace in an error in case of a later conflict.
if (seemsToBeLockedDown()) { | ||
// eslint-disable-next-line @endo/no-polymorphic-call | ||
console.log('Seems to already be locked down. Skipping second lockdown'); | ||
return alreadyHardenedIntrinsics; | ||
throw new TypeError( | ||
`Already locked down but not by this SES instance (SES_MULTIPLE_INSTANCES)`, | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes clear which of the two conditions we treat as an error: where both lockdowns are called. This seems sensible.
packages/ses/src/lockdown-shim.js
Outdated
* We define hardenIntrinsics here so that options are in scope, but return | ||
* it to the caller so we can benchmark repair separately from hardening. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The other motivation is to prepare for vetted shims, which would run after repair and before hardening. In fact, this was the original and primary motivation.
domainTaming, | ||
__allowUnsafeMonkeyPatching__, | ||
}; | ||
priorLockdown = new TypeError('Prior lockdown (SES_ALREADY_LOCKED_DOWN)'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI this will keep the scope of this function and of its predecessors in the stack around since engines (well at least v8) lazily generate the stack string. While this probably happens early enough in the program execution, it might be worth "touching" the priorLockdown.stack
for good measure?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really? I have no direct knowledge, but I would have kept only a stack of PC addresses.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apparently JSC automatically generates the stack string if the scope would otherwise have been collected: https://twitter.com/filpizlo/status/1365140028247007234
Maybe v8 could perform some optimization in the case of strict functions and only keep the function name, and location around for Error.prepareStackTrace
. If you look at the Twitter thread, they apparently ran into some other perf issues.
*BREAKING CHANGE*: Lockdown can no longer be called more than once. Lockdown no longer returns a boolean to indicate whether it was effective (true) or redundant (false). Fixes #814
fbb1a10
to
6bf5b9a
Compare
BREAKING CHANGE: Lockdown can no longer be called more than once. Lockdown no longer returns a boolean to indicate whether it was effective (true) or redundant (false). Instead, Lockdown will return undefined for its first invocation or throw an error otherwise.
Fixes #814