Skip to content

Commit d617f0d

Browse files
committed
landlock: Optimize file path walks and prepare for audit support
Always synchronize access_masked_parent* with access_request_parent* according to allowed_parent*. This is required for audit support to be able to get back to the reason of denial. In a rename/link action, instead of always checking a rule two times for the same parent directory of the source and the destination files, only check it when an action on a child was not already allowed. This also enables us to keep consistent allowed_parent* status, which is required to get back to the reason of denial. For internal mount points, only upgrade allowed_parent* to true but do not wrongfully set both of them to false otherwise. This is also required to get back to the reason of denial. This does not impact the current behavior but slightly optimize code and prepare for audit support that needs to know the exact reason why an access was denied. Cc: Günther Noack <gnoack@google.com> Link: https://lore.kernel.org/r/20250108154338.1129069-14-mic@digikod.net Signed-off-by: Mickaël Salaün <mic@digikod.net>
1 parent 12264f7 commit d617f0d

File tree

1 file changed

+27
-17
lines changed
  • security/landlock

1 file changed

+27
-17
lines changed

security/landlock/fs.c

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -852,31 +852,39 @@ static bool is_access_to_paths_allowed(
852852
child1_is_directory, layer_masks_parent2,
853853
layer_masks_child2,
854854
child2_is_directory))) {
855-
allowed_parent1 = scope_to_request(
856-
access_request_parent1, layer_masks_parent1);
857-
allowed_parent2 = scope_to_request(
858-
access_request_parent2, layer_masks_parent2);
859-
860-
/* Stops when all accesses are granted. */
861-
if (allowed_parent1 && allowed_parent2)
862-
break;
863-
864855
/*
865856
* Now, downgrades the remaining checks from domain
866857
* handled accesses to requested accesses.
867858
*/
868859
is_dom_check = false;
869860
access_masked_parent1 = access_request_parent1;
870861
access_masked_parent2 = access_request_parent2;
862+
863+
allowed_parent1 =
864+
allowed_parent1 ||
865+
scope_to_request(access_masked_parent1,
866+
layer_masks_parent1);
867+
allowed_parent2 =
868+
allowed_parent2 ||
869+
scope_to_request(access_masked_parent2,
870+
layer_masks_parent2);
871+
872+
/* Stops when all accesses are granted. */
873+
if (allowed_parent1 && allowed_parent2)
874+
break;
871875
}
872876

873877
rule = find_rule(domain, walker_path.dentry);
874-
allowed_parent1 = landlock_unmask_layers(
875-
rule, access_masked_parent1, layer_masks_parent1,
876-
ARRAY_SIZE(*layer_masks_parent1));
877-
allowed_parent2 = landlock_unmask_layers(
878-
rule, access_masked_parent2, layer_masks_parent2,
879-
ARRAY_SIZE(*layer_masks_parent2));
878+
allowed_parent1 = allowed_parent1 ||
879+
landlock_unmask_layers(
880+
rule, access_masked_parent1,
881+
layer_masks_parent1,
882+
ARRAY_SIZE(*layer_masks_parent1));
883+
allowed_parent2 = allowed_parent2 ||
884+
landlock_unmask_layers(
885+
rule, access_masked_parent2,
886+
layer_masks_parent2,
887+
ARRAY_SIZE(*layer_masks_parent2));
880888

881889
/* Stops when a rule from each layer grants access. */
882890
if (allowed_parent1 && allowed_parent2)
@@ -900,8 +908,10 @@ static bool is_access_to_paths_allowed(
900908
* access to internal filesystems (e.g. nsfs, which is
901909
* reachable through /proc/<pid>/ns/<namespace>).
902910
*/
903-
allowed_parent1 = allowed_parent2 =
904-
!!(walker_path.mnt->mnt_flags & MNT_INTERNAL);
911+
if (walker_path.mnt->mnt_flags & MNT_INTERNAL) {
912+
allowed_parent1 = true;
913+
allowed_parent2 = true;
914+
}
905915
break;
906916
}
907917
parent_dentry = dget_parent(walker_path.dentry);

0 commit comments

Comments
 (0)