Merge branch 'stable-4.8' of git://git.infradead.org/users/pcmoore/selinux into next
authorJames Morris <james.l.morris@oracle.com>
Thu, 7 Jul 2016 00:15:34 +0000 (10:15 +1000)
committerJames Morris <james.l.morris@oracle.com>
Thu, 7 Jul 2016 00:15:34 +0000 (10:15 +1000)
1  2 
include/net/ipv6.h
net/dccp/ipv6.c
net/ipv4/cipso_ipv4.c
net/ipv4/tcp_input.c
net/ipv6/Makefile
net/ipv6/af_inet6.c
net/ipv6/exthdrs.c
net/ipv6/ipv6_sockglue.c
net/ipv6/tcp_ipv6.c
security/selinux/hooks.c
security/smack/smack_lsm.c

diff --combined include/net/ipv6.h
index 11a045281948f07e638deb4515e60eaaf8c70774,24a5ebecaf1fae12fefb9fef35b380f056fc229c..8fed1cd78658a6e088b63f7703290cb02c1969b6
@@@ -121,21 -121,21 +121,21 @@@ struct frag_hdr 
  extern int sysctl_mld_max_msf;
  extern int sysctl_mld_qrv;
  
 -#define _DEVINC(net, statname, modifier, idev, field)                 \
 +#define _DEVINC(net, statname, mod, idev, field)                      \
  ({                                                                    \
        struct inet6_dev *_idev = (idev);                               \
        if (likely(_idev != NULL))                                      \
 -              SNMP_INC_STATS##modifier((_idev)->stats.statname, (field)); \
 -      SNMP_INC_STATS##modifier((net)->mib.statname##_statistics, (field));\
 +              mod##SNMP_INC_STATS64((_idev)->stats.statname, (field));\
 +      mod##SNMP_INC_STATS64((net)->mib.statname##_statistics, (field));\
  })
  
  /* per device counters are atomic_long_t */
 -#define _DEVINCATOMIC(net, statname, modifier, idev, field)           \
 +#define _DEVINCATOMIC(net, statname, mod, idev, field)                        \
  ({                                                                    \
        struct inet6_dev *_idev = (idev);                               \
        if (likely(_idev != NULL))                                      \
                SNMP_INC_STATS_ATOMIC_LONG((_idev)->stats.statname##dev, (field)); \
 -      SNMP_INC_STATS##modifier((net)->mib.statname##_statistics, (field));\
 +      mod##SNMP_INC_STATS((net)->mib.statname##_statistics, (field));\
  })
  
  /* per device and per net counters are atomic_long_t */
        SNMP_INC_STATS_ATOMIC_LONG((net)->mib.statname##_statistics, (field));\
  })
  
 -#define _DEVADD(net, statname, modifier, idev, field, val)            \
 +#define _DEVADD(net, statname, mod, idev, field, val)                 \
  ({                                                                    \
        struct inet6_dev *_idev = (idev);                               \
        if (likely(_idev != NULL))                                      \
 -              SNMP_ADD_STATS##modifier((_idev)->stats.statname, (field), (val)); \
 -      SNMP_ADD_STATS##modifier((net)->mib.statname##_statistics, (field), (val));\
 +              mod##SNMP_ADD_STATS((_idev)->stats.statname, (field), (val)); \
 +      mod##SNMP_ADD_STATS((net)->mib.statname##_statistics, (field), (val));\
  })
  
 -#define _DEVUPD(net, statname, modifier, idev, field, val)            \
 +#define _DEVUPD(net, statname, mod, idev, field, val)                 \
  ({                                                                    \
        struct inet6_dev *_idev = (idev);                               \
        if (likely(_idev != NULL))                                      \
 -              SNMP_UPD_PO_STATS##modifier((_idev)->stats.statname, field, (val)); \
 -      SNMP_UPD_PO_STATS##modifier((net)->mib.statname##_statistics, field, (val));\
 +              mod##SNMP_UPD_PO_STATS((_idev)->stats.statname, field, (val)); \
 +      mod##SNMP_UPD_PO_STATS((net)->mib.statname##_statistics, field, (val));\
  })
  
  /* MIBs */
  
  #define IP6_INC_STATS(net, idev,field)                \
 -              _DEVINC(net, ipv6, 64, idev, field)
 -#define IP6_INC_STATS_BH(net, idev,field)     \
 -              _DEVINC(net, ipv6, 64_BH, idev, field)
 +              _DEVINC(net, ipv6, , idev, field)
 +#define __IP6_INC_STATS(net, idev,field)      \
 +              _DEVINC(net, ipv6, __, idev, field)
  #define IP6_ADD_STATS(net, idev,field,val)    \
 -              _DEVADD(net, ipv6, 64, idev, field, val)
 -#define IP6_ADD_STATS_BH(net, idev,field,val) \
 -              _DEVADD(net, ipv6, 64_BH, idev, field, val)
 +              _DEVADD(net, ipv6, , idev, field, val)
 +#define __IP6_ADD_STATS(net, idev,field,val)  \
 +              _DEVADD(net, ipv6, __, idev, field, val)
  #define IP6_UPD_PO_STATS(net, idev,field,val)   \
 -              _DEVUPD(net, ipv6, 64, idev, field, val)
 -#define IP6_UPD_PO_STATS_BH(net, idev,field,val)   \
 -              _DEVUPD(net, ipv6, 64_BH, idev, field, val)
 +              _DEVUPD(net, ipv6, , idev, field, val)
 +#define __IP6_UPD_PO_STATS(net, idev,field,val)   \
 +              _DEVUPD(net, ipv6, __, idev, field, val)
  #define ICMP6_INC_STATS(net, idev, field)     \
                _DEVINCATOMIC(net, icmpv6, , idev, field)
 -#define ICMP6_INC_STATS_BH(net, idev, field)  \
 -              _DEVINCATOMIC(net, icmpv6, _BH, idev, field)
 +#define __ICMP6_INC_STATS(net, idev, field)   \
 +              _DEVINCATOMIC(net, icmpv6, __, idev, field)
  
  #define ICMP6MSGOUT_INC_STATS(net, idev, field)               \
        _DEVINC_ATOMIC_ATOMIC(net, icmpv6msg, idev, field +256)
 -#define ICMP6MSGOUT_INC_STATS_BH(net, idev, field)    \
 -      _DEVINC_ATOMIC_ATOMIC(net, icmpv6msg, idev, field +256)
 -#define ICMP6MSGIN_INC_STATS_BH(net, idev, field)     \
 +#define ICMP6MSGIN_INC_STATS(net, idev, field)        \
        _DEVINC_ATOMIC_ATOMIC(net, icmpv6msg, idev, field)
  
  struct ip6_ra_chain {
@@@ -251,13 -253,6 +251,13 @@@ struct ipv6_fl_socklist 
        struct rcu_head                 rcu;
  };
  
 +struct ipcm6_cookie {
 +      __s16 hlimit;
 +      __s16 tclass;
 +      __s8  dontfrag;
 +      struct ipv6_txoptions *opt;
 +};
 +
  static inline struct ipv6_txoptions *txopt_get(const struct ipv6_pinfo *np)
  {
        struct ipv6_txoptions *opt;
@@@ -313,11 -308,19 +313,19 @@@ struct ipv6_txoptions *ipv6_renew_optio
                                          int newtype,
                                          struct ipv6_opt_hdr __user *newopt,
                                          int newoptlen);
+ struct ipv6_txoptions *
+ ipv6_renew_options_kern(struct sock *sk,
+                       struct ipv6_txoptions *opt,
+                       int newtype,
+                       struct ipv6_opt_hdr *newopt,
+                       int newoptlen);
  struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
                                          struct ipv6_txoptions *opt);
  
  bool ipv6_opt_accepted(const struct sock *sk, const struct sk_buff *skb,
                       const struct inet6_skb_parm *opt);
+ struct ipv6_txoptions *ipv6_update_options(struct sock *sk,
+                                          struct ipv6_txoptions *opt);
  
  static inline bool ipv6_accept_ra(struct inet6_dev *idev)
  {
@@@ -870,10 -873,9 +878,10 @@@ int ip6_find_1stfragopt(struct sk_buff 
  int ip6_append_data(struct sock *sk,
                    int getfrag(void *from, char *to, int offset, int len,
                                int odd, struct sk_buff *skb),
 -                  void *from, int length, int transhdrlen, int hlimit,
 -                  int tclass, struct ipv6_txoptions *opt, struct flowi6 *fl6,
 -                  struct rt6_info *rt, unsigned int flags, int dontfrag);
 +                  void *from, int length, int transhdrlen,
 +                  struct ipcm6_cookie *ipc6, struct flowi6 *fl6,
 +                  struct rt6_info *rt, unsigned int flags,
 +                  const struct sockcm_cookie *sockc);
  
  int ip6_push_pending_frames(struct sock *sk);
  
@@@ -888,9 -890,9 +896,9 @@@ struct sk_buff *ip6_make_skb(struct soc
                             int getfrag(void *from, char *to, int offset,
                                         int len, int odd, struct sk_buff *skb),
                             void *from, int length, int transhdrlen,
 -                           int hlimit, int tclass, struct ipv6_txoptions *opt,
 -                           struct flowi6 *fl6, struct rt6_info *rt,
 -                           unsigned int flags, int dontfrag);
 +                           struct ipcm6_cookie *ipc6, struct flowi6 *fl6,
 +                           struct rt6_info *rt, unsigned int flags,
 +                           const struct sockcm_cookie *sockc);
  
  static inline struct sk_buff *ip6_finish_skb(struct sock *sk)
  {
@@@ -943,7 -945,7 +951,7 @@@ enum 
  int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, int target,
                  unsigned short *fragoff, int *fragflg);
  
- int ipv6_find_tlv(struct sk_buff *skb, int offset, int type);
+ int ipv6_find_tlv(const struct sk_buff *skb, int offset, int type);
  
  struct in6_addr *fl6_update_dst(struct flowi6 *fl6,
                                const struct ipv6_txoptions *opt,
@@@ -965,8 -967,6 +973,8 @@@ int compat_ipv6_getsockopt(struct sock 
  int ip6_datagram_connect(struct sock *sk, struct sockaddr *addr, int addr_len);
  int ip6_datagram_connect_v6_only(struct sock *sk, struct sockaddr *addr,
                                 int addr_len);
 +int ip6_datagram_dst_update(struct sock *sk, bool fix_sk_saddr);
 +void ip6_datagram_release_cb(struct sock *sk);
  
  int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len,
                    int *addr_len);
diff --combined net/dccp/ipv6.c
index d176f4e66369a399f5fe8a440eb864dbac9c7542,3381748bd0f3ba00526207a4f3598a1ddf753a9e..01bacf5bc027430345a1ed450725b033476a0914
@@@ -80,8 -80,8 +80,8 @@@ static void dccp_v6_err(struct sk_buff 
  
        if (skb->len < offset + sizeof(*dh) ||
            skb->len < offset + __dccp_basic_hdr_len(dh)) {
 -              ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev),
 -                                 ICMP6_MIB_INERRORS);
 +              __ICMP6_INC_STATS(net, __in6_dev_get(skb->dev),
 +                                ICMP6_MIB_INERRORS);
                return;
        }
  
@@@ -91,8 -91,8 +91,8 @@@
                                        inet6_iif(skb));
  
        if (!sk) {
 -              ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev),
 -                                 ICMP6_MIB_INERRORS);
 +              __ICMP6_INC_STATS(net, __in6_dev_get(skb->dev),
 +                                ICMP6_MIB_INERRORS);
                return;
        }
  
  
        bh_lock_sock(sk);
        if (sock_owned_by_user(sk))
 -              NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS);
 +              __NET_INC_STATS(net, LINUX_MIB_LOCKDROPPEDICMPS);
  
        if (sk->sk_state == DCCP_CLOSED)
                goto out;
        dp = dccp_sk(sk);
        if ((1 << sk->sk_state) & ~(DCCPF_REQUESTING | DCCPF_LISTEN) &&
            !between48(seq, dp->dccps_awl, dp->dccps_awh)) {
 -              NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
 +              __NET_INC_STATS(net, LINUX_MIB_OUTOFWINDOWICMPS);
                goto out;
        }
  
        case DCCP_RESPOND:  /* Cannot happen.
                               It can, it SYNs are crossed. --ANK */
                if (!sock_owned_by_user(sk)) {
 -                      DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS);
 +                      __DCCP_INC_STATS(DCCP_MIB_ATTEMPTFAILS);
                        sk->sk_err = err;
                        /*
                         * Wake people up to see the error
@@@ -216,14 -216,17 +216,17 @@@ static int dccp_v6_send_response(const 
        skb = dccp_make_response(sk, dst, req);
        if (skb != NULL) {
                struct dccp_hdr *dh = dccp_hdr(skb);
+               struct ipv6_txoptions *opt;
  
                dh->dccph_checksum = dccp_v6_csum_finish(skb,
                                                         &ireq->ir_v6_loc_addr,
                                                         &ireq->ir_v6_rmt_addr);
                fl6.daddr = ireq->ir_v6_rmt_addr;
                rcu_read_lock();
-               err = ip6_xmit(sk, skb, &fl6, rcu_dereference(np->opt),
-                              np->tclass);
+               opt = ireq->ipv6_opt;
+               if (!opt)
+                       opt = rcu_dereference(np->opt);
+               err = ip6_xmit(sk, skb, &fl6, opt, np->tclass);
                rcu_read_unlock();
                err = net_xmit_eval(err);
        }
@@@ -236,6 -239,7 +239,7 @@@ done
  static void dccp_v6_reqsk_destructor(struct request_sock *req)
  {
        dccp_feat_list_purge(&dccp_rsk(req)->dreq_featneg);
+       kfree(inet_rsk(req)->ipv6_opt);
        kfree_skb(inet_rsk(req)->pktopts);
  }
  
@@@ -277,8 -281,8 +281,8 @@@ static void dccp_v6_ctl_send_reset(cons
        if (!IS_ERR(dst)) {
                skb_dst_set(skb, dst);
                ip6_xmit(ctl_sk, skb, &fl6, NULL, 0);
 -              DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
 -              DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS);
 +              DCCP_INC_STATS(DCCP_MIB_OUTSEGS);
 +              DCCP_INC_STATS(DCCP_MIB_OUTRSTS);
                return;
        }
  
@@@ -378,7 -382,7 +382,7 @@@ static int dccp_v6_conn_request(struct 
  drop_and_free:
        reqsk_free(req);
  drop:
 -      DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS);
 +      __DCCP_INC_STATS(DCCP_MIB_ATTEMPTFAILS);
        return -1;
  }
  
@@@ -494,7 -498,9 +498,9 @@@ static struct sock *dccp_v6_request_rec
         * Yes, keeping reference count would be much more clever, but we make
         * one more one thing there: reattach optmem to newsk.
         */
-       opt = rcu_dereference(np->opt);
+       opt = ireq->ipv6_opt;
+       if (!opt)
+               opt = rcu_dereference(np->opt);
        if (opt) {
                opt = ipv6_dup_options(newsk, opt);
                RCU_INIT_POINTER(newnp->opt, opt);
        return newsk;
  
  out_overflow:
 -      NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
 +      __NET_INC_STATS(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
  out_nonewsk:
        dst_release(dst);
  out:
 -      NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
 +      __NET_INC_STATS(sock_net(sk), LINUX_MIB_LISTENDROPS);
        return NULL;
  }
  
@@@ -642,7 -648,6 +648,7 @@@ discard
  static int dccp_v6_rcv(struct sk_buff *skb)
  {
        const struct dccp_hdr *dh;
 +      bool refcounted;
        struct sock *sk;
        int min_cov;
  
  lookup:
        sk = __inet6_lookup_skb(&dccp_hashinfo, skb, __dccp_hdr_len(dh),
                                dh->dccph_sport, dh->dccph_dport,
 -                              inet6_iif(skb));
 +                              inet6_iif(skb), &refcounted);
        if (!sk) {
                dccp_pr_debug("failed to look up flow ID in table and "
                              "get corresponding socket\n");
                        goto lookup;
                }
                sock_hold(sk);
 +              refcounted = true;
                nsk = dccp_check_req(sk, skb, req);
                if (!nsk) {
                        reqsk_put(req);
@@@ -754,8 -758,7 +760,8 @@@ discard_it
        return 0;
  
  discard_and_relse:
 -      sock_put(sk);
 +      if (refcounted)
 +              sock_put(sk);
        goto discard_it;
  }
  
@@@ -868,7 -871,7 +874,7 @@@ static int dccp_v6_connect(struct sock 
        fl6.fl6_sport = inet->inet_sport;
        security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
  
 -      opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk));
 +      opt = rcu_dereference_protected(np->opt, lockdep_sock_is_held(sk));
        final_p = fl6_update_dst(&fl6, opt, &final);
  
        dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
diff --combined net/ipv4/cipso_ipv4.c
index 40d6b87713a132666298cc8e8d875da6a6a1a387,d710d4eb6a2909743a3bab7b73269290b95ed368..72d6f056d863603c959e1d04b9f863909a37c758
@@@ -134,76 -134,6 +134,6 @@@ int cipso_v4_rbm_strictvalid = 1
   * Helper Functions
   */
  
- /**
-  * cipso_v4_bitmap_walk - Walk a bitmap looking for a bit
-  * @bitmap: the bitmap
-  * @bitmap_len: length in bits
-  * @offset: starting offset
-  * @state: if non-zero, look for a set (1) bit else look for a cleared (0) bit
-  *
-  * Description:
-  * Starting at @offset, walk the bitmap from left to right until either the
-  * desired bit is found or we reach the end.  Return the bit offset, -1 if
-  * not found, or -2 if error.
-  */
- static int cipso_v4_bitmap_walk(const unsigned char *bitmap,
-                               u32 bitmap_len,
-                               u32 offset,
-                               u8 state)
- {
-       u32 bit_spot;
-       u32 byte_offset;
-       unsigned char bitmask;
-       unsigned char byte;
-       /* gcc always rounds to zero when doing integer division */
-       byte_offset = offset / 8;
-       byte = bitmap[byte_offset];
-       bit_spot = offset;
-       bitmask = 0x80 >> (offset % 8);
-       while (bit_spot < bitmap_len) {
-               if ((state && (byte & bitmask) == bitmask) ||
-                   (state == 0 && (byte & bitmask) == 0))
-                       return bit_spot;
-               bit_spot++;
-               bitmask >>= 1;
-               if (bitmask == 0) {
-                       byte = bitmap[++byte_offset];
-                       bitmask = 0x80;
-               }
-       }
-       return -1;
- }
- /**
-  * cipso_v4_bitmap_setbit - Sets a single bit in a bitmap
-  * @bitmap: the bitmap
-  * @bit: the bit
-  * @state: if non-zero, set the bit (1) else clear the bit (0)
-  *
-  * Description:
-  * Set a single bit in the bitmask.  Returns zero on success, negative values
-  * on error.
-  */
- static void cipso_v4_bitmap_setbit(unsigned char *bitmap,
-                                  u32 bit,
-                                  u8 state)
- {
-       u32 byte_spot;
-       u8 bitmask;
-       /* gcc always rounds to zero when doing integer division */
-       byte_spot = bit / 8;
-       bitmask = 0x80 >> (bit % 8);
-       if (state)
-               bitmap[byte_spot] |= bitmask;
-       else
-               bitmap[byte_spot] &= ~bitmask;
- }
  /**
   * cipso_v4_cache_entry_free - Frees a cache entry
   * @entry: the entry to free
@@@ -840,10 -770,10 +770,10 @@@ static int cipso_v4_map_cat_rbm_valid(c
                cipso_cat_size = doi_def->map.std->cat.cipso_size;
                cipso_array = doi_def->map.std->cat.cipso;
                for (;;) {
-                       cat = cipso_v4_bitmap_walk(bitmap,
-                                                  bitmap_len_bits,
-                                                  cat + 1,
-                                                  1);
+                       cat = netlbl_bitmap_walk(bitmap,
+                                                bitmap_len_bits,
+                                                cat + 1,
+                                                1);
                        if (cat < 0)
                                break;
                        if (cat >= cipso_cat_size ||
@@@ -909,7 -839,7 +839,7 @@@ static int cipso_v4_map_cat_rbm_hton(co
                }
                if (net_spot >= net_clen_bits)
                        return -ENOSPC;
-               cipso_v4_bitmap_setbit(net_cat, net_spot, 1);
+               netlbl_bitmap_setbit(net_cat, net_spot, 1);
  
                if (net_spot > net_spot_max)
                        net_spot_max = net_spot;
@@@ -951,10 -881,10 +881,10 @@@ static int cipso_v4_map_cat_rbm_ntoh(co
        }
  
        for (;;) {
-               net_spot = cipso_v4_bitmap_walk(net_cat,
-                                               net_clen_bits,
-                                               net_spot + 1,
-                                               1);
+               net_spot = netlbl_bitmap_walk(net_cat,
+                                             net_clen_bits,
+                                             net_spot + 1,
+                                             1);
                if (net_spot < 0) {
                        if (net_spot == -2)
                                return -EFAULT;
@@@ -1933,8 -1863,7 +1863,8 @@@ int cipso_v4_sock_setattr(struct sock *
  
        sk_inet = inet_sk(sk);
  
 -      old = rcu_dereference_protected(sk_inet->inet_opt, sock_owned_by_user(sk));
 +      old = rcu_dereference_protected(sk_inet->inet_opt,
 +                                      lockdep_sock_is_held(sk));
        if (sk_inet->is_icsk) {
                sk_conn = inet_csk(sk);
                if (old)
diff --combined net/ipv4/tcp_input.c
index d6c8f4cd080001a527f7c137021cc6a3f3604344,071174c13bf95e195844a63b0f8b5bb84e05b662..d663d5071d2630c5cd3279ed04b63a6d79101f98
@@@ -869,7 -869,7 +869,7 @@@ static void tcp_update_reordering(struc
                else
                        mib_idx = LINUX_MIB_TCPSACKREORDER;
  
 -              NET_INC_STATS_BH(sock_net(sk), mib_idx);
 +              NET_INC_STATS(sock_net(sk), mib_idx);
  #if FASTRETRANS_DEBUG > 1
                pr_debug("Disorder%d %d %u f%u s%u rr%d\n",
                         tp->rx_opt.sack_ok, inet_csk(sk)->icsk_ca_state,
@@@ -1062,7 -1062,7 +1062,7 @@@ static bool tcp_check_dsack(struct soc
        if (before(start_seq_0, TCP_SKB_CB(ack_skb)->ack_seq)) {
                dup_sack = true;
                tcp_dsack_seen(tp);
 -              NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPDSACKRECV);
 +              NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPDSACKRECV);
        } else if (num_sacks > 1) {
                u32 end_seq_1 = get_unaligned_be32(&sp[1].end_seq);
                u32 start_seq_1 = get_unaligned_be32(&sp[1].start_seq);
                    !before(start_seq_0, start_seq_1)) {
                        dup_sack = true;
                        tcp_dsack_seen(tp);
 -                      NET_INC_STATS_BH(sock_net(sk),
 +                      NET_INC_STATS(sock_net(sk),
                                        LINUX_MIB_TCPDSACKOFORECV);
                }
        }
@@@ -1289,7 -1289,7 +1289,7 @@@ static bool tcp_shifted_skb(struct soc
  
        if (skb->len > 0) {
                BUG_ON(!tcp_skb_pcount(skb));
 -              NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SACKSHIFTED);
 +              NET_INC_STATS(sock_net(sk), LINUX_MIB_SACKSHIFTED);
                return false;
        }
  
        }
  
        TCP_SKB_CB(prev)->tcp_flags |= TCP_SKB_CB(skb)->tcp_flags;
 +      TCP_SKB_CB(prev)->eor = TCP_SKB_CB(skb)->eor;
        if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN)
                TCP_SKB_CB(prev)->end_seq++;
  
        if (skb == tcp_highest_sack(sk))
                tcp_advance_highest_sack(sk, skb);
  
 +      tcp_skb_collapse_tstamp(prev, skb);
        tcp_unlink_write_queue(skb, sk);
        sk_wmem_free_skb(sk, skb);
  
 -      NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SACKMERGED);
 +      NET_INC_STATS(sock_net(sk), LINUX_MIB_SACKMERGED);
  
        return true;
  }
@@@ -1369,9 -1367,6 +1369,9 @@@ static struct sk_buff *tcp_shift_skb_da
        if ((TCP_SKB_CB(prev)->sacked & TCPCB_TAGBITS) != TCPCB_SACKED_ACKED)
                goto fallback;
  
 +      if (!tcp_skb_can_collapse_to(prev))
 +              goto fallback;
 +
        in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq) &&
                  !before(end_seq, TCP_SKB_CB(skb)->end_seq);
  
@@@ -1473,7 -1468,7 +1473,7 @@@ noop
        return skb;
  
  fallback:
 -      NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SACKSHIFTFALLBACK);
 +      NET_INC_STATS(sock_net(sk), LINUX_MIB_SACKSHIFTFALLBACK);
        return NULL;
  }
  
@@@ -1661,7 -1656,7 +1661,7 @@@ tcp_sacktag_write_queue(struct sock *sk
                                mib_idx = LINUX_MIB_TCPSACKDISCARD;
                        }
  
 -                      NET_INC_STATS_BH(sock_net(sk), mib_idx);
 +                      NET_INC_STATS(sock_net(sk), mib_idx);
                        if (i == 0)
                                first_sack_index = -1;
                        continue;
@@@ -1913,7 -1908,7 +1913,7 @@@ void tcp_enter_loss(struct sock *sk
        skb = tcp_write_queue_head(sk);
        is_reneg = skb && (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED);
        if (is_reneg) {
 -              NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSACKRENEGING);
 +              NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPSACKRENEGING);
                tp->sacked_out = 0;
                tp->fackets_out = 0;
        }
@@@ -2257,6 -2252,16 +2257,6 @@@ static void tcp_update_scoreboard(struc
        }
  }
  
 -/* CWND moderation, preventing bursts due to too big ACKs
 - * in dubious situations.
 - */
 -static inline void tcp_moderate_cwnd(struct tcp_sock *tp)
 -{
 -      tp->snd_cwnd = min(tp->snd_cwnd,
 -                         tcp_packets_in_flight(tp) + tcp_max_burst(tp));
 -      tp->snd_cwnd_stamp = tcp_time_stamp;
 -}
 -
  static bool tcp_tsopt_ecr_before(const struct tcp_sock *tp, u32 when)
  {
        return tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr &&
@@@ -2399,12 -2404,13 +2399,12 @@@ static bool tcp_try_undo_recovery(struc
                else
                        mib_idx = LINUX_MIB_TCPFULLUNDO;
  
 -              NET_INC_STATS_BH(sock_net(sk), mib_idx);
 +              NET_INC_STATS(sock_net(sk), mib_idx);
        }
        if (tp->snd_una == tp->high_seq && tcp_is_reno(tp)) {
                /* Hold old state until something *above* high_seq
                 * is ACKed. For Reno it is MUST to prevent false
                 * fast retransmits (RFC2582). SACK TCP is safe. */
 -              tcp_moderate_cwnd(tp);
                if (!tcp_any_retrans_done(sk))
                        tp->retrans_stamp = 0;
                return true;
@@@ -2421,7 -2427,7 +2421,7 @@@ static bool tcp_try_undo_dsack(struct s
        if (tp->undo_marker && !tp->undo_retrans) {
                DBGUNDO(sk, "D-SACK");
                tcp_undo_cwnd_reduction(sk, false);
 -              NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPDSACKUNDO);
 +              NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPDSACKUNDO);
                return true;
        }
        return false;
@@@ -2436,10 -2442,10 +2436,10 @@@ static bool tcp_try_undo_loss(struct so
                tcp_undo_cwnd_reduction(sk, true);
  
                DBGUNDO(sk, "partial loss");
 -              NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPLOSSUNDO);
 +              NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPLOSSUNDO);
                if (frto_undo)
 -                      NET_INC_STATS_BH(sock_net(sk),
 -                                       LINUX_MIB_TCPSPURIOUSRTOS);
 +                      NET_INC_STATS(sock_net(sk),
 +                                      LINUX_MIB_TCPSPURIOUSRTOS);
                inet_csk(sk)->icsk_retransmits = 0;
                if (frto_undo || tcp_is_sack(tp))
                        tcp_set_ca_state(sk, TCP_CA_Open);
@@@ -2563,7 -2569,7 +2563,7 @@@ static void tcp_mtup_probe_failed(struc
  
        icsk->icsk_mtup.search_high = icsk->icsk_mtup.probe_size - 1;
        icsk->icsk_mtup.probe_size = 0;
 -      NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPMTUPFAIL);
 +      NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMTUPFAIL);
  }
  
  static void tcp_mtup_probe_success(struct sock *sk)
        icsk->icsk_mtup.search_low = icsk->icsk_mtup.probe_size;
        icsk->icsk_mtup.probe_size = 0;
        tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
 -      NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPMTUPSUCCESS);
 +      NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMTUPSUCCESS);
  }
  
  /* Do a simple retransmit without using the backoff mechanisms in
@@@ -2647,7 -2653,7 +2647,7 @@@ static void tcp_enter_recovery(struct s
        else
                mib_idx = LINUX_MIB_TCPSACKRECOVERY;
  
 -      NET_INC_STATS_BH(sock_net(sk), mib_idx);
 +      NET_INC_STATS(sock_net(sk), mib_idx);
  
        tp->prior_ssthresh = 0;
        tcp_init_undo(tp);
@@@ -2740,7 -2746,7 +2740,7 @@@ static bool tcp_try_undo_partial(struc
  
                DBGUNDO(sk, "partial recovery");
                tcp_undo_cwnd_reduction(sk, true);
 -              NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPPARTIALUNDO);
 +              NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPPARTIALUNDO);
                tcp_try_keep_open(sk);
                return true;
        }
@@@ -3087,12 -3093,12 +3087,12 @@@ static void tcp_ack_tstamp(struct sock 
        const struct skb_shared_info *shinfo;
  
        /* Avoid cache line misses to get skb_shinfo() and shinfo->tx_flags */
 -      if (likely(!(sk->sk_tsflags & SOF_TIMESTAMPING_TX_ACK)))
 +      if (likely(!TCP_SKB_CB(skb)->txstamp_ack))
                return;
  
        shinfo = skb_shinfo(skb);
 -      if ((shinfo->tx_flags & SKBTX_ACK_TSTAMP) &&
 -          between(shinfo->tskey, prior_snd_una, tcp_sk(sk)->snd_una - 1))
 +      if (!before(shinfo->tskey, prior_snd_una) &&
 +          before(shinfo->tskey, tcp_sk(sk)->snd_una))
                __skb_tstamp_tx(skb, NULL, sk, SCM_TSTAMP_ACK);
  }
  
@@@ -3248,12 -3254,8 +3248,12 @@@ static int tcp_clean_rtx_queue(struct s
                tcp_rearm_rto(sk);
        }
  
 -      if (icsk->icsk_ca_ops->pkts_acked)
 -              icsk->icsk_ca_ops->pkts_acked(sk, pkts_acked, ca_rtt_us);
 +      if (icsk->icsk_ca_ops->pkts_acked) {
 +              struct ack_sample sample = { .pkts_acked = pkts_acked,
 +                                           .rtt_us = ca_rtt_us };
 +
 +              icsk->icsk_ca_ops->pkts_acked(sk, &sample);
 +      }
  
  #if FASTRETRANS_DEBUG > 0
        WARN_ON((int)tp->sacked_out < 0);
@@@ -3359,10 -3361,9 +3359,10 @@@ static void tcp_snd_una_update(struct t
  {
        u32 delta = ack - tp->snd_una;
  
 -      u64_stats_update_begin(&tp->syncp);
 +      sock_owned_by_me((struct sock *)tp);
 +      u64_stats_update_begin_raw(&tp->syncp);
        tp->bytes_acked += delta;
 -      u64_stats_update_end(&tp->syncp);
 +      u64_stats_update_end_raw(&tp->syncp);
        tp->snd_una = ack;
  }
  
@@@ -3371,10 -3372,9 +3371,10 @@@ static void tcp_rcv_nxt_update(struct t
  {
        u32 delta = seq - tp->rcv_nxt;
  
 -      u64_stats_update_begin(&tp->syncp);
 +      sock_owned_by_me((struct sock *)tp);
 +      u64_stats_update_begin_raw(&tp->syncp);
        tp->bytes_received += delta;
 -      u64_stats_update_end(&tp->syncp);
 +      u64_stats_update_end_raw(&tp->syncp);
        tp->rcv_nxt = seq;
  }
  
@@@ -3440,7 -3440,7 +3440,7 @@@ bool tcp_oow_rate_limited(struct net *n
                s32 elapsed = (s32)(tcp_time_stamp - *last_oow_ack_time);
  
                if (0 <= elapsed && elapsed < sysctl_tcp_invalid_ratelimit) {
 -                      NET_INC_STATS_BH(net, mib_idx);
 +                      NET_INC_STATS(net, mib_idx);
                        return true;    /* rate-limited: don't send yet! */
                }
        }
@@@ -3473,7 -3473,7 +3473,7 @@@ static void tcp_send_challenge_ack(stru
                challenge_count = 0;
        }
        if (++challenge_count <= sysctl_tcp_challenge_ack_limit) {
 -              NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK);
 +              NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK);
                tcp_send_ack(sk);
        }
  }
@@@ -3522,8 -3522,8 +3522,8 @@@ static void tcp_process_tlp_ack(struct 
                tcp_set_ca_state(sk, TCP_CA_CWR);
                tcp_end_cwnd_reduction(sk);
                tcp_try_keep_open(sk);
 -              NET_INC_STATS_BH(sock_net(sk),
 -                               LINUX_MIB_TCPLOSSPROBERECOVERY);
 +              NET_INC_STATS(sock_net(sk),
 +                              LINUX_MIB_TCPLOSSPROBERECOVERY);
        } else if (!(flag & (FLAG_SND_UNA_ADVANCED |
                             FLAG_NOT_DUP | FLAG_DATA_SACKED))) {
                /* Pure dupack: original and TLP probe arrived; no loss */
@@@ -3627,14 -3627,14 +3627,14 @@@ static int tcp_ack(struct sock *sk, con
  
                tcp_in_ack_event(sk, CA_ACK_WIN_UPDATE);
  
 -              NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPHPACKS);
 +              NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPHPACKS);
        } else {
                u32 ack_ev_flags = CA_ACK_SLOWPATH;
  
                if (ack_seq != TCP_SKB_CB(skb)->end_seq)
                        flag |= FLAG_DATA;
                else
 -                      NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPPUREACKS);
 +                      NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPPUREACKS);
  
                flag |= tcp_ack_update_window(sk, skb, ack, ack_seq);
  
@@@ -4137,7 -4137,7 +4137,7 @@@ static void tcp_dsack_set(struct sock *
                else
                        mib_idx = LINUX_MIB_TCPDSACKOFOSENT;
  
 -              NET_INC_STATS_BH(sock_net(sk), mib_idx);
 +              NET_INC_STATS(sock_net(sk), mib_idx);
  
                tp->rx_opt.dsack = 1;
                tp->duplicate_sack[0].start_seq = seq;
@@@ -4161,7 -4161,7 +4161,7 @@@ static void tcp_send_dupack(struct soc
  
        if (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq &&
            before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) {
 -              NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_DELAYEDACKLOST);
 +              NET_INC_STATS(sock_net(sk), LINUX_MIB_DELAYEDACKLOST);
                tcp_enter_quickack_mode(sk);
  
                if (tcp_is_sack(tp) && sysctl_tcp_dsack) {
@@@ -4311,19 -4311,13 +4311,19 @@@ static bool tcp_try_coalesce(struct soc
  
        atomic_add(delta, &sk->sk_rmem_alloc);
        sk_mem_charge(sk, delta);
 -      NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPRCVCOALESCE);
 +      NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPRCVCOALESCE);
        TCP_SKB_CB(to)->end_seq = TCP_SKB_CB(from)->end_seq;
        TCP_SKB_CB(to)->ack_seq = TCP_SKB_CB(from)->ack_seq;
        TCP_SKB_CB(to)->tcp_flags |= TCP_SKB_CB(from)->tcp_flags;
        return true;
  }
  
 +static void tcp_drop(struct sock *sk, struct sk_buff *skb)
 +{
 +      sk_drops_add(sk, skb);
 +      __kfree_skb(skb);
 +}
 +
  /* This one checks to see if we can put data from the
   * out_of_order queue into the receive_queue.
   */
@@@ -4348,7 -4342,7 +4348,7 @@@ static void tcp_ofo_queue(struct sock *
                __skb_unlink(skb, &tp->out_of_order_queue);
                if (!after(TCP_SKB_CB(skb)->end_seq, tp->rcv_nxt)) {
                        SOCK_DEBUG(sk, "ofo packet was already received\n");
 -                      __kfree_skb(skb);
 +                      tcp_drop(sk, skb);
                        continue;
                }
                SOCK_DEBUG(sk, "ofo requeuing : rcv_next %X seq %X - %X\n",
@@@ -4399,8 -4393,8 +4399,8 @@@ static void tcp_data_queue_ofo(struct s
        tcp_ecn_check_ce(tp, skb);
  
        if (unlikely(tcp_try_rmem_schedule(sk, skb, skb->truesize))) {
 -              NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPOFODROP);
 -              __kfree_skb(skb);
 +              NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPOFODROP);
 +              tcp_drop(sk, skb);
                return;
        }
  
        tp->pred_flags = 0;
        inet_csk_schedule_ack(sk);
  
 -      NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPOFOQUEUE);
 +      NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPOFOQUEUE);
        SOCK_DEBUG(sk, "out of order segment: rcv_next %X seq %X - %X\n",
                   tp->rcv_nxt, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq);
  
        if (skb1 && before(seq, TCP_SKB_CB(skb1)->end_seq)) {
                if (!after(end_seq, TCP_SKB_CB(skb1)->end_seq)) {
                        /* All the bits are present. Drop. */
 -                      NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPOFOMERGE);
 -                      __kfree_skb(skb);
 +                      NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPOFOMERGE);
 +                      tcp_drop(sk, skb);
                        skb = NULL;
                        tcp_dsack_set(sk, seq, end_seq);
                        goto add_sack;
                __skb_unlink(skb1, &tp->out_of_order_queue);
                tcp_dsack_extend(sk, TCP_SKB_CB(skb1)->seq,
                                 TCP_SKB_CB(skb1)->end_seq);
 -              NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPOFOMERGE);
 -              __kfree_skb(skb1);
 +              NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPOFOMERGE);
 +              tcp_drop(sk, skb1);
        }
  
  add_sack:
  static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)
  {
        struct tcp_sock *tp = tcp_sk(sk);
 -      int eaten = -1;
        bool fragstolen = false;
 +      int eaten = -1;
  
 -      if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq)
 -              goto drop;
 -
 +      if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq) {
 +              __kfree_skb(skb);
 +              return;
 +      }
        skb_dst_drop(skb);
        __skb_pull(skb, tcp_hdr(skb)->doff * 4);
  
  
                        __set_current_state(TASK_RUNNING);
  
 -                      local_bh_enable();
                        if (!skb_copy_datagram_msg(skb, 0, tp->ucopy.msg, chunk)) {
                                tp->ucopy.len -= chunk;
                                tp->copied_seq += chunk;
                                eaten = (chunk == skb->len);
                                tcp_rcv_space_adjust(sk);
                        }
 -                      local_bh_disable();
                }
  
                if (eaten <= 0) {
@@@ -4665,14 -4660,14 +4665,14 @@@ queue_and_out
  
        if (!after(TCP_SKB_CB(skb)->end_seq, tp->rcv_nxt)) {
                /* A retransmit, 2nd most common case.  Force an immediate ack. */
 -              NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_DELAYEDACKLOST);
 +              NET_INC_STATS(sock_net(sk), LINUX_MIB_DELAYEDACKLOST);
                tcp_dsack_set(sk, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq);
  
  out_of_window:
                tcp_enter_quickack_mode(sk);
                inet_csk_schedule_ack(sk);
  drop:
 -              __kfree_skb(skb);
 +              tcp_drop(sk, skb);
                return;
        }
  
@@@ -4711,7 -4706,7 +4711,7 @@@ static struct sk_buff *tcp_collapse_one
  
        __skb_unlink(skb, list);
        __kfree_skb(skb);
 -      NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPRCVCOLLAPSED);
 +      NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPRCVCOLLAPSED);
  
        return next;
  }
@@@ -4870,7 -4865,7 +4870,7 @@@ static bool tcp_prune_ofo_queue(struct 
        bool res = false;
  
        if (!skb_queue_empty(&tp->out_of_order_queue)) {
 -              NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_OFOPRUNED);
 +              NET_INC_STATS(sock_net(sk), LINUX_MIB_OFOPRUNED);
                __skb_queue_purge(&tp->out_of_order_queue);
  
                /* Reset SACK state.  A conforming SACK implementation will
@@@ -4899,7 -4894,7 +4899,7 @@@ static int tcp_prune_queue(struct sock 
  
        SOCK_DEBUG(sk, "prune_queue: c=%x\n", tp->copied_seq);
  
 -      NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PRUNECALLED);
 +      NET_INC_STATS(sock_net(sk), LINUX_MIB_PRUNECALLED);
  
        if (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf)
                tcp_clamp_window(sk);
         * drop receive data on the floor.  It will get retransmitted
         * and hopefully then we'll have sufficient space.
         */
 -      NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_RCVPRUNED);
 +      NET_INC_STATS(sock_net(sk), LINUX_MIB_RCVPRUNED);
  
        /* Massive buffer overcommit. */
        tp->pred_flags = 0;
@@@ -5138,6 -5133,7 +5138,6 @@@ static int tcp_copy_to_iovec(struct soc
        int chunk = skb->len - hlen;
        int err;
  
 -      local_bh_enable();
        if (skb_csum_unnecessary(skb))
                err = skb_copy_datagram_msg(skb, hlen, tp->ucopy.msg, chunk);
        else
                tcp_rcv_space_adjust(sk);
        }
  
 -      local_bh_disable();
        return err;
  }
  
 -static __sum16 __tcp_checksum_complete_user(struct sock *sk,
 -                                          struct sk_buff *skb)
 -{
 -      __sum16 result;
 -
 -      if (sock_owned_by_user(sk)) {
 -              local_bh_enable();
 -              result = __tcp_checksum_complete(skb);
 -              local_bh_disable();
 -      } else {
 -              result = __tcp_checksum_complete(skb);
 -      }
 -      return result;
 -}
 -
 -static inline bool tcp_checksum_complete_user(struct sock *sk,
 -                                           struct sk_buff *skb)
 -{
 -      return !skb_csum_unnecessary(skb) &&
 -             __tcp_checksum_complete_user(sk, skb);
 -}
 -
  /* Does PAWS and seqno based validation of an incoming segment, flags will
   * play significant role here.
   */
@@@ -5164,7 -5183,7 +5164,7 @@@ static bool tcp_validate_incoming(struc
        if (tcp_fast_parse_options(skb, th, tp) && tp->rx_opt.saw_tstamp &&
            tcp_paws_discard(sk, skb)) {
                if (!th->rst) {
 -                      NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED);
 +                      NET_INC_STATS(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED);
                        if (!tcp_oow_rate_limited(sock_net(sk), skb,
                                                  LINUX_MIB_TCPACKSKIPPEDPAWS,
                                                  &tp->last_oow_ack_time))
        if (th->syn) {
  syn_challenge:
                if (syn_inerr)
 -                      TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS);
 -              NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSYNCHALLENGE);
 +                      TCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS);
 +              NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPSYNCHALLENGE);
                tcp_send_challenge_ack(sk, skb);
                goto discard;
        }
        return true;
  
  discard:
 -      __kfree_skb(skb);
 +      tcp_drop(sk, skb);
        return false;
  }
  
@@@ -5332,7 -5351,7 +5332,7 @@@ void tcp_rcv_established(struct sock *s
                                tcp_data_snd_check(sk);
                                return;
                        } else { /* Header too small */
 -                              TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS);
 +                              TCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS);
                                goto discard;
                        }
                } else {
  
                                        __skb_pull(skb, tcp_header_len);
                                        tcp_rcv_nxt_update(tp, TCP_SKB_CB(skb)->end_seq);
 -                                      NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPHPHITSTOUSER);
 +                                      NET_INC_STATS(sock_net(sk),
 +                                                      LINUX_MIB_TCPHPHITSTOUSER);
                                        eaten = 1;
                                }
                        }
                        if (!eaten) {
 -                              if (tcp_checksum_complete_user(sk, skb))
 +                              if (tcp_checksum_complete(skb))
                                        goto csum_error;
  
                                if ((int)skb->truesize > sk->sk_forward_alloc)
  
                                tcp_rcv_rtt_measure_ts(sk, skb);
  
 -                              NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPHPHITS);
 +                              NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPHPHITS);
  
                                /* Bulk data transfer: receiver */
                                eaten = tcp_queue_rcv(sk, skb, tcp_header_len,
@@@ -5410,7 -5428,7 +5410,7 @@@ no_ack
        }
  
  slow_path:
 -      if (len < (th->doff << 2) || tcp_checksum_complete_user(sk, skb))
 +      if (len < (th->doff << 2) || tcp_checksum_complete(skb))
                goto csum_error;
  
        if (!th->ack && !th->rst && !th->syn)
@@@ -5440,11 -5458,11 +5440,11 @@@ step5
        return;
  
  csum_error:
 -      TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_CSUMERRORS);
 -      TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS);
 +      TCP_INC_STATS(sock_net(sk), TCP_MIB_CSUMERRORS);
 +      TCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS);
  
  discard:
 -      __kfree_skb(skb);
 +      tcp_drop(sk, skb);
  }
  EXPORT_SYMBOL(tcp_rcv_established);
  
@@@ -5529,18 -5547,16 +5529,18 @@@ static bool tcp_rcv_fastopen_synack(str
        if (data) { /* Retransmit unacked data in SYN */
                tcp_for_write_queue_from(data, sk) {
                        if (data == tcp_send_head(sk) ||
 -                          __tcp_retransmit_skb(sk, data))
 +                          __tcp_retransmit_skb(sk, data, 1))
                                break;
                }
                tcp_rearm_rto(sk);
 -              NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPFASTOPENACTIVEFAIL);
 +              NET_INC_STATS(sock_net(sk),
 +                              LINUX_MIB_TCPFASTOPENACTIVEFAIL);
                return true;
        }
        tp->syn_data_acked = tp->syn_data;
        if (tp->syn_data_acked)
 -              NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPFASTOPENACTIVE);
 +              NET_INC_STATS(sock_net(sk),
 +                              LINUX_MIB_TCPFASTOPENACTIVE);
  
        tcp_fastopen_add_skb(sk, synack);
  
@@@ -5575,8 -5591,7 +5575,8 @@@ static int tcp_rcv_synsent_state_proces
                if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr &&
                    !between(tp->rx_opt.rcv_tsecr, tp->retrans_stamp,
                             tcp_time_stamp)) {
 -                      NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSACTIVEREJECTED);
 +                      NET_INC_STATS(sock_net(sk),
 +                                      LINUX_MIB_PAWSACTIVEREJECTED);
                        goto reset_and_undo;
                }
  
                                                  TCP_DELACK_MAX, TCP_RTO_MAX);
  
  discard:
 -                      __kfree_skb(skb);
 +                      tcp_drop(sk, skb);
                        return 0;
                } else {
                        tcp_send_ack(sk);
@@@ -5785,6 -5800,8 +5785,6 @@@ int tcp_rcv_state_process(struct sock *
        int queued = 0;
        bool acceptable;
  
 -      tp->rx_opt.saw_tstamp = 0;
 -
        switch (sk->sk_state) {
        case TCP_CLOSE:
                goto discard;
                        if (icsk->icsk_af_ops->conn_request(sk, skb) < 0)
                                return 1;
  
 -                      /* Now we have several options: In theory there is
 -                       * nothing else in the frame. KA9Q has an option to
 -                       * send data with the syn, BSD accepts data with the
 -                       * syn up to the [to be] advertised window and
 -                       * Solaris 2.1 gives you a protocol error. For now
 -                       * we just ignore it, that fits the spec precisely
 -                       * and avoids incompatibilities. It would be nice in
 -                       * future to drop through and process the data.
 -                       *
 -                       * Now that TTCP is starting to be used we ought to
 -                       * queue this data.
 -                       * But, this leaves one open to an easy denial of
 -                       * service attack, and SYN cookies can't defend
 -                       * against this problem. So, we drop the data
 -                       * in the interest of security over speed unless
 -                       * it's still in use.
 -                       */
 -                      kfree_skb(skb);
 +                      consume_skb(skb);
                        return 0;
                }
                goto discard;
  
        case TCP_SYN_SENT:
 +              tp->rx_opt.saw_tstamp = 0;
                queued = tcp_rcv_synsent_state_process(sk, skb, th);
                if (queued >= 0)
                        return queued;
                return 0;
        }
  
 +      tp->rx_opt.saw_tstamp = 0;
        req = tp->fastopen_rsk;
        if (req) {
                WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV &&
                    (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq &&
                     after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt))) {
                        tcp_done(sk);
 -                      NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONDATA);
 +                      NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTONDATA);
                        return 1;
                }
  
                if (sk->sk_shutdown & RCV_SHUTDOWN) {
                        if (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq &&
                            after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt)) {
 -                              NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONDATA);
 +                              NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTONDATA);
                                tcp_reset(sk);
                                return 1;
                        }
  
        if (!queued) {
  discard:
 -              __kfree_skb(skb);
 +              tcp_drop(sk, skb);
        }
        return 0;
  }
@@@ -6114,6 -6146,9 +6114,9 @@@ struct request_sock *inet_reqsk_alloc(c
  
                kmemcheck_annotate_bitfield(ireq, flags);
                ireq->opt = NULL;
+ #if IS_ENABLED(CONFIG_IPV6)
+               ireq->pktopts = NULL;
+ #endif
                atomic64_set(&ireq->ir_cookie, 0);
                ireq->ireq_state = TCP_NEW_SYN_RECV;
                write_pnet(&ireq->ireq_net, sock_net(sk_listener));
@@@ -6140,10 -6175,10 +6143,10 @@@ static bool tcp_syn_flood_action(const 
        if (net->ipv4.sysctl_tcp_syncookies) {
                msg = "Sending cookies";
                want_cookie = true;
 -              NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPREQQFULLDOCOOKIES);
 +              __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPREQQFULLDOCOOKIES);
        } else
  #endif
 -              NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPREQQFULLDROP);
 +              __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPREQQFULLDROP);
  
        if (!queue->synflood_warned &&
            net->ipv4.sysctl_tcp_syncookies != 2 &&
@@@ -6204,7 -6239,7 +6207,7 @@@ int tcp_conn_request(struct request_soc
         * timeout.
         */
        if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) {
 -              NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
 +              NET_INC_STATS(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
                goto drop;
        }
  
                        if (dst && strict &&
                            !tcp_peer_is_proven(req, dst, true,
                                                tmp_opt.saw_tstamp)) {
 -                              NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED);
 +                              NET_INC_STATS(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED);
                                goto drop_and_release;
                        }
                }
        }
        if (fastopen_sk) {
                af_ops->send_synack(fastopen_sk, dst, &fl, req,
 -                                  &foc, false);
 +                                  &foc, TCP_SYNACK_FASTOPEN);
                /* Add the child socket directly into the accept queue */
                inet_csk_reqsk_queue_add(sk, req, fastopen_sk);
                sk->sk_data_ready(sk);
                tcp_rsk(req)->tfo_listener = false;
                if (!want_cookie)
                        inet_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT);
 -              af_ops->send_synack(sk, dst, &fl, req,
 -                                  &foc, !want_cookie);
 -              if (want_cookie)
 -                      goto drop_and_free;
 +              af_ops->send_synack(sk, dst, &fl, req, &foc,
 +                                  !want_cookie ? TCP_SYNACK_NORMAL :
 +                                                 TCP_SYNACK_COOKIE);
 +              if (want_cookie) {
 +                      reqsk_free(req);
 +                      return 0;
 +              }
        }
        reqsk_put(req);
        return 0;
@@@ -6325,7 -6357,7 +6328,7 @@@ drop_and_release
  drop_and_free:
        reqsk_free(req);
  drop:
 -      NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
 +      tcp_listendrop(sk);
        return 0;
  }
  EXPORT_SYMBOL(tcp_conn_request);
diff --combined net/ipv6/Makefile
index 6d8ea099213e5084927833570e326fcf2cef628a,88ad4477705c7c689fd6b529d0935ecb27a88048..c174ccb340a15bca6e712932ae5e7a9c34739efb
@@@ -8,10 -8,9 +8,10 @@@ ipv6-objs :=   af_inet6.o anycast.o ip6_o
                addrlabel.o \
                route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o udplite.o \
                raw.o icmp.o mcast.o reassembly.o tcp_ipv6.o ping.o \
 -              exthdrs.o datagram.o ip6_flowlabel.o inet6_connection_sock.o
 +              exthdrs.o datagram.o ip6_flowlabel.o inet6_connection_sock.o \
 +              udp_offload.o
  
 -ipv6-offload :=       ip6_offload.o tcpv6_offload.o udp_offload.o exthdrs_offload.o
 +ipv6-offload :=       ip6_offload.o tcpv6_offload.o exthdrs_offload.o
  
  ipv6-$(CONFIG_SYSCTL) = sysctl_net_ipv6.o
  ipv6-$(CONFIG_IPV6_MROUTE) += ip6mr.o
@@@ -22,6 -21,7 +22,7 @@@ ipv6-$(CONFIG_NETFILTER) += netfilter.
  ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o
  ipv6-$(CONFIG_PROC_FS) += proc.o
  ipv6-$(CONFIG_SYN_COOKIES) += syncookies.o
+ ipv6-$(CONFIG_NETLABEL) += calipso.o
  
  ipv6-objs += $(ipv6-y)
  
@@@ -42,7 -42,6 +43,7 @@@ obj-$(CONFIG_IPV6_VTI) += ip6_vti.
  obj-$(CONFIG_IPV6_SIT) += sit.o
  obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o
  obj-$(CONFIG_IPV6_GRE) += ip6_gre.o
 +obj-$(CONFIG_IPV6_FOU) += fou6.o
  
  obj-y += addrconf_core.o exthdrs_core.o ip6_checksum.o ip6_icmp.o
  obj-$(CONFIG_INET) += output_core.o protocol.o $(ipv6-offload)
diff --combined net/ipv6/af_inet6.c
index bfa86f040c161233d4dd9192d205ce0ba3976e4f,c241c1805728f44c7e30c89e14aec413134f19e5..b0994a49dfca4c55a8385b2aec264f7119be8550
  #ifdef CONFIG_IPV6_TUNNEL
  #include <net/ip6_tunnel.h>
  #endif
+ #include <net/calipso.h>
  
  #include <asm/uaccess.h>
  #include <linux/mroute6.h>
  
 +#include "ip6_offload.h"
 +
  MODULE_AUTHOR("Cast of dozens");
  MODULE_DESCRIPTION("IPv6 protocol stack for Linux");
  MODULE_LICENSE("GPL");
@@@ -563,7 -562,6 +564,7 @@@ const struct proto_ops inet6_dgram_ops 
        .recvmsg           = inet_recvmsg,              /* ok           */
        .mmap              = sock_no_mmap,
        .sendpage          = sock_no_sendpage,
 +      .set_peek_off      = sk_set_peek_off,
  #ifdef CONFIG_COMPAT
        .compat_setsockopt = compat_sock_common_setsockopt,
        .compat_getsockopt = compat_sock_common_getsockopt,
@@@ -961,10 -959,6 +962,10 @@@ static int __init inet6_init(void
        if (err)
                goto udplitev6_fail;
  
 +      err = udpv6_offload_init();
 +      if (err)
 +              goto udpv6_offload_fail;
 +
        err = tcpv6_init();
        if (err)
                goto tcpv6_fail;
        if (err)
                goto pingv6_fail;
  
+       err = calipso_init();
+       if (err)
+               goto calipso_fail;
  #ifdef CONFIG_SYSCTL
        err = ipv6_sysctl_register();
        if (err)
@@@ -987,15 -985,15 +992,17 @@@ out
  
  #ifdef CONFIG_SYSCTL
  sysctl_fail:
-       pingv6_exit();
+       calipso_exit();
  #endif
+ calipso_fail:
+       pingv6_exit();
  pingv6_fail:
        ipv6_packet_cleanup();
  ipv6_packet_fail:
        tcpv6_exit();
  tcpv6_fail:
 +      udpv6_offload_exit();
 +udpv6_offload_fail:
        udplitev6_exit();
  udplitev6_fail:
        udpv6_exit();
diff --combined net/ipv6/exthdrs.c
index 8de5dd7aaa05cf50aede2fb7255215df527349d7,0f69cab39986ef62e15baaf82a9a5df9b3e26d5a..139ceb68bd3705b5bc4cedb0c5a1e39fa59fc6b8
@@@ -43,6 -43,7 +43,7 @@@
  #include <net/ndisc.h>
  #include <net/ip6_route.h>
  #include <net/addrconf.h>
+ #include <net/calipso.h>
  #if IS_ENABLED(CONFIG_IPV6_MIP6)
  #include <net/xfrm.h>
  #endif
@@@ -258,8 -259,8 +259,8 @@@ static int ipv6_destopt_rcv(struct sk_b
        if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
            !pskb_may_pull(skb, (skb_transport_offset(skb) +
                                 ((skb_transport_header(skb)[1] + 1) << 3)))) {
 -              IP6_INC_STATS_BH(dev_net(dst->dev), ip6_dst_idev(dst),
 -                               IPSTATS_MIB_INHDRERRORS);
 +              __IP6_INC_STATS(dev_net(dst->dev), ip6_dst_idev(dst),
 +                              IPSTATS_MIB_INHDRERRORS);
                kfree_skb(skb);
                return -1;
        }
                return 1;
        }
  
 -      IP6_INC_STATS_BH(dev_net(dst->dev),
 -                       ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS);
 +      __IP6_INC_STATS(dev_net(dst->dev),
 +                      ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS);
        return -1;
  }
  
@@@ -309,8 -310,8 +310,8 @@@ static int ipv6_rthdr_rcv(struct sk_buf
        if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
            !pskb_may_pull(skb, (skb_transport_offset(skb) +
                                 ((skb_transport_header(skb)[1] + 1) << 3)))) {
 -              IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)),
 -                               IPSTATS_MIB_INHDRERRORS);
 +              __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
 +                              IPSTATS_MIB_INHDRERRORS);
                kfree_skb(skb);
                return -1;
        }
  
        if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) ||
            skb->pkt_type != PACKET_HOST) {
 -              IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)),
 -                               IPSTATS_MIB_INADDRERRORS);
 +              __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
 +                              IPSTATS_MIB_INADDRERRORS);
                kfree_skb(skb);
                return -1;
        }
@@@ -334,8 -335,8 +335,8 @@@ looped_back
                         * processed by own
                         */
                        if (!addr) {
 -                              IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)),
 -                                               IPSTATS_MIB_INADDRERRORS);
 +                              __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
 +                                              IPSTATS_MIB_INADDRERRORS);
                                kfree_skb(skb);
                                return -1;
                        }
                        goto unknown_rh;
                /* Silently discard invalid RTH type 2 */
                if (hdr->hdrlen != 2 || hdr->segments_left != 1) {
 -                      IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)),
 -                                       IPSTATS_MIB_INHDRERRORS);
 +                      __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
 +                                      IPSTATS_MIB_INHDRERRORS);
                        kfree_skb(skb);
                        return -1;
                }
        n = hdr->hdrlen >> 1;
  
        if (hdr->segments_left > n) {
 -              IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)),
 -                               IPSTATS_MIB_INHDRERRORS);
 +              __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
 +                              IPSTATS_MIB_INHDRERRORS);
                icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
                                  ((&hdr->segments_left) -
                                   skb_network_header(skb)));
        if (skb_cloned(skb)) {
                /* the copy is a forwarded packet */
                if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
 -                      IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)),
 -                                       IPSTATS_MIB_OUTDISCARDS);
 +                      __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
 +                                      IPSTATS_MIB_OUTDISCARDS);
                        kfree_skb(skb);
                        return -1;
                }
                if (xfrm6_input_addr(skb, (xfrm_address_t *)addr,
                                     (xfrm_address_t *)&ipv6_hdr(skb)->saddr,
                                     IPPROTO_ROUTING) < 0) {
 -                      IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)),
 -                                       IPSTATS_MIB_INADDRERRORS);
 +                      __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
 +                                      IPSTATS_MIB_INADDRERRORS);
                        kfree_skb(skb);
                        return -1;
                }
                if (!ipv6_chk_home_addr(dev_net(skb_dst(skb)->dev), addr)) {
 -                      IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)),
 -                                       IPSTATS_MIB_INADDRERRORS);
 +                      __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
 +                                      IPSTATS_MIB_INADDRERRORS);
                        kfree_skb(skb);
                        return -1;
                }
        }
  
        if (ipv6_addr_is_multicast(addr)) {
 -              IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)),
 -                               IPSTATS_MIB_INADDRERRORS);
 +              __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
 +                              IPSTATS_MIB_INADDRERRORS);
                kfree_skb(skb);
                return -1;
        }
  
        if (skb_dst(skb)->dev->flags&IFF_LOOPBACK) {
                if (ipv6_hdr(skb)->hop_limit <= 1) {
 -                      IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)),
 -                                       IPSTATS_MIB_INHDRERRORS);
 +                      __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
 +                                      IPSTATS_MIB_INHDRERRORS);
                        icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
                                    0);
                        kfree_skb(skb);
        return -1;
  
  unknown_rh:
 -      IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_INHDRERRORS);
 +      __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_INHDRERRORS);
        icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
                          (&hdr->type) - skb_network_header(skb));
        return -1;
@@@ -568,28 -569,28 +569,28 @@@ static bool ipv6_hop_jumbo(struct sk_bu
        if (nh[optoff + 1] != 4 || (optoff & 3) != 2) {
                net_dbg_ratelimited("ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
                                    nh[optoff+1]);
 -              IP6_INC_STATS_BH(net, ipv6_skb_idev(skb),
 -                               IPSTATS_MIB_INHDRERRORS);
 +              __IP6_INC_STATS(net, ipv6_skb_idev(skb),
 +                              IPSTATS_MIB_INHDRERRORS);
                goto drop;
        }
  
        pkt_len = ntohl(*(__be32 *)(nh + optoff + 2));
        if (pkt_len <= IPV6_MAXPLEN) {
 -              IP6_INC_STATS_BH(net, ipv6_skb_idev(skb),
 -                               IPSTATS_MIB_INHDRERRORS);
 +              __IP6_INC_STATS(net, ipv6_skb_idev(skb),
 +                              IPSTATS_MIB_INHDRERRORS);
                icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
                return false;
        }
        if (ipv6_hdr(skb)->payload_len) {
 -              IP6_INC_STATS_BH(net, ipv6_skb_idev(skb),
 -                               IPSTATS_MIB_INHDRERRORS);
 +              __IP6_INC_STATS(net, ipv6_skb_idev(skb),
 +                              IPSTATS_MIB_INHDRERRORS);
                icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);
                return false;
        }
  
        if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
 -              IP6_INC_STATS_BH(net, ipv6_skb_idev(skb),
 -                               IPSTATS_MIB_INTRUNCATEDPKTS);
 +              __IP6_INC_STATS(net, ipv6_skb_idev(skb),
 +                              IPSTATS_MIB_INTRUNCATEDPKTS);
                goto drop;
        }
  
@@@ -603,6 -604,28 +604,28 @@@ drop
        return false;
  }
  
+ /* CALIPSO RFC 5570 */
+ static bool ipv6_hop_calipso(struct sk_buff *skb, int optoff)
+ {
+       const unsigned char *nh = skb_network_header(skb);
+       if (nh[optoff + 1] < 8)
+               goto drop;
+       if (nh[optoff + 6] * 4 + 8 > nh[optoff + 1])
+               goto drop;
+       if (!calipso_validate(skb, nh + optoff))
+               goto drop;
+       return true;
+ drop:
+       kfree_skb(skb);
+       return false;
+ }
  static const struct tlvtype_proc tlvprochopopt_lst[] = {
        {
                .type   = IPV6_TLV_ROUTERALERT,
                .type   = IPV6_TLV_JUMBO,
                .func   = ipv6_hop_jumbo,
        },
+       {
+               .type   = IPV6_TLV_CALIPSO,
+               .func   = ipv6_hop_calipso,
+       },
        { -1, }
  };
  
@@@ -758,6 -785,27 +785,27 @@@ static int ipv6_renew_option(void *ohdr
        return 0;
  }
  
+ /**
+  * ipv6_renew_options - replace a specific ext hdr with a new one.
+  *
+  * @sk: sock from which to allocate memory
+  * @opt: original options
+  * @newtype: option type to replace in @opt
+  * @newopt: new option of type @newtype to replace (user-mem)
+  * @newoptlen: length of @newopt
+  *
+  * Returns a new set of options which is a copy of @opt with the
+  * option type @newtype replaced with @newopt.
+  *
+  * @opt may be NULL, in which case a new set of options is returned
+  * containing just @newopt.
+  *
+  * @newopt may be NULL, in which case the specified option type is
+  * not copied into the new set of options.
+  *
+  * The new set of options is allocated from the socket option memory
+  * buffer of @sk.
+  */
  struct ipv6_txoptions *
  ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
                   int newtype,
@@@ -830,6 -878,34 +878,34 @@@ out
        return ERR_PTR(err);
  }
  
+ /**
+  * ipv6_renew_options_kern - replace a specific ext hdr with a new one.
+  *
+  * @sk: sock from which to allocate memory
+  * @opt: original options
+  * @newtype: option type to replace in @opt
+  * @newopt: new option of type @newtype to replace (kernel-mem)
+  * @newoptlen: length of @newopt
+  *
+  * See ipv6_renew_options().  The difference is that @newopt is
+  * kernel memory, rather than user memory.
+  */
+ struct ipv6_txoptions *
+ ipv6_renew_options_kern(struct sock *sk, struct ipv6_txoptions *opt,
+                       int newtype, struct ipv6_opt_hdr *newopt,
+                       int newoptlen)
+ {
+       struct ipv6_txoptions *ret_val;
+       const mm_segment_t old_fs = get_fs();
+       set_fs(KERNEL_DS);
+       ret_val = ipv6_renew_options(sk, opt, newtype,
+                                    (struct ipv6_opt_hdr __user *)newopt,
+                                    newoptlen);
+       set_fs(old_fs);
+       return ret_val;
+ }
  struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
                                          struct ipv6_txoptions *opt)
  {
diff --combined net/ipv6/ipv6_sockglue.c
index a9895e15ee9c270f13842121b7dc66ed97a71135,8a80d59bed344228d99dbaca464ed04138eb1ef9..5330262ab673c022fbf700d22782a74ccd1494fe
@@@ -98,7 -98,6 +98,6 @@@ int ip6_ra_control(struct sock *sk, in
        return 0;
  }
  
- static
  struct ipv6_txoptions *ipv6_update_options(struct sock *sk,
                                           struct ipv6_txoptions *opt)
  {
@@@ -407,8 -406,7 +406,8 @@@ static int do_ipv6_setsockopt(struct so
                if (optname != IPV6_RTHDR && !ns_capable(net->user_ns, CAP_NET_RAW))
                        break;
  
 -              opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk));
 +              opt = rcu_dereference_protected(np->opt,
 +                                              lockdep_sock_is_held(sk));
                opt = ipv6_renew_options(sk, opt, optname,
                                         (struct ipv6_opt_hdr __user *)optval,
                                         optlen);
@@@ -472,8 -470,7 +471,8 @@@ sticky_done
                struct ipv6_txoptions *opt = NULL;
                struct msghdr msg;
                struct flowi6 fl6;
 -              int junk;
 +              struct sockcm_cookie sockc_junk;
 +              struct ipcm6_cookie ipc6;
  
                memset(&fl6, 0, sizeof(fl6));
                fl6.flowi6_oif = sk->sk_bound_dev_if;
  
                msg.msg_controllen = optlen;
                msg.msg_control = (void *)(opt+1);
 +              ipc6.opt = opt;
  
 -              retv = ip6_datagram_send_ctl(net, sk, &msg, &fl6, opt, &junk,
 -                                           &junk, &junk);
 +              retv = ip6_datagram_send_ctl(net, sk, &msg, &fl6, &ipc6, &sockc_junk);
                if (retv)
                        goto done;
  update:
@@@ -1125,8 -1122,7 +1124,8 @@@ static int do_ipv6_getsockopt(struct so
                struct ipv6_txoptions *opt;
  
                lock_sock(sk);
 -              opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk));
 +              opt = rcu_dereference_protected(np->opt,
 +                                              lockdep_sock_is_held(sk));
                len = ipv6_getsockopt_sticky(sk, opt, optname, optval, len);
                release_sock(sk);
                /* check if ipv6_getsockopt_sticky() returns err code */
diff --combined net/ipv6/tcp_ipv6.c
index 79e33e02f11accfd5a6c8cf2751df0a8793ab016,18daddc6001c5063a2223f0fc2d90658ce6813f7..818b3b5cd490cbacf1fae9163cab967263fc60a2
@@@ -234,7 -234,7 +234,7 @@@ static int tcp_v6_connect(struct sock *
        fl6.fl6_dport = usin->sin6_port;
        fl6.fl6_sport = inet->inet_sport;
  
 -      opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk));
 +      opt = rcu_dereference_protected(np->opt, lockdep_sock_is_held(sk));
        final_p = fl6_update_dst(&fl6, opt, &final);
  
        security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
@@@ -336,8 -336,8 +336,8 @@@ static void tcp_v6_err(struct sk_buff *
                                        skb->dev->ifindex);
  
        if (!sk) {
 -              ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev),
 -                                 ICMP6_MIB_INERRORS);
 +              __ICMP6_INC_STATS(net, __in6_dev_get(skb->dev),
 +                                ICMP6_MIB_INERRORS);
                return;
        }
  
  
        bh_lock_sock(sk);
        if (sock_owned_by_user(sk) && type != ICMPV6_PKT_TOOBIG)
 -              NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS);
 +              __NET_INC_STATS(net, LINUX_MIB_LOCKDROPPEDICMPS);
  
        if (sk->sk_state == TCP_CLOSE)
                goto out;
  
        if (ipv6_hdr(skb)->hop_limit < inet6_sk(sk)->min_hopcount) {
 -              NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP);
 +              __NET_INC_STATS(net, LINUX_MIB_TCPMINTTLDROP);
                goto out;
        }
  
        snd_una = fastopen ? tcp_rsk(fastopen)->snt_isn : tp->snd_una;
        if (sk->sk_state != TCP_LISTEN &&
            !between(seq, snd_una, tp->snd_nxt)) {
 -              NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
 +              __NET_INC_STATS(net, LINUX_MIB_OUTOFWINDOWICMPS);
                goto out;
        }
  
@@@ -439,10 -439,11 +439,11 @@@ static int tcp_v6_send_synack(const str
                              struct flowi *fl,
                              struct request_sock *req,
                              struct tcp_fastopen_cookie *foc,
 -                            bool attach_req)
 +                            enum tcp_synack_type synack_type)
  {
        struct inet_request_sock *ireq = inet_rsk(req);
        struct ipv6_pinfo *np = inet6_sk(sk);
+       struct ipv6_txoptions *opt;
        struct flowi6 *fl6 = &fl->u.ip6;
        struct sk_buff *skb;
        int err = -ENOMEM;
                                               IPPROTO_TCP)) == NULL)
                goto done;
  
 -      skb = tcp_make_synack(sk, dst, req, foc, attach_req);
 +      skb = tcp_make_synack(sk, dst, req, foc, synack_type);
  
        if (skb) {
                __tcp_v6_send_check(skb, &ireq->ir_v6_loc_addr,
                        fl6->flowlabel = ip6_flowlabel(ipv6_hdr(ireq->pktopts));
  
                rcu_read_lock();
-               err = ip6_xmit(sk, skb, fl6, rcu_dereference(np->opt),
-                              np->tclass);
+               opt = ireq->ipv6_opt;
+               if (!opt)
+                       opt = rcu_dereference(np->opt);
+               err = ip6_xmit(sk, skb, fl6, opt, np->tclass);
                rcu_read_unlock();
                err = net_xmit_eval(err);
        }
@@@ -476,6 -479,7 +479,7 @@@ done
  
  static void tcp_v6_reqsk_destructor(struct request_sock *req)
  {
+       kfree(inet_rsk(req)->ipv6_opt);
        kfree_skb(inet_rsk(req)->pktopts);
  }
  
@@@ -649,12 -653,12 +653,12 @@@ static bool tcp_v6_inbound_md5_hash(con
                return false;
  
        if (hash_expected && !hash_location) {
 -              NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPMD5NOTFOUND);
 +              NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5NOTFOUND);
                return true;
        }
  
        if (!hash_expected && hash_location) {
 -              NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPMD5UNEXPECTED);
 +              NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5UNEXPECTED);
                return true;
        }
  
@@@ -810,13 -814,8 +814,13 @@@ static void tcp_v6_send_response(const 
        fl6.flowi6_proto = IPPROTO_TCP;
        if (rt6_need_strict(&fl6.daddr) && !oif)
                fl6.flowi6_oif = tcp_v6_iif(skb);
 -      else
 +      else {
 +              if (!oif && netif_index_is_l3_master(net, skb->skb_iif))
 +                      oif = skb->skb_iif;
 +
                fl6.flowi6_oif = oif;
 +      }
 +
        fl6.flowi6_mark = IP6_REPLY_MARK(net, skb->mark);
        fl6.fl6_dport = t1->dest;
        fl6.fl6_sport = t1->source;
        if (!IS_ERR(dst)) {
                skb_dst_set(buff, dst);
                ip6_xmit(ctl_sk, buff, &fl6, NULL, tclass);
 -              TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS);
 +              TCP_INC_STATS(net, TCP_MIB_OUTSEGS);
                if (rst)
 -                      TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS);
 +                      TCP_INC_STATS(net, TCP_MIB_OUTRSTS);
                return;
        }
  
@@@ -863,7 -862,6 +867,7 @@@ static void tcp_v6_send_reset(const str
                return;
  
  #ifdef CONFIG_TCP_MD5SIG
 +      rcu_read_lock();
        hash_location = tcp_parse_md5sig_option(th);
        if (sk && sk_fullsock(sk)) {
                key = tcp_v6_md5_do_lookup(sk, &ipv6h->saddr);
                                           th->source, &ipv6h->daddr,
                                           ntohs(th->source), tcp_v6_iif(skb));
                if (!sk1)
 -                      return;
 +                      goto out;
  
 -              rcu_read_lock();
                key = tcp_v6_md5_do_lookup(sk1, &ipv6h->saddr);
                if (!key)
 -                      goto release_sk1;
 +                      goto out;
  
                genhash = tcp_v6_md5_hash_skb(newhash, key, NULL, skb);
                if (genhash || memcmp(hash_location, newhash, 16) != 0)
 -                      goto release_sk1;
 +                      goto out;
        }
  #endif
  
        tcp_v6_send_response(sk, skb, seq, ack_seq, 0, 0, 0, oif, key, 1, 0, 0);
  
  #ifdef CONFIG_TCP_MD5SIG
 -release_sk1:
 -      if (sk1) {
 -              rcu_read_unlock();
 -              sock_put(sk1);
 -      }
 +out:
 +      rcu_read_unlock();
  #endif
  }
  
@@@ -969,7 -971,7 +973,7 @@@ static int tcp_v6_conn_request(struct s
                                &tcp_request_sock_ipv6_ops, sk, skb);
  
  drop:
 -      NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
 +      tcp_listendrop(sk);
        return 0; /* don't send reset */
  }
  
@@@ -1109,7 -1111,9 +1113,9 @@@ static struct sock *tcp_v6_syn_recv_soc
           but we make one more one thing there: reattach optmem
           to newsk.
         */
-       opt = rcu_dereference(np->opt);
+       opt = ireq->ipv6_opt;
+       if (!opt)
+               opt = rcu_dereference(np->opt);
        if (opt) {
                opt = ipv6_dup_options(newsk, opt);
                RCU_INIT_POINTER(newnp->opt, opt);
        return newsk;
  
  out_overflow:
 -      NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
 +      __NET_INC_STATS(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
  out_nonewsk:
        dst_release(dst);
  out:
 -      NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
 +      tcp_listendrop(sk);
        return NULL;
  }
  
@@@ -1281,8 -1285,8 +1287,8 @@@ discard
        kfree_skb(skb);
        return 0;
  csum_err:
 -      TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_CSUMERRORS);
 -      TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS);
 +      TCP_INC_STATS(sock_net(sk), TCP_MIB_CSUMERRORS);
 +      TCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS);
        goto discard;
  
  
@@@ -1353,7 -1357,6 +1359,7 @@@ static int tcp_v6_rcv(struct sk_buff *s
  {
        const struct tcphdr *th;
        const struct ipv6hdr *hdr;
 +      bool refcounted;
        struct sock *sk;
        int ret;
        struct net *net = dev_net(skb->dev);
        /*
         *      Count it even if it's bad.
         */
 -      TCP_INC_STATS_BH(net, TCP_MIB_INSEGS);
 +      __TCP_INC_STATS(net, TCP_MIB_INSEGS);
  
        if (!pskb_may_pull(skb, sizeof(struct tcphdr)))
                goto discard_it;
  
 -      th = tcp_hdr(skb);
 +      th = (const struct tcphdr *)skb->data;
  
 -      if (th->doff < sizeof(struct tcphdr)/4)
 +      if (unlikely(th->doff < sizeof(struct tcphdr)/4))
                goto bad_packet;
        if (!pskb_may_pull(skb, th->doff*4))
                goto discard_it;
        if (skb_checksum_init(skb, IPPROTO_TCP, ip6_compute_pseudo))
                goto csum_error;
  
 -      th = tcp_hdr(skb);
 +      th = (const struct tcphdr *)skb->data;
        hdr = ipv6_hdr(skb);
  
  lookup:
        sk = __inet6_lookup_skb(&tcp_hashinfo, skb, __tcp_hdrlen(th),
 -                              th->source, th->dest, inet6_iif(skb));
 +                              th->source, th->dest, inet6_iif(skb),
 +                              &refcounted);
        if (!sk)
                goto no_tcp_socket;
  
@@@ -1408,7 -1410,6 +1414,7 @@@ process
                        goto lookup;
                }
                sock_hold(sk);
 +              refcounted = true;
                nsk = tcp_check_req(sk, skb, req, false);
                if (!nsk) {
                        reqsk_put(req);
                }
        }
        if (hdr->hop_limit < inet6_sk(sk)->min_hopcount) {
 -              NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP);
 +              __NET_INC_STATS(net, LINUX_MIB_TCPMINTTLDROP);
                goto discard_and_relse;
        }
  
        } else if (unlikely(sk_add_backlog(sk, skb,
                                           sk->sk_rcvbuf + sk->sk_sndbuf))) {
                bh_unlock_sock(sk);
 -              NET_INC_STATS_BH(net, LINUX_MIB_TCPBACKLOGDROP);
 +              __NET_INC_STATS(net, LINUX_MIB_TCPBACKLOGDROP);
                goto discard_and_relse;
        }
        bh_unlock_sock(sk);
  
  put_and_return:
 -      sock_put(sk);
 +      if (refcounted)
 +              sock_put(sk);
        return ret ? -1 : 0;
  
  no_tcp_socket:
  
        if (tcp_checksum_complete(skb)) {
  csum_error:
 -              TCP_INC_STATS_BH(net, TCP_MIB_CSUMERRORS);
 +              __TCP_INC_STATS(net, TCP_MIB_CSUMERRORS);
  bad_packet:
 -              TCP_INC_STATS_BH(net, TCP_MIB_INERRS);
 +              __TCP_INC_STATS(net, TCP_MIB_INERRS);
        } else {
                tcp_v6_send_reset(NULL, skb);
        }
@@@ -1489,9 -1489,7 +1495,9 @@@ discard_it
        return 0;
  
  discard_and_relse:
 -      sock_put(sk);
 +      sk_drops_add(sk, skb);
 +      if (refcounted)
 +              sock_put(sk);
        goto discard_it;
  
  do_time_wait:
                        inet_twsk_deschedule_put(tw);
                        sk = sk2;
                        tcp_v6_restore_cb(skb);
 +                      refcounted = false;
                        goto process;
                }
                /* Fall through to ACK */
diff --combined security/selinux/hooks.c
index a86d537eb79b149a7dfe1536a243e180f4b9ec92,51eafe5d3bf4b9dd2347e3fb1fc3d11dcb0a6de9..da934342a39f59432bde76a4755f85d5082f7ea1
@@@ -513,8 -513,7 +513,8 @@@ static int sb_finish_set_opts(struct su
                        rc = -EOPNOTSUPP;
                        goto out;
                }
 -              rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
 +              rc = root_inode->i_op->getxattr(root, root_inode,
 +                                              XATTR_NAME_SELINUX, NULL, 0);
                if (rc < 0 && rc != -ENODATA) {
                        if (rc == -EOPNOTSUPP)
                                printk(KERN_WARNING "SELinux: (dev %s, type "
@@@ -1326,7 -1325,7 +1326,7 @@@ static int selinux_genfs_get_sid(struc
                                 u32 *sid)
  {
        int rc;
 -      struct super_block *sb = dentry->d_inode->i_sb;
 +      struct super_block *sb = dentry->d_sb;
        char *buffer, *path;
  
        buffer = (char *)__get_free_page(GFP_KERNEL);
@@@ -1422,13 -1421,13 +1422,13 @@@ static int inode_doinit_with_dentry(str
                        goto out_unlock;
                }
                context[len] = '\0';
 -              rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
 +              rc = inode->i_op->getxattr(dentry, inode, XATTR_NAME_SELINUX,
                                           context, len);
                if (rc == -ERANGE) {
                        kfree(context);
  
                        /* Need a larger buffer.  Query for the right size. */
 -                      rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
 +                      rc = inode->i_op->getxattr(dentry, inode, XATTR_NAME_SELINUX,
                                                   NULL, 0);
                        if (rc < 0) {
                                dput(dentry);
                                goto out_unlock;
                        }
                        context[len] = '\0';
 -                      rc = inode->i_op->getxattr(dentry,
 +                      rc = inode->i_op->getxattr(dentry, inode,
                                                   XATTR_NAME_SELINUX,
                                                   context, len);
                }
@@@ -2774,7 -2773,7 +2774,7 @@@ static int selinux_sb_statfs(struct den
  }
  
  static int selinux_mount(const char *dev_name,
 -                       struct path *path,
 +                       const struct path *path,
                         const char *type,
                         unsigned long flags,
                         void *data)
@@@ -4604,13 -4603,13 +4604,13 @@@ static int selinux_socket_sock_rcv_skb(
                err = selinux_inet_sys_rcv_skb(sock_net(sk), skb->skb_iif,
                                               addrp, family, peer_sid, &ad);
                if (err) {
-                       selinux_netlbl_err(skb, err, 0);
+                       selinux_netlbl_err(skb, family, err, 0);
                        return err;
                }
                err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
                                   PEER__RECV, &ad);
                if (err) {
-                       selinux_netlbl_err(skb, err, 0);
+                       selinux_netlbl_err(skb, family, err, 0);
                        return err;
                }
        }
@@@ -4978,7 -4977,7 +4978,7 @@@ static unsigned int selinux_ip_forward(
                err = selinux_inet_sys_rcv_skb(dev_net(indev), indev->ifindex,
                                               addrp, family, peer_sid, &ad);
                if (err) {
-                       selinux_netlbl_err(skb, err, 1);
+                       selinux_netlbl_err(skb, family, err, 1);
                        return NF_DROP;
                }
        }
@@@ -5064,6 -5063,15 +5064,15 @@@ static unsigned int selinux_ipv4_output
        return selinux_ip_output(skb, PF_INET);
  }
  
+ #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ static unsigned int selinux_ipv6_output(void *priv,
+                                       struct sk_buff *skb,
+                                       const struct nf_hook_state *state)
+ {
+       return selinux_ip_output(skb, PF_INET6);
+ }
+ #endif        /* IPV6 */
  static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
                                                int ifindex,
                                                u16 family)
@@@ -6298,6 -6306,12 +6307,12 @@@ static struct nf_hook_ops selinux_nf_op
                .hooknum =      NF_INET_FORWARD,
                .priority =     NF_IP6_PRI_SELINUX_FIRST,
        },
+       {
+               .hook =         selinux_ipv6_output,
+               .pf =           NFPROTO_IPV6,
+               .hooknum =      NF_INET_LOCAL_OUT,
+               .priority =     NF_IP6_PRI_SELINUX_FIRST,
+       },
  #endif        /* IPV6 */
  };
  
index 6777295f4b2b75bd4edc385a60a09cdc4fdde0c0,292fdeaaec7e70f46c868ef930ce224209638025..722f3844286b37e90b14deb9ce22e5bba4244ae9
@@@ -272,7 -272,7 +272,7 @@@ static struct smack_known *smk_fetch(co
        if (buffer == NULL)
                return ERR_PTR(-ENOMEM);
  
 -      rc = ip->i_op->getxattr(dp, name, buffer, SMK_LONGLABEL);
 +      rc = ip->i_op->getxattr(dp, ip, name, buffer, SMK_LONGLABEL);
        if (rc < 0)
                skp = ERR_PTR(rc);
        else if (rc == 0)
@@@ -1444,7 -1444,7 +1444,7 @@@ static int smack_inode_removexattr(stru
         *      XATTR_NAME_SMACKIPOUT
         */
        if (strcmp(name, XATTR_NAME_SMACK) == 0) {
 -              struct super_block *sbp = d_backing_inode(dentry)->i_sb;
 +              struct super_block *sbp = dentry->d_sb;
                struct superblock_smack *sbsp = sbp->s_security;
  
                isp->smk_inode = sbsp->smk_default;
@@@ -3514,12 -3514,12 +3514,12 @@@ static void smack_d_instantiate(struct 
                         */
                        if (isp->smk_flags & SMK_INODE_CHANGED) {
                                isp->smk_flags &= ~SMK_INODE_CHANGED;
 -                              rc = inode->i_op->setxattr(dp,
 +                              rc = inode->i_op->setxattr(dp, inode,
                                        XATTR_NAME_SMACKTRANSMUTE,
                                        TRANS_TRUE, TRANS_TRUE_SIZE,
                                        0);
                        } else {
 -                              rc = inode->i_op->getxattr(dp,
 +                              rc = inode->i_op->getxattr(dp, inode,
                                        XATTR_NAME_SMACKTRANSMUTE, trattr,
                                        TRANS_TRUE_SIZE);
                                if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
@@@ -3992,7 -3992,7 +3992,7 @@@ access_check
                rc = smk_bu_note("IPv4 delivery", skp, ssp->smk_in,
                                        MAY_WRITE, rc);
                if (rc != 0)
-                       netlbl_skbuff_err(skb, rc, 0);
+                       netlbl_skbuff_err(skb, sk->sk_family, rc, 0);
                break;
  #if IS_ENABLED(CONFIG_IPV6)
        case PF_INET6:
This page took 0.078544 seconds and 5 git commands to generate.