On 2024-03-19 16:53, Pádraig Brady wrote: > but would appreciate a quick review of the fts_level usage in the second > patch. > > thanks, > Pádraig
In utilities that perform tree walks, there may be reasons why not following links is a useful option, but it can't be relied on for security. Suppose Alice wants to traverse path /a/b/c where malicious Mallory is in control of component b. If Alice checks whether b is a symlink and refuses to follow it, she suffers from a TOCtoTOU race. The b component can be a directory at the time Alice checks, but just before Alice subsequently traverses it, Mallory swaps it for a symlink. (Sure, not following symlinks will defend against a passive attack, whereby a user just plants a malicious symlink in a directory they control and then waits.) To do this correctly, we need a path-resolution function that carefully avoids following any insecure/untrusted path component. (This could be built into a secure version of nftw, as an optional behavior; nftw itself should have a flag to not follow unsafe links, implemented with the utmost security.) For this, open openat() with O_NOFOLLOW | O_PATH can be used to go from component to component. Nearly two years ago, I experimented with a solution that doesn't use openat, but only classic POSIX calls, which I call safepath: https://www.kylheku.com/cgit/safepath/ The basic idea is that we can traverse the path left to right, and perform a security check at each step: "does a user other than me control this directory, such that the next path component could go anywhere at any time?" If the answer is no, the resolution can proceed to the next component. Under this view, symlinks can be safe. E.g. root can follow a symlink that only root can modify.