diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/ipv6/af_inet6.c | 3 | ||||
| -rw-r--r-- | net/sunrpc/sched.c | 33 | ||||
| -rw-r--r-- | net/sunrpc/xprt.c | 2 | ||||
| -rw-r--r-- | net/sunrpc/xprtsock.c | 23 | ||||
| -rw-r--r-- | net/xfrm/xfrm_state.c | 90 |
5 files changed, 100 insertions, 51 deletions
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index da944eca2ca..9c8309ed35c 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
| @@ -1192,6 +1192,9 @@ module_init(inet6_init); | |||
| 1192 | 1192 | ||
| 1193 | static void __exit inet6_exit(void) | 1193 | static void __exit inet6_exit(void) |
| 1194 | { | 1194 | { |
| 1195 | if (disable_ipv6) | ||
| 1196 | return; | ||
| 1197 | |||
| 1195 | /* First of all disallow new sockets creation. */ | 1198 | /* First of all disallow new sockets creation. */ |
| 1196 | sock_unregister(PF_INET6); | 1199 | sock_unregister(PF_INET6); |
| 1197 | /* Disallow any further netlink messages */ | 1200 | /* Disallow any further netlink messages */ |
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 385f427beda..ff50a054686 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
| @@ -293,11 +293,6 @@ static void rpc_make_runnable(struct rpc_task *task) | |||
| 293 | rpc_clear_queued(task); | 293 | rpc_clear_queued(task); |
| 294 | if (rpc_test_and_set_running(task)) | 294 | if (rpc_test_and_set_running(task)) |
| 295 | return; | 295 | return; |
| 296 | /* We might have raced */ | ||
| 297 | if (RPC_IS_QUEUED(task)) { | ||
| 298 | rpc_clear_running(task); | ||
| 299 | return; | ||
| 300 | } | ||
| 301 | if (RPC_IS_ASYNC(task)) { | 296 | if (RPC_IS_ASYNC(task)) { |
| 302 | int status; | 297 | int status; |
| 303 | 298 | ||
| @@ -607,7 +602,9 @@ void rpc_release_calldata(const struct rpc_call_ops *ops, void *calldata) | |||
| 607 | */ | 602 | */ |
| 608 | static void __rpc_execute(struct rpc_task *task) | 603 | static void __rpc_execute(struct rpc_task *task) |
| 609 | { | 604 | { |
| 610 | int status = 0; | 605 | struct rpc_wait_queue *queue; |
| 606 | int task_is_async = RPC_IS_ASYNC(task); | ||
| 607 | int status = 0; | ||
| 611 | 608 | ||
| 612 | dprintk("RPC: %5u __rpc_execute flags=0x%x\n", | 609 | dprintk("RPC: %5u __rpc_execute flags=0x%x\n", |
| 613 | task->tk_pid, task->tk_flags); | 610 | task->tk_pid, task->tk_flags); |
| @@ -647,15 +644,25 @@ static void __rpc_execute(struct rpc_task *task) | |||
| 647 | */ | 644 | */ |
| 648 | if (!RPC_IS_QUEUED(task)) | 645 | if (!RPC_IS_QUEUED(task)) |
| 649 | continue; | 646 | continue; |
| 650 | rpc_clear_running(task); | 647 | /* |
| 651 | if (RPC_IS_ASYNC(task)) { | 648 | * The queue->lock protects against races with |
| 652 | /* Careful! we may have raced... */ | 649 | * rpc_make_runnable(). |
| 653 | if (RPC_IS_QUEUED(task)) | 650 | * |
| 654 | return; | 651 | * Note that once we clear RPC_TASK_RUNNING on an asynchronous |
| 655 | if (rpc_test_and_set_running(task)) | 652 | * rpc_task, rpc_make_runnable() can assign it to a |
| 656 | return; | 653 | * different workqueue. We therefore cannot assume that the |
| 654 | * rpc_task pointer may still be dereferenced. | ||
| 655 | */ | ||
| 656 | queue = task->tk_waitqueue; | ||
| 657 | spin_lock_bh(&queue->lock); | ||
| 658 | if (!RPC_IS_QUEUED(task)) { | ||
| 659 | spin_unlock_bh(&queue->lock); | ||
| 657 | continue; | 660 | continue; |
| 658 | } | 661 | } |
| 662 | rpc_clear_running(task); | ||
| 663 | spin_unlock_bh(&queue->lock); | ||
| 664 | if (task_is_async) | ||
| 665 | return; | ||
| 659 | 666 | ||
| 660 | /* sync task: sleep here */ | 667 | /* sync task: sleep here */ |
| 661 | dprintk("RPC: %5u sync task going to sleep\n", task->tk_pid); | 668 | dprintk("RPC: %5u sync task going to sleep\n", task->tk_pid); |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 29e401bb612..62098d101a1 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
| @@ -663,7 +663,7 @@ void xprt_connect(struct rpc_task *task) | |||
| 663 | xprt, (xprt_connected(xprt) ? "is" : "is not")); | 663 | xprt, (xprt_connected(xprt) ? "is" : "is not")); |
| 664 | 664 | ||
| 665 | if (!xprt_bound(xprt)) { | 665 | if (!xprt_bound(xprt)) { |
| 666 | task->tk_status = -EIO; | 666 | task->tk_status = -EAGAIN; |
| 667 | return; | 667 | return; |
| 668 | } | 668 | } |
| 669 | if (!xprt_lock_write(xprt, task)) | 669 | if (!xprt_lock_write(xprt, task)) |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 5cbb404c4cd..29c71e645b2 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
| @@ -467,7 +467,7 @@ static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, | |||
| 467 | int err, sent = 0; | 467 | int err, sent = 0; |
| 468 | 468 | ||
| 469 | if (unlikely(!sock)) | 469 | if (unlikely(!sock)) |
| 470 | return -ENOTCONN; | 470 | return -ENOTSOCK; |
| 471 | 471 | ||
| 472 | clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags); | 472 | clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags); |
| 473 | if (base != 0) { | 473 | if (base != 0) { |
| @@ -577,6 +577,8 @@ static int xs_udp_send_request(struct rpc_task *task) | |||
| 577 | req->rq_svec->iov_base, | 577 | req->rq_svec->iov_base, |
| 578 | req->rq_svec->iov_len); | 578 | req->rq_svec->iov_len); |
| 579 | 579 | ||
| 580 | if (!xprt_bound(xprt)) | ||
| 581 | return -ENOTCONN; | ||
| 580 | status = xs_sendpages(transport->sock, | 582 | status = xs_sendpages(transport->sock, |
| 581 | xs_addr(xprt), | 583 | xs_addr(xprt), |
| 582 | xprt->addrlen, xdr, | 584 | xprt->addrlen, xdr, |
| @@ -594,6 +596,10 @@ static int xs_udp_send_request(struct rpc_task *task) | |||
| 594 | } | 596 | } |
| 595 | 597 | ||
| 596 | switch (status) { | 598 | switch (status) { |
| 599 | case -ENOTSOCK: | ||
| 600 | status = -ENOTCONN; | ||
| 601 | /* Should we call xs_close() here? */ | ||
| 602 | break; | ||
| 597 | case -EAGAIN: | 603 | case -EAGAIN: |
| 598 | xs_nospace(task); | 604 | xs_nospace(task); |
| 599 | break; | 605 | break; |
| @@ -693,6 +699,10 @@ static int xs_tcp_send_request(struct rpc_task *task) | |||
| 693 | } | 699 | } |
| 694 | 700 | ||
| 695 | switch (status) { | 701 | switch (status) { |
| 702 | case -ENOTSOCK: | ||
| 703 | status = -ENOTCONN; | ||
| 704 | /* Should we call xs_close() here? */ | ||
| 705 | break; | ||
| 696 | case -EAGAIN: | 706 | case -EAGAIN: |
| 697 | xs_nospace(task); | 707 | xs_nospace(task); |
| 698 | break; | 708 | break; |
| @@ -1523,7 +1533,7 @@ static void xs_udp_connect_worker4(struct work_struct *work) | |||
| 1523 | struct socket *sock = transport->sock; | 1533 | struct socket *sock = transport->sock; |
| 1524 | int err, status = -EIO; | 1534 | int err, status = -EIO; |
| 1525 | 1535 | ||
| 1526 | if (xprt->shutdown || !xprt_bound(xprt)) | 1536 | if (xprt->shutdown) |
| 1527 | goto out; | 1537 | goto out; |
| 1528 | 1538 | ||
| 1529 | /* Start by resetting any existing state */ | 1539 | /* Start by resetting any existing state */ |
| @@ -1564,7 +1574,7 @@ static void xs_udp_connect_worker6(struct work_struct *work) | |||
| 1564 | struct socket *sock = transport->sock; | 1574 | struct socket *sock = transport->sock; |
| 1565 | int err, status = -EIO; | 1575 | int err, status = -EIO; |
| 1566 | 1576 | ||
| 1567 | if (xprt->shutdown || !xprt_bound(xprt)) | 1577 | if (xprt->shutdown) |
| 1568 | goto out; | 1578 | goto out; |
| 1569 | 1579 | ||
| 1570 | /* Start by resetting any existing state */ | 1580 | /* Start by resetting any existing state */ |
| @@ -1648,6 +1658,9 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | |||
| 1648 | write_unlock_bh(&sk->sk_callback_lock); | 1658 | write_unlock_bh(&sk->sk_callback_lock); |
| 1649 | } | 1659 | } |
| 1650 | 1660 | ||
| 1661 | if (!xprt_bound(xprt)) | ||
| 1662 | return -ENOTCONN; | ||
| 1663 | |||
| 1651 | /* Tell the socket layer to start connecting... */ | 1664 | /* Tell the socket layer to start connecting... */ |
| 1652 | xprt->stat.connect_count++; | 1665 | xprt->stat.connect_count++; |
| 1653 | xprt->stat.connect_start = jiffies; | 1666 | xprt->stat.connect_start = jiffies; |
| @@ -1668,7 +1681,7 @@ static void xs_tcp_connect_worker4(struct work_struct *work) | |||
| 1668 | struct socket *sock = transport->sock; | 1681 | struct socket *sock = transport->sock; |
| 1669 | int err, status = -EIO; | 1682 | int err, status = -EIO; |
| 1670 | 1683 | ||
| 1671 | if (xprt->shutdown || !xprt_bound(xprt)) | 1684 | if (xprt->shutdown) |
| 1672 | goto out; | 1685 | goto out; |
| 1673 | 1686 | ||
| 1674 | if (!sock) { | 1687 | if (!sock) { |
| @@ -1728,7 +1741,7 @@ static void xs_tcp_connect_worker6(struct work_struct *work) | |||
| 1728 | struct socket *sock = transport->sock; | 1741 | struct socket *sock = transport->sock; |
| 1729 | int err, status = -EIO; | 1742 | int err, status = -EIO; |
| 1730 | 1743 | ||
| 1731 | if (xprt->shutdown || !xprt_bound(xprt)) | 1744 | if (xprt->shutdown) |
| 1732 | goto out; | 1745 | goto out; |
| 1733 | 1746 | ||
| 1734 | if (!sock) { | 1747 | if (!sock) { |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index e25ff62ab2a..62a5425cc6a 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
| @@ -748,12 +748,51 @@ static void xfrm_hash_grow_check(struct net *net, int have_hash_collision) | |||
| 748 | schedule_work(&net->xfrm.state_hash_work); | 748 | schedule_work(&net->xfrm.state_hash_work); |
| 749 | } | 749 | } |
| 750 | 750 | ||
| 751 | static void xfrm_state_look_at(struct xfrm_policy *pol, struct xfrm_state *x, | ||
| 752 | struct flowi *fl, unsigned short family, | ||
| 753 | xfrm_address_t *daddr, xfrm_address_t *saddr, | ||
| 754 | struct xfrm_state **best, int *acq_in_progress, | ||
| 755 | int *error) | ||
| 756 | { | ||
| 757 | /* Resolution logic: | ||
| 758 | * 1. There is a valid state with matching selector. Done. | ||
| 759 | * 2. Valid state with inappropriate selector. Skip. | ||
| 760 | * | ||
| 761 | * Entering area of "sysdeps". | ||
| 762 | * | ||
| 763 | * 3. If state is not valid, selector is temporary, it selects | ||
| 764 | * only session which triggered previous resolution. Key | ||
| 765 | * manager will do something to install a state with proper | ||
| 766 | * selector. | ||
| 767 | */ | ||
| 768 | if (x->km.state == XFRM_STATE_VALID) { | ||
| 769 | if ((x->sel.family && | ||
| 770 | !xfrm_selector_match(&x->sel, fl, x->sel.family)) || | ||
| 771 | !security_xfrm_state_pol_flow_match(x, pol, fl)) | ||
| 772 | return; | ||
| 773 | |||
| 774 | if (!*best || | ||
| 775 | (*best)->km.dying > x->km.dying || | ||
| 776 | ((*best)->km.dying == x->km.dying && | ||
| 777 | (*best)->curlft.add_time < x->curlft.add_time)) | ||
| 778 | *best = x; | ||
| 779 | } else if (x->km.state == XFRM_STATE_ACQ) { | ||
| 780 | *acq_in_progress = 1; | ||
| 781 | } else if (x->km.state == XFRM_STATE_ERROR || | ||
| 782 | x->km.state == XFRM_STATE_EXPIRED) { | ||
| 783 | if (xfrm_selector_match(&x->sel, fl, x->sel.family) && | ||
| 784 | security_xfrm_state_pol_flow_match(x, pol, fl)) | ||
| 785 | *error = -ESRCH; | ||
| 786 | } | ||
| 787 | } | ||
| 788 | |||
| 751 | struct xfrm_state * | 789 | struct xfrm_state * |
| 752 | xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | 790 | xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, |
| 753 | struct flowi *fl, struct xfrm_tmpl *tmpl, | 791 | struct flowi *fl, struct xfrm_tmpl *tmpl, |
| 754 | struct xfrm_policy *pol, int *err, | 792 | struct xfrm_policy *pol, int *err, |
| 755 | unsigned short family) | 793 | unsigned short family) |
| 756 | { | 794 | { |
| 795 | static xfrm_address_t saddr_wildcard = { }; | ||
| 757 | struct net *net = xp_net(pol); | 796 | struct net *net = xp_net(pol); |
| 758 | unsigned int h; | 797 | unsigned int h; |
| 759 | struct hlist_node *entry; | 798 | struct hlist_node *entry; |
| @@ -773,40 +812,27 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
| 773 | xfrm_state_addr_check(x, daddr, saddr, family) && | 812 | xfrm_state_addr_check(x, daddr, saddr, family) && |
| 774 | tmpl->mode == x->props.mode && | 813 | tmpl->mode == x->props.mode && |
| 775 | tmpl->id.proto == x->id.proto && | 814 | tmpl->id.proto == x->id.proto && |
| 776 | (tmpl->id.spi == x->id.spi || !tmpl->id.spi)) { | 815 | (tmpl->id.spi == x->id.spi || !tmpl->id.spi)) |
| 777 | /* Resolution logic: | 816 | xfrm_state_look_at(pol, x, fl, family, daddr, saddr, |
| 778 | 1. There is a valid state with matching selector. | 817 | &best, &acquire_in_progress, &error); |
| 779 | Done. | 818 | } |
| 780 | 2. Valid state with inappropriate selector. Skip. | 819 | if (best) |
| 781 | 820 | goto found; | |
| 782 | Entering area of "sysdeps". | 821 | |
| 783 | 822 | h = xfrm_dst_hash(net, daddr, &saddr_wildcard, tmpl->reqid, family); | |
| 784 | 3. If state is not valid, selector is temporary, | 823 | hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { |
| 785 | it selects only session which triggered | 824 | if (x->props.family == family && |
| 786 | previous resolution. Key manager will do | 825 | x->props.reqid == tmpl->reqid && |
| 787 | something to install a state with proper | 826 | !(x->props.flags & XFRM_STATE_WILDRECV) && |
| 788 | selector. | 827 | xfrm_state_addr_check(x, daddr, saddr, family) && |
| 789 | */ | 828 | tmpl->mode == x->props.mode && |
| 790 | if (x->km.state == XFRM_STATE_VALID) { | 829 | tmpl->id.proto == x->id.proto && |
| 791 | if ((x->sel.family && !xfrm_selector_match(&x->sel, fl, x->sel.family)) || | 830 | (tmpl->id.spi == x->id.spi || !tmpl->id.spi)) |
| 792 | !security_xfrm_state_pol_flow_match(x, pol, fl)) | 831 | xfrm_state_look_at(pol, x, fl, family, daddr, saddr, |
| 793 | continue; | 832 | &best, &acquire_in_progress, &error); |
| 794 | if (!best || | ||
| 795 | best->km.dying > x->km.dying || | ||
| 796 | (best->km.dying == x->km.dying && | ||
| 797 | best->curlft.add_time < x->curlft.add_time)) | ||
| 798 | best = x; | ||
| 799 | } else if (x->km.state == XFRM_STATE_ACQ) { | ||
| 800 | acquire_in_progress = 1; | ||
| 801 | } else if (x->km.state == XFRM_STATE_ERROR || | ||
| 802 | x->km.state == XFRM_STATE_EXPIRED) { | ||
| 803 | if (xfrm_selector_match(&x->sel, fl, x->sel.family) && | ||
| 804 | security_xfrm_state_pol_flow_match(x, pol, fl)) | ||
| 805 | error = -ESRCH; | ||
| 806 | } | ||
| 807 | } | ||
| 808 | } | 833 | } |
| 809 | 834 | ||
| 835 | found: | ||
| 810 | x = best; | 836 | x = best; |
| 811 | if (!x && !error && !acquire_in_progress) { | 837 | if (!x && !error && !acquire_in_progress) { |
| 812 | if (tmpl->id.spi && | 838 | if (tmpl->id.spi && |
