summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorYun Lu <luyun@kylinos.cn>2025-07-11 17:32:59 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-07-24 08:51:48 +0200
commit1322a7a082ec6514d3d8d988dec39365be2acebe (patch)
tree8c12fc059723786f1c132ad55e083e4ed5f30b2a /net
parentae689b7485c85bc7b6f1cf6cb874654f81aa91b6 (diff)
downloadlinux-1322a7a082ec6514d3d8d988dec39365be2acebe.tar.gz
linux-1322a7a082ec6514d3d8d988dec39365be2acebe.tar.bz2
linux-1322a7a082ec6514d3d8d988dec39365be2acebe.zip
af_packet: fix the SO_SNDTIMEO constraint not effective on tpacked_snd()
commit c1ba3c0cbdb5e53a8ec5d708e99cd4c497028a13 upstream. Due to the changes in commit 581073f626e3 ("af_packet: do not call packet_read_pending() from tpacket_destruct_skb()"), every time tpacket_destruct_skb() is executed, the skb_completion is marked as completed. When wait_for_completion_interruptible_timeout() returns completed, the pending_refcnt has not yet been reduced to zero. Therefore, when ph is NULL, the wait function may need to be called multiple times until packet_read_pending() finally returns zero. We should call sock_sndtimeo() only once, otherwise the SO_SNDTIMEO constraint could be way off. Fixes: 581073f626e3 ("af_packet: do not call packet_read_pending() from tpacket_destruct_skb()") Cc: stable@kernel.org Suggested-by: Eric Dumazet <edumazet@google.com> Signed-off-by: Yun Lu <luyun@kylinos.cn> Reviewed-by: Eric Dumazet <edumazet@google.com> Reviewed-by: Willem de Bruijn <willemb@google.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net')
-rw-r--r--net/packet/af_packet.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index f3bd3e126703..0fae23902bd0 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -2780,7 +2780,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
int len_sum = 0;
int status = TP_STATUS_AVAILABLE;
int hlen, tlen, copylen = 0;
- long timeo = 0;
+ long timeo;
mutex_lock(&po->pg_vec_lock);
@@ -2834,6 +2834,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
if ((size_max > dev->mtu + reserve + VLAN_HLEN) && !po->has_vnet_hdr)
size_max = dev->mtu + reserve + VLAN_HLEN;
+ timeo = sock_sndtimeo(&po->sk, msg->msg_flags & MSG_DONTWAIT);
reinit_completion(&po->skb_completion);
do {
@@ -2841,7 +2842,6 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
TP_STATUS_SEND_REQUEST);
if (unlikely(ph == NULL)) {
if (need_wait && skb) {
- timeo = sock_sndtimeo(&po->sk, msg->msg_flags & MSG_DONTWAIT);
timeo = wait_for_completion_interruptible_timeout(&po->skb_completion, timeo);
if (timeo <= 0) {
err = !timeo ? -ETIMEDOUT : -ERESTARTSYS;