lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251118134639.3314803-12-ivanov.mikhail1@huawei-partners.com>
Date: Tue, 18 Nov 2025 21:46:31 +0800
From: Mikhail Ivanov <ivanov.mikhail1@...wei-partners.com>
To: <mic@...ikod.net>, <gnoack@...gle.com>
CC: <willemdebruijn.kernel@...il.com>, <matthieu@...fet.re>,
	<linux-security-module@...r.kernel.org>, <netdev@...r.kernel.org>,
	<netfilter-devel@...r.kernel.org>, <yusongping@...wei.com>,
	<artem.kuzin@...wei.com>, <konstantin.meskhidze@...wei.com>
Subject: [RFC PATCH v4 11/19] selftests/landlock: Test protocol mappings

It is possible to create sockets of the same protocol with different
protocol number (cf. socket(2)) values. For example, TCP sockets can
be created using one of the following commands:
	1. fd = socket(AF_INET, SOCK_STREAM, 0);
	2. fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
Whereas IPPROTO_TCP = 6. Protocol number 0 correspond to the default
protocol of the given protocol family and can be mapped to another
value. Mapping is handled on the protocol family level.

Socket rules should not perform such mappings to not increase complexity
of rules definition and their maintenance.

(AF_INET, SOCK_PACKET) is an alias for (AF_PACKET, SOCK_PACKET)
(cf. __sock_create) handled due to compatibility reasons. Compared to TCP
network stack performs mapping before calling LSM hook related to socket
creation. Therefore Landlock should not restrict one pair if the other
was allowed.

Add `packet_protocol` and `tcp_protocol` fixtures and tests to validate
these scenarios.

Signed-off-by: Mikhail Ivanov <ivanov.mikhail1@...wei-partners.com>
---
Changes since v3:
* Adds verification of TCP mapping.
* Changes commit message.
---
 .../testing/selftests/landlock/socket_test.c  | 157 ++++++++++++++++++
 1 file changed, 157 insertions(+)

diff --git a/tools/testing/selftests/landlock/socket_test.c b/tools/testing/selftests/landlock/socket_test.c
index ce9a6e283be6..e22e10edb103 100644
--- a/tools/testing/selftests/landlock/socket_test.c
+++ b/tools/testing/selftests/landlock/socket_test.c
@@ -709,4 +709,161 @@ TEST_F(mini, kernel_socket)
 	EXPECT_EQ(0, test_socket(AF_SMC, SOCK_STREAM, 0));
 }
 
+/* clang-format off */
+FIXTURE(packet_protocol) {};
+/* clang-format on */
+
+FIXTURE_VARIANT(packet_protocol)
+{
+	int family, type, protocol;
+};
+
+/* clang-format off */
+FIXTURE_SETUP(packet_protocol) {};
+/* clang-format on */
+
+FIXTURE_TEARDOWN(packet_protocol)
+{
+}
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(packet_protocol, pf_inet) {
+	/* clang-format on */
+	.family = AF_INET,
+	.type = SOCK_PACKET,
+	.protocol = 0,
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(packet_protocol, pf_packet) {
+	/* clang-format on */
+	.family = AF_PACKET,
+	.type = SOCK_PACKET,
+	.protocol = 0,
+};
+
+/*
+ * (AF_INET, SOCK_PACKET) is an alias for the (AF_PACKET, SOCK_PACKET)
+ * handled in socket layer (cf. __sock_create) due to compatibility reasons.
+ *
+ * Checks that Landlock does not restrict one pair if the other was allowed.
+ */
+TEST_F(packet_protocol, alias_restriction)
+{
+	const struct landlock_ruleset_attr ruleset_attr = {
+		.handled_access_socket = LANDLOCK_ACCESS_SOCKET_CREATE,
+	};
+	const int family = variant->family;
+	const int type = variant->type;
+	const int protocol = variant->protocol;
+	const struct landlock_socket_attr packet_socket_create = {
+		.allowed_access = LANDLOCK_ACCESS_SOCKET_CREATE,
+		.family = family,
+		.type = type,
+		.protocol = protocol,
+	};
+	int ruleset_fd;
+
+	/*
+	 * Checks that packet socket is created successfully without
+	 * landlock restrictions.
+	 *
+	 * Packet sockets require CAP_NET_RAW capability.
+	 */
+	set_cap(_metadata, CAP_NET_RAW);
+	ASSERT_EQ(0, test_socket(AF_INET, SOCK_PACKET, 0));
+	ASSERT_EQ(0, test_socket(AF_PACKET, SOCK_PACKET, 0));
+	clear_cap(_metadata, CAP_NET_RAW);
+
+	ruleset_fd =
+		landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
+	ASSERT_LE(0, ruleset_fd);
+
+	ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_SOCKET,
+				       &packet_socket_create, 0));
+	enforce_ruleset(_metadata, ruleset_fd);
+	ASSERT_EQ(0, close(ruleset_fd));
+
+	set_cap(_metadata, CAP_NET_RAW);
+	EXPECT_EQ(0, test_socket(AF_INET, SOCK_PACKET, 0));
+	EXPECT_EQ(0, test_socket(AF_PACKET, SOCK_PACKET, 0));
+	clear_cap(_metadata, CAP_NET_RAW);
+}
+
+/* clang-format off */
+FIXTURE(tcp_protocol) {};
+/* clang-format on */
+
+FIXTURE_VARIANT(tcp_protocol)
+{
+	int family, type, protocol;
+};
+
+/* clang-format off */
+FIXTURE_SETUP(tcp_protocol) {};
+/* clang-format on */
+
+FIXTURE_TEARDOWN(tcp_protocol)
+{
+}
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(tcp_protocol, variant1) {
+	/* clang-format on */
+	.family = AF_INET,
+	.type = SOCK_STREAM,
+	.protocol = 0,
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(tcp_protocol, variant2) {
+	/* clang-format on */
+	.family = AF_INET,
+	.type = SOCK_STREAM,
+	.protocol = IPPROTO_TCP, /* = 6 */
+};
+
+/*
+ * Landlock doesn't perform protocol mappings handled by network stack on
+ * protocol family level. Test verifies that if only one definition is
+ * allowed another becomes restricted.
+ */
+TEST_F(tcp_protocol, alias_restriction)
+{
+	const struct landlock_ruleset_attr ruleset_attr = {
+		.handled_access_socket = LANDLOCK_ACCESS_SOCKET_CREATE,
+	};
+	const int family = variant->family;
+	const int type = variant->type;
+	const int protocol = variant->protocol;
+	const struct landlock_socket_attr tcp_socket_create = {
+		.allowed_access = LANDLOCK_ACCESS_SOCKET_CREATE,
+		.family = family,
+		.type = type,
+		.protocol = protocol,
+	};
+	int ruleset_fd;
+
+	ASSERT_EQ(0, test_socket(AF_INET, SOCK_STREAM, 0));
+	ASSERT_EQ(0, test_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
+
+	ruleset_fd =
+		landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
+	ASSERT_LE(0, ruleset_fd);
+
+	ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_SOCKET,
+				       &tcp_socket_create, 0));
+	enforce_ruleset(_metadata, ruleset_fd);
+	ASSERT_EQ(0, close(ruleset_fd));
+
+	if (protocol == 0) {
+		EXPECT_EQ(0, test_socket(AF_INET, SOCK_STREAM, 0));
+		EXPECT_EQ(EACCES,
+			  test_socket(AF_PACKET, SOCK_STREAM, IPPROTO_TCP));
+	} else if (protocol == IPPROTO_TCP) {
+		EXPECT_EQ(EACCES, test_socket(AF_INET, SOCK_STREAM, 0));
+		EXPECT_EQ(0, test_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
+	}
+}
+
 TEST_HARNESS_MAIN
-- 
2.34.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ