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 French
I 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.
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.
Ok, so apparently, only grp.getgrall() is not thread-safe, and getgrent_r() can be used instead of getgrent() to make the function reentrant. I didn't want to use fgetgrent_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_r is not thread-safe on Linux with glibc. Yuck. And fgetgrent_r isn't a good substitute if groups use LDAP or anything that's not /etc/groups.
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().
Activity
colesbury commented on Nov 2, 2024
Thanks for the bug reports. What is fusil?
devdanzin commented on Nov 2, 2024
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 French
I 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.
colesbury commented on Nov 2, 2024
From a quick glance, it looks like getgrall uses setgrent(), 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.
kumaraditya303 commented on Nov 6, 2024
As a quick fix, I think the module should be marked with Py_MOD_GIL_USED
pythongh-126316: Use critical sections in grp module
pythongh-126316: Use critical sections in grp module
pythongh-126316: Use critical sections in grp module
vstinner commented on Nov 6, 2024
I wrote a fix #126488 using @critical_section.
kumaraditya303 commented on Nov 6, 2024
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.
ZeroIntensity commented on Nov 6, 2024
Yeah, this will still race if there are subinterpreters using grp at the same time. Kumar's suggestion is probably the way to go.
14 remaining items
vstinner commented on Nov 6, 2024
Ok, so apparently, only grp.getgrall() is not thread-safe, and getgrent_r() can be used instead of getgrent() to make the function reentrant. I didn't want to use fgetgrent_r() to not have to open a file (which file?).
In short, I wrote PR gh-126506 to fix the issue using getgrent_r().
colesbury commented on Nov 6, 2024
Ugh, getgrent_r is not thread-safe on Linux with glibc. Yuck. And fgetgrent_r isn't a good substitute if groups use LDAP or anything that's not /etc/groups.
I guess locks it is... at least for Linux.
vstinner commented on Nov 20, 2024
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().
pythongh-126316: Make grp.getgrall() thread-safe: add a mutex
pythongh-126316: Make grp.getgrall() thread-safe: add a mutex
gh-126316: Make grp.getgrall() thread-safe: add a mutex (#127055)
pythongh-126316: Make grp.getgrall() thread-safe: add a mutex (python…
vstinner commented on Nov 21, 2024
Fixed by change 3c2bd66. Backport to 3.13 will follow.
vstinner commented on Nov 21, 2024
Thank you @devdanzin for your bug report.
[3.13] gh-126316: Make grp.getgrall() thread-safe: add a mutex (#127055…
pythongh-126316: Make grp.getgrall() thread-safe: add a mutex (python…