Re: [RFC] Add a prctl to disable ".." traversal in path resolution

Aleksa Sarai
2024-12-13T13:58:44Z

[-- Attachment #1: Type: text/plain, Size: 3767 bytes --]

On 2024-12-11, Al Viro <viro@zeniv.linux.org.uk> wrote:
> On Thu, Dec 12, 2024 at 02:56:59AM +1100, Aleksa Sarai wrote:
>
> > I think RESOLVE_BENEATH is usually more along the lines of what programs
> > that are trying to restrict themselves would want (RESOLVE_IN_ROOT is
> > what extraction tools want, on the other hand) as it only blocks ".."
> > components that move you out of the directory you expect.
> >
> > It also blocks absolute symlinks, which this proposal does nothing about
> > (it even blocks magic-links, which can be an even bigger issue depending
> > on what kind of program we are talking about). Alas, RESOLVE_BENEATH
> > requires education...
>
> So does this prctl, when you get to that - any references to "service manager"
> that might turn it on are contradicted by the "after startup" bit in the
> original posting.
>
> IOW, I very much doubt that this problem is amenable to cargo-culting.

I'm not sure I understand what you're saying -- was this comment
intended for me or Matthew? I was just trying to say that:

1. Most programs that want to access config files or static files to
serve as a web server where there might be ".." symlinks would
probably want RESOLVE_BENEATH behaviour (using the config directory
as the root) because that will only block escaping ".."s (and will
also block absolute symlinks as well as magic-links that can escape
too -- which are also issues that you need to deal with anyway).

2. Blocking this on a process-wide level could cause issues for any
given program because the language's stdlib or runtime could
internally do a ".." open operation, and if that fails the runtime
might decide to crash the program (we've run into issues like this
in Go -- though those were related to errors from pthread_*
functions). If the service manager sets the prctl then if the link
loader or glibc on startup have to resolve ".." due to the way the
system was set up, you would also get errors (and probably a crash).

Obviously, some users would prefer the application crash rather than
resolving a "..", but most would not which is why I'm unsure of how
much this will help solve the problem in practice.

As a devils-advocate proposal, I wonder if we could instead do something
like nosymfollow (so nodotdot?) where you can mark particular mounts
to have this restriction. This could be used to limit all ".."s globally
for a process using a mntns, but it could also be scoped to application
data directories (or to all untrusted directories) without requiring
program changes (the same argument was used for adding nosymfollow when
RESOLVE_NO_SYMLINKS existed).

Obviously there would be problems with this proposal -- unlike
nosymfollow (which is more like nodev or noexec in concept, and so is
more about conceptually restricting access modes of inodes -- even
though nosymfollow is piped through namei), this is would be nd->mnt
impacting how lookups work, which seems kinda ugly and would burn
another MS_ flag (the final one aside from internal ones AFAICS)...

Just food for thought. (I think LOOKUP_NO_DOTDOT / RESOLVE_NO_DOTDOT is
the most usable solution for most programs that really need this, fwiw.)

> _If_ somebody wants to collect actual information about the use patterns,
> something like prctl that would spew a stack trace when running into
> .. would be an obvious approach, but I would strongly object to even
> inserting a tracepoint of that sort into the mainline kernel.

You probably don't need a custom tracepoint, I expect they can get most
of the information they'd need with bpftrace.

--
Aleksa Sarai
Senior Software Engineer (Containers)
SUSE Linux GmbH
<https://www.cyphar.com/>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]