Pull asus into release branch
[pandora-kernel.git] / net / sctp / socket.c
index bdd8bd4..a1d026f 100644 (file)
@@ -381,12 +381,12 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
 
  /* ADDIP Section 4.1.1 Congestion Control of ASCONF Chunks
  *
- * R1) One and only one ASCONF Chunk MAY be in transit and unacknowledged 
+ * R1) One and only one ASCONF Chunk MAY be in transit and unacknowledged
  * at any one time.  If a sender, after sending an ASCONF chunk, decides
- * it needs to transfer another ASCONF Chunk, it MUST wait until the 
+ * it needs to transfer another ASCONF Chunk, it MUST wait until the
  * ASCONF-ACK Chunk returns from the previous ASCONF Chunk before sending a
- * subsequent ASCONF. Note this restriction binds each side, so at any 
- * time two ASCONF may be in-transit on any given association (one sent 
+ * subsequent ASCONF. Note this restriction binds each side, so at any
+ * time two ASCONF may be in-transit on any given association (one sent
  * from each endpoint).
  */
 static int sctp_send_asconf(struct sctp_association *asoc,
@@ -396,10 +396,10 @@ static int sctp_send_asconf(struct sctp_association *asoc,
 
        /* If there is an outstanding ASCONF chunk, queue it for later
         * transmission.
-        */     
+        */
        if (asoc->addip_last_asconf) {
                list_add_tail(&chunk->list, &asoc->addip_chunk_list);
-               goto out;       
+               goto out;
        }
 
        /* Hold the chunk until an ASCONF_ACK is received. */
@@ -449,7 +449,7 @@ int sctp_bindx_add(struct sock *sk, struct sockaddr *addrs, int addrcnt)
                        goto err_bindx_add;
                }
 
-               retval = sctp_do_bind(sk, (union sctp_addr *)sa_addr, 
+               retval = sctp_do_bind(sk, (union sctp_addr *)sa_addr,
                                      af->sockaddr_len);
 
                addr_buf += af->sockaddr_len;
@@ -470,13 +470,13 @@ err_bindx_add:
  * associations that are part of the endpoint indicating that a list of local
  * addresses are added to the endpoint.
  *
- * If any of the addresses is already in the bind address list of the 
+ * If any of the addresses is already in the bind address list of the
  * association, we do not send the chunk for that association.  But it will not
  * affect other associations.
  *
  * Only sctp_setsockopt_bindx() is supposed to call this function.
  */
-static int sctp_send_asconf_add_ip(struct sock         *sk, 
+static int sctp_send_asconf_add_ip(struct sock         *sk,
                                   struct sockaddr      *addrs,
                                   int                  addrcnt)
 {
@@ -517,8 +517,8 @@ static int sctp_send_asconf_add_ip(struct sock              *sk,
                        continue;
 
                /* Check if any address in the packed array of addresses is
-                * in the bind address list of the association. If so, 
-                * do not send the asconf chunk to its peer, but continue with 
+                * in the bind address list of the association. If so,
+                * do not send the asconf chunk to its peer, but continue with
                 * other associations.
                 */
                addr_buf = addrs;
@@ -627,6 +627,12 @@ int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt)
                        retval = -EINVAL;
                        goto err_bindx_rem;
                }
+
+               if (!af->addr_valid(sa_addr, sp, NULL)) {
+                       retval = -EADDRNOTAVAIL;
+                       goto err_bindx_rem;
+               }
+
                if (sa_addr->v4.sin_port != htons(bp->port)) {
                        retval = -EINVAL;
                        goto err_bindx_rem;
@@ -664,7 +670,7 @@ err_bindx_rem:
  * the associations that are part of the endpoint indicating that a list of
  * local addresses are removed from the endpoint.
  *
- * If any of the addresses is already in the bind address list of the 
+ * If any of the addresses is already in the bind address list of the
  * association, we do not send the chunk for that association.  But it will not
  * affect other associations.
  *
@@ -710,7 +716,7 @@ static int sctp_send_asconf_del_ip(struct sock              *sk,
                        continue;
 
                /* Check if any address in the packed array of addresses is
-                * not present in the bind address list of the association.
+                * not present in the bind address list of the association.
                 * If so, do not send the asconf chunk to its peer, but
                 * continue with other associations.
                 */
@@ -898,7 +904,7 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk,
                return -EFAULT;
        }
 
-       /* Walk through the addrs buffer and count the number of addresses. */ 
+       /* Walk through the addrs buffer and count the number of addresses. */
        addr_buf = kaddrs;
        while (walk_size < addrs_size) {
                sa_addr = (struct sockaddr *)addr_buf;
@@ -906,7 +912,7 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk,
 
                /* If the address family is not supported or if this address
                 * causes the address buffer to overflow return EINVAL.
-                */ 
+                */
                if (!af || (walk_size + af->sockaddr_len) > addrs_size) {
                        kfree(kaddrs);
                        return -EINVAL;
@@ -935,7 +941,7 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk,
        default:
                err = -EINVAL;
                break;
-        };
+       };
 
 out:
        kfree(kaddrs);
@@ -1035,10 +1041,10 @@ static int __sctp_connect(struct sock* sk,
                                }
                        } else {
                                /*
-                                * If an unprivileged user inherits a 1-many 
-                                * style socket with open associations on a 
-                                * privileged port, it MAY be permitted to 
-                                * accept new associations, but it SHOULD NOT 
+                                * If an unprivileged user inherits a 1-many
+                                * style socket with open associations on a
+                                * privileged port, it MAY be permitted to
+                                * accept new associations, but it SHOULD NOT
                                 * be permitted to open new associations.
                                 */
                                if (ep->base.bind_addr.port < PROT_SOCK &&
@@ -1094,8 +1100,8 @@ static int __sctp_connect(struct sock* sk,
 out_free:
 
        SCTP_DEBUG_PRINTK("About to exit __sctp_connect() free asoc: %p"
-                         " kaddrs: %p err: %d\n",
-                         asoc, kaddrs, err);
+                         " kaddrs: %p err: %d\n",
+                         asoc, kaddrs, err);
        if (asoc)
                sctp_association_free(asoc);
        return err;
@@ -1435,7 +1441,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
         * length messages when SCTP_EOF|SCTP_ABORT is not set.
         * If SCTP_ABORT is set, the message length could be non zero with
         * the msg_iov set to the user abort reason.
-        */
+        */
        if (((sinfo_flags & SCTP_EOF) && (msg_len > 0)) ||
            (!(sinfo_flags & (SCTP_EOF|SCTP_ABORT)) && (msg_len == 0))) {
                err = -EINVAL;
@@ -1599,7 +1605,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
                                        = sinit->sinit_max_attempts;
                        }
                        if (sinit->sinit_max_init_timeo) {
-                               asoc->max_init_timeo = 
+                               asoc->max_init_timeo =
                                 msecs_to_jiffies(sinit->sinit_max_init_timeo);
                        }
                }
@@ -2298,7 +2304,7 @@ static int sctp_setsockopt_delayed_ack_time(struct sock *sk,
        /* Get association, if assoc_id != 0 and the socket is a one
         * to many style socket, and an association was not found, then
         * the id was invalid.
-        */
+        */
        asoc = sctp_id2assoc(sk, params.assoc_id);
        if (!asoc && params.assoc_id && sctp_style(sk, UDP))
                return -EINVAL;
@@ -2307,22 +2313,22 @@ static int sctp_setsockopt_delayed_ack_time(struct sock *sk,
                if (asoc) {
                        asoc->sackdelay =
                                msecs_to_jiffies(params.assoc_value);
-                       asoc->param_flags = 
+                       asoc->param_flags =
                                (asoc->param_flags & ~SPP_SACKDELAY) |
                                SPP_SACKDELAY_ENABLE;
                } else {
                        sp->sackdelay = params.assoc_value;
-                       sp->param_flags = 
+                       sp->param_flags =
                                (sp->param_flags & ~SPP_SACKDELAY) |
                                SPP_SACKDELAY_ENABLE;
                }
        } else {
                if (asoc) {
-                       asoc->param_flags = 
+                       asoc->param_flags =
                                (asoc->param_flags & ~SPP_SACKDELAY) |
                                SPP_SACKDELAY_DISABLE;
                } else {
-                       sp->param_flags = 
+                       sp->param_flags =
                                (sp->param_flags & ~SPP_SACKDELAY) |
                                SPP_SACKDELAY_DISABLE;
                }
@@ -2338,17 +2344,17 @@ static int sctp_setsockopt_delayed_ack_time(struct sock *sk,
                        if (params.assoc_value) {
                                trans->sackdelay =
                                        msecs_to_jiffies(params.assoc_value);
-                               trans->param_flags = 
+                               trans->param_flags =
                                        (trans->param_flags & ~SPP_SACKDELAY) |
                                        SPP_SACKDELAY_ENABLE;
                        } else {
-                               trans->param_flags = 
+                               trans->param_flags =
                                        (trans->param_flags & ~SPP_SACKDELAY) |
                                        SPP_SACKDELAY_DISABLE;
                        }
                }
        }
+
        return 0;
 }
 
@@ -2374,13 +2380,13 @@ static int sctp_setsockopt_initmsg(struct sock *sk, char __user *optval, int opt
                return -EFAULT;
 
        if (sinit.sinit_num_ostreams)
-               sp->initmsg.sinit_num_ostreams = sinit.sinit_num_ostreams;      
+               sp->initmsg.sinit_num_ostreams = sinit.sinit_num_ostreams;
        if (sinit.sinit_max_instreams)
-               sp->initmsg.sinit_max_instreams = sinit.sinit_max_instreams;    
+               sp->initmsg.sinit_max_instreams = sinit.sinit_max_instreams;
        if (sinit.sinit_max_attempts)
-               sp->initmsg.sinit_max_attempts = sinit.sinit_max_attempts;      
+               sp->initmsg.sinit_max_attempts = sinit.sinit_max_attempts;
        if (sinit.sinit_max_init_timeo)
-               sp->initmsg.sinit_max_init_timeo = sinit.sinit_max_init_timeo;  
+               sp->initmsg.sinit_max_init_timeo = sinit.sinit_max_init_timeo;
 
        return 0;
 }
@@ -2511,7 +2517,7 @@ static int sctp_setsockopt_rtoinfo(struct sock *sk, char __user *optval, int opt
 
        if (asoc) {
                if (rtoinfo.srto_initial != 0)
-                       asoc->rto_initial = 
+                       asoc->rto_initial =
                                msecs_to_jiffies(rtoinfo.srto_initial);
                if (rtoinfo.srto_max != 0)
                        asoc->rto_max = msecs_to_jiffies(rtoinfo.srto_max);
@@ -2665,7 +2671,7 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, int optl
        /* Update the frag_point of the existing associations. */
        list_for_each(pos, &(sp->ep->asocs)) {
                asoc = list_entry(pos, struct sctp_association, asocs);
-               asoc->frag_point = sctp_frag_point(sp, asoc->pathmtu); 
+               asoc->frag_point = sctp_frag_point(sp, asoc->pathmtu);
        }
 
        return 0;
@@ -2703,7 +2709,7 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optva
                return -EFAULT;
 
        asoc = sctp_id2assoc(sk, prim.sspp_assoc_id);
-       if (!asoc) 
+       if (!asoc)
                return -EINVAL;
 
        if (!asoc->peer.asconf_capable)
@@ -2731,17 +2737,17 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optva
        return err;
 }
 
-static int sctp_setsockopt_adaption_layer(struct sock *sk, char __user *optval,
+static int sctp_setsockopt_adaptation_layer(struct sock *sk, char __user *optval,
                                          int optlen)
 {
-       struct sctp_setadaption adaption;
+       struct sctp_setadaptation adaptation;
 
-       if (optlen != sizeof(struct sctp_setadaption))
+       if (optlen != sizeof(struct sctp_setadaptation))
                return -EINVAL;
-       if (copy_from_user(&adaption, optval, optlen)) 
+       if (copy_from_user(&adaptation, optval, optlen))
                return -EFAULT;
 
-       sctp_sk(sk)->adaption_ind = adaption.ssb_adaption_ind;
+       sctp_sk(sk)->adaptation_ind = adaptation.ssb_adaptation_ind;
 
        return 0;
 }
@@ -2894,8 +2900,8 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
        case SCTP_MAXSEG:
                retval = sctp_setsockopt_maxseg(sk, optval, optlen);
                break;
-       case SCTP_ADAPTION_LAYER:
-               retval = sctp_setsockopt_adaption_layer(sk, optval, optlen);
+       case SCTP_ADAPTATION_LAYER:
+               retval = sctp_setsockopt_adaptation_layer(sk, optval, optlen);
                break;
        case SCTP_CONTEXT:
                retval = sctp_setsockopt_context(sk, optval, optlen);
@@ -3015,7 +3021,7 @@ SCTP_STATIC struct sock *sctp_accept(struct sock *sk, int flags, int *err)
 
 out:
        sctp_release_sock(sk);
-       *err = error;
+       *err = error;
        return newsk;
 }
 
@@ -3087,7 +3093,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
        sp->assocparams.sasoc_cookie_life = sctp_valid_cookie_life;
 
        /* Initialize default event subscriptions. By default, all the
-        * options are off. 
+        * options are off.
         */
        memset(&sp->subscribe, 0, sizeof(struct sctp_event_subscribe));
 
@@ -3099,8 +3105,8 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
        sp->pathmtu     = 0; // allow default discovery
        sp->sackdelay   = sctp_sack_timeout;
        sp->param_flags = SPP_HB_ENABLE |
-                         SPP_PMTUD_ENABLE |
-                         SPP_SACKDELAY_ENABLE;
+                         SPP_PMTUD_ENABLE |
+                         SPP_SACKDELAY_ENABLE;
 
        /* If enabled no SCTP message fragmentation will be performed.
         * Configure through SCTP_DISABLE_FRAGMENTS socket option.
@@ -3123,7 +3129,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
        /* User specified fragmentation limit. */
        sp->user_frag         = 0;
 
-       sp->adaption_ind = 0;
+       sp->adaptation_ind = 0;
 
        sp->pf = sctp_get_pf_specific(sk->sk_family);
 
@@ -3680,7 +3686,7 @@ static int sctp_getsockopt_delayed_ack_time(struct sock *sk, int len,
        /* Get association, if assoc_id != 0 and the socket is a one
         * to many style socket, and an association was not found, then
         * the id was invalid.
-        */
+        */
        asoc = sctp_id2assoc(sk, params.assoc_id);
        if (!asoc && params.assoc_id && sctp_style(sk, UDP))
                return -EINVAL;
@@ -3756,7 +3762,7 @@ static int sctp_getsockopt_peer_addrs_num_old(struct sock *sk, int len,
        return cnt;
 }
 
-/* 
+/*
  * Old API for getting list of peer addresses. Does not work for 32-bit
  * programs running on a 64-bit kernel
  */
@@ -3833,7 +3839,7 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
                return -EINVAL;
 
        to = optval + offsetof(struct sctp_getaddrs,addrs);
-       space_left = len - sizeof(struct sctp_getaddrs) - 
+       space_left = len - sizeof(struct sctp_getaddrs) -
                        offsetof(struct sctp_getaddrs,addrs);
 
        list_for_each(pos, &asoc->peer.transport_addr_list) {
@@ -3907,7 +3913,7 @@ static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len,
                                addr = list_entry(pos,
                                                  struct sctp_sockaddr_entry,
                                                  list);
-                               if ((PF_INET == sk->sk_family) && 
+                               if ((PF_INET == sk->sk_family) &&
                                    (AF_INET6 == addr->a.sa.sa_family))
                                        continue;
                                cnt++;
@@ -3941,7 +3947,7 @@ static int sctp_copy_laddrs_to_user_old(struct sock *sk, __u16 port, int max_add
 
        list_for_each_safe(pos, next, &sctp_local_addr_list) {
                addr = list_entry(pos, struct sctp_sockaddr_entry, list);
-               if ((PF_INET == sk->sk_family) && 
+               if ((PF_INET == sk->sk_family) &&
                    (AF_INET6 == addr->a.sa.sa_family))
                        continue;
                memcpy(&temp, &addr->a, sizeof(temp));
@@ -3970,7 +3976,7 @@ static int sctp_copy_laddrs_to_user(struct sock *sk, __u16 port,
 
        list_for_each_safe(pos, next, &sctp_local_addr_list) {
                addr = list_entry(pos, struct sctp_sockaddr_entry, list);
-               if ((PF_INET == sk->sk_family) && 
+               if ((PF_INET == sk->sk_family) &&
                    (AF_INET6 == addr->a.sa.sa_family))
                        continue;
                memcpy(&temp, &addr->a, sizeof(temp));
@@ -4051,7 +4057,7 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len,
                                err = cnt;
                                goto unlock;
                        }
-                       goto copy_getaddrs;             
+                       goto copy_getaddrs;
                }
        }
 
@@ -4139,7 +4145,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
                                err = cnt;
                                goto unlock;
                        }
-                       goto copy_getaddrs;             
+                       goto copy_getaddrs;
                }
        }
 
@@ -4196,7 +4202,7 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len,
 
        if (!asoc->peer.primary_path)
                return -ENOTCONN;
-       
+
        memcpy(&prim.ssp_addr, &asoc->peer.primary_path->ipaddr,
                asoc->peer.primary_path->af_specific->sockaddr_len);
 
@@ -4210,21 +4216,21 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len,
 }
 
 /*
- * 7.1.11  Set Adaption Layer Indicator (SCTP_ADAPTION_LAYER)
+ * 7.1.11  Set Adaptation Layer Indicator (SCTP_ADAPTATION_LAYER)
  *
- * Requests that the local endpoint set the specified Adaption Layer
+ * Requests that the local endpoint set the specified Adaptation Layer
  * Indication parameter for all future INIT and INIT-ACK exchanges.
  */
-static int sctp_getsockopt_adaption_layer(struct sock *sk, int len,
+static int sctp_getsockopt_adaptation_layer(struct sock *sk, int len,
                                  char __user *optval, int __user *optlen)
 {
-       struct sctp_setadaption adaption;
+       struct sctp_setadaptation adaptation;
 
-       if (len != sizeof(struct sctp_setadaption))
+       if (len != sizeof(struct sctp_setadaptation))
                return -EINVAL;
 
-       adaption.ssb_adaption_ind = sctp_sk(sk)->adaption_ind;
-       if (copy_to_user(optval, &adaption, len))
+       adaptation.ssb_adaptation_ind = sctp_sk(sk)->adaptation_ind;
+       if (copy_to_user(optval, &adaptation, len))
                return -EFAULT;
 
        return 0;
@@ -4635,8 +4641,8 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
                retval = sctp_getsockopt_peer_addr_info(sk, len, optval,
                                                        optlen);
                break;
-       case SCTP_ADAPTION_LAYER:
-               retval = sctp_getsockopt_adaption_layer(sk, len, optval,
+       case SCTP_ADAPTATION_LAYER:
+               retval = sctp_getsockopt_adaptation_layer(sk, len, optval,
                                                        optlen);
                break;
        case SCTP_CONTEXT:
@@ -4864,7 +4870,7 @@ SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog)
        if (!backlog) {
                if (sctp_sstate(sk, CLOSED))
                        return 0;
-               
+
                sctp_unhash_endpoint(ep);
                sk->sk_state = SCTP_SS_CLOSED;
        }
@@ -4872,7 +4878,7 @@ SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog)
        /* Return if we are already listening. */
        if (sctp_sstate(sk, LISTENING))
                return 0;
-               
+
        /*
         * If a bind() or sctp_bindx() is not called prior to a listen()
         * call that allows new associations to be accepted, the system
@@ -4907,7 +4913,7 @@ SCTP_STATIC int sctp_stream_listen(struct sock *sk, int backlog)
        if (!backlog) {
                if (sctp_sstate(sk, CLOSED))
                        return 0;
-               
+
                sctp_unhash_endpoint(ep);
                sk->sk_state = SCTP_SS_CLOSED;
        }
@@ -5010,7 +5016,7 @@ unsigned int sctp_poll(struct file *file, struct socket *sock, poll_table *wait)
         */
        if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))
                return (!list_empty(&sp->ep->asocs)) ?
-                       (POLLIN | POLLRDNORM) : 0;
+                       (POLLIN | POLLRDNORM) : 0;
 
        mask = 0;
 
@@ -5430,7 +5436,7 @@ static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p,
        DEFINE_WAIT(wait);
 
        SCTP_DEBUG_PRINTK("wait_for_sndbuf: asoc=%p, timeo=%ld, msg_len=%zu\n",
-                         asoc, (long)(*timeo_p), msg_len);
+                         asoc, (long)(*timeo_p), msg_len);
 
        /* Increment the association's refcnt.  */
        sctp_association_hold(asoc);
@@ -5638,6 +5644,36 @@ void sctp_wait_for_close(struct sock *sk, long timeout)
        finish_wait(sk->sk_sleep, &wait);
 }
 
+static void sctp_sock_rfree_frag(struct sk_buff *skb)
+{
+       struct sk_buff *frag;
+
+       if (!skb->data_len)
+               goto done;
+
+       /* Don't forget the fragments. */
+       for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next)
+               sctp_sock_rfree_frag(frag);
+
+done:
+       sctp_sock_rfree(skb);
+}
+
+static void sctp_skb_set_owner_r_frag(struct sk_buff *skb, struct sock *sk)
+{
+       struct sk_buff *frag;
+
+       if (!skb->data_len)
+               goto done;
+
+       /* Don't forget the fragments. */
+       for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next)
+               sctp_skb_set_owner_r_frag(frag, sk);
+
+done:
+       sctp_skb_set_owner_r(skb, sk);
+}
+
 /* Populate the fields of the newsk from the oldsk and migrate the assoc
  * and its messages to the newsk.
  */
@@ -5692,10 +5728,10 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
        sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) {
                event = sctp_skb2event(skb);
                if (event->asoc == assoc) {
-                       sctp_sock_rfree(skb);
+                       sctp_sock_rfree_frag(skb);
                        __skb_unlink(skb, &oldsk->sk_receive_queue);
                        __skb_queue_tail(&newsk->sk_receive_queue, skb);
-                       sctp_skb_set_owner_r(skb, newsk);
+                       sctp_skb_set_owner_r_frag(skb, newsk);
                }
        }
 
@@ -5723,10 +5759,10 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
                sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) {
                        event = sctp_skb2event(skb);
                        if (event->asoc == assoc) {
-                               sctp_sock_rfree(skb);
+                               sctp_sock_rfree_frag(skb);
                                __skb_unlink(skb, &oldsp->pd_lobby);
                                __skb_queue_tail(queue, skb);
-                               sctp_skb_set_owner_r(skb, newsk);
+                               sctp_skb_set_owner_r_frag(skb, newsk);
                        }
                }
 
@@ -5738,6 +5774,16 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
 
        }
 
+       sctp_skb_for_each(skb, &assoc->ulpq.reasm, tmp) {
+               sctp_sock_rfree_frag(skb);
+               sctp_skb_set_owner_r_frag(skb, newsk);
+       }
+
+       sctp_skb_for_each(skb, &assoc->ulpq.lobby, tmp) {
+               sctp_sock_rfree_frag(skb);
+               sctp_skb_set_owner_r_frag(skb, newsk);
+       }
+
        /* Set the type of socket to indicate that it is peeled off from the
         * original UDP-style socket or created with the accept() call on a
         * TCP-style socket..