aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWillem de Bruijn <willemb@google.com>2019-04-29 11:53:18 -0400
committerDavid S. Miller <davem@davemloft.net>2019-05-01 11:28:35 -0400
commit486efdc8f6ce802b27e15921d2353cc740c55451 (patch)
tree38f6396a1f53717bdd1247a75abb4e632fe2e2ea
parentb2cf86e1563e33a14a1c69b3e508d15dc12f804c (diff)
packet: validate msg_namelen in send directly
Packet sockets in datagram mode take a destination address. Verify its length before passing to dev_hard_header. Prior to 2.6.14-rc3, the send code ignored sll_halen. This is established behavior. Directly compare msg_namelen to dev->addr_len. Change v1->v2: initialize addr in all paths Fixes: 6b8d95f1795c4 ("packet: validate address length if non-zero") Suggested-by: David Laight <David.Laight@aculab.com> Signed-off-by: Willem de Bruijn <willemb@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/packet/af_packet.c24
1 files changed, 14 insertions, 10 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 7d361cd53ad5..9b81813dd16a 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -2602,8 +2602,8 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
2602 void *ph; 2602 void *ph;
2603 DECLARE_SOCKADDR(struct sockaddr_ll *, saddr, msg->msg_name); 2603 DECLARE_SOCKADDR(struct sockaddr_ll *, saddr, msg->msg_name);
2604 bool need_wait = !(msg->msg_flags & MSG_DONTWAIT); 2604 bool need_wait = !(msg->msg_flags & MSG_DONTWAIT);
2605 unsigned char *addr = NULL;
2605 int tp_len, size_max; 2606 int tp_len, size_max;
2606 unsigned char *addr;
2607 void *data; 2607 void *data;
2608 int len_sum = 0; 2608 int len_sum = 0;
2609 int status = TP_STATUS_AVAILABLE; 2609 int status = TP_STATUS_AVAILABLE;
@@ -2614,7 +2614,6 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
2614 if (likely(saddr == NULL)) { 2614 if (likely(saddr == NULL)) {
2615 dev = packet_cached_dev_get(po); 2615 dev = packet_cached_dev_get(po);
2616 proto = po->num; 2616 proto = po->num;
2617 addr = NULL;
2618 } else { 2617 } else {
2619 err = -EINVAL; 2618 err = -EINVAL;
2620 if (msg->msg_namelen < sizeof(struct sockaddr_ll)) 2619 if (msg->msg_namelen < sizeof(struct sockaddr_ll))
@@ -2624,10 +2623,13 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
2624 sll_addr))) 2623 sll_addr)))
2625 goto out; 2624 goto out;
2626 proto = saddr->sll_protocol; 2625 proto = saddr->sll_protocol;
2627 addr = saddr->sll_halen ? saddr->sll_addr : NULL;
2628 dev = dev_get_by_index(sock_net(&po->sk), saddr->sll_ifindex); 2626 dev = dev_get_by_index(sock_net(&po->sk), saddr->sll_ifindex);
2629 if (addr && dev && saddr->sll_halen < dev->addr_len) 2627 if (po->sk.sk_socket->type == SOCK_DGRAM) {
2630 goto out_put; 2628 if (dev && msg->msg_namelen < dev->addr_len +
2629 offsetof(struct sockaddr_ll, sll_addr))
2630 goto out_put;
2631 addr = saddr->sll_addr;
2632 }
2631 } 2633 }
2632 2634
2633 err = -ENXIO; 2635 err = -ENXIO;
@@ -2799,7 +2801,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
2799 struct sk_buff *skb; 2801 struct sk_buff *skb;
2800 struct net_device *dev; 2802 struct net_device *dev;
2801 __be16 proto; 2803 __be16 proto;
2802 unsigned char *addr; 2804 unsigned char *addr = NULL;
2803 int err, reserve = 0; 2805 int err, reserve = 0;
2804 struct sockcm_cookie sockc; 2806 struct sockcm_cookie sockc;
2805 struct virtio_net_hdr vnet_hdr = { 0 }; 2807 struct virtio_net_hdr vnet_hdr = { 0 };
@@ -2816,7 +2818,6 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
2816 if (likely(saddr == NULL)) { 2818 if (likely(saddr == NULL)) {
2817 dev = packet_cached_dev_get(po); 2819 dev = packet_cached_dev_get(po);
2818 proto = po->num; 2820 proto = po->num;
2819 addr = NULL;
2820 } else { 2821 } else {
2821 err = -EINVAL; 2822 err = -EINVAL;
2822 if (msg->msg_namelen < sizeof(struct sockaddr_ll)) 2823 if (msg->msg_namelen < sizeof(struct sockaddr_ll))
@@ -2824,10 +2825,13 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
2824 if (msg->msg_namelen < (saddr->sll_halen + offsetof(struct sockaddr_ll, sll_addr))) 2825 if (msg->msg_namelen < (saddr->sll_halen + offsetof(struct sockaddr_ll, sll_addr)))
2825 goto out; 2826 goto out;
2826 proto = saddr->sll_protocol; 2827 proto = saddr->sll_protocol;
2827 addr = saddr->sll_halen ? saddr->sll_addr : NULL;
2828 dev = dev_get_by_index(sock_net(sk), saddr->sll_ifindex); 2828 dev = dev_get_by_index(sock_net(sk), saddr->sll_ifindex);
2829 if (addr && dev && saddr->sll_halen < dev->addr_len) 2829 if (sock->type == SOCK_DGRAM) {
2830 goto out_unlock; 2830 if (dev && msg->msg_namelen < dev->addr_len +
2831 offsetof(struct sockaddr_ll, sll_addr))
2832 goto out_unlock;
2833 addr = saddr->sll_addr;
2834 }
2831 } 2835 }
2832 2836
2833 err = -ENXIO; 2837 err = -ENXIO;