diff options
Diffstat (limited to 'net/socket.c')
-rw-r--r-- | net/socket.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/net/socket.c b/net/socket.c index e034fe4164be..985ef06792d6 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -652,6 +652,16 @@ int kernel_sendmsg(struct socket *sock, struct msghdr *msg, | |||
652 | } | 652 | } |
653 | EXPORT_SYMBOL(kernel_sendmsg); | 653 | EXPORT_SYMBOL(kernel_sendmsg); |
654 | 654 | ||
655 | static bool skb_is_err_queue(const struct sk_buff *skb) | ||
656 | { | ||
657 | /* pkt_type of skbs enqueued on the error queue are set to | ||
658 | * PACKET_OUTGOING in skb_set_err_queue(). This is only safe to do | ||
659 | * in recvmsg, since skbs received on a local socket will never | ||
660 | * have a pkt_type of PACKET_OUTGOING. | ||
661 | */ | ||
662 | return skb->pkt_type == PACKET_OUTGOING; | ||
663 | } | ||
664 | |||
655 | /* | 665 | /* |
656 | * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP) | 666 | * called from sock_recv_timestamp() if sock_flag(sk, SOCK_RCVTSTAMP) |
657 | */ | 667 | */ |
@@ -695,7 +705,8 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, | |||
695 | put_cmsg(msg, SOL_SOCKET, | 705 | put_cmsg(msg, SOL_SOCKET, |
696 | SCM_TIMESTAMPING, sizeof(tss), &tss); | 706 | SCM_TIMESTAMPING, sizeof(tss), &tss); |
697 | 707 | ||
698 | if (skb->len && (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_STATS)) | 708 | if (skb_is_err_queue(skb) && skb->len && |
709 | SKB_EXT_ERR(skb)->opt_stats) | ||
699 | put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_OPT_STATS, | 710 | put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_OPT_STATS, |
700 | skb->len, skb->data); | 711 | skb->len, skb->data); |
701 | } | 712 | } |