aboutsummaryrefslogtreecommitdiffstats
path: root/net/packet
diff options
context:
space:
mode:
authorHannes Frederic Sowa <hannes@stressinduktion.org>2013-11-20 21:14:22 -0500
committerDavid S. Miller <davem@davemloft.net>2013-11-20 21:52:30 -0500
commitf3d3342602f8bcbf37d7c46641cb9bca7618eb1c (patch)
tree11aebad9cca99426db27130b19417141259c81f4 /net/packet
parentf873042093c0b418d2351fe142222b625c740149 (diff)
net: rework recvmsg handler msg_name and msg_namelen logic
This patch now always passes msg->msg_namelen as 0. recvmsg handlers must set msg_namelen to the proper size <= sizeof(struct sockaddr_storage) to return msg_name to the user. This prevents numerous uninitialized memory leaks we had in the recvmsg handlers and makes it harder for new code to accidentally leak uninitialized memory. Optimize for the case recvfrom is called with NULL as address. We don't need to copy the address at all, so set it to NULL before invoking the recvmsg handler. We can do so, because all the recvmsg handlers must cope with the case a plain read() is called on them. read() also sets msg_name to NULL. Also document these changes in include/linux/net.h as suggested by David Miller. Changes since RFC: Set msg->msg_name = NULL if user specified a NULL in msg_name but had a non-null msg_namelen in verify_iovec/verify_compat_iovec. This doesn't affect sendto as it would bail out earlier while trying to copy-in the address. It also more naturally reflects the logic by the callers of verify_iovec. With this change in place I could remove " if (!uaddr || msg_sys->msg_namelen == 0) msg->msg_name = NULL ". This change does not alter the user visible error logic as we ignore msg_namelen as long as msg_name is NULL. Also remove two unnecessary curly brackets in ___sys_recvmsg and change comments to netdev style. Cc: David Miller <davem@davemloft.net> Suggested-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/packet')
-rw-r--r--net/packet/af_packet.c32
1 files changed, 15 insertions, 17 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 2e8286b47c28..61bd50adead1 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -2660,7 +2660,6 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
2660 struct sock *sk = sock->sk; 2660 struct sock *sk = sock->sk;
2661 struct sk_buff *skb; 2661 struct sk_buff *skb;
2662 int copied, err; 2662 int copied, err;
2663 struct sockaddr_ll *sll;
2664 int vnet_hdr_len = 0; 2663 int vnet_hdr_len = 0;
2665 2664
2666 err = -EINVAL; 2665 err = -EINVAL;
@@ -2744,22 +2743,10 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
2744 goto out_free; 2743 goto out_free;
2745 } 2744 }
2746 2745
2747 /* 2746 /* You lose any data beyond the buffer you gave. If it worries
2748 * If the address length field is there to be filled in, we fill 2747 * a user program they can ask the device for its MTU
2749 * it in now. 2748 * anyway.
2750 */
2751
2752 sll = &PACKET_SKB_CB(skb)->sa.ll;
2753 if (sock->type == SOCK_PACKET)
2754 msg->msg_namelen = sizeof(struct sockaddr_pkt);
2755 else
2756 msg->msg_namelen = sll->sll_halen + offsetof(struct sockaddr_ll, sll_addr);
2757
2758 /*
2759 * You lose any data beyond the buffer you gave. If it worries a
2760 * user program they can ask the device for its MTU anyway.
2761 */ 2749 */
2762
2763 copied = skb->len; 2750 copied = skb->len;
2764 if (copied > len) { 2751 if (copied > len) {
2765 copied = len; 2752 copied = len;
@@ -2772,9 +2759,20 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
2772 2759
2773 sock_recv_ts_and_drops(msg, sk, skb); 2760 sock_recv_ts_and_drops(msg, sk, skb);
2774 2761
2775 if (msg->msg_name) 2762 if (msg->msg_name) {
2763 /* If the address length field is there to be filled
2764 * in, we fill it in now.
2765 */
2766 if (sock->type == SOCK_PACKET) {
2767 msg->msg_namelen = sizeof(struct sockaddr_pkt);
2768 } else {
2769 struct sockaddr_ll *sll = &PACKET_SKB_CB(skb)->sa.ll;
2770 msg->msg_namelen = sll->sll_halen +
2771 offsetof(struct sockaddr_ll, sll_addr);
2772 }
2776 memcpy(msg->msg_name, &PACKET_SKB_CB(skb)->sa, 2773 memcpy(msg->msg_name, &PACKET_SKB_CB(skb)->sa,
2777 msg->msg_namelen); 2774 msg->msg_namelen);
2775 }
2778 2776
2779 if (pkt_sk(sk)->auxdata) { 2777 if (pkt_sk(sk)->auxdata) {
2780 struct tpacket_auxdata aux; 2778 struct tpacket_auxdata aux;