Unverified Commit 2cd7cd6e authored by Mickaël Salaün's avatar Mickaël Salaün
Browse files

landlock: Create find_rule() from unmask_layers()



This refactoring will be useful in a following commit.

Reviewed-by: default avatarPaul 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: default avatarMickaël Salaün <mic@digikod.net>
parent 75c542d6
Loading
Loading
Loading
Loading
+28 −13
Original line number Diff line number Diff line
@@ -183,23 +183,36 @@ int landlock_append_fs_rule(struct landlock_ruleset *const ruleset,

/* 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_ruleset *const domain,
	 * 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 struct landlock_ruleset *const domain,
	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;