diff options
Diffstat (limited to 'net/socket.c')
| -rw-r--r-- | net/socket.c | 35 | 
1 files changed, 23 insertions, 12 deletions
diff --git a/net/socket.c b/net/socket.c index e6945e318f02..b68801c7d0ab 100644 --- a/net/socket.c +++ b/net/socket.c @@ -941,7 +941,8 @@ void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))  EXPORT_SYMBOL(dlci_ioctl_set);  static long sock_do_ioctl(struct net *net, struct socket *sock, -				 unsigned int cmd, unsigned long arg) +			  unsigned int cmd, unsigned long arg, +			  unsigned int ifreq_size)  {  	int err;  	void __user *argp = (void __user *)arg; @@ -967,11 +968,11 @@ static long sock_do_ioctl(struct net *net, struct socket *sock,  	} else {  		struct ifreq ifr;  		bool need_copyout; -		if (copy_from_user(&ifr, argp, sizeof(struct ifreq))) +		if (copy_from_user(&ifr, argp, ifreq_size))  			return -EFAULT;  		err = dev_ioctl(net, cmd, &ifr, &need_copyout);  		if (!err && need_copyout) -			if (copy_to_user(argp, &ifr, sizeof(struct ifreq))) +			if (copy_to_user(argp, &ifr, ifreq_size))  				return -EFAULT;  	}  	return err; @@ -1070,7 +1071,8 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)  			err = open_related_ns(&net->ns, get_net_ns);  			break;  		default: -			err = sock_do_ioctl(net, sock, cmd, arg); +			err = sock_do_ioctl(net, sock, cmd, arg, +					    sizeof(struct ifreq));  			break;  		}  	return err; @@ -1473,7 +1475,7 @@ int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)  	sock = sockfd_lookup_light(fd, &err, &fput_needed);  	if (sock) {  		err = move_addr_to_kernel(umyaddr, addrlen, &address); -		if (err >= 0) { +		if (!err) {  			err = security_socket_bind(sock,  						   (struct sockaddr *)&address,  						   addrlen); @@ -2750,7 +2752,8 @@ static int do_siocgstamp(struct net *net, struct socket *sock,  	int err;  	set_fs(KERNEL_DS); -	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv); +	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv, +			    sizeof(struct compat_ifreq));  	set_fs(old_fs);  	if (!err)  		err = compat_put_timeval(&ktv, up); @@ -2766,7 +2769,8 @@ static int do_siocgstampns(struct net *net, struct socket *sock,  	int err;  	set_fs(KERNEL_DS); -	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts); +	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts, +			    sizeof(struct compat_ifreq));  	set_fs(old_fs);  	if (!err)  		err = compat_put_timespec(&kts, up); @@ -2871,9 +2875,14 @@ static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)  		    copy_in_user(&rxnfc->fs.ring_cookie,  				 &compat_rxnfc->fs.ring_cookie,  				 (void __user *)(&rxnfc->fs.location + 1) - -				 (void __user *)&rxnfc->fs.ring_cookie) || -		    copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt, -				 sizeof(rxnfc->rule_cnt))) +				 (void __user *)&rxnfc->fs.ring_cookie)) +			return -EFAULT; +		if (ethcmd == ETHTOOL_GRXCLSRLALL) { +			if (put_user(rule_cnt, &rxnfc->rule_cnt)) +				return -EFAULT; +		} else if (copy_in_user(&rxnfc->rule_cnt, +					&compat_rxnfc->rule_cnt, +					sizeof(rxnfc->rule_cnt)))  			return -EFAULT;  	} @@ -3072,7 +3081,8 @@ static int routing_ioctl(struct net *net, struct socket *sock,  	}  	set_fs(KERNEL_DS); -	ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r); +	ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r, +			    sizeof(struct compat_ifreq));  	set_fs(old_fs);  out: @@ -3185,7 +3195,8 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,  	case SIOCBONDSETHWADDR:  	case SIOCBONDCHANGEACTIVE:  	case SIOCGIFNAME: -		return sock_do_ioctl(net, sock, cmd, arg); +		return sock_do_ioctl(net, sock, cmd, arg, +				     sizeof(struct compat_ifreq));  	}  	return -ENOIOCTLCMD;  | 
