]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - net/x25/af_x25.c
X25: pushdown bkl in ioctls
[net-next-2.6.git] / net / x25 / af_x25.c
index 36e84e13c6aa9f6167d9b6ba2cf48b72829c2d58..c99029bc411c41eecacdf9aa74526d404eb0d88e 100644 (file)
@@ -453,7 +453,6 @@ static int x25_setsockopt(struct socket *sock, int level, int optname,
        struct sock *sk = sock->sk;
        int rc = -ENOPROTOOPT;
 
-       lock_kernel();
        if (level != SOL_X25 || optname != X25_QBITINCL)
                goto out;
 
@@ -465,10 +464,12 @@ static int x25_setsockopt(struct socket *sock, int level, int optname,
        if (get_user(opt, (int __user *)optval))
                goto out;
 
-       x25_sk(sk)->qbitincl = !!opt;
+       if (opt)
+               set_bit(X25_Q_BIT_FLAG, &x25_sk(sk)->flags);
+       else
+               clear_bit(X25_Q_BIT_FLAG, &x25_sk(sk)->flags);
        rc = 0;
 out:
-       unlock_kernel();
        return rc;
 }
 
@@ -478,7 +479,6 @@ static int x25_getsockopt(struct socket *sock, int level, int optname,
        struct sock *sk = sock->sk;
        int val, len, rc = -ENOPROTOOPT;
 
-       lock_kernel();
        if (level != SOL_X25 || optname != X25_QBITINCL)
                goto out;
 
@@ -496,10 +496,9 @@ static int x25_getsockopt(struct socket *sock, int level, int optname,
        if (put_user(len, optlen))
                goto out;
 
-       val = x25_sk(sk)->qbitincl;
+       val = test_bit(X25_Q_BIT_FLAG, &x25_sk(sk)->flags);
        rc = copy_to_user(optval, &val, len) ? -EFAULT : 0;
 out:
-       unlock_kernel();
        return rc;
 }
 
@@ -508,14 +507,14 @@ static int x25_listen(struct socket *sock, int backlog)
        struct sock *sk = sock->sk;
        int rc = -EOPNOTSUPP;
 
-       lock_kernel();
+       lock_sock(sk);
        if (sk->sk_state != TCP_LISTEN) {
                memset(&x25_sk(sk)->dest_addr, 0, X25_ADDR_LEN);
                sk->sk_max_ack_backlog = backlog;
                sk->sk_state           = TCP_LISTEN;
                rc = 0;
        }
-       unlock_kernel();
+       release_sock(sk);
 
        return rc;
 }
@@ -583,7 +582,7 @@ static int x25_create(struct net *net, struct socket *sock, int protocol,
        x25->t2    = sysctl_x25_ack_holdback_timeout;
        x25->state = X25_STATE_0;
        x25->cudmatchlength = 0;
-       x25->accptapprv = X25_DENY_ACCPT_APPRV;         /* normally no cud  */
+       set_bit(X25_ACCPT_APPRV_FLAG, &x25->flags);     /* normally no cud  */
                                                        /* on call accept   */
 
        x25->facilities.winsize_in  = X25_DEFAULT_WINDOW_SIZE;
@@ -632,12 +631,12 @@ static struct sock *x25_make_new(struct sock *osk)
        x25->t22        = ox25->t22;
        x25->t23        = ox25->t23;
        x25->t2         = ox25->t2;
+       x25->flags      = ox25->flags;
        x25->facilities = ox25->facilities;
-       x25->qbitincl   = ox25->qbitincl;
        x25->dte_facilities = ox25->dte_facilities;
        x25->cudmatchlength = ox25->cudmatchlength;
-       x25->accptapprv = ox25->accptapprv;
 
+       clear_bit(X25_INTERRUPT_FLAG, &x25->flags);
        x25_init_timers(sk);
 out:
        return sk;
@@ -689,7 +688,6 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr;
        int len, i, rc = 0;
 
-       lock_kernel();
        if (!sock_flag(sk, SOCK_ZAPPED) ||
            addr_len != sizeof(struct sockaddr_x25) ||
            addr->sx25_family != AF_X25) {
@@ -705,12 +703,13 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
                }
        }
 
+       lock_sock(sk);
        x25_sk(sk)->source_addr = addr->sx25_addr;
        x25_insert_socket(sk);
        sock_reset_flag(sk, SOCK_ZAPPED);
+       release_sock(sk);
        SOCK_DEBUG(sk, "x25_bind: socket is bound\n");
 out:
-       unlock_kernel();
        return rc;
 }
 
@@ -719,7 +718,7 @@ static int x25_wait_for_connection_establishment(struct sock *sk)
        DECLARE_WAITQUEUE(wait, current);
        int rc;
 
-       add_wait_queue_exclusive(sk->sk_sleep, &wait);
+       add_wait_queue_exclusive(sk_sleep(sk), &wait);
        for (;;) {
                __set_current_state(TASK_INTERRUPTIBLE);
                rc = -ERESTARTSYS;
@@ -739,7 +738,7 @@ static int x25_wait_for_connection_establishment(struct sock *sk)
                        break;
        }
        __set_current_state(TASK_RUNNING);
-       remove_wait_queue(sk->sk_sleep, &wait);
+       remove_wait_queue(sk_sleep(sk), &wait);
        return rc;
 }
 
@@ -752,7 +751,6 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr,
        struct x25_route *rt;
        int rc = 0;
 
-       lock_kernel();
        lock_sock(sk);
        if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
                sock->state = SS_CONNECTED;
@@ -830,7 +828,6 @@ out_put_route:
        x25_route_put(rt);
 out:
        release_sock(sk);
-       unlock_kernel();
        return rc;
 }
 
@@ -839,7 +836,7 @@ static int x25_wait_for_data(struct sock *sk, long timeout)
        DECLARE_WAITQUEUE(wait, current);
        int rc = 0;
 
-       add_wait_queue_exclusive(sk->sk_sleep, &wait);
+       add_wait_queue_exclusive(sk_sleep(sk), &wait);
        for (;;) {
                __set_current_state(TASK_INTERRUPTIBLE);
                if (sk->sk_shutdown & RCV_SHUTDOWN)
@@ -859,7 +856,7 @@ static int x25_wait_for_data(struct sock *sk, long timeout)
                        break;
        }
        __set_current_state(TASK_RUNNING);
-       remove_wait_queue(sk->sk_sleep, &wait);
+       remove_wait_queue(sk_sleep(sk), &wait);
        return rc;
 }
 
@@ -870,8 +867,7 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags)
        struct sk_buff *skb;
        int rc = -EINVAL;
 
-       lock_kernel();
-       if (!sk || sk->sk_state != TCP_LISTEN)
+       if (!sk)
                goto out;
 
        rc = -EOPNOTSUPP;
@@ -879,6 +875,10 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags)
                goto out;
 
        lock_sock(sk);
+       rc = -EINVAL;
+       if (sk->sk_state != TCP_LISTEN)
+               goto out2;
+
        rc = x25_wait_for_data(sk, sk->sk_rcvtimeo);
        if (rc)
                goto out2;
@@ -898,7 +898,6 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags)
 out2:
        release_sock(sk);
 out:
-       unlock_kernel();
        return rc;
 }
 
@@ -910,7 +909,6 @@ static int x25_getname(struct socket *sock, struct sockaddr *uaddr,
        struct x25_sock *x25 = x25_sk(sk);
        int rc = 0;
 
-       lock_kernel();
        if (peer) {
                if (sk->sk_state != TCP_ESTABLISHED) {
                        rc = -ENOTCONN;
@@ -924,19 +922,6 @@ static int x25_getname(struct socket *sock, struct sockaddr *uaddr,
        *uaddr_len = sizeof(*sx25);
 
 out:
-       unlock_kernel();
-       return rc;
-}
-
-static unsigned int x25_datagram_poll(struct file *file, struct socket *sock,
-                          poll_table *wait)
-{
-       int rc;
-
-       lock_kernel();
-       rc = datagram_poll(file, sock, wait);
-       unlock_kernel();
-
        return rc;
 }
 
@@ -1053,8 +1038,8 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
        makex25->vc_facil_mask &= ~X25_MASK_CALLING_AE;
        makex25->cudmatchlength = x25_sk(sk)->cudmatchlength;
 
-       /* Normally all calls are accepted immediatly */
-       if(makex25->accptapprv & X25_DENY_ACCPT_APPRV) {
+       /* Normally all calls are accepted immediately */
+       if (test_bit(X25_ACCPT_APPRV_FLAG, &makex25->flags)) {
                x25_write_internal(make, X25_CALL_ACCEPTED);
                makex25->state = X25_STATE_3;
        }
@@ -1186,7 +1171,7 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock,
         *      If the Q BIT Include socket option is in force, the first
         *      byte of the user data is the logical value of the Q Bit.
         */
-       if (x25->qbitincl) {
+       if (test_bit(X25_Q_BIT_FLAG, &x25->flags)) {
                qbit = skb->data[0];
                skb_pull(skb, 1);
        }
@@ -1242,7 +1227,7 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock,
                len = rc;
                if (rc < 0)
                        kfree_skb(skb);
-               else if (x25->qbitincl)
+               else if (test_bit(X25_Q_BIT_FLAG, &x25->flags))
                        len++;
        }
 
@@ -1307,7 +1292,7 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock,
                /*
                 *      No Q bit information on Interrupt data.
                 */
-               if (x25->qbitincl) {
+               if (test_bit(X25_Q_BIT_FLAG, &x25->flags)) {
                        asmptr  = skb_push(skb, 1);
                        *asmptr = 0x00;
                }
@@ -1325,7 +1310,7 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock,
                skb_pull(skb, x25->neighbour->extended ?
                                X25_EXT_MIN_LEN : X25_STD_MIN_LEN);
 
-               if (x25->qbitincl) {
+               if (test_bit(X25_Q_BIT_FLAG, &x25->flags)) {
                        asmptr  = skb_push(skb, 1);
                        *asmptr = qbit;
                }
@@ -1372,14 +1357,16 @@ 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;
 
+                       lock_kernel();
+                       amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
                        if (amount < 0)
                                amount = 0;
                        rc = put_user(amount, (unsigned int __user *)argp);
+                       unlock_kernel();
                        break;
                }
 
@@ -1390,23 +1377,29 @@ 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_kernel();
                        if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL)
                                amount = skb->len;
                        rc = put_user(amount, (unsigned int __user *)argp);
+                       unlock_kernel();
                        break;
                }
 
                case SIOCGSTAMP:
                        rc = -EINVAL;
+                       lock_kernel();
                        if (sk)
                                rc = sock_get_timestamp(sk,
                                                (struct timeval __user *)argp);
+                       unlock_kernel();
                        break;
                case SIOCGSTAMPNS:
                        rc = -EINVAL;
+                       lock_kernel();
                        if (sk)
                                rc = sock_get_timestampns(sk,
                                                (struct timespec __user *)argp);
+                       unlock_kernel();
                        break;
                case SIOCGIFADDR:
                case SIOCSIFADDR:
@@ -1425,27 +1418,36 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                        rc = -EPERM;
                        if (!capable(CAP_NET_ADMIN))
                                break;
+                       lock_kernel();
                        rc = x25_route_ioctl(cmd, argp);
+                       unlock_kernel();
                        break;
                case SIOCX25GSUBSCRIP:
+                       lock_kernel();
                        rc = x25_subscr_ioctl(cmd, argp);
+                       unlock_kernel();
                        break;
                case SIOCX25SSUBSCRIP:
                        rc = -EPERM;
                        if (!capable(CAP_NET_ADMIN))
                                break;
+                       lock_kernel();
                        rc = x25_subscr_ioctl(cmd, argp);
+                       unlock_kernel();
                        break;
                case SIOCX25GFACILITIES: {
                        struct x25_facilities fac = x25->facilities;
+                       lock_kernel();
                        rc = copy_to_user(argp, &fac,
                                          sizeof(fac)) ? -EFAULT : 0;
+                       unlock_kernel();
                        break;
                }
 
                case SIOCX25SFACILITIES: {
                        struct x25_facilities facilities;
                        rc = -EFAULT;
+                       lock_kernel();
                        if (copy_from_user(&facilities, argp,
                                           sizeof(facilities)))
                                break;
@@ -1481,12 +1483,15 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                                break;
                        x25->facilities = facilities;
                        rc = 0;
+                       unlock_kernel();
                        break;
                }
 
                case SIOCX25GDTEFACILITIES: {
+                       lock_kernel();
                        rc = copy_to_user(argp, &x25->dte_facilities,
                                                sizeof(x25->dte_facilities));
+                       unlock_kernel();
                        if (rc)
                                rc = -EFAULT;
                        break;
@@ -1495,6 +1500,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                case SIOCX25SDTEFACILITIES: {
                        struct x25_dte_facilities dtefacs;
                        rc = -EFAULT;
+                       lock_kernel();
                        if (copy_from_user(&dtefacs, argp, sizeof(dtefacs)))
                                break;
                        rc = -EINVAL;
@@ -1511,13 +1517,16 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                                break;
                        x25->dte_facilities = dtefacs;
                        rc = 0;
+                       unlock_kernel();
                        break;
                }
 
                case SIOCX25GCALLUSERDATA: {
                        struct x25_calluserdata cud = x25->calluserdata;
+                       lock_kernel();
                        rc = copy_to_user(argp, &cud,
                                          sizeof(cud)) ? -EFAULT : 0;
+                       unlock_kernel();
                        break;
                }
 
@@ -1525,6 +1534,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                        struct x25_calluserdata calluserdata;
 
                        rc = -EFAULT;
+                       lock_kernel();
                        if (copy_from_user(&calluserdata, argp,
                                           sizeof(calluserdata)))
                                break;
@@ -1532,24 +1542,29 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                        if (calluserdata.cudlength > X25_MAX_CUD_LEN)
                                break;
                        x25->calluserdata = calluserdata;
+                       unlock_kernel();
                        rc = 0;
                        break;
                }
 
                case SIOCX25GCAUSEDIAG: {
                        struct x25_causediag causediag;
+                       lock_kernel();
                        causediag = x25->causediag;
                        rc = copy_to_user(argp, &causediag,
                                          sizeof(causediag)) ? -EFAULT : 0;
+                       unlock_kernel();
                        break;
                }
 
                case SIOCX25SCAUSEDIAG: {
                        struct x25_causediag causediag;
                        rc = -EFAULT;
+                       lock_kernel();
                        if (copy_from_user(&causediag, argp, sizeof(causediag)))
                                break;
                        x25->causediag = causediag;
+                       unlock_kernel();
                        rc = 0;
                        break;
 
@@ -1558,6 +1573,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                case SIOCX25SCUDMATCHLEN: {
                        struct x25_subaddr sub_addr;
                        rc = -EINVAL;
+                       lock_kernel();
                        if(sk->sk_state != TCP_CLOSE)
                                break;
                        rc = -EFAULT;
@@ -1568,27 +1584,33 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                        if(sub_addr.cudmatchlength > X25_MAX_CUD_LEN)
                                break;
                        x25->cudmatchlength = sub_addr.cudmatchlength;
+                       unlock_kernel();
                        rc = 0;
                        break;
                }
 
                case SIOCX25CALLACCPTAPPRV: {
                        rc = -EINVAL;
+                       lock_kernel();
                        if (sk->sk_state != TCP_CLOSE)
                                break;
-                       x25->accptapprv = X25_ALLOW_ACCPT_APPRV;
+                       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;
-                       if (x25->accptapprv)    /* must call accptapprv above */
+                       /* must call accptapprv above */
+                       if (test_bit(X25_ACCPT_APPRV_FLAG, &x25->flags))
                                break;
                        x25_write_internal(sk, X25_CALL_ACCEPTED);
                        x25->state = X25_STATE_3;
+                       unlock_kernel();
                        rc = 0;
                        break;
                }
@@ -1597,7 +1619,6 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                        rc = -ENOIOCTLCMD;
                        break;
        }
-       unlock_kernel();
 
        return rc;
 }
@@ -1746,7 +1767,7 @@ static const struct proto_ops x25_proto_ops = {
        .socketpair =   sock_no_socketpair,
        .accept =       x25_accept,
        .getname =      x25_getname,
-       .poll =         x25_datagram_poll,
+       .poll =         datagram_poll,
        .ioctl =        x25_ioctl,
 #ifdef CONFIG_COMPAT
        .compat_ioctl = compat_x25_ioctl,