[PATCH v9 1/9] landlock: Add a place for flags to layer rules
Justin Suess
utilityemal77 at gmail.com
Thu May 28 22:01:10 UTC 2026
On Wed, May 27, 2026 at 02:01:11AM +0100, Tingmao Wang wrote:
> To avoid unnecessarily increasing the size of struct landlock_layer, we
> make the layer level a u8 and use the space to store the flags struct.
>
> struct layer_access_masks is renamed to struct layer_masks, and a new
> field is added to track whether a quiet flag rule is seen for each
> layer. Through use of bitfields, this does not increase the size of the
> struct.
>
> Cc: Justin Suess <utilityemal77 at gmail.com>
> Assisted-by: GitHub Copilot:claude-opus-4.7 copilot-review
> Signed-off-by: Tingmao Wang <m at maowtm.org>
> Co-developed-by: Justin Suess <utilityemal77 at gmail.com>
> Signed-off-by: Justin Suess <utilityemal77 at gmail.com>
> ---
>
> Changes in v9:
> - Move a hunk from patch 2 to here
> - Fix comment and format
> - Renamed struct layer_access_masks to struct layer_masks, and moved the
> content of struct collected_rule_flags into this struct, getting rid
> of the extra struct collected_rule_flags and function parameters.
> This is following a discussion in [3]. The flag is now initialized in
> landlock_init_layer_masks as false.
> - Thus also removed now unnecessary layer_mask_t
>
> Changes in v8:
> - Rebase on top of mic/next
> - Add Co-developed-by: Justin Suess for handling this rebase initially
> - layer_mask_t was removed in [1] but we still need it for the
> collected_rule_flags. Rather than using raw u16, I've chosen to
> re-define it back in ruleset.h (it was in access.h).
>
> Changes in v7:
> - Take rule_flags separately from landlock_request in
> is_access_to_paths_allowed to avoid writing to the landlock_request
> variable if CONFIG_AUDIT is disabled (to enable compiler elision).
> - Due to the above change, we don't need rule_flags in landlock_request in
> this commit anymore (will be added later).
>
> Changes in v6:
> - Rebased to include the revised disconnected directory handling changes
> (without the "reverting" behaviour)
>
> Changes in v5:
> - Move rule_flags into landlock_request. This lets us get rid of the
> extra parameters to is_access_to_paths_allowed (and later on,
> landlock_log_denial), and thus less code changes.
>
> Changes in v3:
> - Comment changes, move local variables, simplify if branch
>
> Changes in v2:
> - Comment changes
> - Rebased to include disconnected directory handling changes on mic/next
> and add backing up of collected_rule_flags.
>
> [1]: https://lore.kernel.org/all/20260125195853.109967-1-gnoack3000@gmail.com/
> [2]: https://lore.kernel.org/all/20251221194301.247484-1-utilityemal77@gmail.com/
> [3]: https://lore.kernel.org/all/20260524.eFiz4hahrami@digikod.net/
>
> security/landlock/access.h | 35 +++++++--
> security/landlock/audit.c | 20 ++---
> security/landlock/audit.h | 2 +-
> security/landlock/domain.c | 19 ++---
> security/landlock/domain.h | 2 +-
> security/landlock/fs.c | 147 +++++++++++++++++++-----------------
> security/landlock/limits.h | 3 +
> security/landlock/net.c | 2 +-
> security/landlock/ruleset.c | 33 +++++---
> security/landlock/ruleset.h | 17 ++++-
> 10 files changed, 170 insertions(+), 110 deletions(-)
>
> diff --git a/security/landlock/access.h b/security/landlock/access.h
> index c19d5bc13944..3b8ba6c1300d 100644
> --- a/security/landlock/access.h
> +++ b/security/landlock/access.h
> @@ -62,18 +62,37 @@ static_assert(sizeof(typeof_member(union access_masks_all, masks)) ==
> sizeof(typeof_member(union access_masks_all, all)));
>
> /**
> - * struct layer_access_masks - A boolean matrix of layers and access rights
> + * struct layer_mask - The unfulfilled access rights and rule flags for
> + * a layer.
> *
> - * This has a bit for each combination of layer numbers and access rights.
> - * During access checks, it is used to represent the access rights for each
> - * layer which still need to be fulfilled. When all bits are 0, the access
> - * request is considered to be fulfilled.
> + * During access checks, @access is used to represent the access rights
> + * for each layer which still need to be fulfilled. When all bits in
> + * @access is 0, the access request is allowed by this layer.
> + *
> + * @quiet is used to store whether we have encountered a rule with the
> + * quiet flag for this layer, which will be used to control audit logging.
> + */
> +struct layer_mask {
> + access_mask_t access:LANDLOCK_NUM_ACCESS_MAX;
> +#ifdef CONFIG_AUDIT
> + bool quiet:1;
> +#endif /* CONFIG_AUDIT */
> +};
>From landlock-test-tools/docker-run.sh:
Warning: security/landlock/access.h:79 struct member 'access' not described in 'layer_mask'
Warning: security/landlock/access.h:79 struct member 'quiet' not described in 'layer_mask'
Warning: security/landlock/access.h:79 struct member 'access' not described in 'layer_mask'
Warning: security/landlock/access.h:79 struct member 'quiet' not described in 'layer_mask
Probably worth adding these.
Tested this out as a basis of my draft for next version of
the no inherit series and it works great, handles addition
of more flags and passes selftests with no issues.
Tested-by: Justin Suess <utilityemal77 at gmail.com>
> [...]
More information about the Linux-security-module-archive
mailing list