[PATCH] net/packet: zero-pad spkt_device and preserve sa.origlen across MSG_PEEK
From: Hui Peng <hidden>
Date: 2026-09-19 21:52:40
Also in:
lkml
Subsystem:
networking [general], packet sockets, the rest · Maintainers:
"David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Willem de Bruijn, Linus Torvalds
Fix two issues in net/packet/af_packet.c:
1. In packet_rcv_spkt(), use strscpy_pad() instead of strscpy() when
populating spkt->spkt_device so trailing bytes after dev->name's NUL
terminator in the 14-byte buffer are zeroed.
2. In packet_recvmsg(), PACKET_SKB_CB(skb)->sa.origlen aliases
sll->sll_family and sll->sll_protocol inside the union. Overwriting
sll->sll_family and sll->sll_protocol in PACKET_SKB_CB(skb) directly
clobbers sa.origlen for subsequent recvmsg(MSG_PEEK | MSG_TRUNC) calls
on the same skb. Instead, write sll_family and sll_protocol into the
destination msg->msg_name buffer after copying PACKET_SKB_CB(skb)->sa.
Fixes: 2472d7613bd3 ("net: packet: use sockaddr_ll fields as storage for skb original length in recvmsg path")
Assisted-by: LLM
Signed-off-by: Hui Peng <redacted>
---diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 50cae32ae269..15def2d16806 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c@@ -1918,7 +1918,7 @@ static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev, */ spkt->spkt_family = dev->type; - strscpy(spkt->spkt_device, dev->name, sizeof(spkt->spkt_device)); + strscpy_pad(spkt->spkt_device, dev->name, sizeof(spkt->spkt_device)); spkt->spkt_protocol = skb->protocol; /*
@@ -3510,15 +3510,8 @@ static int packet_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, if (err) goto out_free; - if (sock->type != SOCK_PACKET) { - struct sockaddr_ll *sll = &PACKET_SKB_CB(skb)->sa.ll; - - /* Original length was stored in sockaddr_ll fields */ + if (sock->type != SOCK_PACKET) origlen = PACKET_SKB_CB(skb)->sa.origlen; - sll->sll_family = AF_PACKET; - sll->sll_protocol = (sock->type == SOCK_DGRAM) ? - vlan_get_protocol_dgram(skb) : skb->protocol; - } sock_recv_cmsgs(msg, sk, skb);
@@ -3552,6 +3545,13 @@ static int packet_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, msg->msg_namelen = copy_len; } memcpy(msg->msg_name, &PACKET_SKB_CB(skb)->sa, copy_len); + if (sock->type != SOCK_PACKET) { + struct sockaddr_ll *u_sll = msg->msg_name; + + u_sll->sll_family = AF_PACKET; + u_sll->sll_protocol = (sock->type == SOCK_DGRAM) ? + vlan_get_protocol_dgram(skb) : skb->protocol; + } } if (packet_sock_flag(pkt_sk(sk), PACKET_SOCK_AUXDATA)) {