Message ID | 20220312232958.3535620-1-eric.dumazet@gmail.com (mailing list archive) |
---|---|
State | Accepted |
Commit | c700525fcc06b05adfea78039de02628af79e07a |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | [net] net/packet: fix slab-out-of-bounds access in packet_recvmsg() | expand |
Hello: This patch was applied to netdev/net.git (master) by Jakub Kicinski <kuba@kernel.org>: On Sat, 12 Mar 2022 15:29:58 -0800 you wrote: > From: Eric Dumazet <edumazet@google.com> > > syzbot found that when an AF_PACKET socket is using PACKET_COPY_THRESH > and mmap operations, tpacket_rcv() is queueing skbs with > garbage in skb->cb[], triggering a too big copy [1] > > Presumably, users of af_packet using mmap() already gets correct > metadata from the mapped buffer, we can simply make sure > to clear 12 bytes that might be copied to user space later. > > [...] Here is the summary with links: - [net] net/packet: fix slab-out-of-bounds access in packet_recvmsg() https://git.kernel.org/netdev/net/c/c700525fcc06 You are awesome, thank you!
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 1b93ce1a5600d73284ccb2a2de6c6dbdd9e8dd3c..c39c09899fd0e1c5e7572eda554752e76c481aff 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -2318,8 +2318,11 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, copy_skb = skb_get(skb); skb_head = skb->data; } - if (copy_skb) + if (copy_skb) { + memset(&PACKET_SKB_CB(copy_skb)->sa.ll, 0, + sizeof(PACKET_SKB_CB(copy_skb)->sa.ll)); skb_set_owner_r(copy_skb, sk); + } } snaplen = po->rx_ring.frame_size - macoff; if ((int)snaplen < 0) { @@ -3464,6 +3467,8 @@ static int packet_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, sock_recv_ts_and_drops(msg, sk, skb); if (msg->msg_name) { + const size_t max_len = min(sizeof(skb->cb), + sizeof(struct sockaddr_storage)); int copy_len; /* If the address length field is there to be filled @@ -3486,6 +3491,10 @@ static int packet_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, msg->msg_namelen = sizeof(struct sockaddr_ll); } } + if (WARN_ON_ONCE(copy_len > max_len)) { + copy_len = max_len; + msg->msg_namelen = copy_len; + } memcpy(msg->msg_name, &PACKET_SKB_CB(skb)->sa, copy_len); }