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 segfault or stack overflow caused by large derivation fields #5875

Merged
merged 6 commits into from
Jan 24, 2022

Conversation

roberth
Copy link
Member

@roberth roberth commented Jan 6, 2022

This removes a dynamic stack allocation, making the derivation
unparsing logic robust against overflows when large strings are
added to a derivation.
Overflow behavior depends on the platform and stack configuration.

For instance, x86_64-linux/glibc behaves as (somewhat) expected:

$ (ulimit -s 20000; nix-instantiate tests/lang/eval-okay-big-derivation-attr.nix)
error: stack overflow (possible infinite recursion)

$ (ulimit -s 40000; nix-instantiate tests/lang/eval-okay-big-derivation-attr.nix)
error: expression does not evaluate to a derivation (or a set or list of those)

However, on aarch64-darwin:

$ nix-instantiate big-attr.nix ~
zsh: segmentation fault nix-instantiate big-attr.nix

This indicates a slight flaw in the single stack protection page
approach that is not encountered with normal stack frames.
With this change, we avoid both types of failure.

src/libstore/derivations.cc Outdated Show resolved Hide resolved
@roberth roberth force-pushed the fix-large-drv-field-stack-overflow branch 2 times, most recently from 3f3c0a0 to 08ff118 Compare January 6, 2022 12:40
src/libstore/derivations.cc Outdated Show resolved Hide resolved
@roberth
Copy link
Member Author

roberth commented Jan 6, 2022

Interestingly, the new test case triggers #3605 when run with a daemon, but not when the derivation field is modified to be "just" 1MiB.
Is it possible that test suite on darwin doesn't run with a daemon?
Regardless, I have manually confirmed that the darwin segfault is triggered by the 1MiB test using ulimit -s 100, but not after the PR is applied.

src/libutil/util.hh Outdated Show resolved Hide resolved
@dasJ
Copy link
Member

dasJ commented Jan 10, 2022

I can confirm this fixes our Hydra Evaluator crashing. It would be nice to somehow fix that Darwin situation

@roberth
Copy link
Member Author

roberth commented Jan 10, 2022

It would be nice to somehow fix that Darwin situation

I think you were referring to a flaky test result in CI and I agree.

@roberth
Copy link
Member Author

roberth commented Jan 10, 2022

@edolstra This is ready for review

@pennae
Copy link
Contributor

pennae commented Jan 11, 2022

we've run the current head with decreased buffer size through our benchmarks and haven't seen a significant impact. 👍

@roberth roberth requested a review from edolstra January 18, 2022 10:46
@roberth
Copy link
Member Author

roberth commented Jan 19, 2022

@thufschmitt I believe this is ready to be merged.

@roberth
Copy link
Member Author

roberth commented Jan 19, 2022

Could you add backport labels?

Copy link
Member

@thufschmitt thufschmitt left a comment

Choose a reason for hiding this comment

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

Just a small request for some extra doc, but 👍 otherwise

src/libutil/util.hh Outdated Show resolved Hide resolved
@roberth roberth force-pushed the fix-large-drv-field-stack-overflow branch from 961b680 to 2b3da07 Compare January 19, 2022 13:30
This removes a dynamic stack allocation, making the derivation
unparsing logic robust against overflows when large strings are
added to a derivation.
Overflow behavior depends on the platform and stack configuration.

For instance, x86_64-linux/glibc behaves as (somewhat) expected:

$ (ulimit -s 20000; nix-instantiate tests/lang/eval-okay-big-derivation-attr.nix)
error: stack overflow (possible infinite recursion)

$ (ulimit -s 40000; nix-instantiate tests/lang/eval-okay-big-derivation-attr.nix)
error: expression does not evaluate to a derivation (or a set or list of those)

However, on aarch64-darwin:

$ nix-instantiate big-attr.nix                                                                                                                                                                                                                                                       ~
zsh: segmentation fault  nix-instantiate big-attr.nix

This indicates a slight flaw in the single stack protection page
approach that is not encountered with normal stack frames.
... to avoid non-standard, unidiomatic alloca.
Although this will leave gaps in the stack, the performance impact
of those should be insignificant and we get a simpler solution
this way.
@roberth roberth force-pushed the fix-large-drv-field-stack-overflow branch from 2b3da07 to dec7748 Compare January 19, 2022 14:22
If we want to be careful about hitting the stack protector page, we should use `-fstack-check` instead.

Co-authored-by: Eelco Dolstra <[email protected]>
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.

5 participants