.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Syncookies implementation for the Linux kernel |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 1997 Andi Kleen |
---|
5 | 6 | * Based on ideas by D.J.Bernstein and Eric Schenk. |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or |
---|
8 | | - * modify it under the terms of the GNU General Public License |
---|
9 | | - * as published by the Free Software Foundation; either version |
---|
10 | | - * 2 of the License, or (at your option) any later version. |
---|
11 | 7 | */ |
---|
12 | 8 | |
---|
13 | 9 | #include <linux/tcp.h> |
---|
.. | .. |
---|
66 | 62 | * Since subsequent timestamps use the normal tcp_time_stamp value, we |
---|
67 | 63 | * must make sure that the resulting initial timestamp is <= tcp_time_stamp. |
---|
68 | 64 | */ |
---|
69 | | -u64 cookie_init_timestamp(struct request_sock *req) |
---|
| 65 | +u64 cookie_init_timestamp(struct request_sock *req, u64 now) |
---|
70 | 66 | { |
---|
71 | 67 | struct inet_request_sock *ireq; |
---|
72 | | - u32 ts, ts_now = tcp_time_stamp_raw(); |
---|
| 68 | + u32 ts, ts_now = tcp_ns_to_ts(now); |
---|
73 | 69 | u32 options = 0; |
---|
74 | 70 | |
---|
75 | 71 | ireq = inet_rsk(req); |
---|
.. | .. |
---|
88 | 84 | ts <<= TSBITS; |
---|
89 | 85 | ts |= options; |
---|
90 | 86 | } |
---|
91 | | - return (u64)ts * (USEC_PER_SEC / TCP_TS_HZ); |
---|
| 87 | + return (u64)ts * (NSEC_PER_SEC / TCP_TS_HZ); |
---|
92 | 88 | } |
---|
93 | 89 | |
---|
94 | 90 | |
---|
.. | .. |
---|
216 | 212 | refcount_set(&req->rsk_refcnt, 1); |
---|
217 | 213 | tcp_sk(child)->tsoffset = tsoff; |
---|
218 | 214 | sock_rps_save_rxhash(child, skb); |
---|
219 | | - if (!inet_csk_reqsk_queue_add(sk, req, child)) { |
---|
220 | | - bh_unlock_sock(child); |
---|
221 | | - sock_put(child); |
---|
222 | | - child = NULL; |
---|
| 215 | + |
---|
| 216 | + if (rsk_drop_req(req)) { |
---|
223 | 217 | reqsk_put(req); |
---|
| 218 | + return child; |
---|
224 | 219 | } |
---|
225 | | - } else { |
---|
226 | | - reqsk_free(req); |
---|
| 220 | + |
---|
| 221 | + if (inet_csk_reqsk_queue_add(sk, req, child)) |
---|
| 222 | + return child; |
---|
| 223 | + |
---|
| 224 | + bh_unlock_sock(child); |
---|
| 225 | + sock_put(child); |
---|
227 | 226 | } |
---|
228 | | - return child; |
---|
| 227 | + __reqsk_free(req); |
---|
| 228 | + |
---|
| 229 | + return NULL; |
---|
229 | 230 | } |
---|
230 | 231 | EXPORT_SYMBOL(tcp_get_cookie_sock); |
---|
231 | 232 | |
---|
.. | .. |
---|
248 | 249 | return true; |
---|
249 | 250 | } |
---|
250 | 251 | |
---|
251 | | - if (!net->ipv4.sysctl_tcp_timestamps) |
---|
| 252 | + if (!READ_ONCE(net->ipv4.sysctl_tcp_timestamps)) |
---|
252 | 253 | return false; |
---|
253 | 254 | |
---|
254 | 255 | tcp_opt->sack_ok = (options & TS_OPT_SACK) ? TCP_SACK_SEEN : 0; |
---|
255 | 256 | |
---|
256 | | - if (tcp_opt->sack_ok && !net->ipv4.sysctl_tcp_sack) |
---|
| 257 | + if (tcp_opt->sack_ok && !READ_ONCE(net->ipv4.sysctl_tcp_sack)) |
---|
257 | 258 | return false; |
---|
258 | 259 | |
---|
259 | 260 | if ((options & TS_OPT_WSCALE_MASK) == TS_OPT_WSCALE_MASK) |
---|
.. | .. |
---|
262 | 263 | tcp_opt->wscale_ok = 1; |
---|
263 | 264 | tcp_opt->snd_wscale = options & TS_OPT_WSCALE_MASK; |
---|
264 | 265 | |
---|
265 | | - return net->ipv4.sysctl_tcp_window_scaling != 0; |
---|
| 266 | + return READ_ONCE(net->ipv4.sysctl_tcp_window_scaling) != 0; |
---|
266 | 267 | } |
---|
267 | 268 | EXPORT_SYMBOL(cookie_timestamp_decode); |
---|
268 | 269 | |
---|
.. | .. |
---|
280 | 281 | return dst_feature(dst, RTAX_FEATURE_ECN); |
---|
281 | 282 | } |
---|
282 | 283 | EXPORT_SYMBOL(cookie_ecn_ok); |
---|
| 284 | + |
---|
| 285 | +struct request_sock *cookie_tcp_reqsk_alloc(const struct request_sock_ops *ops, |
---|
| 286 | + const struct tcp_request_sock_ops *af_ops, |
---|
| 287 | + struct sock *sk, |
---|
| 288 | + struct sk_buff *skb) |
---|
| 289 | +{ |
---|
| 290 | + struct tcp_request_sock *treq; |
---|
| 291 | + struct request_sock *req; |
---|
| 292 | + |
---|
| 293 | + if (sk_is_mptcp(sk)) |
---|
| 294 | + req = mptcp_subflow_reqsk_alloc(ops, sk, false); |
---|
| 295 | + else |
---|
| 296 | + req = inet_reqsk_alloc(ops, sk, false); |
---|
| 297 | + |
---|
| 298 | + if (!req) |
---|
| 299 | + return NULL; |
---|
| 300 | + |
---|
| 301 | + treq = tcp_rsk(req); |
---|
| 302 | + |
---|
| 303 | + /* treq->af_specific might be used to perform TCP_MD5 lookup */ |
---|
| 304 | + treq->af_specific = af_ops; |
---|
| 305 | + |
---|
| 306 | + treq->syn_tos = TCP_SKB_CB(skb)->ip_dsfield; |
---|
| 307 | +#if IS_ENABLED(CONFIG_MPTCP) |
---|
| 308 | + treq->is_mptcp = sk_is_mptcp(sk); |
---|
| 309 | + if (treq->is_mptcp) { |
---|
| 310 | + int err = mptcp_subflow_init_cookie_req(req, sk, skb); |
---|
| 311 | + |
---|
| 312 | + if (err) { |
---|
| 313 | + reqsk_free(req); |
---|
| 314 | + return NULL; |
---|
| 315 | + } |
---|
| 316 | + } |
---|
| 317 | +#endif |
---|
| 318 | + |
---|
| 319 | + return req; |
---|
| 320 | +} |
---|
| 321 | +EXPORT_SYMBOL_GPL(cookie_tcp_reqsk_alloc); |
---|
283 | 322 | |
---|
284 | 323 | /* On input, sk is a listener. |
---|
285 | 324 | * Output is listener if incoming packet would not create a child |
---|
.. | .. |
---|
302 | 341 | struct flowi4 fl4; |
---|
303 | 342 | u32 tsoff = 0; |
---|
304 | 343 | |
---|
305 | | - if (!sock_net(sk)->ipv4.sysctl_tcp_syncookies || !th->ack || th->rst) |
---|
| 344 | + if (!READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_syncookies) || |
---|
| 345 | + !th->ack || th->rst) |
---|
306 | 346 | goto out; |
---|
307 | 347 | |
---|
308 | 348 | if (tcp_synq_no_recent_overflow(sk)) |
---|
.. | .. |
---|
331 | 371 | goto out; |
---|
332 | 372 | |
---|
333 | 373 | ret = NULL; |
---|
334 | | - req = inet_reqsk_alloc(&tcp_request_sock_ops, sk, false); /* for safety */ |
---|
| 374 | + req = cookie_tcp_reqsk_alloc(&tcp_request_sock_ops, |
---|
| 375 | + &tcp_request_sock_ipv4_ops, sk, skb); |
---|
335 | 376 | if (!req) |
---|
336 | 377 | goto out; |
---|
337 | 378 | |
---|
.. | .. |
---|
354 | 395 | req->ts_recent = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsval : 0; |
---|
355 | 396 | treq->snt_synack = 0; |
---|
356 | 397 | treq->tfo_listener = false; |
---|
| 398 | + |
---|
357 | 399 | if (IS_ENABLED(CONFIG_SMC)) |
---|
358 | 400 | ireq->smc_ok = 0; |
---|
359 | 401 | |
---|
.. | .. |
---|
382 | 424 | inet_sk_flowi_flags(sk), |
---|
383 | 425 | opt->srr ? opt->faddr : ireq->ir_rmt_addr, |
---|
384 | 426 | ireq->ir_loc_addr, th->source, th->dest, sk->sk_uid); |
---|
385 | | - security_req_classify_flow(req, flowi4_to_flowi(&fl4)); |
---|
| 427 | + security_req_classify_flow(req, flowi4_to_flowi_common(&fl4)); |
---|
386 | 428 | rt = ip_route_output_key(sock_net(sk), &fl4); |
---|
387 | 429 | if (IS_ERR(rt)) { |
---|
388 | 430 | reqsk_free(req); |
---|