-
Notifications
You must be signed in to change notification settings - Fork 566
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
Thread creation while a directory handle is open does a fchdir, affecting other threads (race condition) #23010
Comments
I had copied an incorrect version of the script. This is now the correct one. Note that as I said in a comment in the Debian bug, if I change the script to do opendir DIR, $dir or die "$0: opendir failed ($!)\n";
my @files = readdir DIR;
foreach my $file (@files)
{
$nthreads < $maxthreads or join_threads;
$nthreads++ < $maxthreads or die "$0: internal error\n";
threads->create(\&stat_test, $file);
}
closedir DIR or die "$0: closedir failed ($!)\n"; then the failures still occur. But if I change it to do opendir DIR, $dir or die "$0: opendir failed ($!)\n";
my @files = readdir DIR;
closedir DIR or die "$0: closedir failed ($!)\n";
foreach my $file (@files)
{
$nthreads < $maxthreads or join_threads;
$nthreads++ < $maxthreads or die "$0: internal error\n";
threads->create(\&stat_test, $file);
} (i.e. moving the |
Yeah. There's a real bug there that they were fixing, but this feels like the wrong solution. It needs a new |
Well, as part of this bug, there is a second bug: in There are other issues with the current |
When a thread is created while a directory handle is open, a
fchdir
is done (according tostrace
output under GNU Linux), affecting other threads. The issue can be reproduced on various platforms (GNU Linux, Android, macOS) with the following testcase, wherestat
randomly fails with a "No such file or directory" error (ENOENT
):In short, for each file in the directory, a thread is created, which does 100
stat
on the file. This script uses no more than 2 worker threads at the same time by default: the main loop waits for a worker thread to terminate before a new one is created.To reproduce the issue more easily, create a directory with many files:
Then run this script with the directory name (e.g.
test
) in argument. Failures are much more likely to occur withstrace -f
(as usual, also use the-o
option to redirect the output to a file).In the
strace
output under GNU Linux, one can see for instance:This excerpt shows 3
newfstatat
on the same filetest/275
. The first two succeeded, but the third one failed withENOENT
(No such file or directory).I think that this bug comes from the fix of #10387 (old rt.perl.org bug 75174), 11a11ec, which does a
fchdir
inPerl_dirp_dup
fromsv.c
, so Perl versions since 2010 should be affected, and this issue is still present in the repository. As the current working directory is global to the process, this affects other threads. Even though the current working directory is set back to the old value, this is a race condition, which can affect real scripts (this is how I identified this bug). Note that this is a vulnerability as the directory may be an untrusted one, so really bad things could happen (even when the directory is trusted, BTW).I could reproduce the issue under GNU Linux with several file systems (ext4, tmpfs, NFS), and also on my Android phone (using Termux) and on a macOS machine (from the cfarm project).
Past bug reports:
The text was updated successfully, but these errors were encountered: