diff options
Diffstat (limited to 'security/landlock/ruleset.c')
| -rw-r--r-- | security/landlock/ruleset.c | 49 |
1 files changed, 37 insertions, 12 deletions
diff --git a/security/landlock/ruleset.c b/security/landlock/ruleset.c index 181df7736bb9..4dd09ea22c84 100644 --- a/security/landlock/ruleset.c +++ b/security/landlock/ruleset.c @@ -21,6 +21,7 @@ #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/workqueue.h> +#include <uapi/linux/landlock.h> #include "access.h" #include "domain.h" @@ -255,6 +256,7 @@ static int insert_rule(struct landlock_ruleset *const ruleset, if (WARN_ON_ONCE(this->layers[0].level != 0)) return -EINVAL; this->layers[0].access |= (*layers)[0].access; + this->layers[0].flags.quiet |= (*layers)[0].flags.quiet; return 0; } @@ -305,12 +307,15 @@ static void build_check_layer(void) /* @ruleset must be locked by the caller. */ int landlock_insert_rule(struct landlock_ruleset *const ruleset, const struct landlock_id id, - const access_mask_t access) + const access_mask_t access, const u32 flags) { struct landlock_layer layers[] = { { .access = access, /* When @level is zero, insert_rule() extends @ruleset. */ .level = 0, + .flags = { + .quiet = !!(flags & LANDLOCK_ADD_RULE_QUIET), + }, } }; build_check_layer(); @@ -351,6 +356,7 @@ static int merge_tree(struct landlock_ruleset *const dst, return -EINVAL; layers[0].access = walker_rule->layers[0].access; + layers[0].flags = walker_rule->layers[0].flags; err = insert_rule(dst, id, &layers, ARRAY_SIZE(layers)); if (err) @@ -581,6 +587,10 @@ landlock_merge_ruleset(struct landlock_ruleset *const parent, if (err) return ERR_PTR(err); +#ifdef CONFIG_AUDIT + new_dom->hierarchy->quiet_masks = ruleset->quiet_masks; +#endif /* CONFIG_AUDIT */ + return no_free_ptr(new_dom); } @@ -628,7 +638,7 @@ landlock_find_rule(const struct landlock_ruleset *const ruleset, * remaining unfulfilled access rights and masks has no leftover set bits). */ bool landlock_unmask_layers(const struct landlock_rule *const rule, - struct layer_access_masks *masks) + struct layer_masks *masks) { if (!masks) return true; @@ -649,11 +659,17 @@ bool landlock_unmask_layers(const struct landlock_rule *const rule, const struct landlock_layer *const layer = &rule->layers[i]; /* Clear the bits where the layer in the rule grants access. */ - masks->access[layer->level - 1] &= ~layer->access; + masks->layers[layer->level - 1].access &= ~layer->access; + +#ifdef CONFIG_AUDIT + /* Collect rule flags for each layer. */ + if (layer->flags.quiet) + masks->layers[layer->level - 1].quiet = true; +#endif /* CONFIG_AUDIT */ } - for (size_t i = 0; i < ARRAY_SIZE(masks->access); i++) { - if (masks->access[i]) + for (size_t i = 0; i < ARRAY_SIZE(masks->layers); i++) { + if (masks->layers[i].access) return false; } return true; @@ -666,8 +682,9 @@ get_access_mask_t(const struct landlock_ruleset *const ruleset, /** * landlock_init_layer_masks - Initialize layer masks from an access request * - * Populates @masks such that for each access right in @access_request, - * the bits for all the layers are set where this access right is handled. + * Populates @masks such that for each access right in @access_request, the bits + * for all the layers are set where this access right is handled. Rule flags + * are also zeroed. * * @domain: The domain that defines the current restrictions. * @access_request: The requested access rights to check. @@ -680,7 +697,7 @@ get_access_mask_t(const struct landlock_ruleset *const ruleset, access_mask_t landlock_init_layer_masks(const struct landlock_ruleset *const domain, const access_mask_t access_request, - struct layer_access_masks *const masks, + struct layer_masks *const masks, const enum landlock_key_type key_type) { access_mask_t handled_accesses = 0; @@ -709,11 +726,19 @@ landlock_init_layer_masks(const struct landlock_ruleset *const domain, for (size_t i = 0; i < domain->num_layers; i++) { const access_mask_t handled = get_access_mask(domain, i); - masks->access[i] = access_request & handled; - handled_accesses |= masks->access[i]; + masks->layers[i].access = access_request & handled; + handled_accesses |= masks->layers[i].access; +#ifdef CONFIG_AUDIT + masks->layers[i].quiet = false; +#endif /* CONFIG_AUDIT */ + } + for (size_t i = domain->num_layers; i < ARRAY_SIZE(masks->layers); + i++) { + masks->layers[i].access = 0; +#ifdef CONFIG_AUDIT + masks->layers[i].quiet = false; +#endif /* CONFIG_AUDIT */ } - for (size_t i = domain->num_layers; i < ARRAY_SIZE(masks->access); i++) - masks->access[i] = 0; return handled_accesses; } |
