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

GH-116017: Put JIT code and data on the same page #116845

Merged
merged 8 commits into from
Mar 19, 2024

Conversation

brandtbucher
Copy link
Member

@brandtbucher brandtbucher commented Mar 14, 2024

Instead of marking code as read-exec and data as read-only, put both on the same read-exec pages. This halves the amount of memory used for short traces, and also results in half as many expensive mprotect calls per trace.

3% faster (10% faster startup), 9% less memory (12% less at startup).

The next step after this will be sharing pages between traces, to further reduce the amount of wasted memory. At the same time, we can expose a way to compile multiple traces at once with a single mprotect call (useful for the cold exit array).

@brandtbucher brandtbucher added performance Performance or resource usage skip news interpreter-core (Objects, Python, Grammar, and Parser dirs) labels Mar 14, 2024
@brandtbucher brandtbucher self-assigned this Mar 14, 2024
@brandtbucher
Copy link
Member Author

This also fixes an issue where we weren't using the correct alignment during parts of the build process and things just accidentally worked (due to the data starting on a page boundary).

Python/jit.c Outdated Show resolved Hide resolved
@mdboom
Copy link
Contributor

mdboom commented Mar 15, 2024

I realise it probably makes sense to benchmark this one on macOS (since that's where we saw the greatest memory increase in #116017). I'll fire off a run right now.

@brandtbucher
Copy link
Member Author

Oh, I already did. :) Results were less good: 1% faster, no memory impact (which is a bit odd, but I haven't really dug into it yet).

@hartwork
Copy link
Contributor

Instead of marking code as read-exec and data as read-only, put both on the same read-exec pages.

@brandtbucher I may be missing something here: is this a reduction in security? Has this been discussed with the security team?

@brandtbucher
Copy link
Member Author

brandtbucher commented Mar 18, 2024

Instead of marking code as read-exec and data as read-only, put both on the same read-exec pages.

@brandtbucher I may be missing something here: is this a reduction in security? Has this been discussed with the security team?

I should clarify: this change doesn't mean that we're now executing arbitrary user data. In this case, "data" is stuff like C string literals for error messages, pointers to cached objects, static C function addresses, version numbers, opargs, etc.

Since this data is now executable (as it lives on the same pages as the machine code), in theory an attacker capable of forcing the compilation of an instruction operand that happens to have the same encoding as a machine instruction could take control of the program. However, that would require that we jump into the data at some point, something which never happens during normal operation. As such, this would require a separate, highly specific bug in machine code generation in order to actually exploit.

The most likely way this would happen is not by jumping from the machine code into the data, but rather accidentally running off the end of the machine code into the data portion of the buffer (again, not something that happens with the sort of well-formed traces that tier two creates). This situation currently crashes on main, but would indeed begin executing the "read-only" data with the proposed change. However, this patch mitigates this risk by always adding a _FATAL_ERROR block to the end of the code portion of the trace, assuring that even if we did have a malformed trace, the program would abort before it actually overran the buffer.

I appreciate your comment, though. Please let me know if I've missed anything, or if you still have any concerns.

@brandtbucher brandtbucher merged commit 2c82592 into python:main Mar 19, 2024
56 of 57 checks passed
vstinner pushed a commit to vstinner/cpython that referenced this pull request Mar 20, 2024
@mdboom
Copy link
Contributor

mdboom commented Mar 20, 2024

@brandtbucher
Copy link
Member Author

Awesome! Wonder why it didn't come through in my first run...

@mdboom
Copy link
Contributor

mdboom commented Mar 20, 2024

The compiler on that machine was still broken when you kicked it off yesterday -- I didn't truly fix it until this morning.

@mdboom
Copy link
Contributor

mdboom commented Mar 20, 2024

It's also a solid 1-3% faster on macOS.

@mdboom
Copy link
Contributor

mdboom commented Mar 20, 2024

The compiler on that machine was still broken when you kicked it off yesterday -- I didn't truly fix it until this morning.

Oh, I see you mean the run from 5 days ago. Yeah, it's not clear why it shows "no change". Something to keep an eye on for the future in case there is a bug somewhere in the benchmarking infra (but not clear what it would be).

adorilson pushed a commit to adorilson/cpython that referenced this pull request Mar 25, 2024
diegorusso pushed a commit to diegorusso/cpython that referenced this pull request Apr 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
interpreter-core (Objects, Python, Grammar, and Parser dirs) performance Performance or resource usage skip news topic-JIT
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants