aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-06-24 05:58:51 -0400
committerDavid S. Miller <davem@davemloft.net>2015-06-24 05:58:51 -0400
commit3a07bd6fead4f00f67b1bf5f551e686661c4f52c (patch)
treef8b8f257d928a9ae1aeb3fdbe748f03f1012f02e /net/sctp
parent204621551b2a0060a013b92f7add4d5c452fa7cb (diff)
parentf1590670ce069eefeb93916391a67643e6ad1630 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Conflicts: drivers/net/ethernet/mellanox/mlx4/main.c net/packet/af_packet.c Both conflicts were cases of simple overlapping changes. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp')
-rw-r--r--net/sctp/socket.c43
1 files changed, 32 insertions, 11 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index f09de7fac2e6..5f6c4e61325b 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -1528,8 +1528,10 @@ static void sctp_close(struct sock *sk, long timeout)
1528 1528
1529 /* Supposedly, no process has access to the socket, but 1529 /* Supposedly, no process has access to the socket, but
1530 * the net layers still may. 1530 * the net layers still may.
1531 * Also, sctp_destroy_sock() needs to be called with addr_wq_lock
1532 * held and that should be grabbed before socket lock.
1531 */ 1533 */
1532 local_bh_disable(); 1534 spin_lock_bh(&net->sctp.addr_wq_lock);
1533 bh_lock_sock(sk); 1535 bh_lock_sock(sk);
1534 1536
1535 /* Hold the sock, since sk_common_release() will put sock_put() 1537 /* Hold the sock, since sk_common_release() will put sock_put()
@@ -1539,7 +1541,7 @@ static void sctp_close(struct sock *sk, long timeout)
1539 sk_common_release(sk); 1541 sk_common_release(sk);
1540 1542
1541 bh_unlock_sock(sk); 1543 bh_unlock_sock(sk);
1542 local_bh_enable(); 1544 spin_unlock_bh(&net->sctp.addr_wq_lock);
1543 1545
1544 sock_put(sk); 1546 sock_put(sk);
1545 1547
@@ -3580,6 +3582,7 @@ static int sctp_setsockopt_auto_asconf(struct sock *sk, char __user *optval,
3580 if ((val && sp->do_auto_asconf) || (!val && !sp->do_auto_asconf)) 3582 if ((val && sp->do_auto_asconf) || (!val && !sp->do_auto_asconf))
3581 return 0; 3583 return 0;
3582 3584
3585 spin_lock_bh(&sock_net(sk)->sctp.addr_wq_lock);
3583 if (val == 0 && sp->do_auto_asconf) { 3586 if (val == 0 && sp->do_auto_asconf) {
3584 list_del(&sp->auto_asconf_list); 3587 list_del(&sp->auto_asconf_list);
3585 sp->do_auto_asconf = 0; 3588 sp->do_auto_asconf = 0;
@@ -3588,6 +3591,7 @@ static int sctp_setsockopt_auto_asconf(struct sock *sk, char __user *optval,
3588 &sock_net(sk)->sctp.auto_asconf_splist); 3591 &sock_net(sk)->sctp.auto_asconf_splist);
3589 sp->do_auto_asconf = 1; 3592 sp->do_auto_asconf = 1;
3590 } 3593 }
3594 spin_unlock_bh(&sock_net(sk)->sctp.addr_wq_lock);
3591 return 0; 3595 return 0;
3592} 3596}
3593 3597
@@ -4121,18 +4125,28 @@ static int sctp_init_sock(struct sock *sk)
4121 local_bh_disable(); 4125 local_bh_disable();
4122 percpu_counter_inc(&sctp_sockets_allocated); 4126 percpu_counter_inc(&sctp_sockets_allocated);
4123 sock_prot_inuse_add(net, sk->sk_prot, 1); 4127 sock_prot_inuse_add(net, sk->sk_prot, 1);
4128
4129 /* Nothing can fail after this block, otherwise
4130 * sctp_destroy_sock() will be called without addr_wq_lock held
4131 */
4124 if (net->sctp.default_auto_asconf) { 4132 if (net->sctp.default_auto_asconf) {
4133 spin_lock(&sock_net(sk)->sctp.addr_wq_lock);
4125 list_add_tail(&sp->auto_asconf_list, 4134 list_add_tail(&sp->auto_asconf_list,
4126 &net->sctp.auto_asconf_splist); 4135 &net->sctp.auto_asconf_splist);
4127 sp->do_auto_asconf = 1; 4136 sp->do_auto_asconf = 1;
4128 } else 4137 spin_unlock(&sock_net(sk)->sctp.addr_wq_lock);
4138 } else {
4129 sp->do_auto_asconf = 0; 4139 sp->do_auto_asconf = 0;
4140 }
4141
4130 local_bh_enable(); 4142 local_bh_enable();
4131 4143
4132 return 0; 4144 return 0;
4133} 4145}
4134 4146
4135/* Cleanup any SCTP per socket resources. */ 4147/* Cleanup any SCTP per socket resources. Must be called with
4148 * sock_net(sk)->sctp.addr_wq_lock held if sp->do_auto_asconf is true
4149 */
4136static void sctp_destroy_sock(struct sock *sk) 4150static void sctp_destroy_sock(struct sock *sk)
4137{ 4151{
4138 struct sctp_sock *sp; 4152 struct sctp_sock *sp;
@@ -7195,6 +7209,19 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk,
7195 newinet->mc_list = NULL; 7209 newinet->mc_list = NULL;
7196} 7210}
7197 7211
7212static inline void sctp_copy_descendant(struct sock *sk_to,
7213 const struct sock *sk_from)
7214{
7215 int ancestor_size = sizeof(struct inet_sock) +
7216 sizeof(struct sctp_sock) -
7217 offsetof(struct sctp_sock, auto_asconf_list);
7218
7219 if (sk_from->sk_family == PF_INET6)
7220 ancestor_size += sizeof(struct ipv6_pinfo);
7221
7222 __inet_sk_copy_descendant(sk_to, sk_from, ancestor_size);
7223}
7224
7198/* Populate the fields of the newsk from the oldsk and migrate the assoc 7225/* Populate the fields of the newsk from the oldsk and migrate the assoc
7199 * and its messages to the newsk. 7226 * and its messages to the newsk.
7200 */ 7227 */
@@ -7209,7 +7236,6 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
7209 struct sk_buff *skb, *tmp; 7236 struct sk_buff *skb, *tmp;
7210 struct sctp_ulpevent *event; 7237 struct sctp_ulpevent *event;
7211 struct sctp_bind_hashbucket *head; 7238 struct sctp_bind_hashbucket *head;
7212 struct list_head tmplist;
7213 7239
7214 /* Migrate socket buffer sizes and all the socket level options to the 7240 /* Migrate socket buffer sizes and all the socket level options to the
7215 * new socket. 7241 * new socket.
@@ -7217,12 +7243,7 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
7217 newsk->sk_sndbuf = oldsk->sk_sndbuf; 7243 newsk->sk_sndbuf = oldsk->sk_sndbuf;
7218 newsk->sk_rcvbuf = oldsk->sk_rcvbuf; 7244 newsk->sk_rcvbuf = oldsk->sk_rcvbuf;
7219 /* Brute force copy old sctp opt. */ 7245 /* Brute force copy old sctp opt. */
7220 if (oldsp->do_auto_asconf) { 7246 sctp_copy_descendant(newsk, oldsk);
7221 memcpy(&tmplist, &newsp->auto_asconf_list, sizeof(tmplist));
7222 inet_sk_copy_descendant(newsk, oldsk);
7223 memcpy(&newsp->auto_asconf_list, &tmplist, sizeof(tmplist));
7224 } else
7225 inet_sk_copy_descendant(newsk, oldsk);
7226 7247
7227 /* Restore the ep value that was overwritten with the above structure 7248 /* Restore the ep value that was overwritten with the above structure
7228 * copy. 7249 * copy.