Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757988AbcJQNFG (ORCPT ); Mon, 17 Oct 2016 09:05:06 -0400 Received: from mail-vk0-f52.google.com ([209.85.213.52]:35213 "EHLO mail-vk0-f52.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754664AbcJQNDP (ORCPT ); Mon, 17 Oct 2016 09:03:15 -0400 MIME-Version: 1.0 In-Reply-To: References: <1476455305-35554-1-git-send-email-mnissler@chromium.org> <20161014145515.GA19539@ZenIV.linux.org.uk> <20161014150017.GB19539@ZenIV.linux.org.uk> From: Mattias Nissler Date: Mon, 17 Oct 2016 15:02:52 +0200 X-Google-Sender-Auth: kxBXlcy8dzkYz5yoEa38SfRZYZM Message-ID: Subject: Re: [RFC] [PATCH] Add a "nolinks" mount option. To: Al Viro Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 5329 Lines: 98 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 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 wrote: >> On Fri, Oct 14, 2016 at 5:00 PM, Al Viro 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...