Linux Security Modules development
 help / color / mirror / Atom feed
* [PATCH] landlock: Fix layer composition of LANDLOCK_ACCESS_FS_REFER
@ 2026-11-12  2:55 pandaWall
  2026-11-12  3:17 ` sashiko-bot
  2026-11-12  5:27 ` [RFC PATCH v2 1/2] " pandaWall
  0 siblings, 2 replies; 6+ messages in thread
From: pandaWall @ 2026-11-12  2:55 UTC (permalink / raw)
  To: mic, gnoack; +Cc: linux-security-module, linux-kernel, pandaWall

landlock_get_fs_access_mask() unconditionally ORs
_LANDLOCK_ACCESS_FS_INITIALLY_DENIED (i.e. LANDLOCK_ACCESS_FS_REFER)
into every layer's handled filesystem mask.  Layers created from
rulesets that only handle other rule types (network ports, scopes) or
only permissions therefore report REFER as handled even though
landlock_upgrade_handled_layer_config() only adds the bit when
handled.fs is non-zero, and no filesystem rule can ever clear a bit
of such a layer.

The consequence is that stacking any non-filesystem ruleset on top of
a filesystem ruleset makes link(2), rename(2) and
renameat2(RENAME_EXCHANGE) fail with -EXDEV/-EACCES even when each
ruleset individually allows the operation: landlock_unmask_layers()
requires every layer's mask to be cleared, and a non-filesystem
layer's mask can never be.

Only implicitly handle REFER for layers that already handle
filesystem access rights.

Fixes: fff69fb03dde ("landlock: Support network rules with TCP bind and connect")
Signed-off-by: pandaWall <mangosteen922@126.com>

Add a corresponding regression test to the layout1 fs_test suite:
stacking a network-only ruleset (handled_access_net only) on top of a
filesystem ruleset allowing REFER and MAKE_REG must not deny
different-parent rename/exchange.
---
 security/landlock/domain.h                 | 15 +++++++--
 tools/testing/selftests/landlock/fs_test.c | 37 ++++++++++++++++++++++
 2 files changed, 49 insertions(+), 3 deletions(-)

diff --git a/security/landlock/domain.h b/security/landlock/domain.h
index 935e18b12..07d4a23fc 100644
--- a/security/landlock/domain.h
+++ b/security/landlock/domain.h
@@ -262,9 +262,18 @@ static inline access_mask_t
 landlock_get_fs_access_mask(const struct landlock_domain *const domain,
 			    const u16 layer_level)
 {
-	/* Handles all initially denied by default access rights. */
-	return domain->layers[layer_level].handled.fs |
-	       _LANDLOCK_ACCESS_FS_INITIALLY_DENIED;
+	access_mask_t handled = domain->layers[layer_level].handled.fs;
+
+	/*
+	 * Only layers that handle filesystem access rights implicitly
+	 * handle REFER.  A layer that handles other rule types (e.g.
+	 * network, scopes) must not imply REFER, otherwise it would
+	 * spuriously deny link and rename operations.
+	 */
+	if (handled)
+		handled |= _LANDLOCK_ACCESS_FS_INITIALLY_DENIED;
+
+	return handled;
 }
 
 static inline access_mask_t
diff --git a/tools/testing/selftests/landlock/fs_test.c b/tools/testing/selftests/landlock/fs_test.c
index f725882fa..5588f0ee5 100644
--- a/tools/testing/selftests/landlock/fs_test.c
+++ b/tools/testing/selftests/landlock/fs_test.c
@@ -2570,6 +2570,43 @@ const struct rule layer_dir_s2d1_execute[] = {
 	{},
 };
 
+/*
+ * Tests that a layer not handling filesystem access rights does not
+ * implicitly handle LANDLOCK_ACCESS_FS_REFER, which would otherwise deny
+ * different-parent renames and links stacked on top of a filesystem ruleset.
+ */
+TEST_F_FORK(layout1, refer_with_net_layer)
+{
+	const struct rule layer_fs[] = {
+		{
+			.path = dir_s1d2,
+			.access = LANDLOCK_ACCESS_FS_REFER,
+		},
+		{
+			.path = dir_s1d3,
+			.access = LANDLOCK_ACCESS_FS_MAKE_REG,
+		},
+		{},
+	};
+	const struct landlock_ruleset_attr ruleset_net = {
+		.handled_access_net = LANDLOCK_ACCESS_NET_BIND_TCP,
+	};
+
+	/* layer_fs alone: different-parent rename is allowed. */
+	enforce_fs(_metadata, LANDLOCK_ACCESS_FS_REFER |
+				      LANDLOCK_ACCESS_FS_MAKE_REG,
+		   layer_fs);
+	ASSERT_EQ(0, test_rename(file1_s1d2, file1_s1d3));
+	ASSERT_EQ(0, test_rename(file1_s1d3, file1_s1d2));
+	ASSERT_EQ(0, test_exchange(file2_s1d2, file2_s1d3));
+
+	/* Stacks a network-only layer: still allowed. */
+	drop_access_rights(_metadata, &ruleset_net);
+	ASSERT_EQ(0, test_rename(file1_s1d2, file1_s1d3));
+	ASSERT_EQ(0, test_rename(file1_s1d3, file1_s1d2));
+	ASSERT_EQ(0, test_exchange(file2_s1d2, file2_s1d3));
+}
+
 /*
  * Tests precedence over renames: denied by default for different parent
  * directories, *with* a rule matching a parent directory, but not directly
-- 
2.56.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-11-12  5:42 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-12  2:55 [PATCH] landlock: Fix layer composition of LANDLOCK_ACCESS_FS_REFER pandaWall
2026-11-12  3:17 ` sashiko-bot
2026-11-12  5:27 ` [RFC PATCH v2 1/2] " pandaWall
2026-11-12  5:27   ` [RFC PATCH v2 2/2] landlock: Add a test for REFER layer composition with network layer pandaWall
2026-11-12  5:42     ` sashiko-bot
2026-11-12  5:36   ` [RFC PATCH v2 1/2] landlock: Fix layer composition of LANDLOCK_ACCESS_FS_REFER sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox