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 case AF_INET: { 75 const struct sockaddr_in *addr4; 76 77 if (addrlen < sizeof(struct sockaddr_in)) 78 return -EINVAL; 79 80 addr4 = (struct sockaddr_in *)address; 81 port = addr4->sin_port; 82 83 if (access_request == LANDLOCK_ACCESS_NET_CONNECT_TCP) { 84 audit_net.dport = port; 85 audit_net.v4info.daddr = addr4->sin_addr.s_addr; 86 } else if (access_request == LANDLOCK_ACCESS_NET_BIND_TCP) { 87 audit_net.sport = port; 88 audit_net.v4info.saddr = addr4->sin_addr.s_addr; 89 } else { 90 WARN_ON_ONCE(1); 91 } 92 break; 93 } 94 95 #if IS_ENABLED(CONFIG_IPV6) 96 case AF_INET6: { 97 const struct sockaddr_in6 *addr6; 98 99 if (addrlen < SIN6_LEN_RFC2133) 100 return -EINVAL; 101 102 addr6 = (struct sockaddr_in6 *)address; 103 port = addr6->sin6_port; 104 105 if (access_request == LANDLOCK_ACCESS_NET_CONNECT_TCP) { 106 audit_net.dport = port; 107 audit_net.v6info.daddr = addr6->sin6_addr; 108 } else if (access_request == LANDLOCK_ACCESS_NET_BIND_TCP) { 109 audit_net.sport = port; 110 audit_net.v6info.saddr = addr6->sin6_addr; 111 } else { 112 WARN_ON_ONCE(1); 113 } 114 break; 115 } 116 #endif /* IS_ENABLED(CONFIG_IPV6) */ 117 118 default: 119 return 0; 120 } 121 122 /* Specific AF_UNSPEC handling. */ 123 if (address->sa_family == AF_UNSPEC) { 124 /* 125 * Connecting to an address with AF_UNSPEC dissolves the TCP 126 * association, which have the same effect as closing the 127 * connection while retaining the socket object (i.e., the file 128 * descriptor). As for dropping privileges, closing 129 * connections is always allowed. 130 * 131 * For a TCP access control system, this request is legitimate. 132 * Let the network stack handle potential inconsistencies and 133 * return -EINVAL if needed. 134 */ 135 if (access_request == LANDLOCK_ACCESS_NET_CONNECT_TCP) 136 return 0; 137 138 /* 139 * For compatibility reason, accept AF_UNSPEC for bind 140 * accesses (mapped to AF_INET) only if the address is 141 * INADDR_ANY (cf. __inet_bind). Checking the address is 142 * required to not wrongfully return -EACCES instead of 143 * -EAFNOSUPPORT. 144 * 145 * We could return 0 and let the network stack handle these 146 * checks, but it is safer to return a proper error and test 147 * consistency thanks to kselftest. 148 */ 149 if (access_request == LANDLOCK_ACCESS_NET_BIND_TCP) { 150 /* addrlen has already been checked for AF_UNSPEC. */ 151 const struct sockaddr_in *const sockaddr = 152 (struct sockaddr_in *)address; 153 154 if (sock->sk->__sk_common.skc_family != AF_INET) 155 return -EINVAL; 156 157 if (sockaddr->sin_addr.s_addr != htonl(INADDR_ANY)) 158 return -EAFNOSUPPORT; 159 } 160 } else { 161 /* 162 * Checks sa_family consistency to not wrongfully return 163 * -EACCES instead of -EINVAL. Valid sa_family changes are 164 * only (from AF_INET or AF_INET6) to AF_UNSPEC. 165 * 166 * We could return 0 and let the network stack handle this 167 * check, but it is safer to return a proper error and test 168 * consistency thanks to kselftest. 169 */ 170 if (address->sa_family != sock->sk->__sk_common.skc_family) 171 return -EINVAL; 172 } 173 174 id.key.data = (__force uintptr_t)port; 175 BUILD_BUG_ON(sizeof(port) > sizeof(id.key.data)); 176 177 rule = landlock_find_rule(subject->domain, id); 178 access_request = landlock_init_layer_masks(subject->domain, 179 access_request, &layer_masks, 180 LANDLOCK_KEY_NET_PORT); 181 if (landlock_unmask_layers(rule, access_request, &layer_masks, 182 ARRAY_SIZE(layer_masks))) 183 return 0; 184 185 audit_net.family = address->sa_family; 186 landlock_log_denial(subject, 187 &(struct landlock_request){ 188 .type = LANDLOCK_REQUEST_NET_ACCESS, 189 .audit.type = LSM_AUDIT_DATA_NET, 190 .audit.u.net = &audit_net, 191 .access = access_request, 192 .layer_masks = &layer_masks, 193 .layer_masks_size = ARRAY_SIZE(layer_masks), 194 }); 195 return -EACCES; 196 } 197 198 static int hook_socket_bind(struct socket *const sock, 199 struct sockaddr *const address, const int addrlen) 200 { 201 return current_check_access_socket(sock, address, addrlen, 202 LANDLOCK_ACCESS_NET_BIND_TCP); 203 } 204 205 static int hook_socket_connect(struct socket *const sock, 206 struct sockaddr *const address, 207 const int addrlen) 208 { 209 return current_check_access_socket(sock, address, addrlen, 210 LANDLOCK_ACCESS_NET_CONNECT_TCP); 211 } 212 213 static struct security_hook_list landlock_hooks[] __ro_after_init = { 214 LSM_HOOK_INIT(socket_bind, hook_socket_bind), 215 LSM_HOOK_INIT(socket_connect, hook_socket_connect), 216 }; 217 218 __init void landlock_add_net_hooks(void) 219 { 220 security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks), 221 &landlock_lsmid); 222 } 223