Merge tag 'pm+acpi-3.20-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafae...
[firefly-linux-kernel-4.4.55.git] / net / core / skbuff.c
index 395c15b82087253cd9905d315cd689a29b89ae4d..88c613eab142962dc44f2075378fce0b94349e8e 100644 (file)
@@ -74,6 +74,8 @@
 #include <asm/uaccess.h>
 #include <trace/events/skb.h>
 #include <linux/highmem.h>
+#include <linux/capability.h>
+#include <linux/user_namespace.h>
 
 struct kmem_cache *skbuff_head_cache __read_mostly;
 static struct kmem_cache *skbuff_fclone_cache __read_mostly;
@@ -677,13 +679,6 @@ static void skb_release_head_state(struct sk_buff *skb)
 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
        nf_bridge_put(skb->nf_bridge);
 #endif
-/* XXX: IS this still necessary? - JHS */
-#ifdef CONFIG_NET_SCHED
-       skb->tc_index = 0;
-#ifdef CONFIG_NET_CLS_ACT
-       skb->tc_verd = 0;
-#endif
-#endif
 }
 
 /* Free everything but the sk_buff shell. */
@@ -830,6 +825,9 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
 #ifdef CONFIG_NET_RX_BUSY_POLL
        CHECK_SKB_FIELD(napi_id);
 #endif
+#ifdef CONFIG_XPS
+       CHECK_SKB_FIELD(sender_cpu);
+#endif
 #ifdef CONFIG_NET_SCHED
        CHECK_SKB_FIELD(tc_index);
 #ifdef CONFIG_NET_CLS_ACT
@@ -3697,11 +3695,28 @@ static void __skb_complete_tx_timestamp(struct sk_buff *skb,
                kfree_skb(skb);
 }
 
+static bool skb_may_tx_timestamp(struct sock *sk, bool tsonly)
+{
+       bool ret;
+
+       if (likely(sysctl_tstamp_allow_data || tsonly))
+               return true;
+
+       read_lock_bh(&sk->sk_callback_lock);
+       ret = sk->sk_socket && sk->sk_socket->file &&
+             file_ns_capable(sk->sk_socket->file, &init_user_ns, CAP_NET_RAW);
+       read_unlock_bh(&sk->sk_callback_lock);
+       return ret;
+}
+
 void skb_complete_tx_timestamp(struct sk_buff *skb,
                               struct skb_shared_hwtstamps *hwtstamps)
 {
        struct sock *sk = skb->sk;
 
+       if (!skb_may_tx_timestamp(sk, false))
+               return;
+
        /* take a reference to prevent skb_orphan() from freeing the socket */
        sock_hold(sk);
 
@@ -3717,19 +3732,28 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb,
                     struct sock *sk, int tstype)
 {
        struct sk_buff *skb;
+       bool tsonly = sk->sk_tsflags & SOF_TIMESTAMPING_OPT_TSONLY;
 
-       if (!sk)
+       if (!sk || !skb_may_tx_timestamp(sk, tsonly))
                return;
 
-       if (hwtstamps)
-               *skb_hwtstamps(orig_skb) = *hwtstamps;
+       if (tsonly)
+               skb = alloc_skb(0, GFP_ATOMIC);
        else
-               orig_skb->tstamp = ktime_get_real();
-
-       skb = skb_clone(orig_skb, GFP_ATOMIC);
+               skb = skb_clone(orig_skb, GFP_ATOMIC);
        if (!skb)
                return;
 
+       if (tsonly) {
+               skb_shinfo(skb)->tx_flags = skb_shinfo(orig_skb)->tx_flags;
+               skb_shinfo(skb)->tskey = skb_shinfo(orig_skb)->tskey;
+       }
+
+       if (hwtstamps)
+               *skb_hwtstamps(skb) = *hwtstamps;
+       else
+               skb->tstamp = ktime_get_real();
+
        __skb_complete_tx_timestamp(skb, sk, tstype);
 }
 EXPORT_SYMBOL_GPL(__skb_tstamp_tx);
@@ -4148,6 +4172,7 @@ void skb_scrub_packet(struct sk_buff *skb, bool xnet)
        skb->ignore_df = 0;
        skb_dst_drop(skb);
        skb->mark = 0;
+       skb->sender_cpu = 0;
        skb_init_secmark(skb);
        secpath_reset(skb);
        nf_reset(skb);
@@ -4204,7 +4229,7 @@ struct sk_buff *skb_vlan_untag(struct sk_buff *skb)
        struct vlan_hdr *vhdr;
        u16 vlan_tci;
 
-       if (unlikely(vlan_tx_tag_present(skb))) {
+       if (unlikely(skb_vlan_tag_present(skb))) {
                /* vlan_tci is already set-up so leave this for another time */
                return skb;
        }
@@ -4290,7 +4315,7 @@ int skb_vlan_pop(struct sk_buff *skb)
        __be16 vlan_proto;
        int err;
 
-       if (likely(vlan_tx_tag_present(skb))) {
+       if (likely(skb_vlan_tag_present(skb))) {
                skb->vlan_tci = 0;
        } else {
                if (unlikely((skb->protocol != htons(ETH_P_8021Q) &&
@@ -4320,7 +4345,7 @@ EXPORT_SYMBOL(skb_vlan_pop);
 
 int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci)
 {
-       if (vlan_tx_tag_present(skb)) {
+       if (skb_vlan_tag_present(skb)) {
                unsigned int offset = skb->data - skb_mac_header(skb);
                int err;
 
@@ -4330,7 +4355,7 @@ int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci)
                 */
                __skb_push(skb, offset);
                err = __vlan_insert_tag(skb, skb->vlan_proto,
-                                       vlan_tx_tag_get(skb));
+                                       skb_vlan_tag_get(skb));
                if (err)
                        return err;
                skb->protocol = skb->vlan_proto;