diff options
Diffstat (limited to 'net/unix/af_unix.c')
| -rw-r--r-- | net/unix/af_unix.c | 36 | 
1 files changed, 23 insertions, 13 deletions
| diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index d510353ef431..641f2e47f165 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -149,9 +149,10 @@ static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)   *    each socket state is protected by separate spin lock.   */ -static inline unsigned unix_hash_fold(__wsum n) +static inline unsigned int unix_hash_fold(__wsum n)  { -	unsigned hash = (__force unsigned)n; +	unsigned int hash = (__force unsigned int)n; +  	hash ^= hash>>16;  	hash ^= hash>>8;  	return hash&(UNIX_HASH_SIZE-1); @@ -200,7 +201,7 @@ static inline void unix_release_addr(struct unix_address *addr)   *		- if started by zero, it is abstract name.   */ -static int unix_mkname(struct sockaddr_un *sunaddr, int len, unsigned *hashp) +static int unix_mkname(struct sockaddr_un *sunaddr, int len, unsigned int *hashp)  {  	if (len <= sizeof(short) || len > sizeof(*sunaddr))  		return -EINVAL; @@ -250,7 +251,7 @@ static inline void unix_insert_socket(struct hlist_head *list, struct sock *sk)  static struct sock *__unix_find_socket_byname(struct net *net,  					      struct sockaddr_un *sunname, -					      int len, int type, unsigned hash) +					      int len, int type, unsigned int hash)  {  	struct sock *s;  	struct hlist_node *node; @@ -273,7 +274,7 @@ found:  static inline struct sock *unix_find_socket_byname(struct net *net,  						   struct sockaddr_un *sunname,  						   int len, int type, -						   unsigned hash) +						   unsigned int hash)  {  	struct sock *s; @@ -760,7 +761,7 @@ out:	mutex_unlock(&u->readlock);  static struct sock *unix_find_other(struct net *net,  				    struct sockaddr_un *sunname, int len, -				    int type, unsigned hash, int *error) +				    int type, unsigned int hash, int *error)  {  	struct sock *u;  	struct path path; @@ -824,7 +825,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)  	struct dentry *dentry = NULL;  	struct path path;  	int err; -	unsigned hash; +	unsigned int hash;  	struct unix_address *addr;  	struct hlist_head *list; @@ -964,7 +965,7 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,  	struct net *net = sock_net(sk);  	struct sockaddr_un *sunaddr = (struct sockaddr_un *)addr;  	struct sock *other; -	unsigned hash; +	unsigned int hash;  	int err;  	if (addr->sa_family != AF_UNSPEC) { @@ -1062,7 +1063,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,  	struct sock *newsk = NULL;  	struct sock *other = NULL;  	struct sk_buff *skb = NULL; -	unsigned hash; +	unsigned int hash;  	int st;  	int err;  	long timeo; @@ -1437,11 +1438,12 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,  	struct sock *other = NULL;  	int namelen = 0; /* fake GCC */  	int err; -	unsigned hash; +	unsigned int hash;  	struct sk_buff *skb;  	long timeo;  	struct scm_cookie tmp_scm;  	int max_level; +	int data_len = 0;  	if (NULL == siocb->scm)  		siocb->scm = &tmp_scm; @@ -1475,7 +1477,13 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,  	if (len > sk->sk_sndbuf - 32)  		goto out; -	skb = sock_alloc_send_skb(sk, len, msg->msg_flags&MSG_DONTWAIT, &err); +	if (len > SKB_MAX_ALLOC) +		data_len = min_t(size_t, +				 len - SKB_MAX_ALLOC, +				 MAX_SKB_FRAGS * PAGE_SIZE); + +	skb = sock_alloc_send_pskb(sk, len - data_len, data_len, +				   msg->msg_flags & MSG_DONTWAIT, &err);  	if (skb == NULL)  		goto out; @@ -1485,8 +1493,10 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,  	max_level = err + 1;  	unix_get_secdata(siocb->scm, skb); -	skb_reset_transport_header(skb); -	err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); +	skb_put(skb, len - data_len); +	skb->data_len = data_len; +	skb->len = len; +	err = skb_copy_datagram_from_iovec(skb, 0, msg->msg_iov, 0, len);  	if (err)  		goto out_free; | 
