]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - net/x25/af_x25.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / net / x25 / af_x25.c
index f7af98dff40954705df9a195382435496228df97..ad96ee90fe2760d324876a7ec582ed82d71b25d2 100644 (file)
@@ -1357,11 +1357,11 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
        void __user *argp = (void __user *)arg;
        int rc;
 
-       lock_kernel();
        switch (cmd) {
                case TIOCOUTQ: {
-                       int amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
+                       int amount;
 
+                       amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
                        if (amount < 0)
                                amount = 0;
                        rc = put_user(amount, (unsigned int __user *)argp);
@@ -1375,8 +1375,10 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                         * These two are safe on a single CPU system as
                         * only user tasks fiddle here
                         */
+                       lock_sock(sk);
                        if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL)
                                amount = skb->len;
+                       release_sock(sk);
                        rc = put_user(amount, (unsigned int __user *)argp);
                        break;
                }
@@ -1422,9 +1424,11 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                        rc = x25_subscr_ioctl(cmd, argp);
                        break;
                case SIOCX25GFACILITIES: {
-                       struct x25_facilities fac = x25->facilities;
-                       rc = copy_to_user(argp, &fac,
-                                         sizeof(fac)) ? -EFAULT : 0;
+                       lock_sock(sk);
+                       rc = copy_to_user(argp, &x25->facilities,
+                                               sizeof(x25->facilities))
+                                               ? -EFAULT : 0;
+                       release_sock(sk);
                        break;
                }
 
@@ -1435,18 +1439,19 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                                           sizeof(facilities)))
                                break;
                        rc = -EINVAL;
+                       lock_sock(sk);
                        if (sk->sk_state != TCP_LISTEN &&
                            sk->sk_state != TCP_CLOSE)
-                               break;
+                               goto out_fac_release;
                        if (facilities.pacsize_in < X25_PS16 ||
                            facilities.pacsize_in > X25_PS4096)
-                               break;
+                               goto out_fac_release;
                        if (facilities.pacsize_out < X25_PS16 ||
                            facilities.pacsize_out > X25_PS4096)
-                               break;
+                               goto out_fac_release;
                        if (facilities.winsize_in < 1 ||
                            facilities.winsize_in > 127)
-                               break;
+                               goto out_fac_release;
                        if (facilities.throughput) {
                                int out = facilities.throughput & 0xf0;
                                int in  = facilities.throughput & 0x0f;
@@ -1454,24 +1459,28 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                                        facilities.throughput |=
                                                X25_DEFAULT_THROUGHPUT << 4;
                                else if (out < 0x30 || out > 0xD0)
-                                       break;
+                                       goto out_fac_release;
                                if (!in)
                                        facilities.throughput |=
                                                X25_DEFAULT_THROUGHPUT;
                                else if (in < 0x03 || in > 0x0D)
-                                       break;
+                                       goto out_fac_release;
                        }
                        if (facilities.reverse &&
                                (facilities.reverse & 0x81) != 0x81)
-                               break;
+                               goto out_fac_release;
                        x25->facilities = facilities;
                        rc = 0;
+out_fac_release:
+                       release_sock(sk);
                        break;
                }
 
                case SIOCX25GDTEFACILITIES: {
+                       lock_sock(sk);
                        rc = copy_to_user(argp, &x25->dte_facilities,
                                                sizeof(x25->dte_facilities));
+                       release_sock(sk);
                        if (rc)
                                rc = -EFAULT;
                        break;
@@ -1483,26 +1492,31 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                        if (copy_from_user(&dtefacs, argp, sizeof(dtefacs)))
                                break;
                        rc = -EINVAL;
+                       lock_sock(sk);
                        if (sk->sk_state != TCP_LISTEN &&
                                        sk->sk_state != TCP_CLOSE)
-                               break;
+                               goto out_dtefac_release;
                        if (dtefacs.calling_len > X25_MAX_AE_LEN)
-                               break;
+                               goto out_dtefac_release;
                        if (dtefacs.calling_ae == NULL)
-                               break;
+                               goto out_dtefac_release;
                        if (dtefacs.called_len > X25_MAX_AE_LEN)
-                               break;
+                               goto out_dtefac_release;
                        if (dtefacs.called_ae == NULL)
-                               break;
+                               goto out_dtefac_release;
                        x25->dte_facilities = dtefacs;
                        rc = 0;
+out_dtefac_release:
+                       release_sock(sk);
                        break;
                }
 
                case SIOCX25GCALLUSERDATA: {
-                       struct x25_calluserdata cud = x25->calluserdata;
-                       rc = copy_to_user(argp, &cud,
-                                         sizeof(cud)) ? -EFAULT : 0;
+                       lock_sock(sk);
+                       rc = copy_to_user(argp, &x25->calluserdata,
+                                       sizeof(x25->calluserdata))
+                                       ? -EFAULT : 0;
+                       release_sock(sk);
                        break;
                }
 
@@ -1516,16 +1530,19 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                        rc = -EINVAL;
                        if (calluserdata.cudlength > X25_MAX_CUD_LEN)
                                break;
+                       lock_sock(sk);
                        x25->calluserdata = calluserdata;
+                       release_sock(sk);
                        rc = 0;
                        break;
                }
 
                case SIOCX25GCAUSEDIAG: {
-                       struct x25_causediag causediag;
-                       causediag = x25->causediag;
-                       rc = copy_to_user(argp, &causediag,
-                                         sizeof(causediag)) ? -EFAULT : 0;
+                       lock_sock(sk);
+                       rc = copy_to_user(argp, &x25->causediag,
+                                       sizeof(x25->causediag))
+                                       ? -EFAULT : 0;
+                       release_sock(sk);
                        break;
                }
 
@@ -1534,7 +1551,9 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                        rc = -EFAULT;
                        if (copy_from_user(&causediag, argp, sizeof(causediag)))
                                break;
+                       lock_sock(sk);
                        x25->causediag = causediag;
+                       release_sock(sk);
                        rc = 0;
                        break;
 
@@ -1543,31 +1562,37 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                case SIOCX25SCUDMATCHLEN: {
                        struct x25_subaddr sub_addr;
                        rc = -EINVAL;
+                       lock_sock(sk);
                        if(sk->sk_state != TCP_CLOSE)
-                               break;
+                               goto out_cud_release;
                        rc = -EFAULT;
                        if (copy_from_user(&sub_addr, argp,
                                        sizeof(sub_addr)))
-                               break;
+                               goto out_cud_release;
                        rc = -EINVAL;
                        if(sub_addr.cudmatchlength > X25_MAX_CUD_LEN)
-                               break;
+                               goto out_cud_release;
                        x25->cudmatchlength = sub_addr.cudmatchlength;
                        rc = 0;
+out_cud_release:
+                       release_sock(sk);
                        break;
                }
 
                case SIOCX25CALLACCPTAPPRV: {
                        rc = -EINVAL;
+                       lock_kernel();
                        if (sk->sk_state != TCP_CLOSE)
                                break;
                        clear_bit(X25_ACCPT_APPRV_FLAG, &x25->flags);
+                       unlock_kernel();
                        rc = 0;
                        break;
                }
 
                case SIOCX25SENDCALLACCPT:  {
                        rc = -EINVAL;
+                       lock_kernel();
                        if (sk->sk_state != TCP_ESTABLISHED)
                                break;
                        /* must call accptapprv above */
@@ -1575,6 +1600,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                                break;
                        x25_write_internal(sk, X25_CALL_ACCEPTED);
                        x25->state = X25_STATE_3;
+                       unlock_kernel();
                        rc = 0;
                        break;
                }
@@ -1583,7 +1609,6 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                        rc = -ENOIOCTLCMD;
                        break;
        }
-       unlock_kernel();
 
        return rc;
 }
@@ -1619,16 +1644,20 @@ static int compat_x25_subscr_ioctl(unsigned int cmd,
        dev_put(dev);
 
        if (cmd == SIOCX25GSUBSCRIP) {
+               read_lock_bh(&x25_neigh_list_lock);
                x25_subscr.extended = nb->extended;
                x25_subscr.global_facil_mask = nb->global_facil_mask;
+               read_unlock_bh(&x25_neigh_list_lock);
                rc = copy_to_user(x25_subscr32, &x25_subscr,
                                sizeof(*x25_subscr32)) ? -EFAULT : 0;
        } else {
                rc = -EINVAL;
                if (x25_subscr.extended == 0 || x25_subscr.extended == 1) {
                        rc = 0;
+                       write_lock_bh(&x25_neigh_list_lock);
                        nb->extended = x25_subscr.extended;
                        nb->global_facil_mask = x25_subscr.global_facil_mask;
+                       write_unlock_bh(&x25_neigh_list_lock);
                }
        }
        x25_neigh_put(nb);
@@ -1654,19 +1683,15 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
                break;
        case SIOCGSTAMP:
                rc = -EINVAL;
-               lock_kernel();
                if (sk)
                        rc = compat_sock_get_timestamp(sk,
                                        (struct timeval __user*)argp);
-               unlock_kernel();
                break;
        case SIOCGSTAMPNS:
                rc = -EINVAL;
-               lock_kernel();
                if (sk)
                        rc = compat_sock_get_timestampns(sk,
                                        (struct timespec __user*)argp);
-               unlock_kernel();
                break;
        case SIOCGIFADDR:
        case SIOCSIFADDR:
@@ -1685,22 +1710,16 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
                rc = -EPERM;
                if (!capable(CAP_NET_ADMIN))
                        break;
-               lock_kernel();
                rc = x25_route_ioctl(cmd, argp);
-               unlock_kernel();
                break;
        case SIOCX25GSUBSCRIP:
-               lock_kernel();
                rc = compat_x25_subscr_ioctl(cmd, argp);
-               unlock_kernel();
                break;
        case SIOCX25SSUBSCRIP:
                rc = -EPERM;
                if (!capable(CAP_NET_ADMIN))
                        break;
-               lock_kernel();
                rc = compat_x25_subscr_ioctl(cmd, argp);
-               unlock_kernel();
                break;
        case SIOCX25GFACILITIES:
        case SIOCX25SFACILITIES: