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-117657: TSAN Fix race in PyMember_Get and PyMember_Set, for Py_T_OBJECT_EX type #119368

Merged
merged 20 commits into from
Jun 17, 2024

Conversation

dpdani
Copy link
Contributor

@dpdani dpdani commented May 21, 2024

Fix one data race and use-after-free in PyMember.

I've just started working on this, there are more races to be solved, but this is the only one visible from python code, AFAIU.

More PRs are required for making these functions thread-safe.
I've added some commented code to show what the follow-up tests would look like.

@bedevere-app
Copy link

bedevere-app bot commented May 21, 2024

Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply the skip news label instead.

@bedevere-app
Copy link

bedevere-app bot commented May 22, 2024

Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply the skip news label instead.

@bedevere-app
Copy link

bedevere-app bot commented May 22, 2024

Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply the skip news label instead.

@dpdani
Copy link
Contributor Author

dpdani commented May 22, 2024

@DinoV this is ready for review now

@colesbury colesbury changed the title gh-117657 TSAN Fix race in PyMember_Get and PyMember_Set, for Py_T_OBJECT_EX type gh-117657: TSAN Fix race in PyMember_Get and PyMember_Set, for Py_T_OBJECT_EX type May 31, 2024
Copy link
Contributor

@colesbury colesbury left a comment

Choose a reason for hiding this comment

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

I don't think we can rely on _Py_REF_MAYBE_WEAKREF (i.e., _PyObject_SetMaybeWeakref) being set on the field's value. The underlying field may be modified by a C API user outside of PyMember_SetOne, such as if it's defined with a PyMemberDef.

I think the setter needs to use a critical section. The reader can optimistically try _Py_TryIncrefCompare, but needs to fall back to a read inside a critical section if that fails.

@bedevere-app
Copy link

bedevere-app bot commented May 31, 2024

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

@dpdani
Copy link
Contributor Author

dpdani commented Jun 4, 2024

I see your point, but there would be a problem that I cannot see how to solve, though.
The signature PyMember_SetOne(char *addr, ...) implies that not only PyObjects can be passed in.
Also the comment above PyMemberDef implies the same (emphasis mine):

An array of PyMemberDef structures defines the name, type and offset
of selected members of a C structure. ...

So, what lock would I use for the critical section?
Do I just assume that char *addr always points to a python object?

@colesbury
Copy link
Contributor

Use the original address (i.e., obj_addr in PyMember_GetOne), not the field.

We already assume it's a PyObject:

PyObject *obj = (PyObject *)obj_addr;

@bedevere-app
Copy link

bedevere-app bot commented Jun 4, 2024

Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply the skip news label instead.

@@ -59,6 +59,8 @@ extern "C" {
_Py_atomic_store_uint16_relaxed(&value, new_value)
#define FT_ATOMIC_STORE_UINT32_RELAXED(value, new_value) \
_Py_atomic_store_uint32_relaxed(&value, new_value)
#define FT_ATOMIC_EXCHANGE_PTR(value, new_value) \
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not using this now, should I leave it in?

Copy link
Contributor

Choose a reason for hiding this comment

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

Let's remove it then.

@bedevere-app
Copy link

bedevere-app bot commented Jun 4, 2024

Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply the skip news label instead.

Python/structmember.c Outdated Show resolved Hide resolved
Tools/tsan/suppressions_free_threading.txt Outdated Show resolved Hide resolved
Python/structmember.c Outdated Show resolved Hide resolved
Python/structmember.c Outdated Show resolved Hide resolved
Python/structmember.c Outdated Show resolved Hide resolved
Python/structmember.c Outdated Show resolved Hide resolved
Co-authored-by: Erlend E. Aasland <[email protected]>
@bedevere-app
Copy link

bedevere-app bot commented Jun 7, 2024

Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply the skip news label instead.

@dpdani
Copy link
Contributor Author

dpdani commented Jun 7, 2024

@colesbury I can just remove the commented code, it isn't relevant yet.
Or did you want me to change it?

@bedevere-app
Copy link

bedevere-app bot commented Jun 7, 2024

Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply the skip news label instead.

dpdani and others added 2 commits June 11, 2024 16:21
@dpdani
Copy link
Contributor Author

dpdani commented Jun 12, 2024

@colesbury let me know if you want me to make more changes.

Copy link
Contributor

@colesbury colesbury left a comment

Choose a reason for hiding this comment

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

Sorry for the delay - I was on vacation last week.

This LGTM with a minor edit to the test. I'll make the change directly and merge this.

Lib/test/test_free_threading/test_slots.py Outdated Show resolved Hide resolved
@colesbury colesbury added the needs backport to 3.13 bugs and security fixes label Jun 17, 2024
@colesbury colesbury enabled auto-merge (squash) June 17, 2024 18:43
@colesbury colesbury merged commit 362cd26 into python:main Jun 17, 2024
35 checks passed
@miss-islington-app
Copy link

Thanks @dpdani for the PR, and @colesbury for merging it 🌮🎉.. I'm working now to backport this PR to: 3.13.
🐍🍒⛏🤖

miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Jun 17, 2024
…pythonGH-119368)

Fix a race in `PyMember_GetOne` and `PyMember_SetOne` for `Py_T_OBJECT_EX`.
These functions implement `__slots__` accesses for Python objects.
(cherry picked from commit 362cd26)

Co-authored-by: Daniele Parmeggiani <[email protected]>
@bedevere-app
Copy link

bedevere-app bot commented Jun 17, 2024

GH-120655 is a backport of this pull request to the 3.13 branch.

@bedevere-app bedevere-app bot removed the needs backport to 3.13 bugs and security fixes label Jun 17, 2024
colesbury pushed a commit that referenced this pull request Jun 17, 2024
GH-119368) (#120655)

Fix a race in `PyMember_GetOne` and `PyMember_SetOne` for `Py_T_OBJECT_EX`.
These functions implement `__slots__` accesses for Python objects.
(cherry picked from commit 362cd26)

Co-authored-by: Daniele Parmeggiani <[email protected]>
@dpdani
Copy link
Contributor Author

dpdani commented Jun 17, 2024

thank you @colesbury, celebrated with a good beer and good vibes 1️⃣🍻🎉

mrahtz pushed a commit to mrahtz/cpython that referenced this pull request Jun 30, 2024
…python#119368)

Fix a race in `PyMember_GetOne` and `PyMember_SetOne` for `Py_T_OBJECT_EX`.
These functions implement `__slots__` accesses for Python objects.
noahbkim pushed a commit to hudson-trading/cpython that referenced this pull request Jul 11, 2024
…python#119368)

Fix a race in `PyMember_GetOne` and `PyMember_SetOne` for `Py_T_OBJECT_EX`.
These functions implement `__slots__` accesses for Python objects.
estyxx pushed a commit to estyxx/cpython that referenced this pull request Jul 17, 2024
…python#119368)

Fix a race in `PyMember_GetOne` and `PyMember_SetOne` for `Py_T_OBJECT_EX`.
These functions implement `__slots__` accesses for Python objects.
@dpdani dpdani deleted the tsan-pymember branch August 21, 2024 13:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants