1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Landlock - Network management and hooks 4 * 5 * Copyright © 2022-2023 Huawei Tech. Co., Ltd. 6 * Copyright © 2022-2025 Microsoft Corporation 7 */ 8 9 #include <linux/in.h> 10 #include <linux/lsm_audit.h> 11 #include <linux/net.h> 12 #include <linux/socket.h> 13 #include <net/ipv6.h> 14 15 #include "audit.h" 16 #include "common.h" 17 #include "cred.h" 18 #include "limits.h" 19 #include "net.h" 20 #include "ruleset.h" 21 22 int landlock_append_net_rule(struct landlock_ruleset *const ruleset, 23 const u16 port, access_mask_t access_rights) 24 { 25 int err; 26 const struct landlock_id id = { 27 .key.data = (__force uintptr_t)htons(port), 28 .type = LANDLOCK_KEY_NET_PORT, 29 }; 30 31 BUILD_BUG_ON(sizeof(port) > sizeof(id.key.data)); 32 33 /* Transforms relative access rights to absolute ones. */ 34 access_rights |= LANDLOCK_MASK_ACCESS_NET & 35 ~landlock_get_net_access_mask(ruleset, 0); 36 37 mutex_lock(&ruleset->lock); 38 err = landlock_insert_rule(ruleset, id, access_rights); 39 mutex_unlock(&ruleset->lock); 40 41 return err; 42 } 43 44 static int current_check_access_socket(struct socket *const sock, 45 struct sockaddr *const address, 46 const int addrlen, 47 access_mask_t access_request) 48 { 49 __be16 port; 50 layer_mask_t layer_masks[LANDLOCK_NUM_ACCESS_NET] = {}; 51 const struct landlock_rule *rule; 52 struct landlock_id id = { 53 .type = LANDLOCK_KEY_NET_PORT, 54 }; 55 const struct access_masks masks = { 56 .net = access_request, 57 }; 58 const struct landlock_cred_security *const subject = 59 landlock_get_applicable_subject(current_cred(), masks, NULL); 60 struct lsm_network_audit audit_net = {}; 61 62 if (!subject) 63 return 0; 64 65 if (!sk_is_tcp(sock->sk)) 66 return 0; 67 68 /* Checks for minimal header length to safely read sa_family. */ 69 if (addrlen < offsetofend(typeof(*address), sa_family)) 70 return -EINVAL; 71 72 switch (address->sa_family) { 73 case AF_UNSPEC: 74 if (access_request == LANDLOCK_ACCESS_NET_CONNECT_TCP) { 75 /* 76 * Connecting to an address with AF_UNSPEC dissolves 77 * the TCP association, which have the same effect as 78 * closing the connection while retaining the socket 79 * object (i.e., the file descriptor). As for dropping 80 * privileges, closing connections is always allowed. 81 * 82 * For a TCP access control system, this request is 83 * legitimate. Let the network stack handle potential 84 * inconsistencies and return -EINVAL if needed. 85 */ 86 return 0; 87 } else if (access_request == LANDLOCK_ACCESS_NET_BIND_TCP) { 88 /* 89 * Binding to an AF_UNSPEC address is treated 90 * differently by IPv4 and IPv6 sockets. The socket's 91 * family may change under our feet due to 92 * setsockopt(IPV6_ADDRFORM), but that's ok: we either 93 * reject entirely or require 94 * %LANDLOCK_ACCESS_NET_BIND_TCP for the given port, so 95 * it cannot be used to bypass the policy. 96 * 97 * IPv4 sockets map AF_UNSPEC to AF_INET for 98 * retrocompatibility for bind accesses, only if the 99 * address is INADDR_ANY (cf. __inet_bind). IPv6 100 * sockets always reject it. 101 * 102 * Checking the address is required to not wrongfully 103 * return -EACCES instead of -EAFNOSUPPORT or -EINVAL. 104 * We could return 0 and let the network stack handle 105 * these checks, but it is safer to return a proper 106 * error and test consistency thanks to kselftest. 107 */ 108 if (sock->sk->__sk_common.skc_family == AF_INET) { 109 const struct sockaddr_in *const sockaddr = 110 (struct sockaddr_in *)address; 111 112 if (addrlen < sizeof(struct sockaddr_in)) 113 return -EINVAL; 114 115 if (sockaddr->sin_addr.s_addr != 116 htonl(INADDR_ANY)) 117 return -EAFNOSUPPORT; 118 } else { 119 if (addrlen < SIN6_LEN_RFC2133) 120 return -EINVAL; 121 else 122 return -EAFNOSUPPORT; 123 } 124 } else { 125 WARN_ON_ONCE(1); 126 } 127 /* Only for bind(AF_UNSPEC+INADDR_ANY) on IPv4 socket. */ 128 fallthrough; 129 case AF_INET: { 130 const struct sockaddr_in *addr4; 131 132 if (addrlen < sizeof(struct sockaddr_in)) 133 return -EINVAL; 134 135 addr4 = (struct sockaddr_in *)address; 136 port = addr4->sin_port; 137 138 if (access_request == LANDLOCK_ACCESS_NET_CONNECT_TCP) { 139 audit_net.dport = port; 140 audit_net.v4info.daddr = addr4->sin_addr.s_addr; 141 } else if (access_request == LANDLOCK_ACCESS_NET_BIND_TCP) { 142 audit_net.sport = port; 143 audit_net.v4info.saddr = addr4->sin_addr.s_addr; 144 } else { 145 WARN_ON_ONCE(1); 146 } 147 break; 148 } 149 150 #if IS_ENABLED(CONFIG_IPV6) 151 case AF_INET6: { 152 const struct sockaddr_in6 *addr6; 153 154 if (addrlen < SIN6_LEN_RFC2133) 155 return -EINVAL; 156 157 addr6 = (struct sockaddr_in6 *)address; 158 port = addr6->sin6_port; 159 160 if (access_request == LANDLOCK_ACCESS_NET_CONNECT_TCP) { 161 audit_net.dport = port; 162 audit_net.v6info.daddr = addr6->sin6_addr; 163 } else if (access_request == LANDLOCK_ACCESS_NET_BIND_TCP) { 164 audit_net.sport = port; 165 audit_net.v6info.saddr = addr6->sin6_addr; 166 } else { 167 WARN_ON_ONCE(1); 168 } 169 break; 170 } 171 #endif /* IS_ENABLED(CONFIG_IPV6) */ 172 173 default: 174 return 0; 175 } 176 177 /* 178 * Checks sa_family consistency to not wrongfully return 179 * -EACCES instead of -EINVAL. Valid sa_family changes are 180 * only (from AF_INET or AF_INET6) to AF_UNSPEC. 181 * 182 * We could return 0 and let the network stack handle this 183 * check, but it is safer to return a proper error and test 184 * consistency thanks to kselftest. 185 */ 186 if (address->sa_family != sock->sk->__sk_common.skc_family && 187 address->sa_family != AF_UNSPEC) 188 return -EINVAL; 189 190 id.key.data = (__force uintptr_t)port; 191 BUILD_BUG_ON(sizeof(port) > sizeof(id.key.data)); 192 193 rule = landlock_find_rule(subject->domain, id); 194 access_request = landlock_init_layer_masks(subject->domain, 195 access_request, &layer_masks, 196 LANDLOCK_KEY_NET_PORT); 197 if (landlock_unmask_layers(rule, access_request, &layer_masks, 198 ARRAY_SIZE(layer_masks))) 199 return 0; 200 201 audit_net.family = address->sa_family; 202 landlock_log_denial(subject, 203 &(struct landlock_request){ 204 .type = LANDLOCK_REQUEST_NET_ACCESS, 205 .audit.type = LSM_AUDIT_DATA_NET, 206 .audit.u.net = &audit_net, 207 .access = access_request, 208 .layer_masks = &layer_masks, 209 .layer_masks_size = ARRAY_SIZE(layer_masks), 210 }); 211 return -EACCES; 212 } 213 214 static int hook_socket_bind(struct socket *const sock, 215 struct sockaddr *const address, const int addrlen) 216 { 217 return current_check_access_socket(sock, address, addrlen, 218 LANDLOCK_ACCESS_NET_BIND_TCP); 219 } 220 221 static int hook_socket_connect(struct socket *const sock, 222 struct sockaddr *const address, 223 const int addrlen) 224 { 225 return current_check_access_socket(sock, address, addrlen, 226 LANDLOCK_ACCESS_NET_CONNECT_TCP); 227 } 228 229 static struct security_hook_list landlock_hooks[] __ro_after_init = { 230 LSM_HOOK_INIT(socket_bind, hook_socket_bind), 231 LSM_HOOK_INIT(socket_connect, hook_socket_connect), 232 }; 233 234 __init void landlock_add_net_hooks(void) 235 { 236 security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks), 237 &landlock_lsmid); 238 } 239