Re: [RFC] [PATCH] Add a "nolinks" mount option.

From: Mattias Nissler
Date: Mon Oct 17 2016 - 09:05:09 EST


OK, no more feedback thus far. Is there generally any interest in a
mount option to avoid path name aliasing resulting in target file
confusion? Perhaps a version that only disables symlinks instead of
also hard-disabling files hard-linked to multiple locations (those are
much lower risk for the situation I care about)?

If there is interest, I'm happy to iterate the patch until it's
accepted. If there's no interest, that's fine too - I'll then likely
resort to moving the restrictions desired for Chrome OS into an LSM we
compile into our kernels.

On Fri, Oct 14, 2016 at 6:22 PM, Mattias Nissler <mnissler@xxxxxxxxxxxx> wrote:
> Forgot to mention: I realize my motivation is very specific to Chrome
> OS, however the nolinks option seemed useful also as a mitigation to
> generic privilege escalation symlink attacks, for cases where
> disabling symlinks/hardlinks is acceptable.
>
> On Fri, Oct 14, 2016 at 5:50 PM, Mattias Nissler <mnissler@xxxxxxxxxxxx> wrote:
>> On Fri, Oct 14, 2016 at 5:00 PM, Al Viro <viro@xxxxxxxxxxxxxxxxxx> wrote:
>>>
>>> On Fri, Oct 14, 2016 at 03:55:15PM +0100, Al Viro wrote:
>>> > > Setting the "nolinks" mount option helps prevent privileged writers
>>> > > from modifying files unintentionally in case there is an unexpected
>>> > > link along the accessed path. The "nolinks" option is thus useful as a
>>> > > defensive measure against persistent exploits (i.e. a system getting
>>> > > re-exploited after a reboot) for systems that employ a read-only or
>>> > > dm-verity-protected rootfs. These systems prevent non-legit binaries
>>> > > from running after reboot. However, legit code typically still reads
>>> > > from and writes to a writable file system previously under full
>>> > > control of the attacker, who can place symlinks to trick file writes
>>> > > after reboot to target a file of their choice. "nolinks" fundamentally
>>> > > prevents this.
>>> >
>>> > Which parts of the tree would be on that "protected" rootfs and which would
>>> > you mount with that option? Description above is rather vague and I'm
>>> > not convinced that it actually buys you anything. Details, please...
>>
>> Apologies for the vague description, I'm happy to explain in detail.
>>
>> In case of Chrome OS, we have all binaries on a dm-verity rootfs, so
>> an attacker can't modify any binaries. After reboot, everything except
>> the rootfs is mounted noexec, so there's no way to re-gain code
>> execution after reboot by modifying existing binaries or dropping new
>> ones.
>>
>> We've seen multiple exploits now where the attacker worked around
>> these limitations in two steps:
>>
>> 1. Before reboot, the attacker sets up symlinks on the writeable file
>> system (called "stateful" file system), which are later accessed by
>> legit boot code (such as init scripts) after reboot. For example, an
>> init script that copies file A to B can be abused by an attacker by
>> symlinking or hardlinking B to a location C of their choice, and
>> placing desired data to be written to C in A. That gives the attacker
>> a primitive to write data of their choice to a path of their choice
>> after reboot. Note that this primitive may target locations _outside_
>> the stateful file system the attacker previously had control of.
>> Particularly of interest are targets on /sys, but also tmpfs on /run
>> etc.
>>
>> 2. The second step for a successful attack is finding some legit code
>> invoked in the boot flow that has a vulnerability exploitable by
>> feeding it unexpected data. As an example, there are Linux userspace
>> utilities that read config from /run which may contain shell commands
>> the the utility executes, through which the attacker can gain code
>> execution again.
>>
>> The purpose of the proposed patch is to raise the bar for the first
>> step of the attack: Writing arbitrary files after reboot. I'm
>> intending to mount the stateful file system with the nolinks option
>> (or otherwise prevent symlink traversal). This will help make sure
>> that any legit writes taking place during boot in init scripts etc. go
>> to the files intended by the developer, and can't be redirected by an
>> attacker.
>>
>> Does this make more sense to you?
>>
>>>
>>>
>>> PS: what the hell do restrictions on _following_ symlinks have to _creating_
>>> hardlinks? I'm trying to imagine a threat model where both would apply or
>>> anything else beyond the word "link" they would have in common...
>>
>> The restriction is not on _creating_ hard links, but _opening_
>> hardlinks. The commonality is in the confusion between the file you're
>> meaning to write vs. the file you actually end up writing to, which
>> stems from the fact that as things stand a file can be accessible on
>> other paths than its canonical one. For Chrome OS, I'd like to get to
>> a point where most privileged code can only access a file via its
>> canonical name (bind mounts are an OK exception as they're not
>> persistent, so out of reach for manipulation).
>>
>>>
>>> The one you've described above might have something to do with the first
>>> one (modulo missing description of the setup you have in mind), but it
>>> clearly has nothing to do with the second - attackers could've created
>>> whatever they wanted while the fs had been under their control, after all.
>>> Doesn't make sense...