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

fix(ses): harden hacks v8 stack own accessor problem #2232

Merged
merged 7 commits into from
Apr 22, 2024

Conversation

erights
Copy link
Contributor

@erights erights commented Apr 21, 2024

closes: #2198
refs: #2230 #2200 https://chromium-review.googlesource.com/c/v8/v8/+/4459251 #2229 #2231 https://issues.chromium.org/issues/40279506

Description

Alternative to #2229 that just hacks harden to directly repair a problematic error own stack accessor property, replacing it with a data property.

Security Considerations

Both before and after this PR, passStyleOf will reject errors with the v8 problematic error own stack accessor property, preventing the unsafety at stake here. However, this would mean that much existing code that used to be correct will break when run on a v8 with this problem.

Scaling Considerations

Avoids any extra overhead on platforms without this problem, including all platforms other than v8.

Documentation Considerations

probably none. This PR essentially avoids the need to document the v8 problem that it masks.

Testing Considerations

Only needed to repair one test to use harden rather than freeze, in a case where harden was more natural anyway.

Compatibility Considerations

This PR enables more errors to pass that check without further changes to user code. #2229 had similar goals, but would still require more changes to user code than this PR. This is demonstrated by all the test code in #2229 that needed to be fixed that does not need to be fixed in this PR.

Upgrade Considerations

none

  • [ ] Includes *BREAKING*: in the commit message with migration instructions for any breaking change.
  • [ ] Updates NEWS.md for user-facing changes.

@erights erights self-assigned this Apr 21, 2024
@erights erights requested a review from kriskowal April 21, 2024 00:44
@erights erights marked this pull request as ready for review April 21, 2024 00:44
@erights erights changed the title fix(ses): harden hacks v8 stack own accessor problem fix(ses): harden hacks v8 stack own accessor problem Apr 21, 2024
@erights erights mentioned this pull request Apr 21, 2024
2 tasks
@erights
Copy link
Contributor Author

erights commented Apr 21, 2024

CI for #2233 fails on Node 21 due to the v8 problems that this PR hacks around. CI for #2234 succeeds, validating that for at least these occurrences of the problem, this PR fixes them.

Copy link
Contributor

@mhofman mhofman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Besides the couple small nits, I am concerned about modifying harden to mitigate this. I understand the reasoning, but it breaks the layering inside the ses shim (and would prevent my hope to extract harden as its own shim)

packages/ses/src/commons.js Show resolved Hide resolved
packages/ses/src/commons.js Outdated Show resolved Hide resolved
const stackDesc = getOwnPropertyDescriptor(obj, 'stack');
if (
stackDesc &&
stackDesc.get === FERAL_STACK_GETTER &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test for either the getter or setter?

Suggested change
stackDesc.get === FERAL_STACK_GETTER &&
(stackDesc.get === FERAL_STACK_GETTER || stackDesc.set === FERAL_STACK_SETTER) &&

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, but with && rather than || to be more conservative. But either they are both set or neither is set, so cannot actually make a difference.

Resolving.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe I didn't express myself correctly. I was trying to handle the case where an error object would show up with either a getter or a setter own prop. Arguably someone would have to go muck with the prop descriptor before hardening the error object, so probably not worth bothering about.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test here is only testing whether we're on a platform suffering from v8's misbehavior.

Ok to reresolve?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding is that we already know we're on an affected platform, but here we're testing whether the error object we found exhibit the bad behavior. It's possible the error object got modified already (e.g. stack prop removed, or replaced with data). The question is which kind of modifications we want to handle here (in particular whether we want to handle a setter only stack prop if we find one)

packages/ses/src/make-hardener.js Show resolved Hide resolved
@erights erights force-pushed the markm-harden-hacks-stack-accessor branch from 661f391 to b11beba Compare April 22, 2024 18:42
@erights
Copy link
Contributor Author

erights commented Apr 22, 2024

Since #2231 was already merged, causing CI errors for the CI cases that this PR is trying to address, I added to this PR the change from #2233 / #2234 that switches from trying to use 22.x, which fails because it is not found, to using 21.x, which is found. I will thus also close #2233 and #2234 in favor of this PR.

Copy link
Member

@kriskowal kriskowal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to hear more from @mhofman about how this change would preclude a separable harden shim.

@mhofman
Copy link
Contributor

mhofman commented Apr 22, 2024

I want to hear more from @mhofman about how this change would preclude a separable harden shim.

This is a repair that harden does for the benefit other layers (pass style). IMO, it's conceptually hard to justify its presence in the ses shim itself. It wouldn't be justifiable at all in a standalone harden shim.

@erights
Copy link
Contributor Author

erights commented Apr 22, 2024

I want to hear more from @mhofman about how this change would preclude a separable harden shim.

This is a repair that harden does for the benefit other layers (pass style). IMO, it's conceptually hard to justify its presence in the ses shim itself. It wouldn't be justifiable at all in a standalone harden shim.

It could be exposed as a configuration option in a standalone harden shim. I agree that it is unpleasant, but the underlying problem caused by v8 is the source of the unpleasantness. "Fixing" it in harden is, I think, the fix that's least unpleasant for users, as evidenced by all the test case changes that I no longer needed to do.

@erights erights enabled auto-merge (squash) April 22, 2024 23:14
@erights erights merged commit 4b529e0 into master Apr 22, 2024
20 checks passed
@erights erights deleted the markm-harden-hacks-stack-accessor branch April 22, 2024 23:16
@erights
Copy link
Contributor Author

erights commented Apr 24, 2024

erights added a commit that referenced this pull request Apr 29, 2024
## Description

All this `path` maintenance within `harden` was there in case we
encountered failures to harden that were hard to diagnose. They
accumulate the path accumulated from the harden root to the thing that
failed to be hardened. But it was never used to produce a better error
message. Rather, they could have been useful from a debugger's eye view.
But in all the years we've paid the price for this diagnostic, we have
not made use of it. The operations used to accumulate the path are
expensive string operations and WeakSet operations.

Because the diagnostic information was never actually shown in any
diagnostic, this change should be completely without any observable
effect. Hence, this PR is a pure refactor.

### Security Considerations

Mostly none. By making `harden` cheaper, perhaps it'll be used more,
which would help security. But we have not generally avoided harden due
to its runtime cost, with the exception of the SwingSet kernel.

### Scaling Considerations

The point.

Note though that on XS we're already using the native harden that does
not pay this price. The SwingSet kernel `harden` is already suppressed.
So this PR only affects use of `harden` not on XS and not within the
SwingSet kernel itself.

@gibson042 , before merging this, I'd like to work with you to quantify
its performance impact. If it has none, perhaps it isn't work doing and
we should keep the diagnostic info, just in case?

### Documentation Considerations

none. 

### Testing Considerations

none

### Compatibility Considerations

none

However, I noticed this while working on #2232 because I had to modify
the same code for different purposes. There will be minor merge
conflicts coming between these two PRs which I'll resolve after one of
them is merged.

### Upgrade Considerations

none

- ~[ ] Includes `*BREAKING*:` in the commit message with migration
instructions for any breaking change.~
- ~[ ] Updates `NEWS.md` for user-facing changes.~
@erights erights mentioned this pull request May 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Marshal fails to rehydrate errors in Chrome, Firefox, Safari
3 participants