aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWillem de Bruijn <willemb@google.com>2019-04-29 11:46:55 -0400
committerDavid S. Miller <davem@davemloft.net>2019-05-01 11:27:55 -0400
commitb2cf86e1563e33a14a1c69b3e508d15dc12f804c (patch)
tree4236ee87de8e6e14adabdca0a66f153f4a14b5ba
parentfbd019737d71e405f86549fd738f81e2ff3dd073 (diff)
packet: in recvmsg msg_name return at least sizeof sockaddr_ll
Packet send checks that msg_name is at least sizeof sockaddr_ll. Packet recv must return at least this length, so that its output can be passed unmodified to packet send. This ceased to be true since adding support for lladdr longer than sll_addr. Since, the return value uses true address length. Always return at least sizeof sockaddr_ll, even if address length is shorter. Zero the padding bytes. Change v1->v2: do not overwrite zeroed padding again. use copy_len. Fixes: 0fb375fb9b93 ("[AF_PACKET]: Allow for > 8 byte hardware addresses.") 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.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 9419c5cf4de5..7d361cd53ad5 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -3344,20 +3344,29 @@ static int packet_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
3344 sock_recv_ts_and_drops(msg, sk, skb); 3344 sock_recv_ts_and_drops(msg, sk, skb);
3345 3345
3346 if (msg->msg_name) { 3346 if (msg->msg_name) {
3347 int copy_len;
3348
3347 /* If the address length field is there to be filled 3349 /* If the address length field is there to be filled
3348 * in, we fill it in now. 3350 * in, we fill it in now.
3349 */ 3351 */
3350 if (sock->type == SOCK_PACKET) { 3352 if (sock->type == SOCK_PACKET) {
3351 __sockaddr_check_size(sizeof(struct sockaddr_pkt)); 3353 __sockaddr_check_size(sizeof(struct sockaddr_pkt));
3352 msg->msg_namelen = sizeof(struct sockaddr_pkt); 3354 msg->msg_namelen = sizeof(struct sockaddr_pkt);
3355 copy_len = msg->msg_namelen;
3353 } else { 3356 } else {
3354 struct sockaddr_ll *sll = &PACKET_SKB_CB(skb)->sa.ll; 3357 struct sockaddr_ll *sll = &PACKET_SKB_CB(skb)->sa.ll;
3355 3358
3356 msg->msg_namelen = sll->sll_halen + 3359 msg->msg_namelen = sll->sll_halen +
3357 offsetof(struct sockaddr_ll, sll_addr); 3360 offsetof(struct sockaddr_ll, sll_addr);
3361 copy_len = msg->msg_namelen;
3362 if (msg->msg_namelen < sizeof(struct sockaddr_ll)) {
3363 memset(msg->msg_name +
3364 offsetof(struct sockaddr_ll, sll_addr),
3365 0, sizeof(sll->sll_addr));
3366 msg->msg_namelen = sizeof(struct sockaddr_ll);
3367 }
3358 } 3368 }
3359 memcpy(msg->msg_name, &PACKET_SKB_CB(skb)->sa, 3369 memcpy(msg->msg_name, &PACKET_SKB_CB(skb)->sa, copy_len);
3360 msg->msg_namelen);
3361 } 3370 }
3362 3371
3363 if (pkt_sk(sk)->auxdata) { 3372 if (pkt_sk(sk)->auxdata) {