Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[LLC]: Fix the accept path

Borrowing the structure of TCP/IP for this. On the receive of new connections I
was bh_lock_socking the _new_ sock, not the listening one, duh, now it survives
the ssh connections storm I've been using to test this specific bug.

Also fixes send side skb sock accounting.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>

+133 -94
+2 -1
include/net/llc_sap.h
··· 19 19 extern void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb); 20 20 extern void llc_save_primitive(struct sock *sk, struct sk_buff* skb, 21 21 unsigned char prim); 22 - extern struct sk_buff *llc_alloc_frame(struct net_device *dev); 22 + extern struct sk_buff *llc_alloc_frame(struct sock *sk, 23 + struct net_device *dev); 23 24 24 25 extern void llc_build_and_send_test_pkt(struct llc_sap *sap, 25 26 struct sk_buff *skb,
+25 -39
net/llc/llc_c_ac.c
··· 60 60 61 61 int llc_conn_ac_conn_ind(struct sock *sk, struct sk_buff *skb) 62 62 { 63 - int rc = -ENOTCONN; 64 - u8 dsap; 65 - struct llc_sap *sap; 63 + struct llc_conn_state_ev *ev = llc_conn_ev(skb); 66 64 67 - llc_pdu_decode_dsap(skb, &dsap); 68 - sap = llc_sap_find(dsap); 69 - if (sap) { 70 - struct llc_conn_state_ev *ev = llc_conn_ev(skb); 71 - struct llc_sock *llc = llc_sk(sk); 72 - 73 - llc_pdu_decode_sa(skb, llc->daddr.mac); 74 - llc_pdu_decode_da(skb, llc->laddr.mac); 75 - llc->dev = skb->dev; 76 - ev->ind_prim = LLC_CONN_PRIM; 77 - rc = 0; 78 - llc_sap_put(sap); 79 - } 80 - return rc; 65 + ev->ind_prim = LLC_CONN_PRIM; 66 + return 0; 81 67 } 82 68 83 69 int llc_conn_ac_conn_confirm(struct sock *sk, struct sk_buff *skb) ··· 199 213 { 200 214 int rc = -ENOBUFS; 201 215 struct llc_sock *llc = llc_sk(sk); 202 - struct sk_buff *nskb = llc_alloc_frame(llc->dev); 216 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 203 217 204 218 if (nskb) { 205 219 struct llc_sap *sap = llc->sap; ··· 224 238 { 225 239 int rc = -ENOBUFS; 226 240 struct llc_sock *llc = llc_sk(sk); 227 - struct sk_buff *nskb = llc_alloc_frame(llc->dev); 241 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 228 242 229 243 if (nskb) { 230 244 struct llc_sap *sap = llc->sap; ··· 250 264 { 251 265 int rc = -ENOBUFS; 252 266 struct llc_sock *llc = llc_sk(sk); 253 - struct sk_buff *nskb = llc_alloc_frame(llc->dev); 267 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 254 268 255 269 if (nskb) { 256 270 struct llc_sap *sap = llc->sap; ··· 283 297 llc_pdu_decode_pf_bit(skb, &f_bit); 284 298 else 285 299 f_bit = 0; 286 - nskb = llc_alloc_frame(llc->dev); 300 + nskb = llc_alloc_frame(sk, llc->dev); 287 301 if (nskb) { 288 302 struct llc_sap *sap = llc->sap; 289 303 ··· 307 321 { 308 322 int rc = -ENOBUFS; 309 323 struct llc_sock *llc = llc_sk(sk); 310 - struct sk_buff *nskb = llc_alloc_frame(llc->dev); 324 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 311 325 312 326 if (nskb) { 313 327 struct llc_sap *sap = llc->sap; ··· 337 351 struct llc_sock *llc = llc_sk(sk); 338 352 339 353 llc_pdu_decode_pf_bit(skb, &f_bit); 340 - nskb = llc_alloc_frame(llc->dev); 354 + nskb = llc_alloc_frame(sk, llc->dev); 341 355 if (nskb) { 342 356 struct llc_sap *sap = llc->sap; 343 357 struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); ··· 425 439 struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); 426 440 int rc = -ENOBUFS; 427 441 struct llc_sock *llc = llc_sk(sk); 428 - struct sk_buff *nskb = llc_alloc_frame(llc->dev); 442 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 429 443 430 444 if (nskb) { 431 445 struct llc_sap *sap = llc->sap; ··· 460 474 { 461 475 int rc = -ENOBUFS; 462 476 struct llc_sock *llc = llc_sk(sk); 463 - struct sk_buff *nskb = llc_alloc_frame(llc->dev); 477 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 464 478 465 479 if (nskb) { 466 480 struct llc_sap *sap = llc->sap; ··· 484 498 { 485 499 int rc = -ENOBUFS; 486 500 struct llc_sock *llc = llc_sk(sk); 487 - struct sk_buff *nskb = llc_alloc_frame(llc->dev); 501 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 488 502 489 503 if (nskb) { 490 504 struct llc_sap *sap = llc->sap; ··· 508 522 { 509 523 int rc = -ENOBUFS; 510 524 struct llc_sock *llc = llc_sk(sk); 511 - struct sk_buff *nskb = llc_alloc_frame(llc->dev); 525 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 512 526 513 527 if (nskb) { 514 528 struct llc_sap *sap = llc->sap; ··· 532 546 { 533 547 int rc = -ENOBUFS; 534 548 struct llc_sock *llc = llc_sk(sk); 535 - struct sk_buff *nskb = llc_alloc_frame(llc->dev); 549 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 536 550 537 551 if (nskb) { 538 552 struct llc_sap *sap = llc->sap; ··· 556 570 { 557 571 int rc = -ENOBUFS; 558 572 struct llc_sock *llc = llc_sk(sk); 559 - struct sk_buff *nskb = llc_alloc_frame(llc->dev); 573 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 560 574 561 575 if (nskb) { 562 576 struct llc_sap *sap = llc->sap; ··· 580 594 { 581 595 int rc = -ENOBUFS; 582 596 struct llc_sock *llc = llc_sk(sk); 583 - struct sk_buff *nskb = llc_alloc_frame(llc->dev); 597 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 584 598 585 599 if (nskb) { 586 600 struct llc_sap *sap = llc->sap; ··· 616 630 { 617 631 int rc = -ENOBUFS; 618 632 struct llc_sock *llc = llc_sk(sk); 619 - struct sk_buff *nskb = llc_alloc_frame(llc->dev); 633 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 620 634 621 635 if (nskb) { 622 636 struct llc_sap *sap = llc->sap; ··· 640 654 { 641 655 int rc = -ENOBUFS; 642 656 struct llc_sock *llc = llc_sk(sk); 643 - struct sk_buff *nskb = llc_alloc_frame(llc->dev); 657 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 644 658 645 659 if (nskb) { 646 660 struct llc_sap *sap = llc->sap; ··· 664 678 { 665 679 int rc = -ENOBUFS; 666 680 struct llc_sock *llc = llc_sk(sk); 667 - struct sk_buff *nskb = llc_alloc_frame(llc->dev); 681 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 668 682 669 683 if (nskb) { 670 684 struct llc_sap *sap = llc->sap; ··· 689 703 { 690 704 int rc = -ENOBUFS; 691 705 struct llc_sock *llc = llc_sk(sk); 692 - struct sk_buff *nskb = llc_alloc_frame(llc->dev); 706 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 693 707 694 708 if (nskb) { 695 709 struct llc_sap *sap = llc->sap; ··· 713 727 { 714 728 int rc = -ENOBUFS; 715 729 struct llc_sock *llc = llc_sk(sk); 716 - struct sk_buff *nskb = llc_alloc_frame(llc->dev); 730 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 717 731 718 732 if (nskb) { 719 733 struct llc_sap *sap = llc->sap; ··· 737 751 { 738 752 int rc = -ENOBUFS; 739 753 struct llc_sock *llc = llc_sk(sk); 740 - struct sk_buff *nskb = llc_alloc_frame(llc->dev); 754 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 741 755 742 756 if (nskb) { 743 757 struct llc_sap *sap = llc->sap; ··· 771 785 { 772 786 int rc = -ENOBUFS; 773 787 struct llc_sock *llc = llc_sk(sk); 774 - struct sk_buff *nskb = llc_alloc_frame(llc->dev); 788 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 775 789 776 790 if (nskb) { 777 791 struct llc_sap *sap = llc->sap; ··· 800 814 u8 f_bit; 801 815 int rc = -ENOBUFS; 802 816 struct llc_sock *llc = llc_sk(sk); 803 - struct sk_buff *nskb = llc_alloc_frame(llc->dev); 817 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 804 818 805 819 llc_pdu_decode_pf_bit(skb, &f_bit); 806 820 if (nskb) { ··· 956 970 { 957 971 int rc = -ENOBUFS; 958 972 struct llc_sock *llc = llc_sk(sk); 959 - struct sk_buff *nskb = llc_alloc_frame(llc->dev); 973 + struct sk_buff *nskb = llc_alloc_frame(sk, llc->dev); 960 974 961 975 if (nskb) { 962 976 struct llc_sap *sap = llc->sap;
+96 -48
net/llc/llc_conn.c
··· 58 58 int llc_conn_state_process(struct sock *sk, struct sk_buff *skb) 59 59 { 60 60 int rc; 61 - struct llc_sock *llc = llc_sk(sk); 61 + struct llc_sock *llc = llc_sk(skb->sk); 62 62 struct llc_conn_state_ev *ev = llc_conn_ev(skb); 63 63 64 64 /* ··· 68 68 */ 69 69 skb_get(skb); 70 70 ev->ind_prim = ev->cfm_prim = 0; 71 - rc = llc_conn_service(sk, skb); /* sending event to state machine */ 71 + /* 72 + * Send event to state machine 73 + */ 74 + rc = llc_conn_service(skb->sk, skb); 72 75 if (unlikely(rc != 0)) { 73 76 printk(KERN_ERR "%s: llc_conn_service failed\n", __FUNCTION__); 74 77 goto out_kfree_skb; ··· 103 100 kfree_skb(skb); 104 101 } 105 102 break; 106 - case LLC_CONN_PRIM: { 107 - struct sock *parent = skb->sk; 108 - 109 - skb_orphan(skb); 103 + case LLC_CONN_PRIM: 110 104 /* 111 - * Set the skb->sk to the new struct sock, so that at accept 112 - * type the upper layer can get the newly created struct sock. 105 + * Can't be sock_queue_rcv_skb, because we have to leave the 106 + * skb->sk pointing to the newly created struct sock in 107 + * llc_conn_handler. -acme 113 108 */ 114 - skb->sk = sk; 115 - skb_queue_tail(&parent->sk_receive_queue, skb); 116 - sk->sk_state_change(parent); 117 - } 109 + skb_queue_tail(&sk->sk_receive_queue, skb); 110 + sk->sk_state_change(sk); 118 111 break; 119 112 case LLC_DISC_PRIM: 120 113 sock_hold(sk); ··· 474 475 } 475 476 476 477 /** 477 - * llc_lookup_established - Finds connection for the remote/local sap/mac 478 + * __llc_lookup_established - Finds connection for the remote/local sap/mac 478 479 * @sap: SAP 479 480 * @daddr: address of remote LLC (MAC + SAP) 480 481 * @laddr: address of local LLC (MAC + SAP) ··· 482 483 * Search connection list of the SAP and finds connection using the remote 483 484 * mac, remote sap, local mac, and local sap. Returns pointer for 484 485 * connection found, %NULL otherwise. 486 + * Caller has to make sure local_bh is disabled. 485 487 */ 486 - struct sock *llc_lookup_established(struct llc_sap *sap, struct llc_addr *daddr, 487 - struct llc_addr *laddr) 488 + static struct sock *__llc_lookup_established(struct llc_sap *sap, 489 + struct llc_addr *daddr, 490 + struct llc_addr *laddr) 488 491 { 489 492 struct sock *rc; 490 493 struct hlist_node *node; 491 494 492 - read_lock_bh(&sap->sk_list.lock); 495 + read_lock(&sap->sk_list.lock); 493 496 sk_for_each(rc, node, &sap->sk_list.list) { 494 497 struct llc_sock *llc = llc_sk(rc); 495 498 ··· 505 504 } 506 505 rc = NULL; 507 506 found: 508 - read_unlock_bh(&sap->sk_list.lock); 507 + read_unlock(&sap->sk_list.lock); 509 508 return rc; 509 + } 510 + 511 + struct sock *llc_lookup_established(struct llc_sap *sap, 512 + struct llc_addr *daddr, 513 + struct llc_addr *laddr) 514 + { 515 + struct sock *sk; 516 + 517 + local_bh_disable(); 518 + sk = __llc_lookup_established(sap, daddr, laddr); 519 + local_bh_enable(); 520 + return sk; 510 521 } 511 522 512 523 /** ··· 529 516 * Search connection list of the SAP and finds connection listening on 530 517 * local mac, and local sap. Returns pointer for parent socket found, 531 518 * %NULL otherwise. 519 + * Caller has to make sure local_bh is disabled. 532 520 */ 533 521 static struct sock *llc_lookup_listener(struct llc_sap *sap, 534 522 struct llc_addr *laddr) ··· 537 523 struct sock *rc; 538 524 struct hlist_node *node; 539 525 540 - read_lock_bh(&sap->sk_list.lock); 526 + read_lock(&sap->sk_list.lock); 541 527 sk_for_each(rc, node, &sap->sk_list.list) { 542 528 struct llc_sock *llc = llc_sk(rc); 543 529 ··· 551 537 } 552 538 rc = NULL; 553 539 found: 554 - read_unlock_bh(&sap->sk_list.lock); 540 + read_unlock(&sap->sk_list.lock); 555 541 return rc; 542 + } 543 + 544 + static struct sock *__llc_lookup(struct llc_sap *sap, 545 + struct llc_addr *daddr, 546 + struct llc_addr *laddr) 547 + { 548 + struct sock *sk = __llc_lookup_established(sap, daddr, laddr); 549 + 550 + return sk ? : llc_lookup_listener(sap, laddr); 556 551 } 557 552 558 553 /** ··· 689 666 static int llc_conn_rcv(struct sock* sk, struct sk_buff *skb) 690 667 { 691 668 struct llc_conn_state_ev *ev = llc_conn_ev(skb); 692 - struct llc_sock *llc = llc_sk(sk); 693 669 694 - if (!llc->dev) 695 - llc->dev = skb->dev; 696 670 ev->type = LLC_CONN_EV_TYPE_PDU; 697 671 ev->reason = 0; 698 672 return llc_conn_state_process(sk, skb); 673 + } 674 + 675 + static struct sock *llc_create_incoming_sock(struct sock *sk, 676 + struct net_device *dev, 677 + struct llc_addr *saddr, 678 + struct llc_addr *daddr) 679 + { 680 + struct sock *newsk = llc_sk_alloc(sk->sk_family, GFP_ATOMIC, 681 + sk->sk_prot); 682 + struct llc_sock *newllc, *llc = llc_sk(sk); 683 + 684 + if (!newsk) 685 + goto out; 686 + newllc = llc_sk(newsk); 687 + memcpy(&newllc->laddr, daddr, sizeof(newllc->laddr)); 688 + memcpy(&newllc->daddr, saddr, sizeof(newllc->daddr)); 689 + newllc->dev = dev; 690 + dev_hold(dev); 691 + llc_sap_add_socket(llc->sap, newsk); 692 + llc_sap_hold(llc->sap); 693 + out: 694 + return newsk; 699 695 } 700 696 701 697 void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb) ··· 727 685 llc_pdu_decode_da(skb, daddr.mac); 728 686 llc_pdu_decode_dsap(skb, &daddr.lsap); 729 687 730 - sk = llc_lookup_established(sap, &saddr, &daddr); 731 - if (!sk) { 732 - /* 733 - * Didn't find an active connection; verify if there 734 - * is a listening socket for this llc addr 735 - */ 736 - struct llc_sock *llc; 737 - struct sock *parent = llc_lookup_listener(sap, &daddr); 688 + sk = __llc_lookup(sap, &saddr, &daddr); 689 + if (!sk) 690 + goto drop; 738 691 739 - if (!parent) { 740 - dprintk("llc_lookup_listener failed!\n"); 741 - goto drop; 742 - } 743 - 744 - sk = llc_sk_alloc(parent->sk_family, GFP_ATOMIC, parent->sk_prot); 745 - if (!sk) { 746 - sock_put(parent); 747 - goto drop; 748 - } 749 - llc = llc_sk(sk); 750 - memcpy(&llc->laddr, &daddr, sizeof(llc->laddr)); 751 - memcpy(&llc->daddr, &saddr, sizeof(llc->daddr)); 752 - llc_sap_add_socket(sap, sk); 753 - sock_hold(sk); 754 - skb_set_owner_r(skb, parent); 755 - sock_put(parent); 756 - } 757 692 bh_lock_sock(sk); 693 + /* 694 + * This has to be done here and not at the upper layer ->accept 695 + * method because of the way the PROCOM state machine works: 696 + * it needs to set several state variables (see, for instance, 697 + * llc_adm_actions_2 in net/llc/llc_c_st.c) and send a packet to 698 + * the originator of the new connection, and this state has to be 699 + * in the newly created struct sock private area. -acme 700 + */ 701 + if (unlikely(sk->sk_state == TCP_LISTEN)) { 702 + struct sock *newsk = llc_create_incoming_sock(sk, skb->dev, 703 + &saddr, &daddr); 704 + if (!newsk) 705 + goto drop_unlock; 706 + skb_set_owner_r(skb, newsk); 707 + } else { 708 + /* 709 + * Can't be skb_set_owner_r, this will be done at the 710 + * llc_conn_state_process function, later on, when we will use 711 + * skb_queue_rcv_skb to send it to upper layers, this is 712 + * another trick required to cope with how the PROCOM state 713 + * machine works. -acme 714 + */ 715 + skb->sk = sk; 716 + } 758 717 if (!sock_owned_by_user(sk)) 759 718 llc_conn_rcv(sk, skb); 760 719 else { ··· 763 720 llc_set_backlog_type(skb, LLC_PACKET); 764 721 sk_add_backlog(sk, skb); 765 722 } 723 + out: 766 724 bh_unlock_sock(sk); 767 725 sock_put(sk); 768 726 return; 769 727 drop: 770 728 kfree_skb(skb); 729 + return; 730 + drop_unlock: 731 + kfree_skb(skb); 732 + goto out; 771 733 } 772 734 773 735 #undef LLC_REFCNT_DEBUG
+2
net/llc/llc_if.c
··· 107 107 ev->type = LLC_CONN_EV_TYPE_PRIM; 108 108 ev->prim = LLC_CONN_PRIM; 109 109 ev->prim_type = LLC_PRIM_TYPE_REQ; 110 + skb_set_owner_w(skb, sk); 110 111 rc = llc_conn_state_process(sk, skb); 111 112 } 112 113 out_put: ··· 142 141 skb = alloc_skb(0, GFP_ATOMIC); 143 142 if (!skb) 144 143 goto out; 144 + skb_set_owner_w(skb, sk); 145 145 sk->sk_state = TCP_CLOSING; 146 146 ev = llc_conn_ev(skb); 147 147 ev->type = LLC_CONN_EV_TYPE_PRIM;
+2 -2
net/llc/llc_s_ac.c
··· 103 103 llc_pdu_decode_sa(skb, mac_da); 104 104 llc_pdu_decode_da(skb, mac_sa); 105 105 llc_pdu_decode_ssap(skb, &dsap); 106 - nskb = llc_alloc_frame(skb->dev); 106 + nskb = llc_alloc_frame(NULL, skb->dev); 107 107 if (!nskb) 108 108 goto out; 109 109 llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap, ··· 148 148 llc_pdu_decode_sa(skb, mac_da); 149 149 llc_pdu_decode_da(skb, mac_sa); 150 150 llc_pdu_decode_ssap(skb, &dsap); 151 - nskb = llc_alloc_frame(skb->dev); 151 + nskb = llc_alloc_frame(NULL, skb->dev); 152 152 if (!nskb) 153 153 goto out; 154 154 llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap,
+3 -1
net/llc/llc_sap.c
··· 31 31 * Allocates an sk_buff for frame and initializes sk_buff fields. 32 32 * Returns allocated skb or %NULL when out of memory. 33 33 */ 34 - struct sk_buff *llc_alloc_frame(struct net_device *dev) 34 + struct sk_buff *llc_alloc_frame(struct sock *sk, struct net_device *dev) 35 35 { 36 36 struct sk_buff *skb = alloc_skb(128, GFP_ATOMIC); 37 37 ··· 41 41 skb->protocol = htons(ETH_P_802_2); 42 42 skb->dev = dev; 43 43 skb->mac.raw = skb->head; 44 + if (sk != NULL) 45 + skb_set_owner_w(skb, sk); 44 46 } 45 47 return skb; 46 48 }
+3 -3
net/llc/llc_station.c
··· 254 254 static int llc_station_ac_send_null_dsap_xid_c(struct sk_buff *skb) 255 255 { 256 256 int rc = 1; 257 - struct sk_buff *nskb = llc_alloc_frame(skb->dev); 257 + struct sk_buff *nskb = llc_alloc_frame(NULL, skb->dev); 258 258 259 259 if (!nskb) 260 260 goto out; ··· 275 275 { 276 276 u8 mac_da[ETH_ALEN], dsap; 277 277 int rc = 1; 278 - struct sk_buff* nskb = llc_alloc_frame(skb->dev); 278 + struct sk_buff* nskb = llc_alloc_frame(NULL, skb->dev); 279 279 280 280 if (!nskb) 281 281 goto out; ··· 299 299 { 300 300 u8 mac_da[ETH_ALEN], dsap; 301 301 int rc = 1; 302 - struct sk_buff *nskb = llc_alloc_frame(skb->dev); 302 + struct sk_buff *nskb = llc_alloc_frame(NULL, skb->dev); 303 303 304 304 if (!nskb) 305 305 goto out;