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 struct layer_access_masks layer_masks = {}; 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 /* Checks for minimal header length to safely read sa_family. */ 66 if (addrlen < offsetofend(typeof(*address), sa_family)) 67 return -EINVAL; 68 69 switch (address->sa_family) { 70 case AF_UNSPEC: 71 if (access_request == LANDLOCK_ACCESS_NET_CONNECT_TCP) { 72 /* 73 * Connecting to an address with AF_UNSPEC dissolves 74 * the TCP association, which have the same effect as 75 * closing the connection while retaining the socket 76 * object (i.e., the file descriptor). As for dropping 77 * privileges, closing connections is always allowed. 78 * 79 * For a TCP access control system, this request is 80 * legitimate. Let the network stack handle potential 81 * inconsistencies and return -EINVAL if needed. 82 */ 83 return 0; 84 } else if (access_request == LANDLOCK_ACCESS_NET_BIND_TCP) { 85 /* 86 * Binding to an AF_UNSPEC address is treated 87 * differently by IPv4 and IPv6 sockets. The socket's 88 * family may change under our feet due to 89 * setsockopt(IPV6_ADDRFORM), but that's ok: we either 90 * reject entirely or require 91 * %LANDLOCK_ACCESS_NET_BIND_TCP for the given port, so 92 * it cannot be used to bypass the policy. 93 * 94 * IPv4 sockets map AF_UNSPEC to AF_INET for 95 * retrocompatibility for bind accesses, only if the 96 * address is INADDR_ANY (cf. __inet_bind). IPv6 97 * sockets always reject it. 98 * 99 * Checking the address is required to not wrongfully 100 * return -EACCES instead of -EAFNOSUPPORT or -EINVAL. 101 * We could return 0 and let the network stack handle 102 * these checks, but it is safer to return a proper 103 * error and test consistency thanks to kselftest. 104 */ 105 if (sock->sk->__sk_common.skc_family == AF_INET) { 106 const struct sockaddr_in *const sockaddr = 107 (struct sockaddr_in *)address; 108 109 if (addrlen < sizeof(struct sockaddr_in)) 110 return -EINVAL; 111 112 if (sockaddr->sin_addr.s_addr != 113 htonl(INADDR_ANY)) 114 return -EAFNOSUPPORT; 115 } else { 116 if (addrlen < SIN6_LEN_RFC2133) 117 return -EINVAL; 118 else 119 return -EAFNOSUPPORT; 120 } 121 } else { 122 WARN_ON_ONCE(1); 123 } 124 /* Only for bind(AF_UNSPEC+INADDR_ANY) on IPv4 socket. */ 125 fallthrough; 126 case AF_INET: { 127 const struct sockaddr_in *addr4; 128 129 if (addrlen < sizeof(struct sockaddr_in)) 130 return -EINVAL; 131 132 addr4 = (struct sockaddr_in *)address; 133 port = addr4->sin_port; 134 135 if (access_request == LANDLOCK_ACCESS_NET_CONNECT_TCP) { 136 audit_net.dport = port; 137 audit_net.v4info.daddr = addr4->sin_addr.s_addr; 138 } else if (access_request == LANDLOCK_ACCESS_NET_BIND_TCP) { 139 audit_net.sport = port; 140 audit_net.v4info.saddr = addr4->sin_addr.s_addr; 141 } else { 142 WARN_ON_ONCE(1); 143 } 144 break; 145 } 146 147 #if IS_ENABLED(CONFIG_IPV6) 148 case AF_INET6: { 149 const struct sockaddr_in6 *addr6; 150 151 if (addrlen < SIN6_LEN_RFC2133) 152 return -EINVAL; 153 154 addr6 = (struct sockaddr_in6 *)address; 155 port = addr6->sin6_port; 156 157 if (access_request == LANDLOCK_ACCESS_NET_CONNECT_TCP) { 158 audit_net.dport = port; 159 audit_net.v6info.daddr = addr6->sin6_addr; 160 } else if (access_request == LANDLOCK_ACCESS_NET_BIND_TCP) { 161 audit_net.sport = port; 162 audit_net.v6info.saddr = addr6->sin6_addr; 163 } else { 164 WARN_ON_ONCE(1); 165 } 166 break; 167 } 168 #endif /* IS_ENABLED(CONFIG_IPV6) */ 169 170 default: 171 return 0; 172 } 173 174 /* 175 * Checks sa_family consistency to not wrongfully return 176 * -EACCES instead of -EINVAL. Valid sa_family changes are 177 * only (from AF_INET or AF_INET6) to AF_UNSPEC. 178 * 179 * We could return 0 and let the network stack handle this 180 * check, but it is safer to return a proper error and test 181 * consistency thanks to kselftest. 182 */ 183 if (address->sa_family != sock->sk->__sk_common.skc_family && 184 address->sa_family != AF_UNSPEC) 185 return -EINVAL; 186 187 id.key.data = (__force uintptr_t)port; 188 BUILD_BUG_ON(sizeof(port) > sizeof(id.key.data)); 189 190 rule = landlock_find_rule(subject->domain, id); 191 access_request = landlock_init_layer_masks(subject->domain, 192 access_request, &layer_masks, 193 LANDLOCK_KEY_NET_PORT); 194 if (!access_request) 195 return 0; 196 197 if (landlock_unmask_layers(rule, &layer_masks)) 198 return 0; 199 200 audit_net.family = address->sa_family; 201 landlock_log_denial(subject, 202 &(struct landlock_request){ 203 .type = LANDLOCK_REQUEST_NET_ACCESS, 204 .audit.type = LSM_AUDIT_DATA_NET, 205 .audit.u.net = &audit_net, 206 .access = access_request, 207 .layer_masks = &layer_masks, 208 }); 209 return -EACCES; 210 } 211 212 static int hook_socket_bind(struct socket *const sock, 213 struct sockaddr *const address, const int addrlen) 214 { 215 access_mask_t access_request; 216 217 if (sk_is_tcp(sock->sk)) 218 access_request = LANDLOCK_ACCESS_NET_BIND_TCP; 219 else 220 return 0; 221 222 return current_check_access_socket(sock, address, addrlen, 223 access_request); 224 } 225 226 static int hook_socket_connect(struct socket *const sock, 227 struct sockaddr *const address, 228 const int addrlen) 229 { 230 access_mask_t access_request; 231 232 if (sk_is_tcp(sock->sk)) 233 access_request = LANDLOCK_ACCESS_NET_CONNECT_TCP; 234 else 235 return 0; 236 237 return current_check_access_socket(sock, address, addrlen, 238 access_request); 239 } 240 241 static struct security_hook_list landlock_hooks[] __ro_after_init = { 242 LSM_HOOK_INIT(socket_bind, hook_socket_bind), 243 LSM_HOOK_INIT(socket_connect, hook_socket_connect), 244 }; 245 246 __init void landlock_add_net_hooks(void) 247 { 248 security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks), 249 &landlock_lsmid); 250 } 251