net: pass a sockptr_t into ->setsockopt
Rework the remaining setsockopt code to pass a sockptr_t instead of a plain user pointer. This removes the last remaining set_fs(KERNEL_DS) outside of architecture specific code. Signed-off-by: Christoph Hellwig <hch@lst.de> Acked-by: Stefan Schmidt <stefan@datenfreihafen.org> [ieee802154] Acked-by: Matthieu Baerts <matthieu.baerts@tessares.net> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									d38d2b00ba
								
							
						
					
					
						commit
						a7b75c5a8c
					
				| @ -197,8 +197,7 @@ unlock: | |||||||
| 	return err; | 	return err; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int alg_setkey(struct sock *sk, char __user *ukey, | static int alg_setkey(struct sock *sk, sockptr_t ukey, unsigned int keylen) | ||||||
| 		      unsigned int keylen) |  | ||||||
| { | { | ||||||
| 	struct alg_sock *ask = alg_sk(sk); | 	struct alg_sock *ask = alg_sk(sk); | ||||||
| 	const struct af_alg_type *type = ask->type; | 	const struct af_alg_type *type = ask->type; | ||||||
| @ -210,7 +209,7 @@ static int alg_setkey(struct sock *sk, char __user *ukey, | |||||||
| 		return -ENOMEM; | 		return -ENOMEM; | ||||||
| 
 | 
 | ||||||
| 	err = -EFAULT; | 	err = -EFAULT; | ||||||
| 	if (copy_from_user(key, ukey, keylen)) | 	if (copy_from_sockptr(key, ukey, keylen)) | ||||||
| 		goto out; | 		goto out; | ||||||
| 
 | 
 | ||||||
| 	err = type->setkey(ask->private, key, keylen); | 	err = type->setkey(ask->private, key, keylen); | ||||||
| @ -222,7 +221,7 @@ out: | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int alg_setsockopt(struct socket *sock, int level, int optname, | static int alg_setsockopt(struct socket *sock, int level, int optname, | ||||||
| 			  char __user *optval, unsigned int optlen) | 			  sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| 	struct alg_sock *ask = alg_sk(sk); | 	struct alg_sock *ask = alg_sk(sk); | ||||||
|  | |||||||
| @ -488,7 +488,7 @@ static int chtls_getsockopt(struct sock *sk, int level, int optname, | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int do_chtls_setsockopt(struct sock *sk, int optname, | static int do_chtls_setsockopt(struct sock *sk, int optname, | ||||||
| 			       char __user *optval, unsigned int optlen) | 			       sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct tls_crypto_info *crypto_info, tmp_crypto_info; | 	struct tls_crypto_info *crypto_info, tmp_crypto_info; | ||||||
| 	struct chtls_sock *csk; | 	struct chtls_sock *csk; | ||||||
| @ -498,12 +498,12 @@ static int do_chtls_setsockopt(struct sock *sk, int optname, | |||||||
| 
 | 
 | ||||||
| 	csk = rcu_dereference_sk_user_data(sk); | 	csk = rcu_dereference_sk_user_data(sk); | ||||||
| 
 | 
 | ||||||
| 	if (!optval || optlen < sizeof(*crypto_info)) { | 	if (sockptr_is_null(optval) || optlen < sizeof(*crypto_info)) { | ||||||
| 		rc = -EINVAL; | 		rc = -EINVAL; | ||||||
| 		goto out; | 		goto out; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	rc = copy_from_user(&tmp_crypto_info, optval, sizeof(*crypto_info)); | 	rc = copy_from_sockptr(&tmp_crypto_info, optval, sizeof(*crypto_info)); | ||||||
| 	if (rc) { | 	if (rc) { | ||||||
| 		rc = -EFAULT; | 		rc = -EFAULT; | ||||||
| 		goto out; | 		goto out; | ||||||
| @ -525,8 +525,9 @@ static int do_chtls_setsockopt(struct sock *sk, int optname, | |||||||
| 		/* Obtain version and type from previous copy */ | 		/* Obtain version and type from previous copy */ | ||||||
| 		crypto_info[0] = tmp_crypto_info; | 		crypto_info[0] = tmp_crypto_info; | ||||||
| 		/* Now copy the following data */ | 		/* Now copy the following data */ | ||||||
| 		rc = copy_from_user((char *)crypto_info + sizeof(*crypto_info), | 		sockptr_advance(optval, sizeof(*crypto_info)); | ||||||
| 				optval + sizeof(*crypto_info), | 		rc = copy_from_sockptr((char *)crypto_info + sizeof(*crypto_info), | ||||||
|  | 				optval, | ||||||
| 				sizeof(struct tls12_crypto_info_aes_gcm_128) | 				sizeof(struct tls12_crypto_info_aes_gcm_128) | ||||||
| 				- sizeof(*crypto_info)); | 				- sizeof(*crypto_info)); | ||||||
| 
 | 
 | ||||||
| @ -541,8 +542,9 @@ static int do_chtls_setsockopt(struct sock *sk, int optname, | |||||||
| 	} | 	} | ||||||
| 	case TLS_CIPHER_AES_GCM_256: { | 	case TLS_CIPHER_AES_GCM_256: { | ||||||
| 		crypto_info[0] = tmp_crypto_info; | 		crypto_info[0] = tmp_crypto_info; | ||||||
| 		rc = copy_from_user((char *)crypto_info + sizeof(*crypto_info), | 		sockptr_advance(optval, sizeof(*crypto_info)); | ||||||
| 				    optval + sizeof(*crypto_info), | 		rc = copy_from_sockptr((char *)crypto_info + sizeof(*crypto_info), | ||||||
|  | 				    optval, | ||||||
| 				sizeof(struct tls12_crypto_info_aes_gcm_256) | 				sizeof(struct tls12_crypto_info_aes_gcm_256) | ||||||
| 				- sizeof(*crypto_info)); | 				- sizeof(*crypto_info)); | ||||||
| 
 | 
 | ||||||
| @ -565,7 +567,7 @@ out: | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int chtls_setsockopt(struct sock *sk, int level, int optname, | static int chtls_setsockopt(struct sock *sk, int level, int optname, | ||||||
| 			    char __user *optval, unsigned int optlen) | 			    sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct tls_context *ctx = tls_get_ctx(sk); | 	struct tls_context *ctx = tls_get_ctx(sk); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -401,7 +401,7 @@ data_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int data_sock_setsockopt(struct socket *sock, int level, int optname, | static int data_sock_setsockopt(struct socket *sock, int level, int optname, | ||||||
| 				char __user *optval, unsigned int len) | 				sockptr_t optval, unsigned int len) | ||||||
| { | { | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| 	int err = 0, opt = 0; | 	int err = 0, opt = 0; | ||||||
| @ -414,7 +414,7 @@ static int data_sock_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 
 | 
 | ||||||
| 	switch (optname) { | 	switch (optname) { | ||||||
| 	case MISDN_TIME_STAMP: | 	case MISDN_TIME_STAMP: | ||||||
| 		if (get_user(opt, (int __user *)optval)) { | 		if (copy_from_sockptr(&opt, optval, sizeof(int))) { | ||||||
| 			err = -EFAULT; | 			err = -EFAULT; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -21,6 +21,7 @@ | |||||||
| #include <linux/rcupdate.h> | #include <linux/rcupdate.h> | ||||||
| #include <linux/once.h> | #include <linux/once.h> | ||||||
| #include <linux/fs.h> | #include <linux/fs.h> | ||||||
|  | #include <linux/sockptr.h> | ||||||
| 
 | 
 | ||||||
| #include <uapi/linux/net.h> | #include <uapi/linux/net.h> | ||||||
| 
 | 
 | ||||||
| @ -162,7 +163,8 @@ struct proto_ops { | |||||||
| 	int		(*listen)    (struct socket *sock, int len); | 	int		(*listen)    (struct socket *sock, int len); | ||||||
| 	int		(*shutdown)  (struct socket *sock, int flags); | 	int		(*shutdown)  (struct socket *sock, int flags); | ||||||
| 	int		(*setsockopt)(struct socket *sock, int level, | 	int		(*setsockopt)(struct socket *sock, int level, | ||||||
| 				      int optname, char __user *optval, unsigned int optlen); | 				      int optname, sockptr_t optval, | ||||||
|  | 				      unsigned int optlen); | ||||||
| 	int		(*getsockopt)(struct socket *sock, int level, | 	int		(*getsockopt)(struct socket *sock, int level, | ||||||
| 				      int optname, char __user *optval, int __user *optlen); | 				      int optname, char __user *optval, int __user *optlen); | ||||||
| 	void		(*show_fdinfo)(struct seq_file *m, struct socket *sock); | 	void		(*show_fdinfo)(struct seq_file *m, struct socket *sock); | ||||||
|  | |||||||
| @ -16,6 +16,7 @@ | |||||||
| #include <linux/timer.h> | #include <linux/timer.h> | ||||||
| #include <linux/poll.h> | #include <linux/poll.h> | ||||||
| #include <linux/kernel.h> | #include <linux/kernel.h> | ||||||
|  | #include <linux/sockptr.h> | ||||||
| 
 | 
 | ||||||
| #include <net/inet_sock.h> | #include <net/inet_sock.h> | ||||||
| #include <net/request_sock.h> | #include <net/request_sock.h> | ||||||
| @ -45,7 +46,7 @@ struct inet_connection_sock_af_ops { | |||||||
| 	u16	    net_frag_header_len; | 	u16	    net_frag_header_len; | ||||||
| 	u16	    sockaddr_len; | 	u16	    sockaddr_len; | ||||||
| 	int	    (*setsockopt)(struct sock *sk, int level, int optname, | 	int	    (*setsockopt)(struct sock *sk, int level, int optname, | ||||||
| 				  char __user *optval, unsigned int optlen); | 				  sockptr_t optval, unsigned int optlen); | ||||||
| 	int	    (*getsockopt)(struct sock *sk, int level, int optname, | 	int	    (*getsockopt)(struct sock *sk, int level, int optname, | ||||||
| 				  char __user *optval, int __user *optlen); | 				  char __user *optval, int __user *optlen); | ||||||
| 	void	    (*addr2sockaddr)(struct sock *sk, struct sockaddr *); | 	void	    (*addr2sockaddr)(struct sock *sk, struct sockaddr *); | ||||||
|  | |||||||
| @ -722,7 +722,7 @@ void ip_cmsg_recv_offset(struct msghdr *msg, struct sock *sk, | |||||||
| 			 struct sk_buff *skb, int tlen, int offset); | 			 struct sk_buff *skb, int tlen, int offset); | ||||||
| int ip_cmsg_send(struct sock *sk, struct msghdr *msg, | int ip_cmsg_send(struct sock *sk, struct msghdr *msg, | ||||||
| 		 struct ipcm_cookie *ipc, bool allow_ipv6); | 		 struct ipcm_cookie *ipc, bool allow_ipv6); | ||||||
| int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, | int ip_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval, | ||||||
| 		  unsigned int optlen); | 		  unsigned int optlen); | ||||||
| int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, | int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval, | ||||||
| 		  int __user *optlen); | 		  int __user *optlen); | ||||||
|  | |||||||
| @ -1084,8 +1084,8 @@ struct in6_addr *fl6_update_dst(struct flowi6 *fl6, | |||||||
|  *	socket options (ipv6_sockglue.c) |  *	socket options (ipv6_sockglue.c) | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| int ipv6_setsockopt(struct sock *sk, int level, int optname, | int ipv6_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval, | ||||||
| 		    char __user *optval, unsigned int optlen); | 		    unsigned int optlen); | ||||||
| int ipv6_getsockopt(struct sock *sk, int level, int optname, | int ipv6_getsockopt(struct sock *sk, int level, int optname, | ||||||
| 		    char __user *optval, int __user *optlen); | 		    char __user *optval, int __user *optlen); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -431,7 +431,7 @@ struct sctp_af { | |||||||
| 	int		(*setsockopt)	(struct sock *sk, | 	int		(*setsockopt)	(struct sock *sk, | ||||||
| 					 int level, | 					 int level, | ||||||
| 					 int optname, | 					 int optname, | ||||||
| 					 char __user *optval, | 					 sockptr_t optval, | ||||||
| 					 unsigned int optlen); | 					 unsigned int optlen); | ||||||
| 	int		(*getsockopt)	(struct sock *sk, | 	int		(*getsockopt)	(struct sock *sk, | ||||||
| 					 int level, | 					 int level, | ||||||
|  | |||||||
| @ -1141,7 +1141,7 @@ struct proto { | |||||||
| 	void			(*destroy)(struct sock *sk); | 	void			(*destroy)(struct sock *sk); | ||||||
| 	void			(*shutdown)(struct sock *sk, int how); | 	void			(*shutdown)(struct sock *sk, int how); | ||||||
| 	int			(*setsockopt)(struct sock *sk, int level, | 	int			(*setsockopt)(struct sock *sk, int level, | ||||||
| 					int optname, char __user *optval, | 					int optname, sockptr_t optval, | ||||||
| 					unsigned int optlen); | 					unsigned int optlen); | ||||||
| 	int			(*getsockopt)(struct sock *sk, int level, | 	int			(*getsockopt)(struct sock *sk, int level, | ||||||
| 					int optname, char __user *optval, | 					int optname, char __user *optval, | ||||||
| @ -1734,7 +1734,7 @@ int sock_common_getsockopt(struct socket *sock, int level, int optname, | |||||||
| int sock_common_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, | int sock_common_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, | ||||||
| 			int flags); | 			int flags); | ||||||
| int sock_common_setsockopt(struct socket *sock, int level, int optname, | int sock_common_setsockopt(struct socket *sock, int level, int optname, | ||||||
| 				  char __user *optval, unsigned int optlen); | 			   sockptr_t optval, unsigned int optlen); | ||||||
| 
 | 
 | ||||||
| void sk_common_release(struct sock *sk); | void sk_common_release(struct sock *sk); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -399,8 +399,8 @@ __poll_t tcp_poll(struct file *file, struct socket *sock, | |||||||
| 		      struct poll_table_struct *wait); | 		      struct poll_table_struct *wait); | ||||||
| int tcp_getsockopt(struct sock *sk, int level, int optname, | int tcp_getsockopt(struct sock *sk, int level, int optname, | ||||||
| 		   char __user *optval, int __user *optlen); | 		   char __user *optval, int __user *optlen); | ||||||
| int tcp_setsockopt(struct sock *sk, int level, int optname, | int tcp_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval, | ||||||
| 		   char __user *optval, unsigned int optlen); | 		   unsigned int optlen); | ||||||
| void tcp_set_keepalive(struct sock *sk, int val); | void tcp_set_keepalive(struct sock *sk, int val); | ||||||
| void tcp_syn_ack_timeout(const struct request_sock *req); | void tcp_syn_ack_timeout(const struct request_sock *req); | ||||||
| int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock, | int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock, | ||||||
|  | |||||||
| @ -745,7 +745,7 @@ static int check_qos(const struct atm_qos *qos) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int vcc_setsockopt(struct socket *sock, int level, int optname, | int vcc_setsockopt(struct socket *sock, int level, int optname, | ||||||
| 		   char __user *optval, unsigned int optlen) | 		   sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct atm_vcc *vcc; | 	struct atm_vcc *vcc; | ||||||
| 	unsigned long value; | 	unsigned long value; | ||||||
| @ -760,7 +760,7 @@ int vcc_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 	{ | 	{ | ||||||
| 		struct atm_qos qos; | 		struct atm_qos qos; | ||||||
| 
 | 
 | ||||||
| 		if (copy_from_user(&qos, optval, sizeof(qos))) | 		if (copy_from_sockptr(&qos, optval, sizeof(qos))) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| 		error = check_qos(&qos); | 		error = check_qos(&qos); | ||||||
| 		if (error) | 		if (error) | ||||||
| @ -774,7 +774,7 @@ int vcc_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 		return 0; | 		return 0; | ||||||
| 	} | 	} | ||||||
| 	case SO_SETCLP: | 	case SO_SETCLP: | ||||||
| 		if (get_user(value, (unsigned long __user *)optval)) | 		if (copy_from_sockptr(&value, optval, sizeof(value))) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| 		if (value) | 		if (value) | ||||||
| 			vcc->atm_options |= ATM_ATMOPT_CLP; | 			vcc->atm_options |= ATM_ATMOPT_CLP; | ||||||
|  | |||||||
| @ -21,7 +21,7 @@ __poll_t vcc_poll(struct file *file, struct socket *sock, poll_table *wait); | |||||||
| int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg); | int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg); | ||||||
| int vcc_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg); | int vcc_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg); | ||||||
| int vcc_setsockopt(struct socket *sock, int level, int optname, | int vcc_setsockopt(struct socket *sock, int level, int optname, | ||||||
| 		   char __user *optval, unsigned int optlen); | 		   sockptr_t optval, unsigned int optlen); | ||||||
| int vcc_getsockopt(struct socket *sock, int level, int optname, | int vcc_getsockopt(struct socket *sock, int level, int optname, | ||||||
| 		   char __user *optval, int __user *optlen); | 		   char __user *optval, int __user *optlen); | ||||||
| void vcc_process_recv_queue(struct atm_vcc *vcc); | void vcc_process_recv_queue(struct atm_vcc *vcc); | ||||||
|  | |||||||
| @ -63,7 +63,7 @@ static int pvc_connect(struct socket *sock, struct sockaddr *sockaddr, | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int pvc_setsockopt(struct socket *sock, int level, int optname, | static int pvc_setsockopt(struct socket *sock, int level, int optname, | ||||||
| 			  char __user *optval, unsigned int optlen) | 			  sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| 	int error; | 	int error; | ||||||
|  | |||||||
| @ -451,7 +451,7 @@ int svc_change_qos(struct atm_vcc *vcc, struct atm_qos *qos) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int svc_setsockopt(struct socket *sock, int level, int optname, | static int svc_setsockopt(struct socket *sock, int level, int optname, | ||||||
| 			  char __user *optval, unsigned int optlen) | 			  sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| 	struct atm_vcc *vcc = ATM_SD(sock); | 	struct atm_vcc *vcc = ATM_SD(sock); | ||||||
| @ -464,7 +464,7 @@ static int svc_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 			error = -EINVAL; | 			error = -EINVAL; | ||||||
| 			goto out; | 			goto out; | ||||||
| 		} | 		} | ||||||
| 		if (copy_from_user(&vcc->sap, optval, optlen)) { | 		if (copy_from_sockptr(&vcc->sap, optval, optlen)) { | ||||||
| 			error = -EFAULT; | 			error = -EFAULT; | ||||||
| 			goto out; | 			goto out; | ||||||
| 		} | 		} | ||||||
| @ -475,7 +475,7 @@ static int svc_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 			error = -EINVAL; | 			error = -EINVAL; | ||||||
| 			goto out; | 			goto out; | ||||||
| 		} | 		} | ||||||
| 		if (get_user(value, (int __user *)optval)) { | 		if (copy_from_sockptr(&value, optval, sizeof(int))) { | ||||||
| 			error = -EFAULT; | 			error = -EFAULT; | ||||||
| 			goto out; | 			goto out; | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -528,7 +528,7 @@ ax25_cb *ax25_create_cb(void) | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| static int ax25_setsockopt(struct socket *sock, int level, int optname, | static int ax25_setsockopt(struct socket *sock, int level, int optname, | ||||||
| 	char __user *optval, unsigned int optlen) | 		sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| 	ax25_cb *ax25; | 	ax25_cb *ax25; | ||||||
| @ -543,7 +543,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 	if (optlen < sizeof(unsigned int)) | 	if (optlen < sizeof(unsigned int)) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 
 | 
 | ||||||
| 	if (get_user(opt, (unsigned int __user *)optval)) | 	if (copy_from_sockptr(&opt, optval, sizeof(unsigned int))) | ||||||
| 		return -EFAULT; | 		return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 	lock_sock(sk); | 	lock_sock(sk); | ||||||
| @ -640,7 +640,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 
 | 
 | ||||||
| 		memset(devname, 0, sizeof(devname)); | 		memset(devname, 0, sizeof(devname)); | ||||||
| 
 | 
 | ||||||
| 		if (copy_from_user(devname, optval, optlen)) { | 		if (copy_from_sockptr(devname, optval, optlen)) { | ||||||
| 			res = -EFAULT; | 			res = -EFAULT; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -1842,7 +1842,7 @@ drop: | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int hci_sock_setsockopt(struct socket *sock, int level, int optname, | static int hci_sock_setsockopt(struct socket *sock, int level, int optname, | ||||||
| 			       char __user *optval, unsigned int len) | 			       sockptr_t optval, unsigned int len) | ||||||
| { | { | ||||||
| 	struct hci_ufilter uf = { .opcode = 0 }; | 	struct hci_ufilter uf = { .opcode = 0 }; | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| @ -1862,7 +1862,7 @@ static int hci_sock_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 
 | 
 | ||||||
| 	switch (optname) { | 	switch (optname) { | ||||||
| 	case HCI_DATA_DIR: | 	case HCI_DATA_DIR: | ||||||
| 		if (get_user(opt, (int __user *)optval)) { | 		if (copy_from_sockptr(&opt, optval, sizeof(opt))) { | ||||||
| 			err = -EFAULT; | 			err = -EFAULT; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| @ -1874,7 +1874,7 @@ static int hci_sock_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 		break; | 		break; | ||||||
| 
 | 
 | ||||||
| 	case HCI_TIME_STAMP: | 	case HCI_TIME_STAMP: | ||||||
| 		if (get_user(opt, (int __user *)optval)) { | 		if (copy_from_sockptr(&opt, optval, sizeof(opt))) { | ||||||
| 			err = -EFAULT; | 			err = -EFAULT; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| @ -1896,7 +1896,7 @@ static int hci_sock_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		len = min_t(unsigned int, len, sizeof(uf)); | 		len = min_t(unsigned int, len, sizeof(uf)); | ||||||
| 		if (copy_from_user(&uf, optval, len)) { | 		if (copy_from_sockptr(&uf, optval, len)) { | ||||||
| 			err = -EFAULT; | 			err = -EFAULT; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -703,7 +703,7 @@ static bool l2cap_valid_mtu(struct l2cap_chan *chan, u16 mtu) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, | static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, | ||||||
| 				     char __user *optval, unsigned int optlen) | 				     sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| 	struct l2cap_chan *chan = l2cap_pi(sk)->chan; | 	struct l2cap_chan *chan = l2cap_pi(sk)->chan; | ||||||
| @ -736,7 +736,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, | |||||||
| 		opts.txwin_size = chan->tx_win; | 		opts.txwin_size = chan->tx_win; | ||||||
| 
 | 
 | ||||||
| 		len = min_t(unsigned int, sizeof(opts), optlen); | 		len = min_t(unsigned int, sizeof(opts), optlen); | ||||||
| 		if (copy_from_user((char *) &opts, optval, len)) { | 		if (copy_from_sockptr(&opts, optval, len)) { | ||||||
| 			err = -EFAULT; | 			err = -EFAULT; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| @ -782,7 +782,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, | |||||||
| 		break; | 		break; | ||||||
| 
 | 
 | ||||||
| 	case L2CAP_LM: | 	case L2CAP_LM: | ||||||
| 		if (get_user(opt, (u32 __user *) optval)) { | 		if (copy_from_sockptr(&opt, optval, sizeof(u32))) { | ||||||
| 			err = -EFAULT; | 			err = -EFAULT; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| @ -859,7 +859,7 @@ static int l2cap_set_mode(struct l2cap_chan *chan, u8 mode) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, | static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, | ||||||
| 				 char __user *optval, unsigned int optlen) | 				 sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| 	struct l2cap_chan *chan = l2cap_pi(sk)->chan; | 	struct l2cap_chan *chan = l2cap_pi(sk)->chan; | ||||||
| @ -891,7 +891,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 		sec.level = BT_SECURITY_LOW; | 		sec.level = BT_SECURITY_LOW; | ||||||
| 
 | 
 | ||||||
| 		len = min_t(unsigned int, sizeof(sec), optlen); | 		len = min_t(unsigned int, sizeof(sec), optlen); | ||||||
| 		if (copy_from_user((char *) &sec, optval, len)) { | 		if (copy_from_sockptr(&sec, optval, len)) { | ||||||
| 			err = -EFAULT; | 			err = -EFAULT; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| @ -939,7 +939,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (get_user(opt, (u32 __user *) optval)) { | 		if (copy_from_sockptr(&opt, optval, sizeof(u32))) { | ||||||
| 			err = -EFAULT; | 			err = -EFAULT; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| @ -954,7 +954,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 		break; | 		break; | ||||||
| 
 | 
 | ||||||
| 	case BT_FLUSHABLE: | 	case BT_FLUSHABLE: | ||||||
| 		if (get_user(opt, (u32 __user *) optval)) { | 		if (copy_from_sockptr(&opt, optval, sizeof(u32))) { | ||||||
| 			err = -EFAULT; | 			err = -EFAULT; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| @ -990,7 +990,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 		pwr.force_active = BT_POWER_FORCE_ACTIVE_ON; | 		pwr.force_active = BT_POWER_FORCE_ACTIVE_ON; | ||||||
| 
 | 
 | ||||||
| 		len = min_t(unsigned int, sizeof(pwr), optlen); | 		len = min_t(unsigned int, sizeof(pwr), optlen); | ||||||
| 		if (copy_from_user((char *) &pwr, optval, len)) { | 		if (copy_from_sockptr(&pwr, optval, len)) { | ||||||
| 			err = -EFAULT; | 			err = -EFAULT; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| @ -1002,7 +1002,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 		break; | 		break; | ||||||
| 
 | 
 | ||||||
| 	case BT_CHANNEL_POLICY: | 	case BT_CHANNEL_POLICY: | ||||||
| 		if (get_user(opt, (u32 __user *) optval)) { | 		if (copy_from_sockptr(&opt, optval, sizeof(u32))) { | ||||||
| 			err = -EFAULT; | 			err = -EFAULT; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| @ -1050,7 +1050,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (get_user(opt, (u16 __user *) optval)) { | 		if (copy_from_sockptr(&opt, optval, sizeof(u16))) { | ||||||
| 			err = -EFAULT; | 			err = -EFAULT; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| @ -1081,7 +1081,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (get_user(opt, (u8 __user *) optval)) { | 		if (copy_from_sockptr(&opt, optval, sizeof(u8))) { | ||||||
| 			err = -EFAULT; | 			err = -EFAULT; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -644,7 +644,8 @@ static int rfcomm_sock_recvmsg(struct socket *sock, struct msghdr *msg, | |||||||
| 	return len; | 	return len; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen) | static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, | ||||||
|  | 		sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| 	int err = 0; | 	int err = 0; | ||||||
| @ -656,7 +657,7 @@ static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, char __u | |||||||
| 
 | 
 | ||||||
| 	switch (optname) { | 	switch (optname) { | ||||||
| 	case RFCOMM_LM: | 	case RFCOMM_LM: | ||||||
| 		if (get_user(opt, (u32 __user *) optval)) { | 		if (copy_from_sockptr(&opt, optval, sizeof(u32))) { | ||||||
| 			err = -EFAULT; | 			err = -EFAULT; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| @ -685,7 +686,8 @@ static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, char __u | |||||||
| 	return err; | 	return err; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen) | static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, | ||||||
|  | 		sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| 	struct bt_security sec; | 	struct bt_security sec; | ||||||
| @ -713,7 +715,7 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, c | |||||||
| 		sec.level = BT_SECURITY_LOW; | 		sec.level = BT_SECURITY_LOW; | ||||||
| 
 | 
 | ||||||
| 		len = min_t(unsigned int, sizeof(sec), optlen); | 		len = min_t(unsigned int, sizeof(sec), optlen); | ||||||
| 		if (copy_from_user((char *) &sec, optval, len)) { | 		if (copy_from_sockptr(&sec, optval, len)) { | ||||||
| 			err = -EFAULT; | 			err = -EFAULT; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| @ -732,7 +734,7 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, c | |||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (get_user(opt, (u32 __user *) optval)) { | 		if (copy_from_sockptr(&opt, optval, sizeof(u32))) { | ||||||
| 			err = -EFAULT; | 			err = -EFAULT; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -791,7 +791,7 @@ static int sco_sock_recvmsg(struct socket *sock, struct msghdr *msg, | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int sco_sock_setsockopt(struct socket *sock, int level, int optname, | static int sco_sock_setsockopt(struct socket *sock, int level, int optname, | ||||||
| 			       char __user *optval, unsigned int optlen) | 			       sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| 	int len, err = 0; | 	int len, err = 0; | ||||||
| @ -810,7 +810,7 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (get_user(opt, (u32 __user *) optval)) { | 		if (copy_from_sockptr(&opt, optval, sizeof(u32))) { | ||||||
| 			err = -EFAULT; | 			err = -EFAULT; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| @ -831,7 +831,7 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 		voice.setting = sco_pi(sk)->setting; | 		voice.setting = sco_pi(sk)->setting; | ||||||
| 
 | 
 | ||||||
| 		len = min_t(unsigned int, sizeof(voice), optlen); | 		len = min_t(unsigned int, sizeof(voice), optlen); | ||||||
| 		if (copy_from_user((char *)&voice, optval, len)) { | 		if (copy_from_sockptr(&voice, optval, len)) { | ||||||
| 			err = -EFAULT; | 			err = -EFAULT; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -669,8 +669,8 @@ out_err: | |||||||
| 	return sent ? : err; | 	return sent ? : err; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int setsockopt(struct socket *sock, | static int setsockopt(struct socket *sock, int lvl, int opt, sockptr_t ov, | ||||||
| 		      int lvl, int opt, char __user *ov, unsigned int ol) | 		unsigned int ol) | ||||||
| { | { | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| 	struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); | 	struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); | ||||||
| @ -685,7 +685,7 @@ static int setsockopt(struct socket *sock, | |||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 		if (lvl != SOL_CAIF) | 		if (lvl != SOL_CAIF) | ||||||
| 			goto bad_sol; | 			goto bad_sol; | ||||||
| 		if (copy_from_user(&linksel, ov, sizeof(int))) | 		if (copy_from_sockptr(&linksel, ov, sizeof(int))) | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 		lock_sock(&(cf_sk->sk)); | 		lock_sock(&(cf_sk->sk)); | ||||||
| 		cf_sk->conn_req.link_selector = linksel; | 		cf_sk->conn_req.link_selector = linksel; | ||||||
| @ -699,7 +699,7 @@ static int setsockopt(struct socket *sock, | |||||||
| 			return -ENOPROTOOPT; | 			return -ENOPROTOOPT; | ||||||
| 		lock_sock(&(cf_sk->sk)); | 		lock_sock(&(cf_sk->sk)); | ||||||
| 		if (ol > sizeof(cf_sk->conn_req.param.data) || | 		if (ol > sizeof(cf_sk->conn_req.param.data) || | ||||||
| 			copy_from_user(&cf_sk->conn_req.param.data, ov, ol)) { | 		    copy_from_sockptr(&cf_sk->conn_req.param.data, ov, ol)) { | ||||||
| 			release_sock(&cf_sk->sk); | 			release_sock(&cf_sk->sk); | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -627,14 +627,14 @@ static int j1939_sk_release(struct socket *sock) | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int j1939_sk_setsockopt_flag(struct j1939_sock *jsk, char __user *optval, | static int j1939_sk_setsockopt_flag(struct j1939_sock *jsk, sockptr_t optval, | ||||||
| 				    unsigned int optlen, int flag) | 				    unsigned int optlen, int flag) | ||||||
| { | { | ||||||
| 	int tmp; | 	int tmp; | ||||||
| 
 | 
 | ||||||
| 	if (optlen != sizeof(tmp)) | 	if (optlen != sizeof(tmp)) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	if (copy_from_user(&tmp, optval, optlen)) | 	if (copy_from_sockptr(&tmp, optval, optlen)) | ||||||
| 		return -EFAULT; | 		return -EFAULT; | ||||||
| 	lock_sock(&jsk->sk); | 	lock_sock(&jsk->sk); | ||||||
| 	if (tmp) | 	if (tmp) | ||||||
| @ -646,7 +646,7 @@ static int j1939_sk_setsockopt_flag(struct j1939_sock *jsk, char __user *optval, | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int j1939_sk_setsockopt(struct socket *sock, int level, int optname, | static int j1939_sk_setsockopt(struct socket *sock, int level, int optname, | ||||||
| 			       char __user *optval, unsigned int optlen) | 			       sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| 	struct j1939_sock *jsk = j1939_sk(sk); | 	struct j1939_sock *jsk = j1939_sk(sk); | ||||||
| @ -658,7 +658,7 @@ static int j1939_sk_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 
 | 
 | ||||||
| 	switch (optname) { | 	switch (optname) { | ||||||
| 	case SO_J1939_FILTER: | 	case SO_J1939_FILTER: | ||||||
| 		if (optval) { | 		if (!sockptr_is_null(optval)) { | ||||||
| 			struct j1939_filter *f; | 			struct j1939_filter *f; | ||||||
| 			int c; | 			int c; | ||||||
| 
 | 
 | ||||||
| @ -670,7 +670,7 @@ static int j1939_sk_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 				return -EINVAL; | 				return -EINVAL; | ||||||
| 
 | 
 | ||||||
| 			count = optlen / sizeof(*filters); | 			count = optlen / sizeof(*filters); | ||||||
| 			filters = memdup_user(optval, optlen); | 			filters = memdup_sockptr(optval, optlen); | ||||||
| 			if (IS_ERR(filters)) | 			if (IS_ERR(filters)) | ||||||
| 				return PTR_ERR(filters); | 				return PTR_ERR(filters); | ||||||
| 
 | 
 | ||||||
| @ -703,7 +703,7 @@ static int j1939_sk_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 	case SO_J1939_SEND_PRIO: | 	case SO_J1939_SEND_PRIO: | ||||||
| 		if (optlen != sizeof(tmp)) | 		if (optlen != sizeof(tmp)) | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 		if (copy_from_user(&tmp, optval, optlen)) | 		if (copy_from_sockptr(&tmp, optval, optlen)) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| 		if (tmp < 0 || tmp > 7) | 		if (tmp < 0 || tmp > 7) | ||||||
| 			return -EDOM; | 			return -EDOM; | ||||||
|  | |||||||
| @ -485,7 +485,7 @@ static int raw_getname(struct socket *sock, struct sockaddr *uaddr, | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int raw_setsockopt(struct socket *sock, int level, int optname, | static int raw_setsockopt(struct socket *sock, int level, int optname, | ||||||
| 			  char __user *optval, unsigned int optlen) | 			  sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| 	struct raw_sock *ro = raw_sk(sk); | 	struct raw_sock *ro = raw_sk(sk); | ||||||
| @ -511,11 +511,11 @@ static int raw_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 
 | 
 | ||||||
| 		if (count > 1) { | 		if (count > 1) { | ||||||
| 			/* filter does not fit into dfilter => alloc space */ | 			/* filter does not fit into dfilter => alloc space */ | ||||||
| 			filter = memdup_user(optval, optlen); | 			filter = memdup_sockptr(optval, optlen); | ||||||
| 			if (IS_ERR(filter)) | 			if (IS_ERR(filter)) | ||||||
| 				return PTR_ERR(filter); | 				return PTR_ERR(filter); | ||||||
| 		} else if (count == 1) { | 		} else if (count == 1) { | ||||||
| 			if (copy_from_user(&sfilter, optval, sizeof(sfilter))) | 			if (copy_from_sockptr(&sfilter, optval, sizeof(sfilter))) | ||||||
| 				return -EFAULT; | 				return -EFAULT; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| @ -568,7 +568,7 @@ static int raw_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 		if (optlen != sizeof(err_mask)) | 		if (optlen != sizeof(err_mask)) | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 
 | 
 | ||||||
| 		if (copy_from_user(&err_mask, optval, optlen)) | 		if (copy_from_sockptr(&err_mask, optval, optlen)) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 		err_mask &= CAN_ERR_MASK; | 		err_mask &= CAN_ERR_MASK; | ||||||
| @ -607,7 +607,7 @@ static int raw_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 		if (optlen != sizeof(ro->loopback)) | 		if (optlen != sizeof(ro->loopback)) | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 
 | 
 | ||||||
| 		if (copy_from_user(&ro->loopback, optval, optlen)) | 		if (copy_from_sockptr(&ro->loopback, optval, optlen)) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 		break; | 		break; | ||||||
| @ -616,7 +616,7 @@ static int raw_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 		if (optlen != sizeof(ro->recv_own_msgs)) | 		if (optlen != sizeof(ro->recv_own_msgs)) | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 
 | 
 | ||||||
| 		if (copy_from_user(&ro->recv_own_msgs, optval, optlen)) | 		if (copy_from_sockptr(&ro->recv_own_msgs, optval, optlen)) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 		break; | 		break; | ||||||
| @ -625,7 +625,7 @@ static int raw_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 		if (optlen != sizeof(ro->fd_frames)) | 		if (optlen != sizeof(ro->fd_frames)) | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 
 | 
 | ||||||
| 		if (copy_from_user(&ro->fd_frames, optval, optlen)) | 		if (copy_from_sockptr(&ro->fd_frames, optval, optlen)) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 		break; | 		break; | ||||||
| @ -634,7 +634,7 @@ static int raw_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 		if (optlen != sizeof(ro->join_filters)) | 		if (optlen != sizeof(ro->join_filters)) | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 
 | 
 | ||||||
| 		if (copy_from_user(&ro->join_filters, optval, optlen)) | 		if (copy_from_sockptr(&ro->join_filters, optval, optlen)) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 		break; | 		break; | ||||||
|  | |||||||
| @ -3211,7 +3211,7 @@ EXPORT_SYMBOL(sock_common_recvmsg); | |||||||
|  *	Set socket options on an inet socket. |  *	Set socket options on an inet socket. | ||||||
|  */ |  */ | ||||||
| int sock_common_setsockopt(struct socket *sock, int level, int optname, | int sock_common_setsockopt(struct socket *sock, int level, int optname, | ||||||
| 			   char __user *optval, unsigned int optlen) | 			   sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -295,7 +295,7 @@ int dccp_disconnect(struct sock *sk, int flags); | |||||||
| int dccp_getsockopt(struct sock *sk, int level, int optname, | int dccp_getsockopt(struct sock *sk, int level, int optname, | ||||||
| 		    char __user *optval, int __user *optlen); | 		    char __user *optval, int __user *optlen); | ||||||
| int dccp_setsockopt(struct sock *sk, int level, int optname, | int dccp_setsockopt(struct sock *sk, int level, int optname, | ||||||
| 		    char __user *optval, unsigned int optlen); | 		    sockptr_t optval, unsigned int optlen); | ||||||
| int dccp_ioctl(struct sock *sk, int cmd, unsigned long arg); | int dccp_ioctl(struct sock *sk, int cmd, unsigned long arg); | ||||||
| int dccp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size); | int dccp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size); | ||||||
| int dccp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock, | int dccp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock, | ||||||
|  | |||||||
| @ -411,7 +411,7 @@ out: | |||||||
| EXPORT_SYMBOL_GPL(dccp_ioctl); | EXPORT_SYMBOL_GPL(dccp_ioctl); | ||||||
| 
 | 
 | ||||||
| static int dccp_setsockopt_service(struct sock *sk, const __be32 service, | static int dccp_setsockopt_service(struct sock *sk, const __be32 service, | ||||||
| 				   char __user *optval, unsigned int optlen) | 				   sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct dccp_sock *dp = dccp_sk(sk); | 	struct dccp_sock *dp = dccp_sk(sk); | ||||||
| 	struct dccp_service_list *sl = NULL; | 	struct dccp_service_list *sl = NULL; | ||||||
| @ -426,9 +426,9 @@ static int dccp_setsockopt_service(struct sock *sk, const __be32 service, | |||||||
| 			return -ENOMEM; | 			return -ENOMEM; | ||||||
| 
 | 
 | ||||||
| 		sl->dccpsl_nr = optlen / sizeof(u32) - 1; | 		sl->dccpsl_nr = optlen / sizeof(u32) - 1; | ||||||
| 		if (copy_from_user(sl->dccpsl_list, | 		sockptr_advance(optval, sizeof(service)); | ||||||
| 				   optval + sizeof(service), | 		if (copy_from_sockptr(sl->dccpsl_list, optval, | ||||||
| 				   optlen - sizeof(service)) || | 				      optlen - sizeof(service)) || | ||||||
| 		    dccp_list_has_service(sl, DCCP_SERVICE_INVALID_VALUE)) { | 		    dccp_list_has_service(sl, DCCP_SERVICE_INVALID_VALUE)) { | ||||||
| 			kfree(sl); | 			kfree(sl); | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| @ -482,7 +482,7 @@ static int dccp_setsockopt_cscov(struct sock *sk, int cscov, bool rx) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int dccp_setsockopt_ccid(struct sock *sk, int type, | static int dccp_setsockopt_ccid(struct sock *sk, int type, | ||||||
| 				char __user *optval, unsigned int optlen) | 				sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	u8 *val; | 	u8 *val; | ||||||
| 	int rc = 0; | 	int rc = 0; | ||||||
| @ -490,7 +490,7 @@ static int dccp_setsockopt_ccid(struct sock *sk, int type, | |||||||
| 	if (optlen < 1 || optlen > DCCP_FEAT_MAX_SP_VALS) | 	if (optlen < 1 || optlen > DCCP_FEAT_MAX_SP_VALS) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 
 | 
 | ||||||
| 	val = memdup_user(optval, optlen); | 	val = memdup_sockptr(optval, optlen); | ||||||
| 	if (IS_ERR(val)) | 	if (IS_ERR(val)) | ||||||
| 		return PTR_ERR(val); | 		return PTR_ERR(val); | ||||||
| 
 | 
 | ||||||
| @ -507,7 +507,7 @@ static int dccp_setsockopt_ccid(struct sock *sk, int type, | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int do_dccp_setsockopt(struct sock *sk, int level, int optname, | static int do_dccp_setsockopt(struct sock *sk, int level, int optname, | ||||||
| 		char __user *optval, unsigned int optlen) | 		sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct dccp_sock *dp = dccp_sk(sk); | 	struct dccp_sock *dp = dccp_sk(sk); | ||||||
| 	int val, err = 0; | 	int val, err = 0; | ||||||
| @ -529,7 +529,7 @@ static int do_dccp_setsockopt(struct sock *sk, int level, int optname, | |||||||
| 	if (optlen < (int)sizeof(int)) | 	if (optlen < (int)sizeof(int)) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 
 | 
 | ||||||
| 	if (get_user(val, (int __user *)optval)) | 	if (copy_from_sockptr(&val, optval, sizeof(int))) | ||||||
| 		return -EFAULT; | 		return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 	if (optname == DCCP_SOCKOPT_SERVICE) | 	if (optname == DCCP_SOCKOPT_SERVICE) | ||||||
| @ -572,8 +572,8 @@ static int do_dccp_setsockopt(struct sock *sk, int level, int optname, | |||||||
| 	return err; | 	return err; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int dccp_setsockopt(struct sock *sk, int level, int optname, | int dccp_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval, | ||||||
| 		    char __user *optval, unsigned int optlen) | 		    unsigned int optlen) | ||||||
| { | { | ||||||
| 	if (level != SOL_DCCP) | 	if (level != SOL_DCCP) | ||||||
| 		return inet_csk(sk)->icsk_af_ops->setsockopt(sk, level, | 		return inet_csk(sk)->icsk_af_ops->setsockopt(sk, level, | ||||||
|  | |||||||
| @ -150,7 +150,8 @@ static struct hlist_head dn_sk_hash[DN_SK_HASH_SIZE]; | |||||||
| static struct hlist_head dn_wild_sk; | static struct hlist_head dn_wild_sk; | ||||||
| static atomic_long_t decnet_memory_allocated; | static atomic_long_t decnet_memory_allocated; | ||||||
| 
 | 
 | ||||||
| static int __dn_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen, int flags); | static int __dn_setsockopt(struct socket *sock, int level, int optname, | ||||||
|  | 		sockptr_t optval, unsigned int optlen, int flags); | ||||||
| static int __dn_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen, int flags); | static int __dn_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen, int flags); | ||||||
| 
 | 
 | ||||||
| static struct hlist_head *dn_find_list(struct sock *sk) | static struct hlist_head *dn_find_list(struct sock *sk) | ||||||
| @ -1320,7 +1321,8 @@ out: | |||||||
| 	return err; | 	return err; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int dn_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen) | static int dn_setsockopt(struct socket *sock, int level, int optname, | ||||||
|  | 		sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| 	int err; | 	int err; | ||||||
| @ -1332,14 +1334,14 @@ static int dn_setsockopt(struct socket *sock, int level, int optname, char __use | |||||||
| 	/* we need to exclude all possible ENOPROTOOPTs except default case */ | 	/* we need to exclude all possible ENOPROTOOPTs except default case */ | ||||||
| 	if (err == -ENOPROTOOPT && optname != DSO_LINKINFO && | 	if (err == -ENOPROTOOPT && optname != DSO_LINKINFO && | ||||||
| 	    optname != DSO_STREAM && optname != DSO_SEQPACKET) | 	    optname != DSO_STREAM && optname != DSO_SEQPACKET) | ||||||
| 		err = nf_setsockopt(sk, PF_DECnet, optname, | 		err = nf_setsockopt(sk, PF_DECnet, optname, optval, optlen); | ||||||
| 				    USER_SOCKPTR(optval), optlen); |  | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 	return err; | 	return err; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int __dn_setsockopt(struct socket *sock, int level,int optname, char __user *optval, unsigned int optlen, int flags) | static int __dn_setsockopt(struct socket *sock, int level, int optname, | ||||||
|  | 		sockptr_t optval, unsigned int optlen, int flags) | ||||||
| { | { | ||||||
| 	struct	sock *sk = sock->sk; | 	struct	sock *sk = sock->sk; | ||||||
| 	struct dn_scp *scp = DN_SK(sk); | 	struct dn_scp *scp = DN_SK(sk); | ||||||
| @ -1355,13 +1357,13 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char __us | |||||||
| 	} u; | 	} u; | ||||||
| 	int err; | 	int err; | ||||||
| 
 | 
 | ||||||
| 	if (optlen && !optval) | 	if (optlen && sockptr_is_null(optval)) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 
 | 
 | ||||||
| 	if (optlen > sizeof(u)) | 	if (optlen > sizeof(u)) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 
 | 
 | ||||||
| 	if (copy_from_user(&u, optval, optlen)) | 	if (copy_from_sockptr(&u, optval, optlen)) | ||||||
| 		return -EFAULT; | 		return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 	switch (optname) { | 	switch (optname) { | ||||||
|  | |||||||
| @ -382,7 +382,7 @@ static int raw_getsockopt(struct sock *sk, int level, int optname, | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int raw_setsockopt(struct sock *sk, int level, int optname, | static int raw_setsockopt(struct sock *sk, int level, int optname, | ||||||
| 			  char __user *optval, unsigned int optlen) | 			  sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	return -EOPNOTSUPP; | 	return -EOPNOTSUPP; | ||||||
| } | } | ||||||
| @ -872,7 +872,7 @@ static int dgram_getsockopt(struct sock *sk, int level, int optname, | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int dgram_setsockopt(struct sock *sk, int level, int optname, | static int dgram_setsockopt(struct sock *sk, int level, int optname, | ||||||
| 			    char __user *optval, unsigned int optlen) | 			    sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct dgram_sock *ro = dgram_sk(sk); | 	struct dgram_sock *ro = dgram_sk(sk); | ||||||
| 	struct net *net = sock_net(sk); | 	struct net *net = sock_net(sk); | ||||||
| @ -882,7 +882,7 @@ static int dgram_setsockopt(struct sock *sk, int level, int optname, | |||||||
| 	if (optlen < sizeof(int)) | 	if (optlen < sizeof(int)) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 
 | 
 | ||||||
| 	if (get_user(val, (int __user *)optval)) | 	if (copy_from_sockptr(&val, optval, sizeof(int))) | ||||||
| 		return -EFAULT; | 		return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 	lock_sock(sk); | 	lock_sock(sk); | ||||||
|  | |||||||
| @ -1401,21 +1401,19 @@ void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb) | |||||||
| 	skb_dst_drop(skb); | 	skb_dst_drop(skb); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int ip_setsockopt(struct sock *sk, int level, | int ip_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval, | ||||||
| 		int optname, char __user *optval, unsigned int optlen) | 		unsigned int optlen) | ||||||
| { | { | ||||||
| 	int err; | 	int err; | ||||||
| 
 | 
 | ||||||
| 	if (level != SOL_IP) | 	if (level != SOL_IP) | ||||||
| 		return -ENOPROTOOPT; | 		return -ENOPROTOOPT; | ||||||
| 
 | 
 | ||||||
| 	err = do_ip_setsockopt(sk, level, optname, USER_SOCKPTR(optval), | 	err = do_ip_setsockopt(sk, level, optname, optval, optlen); | ||||||
| 			       optlen); |  | ||||||
| #if IS_ENABLED(CONFIG_BPFILTER_UMH) | #if IS_ENABLED(CONFIG_BPFILTER_UMH) | ||||||
| 	if (optname >= BPFILTER_IPT_SO_SET_REPLACE && | 	if (optname >= BPFILTER_IPT_SO_SET_REPLACE && | ||||||
| 	    optname < BPFILTER_IPT_SET_MAX) | 	    optname < BPFILTER_IPT_SET_MAX) | ||||||
| 		err = bpfilter_ip_set_sockopt(sk, optname, USER_SOCKPTR(optval), | 		err = bpfilter_ip_set_sockopt(sk, optname, optval, optlen); | ||||||
| 					      optlen); |  | ||||||
| #endif | #endif | ||||||
| #ifdef CONFIG_NETFILTER | #ifdef CONFIG_NETFILTER | ||||||
| 	/* we need to exclude all possible ENOPROTOOPTs except default case */ | 	/* we need to exclude all possible ENOPROTOOPTs except default case */ | ||||||
| @ -1423,8 +1421,7 @@ int ip_setsockopt(struct sock *sk, int level, | |||||||
| 			optname != IP_IPSEC_POLICY && | 			optname != IP_IPSEC_POLICY && | ||||||
| 			optname != IP_XFRM_POLICY && | 			optname != IP_XFRM_POLICY && | ||||||
| 			!ip_mroute_opt(optname)) | 			!ip_mroute_opt(optname)) | ||||||
| 		err = nf_setsockopt(sk, PF_INET, optname, USER_SOCKPTR(optval), | 		err = nf_setsockopt(sk, PF_INET, optname, optval, optlen); | ||||||
| 				    optlen); |  | ||||||
| #endif | #endif | ||||||
| 	return err; | 	return err; | ||||||
| } | } | ||||||
|  | |||||||
| @ -809,11 +809,11 @@ static int raw_sk_init(struct sock *sk) | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int raw_seticmpfilter(struct sock *sk, char __user *optval, int optlen) | static int raw_seticmpfilter(struct sock *sk, sockptr_t optval, int optlen) | ||||||
| { | { | ||||||
| 	if (optlen > sizeof(struct icmp_filter)) | 	if (optlen > sizeof(struct icmp_filter)) | ||||||
| 		optlen = sizeof(struct icmp_filter); | 		optlen = sizeof(struct icmp_filter); | ||||||
| 	if (copy_from_user(&raw_sk(sk)->filter, optval, optlen)) | 	if (copy_from_sockptr(&raw_sk(sk)->filter, optval, optlen)) | ||||||
| 		return -EFAULT; | 		return -EFAULT; | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| @ -838,7 +838,7 @@ out:	return ret; | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int do_raw_setsockopt(struct sock *sk, int level, int optname, | static int do_raw_setsockopt(struct sock *sk, int level, int optname, | ||||||
| 			  char __user *optval, unsigned int optlen) | 			     sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	if (optname == ICMP_FILTER) { | 	if (optname == ICMP_FILTER) { | ||||||
| 		if (inet_sk(sk)->inet_num != IPPROTO_ICMP) | 		if (inet_sk(sk)->inet_num != IPPROTO_ICMP) | ||||||
| @ -850,7 +850,7 @@ static int do_raw_setsockopt(struct sock *sk, int level, int optname, | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int raw_setsockopt(struct sock *sk, int level, int optname, | static int raw_setsockopt(struct sock *sk, int level, int optname, | ||||||
| 			  char __user *optval, unsigned int optlen) | 			  sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	if (level != SOL_RAW) | 	if (level != SOL_RAW) | ||||||
| 		return ip_setsockopt(sk, level, optname, optval, optlen); | 		return ip_setsockopt(sk, level, optname, optval, optlen); | ||||||
|  | |||||||
| @ -3323,7 +3323,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level, int optname, | |||||||
| 	return err; | 	return err; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, | int tcp_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval, | ||||||
| 		   unsigned int optlen) | 		   unsigned int optlen) | ||||||
| { | { | ||||||
| 	const struct inet_connection_sock *icsk = inet_csk(sk); | 	const struct inet_connection_sock *icsk = inet_csk(sk); | ||||||
| @ -3331,8 +3331,7 @@ int tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval, | |||||||
| 	if (level != SOL_TCP) | 	if (level != SOL_TCP) | ||||||
| 		return icsk->icsk_af_ops->setsockopt(sk, level, optname, | 		return icsk->icsk_af_ops->setsockopt(sk, level, optname, | ||||||
| 						     optval, optlen); | 						     optval, optlen); | ||||||
| 	return do_tcp_setsockopt(sk, level, optname, USER_SOCKPTR(optval), | 	return do_tcp_setsockopt(sk, level, optname, optval, optlen); | ||||||
| 				 optlen); |  | ||||||
| } | } | ||||||
| EXPORT_SYMBOL(tcp_setsockopt); | EXPORT_SYMBOL(tcp_setsockopt); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -2703,12 +2703,12 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname, | |||||||
| } | } | ||||||
| EXPORT_SYMBOL(udp_lib_setsockopt); | EXPORT_SYMBOL(udp_lib_setsockopt); | ||||||
| 
 | 
 | ||||||
| int udp_setsockopt(struct sock *sk, int level, int optname, | int udp_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval, | ||||||
| 		   char __user *optval, unsigned int optlen) | 		   unsigned int optlen) | ||||||
| { | { | ||||||
| 	if (level == SOL_UDP  ||  level == SOL_UDPLITE) | 	if (level == SOL_UDP  ||  level == SOL_UDPLITE) | ||||||
| 		return udp_lib_setsockopt(sk, level, optname, | 		return udp_lib_setsockopt(sk, level, optname, | ||||||
| 					  USER_SOCKPTR(optval), optlen, | 					  optval, optlen, | ||||||
| 					  udp_push_pending_frames); | 					  udp_push_pending_frames); | ||||||
| 	return ip_setsockopt(sk, level, optname, optval, optlen); | 	return ip_setsockopt(sk, level, optname, optval, optlen); | ||||||
| } | } | ||||||
|  | |||||||
| @ -12,8 +12,8 @@ int __udp4_lib_err(struct sk_buff *, u32, struct udp_table *); | |||||||
| int udp_v4_get_port(struct sock *sk, unsigned short snum); | int udp_v4_get_port(struct sock *sk, unsigned short snum); | ||||||
| void udp_v4_rehash(struct sock *sk); | void udp_v4_rehash(struct sock *sk); | ||||||
| 
 | 
 | ||||||
| int udp_setsockopt(struct sock *sk, int level, int optname, | int udp_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval, | ||||||
| 		   char __user *optval, unsigned int optlen); | 		   unsigned int optlen); | ||||||
| int udp_getsockopt(struct sock *sk, int level, int optname, | int udp_getsockopt(struct sock *sk, int level, int optname, | ||||||
| 		   char __user *optval, int __user *optlen); | 		   char __user *optval, int __user *optlen); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -980,8 +980,8 @@ e_inval: | |||||||
| 	return -EINVAL; | 	return -EINVAL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int ipv6_setsockopt(struct sock *sk, int level, int optname, | int ipv6_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval, | ||||||
| 		    char __user *optval, unsigned int optlen) | 		    unsigned int optlen) | ||||||
| { | { | ||||||
| 	int err; | 	int err; | ||||||
| 
 | 
 | ||||||
| @ -991,14 +991,12 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, | |||||||
| 	if (level != SOL_IPV6) | 	if (level != SOL_IPV6) | ||||||
| 		return -ENOPROTOOPT; | 		return -ENOPROTOOPT; | ||||||
| 
 | 
 | ||||||
| 	err = do_ipv6_setsockopt(sk, level, optname, USER_SOCKPTR(optval), | 	err = do_ipv6_setsockopt(sk, level, optname, optval, optlen); | ||||||
| 				 optlen); |  | ||||||
| #ifdef CONFIG_NETFILTER | #ifdef CONFIG_NETFILTER | ||||||
| 	/* we need to exclude all possible ENOPROTOOPTs except default case */ | 	/* we need to exclude all possible ENOPROTOOPTs except default case */ | ||||||
| 	if (err == -ENOPROTOOPT && optname != IPV6_IPSEC_POLICY && | 	if (err == -ENOPROTOOPT && optname != IPV6_IPSEC_POLICY && | ||||||
| 			optname != IPV6_XFRM_POLICY) | 			optname != IPV6_XFRM_POLICY) | ||||||
| 		err = nf_setsockopt(sk, PF_INET6, optname, USER_SOCKPTR(optval), | 		err = nf_setsockopt(sk, PF_INET6, optname, optval, optlen); | ||||||
| 				    optlen); |  | ||||||
| #endif | #endif | ||||||
| 	return err; | 	return err; | ||||||
| } | } | ||||||
|  | |||||||
| @ -972,13 +972,13 @@ do_confirm: | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int rawv6_seticmpfilter(struct sock *sk, int level, int optname, | static int rawv6_seticmpfilter(struct sock *sk, int level, int optname, | ||||||
| 			       char __user *optval, int optlen) | 			       sockptr_t optval, int optlen) | ||||||
| { | { | ||||||
| 	switch (optname) { | 	switch (optname) { | ||||||
| 	case ICMPV6_FILTER: | 	case ICMPV6_FILTER: | ||||||
| 		if (optlen > sizeof(struct icmp6_filter)) | 		if (optlen > sizeof(struct icmp6_filter)) | ||||||
| 			optlen = sizeof(struct icmp6_filter); | 			optlen = sizeof(struct icmp6_filter); | ||||||
| 		if (copy_from_user(&raw6_sk(sk)->filter, optval, optlen)) | 		if (copy_from_sockptr(&raw6_sk(sk)->filter, optval, optlen)) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| 		return 0; | 		return 0; | ||||||
| 	default: | 	default: | ||||||
| @ -1015,12 +1015,12 @@ static int rawv6_geticmpfilter(struct sock *sk, int level, int optname, | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static int do_rawv6_setsockopt(struct sock *sk, int level, int optname, | static int do_rawv6_setsockopt(struct sock *sk, int level, int optname, | ||||||
| 			    char __user *optval, unsigned int optlen) | 			       sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct raw6_sock *rp = raw6_sk(sk); | 	struct raw6_sock *rp = raw6_sk(sk); | ||||||
| 	int val; | 	int val; | ||||||
| 
 | 
 | ||||||
| 	if (get_user(val, (int __user *)optval)) | 	if (copy_from_sockptr(&val, optval, sizeof(val))) | ||||||
| 		return -EFAULT; | 		return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 	switch (optname) { | 	switch (optname) { | ||||||
| @ -1062,7 +1062,7 @@ static int do_rawv6_setsockopt(struct sock *sk, int level, int optname, | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int rawv6_setsockopt(struct sock *sk, int level, int optname, | static int rawv6_setsockopt(struct sock *sk, int level, int optname, | ||||||
| 			  char __user *optval, unsigned int optlen) | 			    sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	switch (level) { | 	switch (level) { | ||||||
| 	case SOL_RAW: | 	case SOL_RAW: | ||||||
|  | |||||||
| @ -1618,12 +1618,12 @@ void udpv6_destroy_sock(struct sock *sk) | |||||||
| /*
 | /*
 | ||||||
|  *	Socket option code for UDP |  *	Socket option code for UDP | ||||||
|  */ |  */ | ||||||
| int udpv6_setsockopt(struct sock *sk, int level, int optname, | int udpv6_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval, | ||||||
| 		     char __user *optval, unsigned int optlen) | 		     unsigned int optlen) | ||||||
| { | { | ||||||
| 	if (level == SOL_UDP  ||  level == SOL_UDPLITE) | 	if (level == SOL_UDP  ||  level == SOL_UDPLITE) | ||||||
| 		return udp_lib_setsockopt(sk, level, optname, | 		return udp_lib_setsockopt(sk, level, optname, | ||||||
| 					  USER_SOCKPTR(optval), optlen, | 					  optval, optlen, | ||||||
| 					  udp_v6_push_pending_frames); | 					  udp_v6_push_pending_frames); | ||||||
| 	return ipv6_setsockopt(sk, level, optname, optval, optlen); | 	return ipv6_setsockopt(sk, level, optname, optval, optlen); | ||||||
| } | } | ||||||
|  | |||||||
| @ -17,8 +17,8 @@ void udp_v6_rehash(struct sock *sk); | |||||||
| 
 | 
 | ||||||
| int udpv6_getsockopt(struct sock *sk, int level, int optname, | int udpv6_getsockopt(struct sock *sk, int level, int optname, | ||||||
| 		     char __user *optval, int __user *optlen); | 		     char __user *optval, int __user *optlen); | ||||||
| int udpv6_setsockopt(struct sock *sk, int level, int optname, | int udpv6_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval, | ||||||
| 		     char __user *optval, unsigned int optlen); | 		     unsigned int optlen); | ||||||
| int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len); | int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len); | ||||||
| int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock, | int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock, | ||||||
| 		  int flags, int *addr_len); | 		  int flags, int *addr_len); | ||||||
|  | |||||||
| @ -1494,7 +1494,7 @@ static int iucv_sock_release(struct socket *sock) | |||||||
| 
 | 
 | ||||||
| /* getsockopt and setsockopt */ | /* getsockopt and setsockopt */ | ||||||
| static int iucv_sock_setsockopt(struct socket *sock, int level, int optname, | static int iucv_sock_setsockopt(struct socket *sock, int level, int optname, | ||||||
| 				char __user *optval, unsigned int optlen) | 				sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| 	struct iucv_sock *iucv = iucv_sk(sk); | 	struct iucv_sock *iucv = iucv_sk(sk); | ||||||
| @ -1507,7 +1507,7 @@ static int iucv_sock_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 	if (optlen < sizeof(int)) | 	if (optlen < sizeof(int)) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 
 | 
 | ||||||
| 	if (get_user(val, (int __user *) optval)) | 	if (copy_from_sockptr(&val, optval, sizeof(int))) | ||||||
| 		return -EFAULT; | 		return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 	rc = 0; | 	rc = 0; | ||||||
|  | |||||||
| @ -1265,7 +1265,7 @@ static void kcm_recv_enable(struct kcm_sock *kcm) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int kcm_setsockopt(struct socket *sock, int level, int optname, | static int kcm_setsockopt(struct socket *sock, int level, int optname, | ||||||
| 			  char __user *optval, unsigned int optlen) | 			  sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct kcm_sock *kcm = kcm_sk(sock->sk); | 	struct kcm_sock *kcm = kcm_sk(sock->sk); | ||||||
| 	int val, valbool; | 	int val, valbool; | ||||||
| @ -1277,8 +1277,8 @@ static int kcm_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 	if (optlen < sizeof(int)) | 	if (optlen < sizeof(int)) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 
 | 
 | ||||||
| 	if (get_user(val, (int __user *)optval)) | 	if (copy_from_sockptr(&val, optval, sizeof(int))) | ||||||
| 		return -EINVAL; | 		return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 	valbool = val ? 1 : 0; | 	valbool = val ? 1 : 0; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1242,7 +1242,7 @@ static int pppol2tp_session_setsockopt(struct sock *sk, | |||||||
|  * session or the special tunnel type. |  * session or the special tunnel type. | ||||||
|  */ |  */ | ||||||
| static int pppol2tp_setsockopt(struct socket *sock, int level, int optname, | static int pppol2tp_setsockopt(struct socket *sock, int level, int optname, | ||||||
| 			       char __user *optval, unsigned int optlen) | 			       sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| 	struct l2tp_session *session; | 	struct l2tp_session *session; | ||||||
| @ -1256,7 +1256,7 @@ static int pppol2tp_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 	if (optlen < sizeof(int)) | 	if (optlen < sizeof(int)) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 
 | 
 | ||||||
| 	if (get_user(val, (int __user *)optval)) | 	if (copy_from_sockptr(&val, optval, sizeof(int))) | ||||||
| 		return -EFAULT; | 		return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 	err = -ENOTCONN; | 	err = -ENOTCONN; | ||||||
|  | |||||||
| @ -1053,7 +1053,7 @@ static int llc_ui_ioctl(struct socket *sock, unsigned int cmd, | |||||||
|  *	Set various connection specific parameters. |  *	Set various connection specific parameters. | ||||||
|  */ |  */ | ||||||
| static int llc_ui_setsockopt(struct socket *sock, int level, int optname, | static int llc_ui_setsockopt(struct socket *sock, int level, int optname, | ||||||
| 			     char __user *optval, unsigned int optlen) | 			     sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| 	struct llc_sock *llc = llc_sk(sk); | 	struct llc_sock *llc = llc_sk(sk); | ||||||
| @ -1063,7 +1063,7 @@ static int llc_ui_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 	lock_sock(sk); | 	lock_sock(sk); | ||||||
| 	if (unlikely(level != SOL_LLC || optlen != sizeof(int))) | 	if (unlikely(level != SOL_LLC || optlen != sizeof(int))) | ||||||
| 		goto out; | 		goto out; | ||||||
| 	rc = get_user(opt, (int __user *)optval); | 	rc = copy_from_sockptr(&opt, optval, sizeof(opt)); | ||||||
| 	if (rc) | 	if (rc) | ||||||
| 		goto out; | 		goto out; | ||||||
| 	rc = -EINVAL; | 	rc = -EINVAL; | ||||||
|  | |||||||
| @ -1632,7 +1632,7 @@ static void mptcp_destroy(struct sock *sk) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int mptcp_setsockopt_sol_socket(struct mptcp_sock *msk, int optname, | static int mptcp_setsockopt_sol_socket(struct mptcp_sock *msk, int optname, | ||||||
| 				       char __user *optval, unsigned int optlen) | 				       sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct sock *sk = (struct sock *)msk; | 	struct sock *sk = (struct sock *)msk; | ||||||
| 	struct socket *ssock; | 	struct socket *ssock; | ||||||
| @ -1648,8 +1648,7 @@ static int mptcp_setsockopt_sol_socket(struct mptcp_sock *msk, int optname, | |||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		ret = sock_setsockopt(ssock, SOL_SOCKET, optname, | 		ret = sock_setsockopt(ssock, SOL_SOCKET, optname, optval, optlen); | ||||||
| 				      USER_SOCKPTR(optval), optlen); |  | ||||||
| 		if (ret == 0) { | 		if (ret == 0) { | ||||||
| 			if (optname == SO_REUSEPORT) | 			if (optname == SO_REUSEPORT) | ||||||
| 				sk->sk_reuseport = ssock->sk->sk_reuseport; | 				sk->sk_reuseport = ssock->sk->sk_reuseport; | ||||||
| @ -1660,12 +1659,11 @@ static int mptcp_setsockopt_sol_socket(struct mptcp_sock *msk, int optname, | |||||||
| 		return ret; | 		return ret; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return sock_setsockopt(sk->sk_socket, SOL_SOCKET, optname, | 	return sock_setsockopt(sk->sk_socket, SOL_SOCKET, optname, optval, optlen); | ||||||
| 			       USER_SOCKPTR(optval), optlen); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int mptcp_setsockopt_v6(struct mptcp_sock *msk, int optname, | static int mptcp_setsockopt_v6(struct mptcp_sock *msk, int optname, | ||||||
| 			       char __user *optval, unsigned int optlen) | 			       sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct sock *sk = (struct sock *)msk; | 	struct sock *sk = (struct sock *)msk; | ||||||
| 	int ret = -EOPNOTSUPP; | 	int ret = -EOPNOTSUPP; | ||||||
| @ -1692,7 +1690,7 @@ static int mptcp_setsockopt_v6(struct mptcp_sock *msk, int optname, | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int mptcp_setsockopt(struct sock *sk, int level, int optname, | static int mptcp_setsockopt(struct sock *sk, int level, int optname, | ||||||
| 			    char __user *optval, unsigned int optlen) | 			    sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct mptcp_sock *msk = mptcp_sk(sk); | 	struct mptcp_sock *msk = mptcp_sk(sk); | ||||||
| 	struct sock *ssk; | 	struct sock *ssk; | ||||||
|  | |||||||
| @ -1621,7 +1621,7 @@ static void netlink_update_socket_mc(struct netlink_sock *nlk, | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int netlink_setsockopt(struct socket *sock, int level, int optname, | static int netlink_setsockopt(struct socket *sock, int level, int optname, | ||||||
| 			      char __user *optval, unsigned int optlen) | 			      sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| 	struct netlink_sock *nlk = nlk_sk(sk); | 	struct netlink_sock *nlk = nlk_sk(sk); | ||||||
| @ -1632,7 +1632,7 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 		return -ENOPROTOOPT; | 		return -ENOPROTOOPT; | ||||||
| 
 | 
 | ||||||
| 	if (optlen >= sizeof(int) && | 	if (optlen >= sizeof(int) && | ||||||
| 	    get_user(val, (unsigned int __user *)optval)) | 	    copy_from_sockptr(&val, optval, sizeof(val))) | ||||||
| 		return -EFAULT; | 		return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 	switch (optname) { | 	switch (optname) { | ||||||
|  | |||||||
| @ -294,7 +294,7 @@ void nr_destroy_socket(struct sock *sk) | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| static int nr_setsockopt(struct socket *sock, int level, int optname, | static int nr_setsockopt(struct socket *sock, int level, int optname, | ||||||
| 	char __user *optval, unsigned int optlen) | 		sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| 	struct nr_sock *nr = nr_sk(sk); | 	struct nr_sock *nr = nr_sk(sk); | ||||||
| @ -306,7 +306,7 @@ static int nr_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 	if (optlen < sizeof(unsigned int)) | 	if (optlen < sizeof(unsigned int)) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 
 | 
 | ||||||
| 	if (get_user(opt, (unsigned int __user *)optval)) | 	if (copy_from_sockptr(&opt, optval, sizeof(unsigned int))) | ||||||
| 		return -EFAULT; | 		return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 	switch (optname) { | 	switch (optname) { | ||||||
|  | |||||||
| @ -218,7 +218,7 @@ error: | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int nfc_llcp_setsockopt(struct socket *sock, int level, int optname, | static int nfc_llcp_setsockopt(struct socket *sock, int level, int optname, | ||||||
| 			       char __user *optval, unsigned int optlen) | 			       sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| 	struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); | 	struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); | ||||||
| @ -241,7 +241,7 @@ static int nfc_llcp_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (get_user(opt, (u32 __user *) optval)) { | 		if (copy_from_sockptr(&opt, optval, sizeof(u32))) { | ||||||
| 			err = -EFAULT; | 			err = -EFAULT; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| @ -263,7 +263,7 @@ static int nfc_llcp_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (get_user(opt, (u32 __user *) optval)) { | 		if (copy_from_sockptr(&opt, optval, sizeof(u32))) { | ||||||
| 			err = -EFAULT; | 			err = -EFAULT; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -1558,7 +1558,7 @@ static int fanout_set_data_cbpf(struct packet_sock *po, sockptr_t data, | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int fanout_set_data_ebpf(struct packet_sock *po, char __user *data, | static int fanout_set_data_ebpf(struct packet_sock *po, sockptr_t data, | ||||||
| 				unsigned int len) | 				unsigned int len) | ||||||
| { | { | ||||||
| 	struct bpf_prog *new; | 	struct bpf_prog *new; | ||||||
| @ -1568,7 +1568,7 @@ static int fanout_set_data_ebpf(struct packet_sock *po, char __user *data, | |||||||
| 		return -EPERM; | 		return -EPERM; | ||||||
| 	if (len != sizeof(fd)) | 	if (len != sizeof(fd)) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	if (copy_from_user(&fd, data, len)) | 	if (copy_from_sockptr(&fd, data, len)) | ||||||
| 		return -EFAULT; | 		return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 	new = bpf_prog_get_type(fd, BPF_PROG_TYPE_SOCKET_FILTER); | 	new = bpf_prog_get_type(fd, BPF_PROG_TYPE_SOCKET_FILTER); | ||||||
| @ -1579,12 +1579,12 @@ static int fanout_set_data_ebpf(struct packet_sock *po, char __user *data, | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int fanout_set_data(struct packet_sock *po, char __user *data, | static int fanout_set_data(struct packet_sock *po, sockptr_t data, | ||||||
| 			   unsigned int len) | 			   unsigned int len) | ||||||
| { | { | ||||||
| 	switch (po->fanout->type) { | 	switch (po->fanout->type) { | ||||||
| 	case PACKET_FANOUT_CBPF: | 	case PACKET_FANOUT_CBPF: | ||||||
| 		return fanout_set_data_cbpf(po, USER_SOCKPTR(data), len); | 		return fanout_set_data_cbpf(po, data, len); | ||||||
| 	case PACKET_FANOUT_EBPF: | 	case PACKET_FANOUT_EBPF: | ||||||
| 		return fanout_set_data_ebpf(po, data, len); | 		return fanout_set_data_ebpf(po, data, len); | ||||||
| 	default: | 	default: | ||||||
| @ -3652,7 +3652,8 @@ static void packet_flush_mclist(struct sock *sk) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int | static int | ||||||
| packet_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen) | packet_setsockopt(struct socket *sock, int level, int optname, sockptr_t optval, | ||||||
|  | 		  unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| 	struct packet_sock *po = pkt_sk(sk); | 	struct packet_sock *po = pkt_sk(sk); | ||||||
| @ -3672,7 +3673,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv | |||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 		if (len > sizeof(mreq)) | 		if (len > sizeof(mreq)) | ||||||
| 			len = sizeof(mreq); | 			len = sizeof(mreq); | ||||||
| 		if (copy_from_user(&mreq, optval, len)) | 		if (copy_from_sockptr(&mreq, optval, len)) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| 		if (len < (mreq.mr_alen + offsetof(struct packet_mreq, mr_address))) | 		if (len < (mreq.mr_alen + offsetof(struct packet_mreq, mr_address))) | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| @ -3703,7 +3704,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv | |||||||
| 		if (optlen < len) { | 		if (optlen < len) { | ||||||
| 			ret = -EINVAL; | 			ret = -EINVAL; | ||||||
| 		} else { | 		} else { | ||||||
| 			if (copy_from_user(&req_u.req, optval, len)) | 			if (copy_from_sockptr(&req_u.req, optval, len)) | ||||||
| 				ret = -EFAULT; | 				ret = -EFAULT; | ||||||
| 			else | 			else | ||||||
| 				ret = packet_set_ring(sk, &req_u, 0, | 				ret = packet_set_ring(sk, &req_u, 0, | ||||||
| @ -3718,7 +3719,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv | |||||||
| 
 | 
 | ||||||
| 		if (optlen != sizeof(val)) | 		if (optlen != sizeof(val)) | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 		if (copy_from_user(&val, optval, sizeof(val))) | 		if (copy_from_sockptr(&val, optval, sizeof(val))) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 		pkt_sk(sk)->copy_thresh = val; | 		pkt_sk(sk)->copy_thresh = val; | ||||||
| @ -3730,7 +3731,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv | |||||||
| 
 | 
 | ||||||
| 		if (optlen != sizeof(val)) | 		if (optlen != sizeof(val)) | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 		if (copy_from_user(&val, optval, sizeof(val))) | 		if (copy_from_sockptr(&val, optval, sizeof(val))) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| 		switch (val) { | 		switch (val) { | ||||||
| 		case TPACKET_V1: | 		case TPACKET_V1: | ||||||
| @ -3756,7 +3757,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv | |||||||
| 
 | 
 | ||||||
| 		if (optlen != sizeof(val)) | 		if (optlen != sizeof(val)) | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 		if (copy_from_user(&val, optval, sizeof(val))) | 		if (copy_from_sockptr(&val, optval, sizeof(val))) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| 		if (val > INT_MAX) | 		if (val > INT_MAX) | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| @ -3776,7 +3777,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv | |||||||
| 
 | 
 | ||||||
| 		if (optlen != sizeof(val)) | 		if (optlen != sizeof(val)) | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 		if (copy_from_user(&val, optval, sizeof(val))) | 		if (copy_from_sockptr(&val, optval, sizeof(val))) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 		lock_sock(sk); | 		lock_sock(sk); | ||||||
| @ -3795,7 +3796,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv | |||||||
| 
 | 
 | ||||||
| 		if (optlen < sizeof(val)) | 		if (optlen < sizeof(val)) | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 		if (copy_from_user(&val, optval, sizeof(val))) | 		if (copy_from_sockptr(&val, optval, sizeof(val))) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 		lock_sock(sk); | 		lock_sock(sk); | ||||||
| @ -3809,7 +3810,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv | |||||||
| 
 | 
 | ||||||
| 		if (optlen < sizeof(val)) | 		if (optlen < sizeof(val)) | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 		if (copy_from_user(&val, optval, sizeof(val))) | 		if (copy_from_sockptr(&val, optval, sizeof(val))) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 		lock_sock(sk); | 		lock_sock(sk); | ||||||
| @ -3825,7 +3826,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv | |||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 		if (optlen < sizeof(val)) | 		if (optlen < sizeof(val)) | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 		if (copy_from_user(&val, optval, sizeof(val))) | 		if (copy_from_sockptr(&val, optval, sizeof(val))) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 		lock_sock(sk); | 		lock_sock(sk); | ||||||
| @ -3844,7 +3845,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv | |||||||
| 
 | 
 | ||||||
| 		if (optlen != sizeof(val)) | 		if (optlen != sizeof(val)) | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 		if (copy_from_user(&val, optval, sizeof(val))) | 		if (copy_from_sockptr(&val, optval, sizeof(val))) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 		po->tp_tstamp = val; | 		po->tp_tstamp = val; | ||||||
| @ -3856,7 +3857,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv | |||||||
| 
 | 
 | ||||||
| 		if (optlen != sizeof(val)) | 		if (optlen != sizeof(val)) | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 		if (copy_from_user(&val, optval, sizeof(val))) | 		if (copy_from_sockptr(&val, optval, sizeof(val))) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 		return fanout_add(sk, val & 0xffff, val >> 16); | 		return fanout_add(sk, val & 0xffff, val >> 16); | ||||||
| @ -3874,7 +3875,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv | |||||||
| 
 | 
 | ||||||
| 		if (optlen != sizeof(val)) | 		if (optlen != sizeof(val)) | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 		if (copy_from_user(&val, optval, sizeof(val))) | 		if (copy_from_sockptr(&val, optval, sizeof(val))) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| 		if (val < 0 || val > 1) | 		if (val < 0 || val > 1) | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| @ -3888,7 +3889,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv | |||||||
| 
 | 
 | ||||||
| 		if (optlen != sizeof(val)) | 		if (optlen != sizeof(val)) | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 		if (copy_from_user(&val, optval, sizeof(val))) | 		if (copy_from_sockptr(&val, optval, sizeof(val))) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 		lock_sock(sk); | 		lock_sock(sk); | ||||||
| @ -3907,7 +3908,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv | |||||||
| 
 | 
 | ||||||
| 		if (optlen != sizeof(val)) | 		if (optlen != sizeof(val)) | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 		if (copy_from_user(&val, optval, sizeof(val))) | 		if (copy_from_sockptr(&val, optval, sizeof(val))) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 		po->xmit = val ? packet_direct_xmit : dev_queue_xmit; | 		po->xmit = val ? packet_direct_xmit : dev_queue_xmit; | ||||||
|  | |||||||
| @ -975,7 +975,7 @@ static int pep_init(struct sock *sk) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int pep_setsockopt(struct sock *sk, int level, int optname, | static int pep_setsockopt(struct sock *sk, int level, int optname, | ||||||
| 				char __user *optval, unsigned int optlen) | 			  sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct pep_sock *pn = pep_sk(sk); | 	struct pep_sock *pn = pep_sk(sk); | ||||||
| 	int val = 0, err = 0; | 	int val = 0, err = 0; | ||||||
| @ -983,7 +983,7 @@ static int pep_setsockopt(struct sock *sk, int level, int optname, | |||||||
| 	if (level != SOL_PNPIPE) | 	if (level != SOL_PNPIPE) | ||||||
| 		return -ENOPROTOOPT; | 		return -ENOPROTOOPT; | ||||||
| 	if (optlen >= sizeof(int)) { | 	if (optlen >= sizeof(int)) { | ||||||
| 		if (get_user(val, (int __user *) optval)) | 		if (copy_from_sockptr(&val, optval, sizeof(int))) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -290,8 +290,7 @@ static int rds_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int rds_cancel_sent_to(struct rds_sock *rs, char __user *optval, | static int rds_cancel_sent_to(struct rds_sock *rs, sockptr_t optval, int len) | ||||||
| 			      int len) |  | ||||||
| { | { | ||||||
| 	struct sockaddr_in6 sin6; | 	struct sockaddr_in6 sin6; | ||||||
| 	struct sockaddr_in sin; | 	struct sockaddr_in sin; | ||||||
| @ -308,14 +307,15 @@ static int rds_cancel_sent_to(struct rds_sock *rs, char __user *optval, | |||||||
| 		goto out; | 		goto out; | ||||||
| 	} else if (len < sizeof(struct sockaddr_in6)) { | 	} else if (len < sizeof(struct sockaddr_in6)) { | ||||||
| 		/* Assume IPv4 */ | 		/* Assume IPv4 */ | ||||||
| 		if (copy_from_user(&sin, optval, sizeof(struct sockaddr_in))) { | 		if (copy_from_sockptr(&sin, optval, | ||||||
|  | 				sizeof(struct sockaddr_in))) { | ||||||
| 			ret = -EFAULT; | 			ret = -EFAULT; | ||||||
| 			goto out; | 			goto out; | ||||||
| 		} | 		} | ||||||
| 		ipv6_addr_set_v4mapped(sin.sin_addr.s_addr, &sin6.sin6_addr); | 		ipv6_addr_set_v4mapped(sin.sin_addr.s_addr, &sin6.sin6_addr); | ||||||
| 		sin6.sin6_port = sin.sin_port; | 		sin6.sin6_port = sin.sin_port; | ||||||
| 	} else { | 	} else { | ||||||
| 		if (copy_from_user(&sin6, optval, | 		if (copy_from_sockptr(&sin6, optval, | ||||||
| 				   sizeof(struct sockaddr_in6))) { | 				   sizeof(struct sockaddr_in6))) { | ||||||
| 			ret = -EFAULT; | 			ret = -EFAULT; | ||||||
| 			goto out; | 			goto out; | ||||||
| @ -327,21 +327,20 @@ out: | |||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int rds_set_bool_option(unsigned char *optvar, char __user *optval, | static int rds_set_bool_option(unsigned char *optvar, sockptr_t optval, | ||||||
| 			       int optlen) | 			       int optlen) | ||||||
| { | { | ||||||
| 	int value; | 	int value; | ||||||
| 
 | 
 | ||||||
| 	if (optlen < sizeof(int)) | 	if (optlen < sizeof(int)) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	if (get_user(value, (int __user *) optval)) | 	if (copy_from_sockptr(&value, optval, sizeof(int))) | ||||||
| 		return -EFAULT; | 		return -EFAULT; | ||||||
| 	*optvar = !!value; | 	*optvar = !!value; | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int rds_cong_monitor(struct rds_sock *rs, char __user *optval, | static int rds_cong_monitor(struct rds_sock *rs, sockptr_t optval, int optlen) | ||||||
| 			    int optlen) |  | ||||||
| { | { | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| @ -358,8 +357,7 @@ static int rds_cong_monitor(struct rds_sock *rs, char __user *optval, | |||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int rds_set_transport(struct rds_sock *rs, char __user *optval, | static int rds_set_transport(struct rds_sock *rs, sockptr_t optval, int optlen) | ||||||
| 			     int optlen) |  | ||||||
| { | { | ||||||
| 	int t_type; | 	int t_type; | ||||||
| 
 | 
 | ||||||
| @ -369,7 +367,7 @@ static int rds_set_transport(struct rds_sock *rs, char __user *optval, | |||||||
| 	if (optlen != sizeof(int)) | 	if (optlen != sizeof(int)) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 
 | 
 | ||||||
| 	if (copy_from_user(&t_type, (int __user *)optval, sizeof(t_type))) | 	if (copy_from_sockptr(&t_type, optval, sizeof(t_type))) | ||||||
| 		return -EFAULT; | 		return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 	if (t_type < 0 || t_type >= RDS_TRANS_COUNT) | 	if (t_type < 0 || t_type >= RDS_TRANS_COUNT) | ||||||
| @ -380,7 +378,7 @@ static int rds_set_transport(struct rds_sock *rs, char __user *optval, | |||||||
| 	return rs->rs_transport ? 0 : -ENOPROTOOPT; | 	return rs->rs_transport ? 0 : -ENOPROTOOPT; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int rds_enable_recvtstamp(struct sock *sk, char __user *optval, | static int rds_enable_recvtstamp(struct sock *sk, sockptr_t optval, | ||||||
| 				 int optlen, int optname) | 				 int optlen, int optname) | ||||||
| { | { | ||||||
| 	int val, valbool; | 	int val, valbool; | ||||||
| @ -388,7 +386,7 @@ static int rds_enable_recvtstamp(struct sock *sk, char __user *optval, | |||||||
| 	if (optlen != sizeof(int)) | 	if (optlen != sizeof(int)) | ||||||
| 		return -EFAULT; | 		return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 	if (get_user(val, (int __user *)optval)) | 	if (copy_from_sockptr(&val, optval, sizeof(int))) | ||||||
| 		return -EFAULT; | 		return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 	valbool = val ? 1 : 0; | 	valbool = val ? 1 : 0; | ||||||
| @ -404,7 +402,7 @@ static int rds_enable_recvtstamp(struct sock *sk, char __user *optval, | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int rds_recv_track_latency(struct rds_sock *rs, char __user *optval, | static int rds_recv_track_latency(struct rds_sock *rs, sockptr_t optval, | ||||||
| 				  int optlen) | 				  int optlen) | ||||||
| { | { | ||||||
| 	struct rds_rx_trace_so trace; | 	struct rds_rx_trace_so trace; | ||||||
| @ -413,7 +411,7 @@ static int rds_recv_track_latency(struct rds_sock *rs, char __user *optval, | |||||||
| 	if (optlen != sizeof(struct rds_rx_trace_so)) | 	if (optlen != sizeof(struct rds_rx_trace_so)) | ||||||
| 		return -EFAULT; | 		return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 	if (copy_from_user(&trace, optval, sizeof(trace))) | 	if (copy_from_sockptr(&trace, optval, sizeof(trace))) | ||||||
| 		return -EFAULT; | 		return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 	if (trace.rx_traces > RDS_MSG_RX_DGRAM_TRACE_MAX) | 	if (trace.rx_traces > RDS_MSG_RX_DGRAM_TRACE_MAX) | ||||||
| @ -432,7 +430,7 @@ static int rds_recv_track_latency(struct rds_sock *rs, char __user *optval, | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int rds_setsockopt(struct socket *sock, int level, int optname, | static int rds_setsockopt(struct socket *sock, int level, int optname, | ||||||
| 			  char __user *optval, unsigned int optlen) | 			  sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct rds_sock *rs = rds_sk_to_rs(sock->sk); | 	struct rds_sock *rs = rds_sk_to_rs(sock->sk); | ||||||
| 	int ret; | 	int ret; | ||||||
|  | |||||||
| @ -353,21 +353,20 @@ out: | |||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int rds_get_mr(struct rds_sock *rs, char __user *optval, int optlen) | int rds_get_mr(struct rds_sock *rs, sockptr_t optval, int optlen) | ||||||
| { | { | ||||||
| 	struct rds_get_mr_args args; | 	struct rds_get_mr_args args; | ||||||
| 
 | 
 | ||||||
| 	if (optlen != sizeof(struct rds_get_mr_args)) | 	if (optlen != sizeof(struct rds_get_mr_args)) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 
 | 
 | ||||||
| 	if (copy_from_user(&args, (struct rds_get_mr_args __user *)optval, | 	if (copy_from_sockptr(&args, optval, sizeof(struct rds_get_mr_args))) | ||||||
| 			   sizeof(struct rds_get_mr_args))) |  | ||||||
| 		return -EFAULT; | 		return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 	return __rds_rdma_map(rs, &args, NULL, NULL, NULL); | 	return __rds_rdma_map(rs, &args, NULL, NULL, NULL); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int rds_get_mr_for_dest(struct rds_sock *rs, char __user *optval, int optlen) | int rds_get_mr_for_dest(struct rds_sock *rs, sockptr_t optval, int optlen) | ||||||
| { | { | ||||||
| 	struct rds_get_mr_for_dest_args args; | 	struct rds_get_mr_for_dest_args args; | ||||||
| 	struct rds_get_mr_args new_args; | 	struct rds_get_mr_args new_args; | ||||||
| @ -375,7 +374,7 @@ int rds_get_mr_for_dest(struct rds_sock *rs, char __user *optval, int optlen) | |||||||
| 	if (optlen != sizeof(struct rds_get_mr_for_dest_args)) | 	if (optlen != sizeof(struct rds_get_mr_for_dest_args)) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 
 | 
 | ||||||
| 	if (copy_from_user(&args, (struct rds_get_mr_for_dest_args __user *)optval, | 	if (copy_from_sockptr(&args, optval, | ||||||
| 			   sizeof(struct rds_get_mr_for_dest_args))) | 			   sizeof(struct rds_get_mr_for_dest_args))) | ||||||
| 		return -EFAULT; | 		return -EFAULT; | ||||||
| 
 | 
 | ||||||
| @ -394,7 +393,7 @@ int rds_get_mr_for_dest(struct rds_sock *rs, char __user *optval, int optlen) | |||||||
| /*
 | /*
 | ||||||
|  * Free the MR indicated by the given R_Key |  * Free the MR indicated by the given R_Key | ||||||
|  */ |  */ | ||||||
| int rds_free_mr(struct rds_sock *rs, char __user *optval, int optlen) | int rds_free_mr(struct rds_sock *rs, sockptr_t optval, int optlen) | ||||||
| { | { | ||||||
| 	struct rds_free_mr_args args; | 	struct rds_free_mr_args args; | ||||||
| 	struct rds_mr *mr; | 	struct rds_mr *mr; | ||||||
| @ -403,8 +402,7 @@ int rds_free_mr(struct rds_sock *rs, char __user *optval, int optlen) | |||||||
| 	if (optlen != sizeof(struct rds_free_mr_args)) | 	if (optlen != sizeof(struct rds_free_mr_args)) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 
 | 
 | ||||||
| 	if (copy_from_user(&args, (struct rds_free_mr_args __user *)optval, | 	if (copy_from_sockptr(&args, optval, sizeof(struct rds_free_mr_args))) | ||||||
| 			   sizeof(struct rds_free_mr_args))) |  | ||||||
| 		return -EFAULT; | 		return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 	/* Special case - a null cookie means flush all unused MRs */ | 	/* Special case - a null cookie means flush all unused MRs */ | ||||||
|  | |||||||
| @ -924,9 +924,9 @@ int rds_send_pong(struct rds_conn_path *cp, __be16 dport); | |||||||
| 
 | 
 | ||||||
| /* rdma.c */ | /* rdma.c */ | ||||||
| void rds_rdma_unuse(struct rds_sock *rs, u32 r_key, int force); | void rds_rdma_unuse(struct rds_sock *rs, u32 r_key, int force); | ||||||
| int rds_get_mr(struct rds_sock *rs, char __user *optval, int optlen); | int rds_get_mr(struct rds_sock *rs, sockptr_t optval, int optlen); | ||||||
| int rds_get_mr_for_dest(struct rds_sock *rs, char __user *optval, int optlen); | int rds_get_mr_for_dest(struct rds_sock *rs, sockptr_t optval, int optlen); | ||||||
| int rds_free_mr(struct rds_sock *rs, char __user *optval, int optlen); | int rds_free_mr(struct rds_sock *rs, sockptr_t optval, int optlen); | ||||||
| void rds_rdma_drop_keys(struct rds_sock *rs); | void rds_rdma_drop_keys(struct rds_sock *rs); | ||||||
| int rds_rdma_extra_size(struct rds_rdma_args *args, | int rds_rdma_extra_size(struct rds_rdma_args *args, | ||||||
| 			struct rds_iov_vector *iov); | 			struct rds_iov_vector *iov); | ||||||
|  | |||||||
| @ -365,7 +365,7 @@ void rose_destroy_socket(struct sock *sk) | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| static int rose_setsockopt(struct socket *sock, int level, int optname, | static int rose_setsockopt(struct socket *sock, int level, int optname, | ||||||
| 	char __user *optval, unsigned int optlen) | 		sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| 	struct rose_sock *rose = rose_sk(sk); | 	struct rose_sock *rose = rose_sk(sk); | ||||||
| @ -377,7 +377,7 @@ static int rose_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 	if (optlen < sizeof(int)) | 	if (optlen < sizeof(int)) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 
 | 
 | ||||||
| 	if (get_user(opt, (int __user *)optval)) | 	if (copy_from_sockptr(&opt, optval, sizeof(int))) | ||||||
| 		return -EFAULT; | 		return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 	switch (optname) { | 	switch (optname) { | ||||||
|  | |||||||
| @ -588,7 +588,7 @@ EXPORT_SYMBOL(rxrpc_sock_set_min_security_level); | |||||||
|  * set RxRPC socket options |  * set RxRPC socket options | ||||||
|  */ |  */ | ||||||
| static int rxrpc_setsockopt(struct socket *sock, int level, int optname, | static int rxrpc_setsockopt(struct socket *sock, int level, int optname, | ||||||
| 			    char __user *optval, unsigned int optlen) | 			    sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct rxrpc_sock *rx = rxrpc_sk(sock->sk); | 	struct rxrpc_sock *rx = rxrpc_sk(sock->sk); | ||||||
| 	unsigned int min_sec_level; | 	unsigned int min_sec_level; | ||||||
| @ -639,8 +639,8 @@ static int rxrpc_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 			ret = -EISCONN; | 			ret = -EISCONN; | ||||||
| 			if (rx->sk.sk_state != RXRPC_UNBOUND) | 			if (rx->sk.sk_state != RXRPC_UNBOUND) | ||||||
| 				goto error; | 				goto error; | ||||||
| 			ret = get_user(min_sec_level, | 			ret = copy_from_sockptr(&min_sec_level, optval, | ||||||
| 				       (unsigned int __user *) optval); | 				       sizeof(unsigned int)); | ||||||
| 			if (ret < 0) | 			if (ret < 0) | ||||||
| 				goto error; | 				goto error; | ||||||
| 			ret = -EINVAL; | 			ret = -EINVAL; | ||||||
| @ -658,7 +658,7 @@ static int rxrpc_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 			if (rx->sk.sk_state != RXRPC_SERVER_BOUND2) | 			if (rx->sk.sk_state != RXRPC_SERVER_BOUND2) | ||||||
| 				goto error; | 				goto error; | ||||||
| 			ret = -EFAULT; | 			ret = -EFAULT; | ||||||
| 			if (copy_from_user(service_upgrade, optval, | 			if (copy_from_sockptr(service_upgrade, optval, | ||||||
| 					   sizeof(service_upgrade)) != 0) | 					   sizeof(service_upgrade)) != 0) | ||||||
| 				goto error; | 				goto error; | ||||||
| 			ret = -EINVAL; | 			ret = -EINVAL; | ||||||
|  | |||||||
| @ -909,8 +909,8 @@ extern const struct rxrpc_security rxrpc_no_security; | |||||||
| extern struct key_type key_type_rxrpc; | extern struct key_type key_type_rxrpc; | ||||||
| extern struct key_type key_type_rxrpc_s; | extern struct key_type key_type_rxrpc_s; | ||||||
| 
 | 
 | ||||||
| int rxrpc_request_key(struct rxrpc_sock *, char __user *, int); | int rxrpc_request_key(struct rxrpc_sock *, sockptr_t , int); | ||||||
| int rxrpc_server_keyring(struct rxrpc_sock *, char __user *, int); | int rxrpc_server_keyring(struct rxrpc_sock *, sockptr_t, int); | ||||||
| int rxrpc_get_server_data_key(struct rxrpc_connection *, const void *, time64_t, | int rxrpc_get_server_data_key(struct rxrpc_connection *, const void *, time64_t, | ||||||
| 			      u32); | 			      u32); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -896,7 +896,7 @@ static void rxrpc_describe(const struct key *key, struct seq_file *m) | |||||||
| /*
 | /*
 | ||||||
|  * grab the security key for a socket |  * grab the security key for a socket | ||||||
|  */ |  */ | ||||||
| int rxrpc_request_key(struct rxrpc_sock *rx, char __user *optval, int optlen) | int rxrpc_request_key(struct rxrpc_sock *rx, sockptr_t optval, int optlen) | ||||||
| { | { | ||||||
| 	struct key *key; | 	struct key *key; | ||||||
| 	char *description; | 	char *description; | ||||||
| @ -906,7 +906,7 @@ int rxrpc_request_key(struct rxrpc_sock *rx, char __user *optval, int optlen) | |||||||
| 	if (optlen <= 0 || optlen > PAGE_SIZE - 1) | 	if (optlen <= 0 || optlen > PAGE_SIZE - 1) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 
 | 
 | ||||||
| 	description = memdup_user_nul(optval, optlen); | 	description = memdup_sockptr_nul(optval, optlen); | ||||||
| 	if (IS_ERR(description)) | 	if (IS_ERR(description)) | ||||||
| 		return PTR_ERR(description); | 		return PTR_ERR(description); | ||||||
| 
 | 
 | ||||||
| @ -926,8 +926,7 @@ int rxrpc_request_key(struct rxrpc_sock *rx, char __user *optval, int optlen) | |||||||
| /*
 | /*
 | ||||||
|  * grab the security keyring for a server socket |  * grab the security keyring for a server socket | ||||||
|  */ |  */ | ||||||
| int rxrpc_server_keyring(struct rxrpc_sock *rx, char __user *optval, | int rxrpc_server_keyring(struct rxrpc_sock *rx, sockptr_t optval, int optlen) | ||||||
| 			 int optlen) |  | ||||||
| { | { | ||||||
| 	struct key *key; | 	struct key *key; | ||||||
| 	char *description; | 	char *description; | ||||||
| @ -937,7 +936,7 @@ int rxrpc_server_keyring(struct rxrpc_sock *rx, char __user *optval, | |||||||
| 	if (optlen <= 0 || optlen > PAGE_SIZE - 1) | 	if (optlen <= 0 || optlen > PAGE_SIZE - 1) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 
 | 
 | ||||||
| 	description = memdup_user_nul(optval, optlen); | 	description = memdup_sockptr_nul(optval, optlen); | ||||||
| 	if (IS_ERR(description)) | 	if (IS_ERR(description)) | ||||||
| 		return PTR_ERR(description); | 		return PTR_ERR(description); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -4429,7 +4429,7 @@ out: | |||||||
|  *   optlen  - the size of the buffer. |  *   optlen  - the size of the buffer. | ||||||
|  */ |  */ | ||||||
| static int sctp_setsockopt(struct sock *sk, int level, int optname, | static int sctp_setsockopt(struct sock *sk, int level, int optname, | ||||||
| 			   char __user *optval, unsigned int optlen) | 			   sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	void *kopt = NULL; | 	void *kopt = NULL; | ||||||
| 	int retval = 0; | 	int retval = 0; | ||||||
| @ -4449,7 +4449,7 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname, | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (optlen > 0) { | 	if (optlen > 0) { | ||||||
| 		kopt = memdup_user(optval, optlen); | 		kopt = memdup_sockptr(optval, optlen); | ||||||
| 		if (IS_ERR(kopt)) | 		if (IS_ERR(kopt)) | ||||||
| 			return PTR_ERR(kopt); | 			return PTR_ERR(kopt); | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -1731,7 +1731,7 @@ out: | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int smc_setsockopt(struct socket *sock, int level, int optname, | static int smc_setsockopt(struct socket *sock, int level, int optname, | ||||||
| 			  char __user *optval, unsigned int optlen) | 			  sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| 	struct smc_sock *smc; | 	struct smc_sock *smc; | ||||||
| @ -1754,7 +1754,7 @@ static int smc_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 
 | 
 | ||||||
| 	if (optlen < sizeof(int)) | 	if (optlen < sizeof(int)) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	if (get_user(val, (int __user *)optval)) | 	if (copy_from_sockptr(&val, optval, sizeof(int))) | ||||||
| 		return -EFAULT; | 		return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 	lock_sock(sk); | 	lock_sock(sk); | ||||||
|  | |||||||
							
								
								
									
										23
									
								
								net/socket.c
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								net/socket.c
									
									
									
									
									
								
							| @ -2094,10 +2094,10 @@ static bool sock_use_custom_sol_socket(const struct socket *sock) | |||||||
|  *	Set a socket option. Because we don't know the option lengths we have |  *	Set a socket option. Because we don't know the option lengths we have | ||||||
|  *	to pass the user mode parameter for the protocols to sort out. |  *	to pass the user mode parameter for the protocols to sort out. | ||||||
|  */ |  */ | ||||||
| int __sys_setsockopt(int fd, int level, int optname, char __user *optval, | int __sys_setsockopt(int fd, int level, int optname, char __user *user_optval, | ||||||
| 		int optlen) | 		int optlen) | ||||||
| { | { | ||||||
| 	mm_segment_t oldfs = get_fs(); | 	sockptr_t optval = USER_SOCKPTR(user_optval); | ||||||
| 	char *kernel_optval = NULL; | 	char *kernel_optval = NULL; | ||||||
| 	int err, fput_needed; | 	int err, fput_needed; | ||||||
| 	struct socket *sock; | 	struct socket *sock; | ||||||
| @ -2115,7 +2115,7 @@ int __sys_setsockopt(int fd, int level, int optname, char __user *optval, | |||||||
| 
 | 
 | ||||||
| 	if (!in_compat_syscall()) | 	if (!in_compat_syscall()) | ||||||
| 		err = BPF_CGROUP_RUN_PROG_SETSOCKOPT(sock->sk, &level, &optname, | 		err = BPF_CGROUP_RUN_PROG_SETSOCKOPT(sock->sk, &level, &optname, | ||||||
| 						     optval, &optlen, | 						     user_optval, &optlen, | ||||||
| 						     &kernel_optval); | 						     &kernel_optval); | ||||||
| 	if (err < 0) | 	if (err < 0) | ||||||
| 		goto out_put; | 		goto out_put; | ||||||
| @ -2124,25 +2124,16 @@ int __sys_setsockopt(int fd, int level, int optname, char __user *optval, | |||||||
| 		goto out_put; | 		goto out_put; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (kernel_optval) { | 	if (kernel_optval) | ||||||
| 		set_fs(KERNEL_DS); | 		optval = KERNEL_SOCKPTR(kernel_optval); | ||||||
| 		optval = (char __user __force *)kernel_optval; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (level == SOL_SOCKET && !sock_use_custom_sol_socket(sock)) | 	if (level == SOL_SOCKET && !sock_use_custom_sol_socket(sock)) | ||||||
| 		err = sock_setsockopt(sock, level, optname, | 		err = sock_setsockopt(sock, level, optname, optval, optlen); | ||||||
| 				      USER_SOCKPTR(optval), optlen); |  | ||||||
| 	else if (unlikely(!sock->ops->setsockopt)) | 	else if (unlikely(!sock->ops->setsockopt)) | ||||||
| 		err = -EOPNOTSUPP; | 		err = -EOPNOTSUPP; | ||||||
| 	else | 	else | ||||||
| 		err = sock->ops->setsockopt(sock, level, optname, optval, | 		err = sock->ops->setsockopt(sock, level, optname, optval, | ||||||
| 					    optlen); | 					    optlen); | ||||||
| 
 | 	kfree(kernel_optval); | ||||||
| 	if (kernel_optval) { |  | ||||||
| 		set_fs(oldfs); |  | ||||||
| 		kfree(kernel_optval); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| out_put: | out_put: | ||||||
| 	fput_light(sock->file, fput_needed); | 	fput_light(sock->file, fput_needed); | ||||||
| 	return err; | 	return err; | ||||||
|  | |||||||
| @ -3103,7 +3103,7 @@ static int tipc_sk_leave(struct tipc_sock *tsk) | |||||||
|  * Returns 0 on success, errno otherwise |  * Returns 0 on success, errno otherwise | ||||||
|  */ |  */ | ||||||
| static int tipc_setsockopt(struct socket *sock, int lvl, int opt, | static int tipc_setsockopt(struct socket *sock, int lvl, int opt, | ||||||
| 			   char __user *ov, unsigned int ol) | 			   sockptr_t ov, unsigned int ol) | ||||||
| { | { | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| 	struct tipc_sock *tsk = tipc_sk(sk); | 	struct tipc_sock *tsk = tipc_sk(sk); | ||||||
| @ -3124,17 +3124,17 @@ static int tipc_setsockopt(struct socket *sock, int lvl, int opt, | |||||||
| 	case TIPC_NODELAY: | 	case TIPC_NODELAY: | ||||||
| 		if (ol < sizeof(value)) | 		if (ol < sizeof(value)) | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 		if (get_user(value, (u32 __user *)ov)) | 		if (copy_from_sockptr(&value, ov, sizeof(u32))) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| 		break; | 		break; | ||||||
| 	case TIPC_GROUP_JOIN: | 	case TIPC_GROUP_JOIN: | ||||||
| 		if (ol < sizeof(mreq)) | 		if (ol < sizeof(mreq)) | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 		if (copy_from_user(&mreq, ov, sizeof(mreq))) | 		if (copy_from_sockptr(&mreq, ov, sizeof(mreq))) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| 		break; | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		if (ov || ol) | 		if (!sockptr_is_null(ov) || ol) | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -450,7 +450,7 @@ static int tls_getsockopt(struct sock *sk, int level, int optname, | |||||||
| 	return do_tls_getsockopt(sk, optname, optval, optlen); | 	return do_tls_getsockopt(sk, optname, optval, optlen); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int do_tls_setsockopt_conf(struct sock *sk, char __user *optval, | static int do_tls_setsockopt_conf(struct sock *sk, sockptr_t optval, | ||||||
| 				  unsigned int optlen, int tx) | 				  unsigned int optlen, int tx) | ||||||
| { | { | ||||||
| 	struct tls_crypto_info *crypto_info; | 	struct tls_crypto_info *crypto_info; | ||||||
| @ -460,7 +460,7 @@ static int do_tls_setsockopt_conf(struct sock *sk, char __user *optval, | |||||||
| 	int rc = 0; | 	int rc = 0; | ||||||
| 	int conf; | 	int conf; | ||||||
| 
 | 
 | ||||||
| 	if (!optval || (optlen < sizeof(*crypto_info))) { | 	if (sockptr_is_null(optval) || (optlen < sizeof(*crypto_info))) { | ||||||
| 		rc = -EINVAL; | 		rc = -EINVAL; | ||||||
| 		goto out; | 		goto out; | ||||||
| 	} | 	} | ||||||
| @ -479,7 +479,7 @@ static int do_tls_setsockopt_conf(struct sock *sk, char __user *optval, | |||||||
| 		goto out; | 		goto out; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	rc = copy_from_user(crypto_info, optval, sizeof(*crypto_info)); | 	rc = copy_from_sockptr(crypto_info, optval, sizeof(*crypto_info)); | ||||||
| 	if (rc) { | 	if (rc) { | ||||||
| 		rc = -EFAULT; | 		rc = -EFAULT; | ||||||
| 		goto err_crypto_info; | 		goto err_crypto_info; | ||||||
| @ -522,8 +522,9 @@ static int do_tls_setsockopt_conf(struct sock *sk, char __user *optval, | |||||||
| 		goto err_crypto_info; | 		goto err_crypto_info; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	rc = copy_from_user(crypto_info + 1, optval + sizeof(*crypto_info), | 	sockptr_advance(optval, sizeof(*crypto_info)); | ||||||
| 			    optlen - sizeof(*crypto_info)); | 	rc = copy_from_sockptr(crypto_info + 1, optval, | ||||||
|  | 			       optlen - sizeof(*crypto_info)); | ||||||
| 	if (rc) { | 	if (rc) { | ||||||
| 		rc = -EFAULT; | 		rc = -EFAULT; | ||||||
| 		goto err_crypto_info; | 		goto err_crypto_info; | ||||||
| @ -579,8 +580,8 @@ out: | |||||||
| 	return rc; | 	return rc; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int do_tls_setsockopt(struct sock *sk, int optname, | static int do_tls_setsockopt(struct sock *sk, int optname, sockptr_t optval, | ||||||
| 			     char __user *optval, unsigned int optlen) | 			     unsigned int optlen) | ||||||
| { | { | ||||||
| 	int rc = 0; | 	int rc = 0; | ||||||
| 
 | 
 | ||||||
| @ -600,7 +601,7 @@ static int do_tls_setsockopt(struct sock *sk, int optname, | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int tls_setsockopt(struct sock *sk, int level, int optname, | static int tls_setsockopt(struct sock *sk, int level, int optname, | ||||||
| 			  char __user *optval, unsigned int optlen) | 			  sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct tls_context *ctx = tls_get_ctx(sk); | 	struct tls_context *ctx = tls_get_ctx(sk); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1517,7 +1517,7 @@ static void vsock_update_buffer_size(struct vsock_sock *vsk, | |||||||
| static int vsock_stream_setsockopt(struct socket *sock, | static int vsock_stream_setsockopt(struct socket *sock, | ||||||
| 				   int level, | 				   int level, | ||||||
| 				   int optname, | 				   int optname, | ||||||
| 				   char __user *optval, | 				   sockptr_t optval, | ||||||
| 				   unsigned int optlen) | 				   unsigned int optlen) | ||||||
| { | { | ||||||
| 	int err; | 	int err; | ||||||
| @ -1535,7 +1535,7 @@ static int vsock_stream_setsockopt(struct socket *sock, | |||||||
| 			err = -EINVAL;			  \ | 			err = -EINVAL;			  \ | ||||||
| 			goto exit;			  \ | 			goto exit;			  \ | ||||||
| 		}					  \ | 		}					  \ | ||||||
| 		if (copy_from_user(&_v, optval, sizeof(_v)) != 0) {	\ | 		if (copy_from_sockptr(&_v, optval, sizeof(_v)) != 0) {	\ | ||||||
| 			err = -EFAULT;					\ | 			err = -EFAULT;					\ | ||||||
| 			goto exit;					\ | 			goto exit;					\ | ||||||
| 		}							\ | 		}							\ | ||||||
|  | |||||||
| @ -431,7 +431,7 @@ void x25_destroy_socket_from_timer(struct sock *sk) | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| static int x25_setsockopt(struct socket *sock, int level, int optname, | static int x25_setsockopt(struct socket *sock, int level, int optname, | ||||||
| 			  char __user *optval, unsigned int optlen) | 			  sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	int opt; | 	int opt; | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| @ -445,7 +445,7 @@ static int x25_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 		goto out; | 		goto out; | ||||||
| 
 | 
 | ||||||
| 	rc = -EFAULT; | 	rc = -EFAULT; | ||||||
| 	if (get_user(opt, (int __user *)optval)) | 	if (copy_from_sockptr(&opt, optval, sizeof(int))) | ||||||
| 		goto out; | 		goto out; | ||||||
| 
 | 
 | ||||||
| 	if (opt) | 	if (opt) | ||||||
|  | |||||||
| @ -702,7 +702,7 @@ struct xdp_umem_reg_v1 { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static int xsk_setsockopt(struct socket *sock, int level, int optname, | static int xsk_setsockopt(struct socket *sock, int level, int optname, | ||||||
| 			  char __user *optval, unsigned int optlen) | 			  sockptr_t optval, unsigned int optlen) | ||||||
| { | { | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| 	struct xdp_sock *xs = xdp_sk(sk); | 	struct xdp_sock *xs = xdp_sk(sk); | ||||||
| @ -720,7 +720,7 @@ static int xsk_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 
 | 
 | ||||||
| 		if (optlen < sizeof(entries)) | 		if (optlen < sizeof(entries)) | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 		if (copy_from_user(&entries, optval, sizeof(entries))) | 		if (copy_from_sockptr(&entries, optval, sizeof(entries))) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 		mutex_lock(&xs->mutex); | 		mutex_lock(&xs->mutex); | ||||||
| @ -747,7 +747,7 @@ static int xsk_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 		else if (optlen < sizeof(mr)) | 		else if (optlen < sizeof(mr)) | ||||||
| 			mr_size = sizeof(struct xdp_umem_reg_v1); | 			mr_size = sizeof(struct xdp_umem_reg_v1); | ||||||
| 
 | 
 | ||||||
| 		if (copy_from_user(&mr, optval, mr_size)) | 		if (copy_from_sockptr(&mr, optval, mr_size)) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 		mutex_lock(&xs->mutex); | 		mutex_lock(&xs->mutex); | ||||||
| @ -774,7 +774,7 @@ static int xsk_setsockopt(struct socket *sock, int level, int optname, | |||||||
| 		struct xsk_queue **q; | 		struct xsk_queue **q; | ||||||
| 		int entries; | 		int entries; | ||||||
| 
 | 
 | ||||||
| 		if (copy_from_user(&entries, optval, sizeof(entries))) | 		if (copy_from_sockptr(&entries, optval, sizeof(entries))) | ||||||
| 			return -EFAULT; | 			return -EFAULT; | ||||||
| 
 | 
 | ||||||
| 		mutex_lock(&xs->mutex); | 		mutex_lock(&xs->mutex); | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user