diff options
Diffstat (limited to 'security/landlock/ruleset.c')
-rw-r--r-- | security/landlock/ruleset.c | 48 |
1 files changed, 33 insertions, 15 deletions
diff --git a/security/landlock/ruleset.c b/security/landlock/ruleset.c index 28ffeedd21d6c..e36c5c3322429 100644 --- a/security/landlock/ruleset.c +++ b/security/landlock/ruleset.c @@ -573,14 +573,15 @@ landlock_find_rule(const struct landlock_ruleset *const ruleset, /* * @layer_masks is read and may be updated according to the access request and * the matching rule. + * @masks_array_size must be equal to ARRAY_SIZE(*layer_masks). * * Returns true if the request is allowed (i.e. relevant layer masks for the * request are empty). */ -bool landlock_unmask_layers( - const struct landlock_rule *const rule, - const access_mask_t access_request, - layer_mask_t (*const layer_masks)[LANDLOCK_NUM_ACCESS_FS]) +bool landlock_unmask_layers(const struct landlock_rule *const rule, + const access_mask_t access_request, + layer_mask_t (*const layer_masks)[], + const size_t masks_array_size) { size_t layer_level; @@ -612,8 +613,7 @@ bool landlock_unmask_layers( * requested access. */ is_empty = true; - for_each_set_bit(access_bit, &access_req, - ARRAY_SIZE(*layer_masks)) { + for_each_set_bit(access_bit, &access_req, masks_array_size) { if (layer->access & BIT_ULL(access_bit)) (*layer_masks)[access_bit] &= ~layer_bit; is_empty = is_empty && !(*layer_masks)[access_bit]; @@ -624,6 +624,10 @@ bool landlock_unmask_layers( return false; } +typedef access_mask_t +get_access_mask_t(const struct landlock_ruleset *const ruleset, + const u16 layer_level); + /** * landlock_init_layer_masks - Initialize layer masks from an access request * @@ -633,19 +637,34 @@ bool landlock_unmask_layers( * @domain: The domain that defines the current restrictions. * @access_request: The requested access rights to check. * @layer_masks: The layer masks to populate. + * @key_type: The key type to switch between access masks of different types. * * Returns: An access mask where each access right bit is set which is handled * in any of the active layers in @domain. */ -access_mask_t landlock_init_layer_masks( - const struct landlock_ruleset *const domain, - const access_mask_t access_request, - layer_mask_t (*const layer_masks)[LANDLOCK_NUM_ACCESS_FS]) +access_mask_t +landlock_init_layer_masks(const struct landlock_ruleset *const domain, + const access_mask_t access_request, + layer_mask_t (*const layer_masks)[], + const enum landlock_key_type key_type) { access_mask_t handled_accesses = 0; - size_t layer_level; + size_t layer_level, num_access; + get_access_mask_t *get_access_mask; + + switch (key_type) { + case LANDLOCK_KEY_INODE: + get_access_mask = landlock_get_fs_access_mask; + num_access = LANDLOCK_NUM_ACCESS_FS; + break; + default: + WARN_ON_ONCE(1); + return 0; + } + + memset(layer_masks, 0, + array_size(sizeof((*layer_masks)[0]), num_access)); - memset(layer_masks, 0, sizeof(*layer_masks)); /* An empty access request can happen because of O_WRONLY | O_RDWR. */ if (!access_request) return 0; @@ -655,10 +674,9 @@ access_mask_t landlock_init_layer_masks( const unsigned long access_req = access_request; unsigned long access_bit; - for_each_set_bit(access_bit, &access_req, - ARRAY_SIZE(*layer_masks)) { + for_each_set_bit(access_bit, &access_req, num_access) { if (BIT_ULL(access_bit) & - landlock_get_fs_access_mask(domain, layer_level)) { + get_access_mask(domain, layer_level)) { (*layer_masks)[access_bit] |= BIT_ULL(layer_level); handled_accesses |= BIT_ULL(access_bit); |