mac80211: Fix HT rate control configuration
[safe/jmp/linux-2.6] / net / unix / af_unix.c
index ebc4a9a..3d9122e 100644 (file)
@@ -144,7 +144,7 @@ static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
 /*
  *  SMP locking strategy:
  *    hash table is protected with spinlock unix_table_lock
- *    each socket state is protected by separate rwlock.
+ *    each socket state is protected by separate spin lock.
  */
 
 static inline unsigned unix_hash_fold(__wsum n)
@@ -315,7 +315,7 @@ static void unix_write_space(struct sock *sk)
 {
        read_lock(&sk->sk_callback_lock);
        if (unix_writable(sk)) {
-               if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
+               if (sk_has_sleeper(sk))
                        wake_up_interruptible_sync(sk->sk_sleep);
                sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
        }
@@ -353,7 +353,7 @@ static void unix_sock_destructor(struct sock *sk)
        WARN_ON(!sk_unhashed(sk));
        WARN_ON(sk->sk_socket);
        if (!sock_flag(sk, SOCK_DEAD)) {
-               printk(KERN_DEBUG "Attempt to release alive unix socket: %p\n", sk);
+               printk(KERN_INFO "Attempt to release alive unix socket: %p\n", sk);
                return;
        }
 
@@ -361,7 +361,9 @@ static void unix_sock_destructor(struct sock *sk)
                unix_release_addr(u->addr);
 
        atomic_dec(&unix_nr_socks);
+       local_bh_disable();
        sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
+       local_bh_enable();
 #ifdef UNIX_REFCNT_DEBUG
        printk(KERN_DEBUG "UNIX %p is destroyed, %d are still alive.\n", sk,
                atomic_read(&unix_nr_socks));
@@ -468,8 +470,7 @@ static int unix_listen(struct socket *sock, int backlog)
        sk->sk_state            = TCP_LISTEN;
        /* set credentials so connect can copy them */
        sk->sk_peercred.pid     = task_tgid_vnr(current);
-       sk->sk_peercred.uid     = current->euid;
-       sk->sk_peercred.gid     = current->egid;
+       current_euid_egid(&sk->sk_peercred.uid, &sk->sk_peercred.gid);
        err = 0;
 
 out_unlock:
@@ -569,7 +570,6 @@ static const struct proto_ops unix_seqpacket_ops = {
 static struct proto unix_proto = {
        .name                   = "UNIX",
        .owner                  = THIS_MODULE,
-       .sockets_allocated      = &unix_nr_socks,
        .obj_size               = sizeof(struct unix_sock),
 };
 
@@ -613,13 +613,16 @@ static struct sock *unix_create1(struct net *net, struct socket *sock)
 out:
        if (sk == NULL)
                atomic_dec(&unix_nr_socks);
-       else
+       else {
+               local_bh_disable();
                sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
-
+               local_bh_enable();
+       }
        return sk;
 }
 
-static int unix_create(struct net *net, struct socket *sock, int protocol)
+static int unix_create(struct net *net, struct socket *sock, int protocol,
+                      int kern)
 {
        if (protocol && protocol != PF_UNIX)
                return -EPROTONOSUPPORT;
@@ -830,11 +833,15 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
                 * All right, let's create it.
                 */
                mode = S_IFSOCK |
-                      (SOCK_INODE(sock)->i_mode & ~current->fs->umask);
+                      (SOCK_INODE(sock)->i_mode & ~current_umask());
                err = mnt_want_write(nd.path.mnt);
                if (err)
                        goto out_mknod_dput;
+               err = security_path_mknod(&nd.path, dentry, mode, 0);
+               if (err)
+                       goto out_mknod_drop_write;
                err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0);
+out_mknod_drop_write:
                mnt_drop_write(nd.path.mnt);
                if (err)
                        goto out_mknod_dput;
@@ -1026,8 +1033,8 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
                goto out;
        addr_len = err;
 
-       if (test_bit(SOCK_PASSCRED, &sock->flags)
-               && !u->addr && (err = unix_autobind(sock)) != 0)
+       if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr &&
+           (err = unix_autobind(sock)) != 0)
                goto out;
 
        timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
@@ -1068,6 +1075,8 @@ restart:
        err = -ECONNREFUSED;
        if (other->sk_state != TCP_LISTEN)
                goto out_unlock;
+       if (other->sk_shutdown & RCV_SHUTDOWN)
+               goto out_unlock;
 
        if (unix_recvq_full(other)) {
                err = -EAGAIN;
@@ -1131,8 +1140,7 @@ restart:
        newsk->sk_state         = TCP_ESTABLISHED;
        newsk->sk_type          = sk->sk_type;
        newsk->sk_peercred.pid  = task_tgid_vnr(current);
-       newsk->sk_peercred.uid  = current->euid;
-       newsk->sk_peercred.gid  = current->egid;
+       current_euid_egid(&newsk->sk_peercred.uid, &newsk->sk_peercred.gid);
        newu = unix_sk(newsk);
        newsk->sk_sleep         = &newu->peer_wait;
        otheru = unix_sk(other);
@@ -1173,8 +1181,7 @@ out_unlock:
                unix_state_unlock(other);
 
 out:
-       if (skb)
-               kfree_skb(skb);
+       kfree_skb(skb);
        if (newsk)
                unix_release_sock(newsk, 0);
        if (other)
@@ -1192,8 +1199,9 @@ static int unix_socketpair(struct socket *socka, struct socket *sockb)
        unix_peer(ska) = skb;
        unix_peer(skb) = ska;
        ska->sk_peercred.pid = skb->sk_peercred.pid = task_tgid_vnr(current);
-       ska->sk_peercred.uid = skb->sk_peercred.uid = current->euid;
-       ska->sk_peercred.gid = skb->sk_peercred.gid = current->egid;
+       current_euid_egid(&skb->sk_peercred.uid, &skb->sk_peercred.gid);
+       ska->sk_peercred.uid = skb->sk_peercred.uid;
+       ska->sk_peercred.gid = skb->sk_peercred.gid;
 
        if (ska->sk_type != SOCK_DGRAM) {
                ska->sk_state = TCP_ESTABLISHED;
@@ -1251,7 +1259,7 @@ static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_
 {
        struct sock *sk = sock->sk;
        struct unix_sock *u;
-       struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr;
+       DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, uaddr);
        int err = 0;
 
        if (peer) {
@@ -1348,6 +1356,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
 
        if (NULL == siocb->scm)
                siocb->scm = &tmp_scm;
+       wait_for_unix_gc();
        err = scm_send(sock, msg, siocb->scm);
        if (err < 0)
                return err;
@@ -1369,8 +1378,8 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
                        goto out;
        }
 
-       if (test_bit(SOCK_PASSCRED, &sock->flags)
-               && !u->addr && (err = unix_autobind(sock)) != 0)
+       if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr
+           && (err = unix_autobind(sock)) != 0)
                goto out;
 
        err = -EMSGSIZE;
@@ -1495,9 +1504,11 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
        struct sk_buff *skb;
        int sent = 0;
        struct scm_cookie tmp_scm;
+       bool fds_sent = false;
 
        if (NULL == siocb->scm)
                siocb->scm = &tmp_scm;
+       wait_for_unix_gc();
        err = scm_send(sock, msg, siocb->scm);
        if (err < 0)
                return err;
@@ -1555,12 +1566,14 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
                size = min_t(int, size, skb_tailroom(skb));
 
                memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
-               if (siocb->scm->fp) {
+               /* Only send the fds in the first buffer */
+               if (siocb->scm->fp && !fds_sent) {
                        err = unix_attach_fds(siocb->scm, skb);
                        if (err) {
                                kfree_skb(skb);
                                goto out_err;
                        }
+                       fds_sent = true;
                }
 
                err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
@@ -1939,7 +1952,7 @@ static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 
        switch (cmd) {
        case SIOCOUTQ:
-               amount = atomic_read(&sk->sk_wmem_alloc);
+               amount = sk_wmem_alloc_get(sk);
                err = put_user(amount, (int __user *)arg);
                break;
        case SIOCINQ:
@@ -1978,7 +1991,7 @@ static unsigned int unix_poll(struct file *file, struct socket *sock, poll_table
        struct sock *sk = sock->sk;
        unsigned int mask;
 
-       poll_wait(file, sk->sk_sleep, wait);
+       sock_poll_wait(file, sk->sk_sleep, wait);
        mask = 0;
 
        /* exceptional events? */
@@ -2015,7 +2028,7 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock,
        struct sock *sk = sock->sk, *other;
        unsigned int mask, writable;
 
-       poll_wait(file, sk->sk_sleep, wait);
+       sock_poll_wait(file, sk->sk_sleep, wait);
        mask = 0;
 
        /* exceptional events? */
@@ -2046,7 +2059,7 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock,
                other = unix_peer_get(sk);
                if (other) {
                        if (unix_peer(other) != sk) {
-                               poll_wait(file, &unix_sk(other)->peer_wait,
+                               sock_poll_wait(file, &unix_sk(other)->peer_wait,
                                          wait);
                                if (unix_recvq_full(other))
                                        writable = 0;
@@ -2204,14 +2217,14 @@ static const struct file_operations unix_seq_fops = {
 
 #endif
 
-static struct net_proto_family unix_family_ops = {
+static const struct net_proto_family unix_family_ops = {
        .family = PF_UNIX,
        .create = unix_create,
        .owner  = THIS_MODULE,
 };
 
 
-static int unix_net_init(struct net *net)
+static int __net_init unix_net_init(struct net *net)
 {
        int error = -ENOMEM;
 
@@ -2230,7 +2243,7 @@ out:
        return error;
 }
 
-static void unix_net_exit(struct net *net)
+static void __net_exit unix_net_exit(struct net *net)
 {
        unix_sysctl_unregister(net);
        proc_net_remove(net, "unix");