LCOV - code coverage report
Current view: top level - net/ipv4 - syncookies.c (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_real_modules_combined.info Lines: 0 126 0.0 %
Date: 2020-09-30 20:25:40 Functions: 0 11 0.0 %
Branches: 0 66 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-or-later
       2                 :            : /*
       3                 :            :  *  Syncookies implementation for the Linux kernel
       4                 :            :  *
       5                 :            :  *  Copyright (C) 1997 Andi Kleen
       6                 :            :  *  Based on ideas by D.J.Bernstein and Eric Schenk.
       7                 :            :  */
       8                 :            : 
       9                 :            : #include <linux/tcp.h>
      10                 :            : #include <linux/slab.h>
      11                 :            : #include <linux/random.h>
      12                 :            : #include <linux/siphash.h>
      13                 :            : #include <linux/kernel.h>
      14                 :            : #include <linux/export.h>
      15                 :            : #include <net/secure_seq.h>
      16                 :            : #include <net/tcp.h>
      17                 :            : #include <net/route.h>
      18                 :            : 
      19                 :            : static siphash_key_t syncookie_secret[2] __read_mostly;
      20                 :            : 
      21                 :            : #define COOKIEBITS 24   /* Upper bits store count */
      22                 :            : #define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1)
      23                 :            : 
      24                 :            : /* TCP Timestamp: 6 lowest bits of timestamp sent in the cookie SYN-ACK
      25                 :            :  * stores TCP options:
      26                 :            :  *
      27                 :            :  * MSB                               LSB
      28                 :            :  * | 31 ...   6 |  5  |  4   | 3 2 1 0 |
      29                 :            :  * |  Timestamp | ECN | SACK | WScale  |
      30                 :            :  *
      31                 :            :  * When we receive a valid cookie-ACK, we look at the echoed tsval (if
      32                 :            :  * any) to figure out which TCP options we should use for the rebuilt
      33                 :            :  * connection.
      34                 :            :  *
      35                 :            :  * A WScale setting of '0xf' (which is an invalid scaling value)
      36                 :            :  * means that original syn did not include the TCP window scaling option.
      37                 :            :  */
      38                 :            : #define TS_OPT_WSCALE_MASK      0xf
      39                 :            : #define TS_OPT_SACK             BIT(4)
      40                 :            : #define TS_OPT_ECN              BIT(5)
      41                 :            : /* There is no TS_OPT_TIMESTAMP:
      42                 :            :  * if ACK contains timestamp option, we already know it was
      43                 :            :  * requested/supported by the syn/synack exchange.
      44                 :            :  */
      45                 :            : #define TSBITS  6
      46                 :            : #define TSMASK  (((__u32)1 << TSBITS) - 1)
      47                 :            : 
      48                 :          0 : static u32 cookie_hash(__be32 saddr, __be32 daddr, __be16 sport, __be16 dport,
      49                 :            :                        u32 count, int c)
      50                 :            : {
      51   [ #  #  #  # ]:          0 :         net_get_random_once(syncookie_secret, sizeof(syncookie_secret));
      52                 :          0 :         return siphash_4u32((__force u32)saddr, (__force u32)daddr,
      53                 :          0 :                             (__force u32)sport << 16 | (__force u32)dport,
      54                 :          0 :                             count, &syncookie_secret[c]);
      55                 :            : }
      56                 :            : 
      57                 :            : 
      58                 :            : /*
      59                 :            :  * when syncookies are in effect and tcp timestamps are enabled we encode
      60                 :            :  * tcp options in the lower bits of the timestamp value that will be
      61                 :            :  * sent in the syn-ack.
      62                 :            :  * Since subsequent timestamps use the normal tcp_time_stamp value, we
      63                 :            :  * must make sure that the resulting initial timestamp is <= tcp_time_stamp.
      64                 :            :  */
      65                 :          0 : u64 cookie_init_timestamp(struct request_sock *req)
      66                 :            : {
      67                 :            :         struct inet_request_sock *ireq;
      68                 :          0 :         u32 ts, ts_now = tcp_time_stamp_raw();
      69                 :            :         u32 options = 0;
      70                 :            : 
      71                 :            :         ireq = inet_rsk(req);
      72                 :            : 
      73         [ #  # ]:          0 :         options = ireq->wscale_ok ? ireq->snd_wscale : TS_OPT_WSCALE_MASK;
      74         [ #  # ]:          0 :         if (ireq->sack_ok)
      75                 :          0 :                 options |= TS_OPT_SACK;
      76         [ #  # ]:          0 :         if (ireq->ecn_ok)
      77                 :          0 :                 options |= TS_OPT_ECN;
      78                 :            : 
      79                 :          0 :         ts = ts_now & ~TSMASK;
      80                 :          0 :         ts |= options;
      81         [ #  # ]:          0 :         if (ts > ts_now) {
      82                 :          0 :                 ts >>= TSBITS;
      83                 :          0 :                 ts--;
      84                 :          0 :                 ts <<= TSBITS;
      85                 :          0 :                 ts |= options;
      86                 :            :         }
      87                 :          0 :         return (u64)ts * (NSEC_PER_SEC / TCP_TS_HZ);
      88                 :            : }
      89                 :            : 
      90                 :            : 
      91                 :          0 : static __u32 secure_tcp_syn_cookie(__be32 saddr, __be32 daddr, __be16 sport,
      92                 :            :                                    __be16 dport, __u32 sseq, __u32 data)
      93                 :            : {
      94                 :            :         /*
      95                 :            :          * Compute the secure sequence number.
      96                 :            :          * The output should be:
      97                 :            :          *   HASH(sec1,saddr,sport,daddr,dport,sec1) + sseq + (count * 2^24)
      98                 :            :          *      + (HASH(sec2,saddr,sport,daddr,dport,count,sec2) % 2^24).
      99                 :            :          * Where sseq is their sequence number and count increases every
     100                 :            :          * minute by 1.
     101                 :            :          * As an extra hack, we add a small "data" value that encodes the
     102                 :            :          * MSS into the second hash value.
     103                 :            :          */
     104                 :          0 :         u32 count = tcp_cookie_time();
     105                 :          0 :         return (cookie_hash(saddr, daddr, sport, dport, 0, 0) +
     106                 :          0 :                 sseq + (count << COOKIEBITS) +
     107                 :          0 :                 ((cookie_hash(saddr, daddr, sport, dport, count, 1) + data)
     108                 :          0 :                  & COOKIEMASK));
     109                 :            : }
     110                 :            : 
     111                 :            : /*
     112                 :            :  * This retrieves the small "data" value from the syncookie.
     113                 :            :  * If the syncookie is bad, the data returned will be out of
     114                 :            :  * range.  This must be checked by the caller.
     115                 :            :  *
     116                 :            :  * The count value used to generate the cookie must be less than
     117                 :            :  * MAX_SYNCOOKIE_AGE minutes in the past.
     118                 :            :  * The return value (__u32)-1 if this test fails.
     119                 :            :  */
     120                 :          0 : static __u32 check_tcp_syn_cookie(__u32 cookie, __be32 saddr, __be32 daddr,
     121                 :            :                                   __be16 sport, __be16 dport, __u32 sseq)
     122                 :            : {
     123                 :          0 :         u32 diff, count = tcp_cookie_time();
     124                 :            : 
     125                 :            :         /* Strip away the layers from the cookie */
     126                 :          0 :         cookie -= cookie_hash(saddr, daddr, sport, dport, 0, 0) + sseq;
     127                 :            : 
     128                 :            :         /* Cookie is now reduced to (count * 2^24) ^ (hash % 2^24) */
     129                 :          0 :         diff = (count - (cookie >> COOKIEBITS)) & ((__u32) -1 >> COOKIEBITS);
     130         [ #  # ]:          0 :         if (diff >= MAX_SYNCOOKIE_AGE)
     131                 :            :                 return (__u32)-1;
     132                 :            : 
     133                 :          0 :         return (cookie -
     134                 :          0 :                 cookie_hash(saddr, daddr, sport, dport, count - diff, 1))
     135                 :            :                 & COOKIEMASK;       /* Leaving the data behind */
     136                 :            : }
     137                 :            : 
     138                 :            : /*
     139                 :            :  * MSS Values are chosen based on the 2011 paper
     140                 :            :  * 'An Analysis of TCP Maximum Segement Sizes' by S. Alcock and R. Nelson.
     141                 :            :  * Values ..
     142                 :            :  *  .. lower than 536 are rare (< 0.2%)
     143                 :            :  *  .. between 537 and 1299 account for less than < 1.5% of observed values
     144                 :            :  *  .. in the 1300-1349 range account for about 15 to 20% of observed mss values
     145                 :            :  *  .. exceeding 1460 are very rare (< 0.04%)
     146                 :            :  *
     147                 :            :  *  1460 is the single most frequently announced mss value (30 to 46% depending
     148                 :            :  *  on monitor location).  Table must be sorted.
     149                 :            :  */
     150                 :            : static __u16 const msstab[] = {
     151                 :            :         536,
     152                 :            :         1300,
     153                 :            :         1440,   /* 1440, 1452: PPPoE */
     154                 :            :         1460,
     155                 :            : };
     156                 :            : 
     157                 :            : /*
     158                 :            :  * Generate a syncookie.  mssp points to the mss, which is returned
     159                 :            :  * rounded down to the value encoded in the cookie.
     160                 :            :  */
     161                 :          0 : u32 __cookie_v4_init_sequence(const struct iphdr *iph, const struct tcphdr *th,
     162                 :            :                               u16 *mssp)
     163                 :            : {
     164                 :            :         int mssind;
     165                 :          0 :         const __u16 mss = *mssp;
     166                 :            : 
     167         [ #  # ]:          0 :         for (mssind = ARRAY_SIZE(msstab) - 1; mssind ; mssind--)
     168         [ #  # ]:          0 :                 if (mss >= msstab[mssind])
     169                 :            :                         break;
     170                 :          0 :         *mssp = msstab[mssind];
     171                 :            : 
     172                 :          0 :         return secure_tcp_syn_cookie(iph->saddr, iph->daddr,
     173                 :            :                                      th->source, th->dest, ntohl(th->seq),
     174                 :            :                                      mssind);
     175                 :            : }
     176                 :            : EXPORT_SYMBOL_GPL(__cookie_v4_init_sequence);
     177                 :            : 
     178                 :          0 : __u32 cookie_v4_init_sequence(const struct sk_buff *skb, __u16 *mssp)
     179                 :            : {
     180                 :            :         const struct iphdr *iph = ip_hdr(skb);
     181                 :            :         const struct tcphdr *th = tcp_hdr(skb);
     182                 :            : 
     183                 :          0 :         return __cookie_v4_init_sequence(iph, th, mssp);
     184                 :            : }
     185                 :            : 
     186                 :            : /*
     187                 :            :  * Check if a ack sequence number is a valid syncookie.
     188                 :            :  * Return the decoded mss if it is, or 0 if not.
     189                 :            :  */
     190                 :          0 : int __cookie_v4_check(const struct iphdr *iph, const struct tcphdr *th,
     191                 :            :                       u32 cookie)
     192                 :            : {
     193                 :          0 :         __u32 seq = ntohl(th->seq) - 1;
     194                 :          0 :         __u32 mssind = check_tcp_syn_cookie(cookie, iph->saddr, iph->daddr,
     195                 :            :                                             th->source, th->dest, seq);
     196                 :            : 
     197         [ #  # ]:          0 :         return mssind < ARRAY_SIZE(msstab) ? msstab[mssind] : 0;
     198                 :            : }
     199                 :            : EXPORT_SYMBOL_GPL(__cookie_v4_check);
     200                 :            : 
     201                 :          0 : struct sock *tcp_get_cookie_sock(struct sock *sk, struct sk_buff *skb,
     202                 :            :                                  struct request_sock *req,
     203                 :            :                                  struct dst_entry *dst, u32 tsoff)
     204                 :            : {
     205                 :            :         struct inet_connection_sock *icsk = inet_csk(sk);
     206                 :            :         struct sock *child;
     207                 :            :         bool own_req;
     208                 :            : 
     209                 :          0 :         child = icsk->icsk_af_ops->syn_recv_sock(sk, skb, req, dst,
     210                 :            :                                                  NULL, &own_req);
     211         [ #  # ]:          0 :         if (child) {
     212                 :            :                 refcount_set(&req->rsk_refcnt, 1);
     213                 :          0 :                 tcp_sk(child)->tsoffset = tsoff;
     214                 :            :                 sock_rps_save_rxhash(child, skb);
     215         [ #  # ]:          0 :                 if (inet_csk_reqsk_queue_add(sk, req, child))
     216                 :            :                         return child;
     217                 :            : 
     218                 :            :                 bh_unlock_sock(child);
     219                 :          0 :                 sock_put(child);
     220                 :            :         }
     221                 :          0 :         __reqsk_free(req);
     222                 :            : 
     223                 :          0 :         return NULL;
     224                 :            : }
     225                 :            : EXPORT_SYMBOL(tcp_get_cookie_sock);
     226                 :            : 
     227                 :            : /*
     228                 :            :  * when syncookies are in effect and tcp timestamps are enabled we stored
     229                 :            :  * additional tcp options in the timestamp.
     230                 :            :  * This extracts these options from the timestamp echo.
     231                 :            :  *
     232                 :            :  * return false if we decode a tcp option that is disabled
     233                 :            :  * on the host.
     234                 :            :  */
     235                 :          0 : bool cookie_timestamp_decode(const struct net *net,
     236                 :            :                              struct tcp_options_received *tcp_opt)
     237                 :            : {
     238                 :            :         /* echoed timestamp, lowest bits contain options */
     239                 :          0 :         u32 options = tcp_opt->rcv_tsecr;
     240                 :            : 
     241         [ #  # ]:          0 :         if (!tcp_opt->saw_tstamp)  {
     242                 :            :                 tcp_clear_options(tcp_opt);
     243                 :          0 :                 return true;
     244                 :            :         }
     245                 :            : 
     246         [ #  # ]:          0 :         if (!net->ipv4.sysctl_tcp_timestamps)
     247                 :            :                 return false;
     248                 :            : 
     249                 :          0 :         tcp_opt->sack_ok = (options & TS_OPT_SACK) ? TCP_SACK_SEEN : 0;
     250                 :            : 
     251   [ #  #  #  # ]:          0 :         if (tcp_opt->sack_ok && !net->ipv4.sysctl_tcp_sack)
     252                 :            :                 return false;
     253                 :            : 
     254         [ #  # ]:          0 :         if ((options & TS_OPT_WSCALE_MASK) == TS_OPT_WSCALE_MASK)
     255                 :            :                 return true; /* no window scaling */
     256                 :            : 
     257                 :          0 :         tcp_opt->wscale_ok = 1;
     258                 :          0 :         tcp_opt->snd_wscale = options & TS_OPT_WSCALE_MASK;
     259                 :            : 
     260                 :          0 :         return net->ipv4.sysctl_tcp_window_scaling != 0;
     261                 :            : }
     262                 :            : EXPORT_SYMBOL(cookie_timestamp_decode);
     263                 :            : 
     264                 :          0 : bool cookie_ecn_ok(const struct tcp_options_received *tcp_opt,
     265                 :            :                    const struct net *net, const struct dst_entry *dst)
     266                 :            : {
     267                 :          0 :         bool ecn_ok = tcp_opt->rcv_tsecr & TS_OPT_ECN;
     268                 :            : 
     269         [ #  # ]:          0 :         if (!ecn_ok)
     270                 :            :                 return false;
     271                 :            : 
     272         [ #  # ]:          0 :         if (net->ipv4.sysctl_tcp_ecn)
     273                 :            :                 return true;
     274                 :            : 
     275                 :          0 :         return dst_feature(dst, RTAX_FEATURE_ECN);
     276                 :            : }
     277                 :            : EXPORT_SYMBOL(cookie_ecn_ok);
     278                 :            : 
     279                 :            : /* On input, sk is a listener.
     280                 :            :  * Output is listener if incoming packet would not create a child
     281                 :            :  *           NULL if memory could not be allocated.
     282                 :            :  */
     283                 :          0 : struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
     284                 :            : {
     285                 :            :         struct ip_options *opt = &TCP_SKB_CB(skb)->header.h4.opt;
     286                 :            :         struct tcp_options_received tcp_opt;
     287                 :            :         struct inet_request_sock *ireq;
     288                 :            :         struct tcp_request_sock *treq;
     289                 :            :         struct tcp_sock *tp = tcp_sk(sk);
     290                 :            :         const struct tcphdr *th = tcp_hdr(skb);
     291                 :          0 :         __u32 cookie = ntohl(th->ack_seq) - 1;
     292                 :            :         struct sock *ret = sk;
     293                 :            :         struct request_sock *req;
     294                 :            :         int mss;
     295                 :            :         struct rtable *rt;
     296                 :            :         __u8 rcv_wscale;
     297                 :            :         struct flowi4 fl4;
     298                 :            :         u32 tsoff = 0;
     299                 :            : 
     300   [ #  #  #  # ]:          0 :         if (!sock_net(sk)->ipv4.sysctl_tcp_syncookies || !th->ack || th->rst)
     301                 :            :                 goto out;
     302                 :            : 
     303         [ #  # ]:          0 :         if (tcp_synq_no_recent_overflow(sk))
     304                 :            :                 goto out;
     305                 :            : 
     306                 :          0 :         mss = __cookie_v4_check(ip_hdr(skb), th, cookie);
     307         [ #  # ]:          0 :         if (mss == 0) {
     308                 :          0 :                 __NET_INC_STATS(sock_net(sk), LINUX_MIB_SYNCOOKIESFAILED);
     309                 :            :                 goto out;
     310                 :            :         }
     311                 :            : 
     312                 :          0 :         __NET_INC_STATS(sock_net(sk), LINUX_MIB_SYNCOOKIESRECV);
     313                 :            : 
     314                 :            :         /* check for timestamp cookie support */
     315                 :          0 :         memset(&tcp_opt, 0, sizeof(tcp_opt));
     316                 :          0 :         tcp_parse_options(sock_net(sk), skb, &tcp_opt, 0, NULL);
     317                 :            : 
     318   [ #  #  #  # ]:          0 :         if (tcp_opt.saw_tstamp && tcp_opt.rcv_tsecr) {
     319                 :          0 :                 tsoff = secure_tcp_ts_off(sock_net(sk),
     320                 :            :                                           ip_hdr(skb)->daddr,
     321                 :            :                                           ip_hdr(skb)->saddr);
     322                 :          0 :                 tcp_opt.rcv_tsecr -= tsoff;
     323                 :            :         }
     324                 :            : 
     325         [ #  # ]:          0 :         if (!cookie_timestamp_decode(sock_net(sk), &tcp_opt))
     326                 :            :                 goto out;
     327                 :            : 
     328                 :            :         ret = NULL;
     329                 :          0 :         req = inet_reqsk_alloc(&tcp_request_sock_ops, sk, false); /* for safety */
     330         [ #  # ]:          0 :         if (!req)
     331                 :            :                 goto out;
     332                 :            : 
     333                 :            :         ireq = inet_rsk(req);
     334                 :            :         treq = tcp_rsk(req);
     335                 :          0 :         treq->rcv_isn                = ntohl(th->seq) - 1;
     336                 :          0 :         treq->snt_isn                = cookie;
     337                 :          0 :         treq->ts_off         = 0;
     338                 :          0 :         treq->txhash         = net_tx_rndhash();
     339                 :          0 :         req->mss             = mss;
     340                 :          0 :         ireq->ir_num         = ntohs(th->dest);
     341                 :          0 :         ireq->ir_rmt_port    = th->source;
     342                 :          0 :         sk_rcv_saddr_set(req_to_sk(req), ip_hdr(skb)->daddr);
     343                 :          0 :         sk_daddr_set(req_to_sk(req), ip_hdr(skb)->saddr);
     344                 :          0 :         ireq->ir_mark                = inet_request_mark(sk, skb);
     345                 :          0 :         ireq->snd_wscale     = tcp_opt.snd_wscale;
     346                 :          0 :         ireq->sack_ok                = tcp_opt.sack_ok;
     347                 :          0 :         ireq->wscale_ok              = tcp_opt.wscale_ok;
     348                 :          0 :         ireq->tstamp_ok              = tcp_opt.saw_tstamp;
     349         [ #  # ]:          0 :         req->ts_recent               = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsval : 0;
     350                 :          0 :         treq->snt_synack     = 0;
     351                 :          0 :         treq->tfo_listener   = false;
     352                 :            :         if (IS_ENABLED(CONFIG_SMC))
     353                 :            :                 ireq->smc_ok = 0;
     354                 :            : 
     355                 :          0 :         ireq->ir_iif = inet_request_bound_dev_if(sk, skb);
     356                 :            : 
     357                 :            :         /* We throwed the options of the initial SYN away, so we hope
     358                 :            :          * the ACK carries the same options again (see RFC1122 4.2.3.8)
     359                 :            :          */
     360                 :          0 :         RCU_INIT_POINTER(ireq->ireq_opt, tcp_v4_save_options(sock_net(sk), skb));
     361                 :            : 
     362         [ #  # ]:          0 :         if (security_inet_conn_request(sk, skb, req)) {
     363                 :          0 :                 reqsk_free(req);
     364                 :          0 :                 goto out;
     365                 :            :         }
     366                 :            : 
     367                 :          0 :         req->num_retrans = 0;
     368                 :            : 
     369                 :            :         /*
     370                 :            :          * We need to lookup the route here to get at the correct
     371                 :            :          * window size. We should better make sure that the window size
     372                 :            :          * hasn't changed since we received the original syn, but I see
     373                 :            :          * no easy way to do this.
     374                 :            :          */
     375         [ #  # ]:          0 :         flowi4_init_output(&fl4, ireq->ir_iif, ireq->ir_mark,
     376                 :          0 :                            RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, IPPROTO_TCP,
     377                 :            :                            inet_sk_flowi_flags(sk),
     378                 :          0 :                            opt->srr ? opt->faddr : ireq->ir_rmt_addr,
     379                 :            :                            ireq->ir_loc_addr, th->source, th->dest, sk->sk_uid);
     380                 :          0 :         security_req_classify_flow(req, flowi4_to_flowi(&fl4));
     381                 :            :         rt = ip_route_output_key(sock_net(sk), &fl4);
     382         [ #  # ]:          0 :         if (IS_ERR(rt)) {
     383                 :          0 :                 reqsk_free(req);
     384                 :          0 :                 goto out;
     385                 :            :         }
     386                 :            : 
     387                 :            :         /* Try to redo what tcp_v4_send_synack did. */
     388         [ #  # ]:          0 :         req->rsk_window_clamp = tp->window_clamp ? :dst_metric(&rt->dst, RTAX_WINDOW);
     389                 :            : 
     390                 :          0 :         tcp_select_initial_window(sk, tcp_full_space(sk), req->mss,
     391                 :          0 :                                   &req->rsk_rcv_wnd, &req->rsk_window_clamp,
     392                 :          0 :                                   ireq->wscale_ok, &rcv_wscale,
     393                 :          0 :                                   dst_metric(&rt->dst, RTAX_INITRWND));
     394                 :            : 
     395                 :          0 :         ireq->rcv_wscale  = rcv_wscale;
     396                 :          0 :         ireq->ecn_ok = cookie_ecn_ok(&tcp_opt, sock_net(sk), &rt->dst);
     397                 :            : 
     398                 :          0 :         ret = tcp_get_cookie_sock(sk, skb, req, &rt->dst, tsoff);
     399                 :            :         /* ip_queue_xmit() depends on our flow being setup
     400                 :            :          * Normal sockets get it right from inet_csk_route_child_sock()
     401                 :            :          */
     402         [ #  # ]:          0 :         if (ret)
     403                 :          0 :                 inet_sk(ret)->cork.fl.u.ip4 = fl4;
     404                 :          0 : out:    return ret;
     405                 :            : }

Generated by: LCOV version 1.14