diff mbox series

[RFC,v3,10/19] selftests/landlock: Test adding a rule with family and type outside the range

Message ID 20240904104824.1844082-11-ivanov.mikhail1@huawei-partners.com (mailing list archive)
State RFC
Headers show
Series Support socket access-control | expand

Checks

Context Check Description
netdev/tree_selection success Not a local patch, async

Commit Message

Mikhail Ivanov Sept. 4, 2024, 10:48 a.m. UTC
Create `prot_outside_range` fixture. It is used to iterate through
the various family and type pairs that do not fit the valid range.

Add test validating that adding a rule for sockets that do not match
the ranges (0 <= domain < AF_MAX), (0 <= type < SOCK_MAX) is prohibited.

Signed-off-by: Mikhail Ivanov <ivanov.mikhail1@huawei-partners.com>
---
Changes since v2:
* Removes restriction checks on maximum family and type values. Such
  checking is performed in protocol.create now.
* Renames this test into `rule_with_prot_outside_range`
* Creates `prot_outside_range` fixture. It is used to iterate through
  the various family and type pairs that doesn't fit valid range.
  Removes CHECK_RULE_OVERFLOW entries.
* Checks unrestricted socket(2) with family and type outside the range.
* Closes ruleset_fd.
* Refactors commit title.
---
 .../testing/selftests/landlock/socket_test.c  | 102 ++++++++++++++++++
 1 file changed, 102 insertions(+)
diff mbox series

Patch

diff --git a/tools/testing/selftests/landlock/socket_test.c b/tools/testing/selftests/landlock/socket_test.c
index dee676c11227..047603abc5a7 100644
--- a/tools/testing/selftests/landlock/socket_test.c
+++ b/tools/testing/selftests/landlock/socket_test.c
@@ -479,4 +479,106 @@  TEST(ruleset_with_unknown_access)
 	}
 }
 
+FIXTURE(prot_outside_range)
+{
+	struct protocol_variant prot;
+};
+
+FIXTURE_VARIANT(prot_outside_range)
+{
+	struct protocol_variant prot;
+};
+
+FIXTURE_SETUP(prot_outside_range)
+{
+	self->prot = variant->prot;
+};
+
+FIXTURE_TEARDOWN(prot_outside_range)
+{
+}
+
+/* Cf. include/linux/net.h */
+#define SOCK_MAX (SOCK_PACKET + 1)
+#define NEGATIVE_MAX (-1)
+/* Cf. linux/net.h */
+#define SOCK_TYPE_MASK 0xf
+
+#define SOCK_STREAM_FLAG1 (SOCK_STREAM | SOCK_NONBLOCK)
+#define SOCK_STREAM_FLAG2 (SOCK_STREAM | SOCK_CLOEXEC)
+
+#define INVAL_PROTOCOL_VARIANT_ADD(family_, type_)                 \
+	FIXTURE_VARIANT_ADD(prot_outside_range, family_##_##type_) \
+	{                                                          \
+		.prot = {                                          \
+			.family = family_,                         \
+			.type = type_,                             \
+		},                                                 \
+	}
+
+INVAL_PROTOCOL_VARIANT_ADD(INT32_MIN, INT32_MIN);
+INVAL_PROTOCOL_VARIANT_ADD(INT32_MIN, NEGATIVE_MAX);
+INVAL_PROTOCOL_VARIANT_ADD(INT32_MIN, SOCK_STREAM);
+INVAL_PROTOCOL_VARIANT_ADD(INT32_MIN, SOCK_MAX);
+INVAL_PROTOCOL_VARIANT_ADD(INT32_MIN, INT32_MAX);
+
+INVAL_PROTOCOL_VARIANT_ADD(NEGATIVE_MAX, INT32_MIN);
+INVAL_PROTOCOL_VARIANT_ADD(NEGATIVE_MAX, NEGATIVE_MAX);
+INVAL_PROTOCOL_VARIANT_ADD(NEGATIVE_MAX, SOCK_STREAM);
+INVAL_PROTOCOL_VARIANT_ADD(NEGATIVE_MAX, SOCK_MAX);
+INVAL_PROTOCOL_VARIANT_ADD(NEGATIVE_MAX, INT32_MAX);
+
+INVAL_PROTOCOL_VARIANT_ADD(AF_INET, INT32_MIN);
+INVAL_PROTOCOL_VARIANT_ADD(AF_INET, NEGATIVE_MAX);
+INVAL_PROTOCOL_VARIANT_ADD(AF_INET, SOCK_MAX);
+INVAL_PROTOCOL_VARIANT_ADD(AF_INET, INT32_MAX);
+
+INVAL_PROTOCOL_VARIANT_ADD(AF_MAX, INT32_MIN);
+INVAL_PROTOCOL_VARIANT_ADD(AF_MAX, NEGATIVE_MAX);
+INVAL_PROTOCOL_VARIANT_ADD(AF_MAX, SOCK_STREAM);
+INVAL_PROTOCOL_VARIANT_ADD(AF_MAX, SOCK_MAX);
+INVAL_PROTOCOL_VARIANT_ADD(AF_MAX, INT32_MAX);
+
+INVAL_PROTOCOL_VARIANT_ADD(INT32_MAX, INT32_MIN);
+INVAL_PROTOCOL_VARIANT_ADD(INT32_MAX, NEGATIVE_MAX);
+INVAL_PROTOCOL_VARIANT_ADD(INT32_MAX, SOCK_STREAM);
+INVAL_PROTOCOL_VARIANT_ADD(INT32_MAX, SOCK_MAX);
+INVAL_PROTOCOL_VARIANT_ADD(INT32_MAX, INT32_MAX);
+
+TEST_F(prot_outside_range, add_rule)
+{
+	int family = self->prot.family;
+	int type = self->prot.type;
+	const struct landlock_ruleset_attr ruleset_attr = {
+		.handled_access_socket = LANDLOCK_ACCESS_SOCKET_CREATE,
+	};
+	struct landlock_socket_attr create_socket_overflow = {
+		.allowed_access = LANDLOCK_ACCESS_SOCKET_CREATE,
+		.family = family,
+		.type = type,
+	};
+	int ruleset_fd;
+
+	/* Checks type flags using __sys_socket_create. */
+	if ((type & ~SOCK_TYPE_MASK) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) {
+		ASSERT_EQ(EINVAL, test_socket_variant(&self->prot));
+	}
+	/* Checks range using __sock_create. */
+	else if (family >= AF_MAX || family < 0) {
+		ASSERT_EQ(EAFNOSUPPORT, test_socket_variant(&self->prot));
+	} else {
+		ASSERT_EQ(EINVAL, test_socket_variant(&self->prot));
+	}
+
+	ruleset_fd =
+		landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
+	ASSERT_LE(0, ruleset_fd);
+
+	EXPECT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_SOCKET,
+					&create_socket_overflow, 0));
+	EXPECT_EQ(EINVAL, errno);
+
+	ASSERT_EQ(0, close(ruleset_fd));
+}
+
 TEST_HARNESS_MAIN