LCOV - code coverage report
Current view: top level - net/ipv4 - ip_fragment.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 2 295 0.7 %
Date: 2014-04-07 Functions: 2 19 10.5 %
Branches: 0 194 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * INET         An implementation of the TCP/IP protocol suite for the LINUX
       3                 :            :  *              operating system.  INET is implemented using the  BSD Socket
       4                 :            :  *              interface as the means of communication with the user level.
       5                 :            :  *
       6                 :            :  *              The IP fragmentation functionality.
       7                 :            :  *
       8                 :            :  * Authors:     Fred N. van Kempen <waltje@uWalt.NL.Mugnet.ORG>
       9                 :            :  *              Alan Cox <alan@lxorguk.ukuu.org.uk>
      10                 :            :  *
      11                 :            :  * Fixes:
      12                 :            :  *              Alan Cox        :       Split from ip.c , see ip_input.c for history.
      13                 :            :  *              David S. Miller :       Begin massive cleanup...
      14                 :            :  *              Andi Kleen      :       Add sysctls.
      15                 :            :  *              xxxx            :       Overlapfrag bug.
      16                 :            :  *              Ultima          :       ip_expire() kernel panic.
      17                 :            :  *              Bill Hawes      :       Frag accounting and evictor fixes.
      18                 :            :  *              John McDonald   :       0 length frag bug.
      19                 :            :  *              Alexey Kuznetsov:       SMP races, threading, cleanup.
      20                 :            :  *              Patrick McHardy :       LRU queue of frag heads for evictor.
      21                 :            :  */
      22                 :            : 
      23                 :            : #define pr_fmt(fmt) "IPv4: " fmt
      24                 :            : 
      25                 :            : #include <linux/compiler.h>
      26                 :            : #include <linux/module.h>
      27                 :            : #include <linux/types.h>
      28                 :            : #include <linux/mm.h>
      29                 :            : #include <linux/jiffies.h>
      30                 :            : #include <linux/skbuff.h>
      31                 :            : #include <linux/list.h>
      32                 :            : #include <linux/ip.h>
      33                 :            : #include <linux/icmp.h>
      34                 :            : #include <linux/netdevice.h>
      35                 :            : #include <linux/jhash.h>
      36                 :            : #include <linux/random.h>
      37                 :            : #include <linux/slab.h>
      38                 :            : #include <net/route.h>
      39                 :            : #include <net/dst.h>
      40                 :            : #include <net/sock.h>
      41                 :            : #include <net/ip.h>
      42                 :            : #include <net/icmp.h>
      43                 :            : #include <net/checksum.h>
      44                 :            : #include <net/inetpeer.h>
      45                 :            : #include <net/inet_frag.h>
      46                 :            : #include <linux/tcp.h>
      47                 :            : #include <linux/udp.h>
      48                 :            : #include <linux/inet.h>
      49                 :            : #include <linux/netfilter_ipv4.h>
      50                 :            : #include <net/inet_ecn.h>
      51                 :            : 
      52                 :            : /* NOTE. Logic of IP defragmentation is parallel to corresponding IPv6
      53                 :            :  * code now. If you change something here, _PLEASE_ update ipv6/reassembly.c
      54                 :            :  * as well. Or notify me, at least. --ANK
      55                 :            :  */
      56                 :            : 
      57                 :            : static int sysctl_ipfrag_max_dist __read_mostly = 64;
      58                 :            : 
      59                 :            : struct ipfrag_skb_cb
      60                 :            : {
      61                 :            :         struct inet_skb_parm    h;
      62                 :            :         int                     offset;
      63                 :            : };
      64                 :            : 
      65                 :            : #define FRAG_CB(skb)    ((struct ipfrag_skb_cb *)((skb)->cb))
      66                 :            : 
      67                 :            : /* Describe an entry in the "incomplete datagrams" queue. */
      68                 :            : struct ipq {
      69                 :            :         struct inet_frag_queue q;
      70                 :            : 
      71                 :            :         u32             user;
      72                 :            :         __be32          saddr;
      73                 :            :         __be32          daddr;
      74                 :            :         __be16          id;
      75                 :            :         u8              protocol;
      76                 :            :         u8              ecn; /* RFC3168 support */
      77                 :            :         int             iif;
      78                 :            :         unsigned int    rid;
      79                 :            :         struct inet_peer *peer;
      80                 :            : };
      81                 :            : 
      82                 :            : static inline u8 ip4_frag_ecn(u8 tos)
      83                 :            : {
      84                 :          0 :         return 1 << (tos & INET_ECN_MASK);
      85                 :            : }
      86                 :            : 
      87                 :            : static struct inet_frags ip4_frags;
      88                 :            : 
      89                 :          0 : int ip_frag_nqueues(struct net *net)
      90                 :            : {
      91                 :          1 :         return net->ipv4.frags.nqueues;
      92                 :            : }
      93                 :            : 
      94                 :          0 : int ip_frag_mem(struct net *net)
      95                 :            : {
      96                 :          1 :         return sum_frag_mem_limit(&net->ipv4.frags);
      97                 :            : }
      98                 :            : 
      99                 :            : static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
     100                 :            :                          struct net_device *dev);
     101                 :            : 
     102                 :            : struct ip4_create_arg {
     103                 :            :         struct iphdr *iph;
     104                 :            :         u32 user;
     105                 :            : };
     106                 :            : 
     107                 :          0 : static unsigned int ipqhashfn(__be16 id, __be32 saddr, __be32 daddr, u8 prot)
     108                 :            : {
     109         [ #  # ]:          0 :         net_get_random_once(&ip4_frags.rnd, sizeof(ip4_frags.rnd));
     110                 :          0 :         return jhash_3words((__force u32)id << 16 | prot,
     111                 :            :                             (__force u32)saddr, (__force u32)daddr,
     112                 :            :                             ip4_frags.rnd) & (INETFRAGS_HASHSZ - 1);
     113                 :            : }
     114                 :            : 
     115                 :          0 : static unsigned int ip4_hashfn(struct inet_frag_queue *q)
     116                 :            : {
     117                 :            :         struct ipq *ipq;
     118                 :            : 
     119                 :            :         ipq = container_of(q, struct ipq, q);
     120                 :          0 :         return ipqhashfn(ipq->id, ipq->saddr, ipq->daddr, ipq->protocol);
     121                 :            : }
     122                 :            : 
     123                 :          0 : static bool ip4_frag_match(struct inet_frag_queue *q, void *a)
     124                 :            : {
     125                 :            :         struct ipq *qp;
     126                 :            :         struct ip4_create_arg *arg = a;
     127                 :            : 
     128                 :            :         qp = container_of(q, struct ipq, q);
     129         [ #  # ]:          0 :         return  qp->id == arg->iph->id &&
     130         [ #  # ]:          0 :                 qp->saddr == arg->iph->saddr &&
     131         [ #  # ]:          0 :                 qp->daddr == arg->iph->daddr &&
     132 [ #  # ][ #  # ]:          0 :                 qp->protocol == arg->iph->protocol &&
     133                 :          0 :                 qp->user == arg->user;
     134                 :            : }
     135                 :            : 
     136                 :          0 : static void ip4_frag_init(struct inet_frag_queue *q, void *a)
     137                 :            : {
     138                 :            :         struct ipq *qp = container_of(q, struct ipq, q);
     139                 :          0 :         struct netns_ipv4 *ipv4 = container_of(q->net, struct netns_ipv4,
     140                 :            :                                                frags);
     141                 :            :         struct net *net = container_of(ipv4, struct net, ipv4);
     142                 :            : 
     143                 :            :         struct ip4_create_arg *arg = a;
     144                 :            : 
     145                 :          0 :         qp->protocol = arg->iph->protocol;
     146                 :          0 :         qp->id = arg->iph->id;
     147                 :          0 :         qp->ecn = ip4_frag_ecn(arg->iph->tos);
     148                 :          0 :         qp->saddr = arg->iph->saddr;
     149                 :          0 :         qp->daddr = arg->iph->daddr;
     150                 :          0 :         qp->user = arg->user;
     151                 :          0 :         qp->peer = sysctl_ipfrag_max_dist ?
     152         [ #  # ]:          0 :                 inet_getpeer_v4(net->ipv4.peers, arg->iph->saddr, 1) : NULL;
     153                 :          0 : }
     154                 :            : 
     155                 :          0 : static __inline__ void ip4_frag_free(struct inet_frag_queue *q)
     156                 :            : {
     157                 :            :         struct ipq *qp;
     158                 :            : 
     159                 :            :         qp = container_of(q, struct ipq, q);
     160         [ #  # ]:          0 :         if (qp->peer)
     161                 :          0 :                 inet_putpeer(qp->peer);
     162                 :          0 : }
     163                 :            : 
     164                 :            : 
     165                 :            : /* Destruction primitives. */
     166                 :            : 
     167                 :            : static __inline__ void ipq_put(struct ipq *ipq)
     168                 :            : {
     169                 :          0 :         inet_frag_put(&ipq->q, &ip4_frags);
     170                 :            : }
     171                 :            : 
     172                 :            : /* Kill ipq entry. It is not destroyed immediately,
     173                 :            :  * because caller (and someone more) holds reference count.
     174                 :            :  */
     175                 :            : static void ipq_kill(struct ipq *ipq)
     176                 :            : {
     177                 :          0 :         inet_frag_kill(&ipq->q, &ip4_frags);
     178                 :            : }
     179                 :            : 
     180                 :            : /* Memory limiting on fragments.  Evictor trashes the oldest
     181                 :            :  * fragment queue until we are back under the threshold.
     182                 :            :  */
     183                 :          0 : static void ip_evictor(struct net *net)
     184                 :            : {
     185                 :            :         int evicted;
     186                 :            : 
     187                 :          0 :         evicted = inet_frag_evictor(&net->ipv4.frags, &ip4_frags, false);
     188         [ #  # ]:          0 :         if (evicted)
     189                 :          0 :                 IP_ADD_STATS_BH(net, IPSTATS_MIB_REASMFAILS, evicted);
     190                 :          0 : }
     191                 :            : 
     192                 :            : /*
     193                 :            :  * Oops, a fragment queue timed out.  Kill it and send an ICMP reply.
     194                 :            :  */
     195                 :          0 : static void ip_expire(unsigned long arg)
     196                 :            : {
     197                 :            :         struct ipq *qp;
     198                 :            :         struct net *net;
     199                 :            : 
     200                 :          0 :         qp = container_of((struct inet_frag_queue *) arg, struct ipq, q);
     201                 :          0 :         net = container_of(qp->q.net, struct net, ipv4.frags);
     202                 :            : 
     203                 :            :         spin_lock(&qp->q.lock);
     204                 :            : 
     205         [ #  # ]:          0 :         if (qp->q.last_in & INET_FRAG_COMPLETE)
     206                 :            :                 goto out;
     207                 :            : 
     208                 :            :         ipq_kill(qp);
     209                 :            : 
     210                 :          0 :         IP_INC_STATS_BH(net, IPSTATS_MIB_REASMTIMEOUT);
     211                 :          0 :         IP_INC_STATS_BH(net, IPSTATS_MIB_REASMFAILS);
     212                 :            : 
     213 [ #  # ][ #  # ]:          0 :         if ((qp->q.last_in & INET_FRAG_FIRST_IN) && qp->q.fragments != NULL) {
     214                 :            :                 struct sk_buff *head = qp->q.fragments;
     215                 :            :                 const struct iphdr *iph;
     216                 :            :                 int err;
     217                 :            : 
     218                 :            :                 rcu_read_lock();
     219                 :          0 :                 head->dev = dev_get_by_index_rcu(net, qp->iif);
     220         [ #  # ]:          0 :                 if (!head->dev)
     221                 :            :                         goto out_rcu_unlock;
     222                 :            : 
     223                 :            :                 /* skb has no dst, perform route lookup again */
     224                 :            :                 iph = ip_hdr(head);
     225                 :          0 :                 err = ip_route_input_noref(head, iph->daddr, iph->saddr,
     226                 :            :                                            iph->tos, head->dev);
     227         [ #  # ]:          0 :                 if (err)
     228                 :            :                         goto out_rcu_unlock;
     229                 :            : 
     230                 :            :                 /*
     231                 :            :                  * Only an end host needs to send an ICMP
     232                 :            :                  * "Fragment Reassembly Timeout" message, per RFC792.
     233                 :            :                  */
     234 [ #  # ][ #  # ]:          0 :                 if (qp->user == IP_DEFRAG_AF_PACKET ||
     235         [ #  # ]:          0 :                     (qp->user == IP_DEFRAG_CONNTRACK_IN &&
     236                 :          0 :                      skb_rtable(head)->rt_type != RTN_LOCAL))
     237                 :            :                         goto out_rcu_unlock;
     238                 :            : 
     239                 :            : 
     240                 :            :                 /* Send an ICMP "Fragment Reassembly Timeout" message. */
     241                 :          0 :                 icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0);
     242                 :            : out_rcu_unlock:
     243                 :            :                 rcu_read_unlock();
     244                 :            :         }
     245                 :            : out:
     246                 :            :         spin_unlock(&qp->q.lock);
     247                 :            :         ipq_put(qp);
     248                 :          0 : }
     249                 :            : 
     250                 :            : /* Find the correct entry in the "incomplete datagrams" queue for
     251                 :            :  * this IP datagram, and create new one, if nothing is found.
     252                 :            :  */
     253                 :            : static inline struct ipq *ip_find(struct net *net, struct iphdr *iph, u32 user)
     254                 :            : {
     255                 :            :         struct inet_frag_queue *q;
     256                 :            :         struct ip4_create_arg arg;
     257                 :            :         unsigned int hash;
     258                 :            : 
     259                 :          0 :         arg.iph = iph;
     260                 :          0 :         arg.user = user;
     261                 :            : 
     262                 :          0 :         read_lock(&ip4_frags.lock);
     263                 :          0 :         hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol);
     264                 :            : 
     265                 :          0 :         q = inet_frag_find(&net->ipv4.frags, &ip4_frags, &arg, hash);
     266         [ #  # ]:          0 :         if (IS_ERR_OR_NULL(q)) {
     267                 :          0 :                 inet_frag_maybe_warn_overflow(q, pr_fmt());
     268                 :            :                 return NULL;
     269                 :            :         }
     270                 :            :         return container_of(q, struct ipq, q);
     271                 :            : }
     272                 :            : 
     273                 :            : /* Is the fragment too far ahead to be part of ipq? */
     274                 :            : static inline int ip_frag_too_far(struct ipq *qp)
     275                 :            : {
     276                 :          0 :         struct inet_peer *peer = qp->peer;
     277                 :          0 :         unsigned int max = sysctl_ipfrag_max_dist;
     278                 :            :         unsigned int start, end;
     279                 :            : 
     280                 :            :         int rc;
     281                 :            : 
     282         [ #  # ]:          0 :         if (!peer || !max)
     283                 :            :                 return 0;
     284                 :            : 
     285                 :          0 :         start = qp->rid;
     286                 :          0 :         end = atomic_inc_return(&peer->rid);
     287                 :          0 :         qp->rid = end;
     288                 :            : 
     289 [ #  # ][ #  # ]:          0 :         rc = qp->q.fragments && (end - start) > max;
     290                 :            : 
     291         [ #  # ]:          0 :         if (rc) {
     292                 :            :                 struct net *net;
     293                 :            : 
     294                 :          0 :                 net = container_of(qp->q.net, struct net, ipv4.frags);
     295                 :          0 :                 IP_INC_STATS_BH(net, IPSTATS_MIB_REASMFAILS);
     296                 :            :         }
     297                 :            : 
     298                 :            :         return rc;
     299                 :            : }
     300                 :            : 
     301                 :          0 : static int ip_frag_reinit(struct ipq *qp)
     302                 :            : {
     303                 :            :         struct sk_buff *fp;
     304                 :            :         unsigned int sum_truesize = 0;
     305                 :            : 
     306         [ #  # ]:          0 :         if (!mod_timer(&qp->q.timer, jiffies + qp->q.net->timeout)) {
     307                 :          0 :                 atomic_inc(&qp->q.refcnt);
     308                 :          0 :                 return -ETIMEDOUT;
     309                 :            :         }
     310                 :            : 
     311                 :          0 :         fp = qp->q.fragments;
     312                 :            :         do {
     313                 :          0 :                 struct sk_buff *xp = fp->next;
     314                 :            : 
     315                 :          0 :                 sum_truesize += fp->truesize;
     316                 :          0 :                 kfree_skb(fp);
     317                 :            :                 fp = xp;
     318         [ #  # ]:          0 :         } while (fp);
     319                 :          0 :         sub_frag_mem_limit(&qp->q, sum_truesize);
     320                 :            : 
     321                 :          0 :         qp->q.last_in = 0;
     322                 :          0 :         qp->q.len = 0;
     323                 :          0 :         qp->q.meat = 0;
     324                 :          0 :         qp->q.fragments = NULL;
     325                 :          0 :         qp->q.fragments_tail = NULL;
     326                 :          0 :         qp->iif = 0;
     327                 :          0 :         qp->ecn = 0;
     328                 :            : 
     329                 :          0 :         return 0;
     330                 :            : }
     331                 :            : 
     332                 :            : /* Add new segment to existing queue. */
     333                 :          0 : static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
     334                 :            : {
     335                 :            :         struct sk_buff *prev, *next;
     336                 :            :         struct net_device *dev;
     337                 :            :         int flags, offset;
     338                 :            :         int ihl, end;
     339                 :            :         int err = -ENOENT;
     340                 :            :         u8 ecn;
     341                 :            : 
     342         [ #  # ]:          0 :         if (qp->q.last_in & INET_FRAG_COMPLETE)
     343                 :            :                 goto err;
     344                 :            : 
     345 [ #  # ][ #  # ]:          0 :         if (!(IPCB(skb)->flags & IPSKB_FRAG_COMPLETE) &&
     346         [ #  # ]:          0 :             unlikely(ip_frag_too_far(qp)) &&
     347                 :          0 :             unlikely(err = ip_frag_reinit(qp))) {
     348                 :            :                 ipq_kill(qp);
     349                 :            :                 goto err;
     350                 :            :         }
     351                 :            : 
     352                 :          0 :         ecn = ip4_frag_ecn(ip_hdr(skb)->tos);
     353                 :          0 :         offset = ntohs(ip_hdr(skb)->frag_off);
     354                 :            :         flags = offset & ~IP_OFFSET;
     355                 :          0 :         offset &= IP_OFFSET;
     356                 :          0 :         offset <<= 3;             /* offset is in 8-byte chunks */
     357                 :            :         ihl = ip_hdrlen(skb);
     358                 :            : 
     359                 :            :         /* Determine the position of this fragment. */
     360                 :          0 :         end = offset + skb->len - ihl;
     361                 :            :         err = -EINVAL;
     362                 :            : 
     363                 :            :         /* Is this the final fragment? */
     364         [ #  # ]:          0 :         if ((flags & IP_MF) == 0) {
     365                 :            :                 /* If we already have some bits beyond end
     366                 :            :                  * or have different end, the segment is corrupted.
     367                 :            :                  */
     368 [ #  # ][ #  # ]:          0 :                 if (end < qp->q.len ||
     369         [ #  # ]:          0 :                     ((qp->q.last_in & INET_FRAG_LAST_IN) && end != qp->q.len))
     370                 :            :                         goto err;
     371                 :          0 :                 qp->q.last_in |= INET_FRAG_LAST_IN;
     372                 :          0 :                 qp->q.len = end;
     373                 :            :         } else {
     374         [ #  # ]:          0 :                 if (end&7) {
     375                 :          0 :                         end &= ~7;
     376         [ #  # ]:          0 :                         if (skb->ip_summed != CHECKSUM_UNNECESSARY)
     377                 :          0 :                                 skb->ip_summed = CHECKSUM_NONE;
     378                 :            :                 }
     379         [ #  # ]:          0 :                 if (end > qp->q.len) {
     380                 :            :                         /* Some bits beyond end -> corruption. */
     381         [ #  # ]:          0 :                         if (qp->q.last_in & INET_FRAG_LAST_IN)
     382                 :            :                                 goto err;
     383                 :          0 :                         qp->q.len = end;
     384                 :            :                 }
     385                 :            :         }
     386         [ #  # ]:          0 :         if (end == offset)
     387                 :            :                 goto err;
     388                 :            : 
     389                 :            :         err = -ENOMEM;
     390         [ #  # ]:          0 :         if (pskb_pull(skb, ihl) == NULL)
     391                 :            :                 goto err;
     392                 :            : 
     393                 :          0 :         err = pskb_trim_rcsum(skb, end - offset);
     394         [ #  # ]:          0 :         if (err)
     395                 :            :                 goto err;
     396                 :            : 
     397                 :            :         /* Find out which fragments are in front and at the back of us
     398                 :            :          * in the chain of fragments so far.  We must know where to put
     399                 :            :          * this fragment, right?
     400                 :            :          */
     401                 :          0 :         prev = qp->q.fragments_tail;
     402 [ #  # ][ #  # ]:          0 :         if (!prev || FRAG_CB(prev)->offset < offset) {
     403                 :            :                 next = NULL;
     404                 :            :                 goto found;
     405                 :            :         }
     406                 :            :         prev = NULL;
     407         [ #  # ]:          0 :         for (next = qp->q.fragments; next != NULL; next = next->next) {
     408         [ #  # ]:          0 :                 if (FRAG_CB(next)->offset >= offset)
     409                 :            :                         break;  /* bingo! */
     410                 :            :                 prev = next;
     411                 :            :         }
     412                 :            : 
     413                 :            : found:
     414                 :            :         /* We found where to put this one.  Check for overlap with
     415                 :            :          * preceding fragment, and, if needed, align things so that
     416                 :            :          * any overlaps are eliminated.
     417                 :            :          */
     418         [ #  # ]:          0 :         if (prev) {
     419                 :          0 :                 int i = (FRAG_CB(prev)->offset + prev->len) - offset;
     420                 :            : 
     421         [ #  # ]:          0 :                 if (i > 0) {
     422                 :          0 :                         offset += i;
     423                 :            :                         err = -EINVAL;
     424         [ #  # ]:          0 :                         if (end <= offset)
     425                 :            :                                 goto err;
     426                 :            :                         err = -ENOMEM;
     427         [ #  # ]:          0 :                         if (!pskb_pull(skb, i))
     428                 :            :                                 goto err;
     429         [ #  # ]:          0 :                         if (skb->ip_summed != CHECKSUM_UNNECESSARY)
     430                 :          0 :                                 skb->ip_summed = CHECKSUM_NONE;
     431                 :            :                 }
     432                 :            :         }
     433                 :            : 
     434                 :            :         err = -ENOMEM;
     435                 :            : 
     436 [ #  # ][ #  # ]:          0 :         while (next && FRAG_CB(next)->offset < end) {
     437                 :          0 :                 int i = end - FRAG_CB(next)->offset; /* overlap is 'i' bytes */
     438                 :            : 
     439         [ #  # ]:          0 :                 if (i < next->len) {
     440                 :            :                         /* Eat head of the next overlapped fragment
     441                 :            :                          * and leave the loop. The next ones cannot overlap.
     442                 :            :                          */
     443         [ #  # ]:          0 :                         if (!pskb_pull(next, i))
     444                 :            :                                 goto err;
     445                 :          0 :                         FRAG_CB(next)->offset += i;
     446                 :          0 :                         qp->q.meat -= i;
     447         [ #  # ]:          0 :                         if (next->ip_summed != CHECKSUM_UNNECESSARY)
     448                 :          0 :                                 next->ip_summed = CHECKSUM_NONE;
     449                 :            :                         break;
     450                 :            :                 } else {
     451                 :            :                         struct sk_buff *free_it = next;
     452                 :            : 
     453                 :            :                         /* Old fragment is completely overridden with
     454                 :            :                          * new one drop it.
     455                 :            :                          */
     456                 :          0 :                         next = next->next;
     457                 :            : 
     458         [ #  # ]:          0 :                         if (prev)
     459                 :          0 :                                 prev->next = next;
     460                 :            :                         else
     461                 :          0 :                                 qp->q.fragments = next;
     462                 :            : 
     463                 :          0 :                         qp->q.meat -= free_it->len;
     464                 :          0 :                         sub_frag_mem_limit(&qp->q, free_it->truesize);
     465                 :          0 :                         kfree_skb(free_it);
     466                 :            :                 }
     467                 :            :         }
     468                 :            : 
     469                 :          0 :         FRAG_CB(skb)->offset = offset;
     470                 :            : 
     471                 :            :         /* Insert this fragment in the chain of fragments. */
     472                 :          0 :         skb->next = next;
     473         [ #  # ]:          0 :         if (!next)
     474                 :          0 :                 qp->q.fragments_tail = skb;
     475         [ #  # ]:          0 :         if (prev)
     476                 :          0 :                 prev->next = skb;
     477                 :            :         else
     478                 :          0 :                 qp->q.fragments = skb;
     479                 :            : 
     480                 :          0 :         dev = skb->dev;
     481         [ #  # ]:          0 :         if (dev) {
     482                 :          0 :                 qp->iif = dev->ifindex;
     483                 :          0 :                 skb->dev = NULL;
     484                 :            :         }
     485                 :          0 :         qp->q.stamp = skb->tstamp;
     486                 :          0 :         qp->q.meat += skb->len;
     487                 :          0 :         qp->ecn |= ecn;
     488                 :          0 :         add_frag_mem_limit(&qp->q, skb->truesize);
     489         [ #  # ]:          0 :         if (offset == 0)
     490                 :          0 :                 qp->q.last_in |= INET_FRAG_FIRST_IN;
     491                 :            : 
     492 [ #  # ][ #  # ]:          0 :         if (ip_hdr(skb)->frag_off & htons(IP_DF) &&
     493                 :          0 :             skb->len + ihl > qp->q.max_size)
     494                 :          0 :                 qp->q.max_size = skb->len + ihl;
     495                 :            : 
     496 [ #  # ][ #  # ]:          0 :         if (qp->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) &&
     497                 :          0 :             qp->q.meat == qp->q.len) {
     498                 :          0 :                 unsigned long orefdst = skb->_skb_refdst;
     499                 :            : 
     500                 :          0 :                 skb->_skb_refdst = 0UL;
     501                 :          0 :                 err = ip_frag_reasm(qp, prev, dev);
     502                 :          0 :                 skb->_skb_refdst = orefdst;
     503                 :          0 :                 return err;
     504                 :            :         }
     505                 :            : 
     506                 :            :         skb_dst_drop(skb);
     507                 :            :         inet_frag_lru_move(&qp->q);
     508                 :          0 :         return -EINPROGRESS;
     509                 :            : 
     510                 :            : err:
     511                 :          0 :         kfree_skb(skb);
     512                 :          0 :         return err;
     513                 :            : }
     514                 :            : 
     515                 :            : 
     516                 :            : /* Build a new IP datagram from all its fragments. */
     517                 :            : 
     518                 :          0 : static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
     519                 :            :                          struct net_device *dev)
     520                 :            : {
     521                 :          0 :         struct net *net = container_of(qp->q.net, struct net, ipv4.frags);
     522                 :            :         struct iphdr *iph;
     523                 :          0 :         struct sk_buff *fp, *head = qp->q.fragments;
     524                 :            :         int len;
     525                 :            :         int ihlen;
     526                 :            :         int err;
     527                 :            :         int sum_truesize;
     528                 :            :         u8 ecn;
     529                 :            : 
     530                 :            :         ipq_kill(qp);
     531                 :            : 
     532                 :          0 :         ecn = ip_frag_ecn_table[qp->ecn];
     533         [ #  # ]:          0 :         if (unlikely(ecn == 0xff)) {
     534                 :            :                 err = -EINVAL;
     535                 :            :                 goto out_fail;
     536                 :            :         }
     537                 :            :         /* Make the one we just received the head. */
     538         [ #  # ]:          0 :         if (prev) {
     539                 :          0 :                 head = prev->next;
     540                 :          0 :                 fp = skb_clone(head, GFP_ATOMIC);
     541         [ #  # ]:          0 :                 if (!fp)
     542                 :            :                         goto out_nomem;
     543                 :            : 
     544                 :          0 :                 fp->next = head->next;
     545         [ #  # ]:          0 :                 if (!fp->next)
     546                 :          0 :                         qp->q.fragments_tail = fp;
     547                 :          0 :                 prev->next = fp;
     548                 :            : 
     549                 :          0 :                 skb_morph(head, qp->q.fragments);
     550                 :          0 :                 head->next = qp->q.fragments->next;
     551                 :            : 
     552                 :          0 :                 consume_skb(qp->q.fragments);
     553                 :          0 :                 qp->q.fragments = head;
     554                 :            :         }
     555                 :            : 
     556         [ #  # ]:          0 :         WARN_ON(head == NULL);
     557         [ #  # ]:          0 :         WARN_ON(FRAG_CB(head)->offset != 0);
     558                 :            : 
     559                 :            :         /* Allocate a new buffer for the datagram. */
     560                 :            :         ihlen = ip_hdrlen(head);
     561                 :          0 :         len = ihlen + qp->q.len;
     562                 :            : 
     563                 :            :         err = -E2BIG;
     564         [ #  # ]:          0 :         if (len > 65535)
     565                 :            :                 goto out_oversize;
     566                 :            : 
     567                 :            :         /* Head of list must not be cloned. */
     568         [ #  # ]:          0 :         if (skb_unclone(head, GFP_ATOMIC))
     569                 :            :                 goto out_nomem;
     570                 :            : 
     571                 :            :         /* If the first fragment is fragmented itself, we split
     572                 :            :          * it to two chunks: the first with data and paged part
     573                 :            :          * and the second, holding only fragments. */
     574         [ #  # ]:          0 :         if (skb_has_frag_list(head)) {
     575                 :          0 :                 struct sk_buff *clone;
     576                 :            :                 int i, plen = 0;
     577                 :            : 
     578         [ #  # ]:          0 :                 if ((clone = alloc_skb(0, GFP_ATOMIC)) == NULL)
     579                 :            :                         goto out_nomem;
     580                 :          0 :                 clone->next = head->next;
     581                 :          0 :                 head->next = clone;
     582                 :          0 :                 skb_shinfo(clone)->frag_list = skb_shinfo(head)->frag_list;
     583                 :            :                 skb_frag_list_init(head);
     584         [ #  # ]:          0 :                 for (i = 0; i < skb_shinfo(head)->nr_frags; i++)
     585                 :          0 :                         plen += skb_frag_size(&skb_shinfo(head)->frags[i]);
     586                 :          0 :                 clone->len = clone->data_len = head->data_len - plen;
     587                 :          0 :                 head->data_len -= clone->len;
     588                 :          0 :                 head->len -= clone->len;
     589                 :          0 :                 clone->csum = 0;
     590                 :          0 :                 clone->ip_summed = head->ip_summed;
     591                 :          0 :                 add_frag_mem_limit(&qp->q, clone->truesize);
     592                 :            :         }
     593                 :            : 
     594                 :          0 :         skb_push(head, head->data - skb_network_header(head));
     595                 :            : 
     596                 :          0 :         sum_truesize = head->truesize;
     597         [ #  # ]:          0 :         for (fp = head->next; fp;) {
     598                 :            :                 bool headstolen;
     599                 :            :                 int delta;
     600                 :          0 :                 struct sk_buff *next = fp->next;
     601                 :            : 
     602                 :          0 :                 sum_truesize += fp->truesize;
     603         [ #  # ]:          0 :                 if (head->ip_summed != fp->ip_summed)
     604                 :          0 :                         head->ip_summed = CHECKSUM_NONE;
     605         [ #  # ]:          0 :                 else if (head->ip_summed == CHECKSUM_COMPLETE)
     606                 :          0 :                         head->csum = csum_add(head->csum, fp->csum);
     607                 :            : 
     608         [ #  # ]:          0 :                 if (skb_try_coalesce(head, fp, &headstolen, &delta)) {
     609                 :          0 :                         kfree_skb_partial(fp, headstolen);
     610                 :            :                 } else {
     611         [ #  # ]:          0 :                         if (!skb_shinfo(head)->frag_list)
     612                 :          0 :                                 skb_shinfo(head)->frag_list = fp;
     613                 :          0 :                         head->data_len += fp->len;
     614                 :          0 :                         head->len += fp->len;
     615                 :          0 :                         head->truesize += fp->truesize;
     616                 :            :                 }
     617                 :            :                 fp = next;
     618                 :            :         }
     619                 :            :         sub_frag_mem_limit(&qp->q, sum_truesize);
     620                 :            : 
     621                 :          0 :         head->next = NULL;
     622                 :          0 :         head->dev = dev;
     623                 :          0 :         head->tstamp = qp->q.stamp;
     624                 :          0 :         IPCB(head)->frag_max_size = qp->q.max_size;
     625                 :            : 
     626                 :            :         iph = ip_hdr(head);
     627                 :            :         /* max_size != 0 implies at least one fragment had IP_DF set */
     628         [ #  # ]:          0 :         iph->frag_off = qp->q.max_size ? htons(IP_DF) : 0;
     629         [ #  # ]:          0 :         iph->tot_len = htons(len);
     630                 :          0 :         iph->tos |= ecn;
     631                 :          0 :         IP_INC_STATS_BH(net, IPSTATS_MIB_REASMOKS);
     632                 :          0 :         qp->q.fragments = NULL;
     633                 :          0 :         qp->q.fragments_tail = NULL;
     634                 :          0 :         return 0;
     635                 :            : 
     636                 :            : out_nomem:
     637 [ #  # ][ #  # ]:          0 :         LIMIT_NETDEBUG(KERN_ERR pr_fmt("queue_glue: no memory for gluing queue %p\n"),
     638                 :            :                        qp);
     639                 :            :         err = -ENOMEM;
     640                 :            :         goto out_fail;
     641                 :            : out_oversize:
     642         [ #  # ]:          0 :         net_info_ratelimited("Oversized IP packet from %pI4\n", &qp->saddr);
     643                 :            : out_fail:
     644                 :          0 :         IP_INC_STATS_BH(net, IPSTATS_MIB_REASMFAILS);
     645                 :          0 :         return err;
     646                 :            : }
     647                 :            : 
     648                 :            : /* Process an incoming IP datagram fragment. */
     649                 :          0 : int ip_defrag(struct sk_buff *skb, u32 user)
     650                 :            : {
     651                 :            :         struct ipq *qp;
     652                 :            :         struct net *net;
     653                 :            : 
     654                 :            :         net = skb->dev ? dev_net(skb->dev) : dev_net(skb_dst(skb)->dev);
     655                 :          0 :         IP_INC_STATS_BH(net, IPSTATS_MIB_REASMREQDS);
     656                 :            : 
     657                 :            :         /* Start by cleaning up the memory. */
     658                 :          0 :         ip_evictor(net);
     659                 :            : 
     660                 :            :         /* Lookup (or create) queue header */
     661         [ #  # ]:          0 :         if ((qp = ip_find(net, ip_hdr(skb), user)) != NULL) {
     662                 :            :                 int ret;
     663                 :            : 
     664                 :            :                 spin_lock(&qp->q.lock);
     665                 :            : 
     666                 :          0 :                 ret = ip_frag_queue(qp, skb);
     667                 :            : 
     668                 :            :                 spin_unlock(&qp->q.lock);
     669                 :            :                 ipq_put(qp);
     670                 :          0 :                 return ret;
     671                 :            :         }
     672                 :            : 
     673                 :          0 :         IP_INC_STATS_BH(net, IPSTATS_MIB_REASMFAILS);
     674                 :          0 :         kfree_skb(skb);
     675                 :          0 :         return -ENOMEM;
     676                 :            : }
     677                 :            : EXPORT_SYMBOL(ip_defrag);
     678                 :            : 
     679                 :          0 : struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user)
     680                 :            : {
     681                 :            :         struct iphdr iph;
     682                 :            :         u32 len;
     683                 :            : 
     684         [ #  # ]:          0 :         if (skb->protocol != htons(ETH_P_IP))
     685                 :            :                 return skb;
     686                 :            : 
     687         [ #  # ]:          0 :         if (!skb_copy_bits(skb, 0, &iph, sizeof(iph)))
     688                 :            :                 return skb;
     689                 :            : 
     690 [ #  # ][ #  # ]:          0 :         if (iph.ihl < 5 || iph.version != 4)
     691                 :            :                 return skb;
     692                 :            : 
     693         [ #  # ]:          0 :         len = ntohs(iph.tot_len);
     694 [ #  # ][ #  # ]:          0 :         if (skb->len < len || len < (iph.ihl * 4))
     695                 :            :                 return skb;
     696                 :            : 
     697         [ #  # ]:          0 :         if (ip_is_fragment(&iph)) {
     698                 :            :                 skb = skb_share_check(skb, GFP_ATOMIC);
     699         [ #  # ]:          0 :                 if (skb) {
     700         [ #  # ]:          0 :                         if (!pskb_may_pull(skb, iph.ihl*4))
     701                 :            :                                 return skb;
     702         [ #  # ]:          0 :                         if (pskb_trim_rcsum(skb, len))
     703                 :            :                                 return skb;
     704                 :          0 :                         memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
     705         [ #  # ]:          0 :                         if (ip_defrag(skb, user))
     706                 :            :                                 return NULL;
     707                 :          0 :                         skb->rxhash = 0;
     708                 :            :                 }
     709                 :            :         }
     710                 :          0 :         return skb;
     711                 :            : }
     712                 :            : EXPORT_SYMBOL(ip_check_defrag);
     713                 :            : 
     714                 :            : #ifdef CONFIG_SYSCTL
     715                 :            : static int zero;
     716                 :            : 
     717                 :            : static struct ctl_table ip4_frags_ns_ctl_table[] = {
     718                 :            :         {
     719                 :            :                 .procname       = "ipfrag_high_thresh",
     720                 :            :                 .data           = &init_net.ipv4.frags.high_thresh,
     721                 :            :                 .maxlen         = sizeof(int),
     722                 :            :                 .mode           = 0644,
     723                 :            :                 .proc_handler   = proc_dointvec
     724                 :            :         },
     725                 :            :         {
     726                 :            :                 .procname       = "ipfrag_low_thresh",
     727                 :            :                 .data           = &init_net.ipv4.frags.low_thresh,
     728                 :            :                 .maxlen         = sizeof(int),
     729                 :            :                 .mode           = 0644,
     730                 :            :                 .proc_handler   = proc_dointvec
     731                 :            :         },
     732                 :            :         {
     733                 :            :                 .procname       = "ipfrag_time",
     734                 :            :                 .data           = &init_net.ipv4.frags.timeout,
     735                 :            :                 .maxlen         = sizeof(int),
     736                 :            :                 .mode           = 0644,
     737                 :            :                 .proc_handler   = proc_dointvec_jiffies,
     738                 :            :         },
     739                 :            :         { }
     740                 :            : };
     741                 :            : 
     742                 :            : static struct ctl_table ip4_frags_ctl_table[] = {
     743                 :            :         {
     744                 :            :                 .procname       = "ipfrag_secret_interval",
     745                 :            :                 .data           = &ip4_frags.secret_interval,
     746                 :            :                 .maxlen         = sizeof(int),
     747                 :            :                 .mode           = 0644,
     748                 :            :                 .proc_handler   = proc_dointvec_jiffies,
     749                 :            :         },
     750                 :            :         {
     751                 :            :                 .procname       = "ipfrag_max_dist",
     752                 :            :                 .data           = &sysctl_ipfrag_max_dist,
     753                 :            :                 .maxlen         = sizeof(int),
     754                 :            :                 .mode           = 0644,
     755                 :            :                 .proc_handler   = proc_dointvec_minmax,
     756                 :            :                 .extra1         = &zero
     757                 :            :         },
     758                 :            :         { }
     759                 :            : };
     760                 :            : 
     761                 :          0 : static int __net_init ip4_frags_ns_ctl_register(struct net *net)
     762                 :            : {
     763                 :            :         struct ctl_table *table;
     764                 :            :         struct ctl_table_header *hdr;
     765                 :            : 
     766                 :            :         table = ip4_frags_ns_ctl_table;
     767                 :            :         if (!net_eq(net, &init_net)) {
     768                 :            :                 table = kmemdup(table, sizeof(ip4_frags_ns_ctl_table), GFP_KERNEL);
     769                 :            :                 if (table == NULL)
     770                 :            :                         goto err_alloc;
     771                 :            : 
     772                 :            :                 table[0].data = &net->ipv4.frags.high_thresh;
     773                 :            :                 table[1].data = &net->ipv4.frags.low_thresh;
     774                 :            :                 table[2].data = &net->ipv4.frags.timeout;
     775                 :            : 
     776                 :            :                 /* Don't export sysctls to unprivileged users */
     777                 :            :                 if (net->user_ns != &init_user_ns)
     778                 :            :                         table[0].procname = NULL;
     779                 :            :         }
     780                 :            : 
     781                 :          0 :         hdr = register_net_sysctl(net, "net/ipv4", table);
     782         [ #  # ]:          0 :         if (hdr == NULL)
     783                 :            :                 goto err_reg;
     784                 :            : 
     785                 :          0 :         net->ipv4.frags_hdr = hdr;
     786                 :          0 :         return 0;
     787                 :            : 
     788                 :            : err_reg:
     789                 :            :         if (!net_eq(net, &init_net))
     790                 :            :                 kfree(table);
     791                 :            : err_alloc:
     792                 :            :         return -ENOMEM;
     793                 :            : }
     794                 :            : 
     795                 :          0 : static void __net_exit ip4_frags_ns_ctl_unregister(struct net *net)
     796                 :            : {
     797                 :            :         struct ctl_table *table;
     798                 :            : 
     799                 :          0 :         table = net->ipv4.frags_hdr->ctl_table_arg;
     800                 :          0 :         unregister_net_sysctl_table(net->ipv4.frags_hdr);
     801                 :          0 :         kfree(table);
     802                 :          0 : }
     803                 :            : 
     804                 :            : static void ip4_frags_ctl_register(void)
     805                 :            : {
     806                 :          0 :         register_net_sysctl(&init_net, "net/ipv4", ip4_frags_ctl_table);
     807                 :            : }
     808                 :            : #else
     809                 :            : static inline int ip4_frags_ns_ctl_register(struct net *net)
     810                 :            : {
     811                 :            :         return 0;
     812                 :            : }
     813                 :            : 
     814                 :            : static inline void ip4_frags_ns_ctl_unregister(struct net *net)
     815                 :            : {
     816                 :            : }
     817                 :            : 
     818                 :            : static inline void ip4_frags_ctl_register(void)
     819                 :            : {
     820                 :            : }
     821                 :            : #endif
     822                 :            : 
     823                 :          0 : static int __net_init ipv4_frags_init_net(struct net *net)
     824                 :            : {
     825                 :            :         /* Fragment cache limits.
     826                 :            :          *
     827                 :            :          * The fragment memory accounting code, (tries to) account for
     828                 :            :          * the real memory usage, by measuring both the size of frag
     829                 :            :          * queue struct (inet_frag_queue (ipv4:ipq/ipv6:frag_queue))
     830                 :            :          * and the SKB's truesize.
     831                 :            :          *
     832                 :            :          * A 64K fragment consumes 129736 bytes (44*2944)+200
     833                 :            :          * (1500 truesize == 2944, sizeof(struct ipq) == 200)
     834                 :            :          *
     835                 :            :          * We will commit 4MB at one time. Should we cross that limit
     836                 :            :          * we will prune down to 3MB, making room for approx 8 big 64K
     837                 :            :          * fragments 8x128k.
     838                 :            :          */
     839                 :          0 :         net->ipv4.frags.high_thresh = 4 * 1024 * 1024;
     840                 :          0 :         net->ipv4.frags.low_thresh  = 3 * 1024 * 1024;
     841                 :            :         /*
     842                 :            :          * Important NOTE! Fragment queue must be destroyed before MSL expires.
     843                 :            :          * RFC791 is wrong proposing to prolongate timer each fragment arrival
     844                 :            :          * by TTL.
     845                 :            :          */
     846                 :          0 :         net->ipv4.frags.timeout = IP_FRAG_TIME;
     847                 :            : 
     848                 :          0 :         inet_frags_init_net(&net->ipv4.frags);
     849                 :            : 
     850                 :          0 :         return ip4_frags_ns_ctl_register(net);
     851                 :            : }
     852                 :            : 
     853                 :          0 : static void __net_exit ipv4_frags_exit_net(struct net *net)
     854                 :            : {
     855                 :          0 :         ip4_frags_ns_ctl_unregister(net);
     856                 :          0 :         inet_frags_exit_net(&net->ipv4.frags, &ip4_frags);
     857                 :          0 : }
     858                 :            : 
     859                 :            : static struct pernet_operations ip4_frags_ops = {
     860                 :            :         .init = ipv4_frags_init_net,
     861                 :            :         .exit = ipv4_frags_exit_net,
     862                 :            : };
     863                 :            : 
     864                 :          0 : void __init ipfrag_init(void)
     865                 :            : {
     866                 :            :         ip4_frags_ctl_register();
     867                 :          0 :         register_pernet_subsys(&ip4_frags_ops);
     868                 :          0 :         ip4_frags.hashfn = ip4_hashfn;
     869                 :          0 :         ip4_frags.constructor = ip4_frag_init;
     870                 :          0 :         ip4_frags.destructor = ip4_frag_free;
     871                 :          0 :         ip4_frags.skb_free = NULL;
     872                 :          0 :         ip4_frags.qsize = sizeof(struct ipq);
     873                 :          0 :         ip4_frags.match = ip4_frag_match;
     874                 :          0 :         ip4_frags.frag_expire = ip_expire;
     875                 :          0 :         ip4_frags.secret_interval = 10 * 60 * HZ;
     876                 :          0 :         inet_frags_init(&ip4_frags);
     877                 :          0 : }

Generated by: LCOV version 1.9