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

landlock: Simplify initially denied access rights

Upgrade domain's handled access masks when creating a domain from a
ruleset, instead of converting them at runtime.  This is more consistent
and helps with audit support.

Cc: Günther Noack <gnoack@google.com>
Link: https://lore.kernel.org/r/20250108154338.1129069-7-mic@digikod.net


Signed-off-by: default avatarMickaël Salaün <mic@digikod.net>
parent 622e2f59
Loading
Loading
Loading
Loading
+16 −1
Original line number Diff line number Diff line
@@ -20,7 +20,8 @@
/*
 * All access rights that are denied by default whether they are handled or not
 * by a ruleset/layer.  This must be ORed with all ruleset->access_masks[]
 * entries when we need to get the absolute handled access masks.
 * entries when we need to get the absolute handled access masks, see
 * landlock_upgrade_handled_access_masks().
 */
/* clang-format off */
#define _LANDLOCK_ACCESS_FS_INITIALLY_DENIED ( \
@@ -59,4 +60,18 @@ typedef u16 layer_mask_t;
/* Makes sure all layers can be checked. */
static_assert(BITS_PER_TYPE(layer_mask_t) >= LANDLOCK_MAX_NUM_LAYERS);

/* Upgrades with all initially denied by default access rights. */
static inline struct access_masks
landlock_upgrade_handled_access_masks(struct access_masks access_masks)
{
	/*
	 * All access rights that are denied by default whether they are
	 * explicitly handled or not.
	 */
	if (access_masks.fs)
		access_masks.fs |= _LANDLOCK_ACCESS_FS_INITIALLY_DENIED;

	return access_masks;
}

#endif /* _SECURITY_LANDLOCK_ACCESS_H */
+1 −9
Original line number Diff line number Diff line
@@ -389,14 +389,6 @@ static bool is_nouser_or_private(const struct dentry *dentry)
		unlikely(IS_PRIVATE(d_backing_inode(dentry))));
}

static access_mask_t
get_handled_fs_accesses(const struct landlock_ruleset *const domain)
{
	/* Handles all initially denied by default access rights. */
	return landlock_union_access_masks(domain).fs |
	       _LANDLOCK_ACCESS_FS_INITIALLY_DENIED;
}

static const struct access_masks any_fs = {
	.fs = ~0,
};
@@ -788,7 +780,7 @@ static bool is_access_to_paths_allowed(
		 * a superset of the meaningful requested accesses).
		 */
		access_masked_parent1 = access_masked_parent2 =
			get_handled_fs_accesses(domain);
			landlock_union_access_masks(domain).fs;
		is_dom_check = true;
	} else {
		if (WARN_ON_ONCE(dentry_child1 || dentry_child2))
+2 −1
Original line number Diff line number Diff line
@@ -387,7 +387,8 @@ static int merge_ruleset(struct landlock_ruleset *const dst,
		err = -EINVAL;
		goto out_unlock;
	}
	dst->access_masks[dst->num_layers - 1] = src->access_masks[0];
	dst->access_masks[dst->num_layers - 1] =
		landlock_upgrade_handled_access_masks(src->access_masks[0]);

	/* Merges the @src inode tree. */
	err = merge_tree(dst, src, LANDLOCK_KEY_INODE);