Skip to contentSkip to conversation

Patch "tcp: fix SCM_TIMESTAMPING_OPT_STATS for normal skbs" has been added to the 4.10-stable tree

PATCH [email protected] 1 participant 1 message Apr 29, 2017

Subsystems (3)
lore
Share & tools
lore

[email protected]

author maintainer Applied
#0 lore raw

This is a note to let you know that I've just added the patch titled

tcp: fix SCM_TIMESTAMPING_OPT_STATS for normal skbs

to the 4.10-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
tcp-fix-scm_timestamping_opt_stats-for-normal-skbs.patch
and it can be found in the queue-4.10 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.

Quoted 1 line

From foo@baz Sat Apr 29 08:22:40 CEST 2017

From: Soheil Hassas Yeganeh <[email protected]>
Date: Sat, 18 Mar 2017 17:02:59 -0400
Subject: tcp: fix SCM_TIMESTAMPING_OPT_STATS for normal skbs

From: Soheil Hassas Yeganeh <[email protected]>

[ Upstream commit 8605330aac5a5785630aec8f64378a54891937cc ]

__sock_recv_timestamp can be called for both normal skbs (for receive timestamps) and for skbs on the error queue (for transmit timestamps).

Commit 1c885808e456
(tcp: SOF_TIMESTAMPING_OPT_STATS option for SO_TIMESTAMPING) assumes any skb passed to __sock_recv_timestamp are from the error queue, containing OPT_STATS in the content of the skb. This results in accessing invalid memory or generating junk data.

To fix this, set skb->pkt_type to PACKET_OUTGOING for packets on the error queue. This is safe because on the receive path on local sockets skb->pkt_type is never set to PACKET_OUTGOING. With that, copy OPT_STATS from a packet, only if its pkt_type is PACKET_OUTGOING.

Fixes 1c885808e456 ("tcp: SOF_TIMESTAMPING_OPT_STATS option for SO_TIMESTAMPING")
---
 net/core/skbuff.c |   10 ++++++++++
 net/socket.c      |   13 ++++++++++++-
 2 files changed, 22 insertions(+), 1 deletion(-)
net/core/skbuff.c +10 -0
@@ -3700,6 +3700,15 @@ static void sock_rmem_free(struct sk_buf
 	atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
 }
 
+static void skb_set_err_queue(struct sk_buff *skb)
+{
+	/* pkt_type of skbs received on local sockets is never PACKET_OUTGOING.
+	 * So, it is safe to (mis)use it to mark skbs on the error queue.
+	 */
+	skb->pkt_type = PACKET_OUTGOING;
+	BUILD_BUG_ON(PACKET_OUTGOING == 0);
+}
+
 /*
  * Note: We dont mem charge error packets (no sk_forward_alloc changes)
  */
@@ -3713,6 +3722,7 @@ int sock_queue_err_skb(struct sock *sk,
 	skb->sk = sk;
 	skb->destructor = sock_rmem_free;
 	atomic_add(skb->truesize, &sk->sk_rmem_alloc);
+	skb_set_err_queue(skb);
 
 	/* before exiting rcu section, make sure dst is refcounted */
 	skb_dst_force(skb);
net/socket.c +12 -1
@@ -654,6 +654,16 @@ int kernel_sendmsg(struct socket *sock,
 }
 EXPORT_SYMBOL(kernel_sendmsg);
 
+static bool skb_is_err_queue(const struct sk_buff *skb)
+{
+	/* pkt_type of skbs enqueued on the error queue are set to
+	 * PACKET_OUTGOING in skb_set_err_queue(). This is only safe to do
+	 * in recvmsg, since skbs received on a local socket will never
+	 * have a pkt_type of PACKET_OUTGOING.
+	 */
+	return skb->pkt_type == PACKET_OUTGOING;
+}
+
 /*
  * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP)
  */
@@ -697,7 +707,8 @@ void __sock_recv_timestamp(struct msghdr
 		put_cmsg(msg, SOL_SOCKET,
 			 SCM_TIMESTAMPING, sizeof(tss), &tss);
 
-		if (skb->len && (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_STATS))
+		if (skb_is_err_queue(skb) && skb->len &&
+		    (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_STATS))
 			put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_OPT_STATS,
 				 skb->len, skb->data);
 	}

Patches currently in stable-queue which might be from [email protected] are

queue-4.10/tcp-mark-skbs-with-scm_timestamping_opt_stats.patch queue-4.10/secure_seq-downgrade-to-per-host-timestamp-offsets.patch queue-4.10/tcp-fix-scm_timestamping_opt_stats-for-normal-skbs.patch