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

Kernel+DynamicLoader: Various fixes around mmap & mprotect syscalls #24190

Merged
merged 3 commits into from May 14, 2024

Conversation

supercomputer7
Copy link
Member

@supercomputer7 supercomputer7 commented May 3, 2024

This PR should fix a couple of issues I've seen in current implementation:

  • We never completely block transition from writable regions to being executable ones, because the DynamicLoader has to do some text relocation and to properly support this, we do various checks (which are "fine"), but we might as well want to completely avoid such complication in the first place.
  • The Region has_been_{r,w,x} flags are not clearly understandable because nothing sets them clearly. A simple search doesn't show those bits being set, and only by looking deeper into the Region set_access_bit method we could see that there's ORing with (access << 4) when enabling an access bit.
  • The logic of enabling syscall region enforcing is overly complicated, instead of being set-once flag.

The following 3 commits are trying to solve all of the mentioned problems. Hopefully I didn't mess anything up, but I'd like to get reviews on these changes and be pointed on problems if so are appeared in this PR.

@github-actions github-actions bot added the 👀 pr-needs-review PR needs review from a maintainer or community member label May 3, 2024
@DanShaders
Copy link
Contributor

Really like this change from userspace perspective. I think I spend around 20 minutes the day before yesterday figuring out how and when various protections get enabled.

@supercomputer7 supercomputer7 force-pushed the fix-mmap-prot-validation branch 2 times, most recently from a58a0f4 to 96a2f9c Compare May 3, 2024 13:00
@supercomputer7
Copy link
Member Author

The second commit will probably disable dlopen from working in a program that needs to dynamically load a module or a shared library.
While it might not be a big problem currently (because nothing in our ecosystem actually do that), it might be a problem for ports - however, we could put the WXALLOWED mount flag (as a bind mount, or just have a separate filesystem mounted specifically for ported software binaries) for ports that need it however, so no actual big issue, besides that we will need to investigate on why the port crashed and find this as the reason.

@DanShaders
Copy link
Contributor

The second commit will probably disable dlopen from working in a program that needs to dynamically load a module or a shared library.

No, if it had done that, the CI would have failed. It does, however, prevent loading modules with text relocations (since only them require remapping from W to X memory) but DynamicLoader doesn't really like text relocations even in initially loaded objects.

@ADKaster
Copy link
Member

ADKaster commented May 7, 2024

This has a conflict with DanShaders' Kernel/Memory/Region changes that I merged today

@ADKaster ADKaster added ⚠️ pr-has-conflicts PR has merge conflicts and needs to be rebased and removed 👀 pr-needs-review PR needs review from a maintainer or community member labels May 7, 2024
This flag is set only once, and should never reset once it has been set,
making it an ideal SetOnce use-case.
It also simplifies the expected conditions for the enabling prctl call,
as we don't expect a boolean flag, but rather the specific prctl option
will always set (enable) Process' AddressSpace syscall region enforcing.
We add a prctl option which would be called once after the dynamic
loader has finished to do text relocations before calling the actual
program entry point.

This change makes it much more obvious when we are allowed to change
a region protection access from being writable to executable.
The dynamic loader should be able to do this, but after a certain point
it is obvious that such mechanism should be disabled.
Before of this change, actually setting the m_access to contain the
HasBeen{Readeable,Writable,Executable} bits was done by the method of
Region set_access_bit which added ORing with (access << 4) when enabling
a certain access bit to achieve this.

Now this is changed and when calling set_{readeable,writable,executable}
methods, they will set an appropriate SetOnce flag that could be checked
later.
@supercomputer7 supercomputer7 removed the ⚠️ pr-has-conflicts PR has merge conflicts and needs to be rebased label May 8, 2024
@github-actions github-actions bot added the 👀 pr-needs-review PR needs review from a maintainer or community member label May 8, 2024
@supercomputer7
Copy link
Member Author

The second commit will probably disable dlopen from working in a program that needs to dynamically load a module or a shared library.

No, if it had done that, the CI would have failed. It does, however, prevent loading modules with text relocations (since only them require remapping from W to X memory) but DynamicLoader doesn't really like text relocations even in initially loaded objects.

Right, it will prevent loading modules that need text relocations to work. Not that we do any of that in our codebase, so it should be OK.

@ADKaster ADKaster merged commit 5194ab5 into SerenityOS:master May 14, 2024
13 checks passed
@github-actions github-actions bot removed the 👀 pr-needs-review PR needs review from a maintainer or community member label May 14, 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.

None yet

3 participants