Merge branch 'for-linus2' of git://git.kernel.org/pub/scm/linux/kernel/git/vegard...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 16 Jun 2009 20:09:51 +0000 (13:09 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 16 Jun 2009 20:09:51 +0000 (13:09 -0700)
* 'for-linus2' of git://git.kernel.org/pub/scm/linux/kernel/git/vegard/kmemcheck: (39 commits)
  signal: fix __send_signal() false positive kmemcheck warning
  fs: fix do_mount_root() false positive kmemcheck warning
  fs: introduce __getname_gfp()
  trace: annotate bitfields in struct ring_buffer_event
  net: annotate struct sock bitfield
  c2port: annotate bitfield for kmemcheck
  net: annotate inet_timewait_sock bitfields
  ieee1394/csr1212: fix false positive kmemcheck report
  ieee1394: annotate bitfield
  net: annotate bitfields in struct inet_sock
  net: use kmemcheck bitfields API for skbuff
  kmemcheck: introduce bitfield API
  kmemcheck: add opcode self-testing at boot
  x86: unify pte_hidden
  x86: make _PAGE_HIDDEN conditional
  kmemcheck: make kconfig accessible for other architectures
  kmemcheck: enable in the x86 Kconfig
  kmemcheck: add hooks for the page allocator
  kmemcheck: add hooks for page- and sg-dma-mappings
  kmemcheck: don't track page tables
  ...

1  2 
MAINTAINERS
include/linux/skbuff.h
include/net/inet_sock.h
include/net/sock.h
kernel/sysctl.c
net/core/skbuff.c
net/core/sock.c
net/ipv4/inet_timewait_sock.c

diff --combined MAINTAINERS
index 685784cc023b6e4a242e4efcfc845a54c64c7e57,22a91178148bee4731f3192478ac214ee773a8c4..af8ef6527f2298c14e71f6f9dfb844be81a60fd4
@@@ -157,10 -157,9 +157,10 @@@ S:       Maintaine
  F:    drivers/net/r8169.c
  
  8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
 +P:    Alan Cox
 +M:    alan@lxorguk.ukuu.org.uk
  L:    linux-serial@vger.kernel.org
  W:    http://serial.sourceforge.net
 -M:    alan@lxorguk.ukuu.org.uk
  S:    Odd Fixes
  F:    drivers/serial/8250*
  F:    include/linux/serial_8250.h
@@@ -948,12 -947,6 +948,12 @@@ P:       Luis R. Rodrigue
  M:    lrodriguez@atheros.com
  P:    Jouni Malinen
  M:    jmalinen@atheros.com
 +P:    Sujith Manoharan
 +M:    Sujith.Manoharan@atheros.com
 +P:    Vasanthakumar Thiagarajan
 +M:    vasanth@atheros.com
 +P:    Senthil Balasubramanian
 +M:    senthilkumar@atheros.com
  L:    linux-wireless@vger.kernel.org
  L:    ath9k-devel@lists.ath9k.org
  S:    Supported
@@@ -1346,13 -1339,6 +1346,13 @@@ F:    drivers/net/can
  F:    include/linux/can/
  F:    include/linux/can.h
  
 +CAN NETWORK DRIVERS
 +P:    Wolfgang Grandegger
 +M:    wg@grandegger.com
 +L:    socketcan-core@lists.berlios.de (subscribers-only)
 +W:    http://developer.berlios.de/projects/socketcan/
 +S:    Maintained
 +
  CELL BROADBAND ENGINE ARCHITECTURE
  P:    Arnd Bergmann
  M:    arnd@arndb.de
@@@ -2857,18 -2843,6 +2857,18 @@@ L:    linux1394-devel@lists.sourceforge.ne
  S:    Maintained
  F:    drivers/ieee1394/raw1394*
  
 +IEEE 802.15.4 SUBSYSTEM
 +P:    Dmitry Eremin-Solenikov
 +M:    dbaryshkov@gmail.com
 +P:    Sergey Lapin
 +M:    slapin@ossfans.org
 +L:    linux-zigbee-devel@lists.sourceforge.net
 +W:    http://apps.sourceforge.net/trac/linux-zigbee
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/lumag/lowpan.git
 +S:    Maintained
 +F:    net/ieee802154/
 +F:    drivers/ieee801254/
 +
  INTEGRITY MEASUREMENT ARCHITECTURE (IMA)
  P:    Mimi Zohar
  M:    zohar@us.ibm.com
@@@ -3162,7 -3136,6 +3162,7 @@@ M:      samuel@sortiz.or
  L:    irda-users@lists.sourceforge.net (subscribers-only)
  W:    http://irda.sourceforge.net/
  S:    Maintained
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/sameo/irda-2.6.git
  F:    Documentation/networking/irda.txt
  F:    drivers/net/irda/
  F:    include/net/irda/
@@@ -3406,6 -3379,14 +3406,14 @@@ F:    drivers/serial/kgdboc.
  F:    include/linux/kgdb.h
  F:    kernel/kgdb.c
  
+ KMEMCHECK
+ P:    Vegard Nossum
+ M:    vegardno@ifi.uio.no
+ P     Pekka Enberg
+ M:    penberg@cs.helsinki.fi
+ L:    linux-kernel@vger.kernel.org
+ S:    Maintained
  KMEMLEAK
  P:    Catalin Marinas
  M:    catalin.marinas@arm.com
@@@ -4648,8 -4629,8 +4656,8 @@@ S:      Maintaine
  F:    drivers/ata/sata_promise.*
  
  PS3 NETWORK SUPPORT
 -P:    Masakazu Mokuno
 -M:    mokuno@sm.sony.co.jp
 +P:    Geoff Levand
 +M:    geoffrey.levand@am.sony.com
  L:    netdev@vger.kernel.org
  L:    cbe-oss-dev@ozlabs.org
  S:    Supported
@@@ -4850,7 -4831,7 +4858,7 @@@ F:      drivers/net/r6040.
  RDS - RELIABLE DATAGRAM SOCKETS
  P:    Andy Grover
  M:    andy.grover@oracle.com
 -L:    rds-devel@oss.oracle.com
 +L:    rds-devel@oss.oracle.com (moderated for non-subscribers)
  S:    Supported
  F:    net/rds/
  
@@@ -4890,9 -4871,9 +4898,9 @@@ S:      Supporte
  F:    fs/reiserfs/
  
  RFKILL
 -P:    Ivo van Doorn
 -M:    IvDoorn@gmail.com
 -L:    netdev@vger.kernel.org
 +P:    Johannes Berg
 +M:    johannes@sipsolutions.net
 +L:    linux-wireless@vger.kernel.org
  S:    Maintained
  F     Documentation/rfkill.txt
  F:    net/rfkill/
@@@ -6165,12 -6146,6 +6173,12 @@@ L:    linux-wireless@vger.kernel.or
  S:    Maintained
  F:    drivers/net/wireless/rndis_wlan.c
  
 +USB XHCI DRIVER
 +P:    Sarah Sharp
 +M:    sarah.a.sharp@intel.com
 +L:    linux-usb@vger.kernel.org
 +S:    Supported
 +
  USB ZC0301 DRIVER
  P:    Luca Risolia
  M:    luca.risolia@studio.unibo.it
diff --combined include/linux/skbuff.h
index fa51293f270811832b97e8f660f979ae14e0bc44,ed6537fc5b487bf25d540247079491eafcf64c33..63ef24bc01d0eb728ab2ff3d7544b6c8380c8fcf
@@@ -15,6 -15,7 +15,7 @@@
  #define _LINUX_SKBUFF_H
  
  #include <linux/kernel.h>
+ #include <linux/kmemcheck.h>
  #include <linux/compiler.h>
  #include <linux/time.h>
  #include <linux/cache.h>
@@@ -189,23 -190,20 +190,23 @@@ struct skb_shared_info 
        atomic_t        dataref;
        unsigned short  nr_frags;
        unsigned short  gso_size;
 +#ifdef CONFIG_HAS_DMA
 +      dma_addr_t      dma_head;
 +#endif
        /* Warning: this field is not always filled in (UFO)! */
        unsigned short  gso_segs;
        unsigned short  gso_type;
        __be32          ip6_frag_id;
        union skb_shared_tx tx_flags;
 -#ifdef CONFIG_HAS_DMA
 -      unsigned int    num_dma_maps;
 -#endif
        struct sk_buff  *frag_list;
        struct skb_shared_hwtstamps hwtstamps;
        skb_frag_t      frags[MAX_SKB_FRAGS];
  #ifdef CONFIG_HAS_DMA
 -      dma_addr_t      dma_maps[MAX_SKB_FRAGS + 1];
 +      dma_addr_t      dma_maps[MAX_SKB_FRAGS];
  #endif
 +      /* Intermediate layers must ensure that destructor_arg
 +       * remains valid until skb destructor */
 +      void *          destructor_arg;
  };
  
  /* We divide dataref into two halves.  The higher 16 bits hold references
@@@ -304,6 -302,9 +305,6 @@@ typedef unsigned char *sk_buff_data_t
   *    @tc_verd: traffic control verdict
   *    @ndisc_nodetype: router type (from link layer)
   *    @do_not_encrypt: set to prevent encryption of this frame
 - *    @requeue: set to indicate that the wireless core should attempt
 - *            a software retry on this frame if we failed to
 - *            receive an ACK for it
   *    @dma_cookie: a cookie to one of several possible DMA operations
   *            done by skb DMA functions
   *    @secmark: security marking
@@@ -319,7 -320,10 +320,7 @@@ struct sk_buff 
        ktime_t                 tstamp;
        struct net_device       *dev;
  
 -      union {
 -              struct  dst_entry       *dst;
 -              struct  rtable          *rtable;
 -      };
 +      unsigned long           _skb_dst;
  #ifdef CONFIG_XFRM
        struct  sec_path        *sp;
  #endif
                };
        };
        __u32                   priority;
+       kmemcheck_bitfield_begin(flags1);
        __u8                    local_df:1,
                                cloned:1,
                                ip_summed:2,
                                ipvs_property:1,
                                peeked:1,
                                nf_trace:1;
+       kmemcheck_bitfield_end(flags1);
        __be16                  protocol;
  
        void                    (*destructor)(struct sk_buff *skb);
        __u16                   tc_verd;        /* traffic control verdict */
  #endif
  #endif
+       kmemcheck_bitfield_begin(flags2);
  #ifdef CONFIG_IPV6_NDISC_NODETYPE
        __u8                    ndisc_nodetype:2;
  #endif
  #if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE)
        __u8                    do_not_encrypt:1;
 -      __u8                    requeue:1;
  #endif
+       kmemcheck_bitfield_end(flags2);
        /* 0/13/14 bit hole */
  
  #ifdef CONFIG_NET_DMA
@@@ -419,21 -430,6 +426,21 @@@ extern void skb_dma_unmap(struct devic
                          enum dma_data_direction dir);
  #endif
  
 +static inline struct dst_entry *skb_dst(const struct sk_buff *skb)
 +{
 +      return (struct dst_entry *)skb->_skb_dst;
 +}
 +
 +static inline void skb_dst_set(struct sk_buff *skb, struct dst_entry *dst)
 +{
 +      skb->_skb_dst = (unsigned long)dst;
 +}
 +
 +static inline struct rtable *skb_rtable(const struct sk_buff *skb)
 +{
 +      return (struct rtable *)skb_dst(skb);
 +}
 +
  extern void kfree_skb(struct sk_buff *skb);
  extern void consume_skb(struct sk_buff *skb);
  extern void          __kfree_skb(struct sk_buff *skb);
@@@ -1073,7 -1069,7 +1080,7 @@@ extern void skb_add_rx_frag(struct sk_b
                            int off, int size);
  
  #define SKB_PAGE_ASSERT(skb)  BUG_ON(skb_shinfo(skb)->nr_frags)
 -#define SKB_FRAG_ASSERT(skb)  BUG_ON(skb_shinfo(skb)->frag_list)
 +#define SKB_FRAG_ASSERT(skb)  BUG_ON(skb_has_frags(skb))
  #define SKB_LINEAR_ASSERT(skb)  BUG_ON(skb_is_nonlinear(skb))
  
  #ifdef NET_SKBUFF_DATA_USES_OFFSET
@@@ -1712,25 -1708,6 +1719,25 @@@ static inline int pskb_trim_rcsum(struc
                     skb = skb->prev)
  
  
 +static inline bool skb_has_frags(const struct sk_buff *skb)
 +{
 +      return skb_shinfo(skb)->frag_list != NULL;
 +}
 +
 +static inline void skb_frag_list_init(struct sk_buff *skb)
 +{
 +      skb_shinfo(skb)->frag_list = NULL;
 +}
 +
 +static inline void skb_frag_add_head(struct sk_buff *skb, struct sk_buff *frag)
 +{
 +      frag->next = skb_shinfo(skb)->frag_list;
 +      skb_shinfo(skb)->frag_list = frag;
 +}
 +
 +#define skb_walk_frags(skb, iter)     \
 +      for (iter = skb_shinfo(skb)->frag_list; iter; iter = iter->next)
 +
  extern struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags,
                                           int *peeked, int *err);
  extern struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags,
@@@ -1745,14 -1722,8 +1752,14 @@@ extern int           skb_copy_and_csum_dat
                                                        struct iovec *iov);
  extern int           skb_copy_datagram_from_iovec(struct sk_buff *skb,
                                                    int offset,
 -                                                  struct iovec *from,
 +                                                  const struct iovec *from,
 +                                                  int from_offset,
                                                    int len);
 +extern int           skb_copy_datagram_const_iovec(const struct sk_buff *from,
 +                                                   int offset,
 +                                                   const struct iovec *to,
 +                                                   int to_offset,
 +                                                   int size);
  extern void          skb_free_datagram(struct sock *sk, struct sk_buff *skb);
  extern int           skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
                                         unsigned int flags);
diff --combined include/net/inet_sock.h
index 20a6957af870a0b12973a4b3cb937d5e0aeac011,cbcda0b0b96497d56860d599c1cfde6cce758d56..47004f35cc7eaf6f2b3cac2779ea7b7ccd5d9c1f
@@@ -17,6 -17,7 +17,7 @@@
  #define _INET_SOCK_H
  
  
+ #include <linux/kmemcheck.h>
  #include <linux/string.h>
  #include <linux/types.h>
  #include <linux/jhash.h>
@@@ -66,14 -67,16 +67,16 @@@ struct inet_request_sock 
        __be32                  loc_addr;
        __be32                  rmt_addr;
        __be16                  rmt_port;
-       u16                     snd_wscale : 4, 
-                               rcv_wscale : 4, 
+       kmemcheck_bitfield_begin(flags);
+       u16                     snd_wscale : 4,
+                               rcv_wscale : 4,
                                tstamp_ok  : 1,
                                sack_ok    : 1,
                                wscale_ok  : 1,
                                ecn_ok     : 1,
                                acked      : 1,
                                no_srccheck: 1;
+       kmemcheck_bitfield_end(flags);
        struct ip_options       *opt;
  };
  
@@@ -130,8 -133,7 +133,8 @@@ struct inet_sock 
                                freebind:1,
                                hdrincl:1,
                                mc_loop:1,
 -                              transparent:1;
 +                              transparent:1,
 +                              mc_all:1;
        int                     mc_index;
        __be32                  mc_addr;
        struct ip_mc_socklist   *mc_list;
@@@ -199,9 -201,12 +202,12 @@@ static inline int inet_sk_ehashfn(cons
  static inline struct request_sock *inet_reqsk_alloc(struct request_sock_ops *ops)
  {
        struct request_sock *req = reqsk_alloc(ops);
+       struct inet_request_sock *ireq = inet_rsk(req);
  
-       if (req != NULL)
-               inet_rsk(req)->opt = NULL;
+       if (req != NULL) {
+               kmemcheck_annotate_bitfield(ireq, flags);
+               ireq->opt = NULL;
+       }
  
        return req;
  }
diff --combined include/net/sock.h
index 010e14a93c9256a0d92e35232e2292e746e8f86c,d933da00d5050511acea852048eb7b84f2c0f027..95bd3fd75f942d42351cd42450420334fef6f2a0
@@@ -218,9 -218,11 +218,11 @@@ struct sock 
  #define sk_hash                       __sk_common.skc_hash
  #define sk_prot                       __sk_common.skc_prot
  #define sk_net                        __sk_common.skc_net
+       kmemcheck_bitfield_begin(flags);
        unsigned char           sk_shutdown : 2,
                                sk_no_check : 2,
                                sk_userlocks : 4;
+       kmemcheck_bitfield_end(flags);
        unsigned char           sk_protocol;
        unsigned short          sk_type;
        int                     sk_rcvbuf;
@@@ -1217,13 -1219,9 +1219,13 @@@ static inline int skb_copy_to_page(stru
  
  static inline void skb_set_owner_w(struct sk_buff *skb, struct sock *sk)
  {
 -      sock_hold(sk);
        skb->sk = sk;
        skb->destructor = sock_wfree;
 +      /*
 +       * We used to take a refcount on sk, but following operation
 +       * is enough to guarantee sk_free() wont free this sock until
 +       * all in-flight packets are completed
 +       */
        atomic_add(skb->truesize, &sk->sk_wmem_alloc);
  }
  
diff --combined kernel/sysctl.c
index 0e51a35a44869425aa3f4e7cf9fca498787fd0fb,9ef80bba35091e0285054257dcc92c9c564132db..f5c76b6cd616d32a89f9e22bf08486d3c0fd5800
@@@ -27,6 -27,7 +27,7 @@@
  #include <linux/security.h>
  #include <linux/ctype.h>
  #include <linux/utsname.h>
+ #include <linux/kmemcheck.h>
  #include <linux/smp_lock.h>
  #include <linux/fs.h>
  #include <linux/init.h>
@@@ -328,14 -329,6 +329,14 @@@ static struct ctl_table kern_table[] = 
                .mode           = 0644,
                .proc_handler   = &proc_dointvec,
        },
 +      {
 +              .ctl_name       = CTL_UNNUMBERED,
 +              .procname       = "timer_migration",
 +              .data           = &sysctl_timer_migration,
 +              .maxlen         = sizeof(unsigned int),
 +              .mode           = 0644,
 +              .proc_handler   = &proc_dointvec,
 +      },
  #endif
        {
                .ctl_name       = CTL_UNNUMBERED,
                .proc_handler   = &proc_dointvec,
        },
  #endif
+ #ifdef CONFIG_KMEMCHECK
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "kmemcheck",
+               .data           = &kmemcheck_enabled,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+       },
+ #endif
  /*
   * NOTE: do not add new entries to this table unless you have read
   * Documentation/sysctl/ctl_unnumbered.txt
diff --combined net/core/skbuff.c
index 1a94a3037370a4c70ee3862fb9676a4975eddeb1,f0c4c6ad774bad3bb6c4bf6ed0ab947f6d0c5ebf..5c93435b0347cc691db1ba36eeb1a23cb33809b6
@@@ -39,6 -39,7 +39,7 @@@
  #include <linux/module.h>
  #include <linux/types.h>
  #include <linux/kernel.h>
+ #include <linux/kmemcheck.h>
  #include <linux/mm.h>
  #include <linux/interrupt.h>
  #include <linux/in.h>
@@@ -201,6 -202,8 +202,8 @@@ struct sk_buff *__alloc_skb(unsigned in
        skb->data = data;
        skb_reset_tail_pointer(skb);
        skb->end = skb->tail + size;
+       kmemcheck_annotate_bitfield(skb, flags1);
+       kmemcheck_annotate_bitfield(skb, flags2);
        /* make sure we initialize shinfo sequentially */
        shinfo = skb_shinfo(skb);
        atomic_set(&shinfo->dataref, 1);
        shinfo->gso_type = 0;
        shinfo->ip6_frag_id = 0;
        shinfo->tx_flags.flags = 0;
 -      shinfo->frag_list = NULL;
 +      skb_frag_list_init(skb);
        memset(&shinfo->hwtstamps, 0, sizeof(shinfo->hwtstamps));
  
        if (fclone) {
                struct sk_buff *child = skb + 1;
                atomic_t *fclone_ref = (atomic_t *) (child + 1);
  
+               kmemcheck_annotate_bitfield(child, flags1);
+               kmemcheck_annotate_bitfield(child, flags2);
                skb->fclone = SKB_FCLONE_ORIG;
                atomic_set(fclone_ref, 1);
  
@@@ -323,7 -328,7 +328,7 @@@ static void skb_clone_fraglist(struct s
  {
        struct sk_buff *list;
  
 -      for (list = skb_shinfo(skb)->frag_list; list; list = list->next)
 +      skb_walk_frags(skb, list)
                skb_get(list);
  }
  
@@@ -338,7 -343,7 +343,7 @@@ static void skb_release_data(struct sk_
                                put_page(skb_shinfo(skb)->frags[i].page);
                }
  
 -              if (skb_shinfo(skb)->frag_list)
 +              if (skb_has_frags(skb))
                        skb_drop_fraglist(skb);
  
                kfree(skb->head);
@@@ -381,7 -386,7 +386,7 @@@ static void kfree_skbmem(struct sk_buf
  
  static void skb_release_head_state(struct sk_buff *skb)
  {
 -      dst_release(skb->dst);
 +      skb_dst_drop(skb);
  #ifdef CONFIG_XFRM
        secpath_put(skb->sp);
  #endif
@@@ -503,7 -508,7 +508,7 @@@ int skb_recycle_check(struct sk_buff *s
        shinfo->gso_type = 0;
        shinfo->ip6_frag_id = 0;
        shinfo->tx_flags.flags = 0;
 -      shinfo->frag_list = NULL;
 +      skb_frag_list_init(skb);
        memset(&shinfo->hwtstamps, 0, sizeof(shinfo->hwtstamps));
  
        memset(skb, 0, offsetof(struct sk_buff, tail));
@@@ -521,12 -526,13 +526,12 @@@ static void __copy_skb_header(struct sk
        new->transport_header   = old->transport_header;
        new->network_header     = old->network_header;
        new->mac_header         = old->mac_header;
 -      new->dst                = dst_clone(old->dst);
 +      skb_dst_set(new, dst_clone(skb_dst(old)));
  #ifdef CONFIG_XFRM
        new->sp                 = secpath_get(old->sp);
  #endif
        memcpy(new->cb, old->cb, sizeof(old->cb));
 -      new->csum_start         = old->csum_start;
 -      new->csum_offset        = old->csum_offset;
 +      new->csum               = old->csum;
        new->local_df           = old->local_df;
        new->pkt_type           = old->pkt_type;
        new->ip_summed          = old->ip_summed;
  #endif
        new->protocol           = old->protocol;
        new->mark               = old->mark;
 +      new->iif                = old->iif;
        __nf_copy(new, old);
  #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
      defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
  #endif
  #endif
        new->vlan_tci           = old->vlan_tci;
 +#if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE)
 +      new->do_not_encrypt     = old->do_not_encrypt;
 +#endif
  
        skb_copy_secmark(new, old);
  }
  
 +/*
 + * You should not add any new code to this function.  Add it to
 + * __copy_skb_header above instead.
 + */
  static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
  {
  #define C(x) n->x = skb->x
        n->cloned = 1;
        n->nohdr = 0;
        n->destructor = NULL;
 -      C(iif);
        C(tail);
        C(end);
        C(head);
        C(data);
        C(truesize);
 -#if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE)
 -      C(do_not_encrypt);
 -      C(requeue);
 -#endif
        atomic_set(&n->users, 1);
  
        atomic_inc(&(skb_shinfo(skb)->dataref));
@@@ -635,6 -638,9 +640,9 @@@ struct sk_buff *skb_clone(struct sk_buf
                n = kmem_cache_alloc(skbuff_head_cache, gfp_mask);
                if (!n)
                        return NULL;
+               kmemcheck_annotate_bitfield(n, flags1);
+               kmemcheck_annotate_bitfield(n, flags2);
                n->fclone = SKB_FCLONE_UNAVAILABLE;
        }
  
@@@ -757,7 -763,7 +765,7 @@@ struct sk_buff *pskb_copy(struct sk_buf
                skb_shinfo(n)->nr_frags = i;
        }
  
 -      if (skb_shinfo(skb)->frag_list) {
 +      if (skb_has_frags(skb)) {
                skb_shinfo(n)->frag_list = skb_shinfo(skb)->frag_list;
                skb_clone_fraglist(n);
        }
@@@ -820,7 -826,7 +828,7 @@@ int pskb_expand_head(struct sk_buff *sk
        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
                get_page(skb_shinfo(skb)->frags[i].page);
  
 -      if (skb_shinfo(skb)->frag_list)
 +      if (skb_has_frags(skb))
                skb_clone_fraglist(skb);
  
        skb_release_data(skb);
@@@ -1092,7 -1098,7 +1100,7 @@@ drop_pages
                for (; i < nfrags; i++)
                        put_page(skb_shinfo(skb)->frags[i].page);
  
 -              if (skb_shinfo(skb)->frag_list)
 +              if (skb_has_frags(skb))
                        skb_drop_fraglist(skb);
                goto done;
        }
@@@ -1187,7 -1193,7 +1195,7 @@@ unsigned char *__pskb_pull_tail(struct 
        /* Optimization: no fragments, no reasons to preestimate
         * size of pulled pages. Superb.
         */
 -      if (!skb_shinfo(skb)->frag_list)
 +      if (!skb_has_frags(skb))
                goto pull_pages;
  
        /* Estimate size of pulled pages. */
@@@ -1284,9 -1290,8 +1292,9 @@@ EXPORT_SYMBOL(__pskb_pull_tail)
  
  int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len)
  {
 -      int i, copy;
        int start = skb_headlen(skb);
 +      struct sk_buff *frag_iter;
 +      int i, copy;
  
        if (offset > (int)skb->len - len)
                goto fault;
                start = end;
        }
  
 -      if (skb_shinfo(skb)->frag_list) {
 -              struct sk_buff *list = skb_shinfo(skb)->frag_list;
 +      skb_walk_frags(skb, frag_iter) {
 +              int end;
  
 -              for (; list; list = list->next) {
 -                      int end;
 -
 -                      WARN_ON(start > offset + len);
 -
 -                      end = start + list->len;
 -                      if ((copy = end - offset) > 0) {
 -                              if (copy > len)
 -                                      copy = len;
 -                              if (skb_copy_bits(list, offset - start,
 -                                                to, copy))
 -                                      goto fault;
 -                              if ((len -= copy) == 0)
 -                                      return 0;
 -                              offset += copy;
 -                              to     += copy;
 -                      }
 -                      start = end;
 +              WARN_ON(start > offset + len);
 +
 +              end = start + frag_iter->len;
 +              if ((copy = end - offset) > 0) {
 +                      if (copy > len)
 +                              copy = len;
 +                      if (skb_copy_bits(frag_iter, offset - start, to, copy))
 +                              goto fault;
 +                      if ((len -= copy) == 0)
 +                              return 0;
 +                      offset += copy;
 +                      to     += copy;
                }
 +              start = end;
        }
        if (!len)
                return 0;
@@@ -1529,7 -1539,6 +1537,7 @@@ int skb_splice_bits(struct sk_buff *skb
                .ops = &sock_pipe_buf_ops,
                .spd_release = sock_spd_release,
        };
 +      struct sk_buff *frag_iter;
        struct sock *sk = skb->sk;
  
        /*
        /*
         * now see if we have a frag_list to map
         */
 -      if (skb_shinfo(skb)->frag_list) {
 -              struct sk_buff *list = skb_shinfo(skb)->frag_list;
 -
 -              for (; list && tlen; list = list->next) {
 -                      if (__skb_splice_bits(list, &offset, &tlen, &spd, sk))
 -                              break;
 -              }
 +      skb_walk_frags(skb, frag_iter) {
 +              if (!tlen)
 +                      break;
 +              if (__skb_splice_bits(frag_iter, &offset, &tlen, &spd, sk))
 +                      break;
        }
  
  done:
  
  int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len)
  {
 -      int i, copy;
        int start = skb_headlen(skb);
 +      struct sk_buff *frag_iter;
 +      int i, copy;
  
        if (offset > (int)skb->len - len)
                goto fault;
                start = end;
        }
  
 -      if (skb_shinfo(skb)->frag_list) {
 -              struct sk_buff *list = skb_shinfo(skb)->frag_list;
 +      skb_walk_frags(skb, frag_iter) {
 +              int end;
  
 -              for (; list; list = list->next) {
 -                      int end;
 -
 -                      WARN_ON(start > offset + len);
 -
 -                      end = start + list->len;
 -                      if ((copy = end - offset) > 0) {
 -                              if (copy > len)
 -                                      copy = len;
 -                              if (skb_store_bits(list, offset - start,
 -                                                 from, copy))
 -                                      goto fault;
 -                              if ((len -= copy) == 0)
 -                                      return 0;
 -                              offset += copy;
 -                              from += copy;
 -                      }
 -                      start = end;
 +              WARN_ON(start > offset + len);
 +
 +              end = start + frag_iter->len;
 +              if ((copy = end - offset) > 0) {
 +                      if (copy > len)
 +                              copy = len;
 +                      if (skb_store_bits(frag_iter, offset - start,
 +                                         from, copy))
 +                              goto fault;
 +                      if ((len -= copy) == 0)
 +                              return 0;
 +                      offset += copy;
 +                      from += copy;
                }
 +              start = end;
        }
        if (!len)
                return 0;
@@@ -1664,7 -1678,6 +1672,7 @@@ __wsum skb_checksum(const struct sk_buf
  {
        int start = skb_headlen(skb);
        int i, copy = start - offset;
 +      struct sk_buff *frag_iter;
        int pos = 0;
  
        /* Checksum header. */
                start = end;
        }
  
 -      if (skb_shinfo(skb)->frag_list) {
 -              struct sk_buff *list = skb_shinfo(skb)->frag_list;
 +      skb_walk_frags(skb, frag_iter) {
 +              int end;
  
 -              for (; list; list = list->next) {
 -                      int end;
 -
 -                      WARN_ON(start > offset + len);
 -
 -                      end = start + list->len;
 -                      if ((copy = end - offset) > 0) {
 -                              __wsum csum2;
 -                              if (copy > len)
 -                                      copy = len;
 -                              csum2 = skb_checksum(list, offset - start,
 -                                                   copy, 0);
 -                              csum = csum_block_add(csum, csum2, pos);
 -                              if ((len -= copy) == 0)
 -                                      return csum;
 -                              offset += copy;
 -                              pos    += copy;
 -                      }
 -                      start = end;
 +              WARN_ON(start > offset + len);
 +
 +              end = start + frag_iter->len;
 +              if ((copy = end - offset) > 0) {
 +                      __wsum csum2;
 +                      if (copy > len)
 +                              copy = len;
 +                      csum2 = skb_checksum(frag_iter, offset - start,
 +                                           copy, 0);
 +                      csum = csum_block_add(csum, csum2, pos);
 +                      if ((len -= copy) == 0)
 +                              return csum;
 +                      offset += copy;
 +                      pos    += copy;
                }
 +              start = end;
        }
        BUG_ON(len);
  
@@@ -1737,7 -1754,6 +1745,7 @@@ __wsum skb_copy_and_csum_bits(const str
  {
        int start = skb_headlen(skb);
        int i, copy = start - offset;
 +      struct sk_buff *frag_iter;
        int pos = 0;
  
        /* Copy header. */
                start = end;
        }
  
 -      if (skb_shinfo(skb)->frag_list) {
 -              struct sk_buff *list = skb_shinfo(skb)->frag_list;
 +      skb_walk_frags(skb, frag_iter) {
 +              __wsum csum2;
 +              int end;
  
 -              for (; list; list = list->next) {
 -                      __wsum csum2;
 -                      int end;
 -
 -                      WARN_ON(start > offset + len);
 -
 -                      end = start + list->len;
 -                      if ((copy = end - offset) > 0) {
 -                              if (copy > len)
 -                                      copy = len;
 -                              csum2 = skb_copy_and_csum_bits(list,
 -                                                             offset - start,
 -                                                             to, copy, 0);
 -                              csum = csum_block_add(csum, csum2, pos);
 -                              if ((len -= copy) == 0)
 -                                      return csum;
 -                              offset += copy;
 -                              to     += copy;
 -                              pos    += copy;
 -                      }
 -                      start = end;
 +              WARN_ON(start > offset + len);
 +
 +              end = start + frag_iter->len;
 +              if ((copy = end - offset) > 0) {
 +                      if (copy > len)
 +                              copy = len;
 +                      csum2 = skb_copy_and_csum_bits(frag_iter,
 +                                                     offset - start,
 +                                                     to, copy, 0);
 +                      csum = csum_block_add(csum, csum2, pos);
 +                      if ((len -= copy) == 0)
 +                              return csum;
 +                      offset += copy;
 +                      to     += copy;
 +                      pos    += copy;
                }
 +              start = end;
        }
        BUG_ON(len);
        return csum;
@@@ -2312,7 -2332,8 +2320,7 @@@ next_skb
                st->frag_data = NULL;
        }
  
 -      if (st->root_skb == st->cur_skb &&
 -          skb_shinfo(st->root_skb)->frag_list) {
 +      if (st->root_skb == st->cur_skb && skb_has_frags(st->root_skb)) {
                st->cur_skb = skb_shinfo(st->root_skb)->frag_list;
                st->frag_idx = 0;
                goto next_skb;
@@@ -2623,7 -2644,7 +2631,7 @@@ struct sk_buff *skb_segment(struct sk_b
                        } else
                                skb_get(fskb2);
  
 -                      BUG_ON(skb_shinfo(nskb)->frag_list);
 +                      SKB_FRAG_ASSERT(nskb);
                        skb_shinfo(nskb)->frag_list = fskb2;
                }
  
@@@ -2648,40 -2669,30 +2656,40 @@@ int skb_gro_receive(struct sk_buff **he
  {
        struct sk_buff *p = *head;
        struct sk_buff *nskb;
 +      struct skb_shared_info *skbinfo = skb_shinfo(skb);
 +      struct skb_shared_info *pinfo = skb_shinfo(p);
        unsigned int headroom;
        unsigned int len = skb_gro_len(skb);
 +      unsigned int offset = skb_gro_offset(skb);
 +      unsigned int headlen = skb_headlen(skb);
  
        if (p->len + len >= 65536)
                return -E2BIG;
  
 -      if (skb_shinfo(p)->frag_list)
 +      if (pinfo->frag_list)
                goto merge;
 -      else if (skb_headlen(skb) <= skb_gro_offset(skb)) {
 -              if (skb_shinfo(p)->nr_frags + skb_shinfo(skb)->nr_frags >
 -                  MAX_SKB_FRAGS)
 +      else if (headlen <= offset) {
 +              skb_frag_t *frag;
 +              skb_frag_t *frag2;
 +              int i = skbinfo->nr_frags;
 +              int nr_frags = pinfo->nr_frags + i;
 +
 +              offset -= headlen;
 +
 +              if (nr_frags > MAX_SKB_FRAGS)
                        return -E2BIG;
  
 -              skb_shinfo(skb)->frags[0].page_offset +=
 -                      skb_gro_offset(skb) - skb_headlen(skb);
 -              skb_shinfo(skb)->frags[0].size -=
 -                      skb_gro_offset(skb) - skb_headlen(skb);
 +              pinfo->nr_frags = nr_frags;
 +              skbinfo->nr_frags = 0;
  
 -              memcpy(skb_shinfo(p)->frags + skb_shinfo(p)->nr_frags,
 -                     skb_shinfo(skb)->frags,
 -                     skb_shinfo(skb)->nr_frags * sizeof(skb_frag_t));
 +              frag = pinfo->frags + nr_frags;
 +              frag2 = skbinfo->frags + i;
 +              do {
 +                      *--frag = *--frag2;
 +              } while (--i);
  
 -              skb_shinfo(p)->nr_frags += skb_shinfo(skb)->nr_frags;
 -              skb_shinfo(skb)->nr_frags = 0;
 +              frag->page_offset += offset;
 +              frag->size -= offset;
  
                skb->truesize -= skb->data_len;
                skb->len -= skb->data_len;
  
        *NAPI_GRO_CB(nskb) = *NAPI_GRO_CB(p);
        skb_shinfo(nskb)->frag_list = p;
 -      skb_shinfo(nskb)->gso_size = skb_shinfo(p)->gso_size;
 +      skb_shinfo(nskb)->gso_size = pinfo->gso_size;
        skb_header_release(p);
        nskb->prev = p;
  
        p = nskb;
  
  merge:
 -      if (skb_gro_offset(skb) > skb_headlen(skb)) {
 -              skb_shinfo(skb)->frags[0].page_offset +=
 -                      skb_gro_offset(skb) - skb_headlen(skb);
 -              skb_shinfo(skb)->frags[0].size -=
 -                      skb_gro_offset(skb) - skb_headlen(skb);
 -              skb_gro_reset_offset(skb);
 -              skb_gro_pull(skb, skb_headlen(skb));
 +      if (offset > headlen) {
 +              skbinfo->frags[0].page_offset += offset - headlen;
 +              skbinfo->frags[0].size -= offset - headlen;
 +              offset = headlen;
        }
  
 -      __skb_pull(skb, skb_gro_offset(skb));
 +      __skb_pull(skb, offset);
  
        p->prev->next = skb;
        p->prev = skb;
@@@ -2780,7 -2794,6 +2788,7 @@@ __skb_to_sgvec(struct sk_buff *skb, str
  {
        int start = skb_headlen(skb);
        int i, copy = start - offset;
 +      struct sk_buff *frag_iter;
        int elt = 0;
  
        if (copy > 0) {
                start = end;
        }
  
 -      if (skb_shinfo(skb)->frag_list) {
 -              struct sk_buff *list = skb_shinfo(skb)->frag_list;
 -
 -              for (; list; list = list->next) {
 -                      int end;
 +      skb_walk_frags(skb, frag_iter) {
 +              int end;
  
 -                      WARN_ON(start > offset + len);
 +              WARN_ON(start > offset + len);
  
 -                      end = start + list->len;
 -                      if ((copy = end - offset) > 0) {
 -                              if (copy > len)
 -                                      copy = len;
 -                              elt += __skb_to_sgvec(list, sg+elt, offset - start,
 -                                                    copy);
 -                              if ((len -= copy) == 0)
 -                                      return elt;
 -                              offset += copy;
 -                      }
 -                      start = end;
 +              end = start + frag_iter->len;
 +              if ((copy = end - offset) > 0) {
 +                      if (copy > len)
 +                              copy = len;
 +                      elt += __skb_to_sgvec(frag_iter, sg+elt, offset - start,
 +                                            copy);
 +                      if ((len -= copy) == 0)
 +                              return elt;
 +                      offset += copy;
                }
 +              start = end;
        }
        BUG_ON(len);
        return elt;
@@@ -2877,7 -2894,7 +2885,7 @@@ int skb_cow_data(struct sk_buff *skb, i
                return -ENOMEM;
  
        /* Easy case. Most of packets will go this way. */
 -      if (!skb_shinfo(skb)->frag_list) {
 +      if (!skb_has_frags(skb)) {
                /* A little of trouble, not enough of space for trailer.
                 * This should not happen, when stack is tuned to generate
                 * good frames. OK, on miss we reallocate and reserve even more
  
                if (skb1->next == NULL && tailbits) {
                        if (skb_shinfo(skb1)->nr_frags ||
 -                          skb_shinfo(skb1)->frag_list ||
 +                          skb_has_frags(skb1) ||
                            skb_tailroom(skb1) < tailbits)
                                ntail = tailbits + 128;
                }
                    skb_cloned(skb1) ||
                    ntail ||
                    skb_shinfo(skb1)->nr_frags ||
 -                  skb_shinfo(skb1)->frag_list) {
 +                  skb_has_frags(skb1)) {
                        struct sk_buff *skb2;
  
                        /* Fuck, we are miserable poor guys... */
@@@ -3007,12 -3024,12 +3015,12 @@@ EXPORT_SYMBOL_GPL(skb_tstamp_tx)
   */
  bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off)
  {
 -      if (unlikely(start > skb->len - 2) ||
 -          unlikely((int)start + off > skb->len - 2)) {
 +      if (unlikely(start > skb_headlen(skb)) ||
 +          unlikely((int)start + off > skb_headlen(skb) - 2)) {
                if (net_ratelimit())
                        printk(KERN_WARNING
                               "bad partial csum: csum=%u/%u len=%u\n",
 -                             start, off, skb->len);
 +                             start, off, skb_headlen(skb));
                return false;
        }
        skb->ip_summed = CHECKSUM_PARTIAL;
diff --combined net/core/sock.c
index 06e26b77ad9e78437948592eb1781539b6947703,ce72c0ae42459739835e7a26a97e965f53fe62c3..b0ba569bc97361dec5b2619a46ffbeab50331dc2
@@@ -155,7 -155,6 +155,7 @@@ static const char *af_family_key_string
    "sk_lock-27"       , "sk_lock-28"          , "sk_lock-AF_CAN"      ,
    "sk_lock-AF_TIPC"  , "sk_lock-AF_BLUETOOTH", "sk_lock-IUCV"        ,
    "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN"     , "sk_lock-AF_PHONET"   ,
 +  "sk_lock-AF_IEEE802154",
    "sk_lock-AF_MAX"
  };
  static const char *af_family_slock_key_strings[AF_MAX+1] = {
    "slock-27"       , "slock-28"          , "slock-AF_CAN"      ,
    "slock-AF_TIPC"  , "slock-AF_BLUETOOTH", "slock-AF_IUCV"     ,
    "slock-AF_RXRPC" , "slock-AF_ISDN"     , "slock-AF_PHONET"   ,
 +  "slock-AF_IEEE802154",
    "slock-AF_MAX"
  };
  static const char *af_family_clock_key_strings[AF_MAX+1] = {
    "clock-27"       , "clock-28"          , "clock-AF_CAN"      ,
    "clock-AF_TIPC"  , "clock-AF_BLUETOOTH", "clock-AF_IUCV"     ,
    "clock-AF_RXRPC" , "clock-AF_ISDN"     , "clock-AF_PHONET"   ,
 +  "clock-AF_IEEE802154",
    "clock-AF_MAX"
  };
  
@@@ -215,7 -212,6 +215,7 @@@ __u32 sysctl_rmem_default __read_mostl
  
  /* Maximal space eaten by iovec or ancilliary data plus some space */
  int sysctl_optmem_max __read_mostly = sizeof(unsigned long)*(2*UIO_MAXIOV+512);
 +EXPORT_SYMBOL(sysctl_optmem_max);
  
  static int sock_set_timeout(long *timeo_p, char __user *optval, int optlen)
  {
@@@ -448,7 -444,7 +448,7 @@@ static inline void sock_valbool_flag(st
  int sock_setsockopt(struct socket *sock, int level, int optname,
                    char __user *optval, int optlen)
  {
 -      struct sock *sk=sock->sk;
 +      struct sock *sk = sock->sk;
        int val;
        int valbool;
        struct linger ling;
        if (get_user(val, (int __user *)optval))
                return -EFAULT;
  
 -      valbool = val?1:0;
 +      valbool = val ? 1 : 0;
  
        lock_sock(sk);
  
 -      switch(optname) {
 +      switch (optname) {
        case SO_DEBUG:
 -              if (val && !capable(CAP_NET_ADMIN)) {
 +              if (val && !capable(CAP_NET_ADMIN))
                        ret = -EACCES;
 -              else
 +              else
                        sock_valbool_flag(sk, SOCK_DBG, valbool);
                break;
        case SO_REUSEADDR:
@@@ -586,7 -582,7 +586,7 @@@ set_rcvbuf
                        ret = -EINVAL;  /* 1003.1g */
                        break;
                }
 -              if (copy_from_user(&ling,optval,sizeof(ling))) {
 +              if (copy_from_user(&ling, optval, sizeof(ling))) {
                        ret = -EFAULT;
                        break;
                }
        case SO_MARK:
                if (!capable(CAP_NET_ADMIN))
                        ret = -EPERM;
 -              else {
 +              else
                        sk->sk_mark = val;
 -              }
                break;
  
                /* We implement the SO_SNDLOWAT etc to
        release_sock(sk);
        return ret;
  }
 +EXPORT_SYMBOL(sock_setsockopt);
  
  
  int sock_getsockopt(struct socket *sock, int level, int optname,
  
        memset(&v, 0, sizeof(v));
  
 -      switch(optname) {
 +      switch (optname) {
        case SO_DEBUG:
                v.val = sock_flag(sk, SOCK_DBG);
                break;
  
        case SO_ERROR:
                v.val = -sock_error(sk);
 -              if (v.val==0)
 +              if (v.val == 0)
                        v.val = xchg(&sk->sk_err_soft, 0);
                break;
  
                break;
  
        case SO_RCVTIMEO:
 -              lv=sizeof(struct timeval);
 +              lv = sizeof(struct timeval);
                if (sk->sk_rcvtimeo == MAX_SCHEDULE_TIMEOUT) {
                        v.tm.tv_sec = 0;
                        v.tm.tv_usec = 0;
                break;
  
        case SO_SNDTIMEO:
 -              lv=sizeof(struct timeval);
 +              lv = sizeof(struct timeval);
                if (sk->sk_sndtimeo == MAX_SCHEDULE_TIMEOUT) {
                        v.tm.tv_sec = 0;
                        v.tm.tv_usec = 0;
                break;
  
        case SO_SNDLOWAT:
 -              v.val=1;
 +              v.val = 1;
                break;
  
        case SO_PASSCRED:
@@@ -945,6 -941,8 +945,8 @@@ static struct sock *sk_prot_alloc(struc
                sk = kmalloc(prot->obj_size, priority);
  
        if (sk != NULL) {
+               kmemcheck_annotate_bitfield(sk, flags);
                if (security_sk_alloc(sk, family, priority))
                        goto out_free;
  
@@@ -1006,9 -1004,8 +1008,9 @@@ struct sock *sk_alloc(struct net *net, 
  
        return sk;
  }
 +EXPORT_SYMBOL(sk_alloc);
  
 -void sk_free(struct sock *sk)
 +static void __sk_free(struct sock *sk)
  {
        struct sk_filter *filter;
  
        sk_prot_free(sk->sk_prot_creator, sk);
  }
  
 +void sk_free(struct sock *sk)
 +{
 +      /*
 +       * We substract one from sk_wmem_alloc and can know if
 +       * some packets are still in some tx queue.
 +       * If not null, sock_wfree() will call __sk_free(sk) later
 +       */
 +      if (atomic_dec_and_test(&sk->sk_wmem_alloc))
 +              __sk_free(sk);
 +}
 +EXPORT_SYMBOL(sk_free);
 +
  /*
   * Last sock_put should drop referrence to sk->sk_net. It has already
   * been dropped in sk_change_net. Taking referrence to stopping namespace
@@@ -1082,10 -1067,7 +1084,10 @@@ struct sock *sk_clone(const struct soc
                newsk->sk_backlog.head  = newsk->sk_backlog.tail = NULL;
  
                atomic_set(&newsk->sk_rmem_alloc, 0);
 -              atomic_set(&newsk->sk_wmem_alloc, 0);
 +              /*
 +               * sk_wmem_alloc set to one (see sk_free() and sock_wfree())
 +               */
 +              atomic_set(&newsk->sk_wmem_alloc, 1);
                atomic_set(&newsk->sk_omem_alloc, 0);
                skb_queue_head_init(&newsk->sk_receive_queue);
                skb_queue_head_init(&newsk->sk_write_queue);
  out:
        return newsk;
  }
 -
  EXPORT_SYMBOL_GPL(sk_clone);
  
  void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
@@@ -1189,20 -1172,13 +1191,20 @@@ void __init sk_init(void
  void sock_wfree(struct sk_buff *skb)
  {
        struct sock *sk = skb->sk;
 +      int res;
  
        /* In case it might be waiting for more memory. */
 -      atomic_sub(skb->truesize, &sk->sk_wmem_alloc);
 +      res = atomic_sub_return(skb->truesize, &sk->sk_wmem_alloc);
        if (!sock_flag(sk, SOCK_USE_WRITE_QUEUE))
                sk->sk_write_space(sk);
 -      sock_put(sk);
 +      /*
 +       * if sk_wmem_alloc reached 0, we are last user and should
 +       * free this sock, as sk_free() call could not do it.
 +       */
 +      if (res == 0)
 +              __sk_free(sk);
  }
 +EXPORT_SYMBOL(sock_wfree);
  
  /*
   * Read buffer destructor automatically called from kfree_skb.
@@@ -1214,7 -1190,6 +1216,7 @@@ void sock_rfree(struct sk_buff *skb
        atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
        sk_mem_uncharge(skb->sk, skb->truesize);
  }
 +EXPORT_SYMBOL(sock_rfree);
  
  
  int sock_i_uid(struct sock *sk)
        read_unlock(&sk->sk_callback_lock);
        return uid;
  }
 +EXPORT_SYMBOL(sock_i_uid);
  
  unsigned long sock_i_ino(struct sock *sk)
  {
        read_unlock(&sk->sk_callback_lock);
        return ino;
  }
 +EXPORT_SYMBOL(sock_i_ino);
  
  /*
   * Allocate a skb from the socket's send buffer.
@@@ -1246,7 -1219,7 +1248,7 @@@ struct sk_buff *sock_wmalloc(struct soc
                             gfp_t priority)
  {
        if (force || atomic_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf) {
 -              struct sk_buff * skb = alloc_skb(size, priority);
 +              struct sk_buff *skb = alloc_skb(size, priority);
                if (skb) {
                        skb_set_owner_w(skb, sk);
                        return skb;
        }
        return NULL;
  }
 +EXPORT_SYMBOL(sock_wmalloc);
  
  /*
   * Allocate a skb from the socket's receive buffer.
@@@ -1291,7 -1263,6 +1293,7 @@@ void *sock_kmalloc(struct sock *sk, in
        }
        return NULL;
  }
 +EXPORT_SYMBOL(sock_kmalloc);
  
  /*
   * Free an option memory block.
@@@ -1301,12 -1272,11 +1303,12 @@@ void sock_kfree_s(struct sock *sk, voi
        kfree(mem);
        atomic_sub(size, &sk->sk_omem_alloc);
  }
 +EXPORT_SYMBOL(sock_kfree_s);
  
  /* It is almost wait_for_tcp_memory minus release_sock/lock_sock.
     I think, these locks should be removed for datagram sockets.
   */
 -static long sock_wait_for_wmem(struct sock * sk, long timeo)
 +static long sock_wait_for_wmem(struct sock *sk, long timeo)
  {
        DEFINE_WAIT(wait);
  
@@@ -1424,7 -1394,6 +1426,7 @@@ struct sk_buff *sock_alloc_send_skb(str
  {
        return sock_alloc_send_pskb(sk, size, 0, noblock, errcode);
  }
 +EXPORT_SYMBOL(sock_alloc_send_skb);
  
  static void __lock_sock(struct sock *sk)
  {
@@@ -1493,6 -1462,7 +1495,6 @@@ int sk_wait_data(struct sock *sk, long 
        finish_wait(sk->sk_sleep, &wait);
        return rc;
  }
 -
  EXPORT_SYMBOL(sk_wait_data);
  
  /**
@@@ -1573,6 -1543,7 +1575,6 @@@ suppress_allocation
        atomic_sub(amt, prot->memory_allocated);
        return 0;
  }
 -
  EXPORT_SYMBOL(__sk_mem_schedule);
  
  /**
@@@ -1591,6 -1562,7 +1593,6 @@@ void __sk_mem_reclaim(struct sock *sk
            (atomic_read(prot->memory_allocated) < prot->sysctl_mem[0]))
                *prot->memory_pressure = 0;
  }
 -
  EXPORT_SYMBOL(__sk_mem_reclaim);
  
  
@@@ -1605,92 -1577,78 +1607,92 @@@ int sock_no_bind(struct socket *sock, s
  {
        return -EOPNOTSUPP;
  }
 +EXPORT_SYMBOL(sock_no_bind);
  
  int sock_no_connect(struct socket *sock, struct sockaddr *saddr,
                    int len, int flags)
  {
        return -EOPNOTSUPP;
  }
 +EXPORT_SYMBOL(sock_no_connect);
  
  int sock_no_socketpair(struct socket *sock1, struct socket *sock2)
  {
        return -EOPNOTSUPP;
  }
 +EXPORT_SYMBOL(sock_no_socketpair);
  
  int sock_no_accept(struct socket *sock, struct socket *newsock, int flags)
  {
        return -EOPNOTSUPP;
  }
 +EXPORT_SYMBOL(sock_no_accept);
  
  int sock_no_getname(struct socket *sock, struct sockaddr *saddr,
                    int *len, int peer)
  {
        return -EOPNOTSUPP;
  }
 +EXPORT_SYMBOL(sock_no_getname);
  
 -unsigned int sock_no_poll(struct file * file, struct socket *sock, poll_table *pt)
 +unsigned int sock_no_poll(struct file *file, struct socket *sock, poll_table *pt)
  {
        return 0;
  }
 +EXPORT_SYMBOL(sock_no_poll);
  
  int sock_no_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
  {
        return -EOPNOTSUPP;
  }
 +EXPORT_SYMBOL(sock_no_ioctl);
  
  int sock_no_listen(struct socket *sock, int backlog)
  {
        return -EOPNOTSUPP;
  }
 +EXPORT_SYMBOL(sock_no_listen);
  
  int sock_no_shutdown(struct socket *sock, int how)
  {
        return -EOPNOTSUPP;
  }
 +EXPORT_SYMBOL(sock_no_shutdown);
  
  int sock_no_setsockopt(struct socket *sock, int level, int optname,
                    char __user *optval, int optlen)
  {
        return -EOPNOTSUPP;
  }
 +EXPORT_SYMBOL(sock_no_setsockopt);
  
  int sock_no_getsockopt(struct socket *sock, int level, int optname,
                    char __user *optval, int __user *optlen)
  {
        return -EOPNOTSUPP;
  }
 +EXPORT_SYMBOL(sock_no_getsockopt);
  
  int sock_no_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
                    size_t len)
  {
        return -EOPNOTSUPP;
  }
 +EXPORT_SYMBOL(sock_no_sendmsg);
  
  int sock_no_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
                    size_t len, int flags)
  {
        return -EOPNOTSUPP;
  }
 +EXPORT_SYMBOL(sock_no_recvmsg);
  
  int sock_no_mmap(struct file *file, struct socket *sock, struct vm_area_struct *vma)
  {
        /* Mirror missing mmap method error code */
        return -ENODEV;
  }
 +EXPORT_SYMBOL(sock_no_mmap);
  
  ssize_t sock_no_sendpage(struct socket *sock, struct page *page, int offset, size_t size, int flags)
  {
        kunmap(page);
        return res;
  }
 +EXPORT_SYMBOL(sock_no_sendpage);
  
  /*
   *    Default Socket Callbacks
@@@ -1768,7 -1725,6 +1770,7 @@@ void sk_send_sigurg(struct sock *sk
                if (send_sigurg(&sk->sk_socket->file->f_owner))
                        sk_wake_async(sk, SOCK_WAKE_URG, POLL_PRI);
  }
 +EXPORT_SYMBOL(sk_send_sigurg);
  
  void sk_reset_timer(struct sock *sk, struct timer_list* timer,
                    unsigned long expires)
        if (!mod_timer(timer, expires))
                sock_hold(sk);
  }
 -
  EXPORT_SYMBOL(sk_reset_timer);
  
  void sk_stop_timer(struct sock *sk, struct timer_list* timer)
        if (timer_pending(timer) && del_timer(timer))
                __sock_put(sk);
  }
 -
  EXPORT_SYMBOL(sk_stop_timer);
  
  void sock_init_data(struct socket *sock, struct sock *sk)
        sk->sk_stamp = ktime_set(-1L, 0);
  
        atomic_set(&sk->sk_refcnt, 1);
 +      atomic_set(&sk->sk_wmem_alloc, 1);
        atomic_set(&sk->sk_drops, 0);
  }
 +EXPORT_SYMBOL(sock_init_data);
  
  void lock_sock_nested(struct sock *sk, int subclass)
  {
        mutex_acquire(&sk->sk_lock.dep_map, subclass, 0, _RET_IP_);
        local_bh_enable();
  }
 -
  EXPORT_SYMBOL(lock_sock_nested);
  
  void release_sock(struct sock *sk)
@@@ -1940,6 -1897,7 +1942,6 @@@ int sock_common_getsockopt(struct socke
  
        return sk->sk_prot->getsockopt(sk, level, optname, optval, optlen);
  }
 -
  EXPORT_SYMBOL(sock_common_getsockopt);
  
  #ifdef CONFIG_COMPAT
@@@ -1969,6 -1927,7 +1971,6 @@@ int sock_common_recvmsg(struct kiocb *i
                msg->msg_namelen = addr_len;
        return err;
  }
 -
  EXPORT_SYMBOL(sock_common_recvmsg);
  
  /*
@@@ -1981,6 -1940,7 +1983,6 @@@ int sock_common_setsockopt(struct socke
  
        return sk->sk_prot->setsockopt(sk, level, optname, optval, optlen);
  }
 -
  EXPORT_SYMBOL(sock_common_setsockopt);
  
  #ifdef CONFIG_COMPAT
@@@ -2031,6 -1991,7 +2033,6 @@@ void sk_common_release(struct sock *sk
        sk_refcnt_debug_release(sk);
        sock_put(sk);
  }
 -
  EXPORT_SYMBOL(sk_common_release);
  
  static DEFINE_RWLOCK(proto_list_lock);
@@@ -2212,6 -2173,7 +2214,6 @@@ out_free_sock_slab
  out:
        return -ENOBUFS;
  }
 -
  EXPORT_SYMBOL(proto_register);
  
  void proto_unregister(struct proto *prot)
                prot->twsk_prot->twsk_slab = NULL;
        }
  }
 -
  EXPORT_SYMBOL(proto_unregister);
  
  #ifdef CONFIG_PROC_FS
@@@ -2363,3 -2326,33 +2365,3 @@@ static int __init proto_init(void
  subsys_initcall(proto_init);
  
  #endif /* PROC_FS */
 -
 -EXPORT_SYMBOL(sk_alloc);
 -EXPORT_SYMBOL(sk_free);
 -EXPORT_SYMBOL(sk_send_sigurg);
 -EXPORT_SYMBOL(sock_alloc_send_skb);
 -EXPORT_SYMBOL(sock_init_data);
 -EXPORT_SYMBOL(sock_kfree_s);
 -EXPORT_SYMBOL(sock_kmalloc);
 -EXPORT_SYMBOL(sock_no_accept);
 -EXPORT_SYMBOL(sock_no_bind);
 -EXPORT_SYMBOL(sock_no_connect);
 -EXPORT_SYMBOL(sock_no_getname);
 -EXPORT_SYMBOL(sock_no_getsockopt);
 -EXPORT_SYMBOL(sock_no_ioctl);
 -EXPORT_SYMBOL(sock_no_listen);
 -EXPORT_SYMBOL(sock_no_mmap);
 -EXPORT_SYMBOL(sock_no_poll);
 -EXPORT_SYMBOL(sock_no_recvmsg);
 -EXPORT_SYMBOL(sock_no_sendmsg);
 -EXPORT_SYMBOL(sock_no_sendpage);
 -EXPORT_SYMBOL(sock_no_setsockopt);
 -EXPORT_SYMBOL(sock_no_shutdown);
 -EXPORT_SYMBOL(sock_no_socketpair);
 -EXPORT_SYMBOL(sock_rfree);
 -EXPORT_SYMBOL(sock_setsockopt);
 -EXPORT_SYMBOL(sock_wfree);
 -EXPORT_SYMBOL(sock_wmalloc);
 -EXPORT_SYMBOL(sock_i_uid);
 -EXPORT_SYMBOL(sock_i_ino);
 -EXPORT_SYMBOL(sysctl_optmem_max);
index 68a8d892c711e44764e8856ef265dbb60f1f915b,03169fc848779fc0ee53bf3f76b05c5357c7f1bb..61283f9288250cc6b74d440abf7621947ed91313
@@@ -9,6 -9,7 +9,7 @@@
   */
  
  #include <linux/kernel.h>
+ #include <linux/kmemcheck.h>
  #include <net/inet_hashtables.h>
  #include <net/inet_timewait_sock.h>
  #include <net/ip.h>
@@@ -49,22 -50,19 +50,22 @@@ static void __inet_twsk_kill(struct ine
        inet_twsk_put(tw);
  }
  
 -void inet_twsk_put(struct inet_timewait_sock *tw)
 +static noinline void inet_twsk_free(struct inet_timewait_sock *tw)
  {
 -      if (atomic_dec_and_test(&tw->tw_refcnt)) {
 -              struct module *owner = tw->tw_prot->owner;
 -              twsk_destructor((struct sock *)tw);
 +      struct module *owner = tw->tw_prot->owner;
 +      twsk_destructor((struct sock *)tw);
  #ifdef SOCK_REFCNT_DEBUG
 -              printk(KERN_DEBUG "%s timewait_sock %p released\n",
 -                     tw->tw_prot->name, tw);
 +      pr_debug("%s timewait_sock %p released\n", tw->tw_prot->name, tw);
  #endif
 -              release_net(twsk_net(tw));
 -              kmem_cache_free(tw->tw_prot->twsk_prot->twsk_slab, tw);
 -              module_put(owner);
 -      }
 +      release_net(twsk_net(tw));
 +      kmem_cache_free(tw->tw_prot->twsk_prot->twsk_slab, tw);
 +      module_put(owner);
 +}
 +
 +void inet_twsk_put(struct inet_timewait_sock *tw)
 +{
 +      if (atomic_dec_and_test(&tw->tw_refcnt))
 +              inet_twsk_free(tw);
  }
  EXPORT_SYMBOL_GPL(inet_twsk_put);
  
@@@ -120,6 -118,8 +121,8 @@@ struct inet_timewait_sock *inet_twsk_al
        if (tw != NULL) {
                const struct inet_sock *inet = inet_sk(sk);
  
+               kmemcheck_annotate_bitfield(tw, flags);
                /* Give us an identity. */
                tw->tw_daddr        = inet->daddr;
                tw->tw_rcv_saddr    = inet->rcv_saddr;