@@ -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__ */