From patchwork Fri Dec 8 15:51:13 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?G=C3=BCnther_Noack?= X-Patchwork-Id: 13485587 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="OiI+sykI" Received: from mail-yw1-x1149.google.com (mail-yw1-x1149.google.com [IPv6:2607:f8b0:4864:20::1149]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 675071734 for ; Fri, 8 Dec 2023 07:51:30 -0800 (PST) Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-5d942a656b7so27780487b3.1 for ; Fri, 08 Dec 2023 07:51:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1702050689; x=1702655489; darn=vger.kernel.org; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:from:to:cc:subject:date :message-id:reply-to; bh=ez7w5bWzPjceJz/ogLgu//o7gCYQ9rmHzEg4Eyh+tpY=; b=OiI+sykI7ABTNfFFiWg+BXkPOh0zfU0Yc1b4kDzirWYqcmSP1JByG7wu6XtCj+PTgI /gj2zeKvjykqUOOiRFxGm+ZfJVHNwaGBXyZGx06o5CaMU6I4FsgH0AW14JbOUhmqnsT9 dKZT6hLKU39MDeUwjJ2GJbABX9REzX18CeXvbtFqCJ5FON+Ex/O5KWpkF+7pnyBdSo5l ct/Nm7iaXJMiL2xBEHciyQ3ERdsJz9UYrF71eFz9IZAFRdM/0QtnncRicy3nNeGbU8iQ rPizPtF5q6dUyTZg0l67Opivof5PsO5egfzxgK8k0cI8OGnAziKhhyKJzCULppKEAElt jTDg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702050689; x=1702655489; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=ez7w5bWzPjceJz/ogLgu//o7gCYQ9rmHzEg4Eyh+tpY=; b=BGCEttq49xKk95IoQOlGDQmFeEn8qExtPMj0lQcYsFZkeGfrKlsLOB6/cLfZuQt33r zDEeybl8f8pTlVWDgz8FMd0+pnB3eq6+pDyXgIaCvmXC0xui4ZwjZsMKqVAwL+fq2u9o 0f62sI+BoUoJiLeuEAQc4NQcvyqE0NskJC6hwNHSR2gNNmM7aBiKhRA8UN44msGOOrR8 7gnIS2NtqEb1LP5ETYX/O4WPixcrQpiZC6iPPuheH/HM8ZZEHEtfzKxheNwyISkpmh3G pp64t6K+sqFrtDq+4DKWGS3sAS6ERZgqpmzKtkK04k6ZtuZjC7zC8KR5HI4SixU3NiHy cRZQ== X-Gm-Message-State: AOJu0YzSMZA0FNSfzEvcrLhOZcmm4qnH8FJx7oEqTvHb6nYpaRYDPahP calrf4mHbE9lnaEdoRWddounLcX0f5s187w7V5rWpfgvCopX8HtXV/FVwAHGsHT95A+hqg2gcgS VY9D5ZbK0IzvPUThqrHaYpj5HADEIR2G/yX3QV70B2rs2rd7QNguOdlgdEbheWGC5AUw9MGO3Z2 WFb7IOCg== X-Google-Smtp-Source: AGHT+IHRbLajaEqB17GmhKG2OlJp/V82vAaj5clrRbCfEGGmtCGCdZTHFPym4wjVbfllWReG7gz6ihhINHA= X-Received: from sport.zrh.corp.google.com ([2a00:79e0:9d:4:d80e:bfc8:2891:24c1]) (user=gnoack job=sendgmr) by 2002:a05:690c:c1c:b0:5d8:8d39:f67e with SMTP id cl28-20020a05690c0c1c00b005d88d39f67emr1976ywb.7.1702050689305; Fri, 08 Dec 2023 07:51:29 -0800 (PST) Date: Fri, 8 Dec 2023 16:51:13 +0100 In-Reply-To: <20231208155121.1943775-1-gnoack@google.com> Message-Id: <20231208155121.1943775-2-gnoack@google.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20231208155121.1943775-1-gnoack@google.com> X-Mailer: git-send-email 2.43.0.472.g3155946c3a-goog Subject: [PATCH v8 1/9] landlock: Remove remaining "inline" modifiers in .c files From: " =?utf-8?q?G=C3=BCnther_Noack?= " To: linux-security-module@vger.kernel.org, " =?utf-8?q?Micka=C3=ABl_Sala?= =?utf-8?q?=C3=BCn?= " Cc: Jeff Xu , Jorge Lucangeli Obes , Allen Webb , Dmitry Torokhov , Paul Moore , Konstantin Meskhidze , Matt Bobrowski , linux-fsdevel@vger.kernel.org, " =?utf-8?q?G=C3=BCnther_Noack?= " For module-internal static functions, compilers are already in a good position to decide whether to inline them or not. Suggested-by: Mickaël Salaün Signed-off-by: Günther Noack --- security/landlock/fs.c | 26 +++++++++++++------------- security/landlock/ruleset.c | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/security/landlock/fs.c b/security/landlock/fs.c index bc7c126deea2..9ba989ef46a5 100644 --- a/security/landlock/fs.c +++ b/security/landlock/fs.c @@ -193,7 +193,7 @@ int landlock_append_fs_rule(struct landlock_ruleset *const ruleset, * * Returns NULL if no rule is found or if @dentry is negative. */ -static inline const struct landlock_rule * +static const struct landlock_rule * find_rule(const struct landlock_ruleset *const domain, const struct dentry *const dentry) { @@ -220,7 +220,7 @@ find_rule(const struct landlock_ruleset *const domain, * sockfs, pipefs), but can still be reachable through * /proc//fd/ */ -static inline bool is_nouser_or_private(const struct dentry *dentry) +static bool is_nouser_or_private(const struct dentry *dentry) { return (dentry->d_sb->s_flags & SB_NOUSER) || (d_is_positive(dentry) && @@ -264,7 +264,7 @@ static const struct landlock_ruleset *get_current_fs_domain(void) * * @layer_masks_child2: Optional child masks. */ -static inline bool no_more_access( +static bool no_more_access( const layer_mask_t (*const layer_masks_parent1)[LANDLOCK_NUM_ACCESS_FS], const layer_mask_t (*const layer_masks_child1)[LANDLOCK_NUM_ACCESS_FS], const bool child1_is_directory, @@ -316,7 +316,7 @@ static inline bool no_more_access( * * Returns true if the request is allowed, false otherwise. */ -static inline bool +static bool scope_to_request(const access_mask_t access_request, layer_mask_t (*const layer_masks)[LANDLOCK_NUM_ACCESS_FS]) { @@ -335,7 +335,7 @@ scope_to_request(const access_mask_t access_request, * Returns true if there is at least one access right different than * LANDLOCK_ACCESS_FS_REFER. */ -static inline bool +static bool is_eacces(const layer_mask_t (*const layer_masks)[LANDLOCK_NUM_ACCESS_FS], const access_mask_t access_request) { @@ -551,9 +551,9 @@ static bool is_access_to_paths_allowed( return allowed_parent1 && allowed_parent2; } -static inline int check_access_path(const struct landlock_ruleset *const domain, - const struct path *const path, - access_mask_t access_request) +static int check_access_path(const struct landlock_ruleset *const domain, + const struct path *const path, + access_mask_t access_request) { layer_mask_t layer_masks[LANDLOCK_NUM_ACCESS_FS] = {}; @@ -565,8 +565,8 @@ static inline int check_access_path(const struct landlock_ruleset *const domain, return -EACCES; } -static inline int current_check_access_path(const struct path *const path, - const access_mask_t access_request) +static int current_check_access_path(const struct path *const path, + const access_mask_t access_request) { const struct landlock_ruleset *const dom = get_current_fs_domain(); @@ -575,7 +575,7 @@ static inline int current_check_access_path(const struct path *const path, return check_access_path(dom, path, access_request); } -static inline access_mask_t get_mode_access(const umode_t mode) +static access_mask_t get_mode_access(const umode_t mode) { switch (mode & S_IFMT) { case S_IFLNK: @@ -600,7 +600,7 @@ static inline access_mask_t get_mode_access(const umode_t mode) } } -static inline access_mask_t maybe_remove(const struct dentry *const dentry) +static access_mask_t maybe_remove(const struct dentry *const dentry) { if (d_is_negative(dentry)) return 0; @@ -1086,7 +1086,7 @@ static int hook_path_truncate(const struct path *const path) * Returns the access rights that are required for opening the given file, * depending on the file type and open mode. */ -static inline access_mask_t +static access_mask_t get_required_file_open_access(const struct file *const file) { access_mask_t access = 0; diff --git a/security/landlock/ruleset.c b/security/landlock/ruleset.c index ffedc99f2b68..789c81b26a50 100644 --- a/security/landlock/ruleset.c +++ b/security/landlock/ruleset.c @@ -305,7 +305,7 @@ int landlock_insert_rule(struct landlock_ruleset *const ruleset, return insert_rule(ruleset, id, &layers, ARRAY_SIZE(layers)); } -static inline void get_hierarchy(struct landlock_hierarchy *const hierarchy) +static void get_hierarchy(struct landlock_hierarchy *const hierarchy) { if (hierarchy) refcount_inc(&hierarchy->usage); From patchwork Fri Dec 8 15:51:14 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?G=C3=BCnther_Noack?= X-Patchwork-Id: 13485588 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="2fXDyaE7" Received: from mail-ed1-x54a.google.com (mail-ed1-x54a.google.com [IPv6:2a00:1450:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E22431723 for ; Fri, 8 Dec 2023 07:51:33 -0800 (PST) Received: by mail-ed1-x54a.google.com with SMTP id 4fb4d7f45d1cf-54dbe033977so1158696a12.0 for ; Fri, 08 Dec 2023 07:51:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1702050692; x=1702655492; darn=vger.kernel.org; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:from:to:cc:subject:date :message-id:reply-to; bh=7kWpQGARUuYr0YqUEA1D+Re6NElKsOYqdPIeXFsPG38=; b=2fXDyaE7ozq3tM27EOya8UmO4n5z+W3gnPNO764Aip06t5Y4eB6iPe9MHdz5pJkSxz Q7HTf/4Y3Ayr+8I3ROWP9S/VhK3BEGtJPHmk7nlsFGU/1/XHlI3QefKBzx4/23NKQe70 KLMvDsv7eC2NgCx5qEmimOQ7QGLxifWCYmojdqc+wIYLCzJ+sJqt07C1ImNDUmt9E2MA laJLwGiTFUyBBsyxA/Y1s/Q/eEXzvLax1hjDXadNSkbSa3mGyUgJZw+BZmQcSNjPnYj6 vekPBsh16G+p6HedonzObcMx7uBrahm/tUcp6DHB8OfT99107nSuo3uc/X321XmuRKpY ArBA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702050692; x=1702655492; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=7kWpQGARUuYr0YqUEA1D+Re6NElKsOYqdPIeXFsPG38=; b=mf7lZYDO+uYpnOPKQk2YuAF1rIls3ZJiBsJehXW+Qnhw4vU2cQvt8xRkzYVVYwLvTT WXadKZSRcj7px74A+Wf3X6QCkW94xFBQs/AdTCqS2kWFnKN6XTBS6fMUYfoFTPjsUi7V 9TI7e+lwxP0DSkUgHPWwgfW4xBOEqqKbBIU4onojL101hplJ/dzH6NiUrMM3Sy437XWs JiGJF4BXuupvG9HcayEqKnzA0m3KbzHstgOTydRV0UNy52v+KwZNlklLFiNLIXUltfeh ooQWDbCg8rZkjJHvXlXoq2DGiSXALnDOOJ2KB+kF6ZaQh5X6tusYkFEZUwy6PYO6fP5u w5Yg== X-Gm-Message-State: AOJu0YyYXOUgMmO+yR4bh7xX+v2rsta+RkbAyU+l0jrEpYQ/YFqL1DCp 39pqm7B0SL0/Ba+lYTTY4Xp8keWpjBazTfRN8cGrwtW4ZWdFWmpRqI4zixbFJdvjyX93tmV0auL fn++/IrNfHjdj3bs3ueX4TwBvKvZkxg3mEtgaWaZ8cmkx9lDMBJrTcobBwJE2ywbw0k3D3qqxaN W70clhZg== X-Google-Smtp-Source: AGHT+IEmKWtB5JCKmUgMb8Dj9DXsjPZORR5fK4vDweMRskchlYpAqg79BFHUKJBKX3h8yttseayvSepE4ZM= X-Received: from sport.zrh.corp.google.com ([2a00:79e0:9d:4:d80e:bfc8:2891:24c1]) (user=gnoack job=sendgmr) by 2002:a50:9eca:0:b0:54f:4811:2a9c with SMTP id a68-20020a509eca000000b0054f48112a9cmr2234edf.6.1702050691941; Fri, 08 Dec 2023 07:51:31 -0800 (PST) Date: Fri, 8 Dec 2023 16:51:14 +0100 In-Reply-To: <20231208155121.1943775-1-gnoack@google.com> Message-Id: <20231208155121.1943775-3-gnoack@google.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20231208155121.1943775-1-gnoack@google.com> X-Mailer: git-send-email 2.43.0.472.g3155946c3a-goog Subject: [PATCH v8 2/9] selftests/landlock: Rename "permitted" to "allowed" in ftruncate tests From: " =?utf-8?q?G=C3=BCnther_Noack?= " To: linux-security-module@vger.kernel.org, " =?utf-8?q?Micka=C3=ABl_Sala?= =?utf-8?q?=C3=BCn?= " Cc: Jeff Xu , Jorge Lucangeli Obes , Allen Webb , Dmitry Torokhov , Paul Moore , Konstantin Meskhidze , Matt Bobrowski , linux-fsdevel@vger.kernel.org, " =?utf-8?q?G=C3=BCnther_Noack?= " Suggested-by: Mickaël Salaün Signed-off-by: Günther Noack --- tools/testing/selftests/landlock/fs_test.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/tools/testing/selftests/landlock/fs_test.c b/tools/testing/selftests/landlock/fs_test.c index a1d17ab527ae..50818904397c 100644 --- a/tools/testing/selftests/landlock/fs_test.c +++ b/tools/testing/selftests/landlock/fs_test.c @@ -3688,7 +3688,7 @@ FIXTURE_TEARDOWN(ftruncate) FIXTURE_VARIANT(ftruncate) { const __u64 handled; - const __u64 permitted; + const __u64 allowed; const int expected_open_result; const int expected_ftruncate_result; }; @@ -3697,7 +3697,7 @@ FIXTURE_VARIANT(ftruncate) FIXTURE_VARIANT_ADD(ftruncate, w_w) { /* clang-format on */ .handled = LANDLOCK_ACCESS_FS_WRITE_FILE, - .permitted = LANDLOCK_ACCESS_FS_WRITE_FILE, + .allowed = LANDLOCK_ACCESS_FS_WRITE_FILE, .expected_open_result = 0, .expected_ftruncate_result = 0, }; @@ -3706,7 +3706,7 @@ FIXTURE_VARIANT_ADD(ftruncate, w_w) { FIXTURE_VARIANT_ADD(ftruncate, t_t) { /* clang-format on */ .handled = LANDLOCK_ACCESS_FS_TRUNCATE, - .permitted = LANDLOCK_ACCESS_FS_TRUNCATE, + .allowed = LANDLOCK_ACCESS_FS_TRUNCATE, .expected_open_result = 0, .expected_ftruncate_result = 0, }; @@ -3715,7 +3715,7 @@ FIXTURE_VARIANT_ADD(ftruncate, t_t) { FIXTURE_VARIANT_ADD(ftruncate, wt_w) { /* clang-format on */ .handled = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_TRUNCATE, - .permitted = LANDLOCK_ACCESS_FS_WRITE_FILE, + .allowed = LANDLOCK_ACCESS_FS_WRITE_FILE, .expected_open_result = 0, .expected_ftruncate_result = EACCES, }; @@ -3724,8 +3724,7 @@ FIXTURE_VARIANT_ADD(ftruncate, wt_w) { FIXTURE_VARIANT_ADD(ftruncate, wt_wt) { /* clang-format on */ .handled = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_TRUNCATE, - .permitted = LANDLOCK_ACCESS_FS_WRITE_FILE | - LANDLOCK_ACCESS_FS_TRUNCATE, + .allowed = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_TRUNCATE, .expected_open_result = 0, .expected_ftruncate_result = 0, }; @@ -3734,7 +3733,7 @@ FIXTURE_VARIANT_ADD(ftruncate, wt_wt) { FIXTURE_VARIANT_ADD(ftruncate, wt_t) { /* clang-format on */ .handled = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_TRUNCATE, - .permitted = LANDLOCK_ACCESS_FS_TRUNCATE, + .allowed = LANDLOCK_ACCESS_FS_TRUNCATE, .expected_open_result = EACCES, }; @@ -3744,7 +3743,7 @@ TEST_F_FORK(ftruncate, open_and_ftruncate) const struct rule rules[] = { { .path = path, - .access = variant->permitted, + .access = variant->allowed, }, {}, }; @@ -3785,7 +3784,7 @@ TEST_F_FORK(ftruncate, open_and_ftruncate_in_different_processes) const struct rule rules[] = { { .path = path, - .access = variant->permitted, + .access = variant->allowed, }, {}, }; From patchwork Fri Dec 8 15:51:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?G=C3=BCnther_Noack?= X-Patchwork-Id: 13485589 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="wqhtnYaW" Received: from mail-ej1-x64a.google.com (mail-ej1-x64a.google.com [IPv6:2a00:1450:4864:20::64a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3B6E310EB for ; Fri, 8 Dec 2023 07:51:37 -0800 (PST) Received: by mail-ej1-x64a.google.com with SMTP id a640c23a62f3a-a1c915eae11so350711766b.1 for ; Fri, 08 Dec 2023 07:51:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1702050696; x=1702655496; darn=vger.kernel.org; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:from:to:cc:subject:date :message-id:reply-to; bh=UQQhASvSHEVVJUGZcFZxCWmvl8oJFIsiHif6PfFONLA=; b=wqhtnYaWZUBS7ooaK+RE/d0d0kJRH+HdA5ddKoZW/HUmDEWwnz6W+zfDowx2T34Q3T Pe0/YKPuphvy93WgffLCtT5vili9H2DNhk1KcJIxRpK/XCd3TiHpuaGfwwT+ohW3PEsv 5+Ctje39iFX0LOsMOoAZOwL5A3Jn4nML5UuEwELwNJkuZQX/ls80MjrX0XMjugCWl7QF T6k00JnvV8zPhO0la/DdMU8/skm5Ia0yswVk++B2t4zVxF1CWSZ5FUKScC/wkfgNd6rj 1gB6mvF/OwK3/+p8m97VinTfTHysiLj3S28GwEAsFyDnJA+eiCf9u9zgDl92Lq9vo1L5 xl5A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702050696; x=1702655496; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=UQQhASvSHEVVJUGZcFZxCWmvl8oJFIsiHif6PfFONLA=; b=VPPV7cK8czAZczc5/NwTpPOpP3mq/NNNU7xS+auYfrtxP1MTu8NK9Az51Lg9T8l7wx XJl4k3xL1hX7tCLEnbRqMvRdefSqxwfCqK9YgM/LpckKEAgycKY4NCVtp9C1lw8R4JQq 7rsx5hSr2q6ofp3+iGP9saPW+9ZRbm5EpWv5tFjAcMhyxggCqiCVSb2ewZAqOENimrxZ 0e+gu7JG1S93h2r7AvaY1Nwgj2ga5o5eGKxc/BEYOPVCszS/LMdnFkba2uqfQTmfBchV zFTLiwiak9KCpGBrvFqaik2rdHHGqb1LFjoq/yvI1xsBPATJmOy9HgeRbAMY8UWLPK5i +FIA== X-Gm-Message-State: AOJu0YzCdavjek0wwnVEcB+3JfILq7E3DU/NRVmG9NrAouR6MAszOZXk cASoKsLl8J7bq3npd3/T+GE5c9TfaNJpkk1eDH6ptDGzGATaKI9E+R7D4ATry7zguTKWK5bSjOQ mjgi2J6AlrYJQBcPdV21ICfzKT5dlkmoHJfUvPwh5g0tK9Z7Tf3bhChnPkYwCdVohk6doyEp7YG WkZZM/yw== X-Google-Smtp-Source: AGHT+IFpaD++LK4E7OEiQC7I4oXVtYGVHw5pHI4ByxvRkcjujlRVCN4Pq1RUgImtFRqk9PUtqPZi4UFPhls= X-Received: from sport.zrh.corp.google.com ([2a00:79e0:9d:4:d80e:bfc8:2891:24c1]) (user=gnoack job=sendgmr) by 2002:a17:907:1b20:b0:a1a:36ed:f807 with SMTP id mp32-20020a1709071b2000b00a1a36edf807mr14369ejc.2.1702050695110; Fri, 08 Dec 2023 07:51:35 -0800 (PST) Date: Fri, 8 Dec 2023 16:51:15 +0100 In-Reply-To: <20231208155121.1943775-1-gnoack@google.com> Message-Id: <20231208155121.1943775-4-gnoack@google.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20231208155121.1943775-1-gnoack@google.com> X-Mailer: git-send-email 2.43.0.472.g3155946c3a-goog Subject: [PATCH v8 3/9] landlock: Optimize the number of calls to get_access_mask slightly From: " =?utf-8?q?G=C3=BCnther_Noack?= " To: linux-security-module@vger.kernel.org, " =?utf-8?q?Micka=C3=ABl_Sala?= =?utf-8?q?=C3=BCn?= " Cc: Jeff Xu , Jorge Lucangeli Obes , Allen Webb , Dmitry Torokhov , Paul Moore , Konstantin Meskhidze , Matt Bobrowski , linux-fsdevel@vger.kernel.org, " =?utf-8?q?G=C3=BCnther_Noack?= " This call is now going through a function pointer, and it is not as obvious any more that it will be inlined. Signed-off-by: Günther Noack --- security/landlock/ruleset.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/security/landlock/ruleset.c b/security/landlock/ruleset.c index 789c81b26a50..e0a5fbf9201a 100644 --- a/security/landlock/ruleset.c +++ b/security/landlock/ruleset.c @@ -723,11 +723,12 @@ landlock_init_layer_masks(const struct landlock_ruleset *const domain, /* Saves all handled accesses per layer. */ for (layer_level = 0; layer_level < domain->num_layers; layer_level++) { const unsigned long access_req = access_request; + const access_mask_t access_mask = + get_access_mask(domain, layer_level); unsigned long access_bit; for_each_set_bit(access_bit, &access_req, num_access) { - if (BIT_ULL(access_bit) & - get_access_mask(domain, layer_level)) { + if (BIT_ULL(access_bit) & access_mask) { (*layer_masks)[access_bit] |= BIT_ULL(layer_level); handled_accesses |= BIT_ULL(access_bit); From patchwork Fri Dec 8 15:51:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?G=C3=BCnther_Noack?= X-Patchwork-Id: 13485590 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="KPUMny61" Received: from mail-ej1-x649.google.com (mail-ej1-x649.google.com [IPv6:2a00:1450:4864:20::649]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 26CBF172A for ; Fri, 8 Dec 2023 07:51:40 -0800 (PST) Received: by mail-ej1-x649.google.com with SMTP id a640c23a62f3a-a1cba77ef87so114272866b.1 for ; Fri, 08 Dec 2023 07:51:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1702050698; x=1702655498; darn=vger.kernel.org; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:from:to:cc:subject:date :message-id:reply-to; bh=oYNJaMP1fvzyNXrIwWyaWB3+lmAWM09K9Qp9YhY63A0=; b=KPUMny61u8SHnlJKR9Qytt9U6uHcQOzcgeOIlAvkcbASf5IYDp3wD5E9hk4v1Sr0z5 d+CGLEYWPZQfKNDqqptfwKAVr8V/snDvUgWecY94ravoAAnwFFTEsRuvqJzwGOtue03I 5op4fLK8KqY2e31X2xhoJIMCbwD+MNYaNJn+9csiGHrjRhUIwKoIk97h3/RPosDn9OyH EqlhTXZsnoSp+3AUaMUYQicmgaRcUUeL5j0i98jqz5rjIvdI55YYtgQ6vmn4+15Zz+/x oN9OenMgus9nfSxqGXSDxnK5MCWuLZ/dL9jHh0f3EAcpY/7IE3bKobbhvyjb61LAWAFi J3Nw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702050698; x=1702655498; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=oYNJaMP1fvzyNXrIwWyaWB3+lmAWM09K9Qp9YhY63A0=; b=qHYG+AFISkQ59omYeBZ5oUoA255MkYW+I9Np/XKrCOPnParwIFxzja3qkT+ClLMjzs Bu5yVM3tioHG11nqscg2uFtK030uvkXmQQRnpAnvZ5igHiVfPmCfF6ma1t2PsDNmhgu5 9JNF4M5c6EHmlC2UDwuHVTIWkHgBL4nkDGWsJtiMmxYLoBFClkyiX9JkMXOop7ojiJJq bn7HYqMBlg6MnauBHtt9QAFhUdgwcsR+sXTXv3ZhIuglFTyjG8RN80pins/7/AMtIiid TtNHxCYkqVciC0v/tWaOVjArOorZxAa++3kYiqvnZTYtx+lJpi0+BINzXSZfnhmcL0Qj q47g== X-Gm-Message-State: AOJu0Yy7cxkUB492GxhKFeL3f0mq7jYdkmHEs1AIkUTfYAOoERJHuzcR 88iymUjRWLe0yOFG257tisr2ipr6NNHzFMJFfcaNFYpuEPRfmQAa4BewwnUCbB5xUICO5VI5B2E kOX+ERv+r1IDYZx3h/RUEL5S/kXoQ0V/M9i3+7xx7sdTZKbItpqN7jsj34FNBDjCBxkb4N3tjVc 4n1YL5Dg== X-Google-Smtp-Source: AGHT+IF+MVJaBkMbddAwFLPJIIGr+0YFnIv72U8RtxrWURdXVmgfWP8hU5PmW73JNE8Rn89uLFCE8JD+5a0= X-Received: from sport.zrh.corp.google.com ([2a00:79e0:9d:4:d80e:bfc8:2891:24c1]) (user=gnoack job=sendgmr) by 2002:a17:906:344f:b0:a1d:119d:d397 with SMTP id d15-20020a170906344f00b00a1d119dd397mr915ejb.12.1702050698027; Fri, 08 Dec 2023 07:51:38 -0800 (PST) Date: Fri, 8 Dec 2023 16:51:16 +0100 In-Reply-To: <20231208155121.1943775-1-gnoack@google.com> Message-Id: <20231208155121.1943775-5-gnoack@google.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20231208155121.1943775-1-gnoack@google.com> X-Mailer: git-send-email 2.43.0.472.g3155946c3a-goog Subject: [PATCH v8 4/9] landlock: Add IOCTL access right From: " =?utf-8?q?G=C3=BCnther_Noack?= " To: linux-security-module@vger.kernel.org, " =?utf-8?q?Micka=C3=ABl_Sala?= =?utf-8?q?=C3=BCn?= " Cc: Jeff Xu , Jorge Lucangeli Obes , Allen Webb , Dmitry Torokhov , Paul Moore , Konstantin Meskhidze , Matt Bobrowski , linux-fsdevel@vger.kernel.org, " =?utf-8?q?G=C3=BCnther_Noack?= " Introduces the LANDLOCK_ACCESS_FS_IOCTL access right and increments the Landlock ABI version to 5. Like the truncate right, these rights are associated with a file descriptor at the time of open(2), and get respected even when the file descriptor is used outside of the thread which it was originally opened in. A newly enabled Landlock policy therefore does not apply to file descriptors which are already open. If the LANDLOCK_ACCESS_FS_IOCTL right is handled, only a small number of safe IOCTL commands will be permitted on newly opened files. The permitted IOCTLs can be configured through the ruleset in limited ways now. (See documentation for details.) Specifically, when LANDLOCK_ACCESS_FS_IOCTL is handled, granting this right on a file or directory will *not* permit to do all IOCTL commands, but only influence the IOCTL commands which are not already handled through other access rights. The intent is to keep the groups of IOCTL commands more fine-grained. Noteworthy scenarios which require special attention: TTY devices support IOCTLs like TIOCSTI and TIOCLINUX, which can be used to control shell processes on the same terminal which run at different privilege levels, which may make it possible to escape a sandbox. Because stdin, stdout and stderr are normally inherited rather than newly opened, IOCTLs are usually permitted on them even after the Landlock policy is enforced. Some legitimate file system features, like setting up fscrypt, are exposed as IOCTL commands on regular files and directories -- users of Landlock are advised to double check that the sandboxed process does not need to invoke these IOCTLs. Known limitations: The LANDLOCK_ACCESS_FS_IOCTL access right is a coarse-grained control over IOCTL commands. Future work will enable a more fine-grained access control for IOCTLs. In the meantime, Landlock users may use path-based restrictions in combination with their knowledge about the file system layout to control what IOCTLs can be done. Mounting file systems with the nodev option can help to distinguish regular files and devices, and give guarantees about the affected files, which Landlock alone can not give yet. Signed-off-by: Günther Noack --- include/uapi/linux/landlock.h | 58 +++++- security/landlock/fs.c | 176 ++++++++++++++++++- security/landlock/fs.h | 2 + security/landlock/limits.h | 11 +- security/landlock/ruleset.h | 2 +- security/landlock/syscalls.c | 19 +- tools/testing/selftests/landlock/base_test.c | 2 +- tools/testing/selftests/landlock/fs_test.c | 5 +- 8 files changed, 253 insertions(+), 22 deletions(-) diff --git a/include/uapi/linux/landlock.h b/include/uapi/linux/landlock.h index 25c8d7677539..578f268b084b 100644 --- a/include/uapi/linux/landlock.h +++ b/include/uapi/linux/landlock.h @@ -128,7 +128,7 @@ struct landlock_net_port_attr { * files and directories. Files or directories opened before the sandboxing * are not subject to these restrictions. * - * A file can only receive these access rights: + * The following access rights apply only to files: * * - %LANDLOCK_ACCESS_FS_EXECUTE: Execute a file. * - %LANDLOCK_ACCESS_FS_WRITE_FILE: Open a file with write access. Note that @@ -138,12 +138,13 @@ struct landlock_net_port_attr { * - %LANDLOCK_ACCESS_FS_READ_FILE: Open a file with read access. * - %LANDLOCK_ACCESS_FS_TRUNCATE: Truncate a file with :manpage:`truncate(2)`, * :manpage:`ftruncate(2)`, :manpage:`creat(2)`, or :manpage:`open(2)` with - * ``O_TRUNC``. Whether an opened file can be truncated with - * :manpage:`ftruncate(2)` is determined during :manpage:`open(2)`, in the - * same way as read and write permissions are checked during - * :manpage:`open(2)` using %LANDLOCK_ACCESS_FS_READ_FILE and - * %LANDLOCK_ACCESS_FS_WRITE_FILE. This access right is available since the - * third version of the Landlock ABI. + * ``O_TRUNC``. This access right is available since the third version of the + * Landlock ABI. + * + * Whether an opened file can be truncated with :manpage:`ftruncate(2)` or used + * with `ioctl(2)` is determined during :manpage:`open(2)`, in the same way as + * read and write permissions are checked during :manpage:`open(2)` using + * %LANDLOCK_ACCESS_FS_READ_FILE and %LANDLOCK_ACCESS_FS_WRITE_FILE. * * A directory can receive access rights related to files or directories. The * following access right is applied to the directory itself, and the @@ -198,13 +199,53 @@ struct landlock_net_port_attr { * If multiple requirements are not met, the ``EACCES`` error code takes * precedence over ``EXDEV``. * + * The following access right applies both to files and directories: + * + * - %LANDLOCK_ACCESS_FS_IOCTL: Invoke :manpage:`ioctl(2)` commands on an opened + * file or directory. + * + * This access right applies to all :manpage:`ioctl(2)` commands, except of + * ``FIOCLEX``, ``FIONCLEX``, ``FIONBIO`` and ``FIOASYNC``. These commands + * continue to be invokable independent of the %LANDLOCK_ACCESS_FS_IOCTL + * access right. + * + * When certain other access rights are handled in the ruleset, in addition to + * %LANDLOCK_ACCESS_FS_IOCTL, granting these access rights will unlock access + * to additional groups of IOCTL commands, on the affected files: + * + * * %LANDLOCK_ACCESS_FS_READ_FILE unlocks access to ``FIOQSIZE``, + * ``FS_IOC_FIEMAP``, ``FIBMAP``, ``FIGETBSZ``, ``FIONREAD``, + * ``FIDEDUPRANGE``. + * + * * %LANDLOCK_ACCESS_FS_WRITE_FILE unlocks access to ``FIOQSIZE``, + * ``FS_IOC_FIEMAP``, ``FIBMAP``, ``FIGETBSZ``, ``FICLONE``, + * ``FICLONERANGE``, ``FS_IOC_RESVSP``, ``FS_IOC_RESVSP64``, + * ``FS_IOC_UNRESVSP``, ``FS_IOC_UNRESVSP64``, ``FS_IOC_ZERO_RANGE``. + * + * * %LANDLOCK_ACCESS_FS_READ_DIR unlocks access to ``FIOQSIZE``, + * ``FS_IOC_FIEMAP``, ``FIBMAP``, ``FIGETBSZ``. + * + * When these access rights are handled in the ruleset, the availability of + * the affected IOCTL commands is not governed by %LANDLOCK_ACCESS_FS_IOCTL + * any more, but by the respective access right. + * + * All other IOCTL commands are not handled specially, and are governed by + * %LANDLOCK_ACCESS_FS_IOCTL. This includes %FS_IOC_GETFLAGS and + * %FS_IOC_SETFLAGS for manipulating inode flags (:manpage:`ioctl_iflags(2)`), + * %FS_IOC_FSFETXATTR and %FS_IOC_FSSETXATTR for manipulating extended + * attributes, as well as %FIFREEZE and %FITHAW for freezing and thawing file + * systems. + * + * This access right is available since the fifth version of the Landlock + * ABI. + * * .. warning:: * * It is currently not possible to restrict some file-related actions * accessible through these syscall families: :manpage:`chdir(2)`, * :manpage:`stat(2)`, :manpage:`flock(2)`, :manpage:`chmod(2)`, * :manpage:`chown(2)`, :manpage:`setxattr(2)`, :manpage:`utime(2)`, - * :manpage:`ioctl(2)`, :manpage:`fcntl(2)`, :manpage:`access(2)`. + * :manpage:`fcntl(2)`, :manpage:`access(2)`. * Future Landlock evolutions will enable to restrict them. */ /* clang-format off */ @@ -223,6 +264,7 @@ struct landlock_net_port_attr { #define LANDLOCK_ACCESS_FS_MAKE_SYM (1ULL << 12) #define LANDLOCK_ACCESS_FS_REFER (1ULL << 13) #define LANDLOCK_ACCESS_FS_TRUNCATE (1ULL << 14) +#define LANDLOCK_ACCESS_FS_IOCTL (1ULL << 15) /* clang-format on */ /** diff --git a/security/landlock/fs.c b/security/landlock/fs.c index 9ba989ef46a5..81ce41e9e6db 100644 --- a/security/landlock/fs.c +++ b/security/landlock/fs.c @@ -7,12 +7,14 @@ * Copyright © 2021-2022 Microsoft Corporation */ +#include #include #include #include #include #include #include +#include #include #include #include @@ -28,6 +30,7 @@ #include #include #include +#include #include #include "common.h" @@ -83,6 +86,145 @@ static const struct landlock_object_underops landlock_fs_underops = { .release = release_inode }; +/* IOCTL helpers */ + +/* + * These are synthetic access rights, which are only used within the kernel, but + * not exposed to callers in userspace. The mapping between these access rights + * and IOCTL commands is defined in the required_ioctl_access() helper function. + */ +#define LANDLOCK_ACCESS_FS_IOCTL_GROUP1 (LANDLOCK_LAST_PUBLIC_ACCESS_FS << 1) +#define LANDLOCK_ACCESS_FS_IOCTL_GROUP2 (LANDLOCK_LAST_PUBLIC_ACCESS_FS << 2) +#define LANDLOCK_ACCESS_FS_IOCTL_GROUP3 (LANDLOCK_LAST_PUBLIC_ACCESS_FS << 3) +#define LANDLOCK_ACCESS_FS_IOCTL_GROUP4 (LANDLOCK_LAST_PUBLIC_ACCESS_FS << 4) + +/* ioctl_groups - all synthetic access rights for IOCTL command groups */ +/* clang-format off */ +#define IOCTL_GROUPS ( \ + LANDLOCK_ACCESS_FS_IOCTL_GROUP1 | \ + LANDLOCK_ACCESS_FS_IOCTL_GROUP2 | \ + LANDLOCK_ACCESS_FS_IOCTL_GROUP3 | \ + LANDLOCK_ACCESS_FS_IOCTL_GROUP4) +/* clang-format on */ + +static_assert((IOCTL_GROUPS & LANDLOCK_MASK_ACCESS_FS) == IOCTL_GROUPS); + +/** + * required_ioctl_access(): Determine required IOCTL access rights. + * + * @cmd: The IOCTL command that is supposed to be run. + * + * Returns: The access rights that must be granted on an opened file in order to + * use the given @cmd. + */ +static access_mask_t required_ioctl_access(unsigned int cmd) +{ + switch (cmd) { + case FIOCLEX: + case FIONCLEX: + case FIONBIO: + case FIOASYNC: + /* + * FIOCLEX, FIONCLEX, FIONBIO and FIOASYNC manipulate the FD's + * close-on-exec and the file's buffered-IO and async flags. + * These operations are also available through fcntl(2), + * and are unconditionally permitted in Landlock. + */ + return 0; + case FIOQSIZE: + return LANDLOCK_ACCESS_FS_IOCTL_GROUP1; + case FS_IOC_FIEMAP: + case FIBMAP: + case FIGETBSZ: + return LANDLOCK_ACCESS_FS_IOCTL_GROUP2; + case FIONREAD: + case FIDEDUPERANGE: + return LANDLOCK_ACCESS_FS_IOCTL_GROUP3; + case FICLONE: + case FICLONERANGE: + case FS_IOC_RESVSP: + case FS_IOC_RESVSP64: + case FS_IOC_UNRESVSP: + case FS_IOC_UNRESVSP64: + case FS_IOC_ZERO_RANGE: + return LANDLOCK_ACCESS_FS_IOCTL_GROUP4; + default: + /* + * Other commands are guarded by the catch-all access right. + */ + return LANDLOCK_ACCESS_FS_IOCTL; + } +} + +/** + * expand_ioctl() - Return the dst flags from either the src flag or the + * %LANDLOCK_ACCESS_FS_IOCTL flag, depending on whether the + * %LANDLOCK_ACCESS_FS_IOCTL and src access rights are handled or not. + * + * @handled: Handled access rights. + * @access: The access mask to copy values from. + * @src: A single access right to copy from in @access. + * @dst: One or more access rights to copy to. + * + * Returns: @dst, or 0. + */ +static access_mask_t expand_ioctl(const access_mask_t handled, + const access_mask_t access, + const access_mask_t src, + const access_mask_t dst) +{ + access_mask_t copy_from; + + if (!(handled & LANDLOCK_ACCESS_FS_IOCTL)) + return 0; + + copy_from = (handled & src) ? src : LANDLOCK_ACCESS_FS_IOCTL; + if (access & copy_from) + return dst; + + return 0; +} + +/** + * landlock_expand_access_fs() - Returns @access with the synthetic IOCTL group + * flags enabled if necessary. + * + * @handled: Handled FS access rights. + * @access: FS access rights to expand. + * + * Returns: @access expanded by the necessary flags for the synthetic IOCTL + * access rights. + */ +static access_mask_t landlock_expand_access_fs(const access_mask_t handled, + const access_mask_t access) +{ + return access | + expand_ioctl(handled, access, LANDLOCK_ACCESS_FS_WRITE_FILE, + LANDLOCK_ACCESS_FS_IOCTL_GROUP1 | + LANDLOCK_ACCESS_FS_IOCTL_GROUP2 | + LANDLOCK_ACCESS_FS_IOCTL_GROUP4) | + expand_ioctl(handled, access, LANDLOCK_ACCESS_FS_READ_FILE, + LANDLOCK_ACCESS_FS_IOCTL_GROUP1 | + LANDLOCK_ACCESS_FS_IOCTL_GROUP2 | + LANDLOCK_ACCESS_FS_IOCTL_GROUP3) | + expand_ioctl(handled, access, LANDLOCK_ACCESS_FS_READ_DIR, + LANDLOCK_ACCESS_FS_IOCTL_GROUP1); +} + +/** + * landlock_expand_handled_access_fs() - add synthetic IOCTL access rights to an + * access mask of handled accesses. + * + * @handled: The handled accesses of a ruleset that is being created. + * + * Returns: @handled, with the bits for the synthetic IOCTL access rights set, + * if %LANDLOCK_ACCESS_FS_IOCTL is handled. + */ +access_mask_t landlock_expand_handled_access_fs(const access_mask_t handled) +{ + return landlock_expand_access_fs(handled, handled); +} + /* Ruleset management */ static struct landlock_object *get_inode_object(struct inode *const inode) @@ -147,7 +289,8 @@ static struct landlock_object *get_inode_object(struct inode *const inode) LANDLOCK_ACCESS_FS_EXECUTE | \ LANDLOCK_ACCESS_FS_WRITE_FILE | \ LANDLOCK_ACCESS_FS_READ_FILE | \ - LANDLOCK_ACCESS_FS_TRUNCATE) + LANDLOCK_ACCESS_FS_TRUNCATE | \ + LANDLOCK_ACCESS_FS_IOCTL) /* clang-format on */ /* @@ -157,6 +300,7 @@ int landlock_append_fs_rule(struct landlock_ruleset *const ruleset, const struct path *const path, access_mask_t access_rights) { + access_mask_t handled; int err; struct landlock_id id = { .type = LANDLOCK_KEY_INODE, @@ -169,9 +313,11 @@ int landlock_append_fs_rule(struct landlock_ruleset *const ruleset, if (WARN_ON_ONCE(ruleset->num_layers != 1)) return -EINVAL; + handled = landlock_get_fs_access_mask(ruleset, 0); + /* Expands the synthetic IOCTL groups. */ + access_rights |= landlock_expand_access_fs(handled, access_rights); /* Transforms relative access rights to absolute ones. */ - access_rights |= LANDLOCK_MASK_ACCESS_FS & - ~landlock_get_fs_access_mask(ruleset, 0); + access_rights |= LANDLOCK_MASK_ACCESS_FS & ~handled; id.key.object = get_inode_object(d_backing_inode(path->dentry)); if (IS_ERR(id.key.object)) return PTR_ERR(id.key.object); @@ -1123,7 +1269,9 @@ static int hook_file_open(struct file *const file) { layer_mask_t layer_masks[LANDLOCK_NUM_ACCESS_FS] = {}; access_mask_t open_access_request, full_access_request, allowed_access; - const access_mask_t optional_access = LANDLOCK_ACCESS_FS_TRUNCATE; + const access_mask_t optional_access = LANDLOCK_ACCESS_FS_TRUNCATE | + LANDLOCK_ACCESS_FS_IOCTL | + IOCTL_GROUPS; const struct landlock_ruleset *const dom = get_current_fs_domain(); if (!dom) @@ -1196,6 +1344,25 @@ static int hook_file_truncate(struct file *const file) return -EACCES; } +static int hook_file_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + const access_mask_t required_access = required_ioctl_access(cmd); + const access_mask_t allowed_access = + landlock_file(file)->allowed_access; + + /* + * It is the access rights at the time of opening the file which + * determine whether IOCTL can be used on the opened file later. + * + * The access right is attached to the opened file in hook_file_open(). + */ + if ((allowed_access & required_access) == required_access) + return 0; + + return -EACCES; +} + static struct security_hook_list landlock_hooks[] __ro_after_init = { LSM_HOOK_INIT(inode_free_security, hook_inode_free_security), @@ -1218,6 +1385,7 @@ static struct security_hook_list landlock_hooks[] __ro_after_init = { LSM_HOOK_INIT(file_alloc_security, hook_file_alloc_security), LSM_HOOK_INIT(file_open, hook_file_open), LSM_HOOK_INIT(file_truncate, hook_file_truncate), + LSM_HOOK_INIT(file_ioctl, hook_file_ioctl), }; __init void landlock_add_fs_hooks(void) diff --git a/security/landlock/fs.h b/security/landlock/fs.h index 488e4813680a..c88fe7bda37b 100644 --- a/security/landlock/fs.h +++ b/security/landlock/fs.h @@ -92,4 +92,6 @@ int landlock_append_fs_rule(struct landlock_ruleset *const ruleset, const struct path *const path, access_mask_t access_hierarchy); +access_mask_t landlock_expand_handled_access_fs(const access_mask_t handled); + #endif /* _SECURITY_LANDLOCK_FS_H */ diff --git a/security/landlock/limits.h b/security/landlock/limits.h index 93c9c6f91556..296795f8a5c1 100644 --- a/security/landlock/limits.h +++ b/security/landlock/limits.h @@ -18,7 +18,16 @@ #define LANDLOCK_MAX_NUM_LAYERS 16 #define LANDLOCK_MAX_NUM_RULES U32_MAX -#define LANDLOCK_LAST_ACCESS_FS LANDLOCK_ACCESS_FS_TRUNCATE +/* + * For file system access rights, Landlock distinguishes between the publicly + * visible access rights (1 to LANDLOCK_LAST_PUBLIC_ACCESS_FS) and the private + * ones which are not exposed to userspace (LANDLOCK_LAST_PUBLIC_ACCESS_FS + 1 + * to LANDLOCK_LAST_ACCESS_FS). The private access rights are defined in fs.c. + */ +#define LANDLOCK_LAST_PUBLIC_ACCESS_FS LANDLOCK_ACCESS_FS_IOCTL +#define LANDLOCK_MASK_PUBLIC_ACCESS_FS ((LANDLOCK_LAST_PUBLIC_ACCESS_FS << 1) - 1) + +#define LANDLOCK_LAST_ACCESS_FS (LANDLOCK_LAST_PUBLIC_ACCESS_FS << 4) #define LANDLOCK_MASK_ACCESS_FS ((LANDLOCK_LAST_ACCESS_FS << 1) - 1) #define LANDLOCK_NUM_ACCESS_FS __const_hweight64(LANDLOCK_MASK_ACCESS_FS) #define LANDLOCK_SHIFT_ACCESS_FS 0 diff --git a/security/landlock/ruleset.h b/security/landlock/ruleset.h index c7f1526784fd..5a28ea8e1c3d 100644 --- a/security/landlock/ruleset.h +++ b/security/landlock/ruleset.h @@ -30,7 +30,7 @@ LANDLOCK_ACCESS_FS_REFER) /* clang-format on */ -typedef u16 access_mask_t; +typedef u32 access_mask_t; /* Makes sure all filesystem access rights can be stored. */ static_assert(BITS_PER_TYPE(access_mask_t) >= LANDLOCK_NUM_ACCESS_FS); /* Makes sure all network access rights can be stored. */ diff --git a/security/landlock/syscalls.c b/security/landlock/syscalls.c index 898358f57fa0..f0bc50003b46 100644 --- a/security/landlock/syscalls.c +++ b/security/landlock/syscalls.c @@ -137,7 +137,7 @@ static const struct file_operations ruleset_fops = { .write = fop_dummy_write, }; -#define LANDLOCK_ABI_VERSION 4 +#define LANDLOCK_ABI_VERSION 5 /** * sys_landlock_create_ruleset - Create a new ruleset @@ -192,8 +192,8 @@ SYSCALL_DEFINE3(landlock_create_ruleset, return err; /* Checks content (and 32-bits cast). */ - if ((ruleset_attr.handled_access_fs | LANDLOCK_MASK_ACCESS_FS) != - LANDLOCK_MASK_ACCESS_FS) + if ((ruleset_attr.handled_access_fs | LANDLOCK_MASK_PUBLIC_ACCESS_FS) != + LANDLOCK_MASK_PUBLIC_ACCESS_FS) return -EINVAL; /* Checks network content (and 32-bits cast). */ @@ -201,6 +201,10 @@ SYSCALL_DEFINE3(landlock_create_ruleset, LANDLOCK_MASK_ACCESS_NET) return -EINVAL; + /* Expands synthetic IOCTL groups. */ + ruleset_attr.handled_access_fs = landlock_expand_handled_access_fs( + ruleset_attr.handled_access_fs); + /* Checks arguments and transforms to kernel struct. */ ruleset = landlock_create_ruleset(ruleset_attr.handled_access_fs, ruleset_attr.handled_access_net); @@ -309,8 +313,13 @@ static int add_rule_path_beneath(struct landlock_ruleset *const ruleset, if (!path_beneath_attr.allowed_access) return -ENOMSG; - /* Checks that allowed_access matches the @ruleset constraints. */ - mask = landlock_get_raw_fs_access_mask(ruleset, 0); + /* + * Checks that allowed_access matches the @ruleset constraints and only + * consists of publicly visible access rights (as opposed to synthetic + * ones). + */ + mask = landlock_get_raw_fs_access_mask(ruleset, 0) & + LANDLOCK_MASK_PUBLIC_ACCESS_FS; if ((path_beneath_attr.allowed_access | mask) != mask) return -EINVAL; diff --git a/tools/testing/selftests/landlock/base_test.c b/tools/testing/selftests/landlock/base_test.c index 646f778dfb1e..d292b419ccba 100644 --- a/tools/testing/selftests/landlock/base_test.c +++ b/tools/testing/selftests/landlock/base_test.c @@ -75,7 +75,7 @@ TEST(abi_version) const struct landlock_ruleset_attr ruleset_attr = { .handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE, }; - ASSERT_EQ(4, landlock_create_ruleset(NULL, 0, + ASSERT_EQ(5, landlock_create_ruleset(NULL, 0, LANDLOCK_CREATE_RULESET_VERSION)); ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr, 0, diff --git a/tools/testing/selftests/landlock/fs_test.c b/tools/testing/selftests/landlock/fs_test.c index 50818904397c..192608c3e840 100644 --- a/tools/testing/selftests/landlock/fs_test.c +++ b/tools/testing/selftests/landlock/fs_test.c @@ -525,9 +525,10 @@ TEST_F_FORK(layout1, inval) LANDLOCK_ACCESS_FS_EXECUTE | \ LANDLOCK_ACCESS_FS_WRITE_FILE | \ LANDLOCK_ACCESS_FS_READ_FILE | \ - LANDLOCK_ACCESS_FS_TRUNCATE) + LANDLOCK_ACCESS_FS_TRUNCATE | \ + LANDLOCK_ACCESS_FS_IOCTL) -#define ACCESS_LAST LANDLOCK_ACCESS_FS_TRUNCATE +#define ACCESS_LAST LANDLOCK_ACCESS_FS_IOCTL #define ACCESS_ALL ( \ ACCESS_FILE | \ From patchwork Fri Dec 8 15:51:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?G=C3=BCnther_Noack?= X-Patchwork-Id: 13485591 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="4gST5b//" Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 70D551732 for ; Fri, 8 Dec 2023 07:51:42 -0800 (PST) Received: by mail-yb1-xb4a.google.com with SMTP id 3f1490d57ef6-db084a0a2e9so2695137276.2 for ; Fri, 08 Dec 2023 07:51:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1702050701; x=1702655501; darn=vger.kernel.org; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:from:to:cc:subject:date :message-id:reply-to; bh=BscG/IXjZszbYWZABJDoMsaRTglf5pOxL6fwttzyF8I=; b=4gST5b//4E/FzQkcpZuYDC4wn50yfvNQ65Vsekw/lMf+KW9rYOgIrBXKT3nUyTMGO6 ccPUYYE956Uckk1g/hJrSIg38uLRgmGnRdK3y8MOSYonqrvIEaEkLy+V0gvur+3sp1Bp 1ZGlzmzt1SdoUo2e1dJ02fps1jX/lqE2qDyc+gI41jFZeCWXtZm10qblpXlPlsKcFhBK OgQa5yb5wPwK3xC2yaVEMRsDfOK4b1tWIj9xNpLFQYmrFMhOvK5H/YxO4KKyMAMrJBhB +PhO9qLeHIPYPJiF7JWv8WOXddpdqdCtGr8RCQknqwmKARr9p6pDHI2aoH1Cb32HRZaH J2qA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702050701; x=1702655501; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=BscG/IXjZszbYWZABJDoMsaRTglf5pOxL6fwttzyF8I=; b=uDyKp64ILWHsW+sdVeCnjYoMGritBQSl5mKJC/8laoZCame9M7n6pnmvkTTDesMA2X CxCvUjBtavyZU9hSz8/1lJnN7SEoyvAtb00mslZ57Xv1jKRC2sPoo1Wp4p9ZA8dyuJyp WYKBirLPSiYz58cyeYbJK/lpgBIns2dmlzR1z0x/I/BuQMjnLngoJhUSmtbeLOYwdMC9 wrnHDC/kNf50tUZdtqa9nqTmkOl1jJYQo2ZEgNRBKeCQGcuzofckA6RB1/PawpVpgVOP Qf86aDux1lTq4nnI42XB9JvWseR/Q+K3bKZKbGV4ZhxJnkDpmlYHQkZFaW02lky3aSc1 Fueg== X-Gm-Message-State: AOJu0YzRJJFloXLuTCL0E63XIozw2KnsWdHFk4Ab9MN9/7fV3Yo99SME 9REnhoaC+hGEA0fqx98ibNHtWcep2u1O8i2/wPr7iMmLD0t02mxaQ/ovTRk55YF60jgokuaoZJS 4VXdI6PV4L/qIvq+mK2ap40VeUc3M4EXcD55OjvZIIrFTVjeQ4Es8a2x/9Msxcyky3590m61A/Z FxYW3Tsw== X-Google-Smtp-Source: AGHT+IEh2S4LNLl4dUM9YAyg4dfFI9v2f39pyTk6aTA0u2w8GWW2YlMvl3+85zmhko1bKOtJLrzcOqEsOlA= X-Received: from sport.zrh.corp.google.com ([2a00:79e0:9d:4:d80e:bfc8:2891:24c1]) (user=gnoack job=sendgmr) by 2002:a25:b908:0:b0:d13:856b:c10a with SMTP id x8-20020a25b908000000b00d13856bc10amr2334ybj.3.1702050700852; Fri, 08 Dec 2023 07:51:40 -0800 (PST) Date: Fri, 8 Dec 2023 16:51:17 +0100 In-Reply-To: <20231208155121.1943775-1-gnoack@google.com> Message-Id: <20231208155121.1943775-6-gnoack@google.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20231208155121.1943775-1-gnoack@google.com> X-Mailer: git-send-email 2.43.0.472.g3155946c3a-goog Subject: [PATCH v8 5/9] selftests/landlock: Test IOCTL support From: " =?utf-8?q?G=C3=BCnther_Noack?= " To: linux-security-module@vger.kernel.org, " =?utf-8?q?Micka=C3=ABl_Sala?= =?utf-8?q?=C3=BCn?= " Cc: Jeff Xu , Jorge Lucangeli Obes , Allen Webb , Dmitry Torokhov , Paul Moore , Konstantin Meskhidze , Matt Bobrowski , linux-fsdevel@vger.kernel.org, " =?utf-8?q?G=C3=BCnther_Noack?= " Exercises Landlock's IOCTL feature in different combinations of handling and permitting the rights LANDLOCK_ACCESS_FS_IOCTL, LANDLOCK_ACCESS_FS_READ_FILE, LANDLOCK_ACCESS_FS_WRITE_FILE and LANDLOCK_ACCESS_FS_READ_DIR, and in different combinations of using files and directories. Signed-off-by: Günther Noack --- tools/testing/selftests/landlock/fs_test.c | 431 ++++++++++++++++++++- 1 file changed, 428 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/landlock/fs_test.c b/tools/testing/selftests/landlock/fs_test.c index 192608c3e840..054779ef4527 100644 --- a/tools/testing/selftests/landlock/fs_test.c +++ b/tools/testing/selftests/landlock/fs_test.c @@ -9,6 +9,7 @@ #define _GNU_SOURCE #include +#include #include #include #include @@ -733,6 +734,9 @@ static int create_ruleset(struct __test_metadata *const _metadata, } for (i = 0; rules[i].path; i++) { + if (!rules[i].access) + continue; + add_path_beneath(_metadata, ruleset_fd, rules[i].access, rules[i].path); } @@ -3441,7 +3445,7 @@ TEST_F_FORK(layout1, truncate_unhandled) LANDLOCK_ACCESS_FS_WRITE_FILE; int ruleset_fd; - /* Enable Landlock. */ + /* Enables Landlock. */ ruleset_fd = create_ruleset(_metadata, handled, rules); ASSERT_LE(0, ruleset_fd); @@ -3524,7 +3528,7 @@ TEST_F_FORK(layout1, truncate) LANDLOCK_ACCESS_FS_TRUNCATE; int ruleset_fd; - /* Enable Landlock. */ + /* Enables Landlock. */ ruleset_fd = create_ruleset(_metadata, handled, rules); ASSERT_LE(0, ruleset_fd); @@ -3750,7 +3754,7 @@ TEST_F_FORK(ftruncate, open_and_ftruncate) }; int fd, ruleset_fd; - /* Enable Landlock. */ + /* Enables Landlock. */ ruleset_fd = create_ruleset(_metadata, variant->handled, rules); ASSERT_LE(0, ruleset_fd); enforce_ruleset(_metadata, ruleset_fd); @@ -3827,6 +3831,16 @@ TEST_F_FORK(ftruncate, open_and_ftruncate_in_different_processes) ASSERT_EQ(0, close(socket_fds[1])); } +/* Invokes the FS_IOC_GETFLAGS IOCTL and returns its errno or 0. */ +static int test_fs_ioc_getflags_ioctl(int fd) +{ + uint32_t flags; + + if (ioctl(fd, FS_IOC_GETFLAGS, &flags) < 0) + return errno; + return 0; +} + TEST(memfd_ftruncate) { int fd; @@ -3843,6 +3857,417 @@ TEST(memfd_ftruncate) ASSERT_EQ(0, close(fd)); } +/* clang-format off */ +FIXTURE(ioctl) {}; +/* clang-format on */ + +FIXTURE_SETUP(ioctl) +{ + prepare_layout(_metadata); + create_file(_metadata, file1_s1d1); +} + +FIXTURE_TEARDOWN(ioctl) +{ + EXPECT_EQ(0, remove_path(file1_s1d1)); + cleanup_layout(_metadata); +} + +FIXTURE_VARIANT(ioctl) +{ + const __u64 handled; + const __u64 allowed; + const mode_t open_mode; + /* + * These are the expected IOCTL results for a representative IOCTL from + * each of the IOCTL groups. We only distinguish the 0 and EACCES + * results here, and treat other errors as 0. + */ + const int expected_fioqsize_result; /* G1 */ + const int expected_fibmap_result; /* G2 */ + const int expected_fionread_result; /* G3 */ + const int expected_fs_ioc_zero_range_result; /* G4 */ + const int expected_fs_ioc_getflags_result; /* other */ +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(ioctl, handled_i_allowed_none) { + /* clang-format on */ + .handled = LANDLOCK_ACCESS_FS_IOCTL, + .allowed = 0, + .open_mode = O_RDWR, + .expected_fioqsize_result = EACCES, + .expected_fibmap_result = EACCES, + .expected_fionread_result = EACCES, + .expected_fs_ioc_zero_range_result = EACCES, + .expected_fs_ioc_getflags_result = EACCES, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(ioctl, handled_i_allowed_i) { + /* clang-format on */ + .handled = LANDLOCK_ACCESS_FS_IOCTL, + .allowed = LANDLOCK_ACCESS_FS_IOCTL, + .open_mode = O_RDWR, + .expected_fioqsize_result = 0, + .expected_fibmap_result = 0, + .expected_fionread_result = 0, + .expected_fs_ioc_zero_range_result = 0, + .expected_fs_ioc_getflags_result = 0, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(ioctl, unhandled) { + /* clang-format on */ + .handled = LANDLOCK_ACCESS_FS_EXECUTE, + .allowed = LANDLOCK_ACCESS_FS_EXECUTE, + .open_mode = O_RDWR, + .expected_fioqsize_result = 0, + .expected_fibmap_result = 0, + .expected_fionread_result = 0, + .expected_fs_ioc_zero_range_result = 0, + .expected_fs_ioc_getflags_result = 0, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(ioctl, handled_rwd_allowed_r) { + /* clang-format on */ + .handled = LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_READ_DIR, + .allowed = LANDLOCK_ACCESS_FS_READ_FILE, + .open_mode = O_RDONLY, + /* If LANDLOCK_ACCESS_FS_IOCTL is not handled, all IOCTLs work. */ + .expected_fioqsize_result = 0, + .expected_fibmap_result = 0, + .expected_fionread_result = 0, + .expected_fs_ioc_zero_range_result = 0, + .expected_fs_ioc_getflags_result = 0, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(ioctl, handled_rwd_allowed_w) { + /* clang-format on */ + .handled = LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_READ_DIR, + .allowed = LANDLOCK_ACCESS_FS_WRITE_FILE, + .open_mode = O_WRONLY, + /* If LANDLOCK_ACCESS_FS_IOCTL is not handled, all IOCTLs work. */ + .expected_fioqsize_result = 0, + .expected_fibmap_result = 0, + .expected_fionread_result = 0, + .expected_fs_ioc_zero_range_result = 0, + .expected_fs_ioc_getflags_result = 0, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(ioctl, handled_ri_allowed_r) { + /* clang-format on */ + .handled = LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_IOCTL, + .allowed = LANDLOCK_ACCESS_FS_READ_FILE, + .open_mode = O_RDONLY, + .expected_fioqsize_result = 0, + .expected_fibmap_result = 0, + .expected_fionread_result = 0, + .expected_fs_ioc_zero_range_result = EACCES, + .expected_fs_ioc_getflags_result = EACCES, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(ioctl, handled_wi_allowed_w) { + /* clang-format on */ + .handled = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_IOCTL, + .allowed = LANDLOCK_ACCESS_FS_WRITE_FILE, + .open_mode = O_WRONLY, + .expected_fioqsize_result = 0, + .expected_fibmap_result = 0, + .expected_fionread_result = EACCES, + .expected_fs_ioc_zero_range_result = 0, + .expected_fs_ioc_getflags_result = EACCES, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(ioctl, handled_di_allowed_d) { + /* clang-format on */ + .handled = LANDLOCK_ACCESS_FS_READ_DIR | LANDLOCK_ACCESS_FS_IOCTL, + .allowed = LANDLOCK_ACCESS_FS_READ_DIR, + .open_mode = O_RDWR, + .expected_fioqsize_result = 0, + .expected_fibmap_result = EACCES, + .expected_fionread_result = EACCES, + .expected_fs_ioc_zero_range_result = EACCES, + .expected_fs_ioc_getflags_result = EACCES, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(ioctl, handled_rwi_allowed_rw) { + /* clang-format on */ + .handled = LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_IOCTL, + .allowed = LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_WRITE_FILE, + .open_mode = O_RDWR, + .expected_fioqsize_result = 0, + .expected_fibmap_result = 0, + .expected_fionread_result = 0, + .expected_fs_ioc_zero_range_result = 0, + .expected_fs_ioc_getflags_result = EACCES, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(ioctl, handled_rwi_allowed_r) { + /* clang-format on */ + .handled = LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_IOCTL, + .allowed = LANDLOCK_ACCESS_FS_READ_FILE, + .open_mode = O_RDONLY, + .expected_fioqsize_result = 0, + .expected_fibmap_result = 0, + .expected_fionread_result = 0, + .expected_fs_ioc_zero_range_result = EACCES, + .expected_fs_ioc_getflags_result = EACCES, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(ioctl, handled_rwi_allowed_ri) { + /* clang-format on */ + .handled = LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_IOCTL, + .allowed = LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_IOCTL, + .open_mode = O_RDONLY, + .expected_fioqsize_result = 0, + .expected_fibmap_result = 0, + .expected_fionread_result = 0, + .expected_fs_ioc_zero_range_result = EACCES, + .expected_fs_ioc_getflags_result = 0, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(ioctl, handled_rwi_allowed_w) { + /* clang-format on */ + .handled = LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_IOCTL, + .allowed = LANDLOCK_ACCESS_FS_WRITE_FILE, + .open_mode = O_WRONLY, + .expected_fioqsize_result = 0, + .expected_fibmap_result = 0, + .expected_fionread_result = EACCES, + .expected_fs_ioc_zero_range_result = 0, + .expected_fs_ioc_getflags_result = EACCES, +}; + +/* clang-format off */ +FIXTURE_VARIANT_ADD(ioctl, handled_rwi_allowed_wi) { + /* clang-format on */ + .handled = LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_IOCTL, + .allowed = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_IOCTL, + .open_mode = O_WRONLY, + .expected_fioqsize_result = 0, + .expected_fibmap_result = 0, + .expected_fionread_result = EACCES, + .expected_fs_ioc_zero_range_result = 0, + .expected_fs_ioc_getflags_result = 0, +}; + +static int test_fioqsize_ioctl(int fd) +{ + size_t sz; + + if (ioctl(fd, FIOQSIZE, &sz) < 0) + return errno; + return 0; +} + +static int test_fibmap_ioctl(int fd) +{ + int blk = 0; + + /* + * We only want to distinguish here whether Landlock already caught it, + * so we treat anything but EACCESS as success. (It commonly returns + * EPERM when missing CAP_SYS_RAWIO.) + */ + if (ioctl(fd, FIBMAP, &blk) < 0 && errno == EACCES) + return errno; + return 0; +} + +static int test_fionread_ioctl(int fd) +{ + size_t sz = 0; + + if (ioctl(fd, FIONREAD, &sz) < 0 && errno == EACCES) + return errno; + return 0; +} + +#define FS_IOC_ZERO_RANGE _IOW('X', 57, struct space_resv) + +static int test_fs_ioc_zero_range_ioctl(int fd) +{ + struct space_resv { + __s16 l_type; + __s16 l_whence; + __s64 l_start; + __s64 l_len; /* len == 0 means until end of file */ + __s32 l_sysid; + __u32 l_pid; + __s32 l_pad[4]; /* reserved area */ + } reservation = {}; + /* + * This can fail for various reasons, but we only want to distinguish + * here whether Landlock already caught it, so we treat anything but + * EACCES as success. + */ + if (ioctl(fd, FS_IOC_ZERO_RANGE, &reservation) < 0 && errno == EACCES) + return errno; + return 0; +} + +TEST_F_FORK(ioctl, handle_dir_access_file) +{ + const int flag = 0; + const struct rule rules[] = { + { + .path = dir_s1d1, + .access = variant->allowed, + }, + {}, + }; + int file_fd, ruleset_fd; + + /* Enables Landlock. */ + ruleset_fd = create_ruleset(_metadata, variant->handled, rules); + ASSERT_LE(0, ruleset_fd); + enforce_ruleset(_metadata, ruleset_fd); + ASSERT_EQ(0, close(ruleset_fd)); + + file_fd = open(file1_s1d1, variant->open_mode); + ASSERT_LE(0, file_fd); + + /* + * Checks that IOCTL commands in each IOCTL group return the expected + * errors. + */ + EXPECT_EQ(variant->expected_fioqsize_result, + test_fioqsize_ioctl(file_fd)); + EXPECT_EQ(variant->expected_fibmap_result, test_fibmap_ioctl(file_fd)); + EXPECT_EQ(variant->expected_fionread_result, + test_fionread_ioctl(file_fd)); + EXPECT_EQ(variant->expected_fs_ioc_zero_range_result, + test_fs_ioc_zero_range_ioctl(file_fd)); + EXPECT_EQ(variant->expected_fs_ioc_getflags_result, + test_fs_ioc_getflags_ioctl(file_fd)); + + /* Checks that unrestrictable commands are unrestricted. */ + EXPECT_EQ(0, ioctl(file_fd, FIOCLEX)); + EXPECT_EQ(0, ioctl(file_fd, FIONCLEX)); + EXPECT_EQ(0, ioctl(file_fd, FIONBIO, &flag)); + EXPECT_EQ(0, ioctl(file_fd, FIOASYNC, &flag)); + + ASSERT_EQ(0, close(file_fd)); +} + +TEST_F_FORK(ioctl, handle_dir_access_dir) +{ + const char *const path = dir_s1d1; + const int flag = 0; + const struct rule rules[] = { + { + .path = path, + .access = variant->allowed, + }, + {}, + }; + int dir_fd, ruleset_fd; + + /* Enables Landlock. */ + ruleset_fd = create_ruleset(_metadata, variant->handled, rules); + ASSERT_LE(0, ruleset_fd); + enforce_ruleset(_metadata, ruleset_fd); + ASSERT_EQ(0, close(ruleset_fd)); + + /* + * Ignore variant->open_mode for this test, as we intend to open a + * directory. If the directory can not be opened, the variant is + * infeasible to test with an opened directory. + */ + dir_fd = open(path, O_RDONLY); + if (dir_fd < 0) + return; + + /* + * Checks that IOCTL commands in each IOCTL group return the expected + * errors. + */ + EXPECT_EQ(variant->expected_fioqsize_result, + test_fioqsize_ioctl(dir_fd)); + EXPECT_EQ(variant->expected_fibmap_result, test_fibmap_ioctl(dir_fd)); + EXPECT_EQ(variant->expected_fionread_result, + test_fionread_ioctl(dir_fd)); + EXPECT_EQ(variant->expected_fs_ioc_zero_range_result, + test_fs_ioc_zero_range_ioctl(dir_fd)); + EXPECT_EQ(variant->expected_fs_ioc_getflags_result, + test_fs_ioc_getflags_ioctl(dir_fd)); + + /* Checks that unrestrictable commands are unrestricted. */ + EXPECT_EQ(0, ioctl(dir_fd, FIOCLEX)); + EXPECT_EQ(0, ioctl(dir_fd, FIONCLEX)); + EXPECT_EQ(0, ioctl(dir_fd, FIONBIO, &flag)); + EXPECT_EQ(0, ioctl(dir_fd, FIOASYNC, &flag)); + + ASSERT_EQ(0, close(dir_fd)); +} + +TEST_F_FORK(ioctl, handle_file_access_file) +{ + const char *const path = file1_s1d1; + const int flag = 0; + const struct rule rules[] = { + { + .path = path, + .access = variant->allowed, + }, + {}, + }; + int file_fd, ruleset_fd; + + if (variant->allowed & LANDLOCK_ACCESS_FS_READ_DIR) { + SKIP(return, "LANDLOCK_ACCESS_FS_READ_DIR " + "can not be granted on files"); + } + + /* Enables Landlock. */ + ruleset_fd = create_ruleset(_metadata, variant->handled, rules); + ASSERT_LE(0, ruleset_fd); + enforce_ruleset(_metadata, ruleset_fd); + ASSERT_EQ(0, close(ruleset_fd)); + + file_fd = open(path, variant->open_mode); + ASSERT_LE(0, file_fd); + + /* + * Checks that IOCTL commands in each IOCTL group return the expected + * errors. + */ + EXPECT_EQ(variant->expected_fioqsize_result, + test_fioqsize_ioctl(file_fd)); + EXPECT_EQ(variant->expected_fibmap_result, test_fibmap_ioctl(file_fd)); + EXPECT_EQ(variant->expected_fionread_result, + test_fionread_ioctl(file_fd)); + EXPECT_EQ(variant->expected_fs_ioc_zero_range_result, + test_fs_ioc_zero_range_ioctl(file_fd)); + EXPECT_EQ(variant->expected_fs_ioc_getflags_result, + test_fs_ioc_getflags_ioctl(file_fd)); + + /* Checks that unrestrictable commands are unrestricted. */ + EXPECT_EQ(0, ioctl(file_fd, FIOCLEX)); + EXPECT_EQ(0, ioctl(file_fd, FIONCLEX)); + EXPECT_EQ(0, ioctl(file_fd, FIONBIO, &flag)); + EXPECT_EQ(0, ioctl(file_fd, FIOASYNC, &flag)); + + ASSERT_EQ(0, close(file_fd)); +} + /* clang-format off */ FIXTURE(layout1_bind) {}; /* clang-format on */ From patchwork Fri Dec 8 15:51:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?G=C3=BCnther_Noack?= X-Patchwork-Id: 13485592 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="gcSmKBq/" Received: from mail-yw1-x114a.google.com (mail-yw1-x114a.google.com [IPv6:2607:f8b0:4864:20::114a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D9D011724 for ; Fri, 8 Dec 2023 07:51:44 -0800 (PST) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-5ca26c07848so28449397b3.0 for ; Fri, 08 Dec 2023 07:51:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1702050704; x=1702655504; darn=vger.kernel.org; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:from:to:cc:subject:date :message-id:reply-to; bh=6mPdEIprGvUFZuXoRGdXLqkm72vuiPRRlFEEhLhd+1s=; b=gcSmKBq/1L3qk1F9Oij9hmCuJx3cmCBt7HsA3lRM8l2Ri0wgQcib8XCNvyh11ELyYy Vfep+VfMHO9Ak4+4VcrjSHg77Ro/on62OtDviJH3Z1073VAUkZZbwC+d65WozaohhpTz IST6IleOUsZOpy8zrSDB5Lk450ItjrbtWBmTYuGvOnQ1kM4trxGIkwPirhMmHawTsShl +wUmXFsPJHUrzCJPAvmulUfMGZIihlFwoWNeAggeFw/xZnmmfkZmQFUPrEIXPCLHUWRh j4AIgrc+NgRd9iUM4TmNkBJcBmmhihsKD32tqzXdQdDLAllHNIKkH4ZBuw14Eo06BMPw bz8g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702050704; x=1702655504; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=6mPdEIprGvUFZuXoRGdXLqkm72vuiPRRlFEEhLhd+1s=; b=ESvY3LetLyjUwps0XHM3toOfggK0hv437HGgvY/u9wnX7mqms6qnYdkMapTZ1wwDQB 4qmU9P0kP6J+mQa4VIr8geOEdKMZ9QD/+8Q3TU/w5YHP66EbEQP0R+qQwcCX3tuixcid UIpcADvCdpaHzZGTSVKRTWnYpxVOhxgzh8nv0mdFVyhfvbc3DGwMgKjDuXsEctJXjiOQ mSQS898lIYEtCzhOoJpvNR2g3KIn3waca4IL/VfkyIvoKoqrdSEUoKf1c2rzCjdv4SDj /DcGKMMvaWUoCbv12DkgsHVagscfY6rgpVkFYXKJWEY11gl7iyOU18BAm6XpRI8gpGQJ GyiA== X-Gm-Message-State: AOJu0YwdrP4+q6UR2MA6GWhj+yX9Cbd/1A7kvLlUy1QI8fyKAP97Ykuv wc0iq4RBkqarx2e7vf/o6ClYq3zStXzJYpujnS1UbS/Dbrb8De9kTdZHWnrXlRpTvo1EGRPSMcv kGwPsdmvSpGaLkjSIcbA3+mg0PAORUAbvzdmJ6bUyV6CktZWaAm68Xzx6zZtSSYGXqMKcueogj0 QBn4888w== X-Google-Smtp-Source: AGHT+IFegrrXXNLonZvTnAfBxTcKZdv4Jx3BrR8i4TJvJucVt//Hla5nVKGApO7TDKDLC1N30gwnhl4Zhr0= X-Received: from sport.zrh.corp.google.com ([2a00:79e0:9d:4:d80e:bfc8:2891:24c1]) (user=gnoack job=sendgmr) by 2002:a05:690c:a8c:b0:5d7:8bf2:de42 with SMTP id ci12-20020a05690c0a8c00b005d78bf2de42mr1866ywb.9.1702050703815; Fri, 08 Dec 2023 07:51:43 -0800 (PST) Date: Fri, 8 Dec 2023 16:51:18 +0100 In-Reply-To: <20231208155121.1943775-1-gnoack@google.com> Message-Id: <20231208155121.1943775-7-gnoack@google.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20231208155121.1943775-1-gnoack@google.com> X-Mailer: git-send-email 2.43.0.472.g3155946c3a-goog Subject: [PATCH v8 6/9] selftests/landlock: Test IOCTL with memfds From: " =?utf-8?q?G=C3=BCnther_Noack?= " To: linux-security-module@vger.kernel.org, " =?utf-8?q?Micka=C3=ABl_Sala?= =?utf-8?q?=C3=BCn?= " Cc: Jeff Xu , Jorge Lucangeli Obes , Allen Webb , Dmitry Torokhov , Paul Moore , Konstantin Meskhidze , Matt Bobrowski , linux-fsdevel@vger.kernel.org, " =?utf-8?q?G=C3=BCnther_Noack?= " Because the LANDLOCK_ACCESS_FS_IOCTL right is associated with the opened file during open(2), IOCTLs are supposed to work with files which are opened by means other than open(2). Signed-off-by: Günther Noack --- tools/testing/selftests/landlock/fs_test.c | 36 ++++++++++++++++------ 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/tools/testing/selftests/landlock/fs_test.c b/tools/testing/selftests/landlock/fs_test.c index 054779ef4527..dcc8ed6cc076 100644 --- a/tools/testing/selftests/landlock/fs_test.c +++ b/tools/testing/selftests/landlock/fs_test.c @@ -3841,20 +3841,38 @@ static int test_fs_ioc_getflags_ioctl(int fd) return 0; } -TEST(memfd_ftruncate) +TEST(memfd_ftruncate_and_ioctl) { - int fd; - - fd = memfd_create("name", MFD_CLOEXEC); - ASSERT_LE(0, fd); + const struct landlock_ruleset_attr attr = { + .handled_access_fs = ACCESS_ALL, + }; + int ruleset_fd, fd, i; /* - * Checks that ftruncate is permitted on file descriptors that are - * created in ways other than open(2). + * We exercise the same test both with and without Landlock enabled, to + * ensure that it behaves the same in both cases. */ - EXPECT_EQ(0, test_ftruncate(fd)); + for (i = 0; i < 2; i++) { + /* Creates a new memfd. */ + fd = memfd_create("name", MFD_CLOEXEC); + ASSERT_LE(0, fd); - ASSERT_EQ(0, close(fd)); + /* + * Checks that operations associated with the opened file + * (ftruncate, ioctl) are permitted on file descriptors that are + * created in ways other than open(2). + */ + EXPECT_EQ(0, test_ftruncate(fd)); + EXPECT_EQ(0, test_fs_ioc_getflags_ioctl(fd)); + + ASSERT_EQ(0, close(fd)); + + /* Enables Landlock. */ + ruleset_fd = landlock_create_ruleset(&attr, sizeof(attr), 0); + ASSERT_LE(0, ruleset_fd); + enforce_ruleset(_metadata, ruleset_fd); + ASSERT_EQ(0, close(ruleset_fd)); + } } /* clang-format off */ From patchwork Fri Dec 8 15:51:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?G=C3=BCnther_Noack?= X-Patchwork-Id: 13485593 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="MAjAqBAD" Received: from mail-wr1-x449.google.com (mail-wr1-x449.google.com [IPv6:2a00:1450:4864:20::449]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 615211734 for ; Fri, 8 Dec 2023 07:51:48 -0800 (PST) Received: by mail-wr1-x449.google.com with SMTP id ffacd0b85a97d-3333c3b6519so1615501f8f.2 for ; Fri, 08 Dec 2023 07:51:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1702050707; x=1702655507; darn=vger.kernel.org; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:from:to:cc:subject:date :message-id:reply-to; bh=avVducTTrz8Unk6ncqcB5xXi1wrDHpE3wxNIhRc8Oys=; b=MAjAqBADgd28HPIVYrmBXgdvBgL4v9Ggd2UYVjCYy1/GK1gV8KgZVJQY0FSnWZtUtO hCeEW/WID9Qv2FP60kiky7faVaLyizSzEJ1nYxXQL5BnPVtVVp4ATh1KPEnNu9kkPqiy lk9apuvnpLM6iNKKE+tyXZip4uaCedk+r3ZYUrXvPgmwU0UeiF0LpTmsp0BI3fbum33H +vnFP6IwarDDDxSiCpciFWFv4BhxqMAQOTfdhJdfX8xOZCv71QjhrQxFTTUjd9E8FU68 AYNpSuv88PuALzJxyNV14DijCra1CwMxycThoxzhqVTIjWOFFpnFlBOLtNxEQBj2cZpN PZOg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702050707; x=1702655507; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=avVducTTrz8Unk6ncqcB5xXi1wrDHpE3wxNIhRc8Oys=; b=QZD/rjG9/su0rUKfwex+s8GrZcAHvrVyN7VomZkUd5g6EuHjRKFavZ31YXFPPVG66h zgetd/hyh8/6Qqjx7kdmlHt40YcF9rIf6Z46tOpod1c43K9B1jKa9WcxRSabrZ14Xrs9 J20WWp6f2bg2f/CE4lR/Njonzgn/blqJpqXZmfIUCaodCKT6X1G4OyDxbdiWC344TpC+ 9xr9zvxb+7UlZ2w7xQehp7EmXTAxC8ppeprs23kjDpbA6ZshWnD6Zzib1rb0E6tjzXrk zH2vln11JJwNkD38lZRzluTzeR9QRJtqDWuQEpQTf8WbdkfYOGvRA40HKBlMOdqVxxl8 1HKQ== X-Gm-Message-State: AOJu0YyZNuKDu+MjFIHTlJowlol6QpsM1tknczMjrskq9A+z9i3oyfaT cibM6S9owEOy4QdeJpartYPdTsa6lUajI5t4OIP93cq9nZ10cmu7k09P/TnvIjnDRtxLY5XNYM7 TL6zDMr/QTOuHozsxLnmZ6RAuvSt+scLBfbvBRuq+eKq1RU6BM1Fq6uARx6bSOC+XOoRqLtSwaZ 09qiAuVw== X-Google-Smtp-Source: AGHT+IGhon+9+mocZYXG/AkXZxfC8IiQVxvHXSA6wYkfaJglO6e4cFbNuHxeQEqiqKsISXIhQUWVcqKng7U= X-Received: from sport.zrh.corp.google.com ([2a00:79e0:9d:4:d80e:bfc8:2891:24c1]) (user=gnoack job=sendgmr) by 2002:adf:d1cf:0:b0:333:5232:d7f5 with SMTP id b15-20020adfd1cf000000b003335232d7f5mr1303wrd.8.1702050706550; Fri, 08 Dec 2023 07:51:46 -0800 (PST) Date: Fri, 8 Dec 2023 16:51:19 +0100 In-Reply-To: <20231208155121.1943775-1-gnoack@google.com> Message-Id: <20231208155121.1943775-8-gnoack@google.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20231208155121.1943775-1-gnoack@google.com> X-Mailer: git-send-email 2.43.0.472.g3155946c3a-goog Subject: [PATCH v8 7/9] selftests/landlock: Test ioctl(2) and ftruncate(2) with open(O_PATH) From: " =?utf-8?q?G=C3=BCnther_Noack?= " To: linux-security-module@vger.kernel.org, " =?utf-8?q?Micka=C3=ABl_Sala?= =?utf-8?q?=C3=BCn?= " Cc: Jeff Xu , Jorge Lucangeli Obes , Allen Webb , Dmitry Torokhov , Paul Moore , Konstantin Meskhidze , Matt Bobrowski , linux-fsdevel@vger.kernel.org, " =?utf-8?q?G=C3=BCnther_Noack?= " ioctl(2) and ftruncate(2) operations on files opened with O_PATH should always return EBADF, independent of the LANDLOCK_ACCESS_FS_TRUNCATE and LANDLOCK_ACCESS_FS_IOCTL access rights in that file hierarchy. Suggested-by: Mickaël Salaün Signed-off-by: Günther Noack --- tools/testing/selftests/landlock/fs_test.c | 40 ++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/tools/testing/selftests/landlock/fs_test.c b/tools/testing/selftests/landlock/fs_test.c index dcc8ed6cc076..89d1e4af6fb2 100644 --- a/tools/testing/selftests/landlock/fs_test.c +++ b/tools/testing/selftests/landlock/fs_test.c @@ -3875,6 +3875,46 @@ TEST(memfd_ftruncate_and_ioctl) } } +TEST_F_FORK(layout1, o_path_ftruncate_and_ioctl) +{ + const struct landlock_ruleset_attr attr = { + .handled_access_fs = ACCESS_ALL, + }; + int ruleset_fd, fd; + + /* + * Checks that for files opened with O_PATH, both ioctl(2) and + * ftruncate(2) yield EBADF, as it is documented in open(2) for the + * O_PATH flag. + */ + fd = open(dir_s1d1, O_PATH | O_CLOEXEC); + ASSERT_LE(0, fd); + + EXPECT_EQ(EBADF, test_ftruncate(fd)); + EXPECT_EQ(EBADF, test_fs_ioc_getflags_ioctl(fd)); + + ASSERT_EQ(0, close(fd)); + + /* Enables Landlock. */ + ruleset_fd = landlock_create_ruleset(&attr, sizeof(attr), 0); + ASSERT_LE(0, ruleset_fd); + enforce_ruleset(_metadata, ruleset_fd); + ASSERT_EQ(0, close(ruleset_fd)); + + /* + * Checks that after enabling Landlock, + * - the file can still be opened with O_PATH + * - both ioctl and truncate still yield EBADF (not EACCES). + */ + fd = open(dir_s1d1, O_PATH | O_CLOEXEC); + ASSERT_LE(0, fd); + + EXPECT_EQ(EBADF, test_ftruncate(fd)); + EXPECT_EQ(EBADF, test_fs_ioc_getflags_ioctl(fd)); + + ASSERT_EQ(0, close(fd)); +} + /* clang-format off */ FIXTURE(ioctl) {}; /* clang-format on */ From patchwork Fri Dec 8 15:51:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?G=C3=BCnther_Noack?= X-Patchwork-Id: 13485594 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="GzFCvtFG" Received: from mail-yw1-x114a.google.com (mail-yw1-x114a.google.com [IPv6:2607:f8b0:4864:20::114a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F1E411985 for ; Fri, 8 Dec 2023 07:51:50 -0800 (PST) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-5d3a1e5f8d6so27481887b3.3 for ; Fri, 08 Dec 2023 07:51:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1702050710; x=1702655510; darn=vger.kernel.org; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:from:to:cc:subject:date :message-id:reply-to; bh=6kdDoWcSv0tcnaDo2x6ejdD3WMv5LtvRZfR97Sl3d0s=; b=GzFCvtFGMMCJQWVmVgkYbB1FAg7fqFByt9RYcg/54PIugE0l5nUxVXLhicmUFrreKk 1t93NHhwKmQPg7QLmMUMnYKbKFtnjMEMAVSIVJATBjizA4yaFTiv4CmOatAvVfcUIX6E Y9NIARgflxXGtEjTVpHVuuJAhR6zio/M6QfNL7Soqbx158Pjfe4llnUwJJiJufgEJ6Kw VwE/i9qdHYtyUk3P1l0jasb6EwhbAhRl4yQySWZUz9svDfKIvZY56lMt20E3FRbxqVi7 6JpLqkluIRuUHh7DsEGp96vhgc8g9IOfuQCjobM63Gl7aLExZ75U8Ki1pFqKRgRVX1Uv +/Sg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702050710; x=1702655510; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=6kdDoWcSv0tcnaDo2x6ejdD3WMv5LtvRZfR97Sl3d0s=; b=SpItwDA+/jXJv01iHOknKaRyy1+I0NkeHaY7Htgcy3wo+FGccgexNHtwId5o8RwhlC 82Fx2c/QjUR36aPFFTqjvwlrVRyRlGS57lzj9ZQzJL5xvK5fgqqRkKcIGVj6A0k6LDk4 zEetN2Cez5uQNYw638l4KYwETtCrrXpuiSGubcrnNStUZhz21AlzU0HgR50rbseprq3L RSq3914Tko/3vn/jfzSVSVwrJZ0nlMDb3koCfuS9QqJ1RNqbK1lQ5ju6WSROk82RM8Al cVDLhUQ2SeMyfb8n5qmDT/pz658aD99UZqCuQDSf0QDlCWDjuFhea3NLJewDpa94sAqB pQkg== X-Gm-Message-State: AOJu0Yw977TtHne60XPr+Cw6EKz8irdJN+xnw89FZQk82kUAODdXunhM +uN47oLNFYNvDZyUA9ABC0K+IE7hDTWkZYjnKCQKWlj6J3vafPRcMGYii/7AxHFWv1Mr7k4IQPk tBDmPYlWQZB10/8zf+4NNO2Mwb2oYVqSQsik4HLYK7c7PClTpcEaaDOSu/Mb6bLMNCDdW9DCMA/ tUIm/hpA== X-Google-Smtp-Source: AGHT+IH2GK2Km/C+rYT3PFzl4qwVpQygC8rxDh3OJ/ae0rcaiPeC3ig+gpdwmILJ+jIPiMLTvaxKXK7nyak= X-Received: from sport.zrh.corp.google.com ([2a00:79e0:9d:4:d80e:bfc8:2891:24c1]) (user=gnoack job=sendgmr) by 2002:a05:690c:3505:b0:5ca:c025:3cb9 with SMTP id fq5-20020a05690c350500b005cac0253cb9mr2108ywb.1.1702050709352; Fri, 08 Dec 2023 07:51:49 -0800 (PST) Date: Fri, 8 Dec 2023 16:51:20 +0100 In-Reply-To: <20231208155121.1943775-1-gnoack@google.com> Message-Id: <20231208155121.1943775-9-gnoack@google.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20231208155121.1943775-1-gnoack@google.com> X-Mailer: git-send-email 2.43.0.472.g3155946c3a-goog Subject: [PATCH v8 8/9] samples/landlock: Add support for LANDLOCK_ACCESS_FS_IOCTL From: " =?utf-8?q?G=C3=BCnther_Noack?= " To: linux-security-module@vger.kernel.org, " =?utf-8?q?Micka=C3=ABl_Sala?= =?utf-8?q?=C3=BCn?= " Cc: Jeff Xu , Jorge Lucangeli Obes , Allen Webb , Dmitry Torokhov , Paul Moore , Konstantin Meskhidze , Matt Bobrowski , linux-fsdevel@vger.kernel.org, " =?utf-8?q?G=C3=BCnther_Noack?= " Add ioctl support to the Landlock sample tool. The ioctl right is grouped with the read-write rights in the sample tool, as some ioctl requests provide features that mutate state. Signed-off-by: Günther Noack --- samples/landlock/sandboxer.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/samples/landlock/sandboxer.c b/samples/landlock/sandboxer.c index 08596c0ef070..d7323e5526be 100644 --- a/samples/landlock/sandboxer.c +++ b/samples/landlock/sandboxer.c @@ -81,7 +81,8 @@ static int parse_path(char *env_path, const char ***const path_list) LANDLOCK_ACCESS_FS_EXECUTE | \ LANDLOCK_ACCESS_FS_WRITE_FILE | \ LANDLOCK_ACCESS_FS_READ_FILE | \ - LANDLOCK_ACCESS_FS_TRUNCATE) + LANDLOCK_ACCESS_FS_TRUNCATE | \ + LANDLOCK_ACCESS_FS_IOCTL) /* clang-format on */ @@ -199,11 +200,12 @@ static int populate_ruleset_net(const char *const env_var, const int ruleset_fd, LANDLOCK_ACCESS_FS_MAKE_BLOCK | \ LANDLOCK_ACCESS_FS_MAKE_SYM | \ LANDLOCK_ACCESS_FS_REFER | \ - LANDLOCK_ACCESS_FS_TRUNCATE) + LANDLOCK_ACCESS_FS_TRUNCATE | \ + LANDLOCK_ACCESS_FS_IOCTL) /* clang-format on */ -#define LANDLOCK_ABI_LAST 4 +#define LANDLOCK_ABI_LAST 5 int main(const int argc, char *const argv[], char *const *const envp) { @@ -317,6 +319,11 @@ int main(const int argc, char *const argv[], char *const *const envp) ruleset_attr.handled_access_net &= ~(LANDLOCK_ACCESS_NET_BIND_TCP | LANDLOCK_ACCESS_NET_CONNECT_TCP); + __attribute__((fallthrough)); + case 4: + /* Removes LANDLOCK_ACCESS_FS_IOCTL for ABI < 5 */ + ruleset_attr.handled_access_fs &= ~LANDLOCK_ACCESS_FS_IOCTL; + fprintf(stderr, "Hint: You should update the running kernel " "to leverage Landlock features " From patchwork Fri Dec 8 15:51:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?G=C3=BCnther_Noack?= X-Patchwork-Id: 13485595 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="hClVuVGf" Received: from mail-yw1-x114a.google.com (mail-yw1-x114a.google.com [IPv6:2607:f8b0:4864:20::114a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9BC841724 for ; Fri, 8 Dec 2023 07:51:53 -0800 (PST) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-5d340a9cf07so27631847b3.3 for ; Fri, 08 Dec 2023 07:51:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1702050713; x=1702655513; darn=vger.kernel.org; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:from:to:cc:subject:date :message-id:reply-to; bh=mju3ViF0d/Jk5ieUylmRq+FCfb/T1IaKWcGes5aRqrg=; b=hClVuVGfdMr5wkmZn0X4IU5Ym4fDxgEo5MgxpHddwJ9K5yfmeS61BJ7jHgSQG4NF+v f5wMVulB9R0CFIchJGPrYdBlI9jPjDr5CnV5cn4BQEOujA7xHKfAOhecsMT7Z+y/oYJl j1MH+oKSsG47B2yJJGnwwxklOuTDzHuCf8qDcjEmmunPVjzhr6eHmFPTka1JM2Uy83mq oq/S1iA9f3czBRBump4De8+EowfOFhiakt6Nu1i+O0n0jvCBPkH5V3jC1cq3Q7jSFLlx uQ6udW9iohe2bf0o4v9r5BU/v0qUpZrK7KaWLfpXuLBNZbj54s+H+z/XCU50+zCXSUhC xm2w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702050713; x=1702655513; h=content-transfer-encoding:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=mju3ViF0d/Jk5ieUylmRq+FCfb/T1IaKWcGes5aRqrg=; b=Pw0NabDMS9HRLeRTCh/nS69PBtj4YbtHyP//a+jnpZ/+HZ3QON9Snf1iF3y8r7/fVj l+wgX8eZvntR3fenxyptnETYlutYql0Bt8Uv7FmiXzua49dLaEQpmtt9RvWv4CPWIIng +6jgixTBImqyN0tDDmX7YNcXfqyRZwJpb0Lq+hk5n5iSzDgIdALAZYamKcjCVlth4LtV NAUDdi7NZcHYH+TasquxOcm11G3THI+qmxHF+x2TrWgh9i1dGcjxiQGWGQfsC/FnO5Sw Qn5VglONy1NRWgJuGwGtU4qMKn5wVkhjGQD9AhLkUvjLBe5wpN9S0yyosBli/gZ98jMV Ff/g== X-Gm-Message-State: AOJu0YxN+YfbE5BUU3PF1zE3o9epV5zomFRgV9XJkyo2apB4BHLGOMTI rsWIN37gFYviE4TEeNnjqp7WXFmgVXbOwLkvt1g0UkTcB0IHns81M/oQHIIYLDfoY665ELsSvMH wS3cPj0AFkse+2+xUNYvtkrVvbZABOhXSe/N7s2o1PGVhcv+v2B+R0pNXU8QC5xTZvMXt/WjUbj XiX4I8YA== X-Google-Smtp-Source: AGHT+IF08Rhtqy3Dy8W8OMYKeuBaF2V/tUXkUmZOLclD76Htb9sZGykZKBCDCf47NU7fqO4KDAlQIZtzMwE= X-Received: from sport.zrh.corp.google.com ([2a00:79e0:9d:4:d80e:bfc8:2891:24c1]) (user=gnoack job=sendgmr) by 2002:a05:690c:b9d:b0:5a8:33ab:d545 with SMTP id ck29-20020a05690c0b9d00b005a833abd545mr2810ywb.2.1702050712043; Fri, 08 Dec 2023 07:51:52 -0800 (PST) Date: Fri, 8 Dec 2023 16:51:21 +0100 In-Reply-To: <20231208155121.1943775-1-gnoack@google.com> Message-Id: <20231208155121.1943775-10-gnoack@google.com> Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20231208155121.1943775-1-gnoack@google.com> X-Mailer: git-send-email 2.43.0.472.g3155946c3a-goog Subject: [PATCH v8 9/9] landlock: Document IOCTL support From: " =?utf-8?q?G=C3=BCnther_Noack?= " To: linux-security-module@vger.kernel.org, " =?utf-8?q?Micka=C3=ABl_Sala?= =?utf-8?q?=C3=BCn?= " Cc: Jeff Xu , Jorge Lucangeli Obes , Allen Webb , Dmitry Torokhov , Paul Moore , Konstantin Meskhidze , Matt Bobrowski , linux-fsdevel@vger.kernel.org, " =?utf-8?q?G=C3=BCnther_Noack?= " In the paragraph above the fallback logic, use the shorter phrasing from the landlock(7) man page. Signed-off-by: Günther Noack --- Documentation/userspace-api/landlock.rst | 119 ++++++++++++++++++++--- 1 file changed, 104 insertions(+), 15 deletions(-) diff --git a/Documentation/userspace-api/landlock.rst b/Documentation/userspace-api/landlock.rst index 2e3822677061..8398851964e6 100644 --- a/Documentation/userspace-api/landlock.rst +++ b/Documentation/userspace-api/landlock.rst @@ -75,7 +75,8 @@ to be explicit about the denied-by-default access rights. LANDLOCK_ACCESS_FS_MAKE_BLOCK | LANDLOCK_ACCESS_FS_MAKE_SYM | LANDLOCK_ACCESS_FS_REFER | - LANDLOCK_ACCESS_FS_TRUNCATE, + LANDLOCK_ACCESS_FS_TRUNCATE | + LANDLOCK_ACCESS_FS_IOCTL, .handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP | LANDLOCK_ACCESS_NET_CONNECT_TCP, @@ -84,10 +85,10 @@ to be explicit about the denied-by-default access rights. Because we may not know on which kernel version an application will be executed, it is safer to follow a best-effort security approach. Indeed, we should try to protect users as much as possible whatever the kernel they are -using. To avoid binary enforcement (i.e. either all security features or -none), we can leverage a dedicated Landlock command to get the current version -of the Landlock ABI and adapt the handled accesses. Let's check if we should -remove access rights which are only supported in higher versions of the ABI. +using. + +To be compatible with older Linux versions, we detect the available Landlock ABI +version, and only use the available subset of access rights: .. code-block:: c @@ -113,6 +114,10 @@ remove access rights which are only supported in higher versions of the ABI. ruleset_attr.handled_access_net &= ~(LANDLOCK_ACCESS_NET_BIND_TCP | LANDLOCK_ACCESS_NET_CONNECT_TCP); + __attribute__((fallthrough)); + case 4: + /* Removes LANDLOCK_ACCESS_FS_IOCTL for ABI < 5 */ + ruleset_attr.handled_access_fs &= ~LANDLOCK_ACCESS_FS_IOCTL; } This enables to create an inclusive ruleset that will contain our rules. @@ -224,6 +229,7 @@ access rights per directory enables to change the location of such directory without relying on the destination directory access rights (except those that are required for this operation, see ``LANDLOCK_ACCESS_FS_REFER`` documentation). + Having self-sufficient hierarchies also helps to tighten the required access rights to the minimal set of data. This also helps avoid sinkhole directories, i.e. directories where data can be linked to but not linked from. However, @@ -317,18 +323,69 @@ It should also be noted that truncating files does not require the system call, this can also be done through :manpage:`open(2)` with the flags ``O_RDONLY | O_TRUNC``. -When opening a file, the availability of the ``LANDLOCK_ACCESS_FS_TRUNCATE`` -right is associated with the newly created file descriptor and will be used for -subsequent truncation attempts using :manpage:`ftruncate(2)`. The behavior is -similar to opening a file for reading or writing, where permissions are checked -during :manpage:`open(2)`, but not during the subsequent :manpage:`read(2)` and +The truncate right is associated with the opened file (see below). + +Rights associated with file descriptors +--------------------------------------- + +When opening a file, the availability of the ``LANDLOCK_ACCESS_FS_TRUNCATE`` and +``LANDLOCK_ACCESS_FS_IOCTL`` rights is associated with the newly created file +descriptor and will be used for subsequent truncation and ioctl attempts using +:manpage:`ftruncate(2)` and :manpage:`ioctl(2)`. The behavior is similar to +opening a file for reading or writing, where permissions are checked during +:manpage:`open(2)`, but not during the subsequent :manpage:`read(2)` and :manpage:`write(2)` calls. -As a consequence, it is possible to have multiple open file descriptors for the -same file, where one grants the right to truncate the file and the other does -not. It is also possible to pass such file descriptors between processes, -keeping their Landlock properties, even when these processes do not have an -enforced Landlock ruleset. +As a consequence, it is possible that a process has multiple open file +descriptors referring to the same file, but Landlock enforces different things +when operating with these file descriptors. This can happen when a Landlock +ruleset gets enforced and the process keeps file descriptors which were opened +both before and after the enforcement. It is also possible to pass such file +descriptors between processes, keeping their Landlock properties, even when some +of the involved processes do not have an enforced Landlock ruleset. + +Restricting IOCTL commands +-------------------------- + +When the ``LANDLOCK_ACCESS_FS_IOCTL`` access right is handled, Landlock will +restrict the invocation of IOCTL commands. However, to *permit* these IOCTL +commands again, some of these IOCTL commands are then granted through other, +preexisting access rights. + +For example, consider a program which handles ``LANDLOCK_ACCESS_FS_IOCTL`` and +``LANDLOCK_ACCESS_FS_READ_FILE``. The program *permits* +``LANDLOCK_ACCESS_FS_READ_FILE`` on a file ``foo.log``. + +By virtue of granting this access on the ``foo.log`` file, it is now possible to +use common and harmless IOCTL commands which are useful when reading files, such +as ``FIONREAD``. + +On the other hand, if the program permits ``LANDLOCK_ACCESS_FS_IOCTL`` on +another file, ``FIONREAD`` will not work on that file when it is opened. As +soon as ``LANDLOCK_ACCESS_FS_READ_FILE`` is *handled* in the ruleset, the IOCTL +commands affected by it can not be reenabled though ``LANDLOCK_ACCESS_FS_IOCTL`` +any more, but are then governed by ``LANDLOCK_ACCESS_FS_READ_FILE``. + +The following table illustrates how IOCTL attempts for ``FIONREAD`` are +filtered, depending on how a Landlock ruleset handles and permits the +``LANDLOCK_ACCESS_FS_IOCTL`` and ``LANDLOCK_ACCESS_FS_READ_FILE`` access rights: + ++------------------------+-------------+-------------------+-------------------+ +| | ``IOCTL`` | ``IOCTL`` handled | ``IOCTL`` handled | +| | not handled | and permitted | and not permitted | ++------------------------+-------------+-------------------+-------------------+ +| ``READ_FILE`` not | allow | allow | deny | +| handled | | | | ++------------------------+ +-------------------+-------------------+ +| ``READ_FILE`` handled | | allow | +| and permitted | | | ++------------------------+ +-------------------+-------------------+ +| ``READ_FILE`` handled | | deny | +| and not permitted | | | ++------------------------+-------------+-------------------+-------------------+ + +The full list of IOCTL commands and the access rights which affect them is +documented below. Compatibility ============= @@ -457,6 +514,28 @@ Memory usage Kernel memory allocated to create rulesets is accounted and can be restricted by the Documentation/admin-guide/cgroup-v1/memory.rst. +IOCTL support +------------- + +The ``LANDLOCK_ACCESS_FS_IOCTL`` access right restricts the use of +:manpage:`ioctl(2)`, but it only applies to newly opened files. This means +specifically that pre-existing file descriptors like stdin, stdout and stderr +are unaffected. + +Users should be aware that TTY devices have traditionally permitted to control +other processes on the same TTY through the ``TIOCSTI`` and ``TIOCLINUX`` IOCTL +commands. It is therefore recommended to close inherited TTY file descriptors, +or to reopen them from ``/proc/self/fd/*`` without the +``LANDLOCK_ACCESS_FS_IOCTL`` right, if possible. The :manpage:`isatty(3)` +function checks whether a given file descriptor is a TTY. + +Landlock's IOCTL support is coarse-grained at the moment, but may become more +fine-grained in the future. Until then, users are advised to establish the +guarantees that they need through the file hierarchy, by only permitting the +``LANDLOCK_ACCESS_FS_IOCTL`` right on files where it is really harmless. In +cases where you can control the mounts, the ``nodev`` mount option can help to +rule out that device files can be accessed. + Previous limitations ==================== @@ -494,6 +573,16 @@ bind and connect actions to only a set of allowed ports thanks to the new ``LANDLOCK_ACCESS_NET_BIND_TCP`` and ``LANDLOCK_ACCESS_NET_CONNECT_TCP`` access rights. +IOCTL (ABI < 5) +--------------- + +IOCTL operations could not be denied before the fifth Landlock ABI, so +:manpage:`ioctl(2)` is always allowed when using a kernel that only supports an +earlier ABI. + +Starting with the Landlock ABI version 5, it is possible to restrict the use of +:manpage:`ioctl(2)` using the new ``LANDLOCK_ACCESS_FS_IOCTL`` access right. + .. _kernel_support: Kernel support