diff options
Diffstat (limited to 'net/packet/af_packet.c')
-rw-r--r-- | net/packet/af_packet.c | 63 |
1 files changed, 44 insertions, 19 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 8690f171c1ef..499ae3df4a44 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -36,6 +36,11 @@ | |||
36 | * Michal Ostrowski : Module initialization cleanup. | 36 | * Michal Ostrowski : Module initialization cleanup. |
37 | * Ulises Alonso : Frame number limit removal and | 37 | * Ulises Alonso : Frame number limit removal and |
38 | * packet_set_ring memory leak. | 38 | * packet_set_ring memory leak. |
39 | * Eric Biederman : Allow for > 8 byte hardware addresses. | ||
40 | * The convention is that longer addresses | ||
41 | * will simply extend the hardware address | ||
42 | * byte arrays at the end of sockaddr_ll | ||
43 | * and packet_mreq. | ||
39 | * | 44 | * |
40 | * This program is free software; you can redistribute it and/or | 45 | * This program is free software; you can redistribute it and/or |
41 | * modify it under the terms of the GNU General Public License | 46 | * modify it under the terms of the GNU General Public License |
@@ -161,7 +166,17 @@ struct packet_mclist | |||
161 | int count; | 166 | int count; |
162 | unsigned short type; | 167 | unsigned short type; |
163 | unsigned short alen; | 168 | unsigned short alen; |
164 | unsigned char addr[8]; | 169 | unsigned char addr[MAX_ADDR_LEN]; |
170 | }; | ||
171 | /* identical to struct packet_mreq except it has | ||
172 | * a longer address field. | ||
173 | */ | ||
174 | struct packet_mreq_max | ||
175 | { | ||
176 | int mr_ifindex; | ||
177 | unsigned short mr_type; | ||
178 | unsigned short mr_alen; | ||
179 | unsigned char mr_address[MAX_ADDR_LEN]; | ||
165 | }; | 180 | }; |
166 | #endif | 181 | #endif |
167 | #ifdef CONFIG_PACKET_MMAP | 182 | #ifdef CONFIG_PACKET_MMAP |
@@ -639,8 +654,8 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe | |||
639 | __net_timestamp(skb); | 654 | __net_timestamp(skb); |
640 | sock_enable_timestamp(sk); | 655 | sock_enable_timestamp(sk); |
641 | } | 656 | } |
642 | h->tp_sec = skb_tv_base.tv_sec + skb->tstamp.off_sec; | 657 | h->tp_sec = skb->tstamp.off_sec; |
643 | h->tp_usec = skb_tv_base.tv_usec + skb->tstamp.off_usec; | 658 | h->tp_usec = skb->tstamp.off_usec; |
644 | 659 | ||
645 | sll = (struct sockaddr_ll*)((u8*)h + TPACKET_ALIGN(sizeof(*h))); | 660 | sll = (struct sockaddr_ll*)((u8*)h + TPACKET_ALIGN(sizeof(*h))); |
646 | sll->sll_halen = 0; | 661 | sll->sll_halen = 0; |
@@ -716,6 +731,8 @@ static int packet_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
716 | err = -EINVAL; | 731 | err = -EINVAL; |
717 | if (msg->msg_namelen < sizeof(struct sockaddr_ll)) | 732 | if (msg->msg_namelen < sizeof(struct sockaddr_ll)) |
718 | goto out; | 733 | goto out; |
734 | if (msg->msg_namelen < (saddr->sll_halen + offsetof(struct sockaddr_ll, sll_addr))) | ||
735 | goto out; | ||
719 | ifindex = saddr->sll_ifindex; | 736 | ifindex = saddr->sll_ifindex; |
720 | proto = saddr->sll_protocol; | 737 | proto = saddr->sll_protocol; |
721 | addr = saddr->sll_addr; | 738 | addr = saddr->sll_addr; |
@@ -1045,6 +1062,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1045 | struct sock *sk = sock->sk; | 1062 | struct sock *sk = sock->sk; |
1046 | struct sk_buff *skb; | 1063 | struct sk_buff *skb; |
1047 | int copied, err; | 1064 | int copied, err; |
1065 | struct sockaddr_ll *sll; | ||
1048 | 1066 | ||
1049 | err = -EINVAL; | 1067 | err = -EINVAL; |
1050 | if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT)) | 1068 | if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT)) |
@@ -1057,16 +1075,6 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1057 | #endif | 1075 | #endif |
1058 | 1076 | ||
1059 | /* | 1077 | /* |
1060 | * If the address length field is there to be filled in, we fill | ||
1061 | * it in now. | ||
1062 | */ | ||
1063 | |||
1064 | if (sock->type == SOCK_PACKET) | ||
1065 | msg->msg_namelen = sizeof(struct sockaddr_pkt); | ||
1066 | else | ||
1067 | msg->msg_namelen = sizeof(struct sockaddr_ll); | ||
1068 | |||
1069 | /* | ||
1070 | * Call the generic datagram receiver. This handles all sorts | 1078 | * Call the generic datagram receiver. This handles all sorts |
1071 | * of horrible races and re-entrancy so we can forget about it | 1079 | * of horrible races and re-entrancy so we can forget about it |
1072 | * in the protocol layers. | 1080 | * in the protocol layers. |
@@ -1087,6 +1095,17 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1087 | goto out; | 1095 | goto out; |
1088 | 1096 | ||
1089 | /* | 1097 | /* |
1098 | * If the address length field is there to be filled in, we fill | ||
1099 | * it in now. | ||
1100 | */ | ||
1101 | |||
1102 | sll = (struct sockaddr_ll*)skb->cb; | ||
1103 | if (sock->type == SOCK_PACKET) | ||
1104 | msg->msg_namelen = sizeof(struct sockaddr_pkt); | ||
1105 | else | ||
1106 | msg->msg_namelen = sll->sll_halen + offsetof(struct sockaddr_ll, sll_addr); | ||
1107 | |||
1108 | /* | ||
1090 | * You lose any data beyond the buffer you gave. If it worries a | 1109 | * You lose any data beyond the buffer you gave. If it worries a |
1091 | * user program they can ask the device for its MTU anyway. | 1110 | * user program they can ask the device for its MTU anyway. |
1092 | */ | 1111 | */ |
@@ -1166,7 +1185,7 @@ static int packet_getname(struct socket *sock, struct sockaddr *uaddr, | |||
1166 | sll->sll_hatype = 0; /* Bad: we have no ARPHRD_UNSPEC */ | 1185 | sll->sll_hatype = 0; /* Bad: we have no ARPHRD_UNSPEC */ |
1167 | sll->sll_halen = 0; | 1186 | sll->sll_halen = 0; |
1168 | } | 1187 | } |
1169 | *uaddr_len = sizeof(*sll); | 1188 | *uaddr_len = offsetof(struct sockaddr_ll, sll_addr) + sll->sll_halen; |
1170 | 1189 | ||
1171 | return 0; | 1190 | return 0; |
1172 | } | 1191 | } |
@@ -1199,7 +1218,7 @@ static void packet_dev_mclist(struct net_device *dev, struct packet_mclist *i, i | |||
1199 | } | 1218 | } |
1200 | } | 1219 | } |
1201 | 1220 | ||
1202 | static int packet_mc_add(struct sock *sk, struct packet_mreq *mreq) | 1221 | static int packet_mc_add(struct sock *sk, struct packet_mreq_max *mreq) |
1203 | { | 1222 | { |
1204 | struct packet_sock *po = pkt_sk(sk); | 1223 | struct packet_sock *po = pkt_sk(sk); |
1205 | struct packet_mclist *ml, *i; | 1224 | struct packet_mclist *ml, *i; |
@@ -1249,7 +1268,7 @@ done: | |||
1249 | return err; | 1268 | return err; |
1250 | } | 1269 | } |
1251 | 1270 | ||
1252 | static int packet_mc_drop(struct sock *sk, struct packet_mreq *mreq) | 1271 | static int packet_mc_drop(struct sock *sk, struct packet_mreq_max *mreq) |
1253 | { | 1272 | { |
1254 | struct packet_mclist *ml, **mlp; | 1273 | struct packet_mclist *ml, **mlp; |
1255 | 1274 | ||
@@ -1315,11 +1334,17 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv | |||
1315 | case PACKET_ADD_MEMBERSHIP: | 1334 | case PACKET_ADD_MEMBERSHIP: |
1316 | case PACKET_DROP_MEMBERSHIP: | 1335 | case PACKET_DROP_MEMBERSHIP: |
1317 | { | 1336 | { |
1318 | struct packet_mreq mreq; | 1337 | struct packet_mreq_max mreq; |
1319 | if (optlen<sizeof(mreq)) | 1338 | int len = optlen; |
1339 | memset(&mreq, 0, sizeof(mreq)); | ||
1340 | if (len < sizeof(struct packet_mreq)) | ||
1320 | return -EINVAL; | 1341 | return -EINVAL; |
1321 | if (copy_from_user(&mreq,optval,sizeof(mreq))) | 1342 | if (len > sizeof(mreq)) |
1343 | len = sizeof(mreq); | ||
1344 | if (copy_from_user(&mreq,optval,len)) | ||
1322 | return -EFAULT; | 1345 | return -EFAULT; |
1346 | if (len < (mreq.mr_alen + offsetof(struct packet_mreq, mr_address))) | ||
1347 | return -EINVAL; | ||
1323 | if (optname == PACKET_ADD_MEMBERSHIP) | 1348 | if (optname == PACKET_ADD_MEMBERSHIP) |
1324 | ret = packet_mc_add(sk, &mreq); | 1349 | ret = packet_mc_add(sk, &mreq); |
1325 | else | 1350 | else |