Repository navigation
Keep plugin directories inside the top directory through links - #3489
Merged
xirvik merged 4 commits intoOct 30, 2026
Merged
Conversation
setsettings checked sdirectory with correctDirectory(), which compares the directory as written. A download added without a directory of its own is written to rtorrent's default directory through any symbolic link along it, so a link inside $topDirectory that points out of it had those downloads written wherever it pointed. sdirectory now also has to pass rTorrent::isInsideTopDirectory(), as add directories do; a refused value is skipped as before. The XML-RPC proxy already resolves links for directory.default.set.
The output directory was checked with correctDirectory(), which compares it as written, and only when it came from the plugin's settings. unrar and unzip write through any symbolic link along it, so a link inside $topDirectory that points out of it had archives extracted wherever it pointed, and a download's own directory reached through such a link was not checked at all. The final directory -- the setting with the label and name added, or the download's own directory -- now has to pass rTorrent::isInsideTopDirectory() before the extraction is started, in the automatic unpack and in both manual ones. A manual unpack that is refused says so.
create checked the path it hashes with correctDirectory(), which compares it as written, and Torrent::scandir() followed every symbolic link in a folder except those back into the folder itself. A link inside $topDirectory that points out of it -- the path itself, or a link inside a folder -- had the file it points at hashed, and with "start seeding" served by rtorrent. action.php now also requires the path to pass rTorrent::isInsideTopDirectory() and answers "Incorrect directory" as before, and Torrent::scandir() leaves out a link that resolves outside the top directory. A top directory of "/" is unchanged.
The finished and watch directories were checked with correctDirectory(), which compares them as written, and only when the settings were saved. The move, the scan, the touch and the load follow symbolic links, so a link inside $topDirectory that points out of it, made at any time, had finished downloads moved and torrents loaded and removed wherever it pointed. The directories are now checked with rTorrent::isInsideTopDirectory() where they are used: check.php leaves a download where its data is when its destination resolves outside the top directory, move.php does not move, copy or link there, and watch.php skips a watch directory, a torrent reached through a link and a data directory that resolve outside it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
#3488 fixed datadir; #3474 also names autotools, unpack and create. Each checked its directory with
correctDirectory(), which compares it as written, while the operations follow symbolic links. A link inside$topDirectorythat points out of it had finished downloads moved, archives extracted, files hashed (and, once seeded, served) and watched torrents loaded and removed wherever it pointed. httprpc'ssetsettingshad the same gap for rTorrent's default directory, where downloads added without a directory of their own are written.What changes
Each directory is checked with
rTorrent::isInsideTopDirectory()where it is used rather than only where it is saved, since a link can be made after the settings are: autotools'check.php,move.phpandwatch.php(watch directory, torrents reached through a link, data directory); unpack's final output directory in the automatic and both manual unpacks; create's path; httprpc'ssdirectory.Torrent::scandir()leaves out a link that resolves outside the top directory. A top directory of/and a remote rTorrent are unchanged.How to test
cd tests && bash php-test.sh.tests/plugins/{httprpc/HttprpcSetDirectoryTest,unpack/UnpackTopDirectoryTest,create/CreateTopDirectoryTest,autotools/AutoToolsTopDirectoryTest}.phpbuild a real tree with a link out, a link that stays inside and a dangling link, and drive the plugins' own scripts; each fails without its fix, and the inside cases pass either way.Closes #3474.