diff options
Diffstat (limited to 'net/unix/af_unix.c')
| -rw-r--r-- | net/unix/af_unix.c | 80 | 
1 files changed, 53 insertions, 27 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 86de99ad297..e9688438073 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -80,6 +80,8 @@   *		  with BSD names.   */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +  #include <linux/module.h>  #include <linux/kernel.h>  #include <linux/signal.h> @@ -161,9 +163,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);  } @@ -366,7 +367,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_INFO "Attempt to release alive unix socket: %p\n", sk); +		pr_info("Attempt to release alive unix socket: %p\n", sk);  		return;  	} @@ -378,7 +379,7 @@ static void unix_sock_destructor(struct sock *sk)  	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, %ld are still alive.\n", sk, +	pr_debug("UNIX %p is destroyed, %ld are still alive.\n", sk,  		atomic_long_read(&unix_nr_socks));  #endif  } @@ -530,13 +531,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;  } @@ -714,7 +719,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) @@ -873,7 +880,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) @@ -1198,7 +1207,7 @@ restart:  	sk->sk_state	= TCP_ESTABLISHED;  	sock_hold(newsk); -	smp_mb__after_atomic_inc();	/* sock_hold() does an atomic_inc() */ +	smp_mb__after_atomic();	/* sock_hold() does an atomic_inc() */  	unix_peer(sk)	= newsk;  	unix_state_unlock(sk); @@ -1208,7 +1217,7 @@ restart:  	__skb_queue_tail(&other->sk_receive_queue, skb);  	spin_unlock(&other->sk_receive_queue.lock);  	unix_state_unlock(other); -	other->sk_data_ready(other, 0); +	other->sk_data_ready(other);  	sock_put(other);  	return 0; @@ -1246,6 +1255,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; @@ -1280,6 +1298,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; @@ -1430,7 +1449,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,  	struct sock *sk = sock->sk;  	struct net *net = sock_net(sk);  	struct unix_sock *u = unix_sk(sk); -	struct sockaddr_un *sunaddr = msg->msg_name; +	DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, msg->msg_name);  	struct sock *other = NULL;  	int namelen = 0; /* fake GCC */  	int err; @@ -1473,10 +1492,14 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,  	if (len > sk->sk_sndbuf - 32)  		goto out; -	if (len > SKB_MAX_ALLOC) +	if (len > SKB_MAX_ALLOC) {  		data_len = min_t(size_t,  				 len - SKB_MAX_ALLOC,  				 MAX_SKB_FRAGS * PAGE_SIZE); +		data_len = PAGE_ALIGN(data_len); + +		BUILD_BUG_ON(SKB_MAX_ALLOC < PAGE_SIZE); +	}  	skb = sock_alloc_send_pskb(sk, len - data_len, data_len,  				   msg->msg_flags & MSG_DONTWAIT, &err, @@ -1581,7 +1604,7 @@ restart:  	if (max_level > unix_sk(other)->recursion_level)  		unix_sk(other)->recursion_level = max_level;  	unix_state_unlock(other); -	other->sk_data_ready(other, len); +	other->sk_data_ready(other);  	sock_put(other);  	scm_destroy(siocb->scm);  	return len; @@ -1651,6 +1674,8 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,  		data_len = max_t(int, 0, size - SKB_MAX_HEAD(0)); +		data_len = min_t(size_t, size, PAGE_ALIGN(data_len)); +  		skb = sock_alloc_send_pskb(sk, size - data_len, data_len,  					   msg->msg_flags & MSG_DONTWAIT, &err,  					   get_order(UNIX_SKB_FRAGS_SZ)); @@ -1687,7 +1712,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,  		if (max_level > unix_sk(other)->recursion_level)  			unix_sk(other)->recursion_level = max_level;  		unix_state_unlock(other); -		other->sk_data_ready(other, size); +		other->sk_data_ready(other);  		sent += size;  	} @@ -1744,7 +1769,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); @@ -1768,11 +1792,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;  	} @@ -1895,8 +1920,9 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,  	struct scm_cookie tmp_scm;  	struct sock *sk = sock->sk;  	struct unix_sock *u = unix_sk(sk); -	struct sockaddr_un *sunaddr = msg->msg_name; +	DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, msg->msg_name);  	int copied = 0; +	int noblock = flags & MSG_DONTWAIT;  	int check_creds = 0;  	int target;  	int err = 0; @@ -1912,9 +1938,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 @@ -1926,8 +1950,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;  	} @@ -2428,8 +2455,7 @@ static int __init af_unix_init(void)  	rc = proto_register(&unix_proto, 1);  	if (rc != 0) { -		printk(KERN_CRIT "%s: Cannot create unix_sock SLAB cache!\n", -		       __func__); +		pr_crit("%s: Cannot create unix_sock SLAB cache!\n", __func__);  		goto out;  	}  | 
