pub fn resolves_within(path: &Path, root: &Path) -> boolExpand description
Whether path still lands inside root once symlinks are followed.
A lexical starts_with check is not containment. It answers “does this
string begin with that string”, and a symlink at <root>/link pointing at
/ satisfies it while pointing anywhere on the filesystem. Every file tool
in Leviath was relying on exactly that check.
path need not exist - a write_file creating a new file is the common
case. The deepest existing ancestor is canonicalized (which is where any
symlink lives) and the unresolved tail re-appended, so a not-yet-created file
under a symlinked parent is still caught.
root is canonicalized here too rather than trusted: on macOS /tmp is a
symlink to /private/tmp, so a root that was stored uncanonicalized would
never prefix-match a canonicalized path and every access would be refused.
This is not TOCTOU-proof - a symlink planted between this call and the
subsequent open still wins. Closing that needs openat/O_NOFOLLOW
throughout. This stops the planted-symlink case, which is the one an agent
can arrange for itself.