Received: by 2002:a05:6a10:f347:0:0:0:0 with SMTP id d7csp1107076pxu; Mon, 23 Nov 2020 11:48:32 -0800 (PST) X-Google-Smtp-Source: ABdhPJw/+7XAA9KP2eR17dMQ8paINcnEIxGZpLnDnPY3KdrlECnTr+LRl/B5JT1DeXFx/t8RuhdB X-Received: by 2002:a17:906:7b82:: with SMTP id s2mr1052712ejo.435.1606160911863; Mon, 23 Nov 2020 11:48:31 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1606160911; cv=none; d=google.com; s=arc-20160816; b=ELLPtMuaPQ2PoSP/f1SPye+fwD3lx8Dg712SAQsIvGCKsCJWR7Ey1cEau/tccpzVvu YzUEg+TRxoR6gJB7lnUTNi9aUrCIuLPsZSchpXRsNcylYPrtXxSmr/5aW08BUFRTtjmg H7g5ZpeHmX+hr5Xo6ArmnTNP0mBT2hoA4Zm7qo7fRoLI+8w+jufdG+DafwhDeJ56pJnz sEpbgCtkoh6HzlUa+SgLGM8DJxSXozqcQWSWFHNqFHMJgyWz7BKDIOwFeeMcChzfTm+6 G6C9XH7DsuqI7ELZ8InI0weV6thVOKJrM1m1676L2AWVOV9vvqmvMg1TvOSmcWNgPews XkEA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:cc:to:subject :message-id:date:from:in-reply-to:references:mime-version :dkim-signature; bh=WkkyfzYc5dkm/KIiF9W4jRT3BRx+3sqZpO+ldzSWHAU=; b=mrzcRnetusDpId3gYtdTjujsbCJoqnGhGP9UqmyJ54se/mULkLtITbdrnr3X9Fjw2v CIXiOUe9zF8z+7auogEh1q78rv0Y1BQU1qlMKnyOF719ENLirS5V5QCTta/E6RqjBwRx ICAeyXLIdUXm1Zx9JbxZpjwKTNbm9lTgLUmwH6uSDKb8P83XokIhMJSg0iufYxE3tbcW sXSxT7Z+nqtT49CiThXxPf2I2dsG1K27+DNUPD01qusRAktg3+e7bFKUL4dVOpm+zT+F tC91siMP6vUwG5wLnP/viN3n3NeQEQA08VRiqncOeWM6nOFKsFN4qI5Dku2gSZItILh5 dF9Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=ucprSht0; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id c9si7342629edn.152.2020.11.23.11.48.07; Mon, 23 Nov 2020 11:48:31 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=ucprSht0; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730962AbgKWTom (ORCPT + 99 others); Mon, 23 Nov 2020 14:44:42 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38400 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730575AbgKWTol (ORCPT ); Mon, 23 Nov 2020 14:44:41 -0500 Received: from mail-lf1-x144.google.com (mail-lf1-x144.google.com [IPv6:2a00:1450:4864:20::144]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 26766C061A4D for ; Mon, 23 Nov 2020 11:44:40 -0800 (PST) Received: by mail-lf1-x144.google.com with SMTP id t6so9318054lfl.13 for ; Mon, 23 Nov 2020 11:44:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc:content-transfer-encoding; bh=WkkyfzYc5dkm/KIiF9W4jRT3BRx+3sqZpO+ldzSWHAU=; b=ucprSht07o3L8qhZLLc2Vt4PubCLLYecCKNAauQVntt/WOQx0TnUKdvhSMo4O3kPUB uaUTYfr9u7VuLEvtbM35aoZwakgOWHYVHjw4Mng7Nx7VrQbWv4Tt/KS5ugKh9SaGeFX2 RVWHUO8H6oE35g5xy4ExNT0J9tz1RPg7b9HOQlsjqvp5KHt1ZdUObef9cJxmfTjtGs3e thKIj2KnAjmAnht0O8u+JMUIDM9eFbTD7ieYfOqhRhtEVosbjAvqv+gyPmolJ+wWqzdt 5ZUswM45maUXB35BfcN7RSu535krwgoOUgZM4t2JGI8pMMDiwiDnaCVZppVOab7LjX70 E/mA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc:content-transfer-encoding; bh=WkkyfzYc5dkm/KIiF9W4jRT3BRx+3sqZpO+ldzSWHAU=; b=rYrfDL2sWVW08InV32JmQRzsYPanxIzEKGe7gLVSuUkGPzzUcg6WTxWYSKtQv1zgDN xFZXCK2P9T7sh+WcqhqkmQvTwD5LscHo9+BH9yWSjU4JUWJCPbnafc8d2vrA7IkLHa+f 2gmTqmSvqF2wFCYWrijgW9O2WohZAkdUP6xHE5HSNkmThnZYEsNNsiM9YM6VHSoC4Wcx sDlFqFMM7EGhP34KPAOGxczHEYYSKn7KA++2E3K7xc8JD1KUPlwL54e/IMwVToF685Gy dL4L0weFmzaIyZ+DbSTzoA2oqe7mHF3R6OzMur0Jm5e6hUpqtB0+dhy2A9OClPTAB8H5 49Wg== X-Gm-Message-State: AOAM531qTs1dyjdjsVWSgRky58MHKU5qS6uOb3WC6ePT5tqzLPo3oIQX /LwY+be8tkMVPeWt9ujahZGMGmaK7Y4EY3gU39BFgA== X-Received: by 2002:ac2:5a49:: with SMTP id r9mr259465lfn.381.1606160678276; Mon, 23 Nov 2020 11:44:38 -0800 (PST) MIME-Version: 1.0 References: <20201112205141.775752-1-mic@digikod.net> <20201112205141.775752-8-mic@digikod.net> <1d524ea9-85eb-049c-2156-05cad6d6fcfd@digikod.net> In-Reply-To: <1d524ea9-85eb-049c-2156-05cad6d6fcfd@digikod.net> From: Jann Horn Date: Mon, 23 Nov 2020 20:44:11 +0100 Message-ID: Subject: Re: [PATCH v24 07/12] landlock: Support filesystem access-control To: =?UTF-8?B?TWlja2HDq2wgU2FsYcO8bg==?= Cc: James Morris , "Serge E . Hallyn" , Al Viro , Andy Lutomirski , Anton Ivanov , Arnd Bergmann , Casey Schaufler , Jeff Dike , Jonathan Corbet , Kees Cook , Michael Kerrisk , Richard Weinberger , Shuah Khan , Vincent Dagonneau , Kernel Hardening , Linux API , linux-arch , "open list:DOCUMENTATION" , linux-fsdevel , kernel list , "open list:KERNEL SELFTEST FRAMEWORK" , linux-security-module , "the arch/x86 maintainers" , =?UTF-8?B?TWlja2HDq2wgU2FsYcO8bg==?= Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Sat, Nov 21, 2020 at 11:06 AM Micka=C3=ABl Sala=C3=BCn = wrote: > On 21/11/2020 08:00, Jann Horn wrote: > > On Thu, Nov 12, 2020 at 9:52 PM Micka=C3=ABl Sala=C3=BCn wrote: > >> Thanks to the Landlock objects and ruleset, it is possible to identify > >> inodes according to a process's domain. To enable an unprivileged > >> process to express a file hierarchy, it first needs to open a director= y > >> (or a file) and pass this file descriptor to the kernel through > >> landlock_add_rule(2). When checking if a file access request is > >> allowed, we walk from the requested dentry to the real root, following > >> the different mount layers. The access to each "tagged" inodes are > >> collected according to their rule layer level, and ANDed to create > >> access to the requested file hierarchy. This makes possible to identi= fy > >> a lot of files without tagging every inodes nor modifying the > >> filesystem, while still following the view and understanding the user > >> has from the filesystem. > >> > >> Add a new ARCH_EPHEMERAL_INODES for UML because it currently does not > >> keep the same struct inodes for the same inodes whereas these inodes a= re > >> in use. > >> > >> This commit adds a minimal set of supported filesystem access-control > >> which doesn't enable to restrict all file-related actions. This is th= e > >> result of multiple discussions to minimize the code of Landlock to eas= e > >> review. Thanks to the Landlock design, extending this access-control > >> without breaking user space will not be a problem. Moreover, seccomp > >> filters can be used to restrict the use of syscall families which may > >> not be currently handled by Landlock. > >> > >> Cc: Al Viro > >> Cc: Anton Ivanov > >> Cc: James Morris > >> Cc: Jann Horn > >> Cc: Jeff Dike > >> Cc: Kees Cook > >> Cc: Richard Weinberger > >> Cc: Serge E. Hallyn > >> Signed-off-by: Micka=C3=ABl Sala=C3=BCn > >> --- > >> > >> Changes since v23: > >> * Enforce deterministic interleaved path rules. To have consistent > >> layered rules, granting access to a path implies that all accesses > >> tied to inodes, from the requested file to the real root, must be > >> checked. Otherwise, stacked rules may result to overzealous > >> restrictions. By excluding the ability to add exceptions in the sam= e > >> layer (e.g. /a allowed, /a/b denied, and /a/b/c allowed), we get > >> deterministic interleaved path rules. This removes an optimization > > > > I don't understand the "deterministic interleaved path rules" part. > > I explain bellow. > > > > > > > What if I have a policy like this? > > > > /home/user READ > > /home/user/Downloads READ+WRITE > > > > That's a reasonable policy, right? > > Definitely, I forgot this, thanks for the outside perspective! > > > > > If I then try to open /home/user/Downloads/foo in WRITE mode, the loop > > will first check against the READ+WRITE rule for /home/user, that > > check will pass, and then it will check against the READ rule for /, > > which will deny the access, right? That seems bad. > > Yes that was the intent. > > > > > > > The v22 code ensured that for each layer, the most specific rule (the > > first we encounter on the walk) always wins, right? What's the problem > > with that? > > This can be explained with the interleaved_masked_accesses test: > https://github.com/landlock-lsm/linux/blob/landlock-v24/tools/testing/sel= ftests/landlock/fs_test.c#L647 > > In this case there is 4 stacked layers: > layer 1: allows s1d1/s1d2/s1d3/file1 > layer 2: allows s1d1/s1d2/s1d3 > denies s1d1/s1d2 > layer 3: allows s1d1 > layer 4: allows s1d1/s1d2 > > In the v23, access to file1 would be allowed until layer 3, but layer 4 > would merge a new rule for the s1d2 inode. Because we don't record where > exactly the access come from, we can't tell that layer 2 allowed access > thanks to s1d3 and that its s1d2 rule was ignored. I think this behavior > doesn't make sense from the user point of view. Aah, I think I'm starting to understand the issue now. Basically, with the current UAPI, the semantics have to be "an access is permitted if, for each policy layer, at least one rule encountered on the pathwalk permits the access; rules that deny the access are irrelevant". And if it turns out that someone needs to be able to deny access to specific inodes, we'll have to extend struct landlock_path_beneath_attr. That reminds me... if we do need to make such a change in the future, it would be easier in terms of UAPI compatibility if landlock_add_rule() used copy_struct_from_user(), which is designed to create backwards and forwards compatibility with other version of UAPI headers. So adding that now might save us some headaches later. > In the v24, access to file1 would only be allowed with layer 1. The > layer 2, would deny access to file1 because of the s1d2 rule. This makes > the reasoning consistent and deterministic whatever the layers are, > while storing the same access and layer bits. But I agree that this may > not be desirable. > > In a perfect v25, file1 should be allowed by all these layers. I didn't > find a simple solution to this while minimizing the memory allocated by > rule (cf. struct landlock_rule: mainly 32-bits for access rights and > 64-bits for the layers that contributed to this ANDed accesses). I would > like to avoid storing 32-bits access rights per stacked layer. Do you > see another solution? I don't think you can avoid storing the access rights per layer unless you actually merge the layers when setting up the ruleset (which would be messy). But I don't think that's a big problem. A straightforward implementation might become inefficient if you stack too many policy layers, but I don't think that's a problem for an initial implementation - the common usecase is probably going to be a single layer, or maybe two, or something like that? If you had a ton of layers, most of them would likely specify the same access permissions - so one possible optimization might be to use the current representation if all rules matching the inode specify the same permissions, and use a different representation otherwise. But I don't think such an optimization is necessary at this point.