-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Security fix for remove_dir_all may have introduced a regression how filesystem loops are handled #93129
Comments
As I wrote in the PR in my opinion there should be no loops. Bind mounts on Linux and directory hardlinks (available for Macos only) are not allowed to loop and we are not descending into symlinked dirs because we open them with But of course running out of file descriptors is currently a problem. I have a follow-up draft branch ready which fixes that differently from #88731 (going up using |
I would love to merge that with your work somehow so we don't run into conflicts or one of us incorporates the work of the other. Either way is fine for me. I will open the draft PR tomorrow so you can have a look and then we can decide on how to proceed. |
My approach is keeping a fixed-size stack of some directory fds open so it go back up and recurse into siblings most of the time and only has to re-walk path occasionally. Using |
I have tried to reproduce loops with bind mounts and overlayfs and it looks I cannot. That leaves the possibility of FUSE or maybe mounted network filesystems containing them, which should make this an even smaller edge-case. |
I am using an iterative version too (@cuviper did the first conversion). I added the fixed deque inspired by your work and then replaced the iterated |
A HashSet with visited inodes or (device, inode) pairs could easily be added for cycle detection. |
I assume there's still a fallback in case the |
Currently there is no fallback for going back up via |
A parent directory getting moved while we're somewhere deeper in the tree, then it won't match the original parent. |
Ah OK. If the inode comparison fails my current implementation returns an error, just as with many other concurrent modification races (added files/directories at the right time cause ENOTEMPTY going up, deleted files/directories cause ENOENT on openat() or unlinkat()). |
Good point, if it gets moved then unlinking would fail anyway after we go back up. Then a fallback isn't necessary. |
Running out of file descriptors should result in a proper error with |
Normally traversing very deep directory trees (e.g. created by bind mounts or FUSE) will result in ENAMETOOLONG or ELOOP.
The fix in #93110, #93112 and #93111 switches to using
-at
syscalls and keeping file descriptors for each child directory that's being descended into. But this way we loose loop detection (as far as I can tell), which means the process will run out of stack space or file descriptors instead of returning a proper error.#88731 was already open which does contain proper loop handling.
The text was updated successfully, but these errors were encountered: