From: "Mickaël Salaün" <mic@digikod.net>
To: Justin Suess <utilityemal77@gmail.com>
Cc: "Tingmao Wang" <m@maowtm.org>,
"Günther Noack" <gnoack3000@gmail.com>, "Jan Kara" <jack@suse.cz>,
"Abhinav Saxena" <xandfury@gmail.com>,
linux-security-module@vger.kernel.org
Subject: Re: [PATCH v8 1/9] landlock: Add a place for flags to layer rules
Date: Mon, 25 May 2026 22:39:16 +0200 [thread overview]
Message-ID: <20260525.quoPhoh6ma3k@digikod.net> (raw)
In-Reply-To: <ahNx8CNCeqhU_Ide@zenbox>
On Sun, May 24, 2026 at 06:08:00PM -0400, Justin Suess wrote:
> On Sun, May 24, 2026 at 07:20:19PM +0100, Tingmao Wang wrote:
> > On 5/24/26 15:46, Justin Suess wrote:
> > > On Sun, May 24, 2026 at 02:29:40AM +0100, Tingmao Wang wrote:
> > >> On 5/23/26 21:48, Mickaël Salaün wrote:
> > >>> [...]
> > >>>> @@ -647,9 +648,14 @@ bool landlock_unmask_layers(const struct landlock_rule *const rule,
> > >>>> */
> > >>>> for (size_t i = 0; i < rule->num_layers; i++) {
> > >>>> const struct landlock_layer *const layer = &rule->layers[i];
> > >>>> + const layer_mask_t layer_bit = BIT_ULL(layer->level - 1);
> > >>>>
> > >>>
> > >>>> /* Clear the bits where the layer in the rule grants access. */
> > >>>> masks->access[layer->level - 1] &= ~layer->access;
> > >>>> +
> > >>>> + /* Collect rule flags for each layer. */
> > >>>> + if (rule_flags && layer->flags.quiet)
> > >>>> + rule_flags->quiet_masks |= layer_bit;
> > >>>
> > >>> Why not store the quiet bit in masks? That would not only be "access"
> > >>> bits anymore but it makes sense to store all this bits it the same
> > >>> place.
> > >>>
> > >>> We should then probably rename struct layer_access_masks to just struct
> > >>> layer_masks.
> > >>>
> > >>> We need to be careful to not increase too much the size of this struct
> > >>> though while keeping the [LANDLOCK_MAX_NUM_LAYERS] approach if possible
> > >>> (see Günther's commit that added it).
> > >>
> > >> Most uses of struct layer_access_masks do not actually care about the rule
> > >> flags tho, e.g. in unmask_scoped_access, scope_to_request, or may_refer.
> > >> Such a rename would touch 31 places (and only a few of them would actually
> > >> touch the quiet flag).
> > >>
> > >> If we want to refactor to make this be in the layer_access_masks (then
> > >> rename it), I guess there are 3 options, which do you prefer?
> > >>
> > >> 1. Add a u16 bitfield for which layers are quieted. Future rule flags
> > >> will be additional bitfields. struct layer_masks becomes 68 bytes (+4).
> > >>
> > >> struct layer_masks {
> > >> access_mask_t access[LANDLOCK_MAX_NUM_LAYERS];
> > >> layer_mask_t quiet_layers;
> > >> };
> > >>
> > >> 2. Make the [LANDLOCK_MAX_NUM_LAYERS] array store both the access mask and
> > >> the quiet bit (or more bits for future rule flags). Size of struct stays
> > >> the same.
> > >>
> > > This approach seems best.
> > >> static_assert(LANDLOCK_NUM_ACCESS_NET <= LANDLOCK_NUM_ACCESS_FS);
> > >> static_assert(LANDLOCK_NUM_SCOPE <= LANDLOCK_NUM_ACCESS_FS);
> > >> struct layer_mask {
> > >> access_mask_t access:LANDLOCK_NUM_ACCESS_FS;
> > >> bool quiet:1;
> > >> };
> > >
> > > Other way to do it could be an (anonymous?) union.
> > >
> > > union {
> > > access_mask_t fs_access:LANDLOCK_NUM_ACCESS_FS;
> > > access_mask_t net_access:LANDLOCK_NUM_ACCESS_NET;
> > > access_mask_t scope_access:LANDLOCK_NUM_SCOPE;
> > > }
> > >
> > > The union should be sized to fit the largest field automatically.
> > >
> > > That way you don't have to change this when adding new access rights
> > > and avoid the brittle static_asserts.
> > >
> > > Not sure about the alignment implications here though.
> >
> > Unfortunately this forces struct layer_mask to be 2x as large:
> > https://godbolt.org/z/5P9b4rrMW
> >
> Yeah I guess the compiler can't pack the fields with differing types.
>
> *In theory* you could make everything a _BitInt or something but it
> seems better to do what you had below.
> > But it turns out I could have just used MAX, seems to compile for me:
> >
> > struct layer_mask {
> > access_mask_t access
> > : MAX(LANDLOCK_NUM_ACCESS_FS,
> > MAX(LANDLOCK_NUM_ACCESS_NET, LANDLOCK_NUM_SCOPE));
> > bool quiet : 1;
> > };
> This works perfectly.
>
> Mickaël's suggestion (except w/ all three access right classes like
> you have here, think he missed LANDLOCK_NUM_SCOPE) is very close
> to this.
> > struct layer_masks {
> > struct layer_mask layer[LANDLOCK_MAX_NUM_LAYERS];
> > };
> >
> > Maybe we could #define LANDLOCK_NUM_ACCESS_MAX to be MAX(...) then use it
> > here.
LANDLOCK_NUM_ACCESS_MAX looks like a better name (even if it also
include scopes).
> >
> > I'm still not sure if putting the collected rule flags in struct
> > layer_(access_)masks is a good idea tho. Passing a separate struct
> > collected_rule_flags to the functions that needs to deal with rule flags
> > (quiet, and later, no inherit / has no inherit descendant) seems quite
> > practical to me.
>
> (Not sure how stingy we gotta be with stack space)
>
> There's a *slight* stack space advantage to keeping them together.
>
> If you pass by value, (separate layer_access_masks, collected_rule_flags),
> those structs must be individually padded and aligned. Which may or may not
> make a difference, it's dependent on alignment and architecture.
>
> Whereas if we keep them all together, we only pad once.
>
> If you pass by pointer, you have to allocate stack space for each
> pointer, so passing it all at once saves sizeof(collected_rule_flags*)
> bytes in the pass by pointer case.
>
> Either way it's probably a couple bytes at worst, so probably nothing to
> worry about.
>
> The more compelling argument is that we don't know how future paths
> will use rule flags, so keeping it all together reduces churn later
> if a function ends up needing to access flags. Moreover, it makes those
> messy function signatures in fs.h/c a little less hairy, and easy to
> refactor later.
Agreed
next prev parent reply other threads:[~2026-05-25 20:39 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 [this message]
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
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.quoPhoh6ma3k@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