Merge branch 'v3.10/topic/cpufreq' of git://git.linaro.org/kernel/linux-linaro-stable...
[firefly-linux-kernel-4.4.55.git] / net / unix / af_unix.c
index 826e09938bff4203def6e5af33db49c4360f3019..75e198d029d2fe044161656b0d589510369a3b22 100644 (file)
@@ -160,9 +160,8 @@ static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
 
 static inline unsigned int unix_hash_fold(__wsum n)
 {
-       unsigned int hash = (__force unsigned int)n;
+       unsigned int hash = (__force unsigned int)csum_fold(n);
 
-       hash ^= hash>>16;
        hash ^= hash>>8;
        return hash&(UNIX_HASH_SIZE-1);
 }
@@ -529,13 +528,17 @@ static int unix_seqpacket_sendmsg(struct kiocb *, struct socket *,
 static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *,
                                  struct msghdr *, size_t, int);
 
-static void unix_set_peek_off(struct sock *sk, int val)
+static int unix_set_peek_off(struct sock *sk, int val)
 {
        struct unix_sock *u = unix_sk(sk);
 
-       mutex_lock(&u->readlock);
+       if (mutex_lock_interruptible(&u->readlock))
+               return -EINTR;
+
        sk->sk_peek_off = val;
        mutex_unlock(&u->readlock);
+
+       return 0;
 }
 
 
@@ -713,7 +716,9 @@ static int unix_autobind(struct socket *sock)
        int err;
        unsigned int retries = 0;
 
-       mutex_lock(&u->readlock);
+       err = mutex_lock_interruptible(&u->readlock);
+       if (err)
+               return err;
 
        err = 0;
        if (u->addr)
@@ -872,7 +877,9 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
                goto out;
        addr_len = err;
 
-       mutex_lock(&u->readlock);
+       err = mutex_lock_interruptible(&u->readlock);
+       if (err)
+               goto out;
 
        err = -EINVAL;
        if (u->addr)
@@ -1245,6 +1252,15 @@ static int unix_socketpair(struct socket *socka, struct socket *sockb)
        return 0;
 }
 
+static void unix_sock_inherit_flags(const struct socket *old,
+                                   struct socket *new)
+{
+       if (test_bit(SOCK_PASSCRED, &old->flags))
+               set_bit(SOCK_PASSCRED, &new->flags);
+       if (test_bit(SOCK_PASSSEC, &old->flags))
+               set_bit(SOCK_PASSSEC, &new->flags);
+}
+
 static int unix_accept(struct socket *sock, struct socket *newsock, int flags)
 {
        struct sock *sk = sock->sk;
@@ -1279,6 +1295,7 @@ static int unix_accept(struct socket *sock, struct socket *newsock, int flags)
        /* attach accepted sock to socket */
        unix_state_lock(tsk);
        newsock->state = SS_CONNECTED;
+       unix_sock_inherit_flags(sock, newsock);
        sock_graft(tsk, newsock);
        unix_state_unlock(tsk);
        return 0;
@@ -1751,7 +1768,6 @@ static void unix_copy_addr(struct msghdr *msg, struct sock *sk)
 {
        struct unix_sock *u = unix_sk(sk);
 
-       msg->msg_namelen = 0;
        if (u->addr) {
                msg->msg_namelen = u->addr->len;
                memcpy(msg->msg_name, u->addr->name, u->addr->len);
@@ -1775,11 +1791,12 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
        if (flags&MSG_OOB)
                goto out;
 
-       msg->msg_namelen = 0;
-
        err = mutex_lock_interruptible(&u->readlock);
-       if (err) {
-               err = sock_intr_errno(sock_rcvtimeo(sk, noblock));
+       if (unlikely(err)) {
+               /* recvmsg() in non blocking mode is supposed to return -EAGAIN
+                * sk_rcvtimeo is not honored by mutex_lock_interruptible()
+                */
+               err = noblock ? -EAGAIN : -ERESTARTSYS;
                goto out;
        }
 
@@ -1899,6 +1916,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
        struct unix_sock *u = unix_sk(sk);
        struct sockaddr_un *sunaddr = msg->msg_name;
        int copied = 0;
+       int noblock = flags & MSG_DONTWAIT;
        int check_creds = 0;
        int target;
        int err = 0;
@@ -1914,9 +1932,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
                goto out;
 
        target = sock_rcvlowat(sk, flags&MSG_WAITALL, size);
-       timeo = sock_rcvtimeo(sk, flags&MSG_DONTWAIT);
-
-       msg->msg_namelen = 0;
+       timeo = sock_rcvtimeo(sk, noblock);
 
        /* Lock the socket to prevent queue disordering
         * while sleeps in memcpy_tomsg
@@ -1928,8 +1944,11 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
        }
 
        err = mutex_lock_interruptible(&u->readlock);
-       if (err) {
-               err = sock_intr_errno(timeo);
+       if (unlikely(err)) {
+               /* recvmsg() in non blocking mode is supposed to return -EAGAIN
+                * sk_rcvtimeo is not honored by mutex_lock_interruptible()
+                */
+               err = noblock ? -EAGAIN : -ERESTARTSYS;
                goto out;
        }