|
17 | 17 | #include <net/ipv6.h> |
18 | 18 | #include <net/icmp.h> |
19 | 19 |
|
| 20 | +DEFINE_STATIC_KEY_DEFERRED_FALSE(tcp_ao_needed, HZ); |
| 21 | + |
20 | 22 | int tcp_ao_calc_traffic_key(struct tcp_ao_key *mkt, u8 *key, void *ctx, |
21 | 23 | unsigned int len, struct tcp_sigpool *hp) |
22 | 24 | { |
@@ -50,6 +52,9 @@ bool tcp_ao_ignore_icmp(const struct sock *sk, int family, int type, int code) |
50 | 52 | bool ignore_icmp = false; |
51 | 53 | struct tcp_ao_info *ao; |
52 | 54 |
|
| 55 | + if (!static_branch_unlikely(&tcp_ao_needed.key)) |
| 56 | + return false; |
| 57 | + |
53 | 58 | /* RFC5925, 7.8: |
54 | 59 | * >> A TCP-AO implementation MUST default to ignore incoming ICMPv4 |
55 | 60 | * messages of Type 3 (destination unreachable), Codes 2-4 (protocol |
@@ -185,6 +190,9 @@ static struct tcp_ao_key *__tcp_ao_do_lookup(const struct sock *sk, |
185 | 190 | struct tcp_ao_key *key; |
186 | 191 | struct tcp_ao_info *ao; |
187 | 192 |
|
| 193 | + if (!static_branch_unlikely(&tcp_ao_needed.key)) |
| 194 | + return NULL; |
| 195 | + |
188 | 196 | ao = rcu_dereference_check(tcp_sk(sk)->ao_info, |
189 | 197 | lockdep_sock_is_held(sk)); |
190 | 198 | if (!ao) |
@@ -276,6 +284,7 @@ void tcp_ao_destroy_sock(struct sock *sk, bool twsk) |
276 | 284 | } |
277 | 285 |
|
278 | 286 | kfree_rcu(ao, rcu); |
| 287 | + static_branch_slow_dec_deferred(&tcp_ao_needed); |
279 | 288 | } |
280 | 289 |
|
281 | 290 | void tcp_ao_time_wait(struct tcp_timewait_sock *tcptw, struct tcp_sock *tp) |
@@ -1180,6 +1189,11 @@ int tcp_ao_copy_all_matching(const struct sock *sk, struct sock *newsk, |
1180 | 1189 | goto free_and_exit; |
1181 | 1190 | } |
1182 | 1191 |
|
| 1192 | + if (!static_key_fast_inc_not_disabled(&tcp_ao_needed.key.key)) { |
| 1193 | + ret = -EUSERS; |
| 1194 | + goto free_and_exit; |
| 1195 | + } |
| 1196 | + |
1183 | 1197 | key_head = rcu_dereference(hlist_first_rcu(&new_ao->head)); |
1184 | 1198 | first_key = hlist_entry_safe(key_head, struct tcp_ao_key, node); |
1185 | 1199 |
|
@@ -1607,6 +1621,10 @@ static int tcp_ao_add_cmd(struct sock *sk, unsigned short int family, |
1607 | 1621 |
|
1608 | 1622 | tcp_ao_link_mkt(ao_info, key); |
1609 | 1623 | if (first) { |
| 1624 | + if (!static_branch_inc(&tcp_ao_needed.key)) { |
| 1625 | + ret = -EUSERS; |
| 1626 | + goto err_free_sock; |
| 1627 | + } |
1610 | 1628 | sk_gso_disable(sk); |
1611 | 1629 | rcu_assign_pointer(tcp_sk(sk)->ao_info, ao_info); |
1612 | 1630 | } |
@@ -1875,6 +1893,10 @@ static int tcp_ao_info_cmd(struct sock *sk, unsigned short int family, |
1875 | 1893 | if (new_rnext) |
1876 | 1894 | WRITE_ONCE(ao_info->rnext_key, new_rnext); |
1877 | 1895 | if (first) { |
| 1896 | + if (!static_branch_inc(&tcp_ao_needed.key)) { |
| 1897 | + err = -EUSERS; |
| 1898 | + goto out; |
| 1899 | + } |
1878 | 1900 | sk_gso_disable(sk); |
1879 | 1901 | rcu_assign_pointer(tcp_sk(sk)->ao_info, ao_info); |
1880 | 1902 | } |
|
0 commit comments