]>
Commit | Line | Data |
---|---|---|
15e6eb8b GKH |
1 | From foo@baz Sat 04 May 2019 11:25:56 AM CEST |
2 | From: Willem de Bruijn <willemb@google.com> | |
3 | Date: Mon, 29 Apr 2019 11:53:18 -0400 | |
4 | Subject: packet: validate msg_namelen in send directly | |
5 | ||
6 | From: Willem de Bruijn <willemb@google.com> | |
7 | ||
8 | [ Upstream commit 486efdc8f6ce802b27e15921d2353cc740c55451 ] | |
9 | ||
10 | Packet sockets in datagram mode take a destination address. Verify its | |
11 | length before passing to dev_hard_header. | |
12 | ||
13 | Prior to 2.6.14-rc3, the send code ignored sll_halen. This is | |
14 | established behavior. Directly compare msg_namelen to dev->addr_len. | |
15 | ||
16 | Change v1->v2: initialize addr in all paths | |
17 | ||
18 | Fixes: 6b8d95f1795c4 ("packet: validate address length if non-zero") | |
19 | Suggested-by: David Laight <David.Laight@aculab.com> | |
20 | Signed-off-by: Willem de Bruijn <willemb@google.com> | |
21 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
22 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
23 | --- | |
24 | net/packet/af_packet.c | 24 ++++++++++++++---------- | |
25 | 1 file changed, 14 insertions(+), 10 deletions(-) | |
26 | ||
27 | --- a/net/packet/af_packet.c | |
28 | +++ b/net/packet/af_packet.c | |
29 | @@ -2641,8 +2641,8 @@ static int tpacket_snd(struct packet_soc | |
30 | void *ph; | |
31 | DECLARE_SOCKADDR(struct sockaddr_ll *, saddr, msg->msg_name); | |
32 | bool need_wait = !(msg->msg_flags & MSG_DONTWAIT); | |
33 | + unsigned char *addr = NULL; | |
34 | int tp_len, size_max; | |
35 | - unsigned char *addr; | |
36 | void *data; | |
37 | int len_sum = 0; | |
38 | int status = TP_STATUS_AVAILABLE; | |
39 | @@ -2653,7 +2653,6 @@ static int tpacket_snd(struct packet_soc | |
40 | if (likely(saddr == NULL)) { | |
41 | dev = packet_cached_dev_get(po); | |
42 | proto = po->num; | |
43 | - addr = NULL; | |
44 | } else { | |
45 | err = -EINVAL; | |
46 | if (msg->msg_namelen < sizeof(struct sockaddr_ll)) | |
47 | @@ -2663,10 +2662,13 @@ static int tpacket_snd(struct packet_soc | |
48 | sll_addr))) | |
49 | goto out; | |
50 | proto = saddr->sll_protocol; | |
51 | - addr = saddr->sll_halen ? saddr->sll_addr : NULL; | |
52 | dev = dev_get_by_index(sock_net(&po->sk), saddr->sll_ifindex); | |
53 | - if (addr && dev && saddr->sll_halen < dev->addr_len) | |
54 | - goto out_put; | |
55 | + if (po->sk.sk_socket->type == SOCK_DGRAM) { | |
56 | + if (dev && msg->msg_namelen < dev->addr_len + | |
57 | + offsetof(struct sockaddr_ll, sll_addr)) | |
58 | + goto out_put; | |
59 | + addr = saddr->sll_addr; | |
60 | + } | |
61 | } | |
62 | ||
63 | err = -ENXIO; | |
64 | @@ -2838,7 +2840,7 @@ static int packet_snd(struct socket *soc | |
65 | struct sk_buff *skb; | |
66 | struct net_device *dev; | |
67 | __be16 proto; | |
68 | - unsigned char *addr; | |
69 | + unsigned char *addr = NULL; | |
70 | int err, reserve = 0; | |
71 | struct sockcm_cookie sockc; | |
72 | struct virtio_net_hdr vnet_hdr = { 0 }; | |
73 | @@ -2855,7 +2857,6 @@ static int packet_snd(struct socket *soc | |
74 | if (likely(saddr == NULL)) { | |
75 | dev = packet_cached_dev_get(po); | |
76 | proto = po->num; | |
77 | - addr = NULL; | |
78 | } else { | |
79 | err = -EINVAL; | |
80 | if (msg->msg_namelen < sizeof(struct sockaddr_ll)) | |
81 | @@ -2863,10 +2864,13 @@ static int packet_snd(struct socket *soc | |
82 | if (msg->msg_namelen < (saddr->sll_halen + offsetof(struct sockaddr_ll, sll_addr))) | |
83 | goto out; | |
84 | proto = saddr->sll_protocol; | |
85 | - addr = saddr->sll_halen ? saddr->sll_addr : NULL; | |
86 | dev = dev_get_by_index(sock_net(sk), saddr->sll_ifindex); | |
87 | - if (addr && dev && saddr->sll_halen < dev->addr_len) | |
88 | - goto out_unlock; | |
89 | + if (sock->type == SOCK_DGRAM) { | |
90 | + if (dev && msg->msg_namelen < dev->addr_len + | |
91 | + offsetof(struct sockaddr_ll, sll_addr)) | |
92 | + goto out_unlock; | |
93 | + addr = saddr->sll_addr; | |
94 | + } | |
95 | } | |
96 | ||
97 | err = -ENXIO; |