diff options
Diffstat (limited to 'net/socket.c')
-rw-r--r-- | net/socket.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/net/socket.c b/net/socket.c index 2c1e8677ff2d..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 | } |
@@ -1506,7 +1517,7 @@ SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr, | |||
1506 | if (err) | 1517 | if (err) |
1507 | goto out_fd; | 1518 | goto out_fd; |
1508 | 1519 | ||
1509 | err = sock->ops->accept(sock, newsock, sock->file->f_flags); | 1520 | err = sock->ops->accept(sock, newsock, sock->file->f_flags, false); |
1510 | if (err < 0) | 1521 | if (err < 0) |
1511 | goto out_fd; | 1522 | goto out_fd; |
1512 | 1523 | ||
@@ -1731,6 +1742,7 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size, | |||
1731 | /* We assume all kernel code knows the size of sockaddr_storage */ | 1742 | /* We assume all kernel code knows the size of sockaddr_storage */ |
1732 | msg.msg_namelen = 0; | 1743 | msg.msg_namelen = 0; |
1733 | msg.msg_iocb = NULL; | 1744 | msg.msg_iocb = NULL; |
1745 | msg.msg_flags = 0; | ||
1734 | if (sock->file->f_flags & O_NONBLOCK) | 1746 | if (sock->file->f_flags & O_NONBLOCK) |
1735 | flags |= MSG_DONTWAIT; | 1747 | flags |= MSG_DONTWAIT; |
1736 | err = sock_recvmsg(sock, &msg, flags); | 1748 | err = sock_recvmsg(sock, &msg, flags); |
@@ -3238,7 +3250,7 @@ int kernel_accept(struct socket *sock, struct socket **newsock, int flags) | |||
3238 | if (err < 0) | 3250 | if (err < 0) |
3239 | goto done; | 3251 | goto done; |
3240 | 3252 | ||
3241 | err = sock->ops->accept(sock, *newsock, flags); | 3253 | err = sock->ops->accept(sock, *newsock, flags, true); |
3242 | if (err < 0) { | 3254 | if (err < 0) { |
3243 | sock_release(*newsock); | 3255 | sock_release(*newsock); |
3244 | *newsock = NULL; | 3256 | *newsock = NULL; |