From: "Mickaël Salaün" <mic@digikod.net>
To: Tingmao Wang <m@maowtm.org>
Cc: "Günther Noack" <gnoack3000@gmail.com>,
"Justin Suess" <utilityemal77@gmail.com>,
"Jan Kara" <jack@suse.cz>, "Abhinav Saxena" <xandfury@gmail.com>,
linux-security-module@vger.kernel.org
Subject: Re: [PATCH v8 3/9] landlock: Suppress logging when quiet flag is present
Date: Mon, 25 May 2026 22:40:05 +0200 [thread overview]
Message-ID: <20260525.xoh3Queurofu@digikod.net> (raw)
In-Reply-To: <5a253279ddbc797fa320849e46f7c88d7578a581.1775490344.git.m@maowtm.org>
On Mon, Apr 06, 2026 at 04:52:16PM +0100, Tingmao Wang wrote:
> The quietness behaviour is as documented in the previous patch.
>
> For optional accesses, since the existing deny_masks can only store 2x4bit
> of layer index, with no way to represent "no layer", we need to either
> expand it or have another field to correctly handle quieting of those.
> This commit uses the latter approach - we add another field to store which
> optional access (of the 2) are covered by quiet rules in their respective
> layers as stored in deny_masks.
>
> We can avoid making struct landlock_file_security larger by converting the
> existing fown_layer to a 4bit field. This commit does that, and adds test
> to ensure that it is large enough for LANDLOCK_MAX_NUM_LAYERS-1.
>
> Signed-off-by: Tingmao Wang <m@maowtm.org>
> ---
>
> Changes in v8:
> - Rebase on top of mic/next
> - Populate request.rule_flags in hook_unix_find()
>
> Changes in v7:
> - Following change in commit 1, now we need to copy rule_flags into
> landlock_request before calling landlock_log_denial for relevant fs
> denials
> - Remove left over param comment
>
> Changes in v5:
> - Update code style and comment in get_layer_from_deny_masks() and
> landlock_log_denial()
> - Now that rule_flags is moved into landlock_request, this version removes
> the extra parameter for landlock_log_denial and gets rid of
> no_rule_flags, simplifying some code.
> - Fix build failure without CONFIG_AUDIT (reported by Justin Suess)
>
> Changes in v3:
> - Renamed patch title from "Check for quiet flag in landlock_log_denial"
> to this given the growth.
> - Moved quiet bit check after domain_exec check
> - Rename, style and comment fixes suggested by Mickaël.
> - Squashed patch 6/6 from v2 "Implement quiet for optional accesses" into
> this one. Changes to that below:
> - Refactor the quiet flag setting in get_layer_from_deny_masks() to be
> more clear.
> - Add KUnit tests
> - Fix comments, add WARN_ON_ONCE, use __const_hweight64() as suggested by
> review
> - Move build_check_file_security to fs.c
> - Use a typedef for quiet_optional_accesses, add static_assert, and
> improve docs on landlock_get_quiet_optional_accesses.
>
> Changes in v2:
> - Supports the new quiet access masks.
> - Support quieting scope requests (but not ptrace and attempted mounting
> for now)
>
> security/landlock/access.h | 5 +
> security/landlock/audit.c | 255 +++++++++++++++++++++++++++++++++++--
> security/landlock/audit.h | 3 +
> security/landlock/domain.c | 33 +++++
> security/landlock/domain.h | 5 +
> security/landlock/fs.c | 35 +++++
> security/landlock/fs.h | 17 ++-
> security/landlock/net.c | 16 +--
> 8 files changed, 340 insertions(+), 29 deletions(-)
>
> diff --git a/security/landlock/access.h b/security/landlock/access.h
> index c19d5bc13944..2775df80c7da 100644
> --- a/security/landlock/access.h
> +++ b/security/landlock/access.h
> @@ -120,4 +120,9 @@ static inline bool access_mask_subset(access_mask_t subset,
> return (subset | superset) == superset;
> }
>
> +/* A bitmask that is large enough to hold set of optional accesses. */
> +typedef u8 optional_access_t;
> +static_assert(BITS_PER_TYPE(optional_access_t) >=
> + HWEIGHT(_LANDLOCK_ACCESS_FS_OPTIONAL));
> +
> #endif /* _SECURITY_LANDLOCK_ACCESS_H */
> diff --git a/security/landlock/audit.c b/security/landlock/audit.c
> index 8d0edf94037d..2941b6d88688 100644
> --- a/security/landlock/audit.c
> +++ b/security/landlock/audit.c
> @@ -246,7 +246,8 @@ static void test_get_denied_layer(struct kunit *const test)
> static size_t
> get_layer_from_deny_masks(access_mask_t *const access_request,
> const access_mask_t all_existing_optional_access,
> - const deny_masks_t deny_masks)
> + const deny_masks_t deny_masks,
> + u8 quiet_optional_accesses, bool *quiet)
optional_access_t quiet_optional_accesses
This type should be used everywhere.
> {
> const unsigned long access_opt = all_existing_optional_access;
> const unsigned long access_req = *access_request;
> @@ -254,6 +255,7 @@ get_layer_from_deny_masks(access_mask_t *const access_request,
> size_t youngest_layer = 0;
> size_t access_index = 0;
> unsigned long access_bit;
> + bool should_quiet = false;
>
> /* This will require change with new object types. */
> WARN_ON_ONCE(access_opt != _LANDLOCK_ACCESS_FS_OPTIONAL);
> @@ -264,18 +266,29 @@ get_layer_from_deny_masks(access_mask_t *const access_request,
> const size_t layer =
> (deny_masks >> (access_index * 4)) &
> (LANDLOCK_MAX_NUM_LAYERS - 1);
> + const bool layer_has_quiet =
> + !!(quiet_optional_accesses & BIT(access_index));
>
> if (layer > youngest_layer) {
> youngest_layer = layer;
> missing = BIT(access_bit);
> + should_quiet = layer_has_quiet;
> } else if (layer == youngest_layer) {
> missing |= BIT(access_bit);
> + /*
> + * Whether the layer has rules with quiet flag covering
> + * the file accessed does not depend on the access, and so
> + * the following WARN_ON_ONCE() should not fail.
> + */
> + WARN_ON_ONCE(should_quiet && !layer_has_quiet);
> + should_quiet = layer_has_quiet;
> }
> }
> access_index++;
> }
>
> *access_request = missing;
> + *quiet = should_quiet;
> return youngest_layer;
> }
>
> @@ -285,42 +298,188 @@ static void test_get_layer_from_deny_masks(struct kunit *const test)
> {
> deny_masks_t deny_mask;
> access_mask_t access;
> + u8 quiet_optional_accesses;
ditto
> diff --git a/security/landlock/audit.h b/security/landlock/audit.h
> index 56778331b58c..c2da854d4405 100644
> --- a/security/landlock/audit.h
> +++ b/security/landlock/audit.h
> @@ -48,6 +48,9 @@ struct landlock_request {
> /* Required fields for requests with deny masks. */
> const access_mask_t all_existing_optional_access;
> deny_masks_t deny_masks;
> + u8 quiet_optional_accesses;
ditto, use optional_access_t
> +
> + struct collected_rule_flags rule_flags;
> };
>
> #ifdef CONFIG_AUDIT
> diff --git a/security/landlock/domain.c b/security/landlock/domain.c
> index 06b6bd845060..f365721050b7 100644
> --- a/security/landlock/domain.c
> +++ b/security/landlock/domain.c
> @@ -156,6 +156,39 @@ get_layer_deny_mask(const access_mask_t all_existing_optional_access,
> << ((access_weight - 1) * HWEIGHT(LANDLOCK_MAX_NUM_LAYERS - 1));
> }
>
> +/**
> + * landlock_get_quiet_optional_accesses - Get optional accesses which are
> + * "covered" by quiet rule flags.
> + *
> + * Returns a bitmask of which optional access are denied by layers for
> + * which rule_flags.quiet_masks has the corresponding bit set.
> + */
> +optional_access_t landlock_get_quiet_optional_accesses(
> + const access_mask_t all_existing_optional_access,
> + const deny_masks_t deny_masks,
> + const struct collected_rule_flags rule_flags)
> +{
> + const unsigned long access_opt = all_existing_optional_access;
> + size_t access_index = 0;
> + unsigned long access_bit;
> + optional_access_t quiet_optional_accesses = 0;
It's only correct here.
> +
> + /* This will require change with new object types. */
> + WARN_ON_ONCE(access_opt != _LANDLOCK_ACCESS_FS_OPTIONAL);
> +
> + for_each_set_bit(access_bit, &access_opt,
> + BITS_PER_TYPE(access_mask_t)) {
> + const u8 layer = (deny_masks >> (access_index * 4)) &
> + (LANDLOCK_MAX_NUM_LAYERS - 1);
> + const bool is_quiet = !!(rule_flags.quiet_masks & BIT(layer));
> +
> + if (is_quiet)
> + quiet_optional_accesses |= BIT(access_index);
> + access_index++;
> + }
> + return quiet_optional_accesses;
> +}
> +
> #ifdef CONFIG_SECURITY_LANDLOCK_KUNIT_TEST
>
> static void test_get_layer_deny_mask(struct kunit *const test)
next prev parent reply other threads:[~2026-05-25 20:40 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-06 15:52 [PATCH v8 0/9] Implement LANDLOCK_ADD_RULE_QUIET Tingmao Wang
2026-04-06 15:52 ` [PATCH v8 1/9] landlock: Add a place for flags to layer rules Tingmao Wang
2026-05-23 20:48 ` Mickaël Salaün
2026-05-24 1:29 ` Tingmao Wang
2026-05-24 14:46 ` Justin Suess
2026-05-24 18:20 ` Tingmao Wang
2026-05-24 22:08 ` Justin Suess
2026-05-25 20:39 ` Mickaël Salaün
2026-05-24 20:35 ` Mickaël Salaün
2026-04-06 15:52 ` [PATCH v8 2/9] landlock: Add API support and docs for the quiet flags Tingmao Wang
2026-05-24 20:35 ` Mickaël Salaün
2026-04-06 15:52 ` [PATCH v8 3/9] landlock: Suppress logging when quiet flag is present Tingmao Wang
2026-05-25 20:40 ` Mickaël Salaün [this message]
2026-04-06 15:52 ` [PATCH v8 4/9] samples/landlock: Add quiet flag support to sandboxer Tingmao Wang
2026-04-06 15:52 ` [PATCH v8 5/9] selftests/landlock: Replace hard-coded 16 with a constant Tingmao Wang
2026-04-06 15:52 ` [PATCH v8 6/9] selftests/landlock: add tests for quiet flag with fs rules Tingmao Wang
2026-04-06 15:52 ` [PATCH v8 7/9] selftests/landlock: add tests for quiet flag with net rules Tingmao Wang
2026-04-06 15:52 ` [PATCH v8 8/9] selftests/landlock: Add tests for quiet flag with scope Tingmao Wang
2026-04-06 15:52 ` [PATCH v8 9/9] selftests/landlock: Add tests for invalid use of quiet flag Tingmao Wang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260525.xoh3Queurofu@digikod.net \
--to=mic@digikod.net \
--cc=gnoack3000@gmail.com \
--cc=jack@suse.cz \
--cc=linux-security-module@vger.kernel.org \
--cc=m@maowtm.org \
--cc=utilityemal77@gmail.com \
--cc=xandfury@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox