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 |
