Received: by 10.223.185.116 with SMTP id b49csp4450678wrg; Mon, 26 Feb 2018 18:42:49 -0800 (PST) X-Google-Smtp-Source: AG47ELvZ2GIU7Lc08vHZBdtYuWfy7K3kdtcdlHZ8zz4/E9WlqyXRPYS0OOy5eHc2AXHC35W+cDfS X-Received: by 10.99.64.198 with SMTP id n189mr4131924pga.191.1519699368941; Mon, 26 Feb 2018 18:42:48 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519699368; cv=none; d=google.com; s=arc-20160816; b=ufrVDgF/nFXuGXVA8DJD6H7JKSMKo9m9cilGBAfbhG5dJwggOHkGYPeVp1mzrkYqxB fZqZvlmeOXgwSPmqCemXJRbHqMPbdepl9blrvtMWPi6L3wt2MgUrthlM25K4pxImKugy 1dhgWtMoLTBNK+TItl8fnlznf1+q8V98fvkslYqQJAZudIfeWSc/8fvB1VzBQamHlI4t Ff3TVV+jiaANQaByQL0Cp0H4Tazmle4NSAfH8f3Runta0QeMiA7f7UkEACBGZRAkGjX4 aewkCXidrs9JNqW3zAmtdRF7IQcZgM12urOusbtijLyBAcA3rK0fUZMbOV0JAjtbbO/R 5Jsw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-transfer-encoding:content-disposition:mime-version :references:message-id:subject:cc:to:from:date:dkim-signature :arc-authentication-results; bh=3/cDy6/mgqhs+MiovDNM+c/ris/c+yDe5DTJC1/iK/I=; b=bPaJnII6ysuXuV0OedTKdba4F5Ud8w6jXFqWJwZPGM9vWyaYb2xuoSELJa4p3fn9Fi RoI6zm2jg9HQxqirfiWdgTQ2RZ5t7qG7BLaCRY5q2cNpo7abnjEDcexwjNzsj0EwGIVU uBe08gkdecqnBEbX4yz/H4KrM9rAiEI7LJWGz8TuLfH2DmB50F9FZUxEXjZxtU/onZow wzvSZkOl8YTYxpctyLpA8vHtA214dszXCz8JJuObNFGuW3hz9qPyIz+duhObd3aGW8nk vpNFrMDY1epdZhqWfmX9z16o773cq4FcfR7/rF7T5JpWgF6X0bN3PR2Ik+6OqyJO35ll Ev2Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=NOcQfsbk; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id d23si6300934pgn.683.2018.02.26.18.42.33; Mon, 26 Feb 2018 18:42:48 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=NOcQfsbk; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751812AbeB0CJI (ORCPT + 99 others); Mon, 26 Feb 2018 21:09:08 -0500 Received: from mail-pl0-f45.google.com ([209.85.160.45]:33272 "EHLO mail-pl0-f45.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751747AbeB0CJD (ORCPT ); Mon, 26 Feb 2018 21:09:03 -0500 Received: by mail-pl0-f45.google.com with SMTP id c11-v6so7049439plo.0; Mon, 26 Feb 2018 18:09:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:content-transfer-encoding:in-reply-to :user-agent; bh=3/cDy6/mgqhs+MiovDNM+c/ris/c+yDe5DTJC1/iK/I=; b=NOcQfsbkIHKbDSHtnnfDe25o0l1a8B3DD9ZxGfPDoBYI6sDXiONOsU07cW7li+84Tw By0R6jcxPsjecUWpqNKeEoeSkTqZkBl41s8t7CHNvYxMDW0bDwiCWcvcdFH/yOJbqG3g 2En3Hz2shQVgPDBCdYaoTTHvA6ZUJlZVVccPFkCViVkd+ibPh4p1odPFchu9g1FVVFGz O8R/i9FeWfP8xJW+cQPx0mvIa0IS7Btq6GP7fhgbKOG3OmFTuNnRDevyaJloJ+iMBras ZLBcoESHsiPOcpmt6lYyFvwVNG6ZGeb8r3p6z2n6jQCk1Mmnb7aAxVCuWAdySmsw+ePS rn0Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:content-transfer-encoding :in-reply-to:user-agent; bh=3/cDy6/mgqhs+MiovDNM+c/ris/c+yDe5DTJC1/iK/I=; b=hFndBmIP9D4/SrZBCuIzNjKbRgLzswNoVmwQ1PsKBe4KCvuto8mpH7nSPERDKrVTwC N+HdIRI9B27CuA2zcdYWoAqvkyFpkm0i9pA1Au98HQK8H9vvxHU2tPBzScfcK9mO0Bpi nq2Og0Mft9tCwc8hRgo+QljBiv0kMqkEy1YekoojQWRX9Z36PF+FDiNvby8rpyEZwZSp efIrgaE51wcWsLszDDjAkRmwcY8GWEGWPsLanPvOw2BupMXBqCypudMpD7VRN06DXRpS QmNu3sHoYQ8Jj6zjasAJ38q5pw05UbJQSUnv4umu51OTvQQeWNVMtdkWRZ4ECD7iyIUL cSXw== X-Gm-Message-State: APf1xPAoSJy9Ze7xK0ghdUa5PVdE1fl+Jh7cVCMe/EYPpv6Ddk9ZuQDQ Mo07Ph4vMapTK141qaUXfTQ= X-Received: by 2002:a17:902:d205:: with SMTP id t5-v6mr13000461ply.322.1519697342118; Mon, 26 Feb 2018 18:09:02 -0800 (PST) Received: from ast-mbp ([2620:10d:c090:180::1:c617]) by smtp.gmail.com with ESMTPSA id c18sm22528632pfd.100.2018.02.26.18.08.59 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 26 Feb 2018 18:09:01 -0800 (PST) Date: Mon, 26 Feb 2018 18:08:58 -0800 From: Alexei Starovoitov To: =?iso-8859-1?Q?Micka=EBl_Sala=FCn?= Cc: linux-kernel@vger.kernel.org, Alexei Starovoitov , Andy Lutomirski , Arnaldo Carvalho de Melo , Casey Schaufler , Daniel Borkmann , David Drysdale , "David S . Miller" , "Eric W . Biederman" , James Morris , Jann Horn , Jonathan Corbet , Michael Kerrisk , Kees Cook , Paul Moore , Sargun Dhillon , "Serge E . Hallyn" , Shuah Khan , Tejun Heo , Thomas Graf , Tycho Andersen , Will Drewry , kernel-hardening@lists.openwall.com, linux-api@vger.kernel.org, linux-security-module@vger.kernel.org, netdev@vger.kernel.org, Andrew Morton Subject: Re: [PATCH bpf-next v8 05/11] seccomp,landlock: Enforce Landlock programs per process hierarchy Message-ID: <20180227020856.teq4hobw3zwussu2@ast-mbp> References: <20180227004121.3633-1-mic@digikod.net> <20180227004121.3633-6-mic@digikod.net> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20180227004121.3633-6-mic@digikod.net> User-Agent: NeoMutt/20170421 (1.8.2) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Tue, Feb 27, 2018 at 01:41:15AM +0100, Micka?l Sala?n wrote: > The seccomp(2) syscall can be used by a task to apply a Landlock program > to itself. As a seccomp filter, a Landlock program is enforced for the > current task and all its future children. A program is immutable and a > task can only add new restricting programs to itself, forming a list of > programss. > > A Landlock program is tied to a Landlock hook. If the action on a kernel > object is allowed by the other Linux security mechanisms (e.g. DAC, > capabilities, other LSM), then a Landlock hook related to this kind of > object is triggered. The list of programs for this hook is then > evaluated. Each program return a 32-bit value which can deny the action > on a kernel object with a non-zero value. If every programs of the list > return zero, then the action on the object is allowed. > > Multiple Landlock programs can be chained to share a 64-bits value for a > call chain (e.g. evaluating multiple elements of a file path). This > chaining is restricted when a process construct this chain by loading a > program, but additional checks are performed when it requests to apply > this chain of programs to itself. The restrictions ensure that it is > not possible to call multiple programs in a way that would imply to > handle multiple shared values (i.e. cookies) for one chain. For now, > only a fs_pick program can be chained to the same type of program, > because it may make sense if they have different triggers (cf. next > commits). This restrictions still allows to reuse Landlock programs in > a safe way (e.g. use the same loaded fs_walk program with multiple > chains of fs_pick programs). > > Signed-off-by: Micka?l Sala?n ... > +struct landlock_prog_set *landlock_prepend_prog( > + struct landlock_prog_set *current_prog_set, > + struct bpf_prog *prog) > +{ > + struct landlock_prog_set *new_prog_set = current_prog_set; > + unsigned long pages; > + int err; > + size_t i; > + struct landlock_prog_set tmp_prog_set = {}; > + > + if (prog->type != BPF_PROG_TYPE_LANDLOCK_HOOK) > + return ERR_PTR(-EINVAL); > + > + /* validate memory size allocation */ > + pages = prog->pages; > + if (current_prog_set) { > + size_t i; > + > + for (i = 0; i < ARRAY_SIZE(current_prog_set->programs); i++) { > + struct landlock_prog_list *walker_p; > + > + for (walker_p = current_prog_set->programs[i]; > + walker_p; walker_p = walker_p->prev) > + pages += walker_p->prog->pages; > + } > + /* count a struct landlock_prog_set if we need to allocate one */ > + if (refcount_read(¤t_prog_set->usage) != 1) > + pages += round_up(sizeof(*current_prog_set), PAGE_SIZE) > + / PAGE_SIZE; > + } > + if (pages > LANDLOCK_PROGRAMS_MAX_PAGES) > + return ERR_PTR(-E2BIG); > + > + /* ensure early that we can allocate enough memory for the new > + * prog_lists */ > + err = store_landlock_prog(&tmp_prog_set, current_prog_set, prog); > + if (err) > + return ERR_PTR(err); > + > + /* > + * Each task_struct points to an array of prog list pointers. These > + * tables are duplicated when additions are made (which means each > + * table needs to be refcounted for the processes using it). When a new > + * table is created, all the refcounters on the prog_list are bumped (to > + * track each table that references the prog). When a new prog is > + * added, it's just prepended to the list for the new table to point > + * at. > + * > + * Manage all the possible errors before this step to not uselessly > + * duplicate current_prog_set and avoid a rollback. > + */ > + if (!new_prog_set) { > + /* > + * If there is no Landlock program set used by the current task, > + * then create a new one. > + */ > + new_prog_set = new_landlock_prog_set(); > + if (IS_ERR(new_prog_set)) > + goto put_tmp_lists; > + } else if (refcount_read(¤t_prog_set->usage) > 1) { > + /* > + * If the current task is not the sole user of its Landlock > + * program set, then duplicate them. > + */ > + new_prog_set = new_landlock_prog_set(); > + if (IS_ERR(new_prog_set)) > + goto put_tmp_lists; > + for (i = 0; i < ARRAY_SIZE(new_prog_set->programs); i++) { > + new_prog_set->programs[i] = > + READ_ONCE(current_prog_set->programs[i]); > + if (new_prog_set->programs[i]) > + refcount_inc(&new_prog_set->programs[i]->usage); > + } > + > + /* > + * Landlock program set from the current task will not be freed > + * here because the usage is strictly greater than 1. It is > + * only prevented to be freed by another task thanks to the > + * caller of landlock_prepend_prog() which should be locked if > + * needed. > + */ > + landlock_put_prog_set(current_prog_set); > + } > + > + /* prepend tmp_prog_set to new_prog_set */ > + for (i = 0; i < ARRAY_SIZE(tmp_prog_set.programs); i++) { > + /* get the last new list */ > + struct landlock_prog_list *last_list = > + tmp_prog_set.programs[i]; > + > + if (last_list) { > + while (last_list->prev) > + last_list = last_list->prev; > + /* no need to increment usage (pointer replacement) */ > + last_list->prev = new_prog_set->programs[i]; > + new_prog_set->programs[i] = tmp_prog_set.programs[i]; > + } > + } > + new_prog_set->chain_last = tmp_prog_set.chain_last; > + return new_prog_set; > + > +put_tmp_lists: > + for (i = 0; i < ARRAY_SIZE(tmp_prog_set.programs); i++) > + put_landlock_prog_list(tmp_prog_set.programs[i]); > + return new_prog_set; > +} Nack on the chaining concept. Please do not reinvent the wheel. There is an existing mechanism for attaching/detaching/quering multiple programs attached to cgroup and tracing hooks that are also efficiently executed via BPF_PROG_RUN_ARRAY. Please use that instead.