From: Mickaël Salaün mic@digikod.net
commit 2cd7cd6eed88b8383cfddce589afe9c0ae1d19b4 upstream.
This refactoring will be useful in a following commit.
Reviewed-by: Paul Moore paul@paul-moore.com Link: https://lore.kernel.org/r/20220506161102.525323-4-mic@digikod.net Cc: stable@vger.kernel.org Signed-off-by: Mickaël Salaün mic@digikod.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- security/landlock/fs.c | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-)
--- a/security/landlock/fs.c +++ b/security/landlock/fs.c @@ -183,23 +183,36 @@ int landlock_append_fs_rule(struct landl
/* Access-control management */
-static inline layer_mask_t -unmask_layers(const struct landlock_ruleset *const domain, - const struct path *const path, const access_mask_t access_request, - layer_mask_t layer_mask) +/* + * The lifetime of the returned rule is tied to @domain. + * + * Returns NULL if no rule is found or if @dentry is negative. + */ +static inline const struct landlock_rule * +find_rule(const struct landlock_ruleset *const domain, + const struct dentry *const dentry) { const struct landlock_rule *rule; const struct inode *inode; - size_t i;
- if (d_is_negative(path->dentry)) - /* Ignore nonexistent leafs. */ - return layer_mask; - inode = d_backing_inode(path->dentry); + /* Ignores nonexistent leafs. */ + if (d_is_negative(dentry)) + return NULL; + + inode = d_backing_inode(dentry); rcu_read_lock(); rule = landlock_find_rule( domain, rcu_dereference(landlock_inode(inode)->object)); rcu_read_unlock(); + return rule; +} + +static inline layer_mask_t unmask_layers(const struct landlock_rule *const rule, + const access_mask_t access_request, + layer_mask_t layer_mask) +{ + size_t layer_level; + if (!rule) return layer_mask;
@@ -210,8 +223,9 @@ unmask_layers(const struct landlock_rule * the remaining layers for each inode, from the first added layer to * the last one. */ - for (i = 0; i < rule->num_layers; i++) { - const struct landlock_layer *const layer = &rule->layers[i]; + for (layer_level = 0; layer_level < rule->num_layers; layer_level++) { + const struct landlock_layer *const layer = + &rule->layers[layer_level]; const layer_mask_t layer_bit = BIT_ULL(layer->level - 1);
/* Checks that the layer grants access to the full request. */ @@ -269,8 +283,9 @@ static int check_access_path(const struc while (true) { struct dentry *parent_dentry;
- layer_mask = unmask_layers(domain, &walker_path, access_request, - layer_mask); + layer_mask = + unmask_layers(find_rule(domain, walker_path.dentry), + access_request, layer_mask); if (layer_mask == 0) { /* Stops when a rule from each layer grants access. */ allowed = true;