]> err.no Git - linux-2.6/blobdiff - net/sctp/socket.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc-merge
[linux-2.6] / net / sctp / socket.c
index c66c161908c0dbd9b784a5eae74a8df8b399c24b..d890dfa8818fb27c592f950506e1ccd7144e55c7 100644 (file)
@@ -1010,6 +1010,19 @@ static int __sctp_connect(struct sock* sk,
                                        err = -EAGAIN;
                                        goto out_free;
                                }
+                       } 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 
+                                * be permitted to open new associations.
+                                */
+                               if (ep->base.bind_addr.port < PROT_SOCK &&
+                                   !capable(CAP_NET_BIND_SERVICE)) {
+                                       err = -EACCES;
+                                       goto out_free;
+                               }
                        }
 
                        scope = sctp_scope(&to);
@@ -1515,6 +1528,19 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
                                err = -EAGAIN;
                                goto out_unlock;
                        }
+               } else {
+                       /*
+                        * If an unprivileged user inherits a one-to-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 &&
+                           !capable(CAP_NET_BIND_SERVICE)) {
+                               err = -EACCES;
+                               goto out_unlock;
+                       }
                }
 
                scope = sctp_scope(&to);
@@ -1906,7 +1932,6 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval,
        if (copy_from_user(&sp->autoclose, optval, optlen))
                return -EFAULT;
 
-       sp->ep->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] = sp->autoclose * HZ;
        return 0;
 }
 
@@ -2306,16 +2331,14 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, int optl
                return -EINVAL;
        if (get_user(val, (int __user *)optval))
                return -EFAULT;
-       if ((val < 8) || (val > SCTP_MAX_CHUNK_LEN))
+       if ((val != 0) && ((val < 8) || (val > SCTP_MAX_CHUNK_LEN)))
                return -EINVAL;
        sp->user_frag = val;
 
-       if (val) {
-               /* 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->pmtu); 
-               }
+       /* 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->pmtu); 
        }
 
        return 0;
@@ -4720,11 +4743,6 @@ static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags,
        struct sk_buff *skb;
        long timeo;
 
-       /* Caller is allowed not to check sk->sk_err before calling.  */
-       error = sock_error(sk);
-       if (error)
-               goto no_packet;
-
        timeo = sock_rcvtimeo(sk, noblock);
 
        SCTP_DEBUG_PRINTK("Timeout: timeo: %ld, MAX: %ld.\n",
@@ -4751,6 +4769,11 @@ static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags,
                if (skb)
                        return skb;
 
+               /* Caller is allowed not to check sk->sk_err before calling. */
+               error = sock_error(sk);
+               if (error)
+                       goto no_packet;
+
                if (sk->sk_shutdown & RCV_SHUTDOWN)
                        break;
 
@@ -5091,8 +5114,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) {
+                       sock_rfree(skb);
                        __skb_unlink(skb, &oldsk->sk_receive_queue);
                        __skb_queue_tail(&newsk->sk_receive_queue, skb);
+                       skb_set_owner_r(skb, newsk);
                }
        }
 
@@ -5120,8 +5145,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) {
+                               sock_rfree(skb);
                                __skb_unlink(skb, &oldsp->pd_lobby);
                                __skb_queue_tail(queue, skb);
+                               skb_set_owner_r(skb, newsk);
                        }
                }