Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'clean-up-and-refactor-cookie_v46_check'

Kuniyuki Iwashima says:

====================
tcp: Clean up and refactor cookie_v[46]_check().

This is a preparation series for upcoming arbitrary SYN Cookie
support with BPF. [0]

There are slight differences between cookie_v[46]_check(). Such a
discrepancy caused an issue in the past, and BPF SYN Cookie support
will add more churn.

The primary purpose of this series is to clean up and refactor
cookie_v[46]_check() to minimise such discrepancies and make the
BPF series easier to review.

[0]: https://lore.kernel.org/netdev/20231121184245.69569-1-kuniyu@amazon.com/
v2: https://lore.kernel.org/netdev/20231125011638.72056-1-kuniyu@amazon.com/
v1: https://lore.kernel.org/netdev/20231123012521.62841-1-kuniyu@amazon.com/
====================

Link: https://lore.kernel.org/r/20231129022924.96156-1-kuniyu@amazon.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+204 -202
+4 -4
include/linux/netfilter_ipv6.h
··· 51 51 u32 (*cookie_init_sequence)(const struct ipv6hdr *iph, 52 52 const struct tcphdr *th, u16 *mssp); 53 53 int (*cookie_v6_check)(const struct ipv6hdr *iph, 54 - const struct tcphdr *th, __u32 cookie); 54 + const struct tcphdr *th); 55 55 #endif 56 56 void (*route_input)(struct sk_buff *skb); 57 57 int (*fragment)(struct net *net, struct sock *sk, struct sk_buff *skb, ··· 179 179 } 180 180 181 181 static inline int nf_cookie_v6_check(const struct ipv6hdr *iph, 182 - const struct tcphdr *th, __u32 cookie) 182 + const struct tcphdr *th) 183 183 { 184 184 #if IS_ENABLED(CONFIG_SYN_COOKIES) 185 185 #if IS_MODULE(CONFIG_IPV6) 186 186 const struct nf_ipv6_ops *v6_ops = nf_get_ipv6_ops(); 187 187 188 188 if (v6_ops) 189 - return v6_ops->cookie_v6_check(iph, th, cookie); 189 + return v6_ops->cookie_v6_check(iph, th); 190 190 #elif IS_BUILTIN(CONFIG_IPV6) 191 - return __cookie_v6_check(iph, th, cookie); 191 + return __cookie_v6_check(iph, th); 192 192 #endif 193 193 #endif 194 194 return 0;
+13 -9
include/net/tcp.h
··· 490 490 /* From syncookies.c */ 491 491 struct sock *tcp_get_cookie_sock(struct sock *sk, struct sk_buff *skb, 492 492 struct request_sock *req, 493 - struct dst_entry *dst, u32 tsoff); 494 - int __cookie_v4_check(const struct iphdr *iph, const struct tcphdr *th, 495 - u32 cookie); 493 + struct dst_entry *dst); 494 + int __cookie_v4_check(const struct iphdr *iph, const struct tcphdr *th); 496 495 struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb); 497 496 struct request_sock *cookie_tcp_reqsk_alloc(const struct request_sock_ops *ops, 498 - const struct tcp_request_sock_ops *af_ops, 499 - struct sock *sk, struct sk_buff *skb); 497 + struct sock *sk, struct sk_buff *skb, 498 + struct tcp_options_received *tcp_opt, 499 + int mss, u32 tsoff); 500 + 500 501 #ifdef CONFIG_SYN_COOKIES 501 502 502 503 /* Syncookies use a monotonic timer which increments every 60 seconds. ··· 583 582 u64 cookie_init_timestamp(struct request_sock *req, u64 now); 584 583 bool cookie_timestamp_decode(const struct net *net, 585 584 struct tcp_options_received *opt); 586 - bool cookie_ecn_ok(const struct tcp_options_received *opt, 587 - const struct net *net, const struct dst_entry *dst); 585 + 586 + static inline bool cookie_ecn_ok(const struct net *net, const struct dst_entry *dst) 587 + { 588 + return READ_ONCE(net->ipv4.sysctl_tcp_ecn) || 589 + dst_feature(dst, RTAX_FEATURE_ECN); 590 + } 588 591 589 592 /* From net/ipv6/syncookies.c */ 590 - int __cookie_v6_check(const struct ipv6hdr *iph, const struct tcphdr *th, 591 - u32 cookie); 593 + int __cookie_v6_check(const struct ipv6hdr *iph, const struct tcphdr *th); 592 594 struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb); 593 595 594 596 u32 __cookie_v6_init_sequence(const struct ipv6hdr *iph,
+2 -4
include/net/tcp_ao.h
··· 265 265 void tcp_ao_finish_connect(struct sock *sk, struct sk_buff *skb); 266 266 void tcp_ao_connect_init(struct sock *sk); 267 267 void tcp_ao_syncookie(struct sock *sk, const struct sk_buff *skb, 268 - struct tcp_request_sock *treq, 269 - unsigned short int family, int l3index); 268 + struct request_sock *req, unsigned short int family); 270 269 #else /* CONFIG_TCP_AO */ 271 270 272 271 static inline int tcp_ao_transmit_skb(struct sock *sk, struct sk_buff *skb, ··· 276 277 } 277 278 278 279 static inline void tcp_ao_syncookie(struct sock *sk, const struct sk_buff *skb, 279 - struct tcp_request_sock *treq, 280 - unsigned short int family, int l3index) 280 + struct request_sock *req, unsigned short int family) 281 281 { 282 282 } 283 283
+4 -11
net/core/filter.c
··· 7238 7238 struct tcphdr *, th, u32, th_len) 7239 7239 { 7240 7240 #ifdef CONFIG_SYN_COOKIES 7241 - u32 cookie; 7242 7241 int ret; 7243 7242 7244 7243 if (unlikely(!sk || th_len < sizeof(*th))) ··· 7259 7260 if (tcp_synq_no_recent_overflow(sk)) 7260 7261 return -ENOENT; 7261 7262 7262 - cookie = ntohl(th->ack_seq) - 1; 7263 - 7264 7263 /* Both struct iphdr and struct ipv6hdr have the version field at the 7265 7264 * same offset so we can cast to the shorter header (struct iphdr). 7266 7265 */ ··· 7267 7270 if (sk->sk_family == AF_INET6 && ipv6_only_sock(sk)) 7268 7271 return -EINVAL; 7269 7272 7270 - ret = __cookie_v4_check((struct iphdr *)iph, th, cookie); 7273 + ret = __cookie_v4_check((struct iphdr *)iph, th); 7271 7274 break; 7272 7275 7273 7276 #if IS_BUILTIN(CONFIG_IPV6) ··· 7278 7281 if (sk->sk_family != AF_INET6) 7279 7282 return -EINVAL; 7280 7283 7281 - ret = __cookie_v6_check((struct ipv6hdr *)iph, th, cookie); 7284 + ret = __cookie_v6_check((struct ipv6hdr *)iph, th); 7282 7285 break; 7283 7286 #endif /* CONFIG_IPV6 */ 7284 7287 ··· 7731 7734 BPF_CALL_2(bpf_tcp_raw_check_syncookie_ipv4, struct iphdr *, iph, 7732 7735 struct tcphdr *, th) 7733 7736 { 7734 - u32 cookie = ntohl(th->ack_seq) - 1; 7735 - 7736 - if (__cookie_v4_check(iph, th, cookie) > 0) 7737 + if (__cookie_v4_check(iph, th) > 0) 7737 7738 return 0; 7738 7739 7739 7740 return -EACCES; ··· 7752 7757 struct tcphdr *, th) 7753 7758 { 7754 7759 #if IS_BUILTIN(CONFIG_IPV6) 7755 - u32 cookie = ntohl(th->ack_seq) - 1; 7756 - 7757 - if (__cookie_v6_check(iph, th, cookie) > 0) 7760 + if (__cookie_v6_check(iph, th) > 0) 7758 7761 return 0; 7759 7762 7760 7763 return -EACCES;
+117 -110
net/ipv4/syncookies.c
··· 189 189 * Check if a ack sequence number is a valid syncookie. 190 190 * Return the decoded mss if it is, or 0 if not. 191 191 */ 192 - int __cookie_v4_check(const struct iphdr *iph, const struct tcphdr *th, 193 - u32 cookie) 192 + int __cookie_v4_check(const struct iphdr *iph, const struct tcphdr *th) 194 193 { 194 + __u32 cookie = ntohl(th->ack_seq) - 1; 195 195 __u32 seq = ntohl(th->seq) - 1; 196 - __u32 mssind = check_tcp_syn_cookie(cookie, iph->saddr, iph->daddr, 197 - th->source, th->dest, seq); 196 + __u32 mssind; 197 + 198 + mssind = check_tcp_syn_cookie(cookie, iph->saddr, iph->daddr, 199 + th->source, th->dest, seq); 198 200 199 201 return mssind < ARRAY_SIZE(msstab) ? msstab[mssind] : 0; 200 202 } ··· 204 202 205 203 struct sock *tcp_get_cookie_sock(struct sock *sk, struct sk_buff *skb, 206 204 struct request_sock *req, 207 - struct dst_entry *dst, u32 tsoff) 205 + struct dst_entry *dst) 208 206 { 209 207 struct inet_connection_sock *icsk = inet_csk(sk); 210 208 struct sock *child; ··· 214 212 NULL, &own_req); 215 213 if (child) { 216 214 refcount_set(&req->rsk_refcnt, 1); 217 - tcp_sk(child)->tsoffset = tsoff; 218 215 sock_rps_save_rxhash(child, skb); 219 216 220 217 if (rsk_drop_req(req)) { ··· 270 269 } 271 270 EXPORT_SYMBOL(cookie_timestamp_decode); 272 271 273 - bool cookie_ecn_ok(const struct tcp_options_received *tcp_opt, 274 - const struct net *net, const struct dst_entry *dst) 272 + static int cookie_tcp_reqsk_init(struct sock *sk, struct sk_buff *skb, 273 + struct request_sock *req) 275 274 { 276 - bool ecn_ok = tcp_opt->rcv_tsecr & TS_OPT_ECN; 275 + struct inet_request_sock *ireq = inet_rsk(req); 276 + struct tcp_request_sock *treq = tcp_rsk(req); 277 + const struct tcphdr *th = tcp_hdr(skb); 277 278 278 - if (!ecn_ok) 279 - return false; 279 + req->num_retrans = 0; 280 280 281 - if (READ_ONCE(net->ipv4.sysctl_tcp_ecn)) 282 - return true; 281 + ireq->ir_num = ntohs(th->dest); 282 + ireq->ir_rmt_port = th->source; 283 + ireq->ir_iif = inet_request_bound_dev_if(sk, skb); 284 + ireq->ir_mark = inet_request_mark(sk, skb); 283 285 284 - return dst_feature(dst, RTAX_FEATURE_ECN); 286 + if (IS_ENABLED(CONFIG_SMC)) 287 + ireq->smc_ok = 0; 288 + 289 + treq->snt_synack = 0; 290 + treq->tfo_listener = false; 291 + treq->txhash = net_tx_rndhash(); 292 + treq->rcv_isn = ntohl(th->seq) - 1; 293 + treq->snt_isn = ntohl(th->ack_seq) - 1; 294 + treq->syn_tos = TCP_SKB_CB(skb)->ip_dsfield; 295 + treq->req_usec_ts = false; 296 + 297 + #if IS_ENABLED(CONFIG_MPTCP) 298 + treq->is_mptcp = sk_is_mptcp(sk); 299 + if (treq->is_mptcp) 300 + return mptcp_subflow_init_cookie_req(req, sk, skb); 301 + #endif 302 + 303 + return 0; 285 304 } 286 - EXPORT_SYMBOL(cookie_ecn_ok); 287 305 288 306 struct request_sock *cookie_tcp_reqsk_alloc(const struct request_sock_ops *ops, 289 - const struct tcp_request_sock_ops *af_ops, 290 - struct sock *sk, 291 - struct sk_buff *skb) 307 + struct sock *sk, struct sk_buff *skb, 308 + struct tcp_options_received *tcp_opt, 309 + int mss, u32 tsoff) 292 310 { 311 + struct inet_request_sock *ireq; 293 312 struct tcp_request_sock *treq; 294 313 struct request_sock *req; 295 314 ··· 321 300 if (!req) 322 301 return NULL; 323 302 303 + if (cookie_tcp_reqsk_init(sk, skb, req)) { 304 + reqsk_free(req); 305 + return NULL; 306 + } 307 + 308 + ireq = inet_rsk(req); 324 309 treq = tcp_rsk(req); 325 310 326 - /* treq->af_specific might be used to perform TCP_MD5 lookup */ 327 - treq->af_specific = af_ops; 311 + req->mss = mss; 312 + req->ts_recent = tcp_opt->saw_tstamp ? tcp_opt->rcv_tsval : 0; 328 313 329 - treq->syn_tos = TCP_SKB_CB(skb)->ip_dsfield; 330 - treq->req_usec_ts = false; 314 + ireq->snd_wscale = tcp_opt->snd_wscale; 315 + ireq->tstamp_ok = tcp_opt->saw_tstamp; 316 + ireq->sack_ok = tcp_opt->sack_ok; 317 + ireq->wscale_ok = tcp_opt->wscale_ok; 318 + ireq->ecn_ok = !!(tcp_opt->rcv_tsecr & TS_OPT_ECN); 331 319 332 - #if IS_ENABLED(CONFIG_MPTCP) 333 - treq->is_mptcp = sk_is_mptcp(sk); 334 - if (treq->is_mptcp) { 335 - int err = mptcp_subflow_init_cookie_req(req, sk, skb); 336 - 337 - if (err) { 338 - reqsk_free(req); 339 - return NULL; 340 - } 341 - } 342 - #endif 320 + treq->ts_off = tsoff; 343 321 344 322 return req; 345 323 } 346 324 EXPORT_SYMBOL_GPL(cookie_tcp_reqsk_alloc); 325 + 326 + static struct request_sock *cookie_tcp_check(struct net *net, struct sock *sk, 327 + struct sk_buff *skb) 328 + { 329 + struct tcp_options_received tcp_opt; 330 + u32 tsoff = 0; 331 + int mss; 332 + 333 + if (tcp_synq_no_recent_overflow(sk)) 334 + goto out; 335 + 336 + mss = __cookie_v4_check(ip_hdr(skb), tcp_hdr(skb)); 337 + if (!mss) { 338 + __NET_INC_STATS(net, LINUX_MIB_SYNCOOKIESFAILED); 339 + goto out; 340 + } 341 + 342 + __NET_INC_STATS(net, LINUX_MIB_SYNCOOKIESRECV); 343 + 344 + /* check for timestamp cookie support */ 345 + memset(&tcp_opt, 0, sizeof(tcp_opt)); 346 + tcp_parse_options(net, skb, &tcp_opt, 0, NULL); 347 + 348 + if (tcp_opt.saw_tstamp && tcp_opt.rcv_tsecr) { 349 + tsoff = secure_tcp_ts_off(net, 350 + ip_hdr(skb)->daddr, 351 + ip_hdr(skb)->saddr); 352 + tcp_opt.rcv_tsecr -= tsoff; 353 + } 354 + 355 + if (!cookie_timestamp_decode(net, &tcp_opt)) 356 + goto out; 357 + 358 + return cookie_tcp_reqsk_alloc(&tcp_request_sock_ops, sk, skb, 359 + &tcp_opt, mss, tsoff); 360 + out: 361 + return ERR_PTR(-EINVAL); 362 + } 347 363 348 364 /* On input, sk is a listener. 349 365 * Output is listener if incoming packet would not create a child ··· 389 331 struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb) 390 332 { 391 333 struct ip_options *opt = &TCP_SKB_CB(skb)->header.h4.opt; 392 - struct tcp_options_received tcp_opt; 393 - struct inet_request_sock *ireq; 394 - struct tcp_request_sock *treq; 395 - struct tcp_sock *tp = tcp_sk(sk); 396 334 const struct tcphdr *th = tcp_hdr(skb); 397 - __u32 cookie = ntohl(th->ack_seq) - 1; 398 - struct sock *ret = sk; 335 + struct tcp_sock *tp = tcp_sk(sk); 336 + struct inet_request_sock *ireq; 337 + struct net *net = sock_net(sk); 399 338 struct request_sock *req; 400 - int full_space, mss; 339 + struct sock *ret = sk; 340 + struct flowi4 fl4; 401 341 struct rtable *rt; 402 342 __u8 rcv_wscale; 403 - struct flowi4 fl4; 404 - u32 tsoff = 0; 405 - int l3index; 343 + int full_space; 406 344 407 - if (!READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_syncookies) || 345 + if (!READ_ONCE(net->ipv4.sysctl_tcp_syncookies) || 408 346 !th->ack || th->rst) 409 347 goto out; 410 348 411 - if (tcp_synq_no_recent_overflow(sk)) 349 + req = cookie_tcp_check(net, sk, skb); 350 + if (IS_ERR(req)) 412 351 goto out; 413 - 414 - mss = __cookie_v4_check(ip_hdr(skb), th, cookie); 415 - if (mss == 0) { 416 - __NET_INC_STATS(sock_net(sk), LINUX_MIB_SYNCOOKIESFAILED); 417 - goto out; 418 - } 419 - 420 - __NET_INC_STATS(sock_net(sk), LINUX_MIB_SYNCOOKIESRECV); 421 - 422 - /* check for timestamp cookie support */ 423 - memset(&tcp_opt, 0, sizeof(tcp_opt)); 424 - tcp_parse_options(sock_net(sk), skb, &tcp_opt, 0, NULL); 425 - 426 - if (tcp_opt.saw_tstamp && tcp_opt.rcv_tsecr) { 427 - tsoff = secure_tcp_ts_off(sock_net(sk), 428 - ip_hdr(skb)->daddr, 429 - ip_hdr(skb)->saddr); 430 - tcp_opt.rcv_tsecr -= tsoff; 431 - } 432 - 433 - if (!cookie_timestamp_decode(sock_net(sk), &tcp_opt)) 434 - goto out; 435 - 436 - ret = NULL; 437 - req = cookie_tcp_reqsk_alloc(&tcp_request_sock_ops, 438 - &tcp_request_sock_ipv4_ops, sk, skb); 439 352 if (!req) 440 - goto out; 353 + goto out_drop; 441 354 442 355 ireq = inet_rsk(req); 443 - treq = tcp_rsk(req); 444 - treq->rcv_isn = ntohl(th->seq) - 1; 445 - treq->snt_isn = cookie; 446 - treq->ts_off = 0; 447 - treq->txhash = net_tx_rndhash(); 448 - req->mss = mss; 449 - ireq->ir_num = ntohs(th->dest); 450 - ireq->ir_rmt_port = th->source; 356 + 451 357 sk_rcv_saddr_set(req_to_sk(req), ip_hdr(skb)->daddr); 452 358 sk_daddr_set(req_to_sk(req), ip_hdr(skb)->saddr); 453 - ireq->ir_mark = inet_request_mark(sk, skb); 454 - ireq->snd_wscale = tcp_opt.snd_wscale; 455 - ireq->sack_ok = tcp_opt.sack_ok; 456 - ireq->wscale_ok = tcp_opt.wscale_ok; 457 - ireq->tstamp_ok = tcp_opt.saw_tstamp; 458 - req->ts_recent = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsval : 0; 459 - treq->snt_synack = 0; 460 - treq->tfo_listener = false; 461 - 462 - if (IS_ENABLED(CONFIG_SMC)) 463 - ireq->smc_ok = 0; 464 - 465 - ireq->ir_iif = inet_request_bound_dev_if(sk, skb); 466 - 467 - l3index = l3mdev_master_ifindex_by_index(sock_net(sk), ireq->ir_iif); 468 - tcp_ao_syncookie(sk, skb, treq, AF_INET, l3index); 469 359 470 360 /* We throwed the options of the initial SYN away, so we hope 471 361 * the ACK carries the same options again (see RFC1122 4.2.3.8) 472 362 */ 473 - RCU_INIT_POINTER(ireq->ireq_opt, tcp_v4_save_options(sock_net(sk), skb)); 363 + RCU_INIT_POINTER(ireq->ireq_opt, tcp_v4_save_options(net, skb)); 474 364 475 - if (security_inet_conn_request(sk, skb, req)) { 476 - reqsk_free(req); 477 - goto out; 478 - } 365 + if (security_inet_conn_request(sk, skb, req)) 366 + goto out_free; 479 367 480 - req->num_retrans = 0; 368 + tcp_ao_syncookie(sk, skb, req, AF_INET); 481 369 482 370 /* 483 371 * We need to lookup the route here to get at the correct ··· 437 433 opt->srr ? opt->faddr : ireq->ir_rmt_addr, 438 434 ireq->ir_loc_addr, th->source, th->dest, sk->sk_uid); 439 435 security_req_classify_flow(req, flowi4_to_flowi_common(&fl4)); 440 - rt = ip_route_output_key(sock_net(sk), &fl4); 441 - if (IS_ERR(rt)) { 442 - reqsk_free(req); 443 - goto out; 444 - } 436 + rt = ip_route_output_key(net, &fl4); 437 + if (IS_ERR(rt)) 438 + goto out_free; 445 439 446 440 /* Try to redo what tcp_v4_send_synack did. */ 447 441 req->rsk_window_clamp = tp->window_clamp ? :dst_metric(&rt->dst, RTAX_WINDOW); ··· 455 453 dst_metric(&rt->dst, RTAX_INITRWND)); 456 454 457 455 ireq->rcv_wscale = rcv_wscale; 458 - ireq->ecn_ok = cookie_ecn_ok(&tcp_opt, sock_net(sk), &rt->dst); 456 + ireq->ecn_ok &= cookie_ecn_ok(net, &rt->dst); 459 457 460 - ret = tcp_get_cookie_sock(sk, skb, req, &rt->dst, tsoff); 458 + ret = tcp_get_cookie_sock(sk, skb, req, &rt->dst); 461 459 /* ip_queue_xmit() depends on our flow being setup 462 460 * Normal sockets get it right from inet_csk_route_child_sock() 463 461 */ 464 462 if (ret) 465 463 inet_sk(ret)->cork.fl.u.ip4 = fl4; 466 - out: return ret; 464 + out: 465 + return ret; 466 + out_free: 467 + reqsk_free(req); 468 + out_drop: 469 + return NULL; 467 470 }
+14 -2
net/ipv4/tcp_ao.c
··· 844 844 } 845 845 846 846 void tcp_ao_syncookie(struct sock *sk, const struct sk_buff *skb, 847 - struct tcp_request_sock *treq, 848 - unsigned short int family, int l3index) 847 + struct request_sock *req, unsigned short int family) 849 848 { 849 + struct tcp_request_sock *treq = tcp_rsk(req); 850 850 const struct tcphdr *th = tcp_hdr(skb); 851 851 const struct tcp_ao_hdr *aoh; 852 852 struct tcp_ao_key *key; 853 + int l3index; 854 + 855 + /* treq->af_specific is used to perform TCP_AO lookup 856 + * in tcp_create_openreq_child(). 857 + */ 858 + #if IS_ENABLED(CONFIG_IPV6) 859 + if (family == AF_INET6) 860 + treq->af_specific = &tcp_request_sock_ipv6_ops; 861 + else 862 + #endif 863 + treq->af_specific = &tcp_request_sock_ipv4_ops; 853 864 854 865 treq->maclen = 0; 855 866 856 867 if (tcp_parse_auth_options(th, NULL, &aoh) || !aoh) 857 868 return; 858 869 870 + l3index = l3mdev_master_ifindex_by_index(sock_net(sk), inet_rsk(req)->ir_iif); 859 871 key = tcp_ao_inbound_lookup(family, sk, skb, -1, aoh->keyid, l3index); 860 872 if (!key) 861 873 /* Key not found, continue without TCP-AO */
+48 -60
net/ipv6/syncookies.c
··· 114 114 return __cookie_v6_init_sequence(iph, th, mssp); 115 115 } 116 116 117 - int __cookie_v6_check(const struct ipv6hdr *iph, const struct tcphdr *th, 118 - __u32 cookie) 117 + int __cookie_v6_check(const struct ipv6hdr *iph, const struct tcphdr *th) 119 118 { 119 + __u32 cookie = ntohl(th->ack_seq) - 1; 120 120 __u32 seq = ntohl(th->seq) - 1; 121 - __u32 mssind = check_tcp_syn_cookie(cookie, &iph->saddr, &iph->daddr, 122 - th->source, th->dest, seq); 121 + __u32 mssind; 122 + 123 + mssind = check_tcp_syn_cookie(cookie, &iph->saddr, &iph->daddr, 124 + th->source, th->dest, seq); 123 125 124 126 return mssind < ARRAY_SIZE(msstab) ? msstab[mssind] : 0; 125 127 } 126 128 EXPORT_SYMBOL_GPL(__cookie_v6_check); 127 129 128 - struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) 130 + static struct request_sock *cookie_tcp_check(struct net *net, struct sock *sk, 131 + struct sk_buff *skb) 129 132 { 130 133 struct tcp_options_received tcp_opt; 131 - struct inet_request_sock *ireq; 132 - struct tcp_request_sock *treq; 133 - struct ipv6_pinfo *np = inet6_sk(sk); 134 - struct tcp_sock *tp = tcp_sk(sk); 135 - const struct tcphdr *th = tcp_hdr(skb); 136 - __u32 cookie = ntohl(th->ack_seq) - 1; 137 - struct sock *ret = sk; 138 - struct request_sock *req; 139 - int full_space, mss; 140 - struct dst_entry *dst; 141 - __u8 rcv_wscale; 142 134 u32 tsoff = 0; 143 - int l3index; 144 - 145 - if (!READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_syncookies) || 146 - !th->ack || th->rst) 147 - goto out; 135 + int mss; 148 136 149 137 if (tcp_synq_no_recent_overflow(sk)) 150 138 goto out; 151 139 152 - mss = __cookie_v6_check(ipv6_hdr(skb), th, cookie); 153 - if (mss == 0) { 154 - __NET_INC_STATS(sock_net(sk), LINUX_MIB_SYNCOOKIESFAILED); 140 + mss = __cookie_v6_check(ipv6_hdr(skb), tcp_hdr(skb)); 141 + if (!mss) { 142 + __NET_INC_STATS(net, LINUX_MIB_SYNCOOKIESFAILED); 155 143 goto out; 156 144 } 157 145 158 - __NET_INC_STATS(sock_net(sk), LINUX_MIB_SYNCOOKIESRECV); 146 + __NET_INC_STATS(net, LINUX_MIB_SYNCOOKIESRECV); 159 147 160 148 /* check for timestamp cookie support */ 161 149 memset(&tcp_opt, 0, sizeof(tcp_opt)); 162 - tcp_parse_options(sock_net(sk), skb, &tcp_opt, 0, NULL); 150 + tcp_parse_options(net, skb, &tcp_opt, 0, NULL); 163 151 164 152 if (tcp_opt.saw_tstamp && tcp_opt.rcv_tsecr) { 165 - tsoff = secure_tcpv6_ts_off(sock_net(sk), 153 + tsoff = secure_tcpv6_ts_off(net, 166 154 ipv6_hdr(skb)->daddr.s6_addr32, 167 155 ipv6_hdr(skb)->saddr.s6_addr32); 168 156 tcp_opt.rcv_tsecr -= tsoff; 169 157 } 170 158 171 - if (!cookie_timestamp_decode(sock_net(sk), &tcp_opt)) 159 + if (!cookie_timestamp_decode(net, &tcp_opt)) 172 160 goto out; 173 161 174 - ret = NULL; 175 - req = cookie_tcp_reqsk_alloc(&tcp6_request_sock_ops, 176 - &tcp_request_sock_ipv6_ops, sk, skb); 177 - if (!req) 162 + return cookie_tcp_reqsk_alloc(&tcp6_request_sock_ops, sk, skb, 163 + &tcp_opt, mss, tsoff); 164 + out: 165 + return ERR_PTR(-EINVAL); 166 + } 167 + 168 + struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) 169 + { 170 + const struct tcphdr *th = tcp_hdr(skb); 171 + struct ipv6_pinfo *np = inet6_sk(sk); 172 + struct tcp_sock *tp = tcp_sk(sk); 173 + struct inet_request_sock *ireq; 174 + struct net *net = sock_net(sk); 175 + struct request_sock *req; 176 + struct dst_entry *dst; 177 + struct sock *ret = sk; 178 + __u8 rcv_wscale; 179 + int full_space; 180 + 181 + if (!READ_ONCE(net->ipv4.sysctl_tcp_syncookies) || 182 + !th->ack || th->rst) 178 183 goto out; 184 + 185 + req = cookie_tcp_check(net, sk, skb); 186 + if (IS_ERR(req)) 187 + goto out; 188 + if (!req) 189 + goto out_drop; 179 190 180 191 ireq = inet_rsk(req); 181 - treq = tcp_rsk(req); 182 - treq->tfo_listener = false; 183 192 184 - req->mss = mss; 185 - ireq->ir_rmt_port = th->source; 186 - ireq->ir_num = ntohs(th->dest); 187 193 ireq->ir_v6_rmt_addr = ipv6_hdr(skb)->saddr; 188 194 ireq->ir_v6_loc_addr = ipv6_hdr(skb)->daddr; 189 195 ··· 203 197 ireq->pktopts = skb; 204 198 } 205 199 206 - ireq->ir_iif = inet_request_bound_dev_if(sk, skb); 207 200 /* So that link locals have meaning */ 208 201 if (!sk->sk_bound_dev_if && 209 202 ipv6_addr_type(&ireq->ir_v6_rmt_addr) & IPV6_ADDR_LINKLOCAL) 210 203 ireq->ir_iif = tcp_v6_iif(skb); 211 204 212 - ireq->ir_mark = inet_request_mark(sk, skb); 213 - 214 - req->num_retrans = 0; 215 - ireq->snd_wscale = tcp_opt.snd_wscale; 216 - ireq->sack_ok = tcp_opt.sack_ok; 217 - ireq->wscale_ok = tcp_opt.wscale_ok; 218 - ireq->tstamp_ok = tcp_opt.saw_tstamp; 219 - req->ts_recent = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsval : 0; 220 - treq->snt_synack = 0; 221 - treq->rcv_isn = ntohl(th->seq) - 1; 222 - treq->snt_isn = cookie; 223 - treq->ts_off = 0; 224 - treq->txhash = net_tx_rndhash(); 225 - 226 - l3index = l3mdev_master_ifindex_by_index(sock_net(sk), ireq->ir_iif); 227 - tcp_ao_syncookie(sk, skb, treq, AF_INET6, l3index); 228 - 229 - if (IS_ENABLED(CONFIG_SMC)) 230 - ireq->smc_ok = 0; 205 + tcp_ao_syncookie(sk, skb, req, AF_INET6); 231 206 232 207 /* 233 208 * We need to lookup the dst_entry to get the correct window size. ··· 230 243 fl6.flowi6_uid = sk->sk_uid; 231 244 security_req_classify_flow(req, flowi6_to_flowi_common(&fl6)); 232 245 233 - dst = ip6_dst_lookup_flow(sock_net(sk), sk, &fl6, final_p); 246 + dst = ip6_dst_lookup_flow(net, sk, &fl6, final_p); 234 247 if (IS_ERR(dst)) 235 248 goto out_free; 236 249 } ··· 248 261 dst_metric(dst, RTAX_INITRWND)); 249 262 250 263 ireq->rcv_wscale = rcv_wscale; 251 - ireq->ecn_ok = cookie_ecn_ok(&tcp_opt, sock_net(sk), dst); 264 + ireq->ecn_ok &= cookie_ecn_ok(net, dst); 252 265 253 - ret = tcp_get_cookie_sock(sk, skb, req, dst, tsoff); 266 + ret = tcp_get_cookie_sock(sk, skb, req, dst); 254 267 out: 255 268 return ret; 256 269 out_free: 257 270 reqsk_free(req); 271 + out_drop: 258 272 return NULL; 259 273 }
+2 -2
net/netfilter/nf_synproxy_core.c
··· 617 617 struct synproxy_net *snet = synproxy_pernet(net); 618 618 int mss; 619 619 620 - mss = __cookie_v4_check(ip_hdr(skb), th, ntohl(th->ack_seq) - 1); 620 + mss = __cookie_v4_check(ip_hdr(skb), th); 621 621 if (mss == 0) { 622 622 this_cpu_inc(snet->stats->cookie_invalid); 623 623 return false; ··· 1034 1034 struct synproxy_net *snet = synproxy_pernet(net); 1035 1035 int mss; 1036 1036 1037 - mss = nf_cookie_v6_check(ipv6_hdr(skb), th, ntohl(th->ack_seq) - 1); 1037 + mss = nf_cookie_v6_check(ipv6_hdr(skb), th); 1038 1038 if (mss == 0) { 1039 1039 this_cpu_inc(snet->stats->cookie_invalid); 1040 1040 return false;