diff options
Diffstat (limited to 'net/socket.c')
| -rw-r--r-- | net/socket.c | 82 | 
1 files changed, 46 insertions, 36 deletions
diff --git a/net/socket.c b/net/socket.c index 81fe8251304..1ba57d88898 100644 --- a/net/socket.c +++ b/net/socket.c @@ -180,9 +180,9 @@ static DEFINE_PER_CPU(int, sockets_in_use) = 0;   *	invalid addresses -EFAULT is returned. On a success 0 is returned.   */ -int move_addr_to_kernel(void __user *uaddr, int ulen, void *kaddr) +int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr *kaddr)  { -	if (ulen < 0 || ulen > MAX_SOCK_ADDR) +	if (ulen < 0 || ulen > sizeof(struct sockaddr_storage))  		return -EINVAL;  	if (ulen == 0)  		return 0; @@ -208,7 +208,7 @@ int move_addr_to_kernel(void __user *uaddr, int ulen, void *kaddr)   *	specified. Zero is returned for a success.   */ -int move_addr_to_user(void *kaddr, int klen, void __user *uaddr, +int move_addr_to_user(struct sockaddr *kaddr, int klen, void __user *uaddr,  		      int __user *ulen)  {  	int err; @@ -219,7 +219,7 @@ int move_addr_to_user(void *kaddr, int klen, void __user *uaddr,  		return err;  	if (len > klen)  		len = klen; -	if (len < 0 || len > MAX_SOCK_ADDR) +	if (len < 0 || len > sizeof(struct sockaddr_storage))  		return -EINVAL;  	if (len) {  		if (audit_sockaddr(klen, kaddr)) @@ -1342,20 +1342,20 @@ out_fd:  asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)  {  	struct socket *sock; -	char address[MAX_SOCK_ADDR]; +	struct sockaddr_storage address;  	int err, fput_needed;  	sock = sockfd_lookup_light(fd, &err, &fput_needed);  	if (sock) { -		err = move_addr_to_kernel(umyaddr, addrlen, address); +		err = move_addr_to_kernel(umyaddr, addrlen, (struct sockaddr *)&address);  		if (err >= 0) {  			err = security_socket_bind(sock, -						   (struct sockaddr *)address, +						   (struct sockaddr *)&address,  						   addrlen);  			if (!err)  				err = sock->ops->bind(sock,  						      (struct sockaddr *) -						      address, addrlen); +						      &address, addrlen);  		}  		fput_light(sock->file, fput_needed);  	} @@ -1407,7 +1407,7 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,  	struct socket *sock, *newsock;  	struct file *newfile;  	int err, len, newfd, fput_needed; -	char address[MAX_SOCK_ADDR]; +	struct sockaddr_storage address;  	sock = sockfd_lookup_light(fd, &err, &fput_needed);  	if (!sock) @@ -1446,13 +1446,13 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,  		goto out_fd;  	if (upeer_sockaddr) { -		if (newsock->ops->getname(newsock, (struct sockaddr *)address, +		if (newsock->ops->getname(newsock, (struct sockaddr *)&address,  					  &len, 2) < 0) {  			err = -ECONNABORTED;  			goto out_fd;  		} -		err = move_addr_to_user(address, len, upeer_sockaddr, -					upeer_addrlen); +		err = move_addr_to_user((struct sockaddr *)&address, +					len, upeer_sockaddr, upeer_addrlen);  		if (err < 0)  			goto out_fd;  	} @@ -1495,22 +1495,22 @@ asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr,  			    int addrlen)  {  	struct socket *sock; -	char address[MAX_SOCK_ADDR]; +	struct sockaddr_storage address;  	int err, fput_needed;  	sock = sockfd_lookup_light(fd, &err, &fput_needed);  	if (!sock)  		goto out; -	err = move_addr_to_kernel(uservaddr, addrlen, address); +	err = move_addr_to_kernel(uservaddr, addrlen, (struct sockaddr *)&address);  	if (err < 0)  		goto out_put;  	err = -	    security_socket_connect(sock, (struct sockaddr *)address, addrlen); +	    security_socket_connect(sock, (struct sockaddr *)&address, addrlen);  	if (err)  		goto out_put; -	err = sock->ops->connect(sock, (struct sockaddr *)address, addrlen, +	err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,  				 sock->file->f_flags);  out_put:  	fput_light(sock->file, fput_needed); @@ -1527,7 +1527,7 @@ asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr,  				int __user *usockaddr_len)  {  	struct socket *sock; -	char address[MAX_SOCK_ADDR]; +	struct sockaddr_storage address;  	int len, err, fput_needed;  	sock = sockfd_lookup_light(fd, &err, &fput_needed); @@ -1538,10 +1538,10 @@ asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr,  	if (err)  		goto out_put; -	err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 0); +	err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0);  	if (err)  		goto out_put; -	err = move_addr_to_user(address, len, usockaddr, usockaddr_len); +	err = move_addr_to_user((struct sockaddr *)&address, len, usockaddr, usockaddr_len);  out_put:  	fput_light(sock->file, fput_needed); @@ -1558,7 +1558,7 @@ asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr,  				int __user *usockaddr_len)  {  	struct socket *sock; -	char address[MAX_SOCK_ADDR]; +	struct sockaddr_storage address;  	int len, err, fput_needed;  	sock = sockfd_lookup_light(fd, &err, &fput_needed); @@ -1570,10 +1570,10 @@ asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr,  		}  		err = -		    sock->ops->getname(sock, (struct sockaddr *)address, &len, +		    sock->ops->getname(sock, (struct sockaddr *)&address, &len,  				       1);  		if (!err) -			err = move_addr_to_user(address, len, usockaddr, +			err = move_addr_to_user((struct sockaddr *)&address, len, usockaddr,  						usockaddr_len);  		fput_light(sock->file, fput_needed);  	} @@ -1591,7 +1591,7 @@ asmlinkage long sys_sendto(int fd, void __user *buff, size_t len,  			   int addr_len)  {  	struct socket *sock; -	char address[MAX_SOCK_ADDR]; +	struct sockaddr_storage address;  	int err;  	struct msghdr msg;  	struct iovec iov; @@ -1610,10 +1610,10 @@ asmlinkage long sys_sendto(int fd, void __user *buff, size_t len,  	msg.msg_controllen = 0;  	msg.msg_namelen = 0;  	if (addr) { -		err = move_addr_to_kernel(addr, addr_len, address); +		err = move_addr_to_kernel(addr, addr_len, (struct sockaddr *)&address);  		if (err < 0)  			goto out_put; -		msg.msg_name = address; +		msg.msg_name = (struct sockaddr *)&address;  		msg.msg_namelen = addr_len;  	}  	if (sock->file->f_flags & O_NONBLOCK) @@ -1649,7 +1649,7 @@ asmlinkage long sys_recvfrom(int fd, void __user *ubuf, size_t size,  	struct socket *sock;  	struct iovec iov;  	struct msghdr msg; -	char address[MAX_SOCK_ADDR]; +	struct sockaddr_storage address;  	int err, err2;  	int fput_needed; @@ -1663,14 +1663,15 @@ asmlinkage long sys_recvfrom(int fd, void __user *ubuf, size_t size,  	msg.msg_iov = &iov;  	iov.iov_len = size;  	iov.iov_base = ubuf; -	msg.msg_name = address; -	msg.msg_namelen = MAX_SOCK_ADDR; +	msg.msg_name = (struct sockaddr *)&address; +	msg.msg_namelen = sizeof(address);  	if (sock->file->f_flags & O_NONBLOCK)  		flags |= MSG_DONTWAIT;  	err = sock_recvmsg(sock, &msg, size, flags);  	if (err >= 0 && addr != NULL) { -		err2 = move_addr_to_user(address, msg.msg_namelen, addr, addr_len); +		err2 = move_addr_to_user((struct sockaddr *)&address, +					 msg.msg_namelen, addr, addr_len);  		if (err2 < 0)  			err = err2;  	} @@ -1790,7 +1791,7 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)  	struct compat_msghdr __user *msg_compat =  	    (struct compat_msghdr __user *)msg;  	struct socket *sock; -	char address[MAX_SOCK_ADDR]; +	struct sockaddr_storage address;  	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;  	unsigned char ctl[sizeof(struct cmsghdr) + 20]  	    __attribute__ ((aligned(sizeof(__kernel_size_t)))); @@ -1828,9 +1829,13 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)  	/* This will also move the address data into kernel space */  	if (MSG_CMSG_COMPAT & flags) { -		err = verify_compat_iovec(&msg_sys, iov, address, VERIFY_READ); +		err = verify_compat_iovec(&msg_sys, iov, +					  (struct sockaddr *)&address, +					  VERIFY_READ);  	} else -		err = verify_iovec(&msg_sys, iov, address, VERIFY_READ); +		err = verify_iovec(&msg_sys, iov, +				   (struct sockaddr *)&address, +				   VERIFY_READ);  	if (err < 0)  		goto out_freeiov;  	total_len = err; @@ -1901,7 +1906,7 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg,  	int fput_needed;  	/* kernel mode address */ -	char addr[MAX_SOCK_ADDR]; +	struct sockaddr_storage addr;  	/* user mode address pointers */  	struct sockaddr __user *uaddr; @@ -1939,9 +1944,13 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg,  	uaddr = (__force void __user *)msg_sys.msg_name;  	uaddr_len = COMPAT_NAMELEN(msg);  	if (MSG_CMSG_COMPAT & flags) { -		err = verify_compat_iovec(&msg_sys, iov, addr, VERIFY_WRITE); +		err = verify_compat_iovec(&msg_sys, iov, +					  (struct sockaddr *)&addr, +					  VERIFY_WRITE);  	} else -		err = verify_iovec(&msg_sys, iov, addr, VERIFY_WRITE); +		err = verify_iovec(&msg_sys, iov, +				   (struct sockaddr *)&addr, +				   VERIFY_WRITE);  	if (err < 0)  		goto out_freeiov;  	total_len = err; @@ -1957,7 +1966,8 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg,  	len = err;  	if (uaddr != NULL) { -		err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, +		err = move_addr_to_user((struct sockaddr *)&addr, +					msg_sys.msg_namelen, uaddr,  					uaddr_len);  		if (err < 0)  			goto out_freeiov;  |