|
@@ -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;
|
|
@@ -3690,11 +3692,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);
|
|
|
|
|
@@ -3712,7 +3731,7 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb,
|
|
|
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 (tsonly)
|