Repository navigation
grp is not thread safe #126316
Description
Activity
- addedtype-crashA hard crash of the interpreter, possibly with a core dumpA hard crash of the interpreter, possibly with a core dump
on Nov 1, 2024 - addedextension-modulesC modules in the Modules dirC modules in the Modules dir
on Nov 2, 2024 Thanks for the bug reports. What is fusil?
What is fusil?
fusil is a fuzzer written in Python by Victor Stinner around 2007 I think. Somehow it has been memory holed, but some references can still be found in the WayBack Machine:
RTD
Home
List of Python bugs found (way back when)
Articles by Victor in FrenchI used it in the old days to find a couple of issues and was curious whether it could still find some. The source is still available even if not so easy to find. I got it, fixed some issues, added a bit of (very rough) threading, and let it search for crashes.
Not sure what to do with the code, first I'd like to know why it disappeared. But I'd be happy to share privately.
From a quick glance, it looks like
getgrallusessetgrent(),getgrent(),endgrent(), which are not thread-safe on Linux.The macOS implementations appear to be thread-safe
Linux with glibc 2.19+ has
fgetgrent_r, which is thread-safe.As a quick fix, I think the module should be marked with
Py_MOD_GIL_USEDAs a quick fix, I think the module should be marked with Py_MOD_GIL_USED
I wrote a fix #126488 using
@critical_section.I don't think that would fix the issue, there can be two instances of module which can race with each other. The correct fix would be to have a global lock which would serialize calls across modules.
Yeah, this will still race if there are subinterpreters using
grpat the same time. Kumar's suggestion is probably the way to go.14 remaining items
Ok, so apparently, only
grp.getgrall()is not thread-safe, andgetgrent_r()can be used instead ofgetgrent()to make the function reentrant. I didn't want to usefgetgrent_r()to not have to open a file (which file?).In short, I wrote PR gh-126506 to fix the issue using getgrent_r().
Ugh,
getgrent_ris not thread-safe on Linux with glibc. Yuck. Andfgetgrent_risn't a good substitute if groups use LDAP or anything that's not/etc/groups.I guess locks it is... at least for Linux.
- added3.13only security fixesonly security fixes3.14bugs and security fixesbugs and security fixes
on Nov 16, 2024 I guess locks it is... at least for Linux.
I proposed
@critical_section(PR gh-126488), but @ZeroIntensity wrote that it's not correct since it doesn't solve the problem for subinterpreters which have their GIL.I proposed adding PyMutex (PR gh-126504), but @colesbury is afraid of deadlock because "mkgrent() function calls a into the Python API". Maybe I can release the mutex while calling
mkgrent()?I also wrote PR gh-126506 to use getgrent_r(), but @colesbury noticed that getgrent_r() is not thread-safe on Linux, so it doesn't solve this issue.
I suppose that the only solution is to use a lock and release it around
mkgrent().- added 4 commits that reference this issue
on Nov 20, 2024 Fixed by change 3c2bd66. Backport to 3.13 will follow.
Thank you @devdanzin for your bug report.
Metadata
Metadata
Assignees
Labels
Projects
- StatusShow more project fieldsDone
Crash report
What happened?
It's possible to crash
grpin a no-gil build by repeatedly calling functions in threads, it only happens withPYTHON_GIL=0.Backtrace is:
Found using fusil by @vstinner.
CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux
Output from running 'python -VV' on the command line:
Python 3.14.0a1+ experimental free-threading build (heads/main:d467d9246c, Nov 1 2024, 09:05:56) [GCC 11.4.0]
Linked PRs