1 // SPDX-License-Identifier: GPL-2.0-only
3 * Landlock LSM - Network management and hooks
5 * Copyright © 2022-2023 Huawei Tech. Co., Ltd.
6 * Copyright © 2022-2023 Microsoft Corporation
10 #include <linux/net.h>
11 #include <linux/socket.h>
20 int landlock_append_net_rule(struct landlock_ruleset
*const ruleset
,
21 const u16 port
, access_mask_t access_rights
)
24 const struct landlock_id id
= {
25 .key
.data
= (__force
uintptr_t)htons(port
),
26 .type
= LANDLOCK_KEY_NET_PORT
,
29 BUILD_BUG_ON(sizeof(port
) > sizeof(id
.key
.data
));
31 /* Transforms relative access rights to absolute ones. */
32 access_rights
|= LANDLOCK_MASK_ACCESS_NET
&
33 ~landlock_get_net_access_mask(ruleset
, 0);
35 mutex_lock(&ruleset
->lock
);
36 err
= landlock_insert_rule(ruleset
, id
, access_rights
);
37 mutex_unlock(&ruleset
->lock
);
42 static const struct access_masks any_net
= {
46 static int current_check_access_socket(struct socket
*const sock
,
47 struct sockaddr
*const address
,
49 access_mask_t access_request
)
52 layer_mask_t layer_masks
[LANDLOCK_NUM_ACCESS_NET
] = {};
53 const struct landlock_rule
*rule
;
54 struct landlock_id id
= {
55 .type
= LANDLOCK_KEY_NET_PORT
,
57 const struct landlock_ruleset
*const dom
=
58 landlock_get_applicable_domain(landlock_get_current_domain(),
63 if (WARN_ON_ONCE(dom
->num_layers
< 1))
66 /* Checks if it's a (potential) TCP socket. */
67 if (sock
->type
!= SOCK_STREAM
)
70 /* Checks for minimal header length to safely read sa_family. */
71 if (addrlen
< offsetofend(typeof(*address
), sa_family
))
74 switch (address
->sa_family
) {
77 if (addrlen
< sizeof(struct sockaddr_in
))
79 port
= ((struct sockaddr_in
*)address
)->sin_port
;
82 #if IS_ENABLED(CONFIG_IPV6)
84 if (addrlen
< SIN6_LEN_RFC2133
)
86 port
= ((struct sockaddr_in6
*)address
)->sin6_port
;
88 #endif /* IS_ENABLED(CONFIG_IPV6) */
94 /* Specific AF_UNSPEC handling. */
95 if (address
->sa_family
== AF_UNSPEC
) {
97 * Connecting to an address with AF_UNSPEC dissolves the TCP
98 * association, which have the same effect as closing the
99 * connection while retaining the socket object (i.e., the file
100 * descriptor). As for dropping privileges, closing
101 * connections is always allowed.
103 * For a TCP access control system, this request is legitimate.
104 * Let the network stack handle potential inconsistencies and
105 * return -EINVAL if needed.
107 if (access_request
== LANDLOCK_ACCESS_NET_CONNECT_TCP
)
111 * For compatibility reason, accept AF_UNSPEC for bind
112 * accesses (mapped to AF_INET) only if the address is
113 * INADDR_ANY (cf. __inet_bind). Checking the address is
114 * required to not wrongfully return -EACCES instead of
117 * We could return 0 and let the network stack handle these
118 * checks, but it is safer to return a proper error and test
119 * consistency thanks to kselftest.
121 if (access_request
== LANDLOCK_ACCESS_NET_BIND_TCP
) {
122 /* addrlen has already been checked for AF_UNSPEC. */
123 const struct sockaddr_in
*const sockaddr
=
124 (struct sockaddr_in
*)address
;
126 if (sock
->sk
->__sk_common
.skc_family
!= AF_INET
)
129 if (sockaddr
->sin_addr
.s_addr
!= htonl(INADDR_ANY
))
130 return -EAFNOSUPPORT
;
134 * Checks sa_family consistency to not wrongfully return
135 * -EACCES instead of -EINVAL. Valid sa_family changes are
136 * only (from AF_INET or AF_INET6) to AF_UNSPEC.
138 * We could return 0 and let the network stack handle this
139 * check, but it is safer to return a proper error and test
140 * consistency thanks to kselftest.
142 if (address
->sa_family
!= sock
->sk
->__sk_common
.skc_family
)
146 id
.key
.data
= (__force
uintptr_t)port
;
147 BUILD_BUG_ON(sizeof(port
) > sizeof(id
.key
.data
));
149 rule
= landlock_find_rule(dom
, id
);
150 access_request
= landlock_init_layer_masks(
151 dom
, access_request
, &layer_masks
, LANDLOCK_KEY_NET_PORT
);
152 if (landlock_unmask_layers(rule
, access_request
, &layer_masks
,
153 ARRAY_SIZE(layer_masks
)))
159 static int hook_socket_bind(struct socket
*const sock
,
160 struct sockaddr
*const address
, const int addrlen
)
162 return current_check_access_socket(sock
, address
, addrlen
,
163 LANDLOCK_ACCESS_NET_BIND_TCP
);
166 static int hook_socket_connect(struct socket
*const sock
,
167 struct sockaddr
*const address
,
170 return current_check_access_socket(sock
, address
, addrlen
,
171 LANDLOCK_ACCESS_NET_CONNECT_TCP
);
174 static struct security_hook_list landlock_hooks
[] __ro_after_init
= {
175 LSM_HOOK_INIT(socket_bind
, hook_socket_bind
),
176 LSM_HOOK_INIT(socket_connect
, hook_socket_connect
),
179 __init
void landlock_add_net_hooks(void)
181 security_add_hooks(landlock_hooks
, ARRAY_SIZE(landlock_hooks
),