diff options
Diffstat (limited to 'drivers/net/pppoe.c')
-rw-r--r-- | drivers/net/pppoe.c | 156 |
1 files changed, 76 insertions, 80 deletions
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index ebfa2967cd68..6f98834e6ace 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c | |||
@@ -207,7 +207,7 @@ static inline struct pppox_sock *get_item(unsigned long sid, | |||
207 | 207 | ||
208 | static inline struct pppox_sock *get_item_by_addr(struct sockaddr_pppox *sp) | 208 | static inline struct pppox_sock *get_item_by_addr(struct sockaddr_pppox *sp) |
209 | { | 209 | { |
210 | struct net_device *dev = NULL; | 210 | struct net_device *dev; |
211 | int ifindex; | 211 | int ifindex; |
212 | 212 | ||
213 | dev = dev_get_by_name(sp->sa_addr.pppoe.dev); | 213 | dev = dev_get_by_name(sp->sa_addr.pppoe.dev); |
@@ -218,20 +218,6 @@ static inline struct pppox_sock *get_item_by_addr(struct sockaddr_pppox *sp) | |||
218 | return get_item(sp->sa_addr.pppoe.sid, sp->sa_addr.pppoe.remote, ifindex); | 218 | return get_item(sp->sa_addr.pppoe.sid, sp->sa_addr.pppoe.remote, ifindex); |
219 | } | 219 | } |
220 | 220 | ||
221 | static inline int set_item(struct pppox_sock *po) | ||
222 | { | ||
223 | int i; | ||
224 | |||
225 | if (!po) | ||
226 | return -EINVAL; | ||
227 | |||
228 | write_lock_bh(&pppoe_hash_lock); | ||
229 | i = __set_item(po); | ||
230 | write_unlock_bh(&pppoe_hash_lock); | ||
231 | |||
232 | return i; | ||
233 | } | ||
234 | |||
235 | static inline struct pppox_sock *delete_item(unsigned long sid, char *addr, int ifindex) | 221 | static inline struct pppox_sock *delete_item(unsigned long sid, char *addr, int ifindex) |
236 | { | 222 | { |
237 | struct pppox_sock *ret; | 223 | struct pppox_sock *ret; |
@@ -255,54 +241,53 @@ static inline struct pppox_sock *delete_item(unsigned long sid, char *addr, int | |||
255 | static void pppoe_flush_dev(struct net_device *dev) | 241 | static void pppoe_flush_dev(struct net_device *dev) |
256 | { | 242 | { |
257 | int hash; | 243 | int hash; |
258 | |||
259 | BUG_ON(dev == NULL); | 244 | BUG_ON(dev == NULL); |
260 | 245 | ||
261 | read_lock_bh(&pppoe_hash_lock); | 246 | write_lock_bh(&pppoe_hash_lock); |
262 | for (hash = 0; hash < PPPOE_HASH_SIZE; hash++) { | 247 | for (hash = 0; hash < PPPOE_HASH_SIZE; hash++) { |
263 | struct pppox_sock *po = item_hash_table[hash]; | 248 | struct pppox_sock *po = item_hash_table[hash]; |
264 | 249 | ||
265 | while (po != NULL) { | 250 | while (po != NULL) { |
266 | if (po->pppoe_dev == dev) { | 251 | struct sock *sk = sk_pppox(po); |
267 | struct sock *sk = sk_pppox(po); | 252 | if (po->pppoe_dev != dev) { |
268 | 253 | po = po->next; | |
269 | sock_hold(sk); | 254 | continue; |
270 | po->pppoe_dev = NULL; | 255 | } |
256 | po->pppoe_dev = NULL; | ||
257 | dev_put(dev); | ||
271 | 258 | ||
272 | /* We hold a reference to SK, now drop the | ||
273 | * hash table lock so that we may attempt | ||
274 | * to lock the socket (which can sleep). | ||
275 | */ | ||
276 | read_unlock_bh(&pppoe_hash_lock); | ||
277 | 259 | ||
278 | lock_sock(sk); | 260 | /* We always grab the socket lock, followed by the |
261 | * pppoe_hash_lock, in that order. Since we should | ||
262 | * hold the sock lock while doing any unbinding, | ||
263 | * we need to release the lock we're holding. | ||
264 | * Hold a reference to the sock so it doesn't disappear | ||
265 | * as we're jumping between locks. | ||
266 | */ | ||
279 | 267 | ||
280 | if (sk->sk_state & | 268 | sock_hold(sk); |
281 | (PPPOX_CONNECTED | PPPOX_BOUND)) { | ||
282 | pppox_unbind_sock(sk); | ||
283 | dev_put(dev); | ||
284 | sk->sk_state = PPPOX_ZOMBIE; | ||
285 | sk->sk_state_change(sk); | ||
286 | } | ||
287 | 269 | ||
288 | release_sock(sk); | 270 | write_unlock_bh(&pppoe_hash_lock); |
271 | lock_sock(sk); | ||
289 | 272 | ||
290 | sock_put(sk); | 273 | if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) { |
274 | pppox_unbind_sock(sk); | ||
275 | sk->sk_state = PPPOX_ZOMBIE; | ||
276 | sk->sk_state_change(sk); | ||
277 | } | ||
291 | 278 | ||
292 | read_lock_bh(&pppoe_hash_lock); | 279 | release_sock(sk); |
280 | sock_put(sk); | ||
293 | 281 | ||
294 | /* Now restart from the beginning of this | 282 | /* Restart scan at the beginning of this hash chain. |
295 | * hash chain. We always NULL out pppoe_dev | 283 | * While the lock was dropped the chain contents may |
296 | * so we are guaranteed to make forward | 284 | * have changed. |
297 | * progress. | 285 | */ |
298 | */ | 286 | write_lock_bh(&pppoe_hash_lock); |
299 | po = item_hash_table[hash]; | 287 | po = item_hash_table[hash]; |
300 | continue; | ||
301 | } | ||
302 | po = po->next; | ||
303 | } | 288 | } |
304 | } | 289 | } |
305 | read_unlock_bh(&pppoe_hash_lock); | 290 | write_unlock_bh(&pppoe_hash_lock); |
306 | } | 291 | } |
307 | 292 | ||
308 | static int pppoe_device_event(struct notifier_block *this, | 293 | static int pppoe_device_event(struct notifier_block *this, |
@@ -344,10 +329,10 @@ static struct notifier_block pppoe_notifier = { | |||
344 | static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb) | 329 | static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb) |
345 | { | 330 | { |
346 | struct pppox_sock *po = pppox_sk(sk); | 331 | struct pppox_sock *po = pppox_sk(sk); |
347 | struct pppox_sock *relay_po = NULL; | 332 | struct pppox_sock *relay_po; |
348 | 333 | ||
349 | if (sk->sk_state & PPPOX_BOUND) { | 334 | if (sk->sk_state & PPPOX_BOUND) { |
350 | struct pppoe_hdr *ph = (struct pppoe_hdr *) skb->nh.raw; | 335 | struct pppoe_hdr *ph = pppoe_hdr(skb); |
351 | int len = ntohs(ph->length); | 336 | int len = ntohs(ph->length); |
352 | skb_pull_rcsum(skb, sizeof(struct pppoe_hdr)); | 337 | skb_pull_rcsum(skb, sizeof(struct pppoe_hdr)); |
353 | if (pskb_trim_rcsum(skb, len)) | 338 | if (pskb_trim_rcsum(skb, len)) |
@@ -401,7 +386,7 @@ static int pppoe_rcv(struct sk_buff *skb, | |||
401 | if (!(skb = skb_share_check(skb, GFP_ATOMIC))) | 386 | if (!(skb = skb_share_check(skb, GFP_ATOMIC))) |
402 | goto out; | 387 | goto out; |
403 | 388 | ||
404 | ph = (struct pppoe_hdr *) skb->nh.raw; | 389 | ph = pppoe_hdr(skb); |
405 | 390 | ||
406 | po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source, dev->ifindex); | 391 | po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source, dev->ifindex); |
407 | if (po != NULL) | 392 | if (po != NULL) |
@@ -433,7 +418,7 @@ static int pppoe_disc_rcv(struct sk_buff *skb, | |||
433 | if (!(skb = skb_share_check(skb, GFP_ATOMIC))) | 418 | if (!(skb = skb_share_check(skb, GFP_ATOMIC))) |
434 | goto out; | 419 | goto out; |
435 | 420 | ||
436 | ph = (struct pppoe_hdr *) skb->nh.raw; | 421 | ph = pppoe_hdr(skb); |
437 | if (ph->code != PADT_CODE) | 422 | if (ph->code != PADT_CODE) |
438 | goto abort; | 423 | goto abort; |
439 | 424 | ||
@@ -514,36 +499,49 @@ static int pppoe_release(struct socket *sock) | |||
514 | { | 499 | { |
515 | struct sock *sk = sock->sk; | 500 | struct sock *sk = sock->sk; |
516 | struct pppox_sock *po; | 501 | struct pppox_sock *po; |
517 | int error = 0; | ||
518 | 502 | ||
519 | if (!sk) | 503 | if (!sk) |
520 | return 0; | 504 | return 0; |
521 | 505 | ||
522 | if (sock_flag(sk, SOCK_DEAD)) | 506 | lock_sock(sk); |
507 | if (sock_flag(sk, SOCK_DEAD)){ | ||
508 | release_sock(sk); | ||
523 | return -EBADF; | 509 | return -EBADF; |
510 | } | ||
524 | 511 | ||
525 | pppox_unbind_sock(sk); | 512 | pppox_unbind_sock(sk); |
526 | 513 | ||
527 | /* Signal the death of the socket. */ | 514 | /* Signal the death of the socket. */ |
528 | sk->sk_state = PPPOX_DEAD; | 515 | sk->sk_state = PPPOX_DEAD; |
529 | 516 | ||
517 | |||
518 | /* Write lock on hash lock protects the entire "po" struct from | ||
519 | * concurrent updates via pppoe_flush_dev. The "po" struct should | ||
520 | * be considered part of the hash table contents, thus protected | ||
521 | * by the hash table lock */ | ||
522 | write_lock_bh(&pppoe_hash_lock); | ||
523 | |||
530 | po = pppox_sk(sk); | 524 | po = pppox_sk(sk); |
531 | if (po->pppoe_pa.sid) { | 525 | if (po->pppoe_pa.sid) { |
532 | delete_item(po->pppoe_pa.sid, po->pppoe_pa.remote, po->pppoe_ifindex); | 526 | __delete_item(po->pppoe_pa.sid, |
527 | po->pppoe_pa.remote, po->pppoe_ifindex); | ||
533 | } | 528 | } |
534 | 529 | ||
535 | if (po->pppoe_dev) | 530 | if (po->pppoe_dev) { |
536 | dev_put(po->pppoe_dev); | 531 | dev_put(po->pppoe_dev); |
532 | po->pppoe_dev = NULL; | ||
533 | } | ||
537 | 534 | ||
538 | po->pppoe_dev = NULL; | 535 | write_unlock_bh(&pppoe_hash_lock); |
539 | 536 | ||
540 | sock_orphan(sk); | 537 | sock_orphan(sk); |
541 | sock->sk = NULL; | 538 | sock->sk = NULL; |
542 | 539 | ||
543 | skb_queue_purge(&sk->sk_receive_queue); | 540 | skb_queue_purge(&sk->sk_receive_queue); |
541 | release_sock(sk); | ||
544 | sock_put(sk); | 542 | sock_put(sk); |
545 | 543 | ||
546 | return error; | 544 | return 0; |
547 | } | 545 | } |
548 | 546 | ||
549 | 547 | ||
@@ -599,14 +597,18 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr, | |||
599 | po->pppoe_dev = dev; | 597 | po->pppoe_dev = dev; |
600 | po->pppoe_ifindex = dev->ifindex; | 598 | po->pppoe_ifindex = dev->ifindex; |
601 | 599 | ||
602 | if (!(dev->flags & IFF_UP)) | 600 | write_lock_bh(&pppoe_hash_lock); |
601 | if (!(dev->flags & IFF_UP)){ | ||
602 | write_unlock_bh(&pppoe_hash_lock); | ||
603 | goto err_put; | 603 | goto err_put; |
604 | } | ||
604 | 605 | ||
605 | memcpy(&po->pppoe_pa, | 606 | memcpy(&po->pppoe_pa, |
606 | &sp->sa_addr.pppoe, | 607 | &sp->sa_addr.pppoe, |
607 | sizeof(struct pppoe_addr)); | 608 | sizeof(struct pppoe_addr)); |
608 | 609 | ||
609 | error = set_item(po); | 610 | error = __set_item(po); |
611 | write_unlock_bh(&pppoe_hash_lock); | ||
610 | if (error < 0) | 612 | if (error < 0) |
611 | goto err_put; | 613 | goto err_put; |
612 | 614 | ||
@@ -762,10 +764,10 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd, | |||
762 | static int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock, | 764 | static int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock, |
763 | struct msghdr *m, size_t total_len) | 765 | struct msghdr *m, size_t total_len) |
764 | { | 766 | { |
765 | struct sk_buff *skb = NULL; | 767 | struct sk_buff *skb; |
766 | struct sock *sk = sock->sk; | 768 | struct sock *sk = sock->sk; |
767 | struct pppox_sock *po = pppox_sk(sk); | 769 | struct pppox_sock *po = pppox_sk(sk); |
768 | int error = 0; | 770 | int error; |
769 | struct pppoe_hdr hdr; | 771 | struct pppoe_hdr hdr; |
770 | struct pppoe_hdr *ph; | 772 | struct pppoe_hdr *ph; |
771 | struct net_device *dev; | 773 | struct net_device *dev; |
@@ -799,7 +801,7 @@ static int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
799 | 801 | ||
800 | /* Reserve space for headers. */ | 802 | /* Reserve space for headers. */ |
801 | skb_reserve(skb, dev->hard_header_len); | 803 | skb_reserve(skb, dev->hard_header_len); |
802 | skb->nh.raw = skb->data; | 804 | skb_reset_network_header(skb); |
803 | 805 | ||
804 | skb->dev = dev; | 806 | skb->dev = dev; |
805 | 807 | ||
@@ -869,7 +871,8 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb) | |||
869 | goto abort; | 871 | goto abort; |
870 | 872 | ||
871 | skb_reserve(skb2, dev->hard_header_len + sizeof(struct pppoe_hdr)); | 873 | skb_reserve(skb2, dev->hard_header_len + sizeof(struct pppoe_hdr)); |
872 | memcpy(skb_put(skb2, skb->len), skb->data, skb->len); | 874 | skb_copy_from_linear_data(skb, skb_put(skb2, skb->len), |
875 | skb->len); | ||
873 | } else { | 876 | } else { |
874 | /* Make a clone so as to not disturb the original skb, | 877 | /* Make a clone so as to not disturb the original skb, |
875 | * give dev_queue_xmit something it can free. | 878 | * give dev_queue_xmit something it can free. |
@@ -884,7 +887,7 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb) | |||
884 | memcpy(ph, &hdr, sizeof(struct pppoe_hdr)); | 887 | memcpy(ph, &hdr, sizeof(struct pppoe_hdr)); |
885 | skb2->protocol = __constant_htons(ETH_P_PPP_SES); | 888 | skb2->protocol = __constant_htons(ETH_P_PPP_SES); |
886 | 889 | ||
887 | skb2->nh.raw = skb2->data; | 890 | skb_reset_network_header(skb2); |
888 | 891 | ||
889 | skb2->dev = dev; | 892 | skb2->dev = dev; |
890 | 893 | ||
@@ -929,10 +932,8 @@ static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
929 | struct msghdr *m, size_t total_len, int flags) | 932 | struct msghdr *m, size_t total_len, int flags) |
930 | { | 933 | { |
931 | struct sock *sk = sock->sk; | 934 | struct sock *sk = sock->sk; |
932 | struct sk_buff *skb = NULL; | 935 | struct sk_buff *skb; |
933 | int error = 0; | 936 | int error = 0; |
934 | int len; | ||
935 | struct pppoe_hdr *ph = NULL; | ||
936 | 937 | ||
937 | if (sk->sk_state & PPPOX_BOUND) { | 938 | if (sk->sk_state & PPPOX_BOUND) { |
938 | error = -EIO; | 939 | error = -EIO; |
@@ -942,26 +943,21 @@ static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
942 | skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, | 943 | skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, |
943 | flags & MSG_DONTWAIT, &error); | 944 | flags & MSG_DONTWAIT, &error); |
944 | 945 | ||
945 | if (error < 0) { | 946 | if (error < 0) |
946 | goto end; | 947 | goto end; |
947 | } | ||
948 | 948 | ||
949 | m->msg_namelen = 0; | 949 | m->msg_namelen = 0; |
950 | 950 | ||
951 | if (skb) { | 951 | if (skb) { |
952 | error = 0; | 952 | struct pppoe_hdr *ph = pppoe_hdr(skb); |
953 | ph = (struct pppoe_hdr *) skb->nh.raw; | 953 | const int len = ntohs(ph->length); |
954 | len = ntohs(ph->length); | ||
955 | 954 | ||
956 | error = memcpy_toiovec(m->msg_iov, (unsigned char *) &ph->tag[0], len); | 955 | error = memcpy_toiovec(m->msg_iov, (unsigned char *) &ph->tag[0], len); |
957 | if (error < 0) | 956 | if (error == 0) |
958 | goto do_skb_free; | 957 | error = len; |
959 | error = len; | ||
960 | } | 958 | } |
961 | 959 | ||
962 | do_skb_free: | 960 | kfree_skb(skb); |
963 | if (skb) | ||
964 | kfree_skb(skb); | ||
965 | end: | 961 | end: |
966 | return error; | 962 | return error; |
967 | } | 963 | } |
@@ -991,7 +987,7 @@ out: | |||
991 | 987 | ||
992 | static __inline__ struct pppox_sock *pppoe_get_idx(loff_t pos) | 988 | static __inline__ struct pppox_sock *pppoe_get_idx(loff_t pos) |
993 | { | 989 | { |
994 | struct pppox_sock *po = NULL; | 990 | struct pppox_sock *po; |
995 | int i = 0; | 991 | int i = 0; |
996 | 992 | ||
997 | for (; i < PPPOE_HASH_SIZE; i++) { | 993 | for (; i < PPPOE_HASH_SIZE; i++) { |