diff mbox series

[v3,2/4] Network helpers in landlock suite common functions

Message ID 20241106-landlock_network-v3-2-855b14df63c6@suse.com
State Accepted
Headers show
Series landlock network coverage support | expand

Commit Message

Andrea Cervesato Nov. 6, 2024, 11:13 a.m. UTC
From: Andrea Cervesato <andrea.cervesato@suse.com>

Landlock suite helpers functions don't support network features. This
patch adds apply_landlock_net_layer() helper that can be used to apply a
network landlock rule in the current sandbox.

Reviewed-by: Cyril Hrubis <chrubis@suse.cz>
Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 .../kernel/syscalls/landlock/landlock_common.h     | 124 +++++++++++++++++++++
 1 file changed, 124 insertions(+)
diff mbox series

Patch

diff --git a/testcases/kernel/syscalls/landlock/landlock_common.h b/testcases/kernel/syscalls/landlock/landlock_common.h
index f3096f4bf15f155f2a00b39c461d0805a76306e5..4aa11b7d2ad46915cd1ce1592bdaa2fb6ad77628 100644
--- a/testcases/kernel/syscalls/landlock/landlock_common.h
+++ b/testcases/kernel/syscalls/landlock/landlock_common.h
@@ -11,6 +11,16 @@ 
 #include "lapi/fcntl.h"
 #include "lapi/landlock.h"
 
+#define IPV4_LOCALHOST "127.0.0.1"
+#define IPV6_LOCALHOST "::1"
+
+struct socket_data {
+	struct sockaddr_in addr_ipv4;
+	struct sockaddr_in6 addr_ipv6;
+	size_t address_size;
+	int fd;
+};
+
 static inline int verify_landlock_is_enabled(void)
 {
 	int abi;
@@ -51,6 +61,22 @@  static inline void apply_landlock_fs_rule(
 	SAFE_CLOSE(path_beneath_attr->parent_fd);
 }
 
+static inline void apply_landlock_net_rule(
+	struct landlock_net_port_attr *net_attr,
+	const int ruleset_fd,
+	const uint64_t port,
+	const uint64_t access)
+{
+	net_attr->port = port;
+	net_attr->allowed_access = access;
+
+	SAFE_LANDLOCK_ADD_RULE(
+		ruleset_fd,
+		LANDLOCK_RULE_NET_PORT,
+		net_attr,
+		0);
+}
+
 static inline void enforce_ruleset(const int ruleset_fd)
 {
 	SAFE_PRCTL(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
@@ -72,4 +98,102 @@  static inline void apply_landlock_fs_layer(
 
 	SAFE_CLOSE(ruleset_fd);
 }
+
+static inline void apply_landlock_net_layer(
+	void *ruleset_attr, size_t attr_size,
+	struct landlock_net_port_attr *net_port_attr,
+	const in_port_t port,
+	const uint64_t access)
+{
+	int ruleset_fd;
+
+	ruleset_fd = SAFE_LANDLOCK_CREATE_RULESET(ruleset_attr, attr_size, 0);
+
+	apply_landlock_net_rule(net_port_attr, ruleset_fd, port, access);
+	enforce_ruleset(ruleset_fd);
+
+	SAFE_CLOSE(ruleset_fd);
+}
+
+static inline in_port_t getsocket_port(struct socket_data *socket,
+	const int addr_family)
+{
+	struct sockaddr_in addr_ipv4;
+	struct sockaddr_in6 addr_ipv6;
+	socklen_t len;
+	in_port_t port = 0;
+
+	switch (addr_family) {
+	case AF_INET:
+		len = sizeof(addr_ipv4);
+		memset(&addr_ipv4, 0, len);
+
+		SAFE_GETSOCKNAME(socket->fd, (struct sockaddr *)&addr_ipv4, &len);
+		port = ntohs(addr_ipv4.sin_port);
+		break;
+	case AF_INET6:
+		len = sizeof(addr_ipv6);
+		memset(&addr_ipv6, 0, len);
+
+		SAFE_GETSOCKNAME(socket->fd, (struct sockaddr *)&addr_ipv6, &len);
+		port = ntohs(addr_ipv6.sin6_port);
+		break;
+	default:
+		tst_brk(TBROK, "Unsupported protocol");
+		break;
+	};
+
+	return port;
+}
+
+static inline void create_socket(struct socket_data *socket,
+	const int addr_family, const in_port_t port)
+{
+	memset(socket, 0, sizeof(struct socket_data));
+
+	switch (addr_family) {
+	case AF_INET:
+		if (!port) {
+			tst_init_sockaddr_inet_bin(&socket->addr_ipv4,
+				INADDR_ANY, 0);
+		} else {
+			tst_init_sockaddr_inet(&socket->addr_ipv4,
+				IPV4_LOCALHOST, port);
+		}
+
+		socket->address_size = sizeof(struct sockaddr_in);
+		break;
+	case AF_INET6:
+		if (!port) {
+			tst_init_sockaddr_inet6_bin(&socket->addr_ipv6,
+				&in6addr_any, 0);
+		} else {
+			tst_init_sockaddr_inet6(&socket->addr_ipv6,
+				IPV6_LOCALHOST, port);
+		}
+
+		socket->address_size = sizeof(struct sockaddr_in6);
+		break;
+	default:
+		tst_brk(TBROK, "Unsupported protocol");
+		return;
+	};
+
+	socket->fd = SAFE_SOCKET(addr_family, SOCK_STREAM | SOCK_CLOEXEC, 0);
+}
+
+static inline void getsocket_addr(struct socket_data *socket,
+	const int addr_family, struct sockaddr **addr)
+{
+	switch (addr_family) {
+	case AF_INET:
+		*addr = (struct sockaddr *)&socket->addr_ipv4;
+		break;
+	case AF_INET6:
+		*addr = (struct sockaddr *)&socket->addr_ipv6;
+		break;
+	default:
+		break;
+	};
+}
 #endif /* LANDLOCK_COMMON_H__ */