lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <deaedc6d-edde-68da-50e8-6474ca818191@datenfreihafen.org>
Date:   Mon, 20 Jul 2020 16:19:38 +0200
From:   Stefan Schmidt <stefan@...enfreihafen.org>
To:     Christoph Hellwig <hch@....de>,
        "David S. Miller" <davem@...emloft.net>,
        Jakub Kicinski <kuba@...nel.org>,
        Alexei Starovoitov <ast@...nel.org>,
        Daniel Borkmann <daniel@...earbox.net>,
        Alexey Kuznetsov <kuznet@....inr.ac.ru>,
        Hideaki YOSHIFUJI <yoshfuji@...ux-ipv6.org>,
        Eric Dumazet <edumazet@...gle.com>
Cc:     linux-crypto@...r.kernel.org, linux-kernel@...r.kernel.org,
        netdev@...r.kernel.org, bpf@...r.kernel.org,
        netfilter-devel@...r.kernel.org, coreteam@...filter.org,
        linux-sctp@...r.kernel.org, linux-hams@...r.kernel.org,
        linux-bluetooth@...r.kernel.org, bridge@...ts.linux-foundation.org,
        linux-can@...r.kernel.org, dccp@...r.kernel.org,
        linux-decnet-user@...ts.sourceforge.net,
        linux-wpan@...r.kernel.org, linux-s390@...r.kernel.org,
        mptcp@...ts.01.org, lvs-devel@...r.kernel.org,
        rds-devel@....oracle.com, linux-afs@...ts.infradead.org,
        tipc-discussion@...ts.sourceforge.net, linux-x25@...r.kernel.org
Subject: Re: [PATCH 24/24] net: pass a sockptr_t into ->setsockopt

Hello.

On 20.07.20 14:47, Christoph Hellwig wrote:
> 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@....de>
> ---
>   crypto/af_alg.c                           |  7 ++--
>   drivers/crypto/chelsio/chtls/chtls_main.c | 18 ++++++-----
>   drivers/isdn/mISDN/socket.c               |  4 +--
>   include/linux/net.h                       |  4 ++-
>   include/net/inet_connection_sock.h        |  3 +-
>   include/net/ip.h                          |  2 +-
>   include/net/ipv6.h                        |  4 +--
>   include/net/sctp/structs.h                |  2 +-
>   include/net/sock.h                        |  4 +--
>   include/net/tcp.h                         |  4 +--
>   net/atm/common.c                          |  6 ++--
>   net/atm/common.h                          |  2 +-
>   net/atm/pvc.c                             |  2 +-
>   net/atm/svc.c                             |  6 ++--
>   net/ax25/af_ax25.c                        |  6 ++--
>   net/bluetooth/hci_sock.c                  |  8 ++---
>   net/bluetooth/l2cap_sock.c                | 22 ++++++-------
>   net/bluetooth/rfcomm/sock.c               | 12 ++++---
>   net/bluetooth/sco.c                       |  6 ++--
>   net/caif/caif_socket.c                    |  8 ++---
>   net/can/j1939/socket.c                    | 12 +++----
>   net/can/raw.c                             | 16 +++++-----
>   net/core/sock.c                           |  2 +-
>   net/dccp/dccp.h                           |  2 +-
>   net/dccp/proto.c                          | 20 ++++++------
>   net/decnet/af_decnet.c                    | 16 ++++++----
>   net/ieee802154/socket.c                   |  6 ++--
>   net/ipv4/ip_sockglue.c                    | 13 +++-----
>   net/ipv4/raw.c                            |  8 ++---
>   net/ipv4/tcp.c                            |  5 ++-
>   net/ipv4/udp.c                            |  6 ++--
>   net/ipv4/udp_impl.h                       |  4 +--
>   net/ipv6/ipv6_sockglue.c                  | 10 +++---
>   net/ipv6/raw.c                            | 10 +++---
>   net/ipv6/udp.c                            |  6 ++--
>   net/ipv6/udp_impl.h                       |  4 +--
>   net/iucv/af_iucv.c                        |  4 +--
>   net/kcm/kcmsock.c                         |  6 ++--
>   net/l2tp/l2tp_ppp.c                       |  4 +--
>   net/llc/af_llc.c                          |  4 +--
>   net/mptcp/protocol.c                      | 14 ++++----
>   net/netlink/af_netlink.c                  |  4 +--
>   net/netrom/af_netrom.c                    |  4 +--
>   net/nfc/llcp_sock.c                       |  6 ++--
>   net/packet/af_packet.c                    | 39 ++++++++++++-----------
>   net/phonet/pep.c                          |  4 +--
>   net/rds/af_rds.c                          | 30 ++++++++---------
>   net/rds/rdma.c                            | 14 ++++----
>   net/rds/rds.h                             |  6 ++--
>   net/rose/af_rose.c                        |  4 +--
>   net/rxrpc/af_rxrpc.c                      |  8 ++---
>   net/rxrpc/ar-internal.h                   |  4 +--
>   net/rxrpc/key.c                           |  9 +++---
>   net/sctp/socket.c                         |  4 +--
>   net/smc/af_smc.c                          |  4 +--
>   net/socket.c                              | 23 ++++---------
>   net/tipc/socket.c                         |  8 ++---
>   net/tls/tls_main.c                        | 17 +++++-----
>   net/vmw_vsock/af_vsock.c                  |  4 +--
>   net/x25/af_x25.c                          |  4 +--
>   net/xdp/xsk.c                             |  8 ++---
>   61 files changed, 248 insertions(+), 258 deletions(-)
> 
> diff --git a/crypto/af_alg.c b/crypto/af_alg.c
> index 29f71428520b4b..892242a42c3ec9 100644
> --- a/crypto/af_alg.c
> +++ b/crypto/af_alg.c
> @@ -197,8 +197,7 @@ static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
>   	return err;
>   }
>   
> -static int alg_setkey(struct sock *sk, char __user *ukey,
> -		      unsigned int keylen)
> +static int alg_setkey(struct sock *sk, sockptr_t ukey, unsigned int keylen)
>   {
>   	struct alg_sock *ask = alg_sk(sk);
>   	const struct af_alg_type *type = ask->type;
> @@ -210,7 +209,7 @@ static int alg_setkey(struct sock *sk, char __user *ukey,
>   		return -ENOMEM;
>   
>   	err = -EFAULT;
> -	if (copy_from_user(key, ukey, keylen))
> +	if (copy_from_sockptr(key, ukey, keylen))
>   		goto out;
>   
>   	err = type->setkey(ask->private, key, keylen);
> @@ -222,7 +221,7 @@ static int alg_setkey(struct sock *sk, char __user *ukey,
>   }
>   
>   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 alg_sock *ask = alg_sk(sk);
> diff --git a/drivers/crypto/chelsio/chtls/chtls_main.c b/drivers/crypto/chelsio/chtls/chtls_main.c
> index d98b89d0fa6eeb..c3058dcdb33c5c 100644
> --- a/drivers/crypto/chelsio/chtls/chtls_main.c
> +++ b/drivers/crypto/chelsio/chtls/chtls_main.c
> @@ -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,
> -			       char __user *optval, unsigned int optlen)
> +			       sockptr_t optval, unsigned int optlen)
>   {
>   	struct tls_crypto_info *crypto_info, tmp_crypto_info;
>   	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);
>   
> -	if (!optval || optlen < sizeof(*crypto_info)) {
> +	if (sockptr_is_null(optval) || optlen < sizeof(*crypto_info)) {
>   		rc = -EINVAL;
>   		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) {
>   		rc = -EFAULT;
>   		goto out;
> @@ -525,8 +525,9 @@ static int do_chtls_setsockopt(struct sock *sk, int optname,
>   		/* Obtain version and type from previous copy */
>   		crypto_info[0] = tmp_crypto_info;
>   		/* Now copy the following data */
> -		rc = copy_from_user((char *)crypto_info + sizeof(*crypto_info),
> -				optval + sizeof(*crypto_info),
> +		sockptr_advance(optval, sizeof(*crypto_info));
> +		rc = copy_from_sockptr((char *)crypto_info + sizeof(*crypto_info),
> +				optval,
>   				sizeof(struct tls12_crypto_info_aes_gcm_128)
>   				- sizeof(*crypto_info));
>   
> @@ -541,8 +542,9 @@ static int do_chtls_setsockopt(struct sock *sk, int optname,
>   	}
>   	case TLS_CIPHER_AES_GCM_256: {
>   		crypto_info[0] = tmp_crypto_info;
> -		rc = copy_from_user((char *)crypto_info + sizeof(*crypto_info),
> -				    optval + sizeof(*crypto_info),
> +		sockptr_advance(optval, sizeof(*crypto_info));
> +		rc = copy_from_sockptr((char *)crypto_info + sizeof(*crypto_info),
> +				    optval,
>   				sizeof(struct tls12_crypto_info_aes_gcm_256)
>   				- sizeof(*crypto_info));
>   
> @@ -565,7 +567,7 @@ static int do_chtls_setsockopt(struct sock *sk, 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);
>   
> diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c
> index 1b2b91479107bc..2835daae9e9f3a 100644
> --- a/drivers/isdn/mISDN/socket.c
> +++ b/drivers/isdn/mISDN/socket.c
> @@ -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,
> -				char __user *optval, unsigned int len)
> +				sockptr_t optval, unsigned int len)
>   {
>   	struct sock *sk = sock->sk;
>   	int err = 0, opt = 0;
> @@ -414,7 +414,7 @@ static int data_sock_setsockopt(struct socket *sock, int level, int optname,
>   
>   	switch (optname) {
>   	case MISDN_TIME_STAMP:
> -		if (get_user(opt, (int __user *)optval)) {
> +		if (copy_from_sockptr(&opt, optval, sizeof(int))) {
>   			err = -EFAULT;
>   			break;
>   		}
> diff --git a/include/linux/net.h b/include/linux/net.h
> index 858ff1d981540d..d48ff11808794c 100644
> --- a/include/linux/net.h
> +++ b/include/linux/net.h
> @@ -21,6 +21,7 @@
>   #include <linux/rcupdate.h>
>   #include <linux/once.h>
>   #include <linux/fs.h>
> +#include <linux/sockptr.h>
>   
>   #include <uapi/linux/net.h>
>   
> @@ -162,7 +163,8 @@ struct proto_ops {
>   	int		(*listen)    (struct socket *sock, int len);
>   	int		(*shutdown)  (struct socket *sock, int flags);
>   	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 optname, char __user *optval, int __user *optlen);
>   	void		(*show_fdinfo)(struct seq_file *m, struct socket *sock);
> diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
> index 157c60cca0ca60..1e209ce7d1bd1b 100644
> --- a/include/net/inet_connection_sock.h
> +++ b/include/net/inet_connection_sock.h
> @@ -16,6 +16,7 @@
>   #include <linux/timer.h>
>   #include <linux/poll.h>
>   #include <linux/kernel.h>
> +#include <linux/sockptr.h>
>   
>   #include <net/inet_sock.h>
>   #include <net/request_sock.h>
> @@ -45,7 +46,7 @@ struct inet_connection_sock_af_ops {
>   	u16	    net_frag_header_len;
>   	u16	    sockaddr_len;
>   	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,
>   				  char __user *optval, int __user *optlen);
>   	void	    (*addr2sockaddr)(struct sock *sk, struct sockaddr *);
> diff --git a/include/net/ip.h b/include/net/ip.h
> index d66ad3a9522081..b09c48d862cc10 100644
> --- a/include/net/ip.h
> +++ b/include/net/ip.h
> @@ -722,7 +722,7 @@ void ip_cmsg_recv_offset(struct msghdr *msg, struct sock *sk,
>   			 struct sk_buff *skb, int tlen, int offset);
>   int ip_cmsg_send(struct sock *sk, struct msghdr *msg,
>   		 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);
>   int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
>   		  int __user *optlen);
> diff --git a/include/net/ipv6.h b/include/net/ipv6.h
> index 4c9d89b5d73268..bd1f396cc9c729 100644
> --- a/include/net/ipv6.h
> +++ b/include/net/ipv6.h
> @@ -1084,8 +1084,8 @@ struct in6_addr *fl6_update_dst(struct flowi6 *fl6,
>    *	socket options (ipv6_sockglue.c)
>    */
>   
> -int ipv6_setsockopt(struct sock *sk, int level, int optname,
> -		    char __user *optval, unsigned int optlen);
> +int ipv6_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
> +		    unsigned int optlen);
>   int ipv6_getsockopt(struct sock *sk, int level, int optname,
>   		    char __user *optval, int __user *optlen);
>   
> diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
> index 233bbf7df5d66c..b33f1aefad0989 100644
> --- a/include/net/sctp/structs.h
> +++ b/include/net/sctp/structs.h
> @@ -431,7 +431,7 @@ struct sctp_af {
>   	int		(*setsockopt)	(struct sock *sk,
>   					 int level,
>   					 int optname,
> -					 char __user *optval,
> +					 sockptr_t optval,
>   					 unsigned int optlen);
>   	int		(*getsockopt)	(struct sock *sk,
>   					 int level,
> diff --git a/include/net/sock.h b/include/net/sock.h
> index bfb2fe2fc36876..2cc3ba667908de 100644
> --- a/include/net/sock.h
> +++ b/include/net/sock.h
> @@ -1141,7 +1141,7 @@ struct proto {
>   	void			(*destroy)(struct sock *sk);
>   	void			(*shutdown)(struct sock *sk, int how);
>   	int			(*setsockopt)(struct sock *sk, int level,
> -					int optname, char __user *optval,
> +					int optname, sockptr_t optval,
>   					unsigned int optlen);
>   	int			(*getsockopt)(struct sock *sk, int level,
>   					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 flags);
>   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);
>   
> diff --git a/include/net/tcp.h b/include/net/tcp.h
> index e3c8e1d820214c..e0c35d56091f22 100644
> --- a/include/net/tcp.h
> +++ b/include/net/tcp.h
> @@ -399,8 +399,8 @@ __poll_t tcp_poll(struct file *file, struct socket *sock,
>   		      struct poll_table_struct *wait);
>   int tcp_getsockopt(struct sock *sk, int level, int optname,
>   		   char __user *optval, int __user *optlen);
> -int tcp_setsockopt(struct sock *sk, int level, int optname,
> -		   char __user *optval, unsigned int optlen);
> +int tcp_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
> +		   unsigned int optlen);
>   void tcp_set_keepalive(struct sock *sk, int val);
>   void tcp_syn_ack_timeout(const struct request_sock *req);
>   int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
> diff --git a/net/atm/common.c b/net/atm/common.c
> index 9b28f1fb3c69c8..84367b844b1473 100644
> --- a/net/atm/common.c
> +++ b/net/atm/common.c
> @@ -745,7 +745,7 @@ static int check_qos(const struct atm_qos *qos)
>   }
>   
>   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;
>   	unsigned long value;
> @@ -760,7 +760,7 @@ int vcc_setsockopt(struct socket *sock, int level, int optname,
>   	{
>   		struct atm_qos qos;
>   
> -		if (copy_from_user(&qos, optval, sizeof(qos)))
> +		if (copy_from_sockptr(&qos, optval, sizeof(qos)))
>   			return -EFAULT;
>   		error = check_qos(&qos);
>   		if (error)
> @@ -774,7 +774,7 @@ int vcc_setsockopt(struct socket *sock, int level, int optname,
>   		return 0;
>   	}
>   	case SO_SETCLP:
> -		if (get_user(value, (unsigned long __user *)optval))
> +		if (copy_from_sockptr(&value, optval, sizeof(value)))
>   			return -EFAULT;
>   		if (value)
>   			vcc->atm_options |= ATM_ATMOPT_CLP;
> diff --git a/net/atm/common.h b/net/atm/common.h
> index 5850649068bb29..a1e56e8de698a3 100644
> --- a/net/atm/common.h
> +++ b/net/atm/common.h
> @@ -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_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
>   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,
>   		   char __user *optval, int __user *optlen);
>   void vcc_process_recv_queue(struct atm_vcc *vcc);
> diff --git a/net/atm/pvc.c b/net/atm/pvc.c
> index 02bd2a436bdf9e..53e7d3f39e26cc 100644
> --- a/net/atm/pvc.c
> +++ b/net/atm/pvc.c
> @@ -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,
> -			  char __user *optval, unsigned int optlen)
> +			  sockptr_t optval, unsigned int optlen)
>   {
>   	struct sock *sk = sock->sk;
>   	int error;
> diff --git a/net/atm/svc.c b/net/atm/svc.c
> index ba144d035e3d41..4a02bcaad279f8 100644
> --- a/net/atm/svc.c
> +++ b/net/atm/svc.c
> @@ -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,
> -			  char __user *optval, unsigned int optlen)
> +			  sockptr_t optval, unsigned int optlen)
>   {
>   	struct sock *sk = sock->sk;
>   	struct atm_vcc *vcc = ATM_SD(sock);
> @@ -464,7 +464,7 @@ static int svc_setsockopt(struct socket *sock, int level, int optname,
>   			error = -EINVAL;
>   			goto out;
>   		}
> -		if (copy_from_user(&vcc->sap, optval, optlen)) {
> +		if (copy_from_sockptr(&vcc->sap, optval, optlen)) {
>   			error = -EFAULT;
>   			goto out;
>   		}
> @@ -475,7 +475,7 @@ static int svc_setsockopt(struct socket *sock, int level, int optname,
>   			error = -EINVAL;
>   			goto out;
>   		}
> -		if (get_user(value, (int __user *)optval)) {
> +		if (copy_from_sockptr(&value, optval, sizeof(int))) {
>   			error = -EFAULT;
>   			goto out;
>   		}
> diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
> index fd91cd34f25e03..17bf31a8969284 100644
> --- a/net/ax25/af_ax25.c
> +++ b/net/ax25/af_ax25.c
> @@ -528,7 +528,7 @@ ax25_cb *ax25_create_cb(void)
>    */
>   
>   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;
>   	ax25_cb *ax25;
> @@ -543,7 +543,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
>   	if (optlen < sizeof(unsigned int))
>   		return -EINVAL;
>   
> -	if (get_user(opt, (unsigned int __user *)optval))
> +	if (copy_from_sockptr(&opt, optval, sizeof(unsigned int)))
>   		return -EFAULT;
>   
>   	lock_sock(sk);
> @@ -640,7 +640,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
>   
>   		memset(devname, 0, sizeof(devname));
>   
> -		if (copy_from_user(devname, optval, optlen)) {
> +		if (copy_from_sockptr(devname, optval, optlen)) {
>   			res = -EFAULT;
>   			break;
>   		}
> diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
> index caf38a8ea6a8ba..d5eff27d5b1e17 100644
> --- a/net/bluetooth/hci_sock.c
> +++ b/net/bluetooth/hci_sock.c
> @@ -1842,7 +1842,7 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg,
>   }
>   
>   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 sock *sk = sock->sk;
> @@ -1862,7 +1862,7 @@ static int hci_sock_setsockopt(struct socket *sock, int level, int optname,
>   
>   	switch (optname) {
>   	case HCI_DATA_DIR:
> -		if (get_user(opt, (int __user *)optval)) {
> +		if (copy_from_sockptr(&opt, optval, sizeof(opt))) {
>   			err = -EFAULT;
>   			break;
>   		}
> @@ -1874,7 +1874,7 @@ static int hci_sock_setsockopt(struct socket *sock, int level, int optname,
>   		break;
>   
>   	case HCI_TIME_STAMP:
> -		if (get_user(opt, (int __user *)optval)) {
> +		if (copy_from_sockptr(&opt, optval, sizeof(opt))) {
>   			err = -EFAULT;
>   			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));
> -		if (copy_from_user(&uf, optval, len)) {
> +		if (copy_from_sockptr(&uf, optval, len)) {
>   			err = -EFAULT;
>   			break;
>   		}
> diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
> index a995d2c51fa7f1..a3d104123f38dd 100644
> --- a/net/bluetooth/l2cap_sock.c
> +++ b/net/bluetooth/l2cap_sock.c
> @@ -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,
> -				     char __user *optval, unsigned int optlen)
> +				     sockptr_t optval, unsigned int optlen)
>   {
>   	struct sock *sk = sock->sk;
>   	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;
>   
>   		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;
>   			break;
>   		}
> @@ -782,7 +782,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
>   		break;
>   
>   	case L2CAP_LM:
> -		if (get_user(opt, (u32 __user *) optval)) {
> +		if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
>   			err = -EFAULT;
>   			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,
> -				 char __user *optval, unsigned int optlen)
> +				 sockptr_t optval, unsigned int optlen)
>   {
>   	struct sock *sk = sock->sk;
>   	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;
>   
>   		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;
>   			break;
>   		}
> @@ -939,7 +939,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
>   			break;
>   		}
>   
> -		if (get_user(opt, (u32 __user *) optval)) {
> +		if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
>   			err = -EFAULT;
>   			break;
>   		}
> @@ -954,7 +954,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
>   		break;
>   
>   	case BT_FLUSHABLE:
> -		if (get_user(opt, (u32 __user *) optval)) {
> +		if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
>   			err = -EFAULT;
>   			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;
>   
>   		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;
>   			break;
>   		}
> @@ -1002,7 +1002,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
>   		break;
>   
>   	case BT_CHANNEL_POLICY:
> -		if (get_user(opt, (u32 __user *) optval)) {
> +		if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
>   			err = -EFAULT;
>   			break;
>   		}
> @@ -1050,7 +1050,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
>   			break;
>   		}
>   
> -		if (get_user(opt, (u16 __user *) optval)) {
> +		if (copy_from_sockptr(&opt, optval, sizeof(u16))) {
>   			err = -EFAULT;
>   			break;
>   		}
> @@ -1081,7 +1081,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
>   			break;
>   		}
>   
> -		if (get_user(opt, (u8 __user *) optval)) {
> +		if (copy_from_sockptr(&opt, optval, sizeof(u8))) {
>   			err = -EFAULT;
>   			break;
>   		}
> diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
> index df14eebe80da8b..dba4ea0e1b0dc7 100644
> --- a/net/bluetooth/rfcomm/sock.c
> +++ b/net/bluetooth/rfcomm/sock.c
> @@ -644,7 +644,8 @@ static int rfcomm_sock_recvmsg(struct socket *sock, struct msghdr *msg,
>   	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;
>   	int err = 0;
> @@ -656,7 +657,7 @@ static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, char __u
>   
>   	switch (optname) {
>   	case RFCOMM_LM:
> -		if (get_user(opt, (u32 __user *) optval)) {
> +		if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
>   			err = -EFAULT;
>   			break;
>   		}
> @@ -685,7 +686,8 @@ static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, char __u
>   	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 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;
>   
>   		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;
>   			break;
>   		}
> @@ -732,7 +734,7 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, c
>   			break;
>   		}
>   
> -		if (get_user(opt, (u32 __user *) optval)) {
> +		if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
>   			err = -EFAULT;
>   			break;
>   		}
> diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
> index c8c3d38cdc7b56..37260baf71507b 100644
> --- a/net/bluetooth/sco.c
> +++ b/net/bluetooth/sco.c
> @@ -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,
> -			       char __user *optval, unsigned int optlen)
> +			       sockptr_t optval, unsigned int optlen)
>   {
>   	struct sock *sk = sock->sk;
>   	int len, err = 0;
> @@ -810,7 +810,7 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
>   			break;
>   		}
>   
> -		if (get_user(opt, (u32 __user *) optval)) {
> +		if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
>   			err = -EFAULT;
>   			break;
>   		}
> @@ -831,7 +831,7 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
>   		voice.setting = sco_pi(sk)->setting;
>   
>   		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;
>   			break;
>   		}
> diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c
> index b94ecd931002e7..3ad0a1df671283 100644
> --- a/net/caif/caif_socket.c
> +++ b/net/caif/caif_socket.c
> @@ -669,8 +669,8 @@ static int caif_stream_sendmsg(struct socket *sock, struct msghdr *msg,
>   	return sent ? : err;
>   }
>   
> -static int setsockopt(struct socket *sock,
> -		      int lvl, int opt, char __user *ov, unsigned int ol)
> +static int setsockopt(struct socket *sock, int lvl, int opt, sockptr_t ov,
> +		unsigned int ol)
>   {
>   	struct sock *sk = sock->sk;
>   	struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
> @@ -685,7 +685,7 @@ static int setsockopt(struct socket *sock,
>   			return -EINVAL;
>   		if (lvl != SOL_CAIF)
>   			goto bad_sol;
> -		if (copy_from_user(&linksel, ov, sizeof(int)))
> +		if (copy_from_sockptr(&linksel, ov, sizeof(int)))
>   			return -EINVAL;
>   		lock_sock(&(cf_sk->sk));
>   		cf_sk->conn_req.link_selector = linksel;
> @@ -699,7 +699,7 @@ static int setsockopt(struct socket *sock,
>   			return -ENOPROTOOPT;
>   		lock_sock(&(cf_sk->sk));
>   		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);
>   			return -EINVAL;
>   		}
> diff --git a/net/can/j1939/socket.c b/net/can/j1939/socket.c
> index f7587428febdd2..78ff9b3f1d40c7 100644
> --- a/net/can/j1939/socket.c
> +++ b/net/can/j1939/socket.c
> @@ -627,14 +627,14 @@ static int j1939_sk_release(struct socket *sock)
>   	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)
>   {
>   	int tmp;
>   
>   	if (optlen != sizeof(tmp))
>   		return -EINVAL;
> -	if (copy_from_user(&tmp, optval, optlen))
> +	if (copy_from_sockptr(&tmp, optval, optlen))
>   		return -EFAULT;
>   	lock_sock(&jsk->sk);
>   	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,
> -			       char __user *optval, unsigned int optlen)
> +			       sockptr_t optval, unsigned int optlen)
>   {
>   	struct sock *sk = sock->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) {
>   	case SO_J1939_FILTER:
> -		if (optval) {
> +		if (!sockptr_is_null(optval)) {
>   			struct j1939_filter *f;
>   			int c;
>   
> @@ -670,7 +670,7 @@ static int j1939_sk_setsockopt(struct socket *sock, int level, int optname,
>   				return -EINVAL;
>   
>   			count = optlen / sizeof(*filters);
> -			filters = memdup_user(optval, optlen);
> +			filters = memdup_sockptr(optval, optlen);
>   			if (IS_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:
>   		if (optlen != sizeof(tmp))
>   			return -EINVAL;
> -		if (copy_from_user(&tmp, optval, optlen))
> +		if (copy_from_sockptr(&tmp, optval, optlen))
>   			return -EFAULT;
>   		if (tmp < 0 || tmp > 7)
>   			return -EDOM;
> diff --git a/net/can/raw.c b/net/can/raw.c
> index 59c039d73c6d58..94a9405658dc61 100644
> --- a/net/can/raw.c
> +++ b/net/can/raw.c
> @@ -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,
> -			  char __user *optval, unsigned int optlen)
> +			  sockptr_t optval, unsigned int optlen)
>   {
>   	struct sock *sk = sock->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) {
>   			/* filter does not fit into dfilter => alloc space */
> -			filter = memdup_user(optval, optlen);
> +			filter = memdup_sockptr(optval, optlen);
>   			if (IS_ERR(filter))
>   				return PTR_ERR(filter);
>   		} else if (count == 1) {
> -			if (copy_from_user(&sfilter, optval, sizeof(sfilter)))
> +			if (copy_from_sockptr(&sfilter, optval, sizeof(sfilter)))
>   				return -EFAULT;
>   		}
>   
> @@ -568,7 +568,7 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
>   		if (optlen != sizeof(err_mask))
>   			return -EINVAL;
>   
> -		if (copy_from_user(&err_mask, optval, optlen))
> +		if (copy_from_sockptr(&err_mask, optval, optlen))
>   			return -EFAULT;
>   
>   		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))
>   			return -EINVAL;
>   
> -		if (copy_from_user(&ro->loopback, optval, optlen))
> +		if (copy_from_sockptr(&ro->loopback, optval, optlen))
>   			return -EFAULT;
>   
>   		break;
> @@ -616,7 +616,7 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
>   		if (optlen != sizeof(ro->recv_own_msgs))
>   			return -EINVAL;
>   
> -		if (copy_from_user(&ro->recv_own_msgs, optval, optlen))
> +		if (copy_from_sockptr(&ro->recv_own_msgs, optval, optlen))
>   			return -EFAULT;
>   
>   		break;
> @@ -625,7 +625,7 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
>   		if (optlen != sizeof(ro->fd_frames))
>   			return -EINVAL;
>   
> -		if (copy_from_user(&ro->fd_frames, optval, optlen))
> +		if (copy_from_sockptr(&ro->fd_frames, optval, optlen))
>   			return -EFAULT;
>   
>   		break;
> @@ -634,7 +634,7 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
>   		if (optlen != sizeof(ro->join_filters))
>   			return -EINVAL;
>   
> -		if (copy_from_user(&ro->join_filters, optval, optlen))
> +		if (copy_from_sockptr(&ro->join_filters, optval, optlen))
>   			return -EFAULT;
>   
>   		break;
> diff --git a/net/core/sock.c b/net/core/sock.c
> index 9cf8318bc51de4..ff22629f10ce92 100644
> --- a/net/core/sock.c
> +++ b/net/core/sock.c
> @@ -3210,7 +3210,7 @@ EXPORT_SYMBOL(sock_common_recvmsg);
>    *	Set socket options on an inet socket.
>    */
>   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;
>   
> diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
> index 434eea91b7679d..9cc9d1ee6cdb9a 100644
> --- a/net/dccp/dccp.h
> +++ b/net/dccp/dccp.h
> @@ -295,7 +295,7 @@ int dccp_disconnect(struct sock *sk, int flags);
>   int dccp_getsockopt(struct sock *sk, int level, int optname,
>   		    char __user *optval, int __user *optlen);
>   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_sendmsg(struct sock *sk, struct msghdr *msg, size_t size);
>   int dccp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
> diff --git a/net/dccp/proto.c b/net/dccp/proto.c
> index fd92d3fe321f08..9e58787047f197 100644
> --- a/net/dccp/proto.c
> +++ b/net/dccp/proto.c
> @@ -402,7 +402,7 @@ int dccp_ioctl(struct sock *sk, int cmd, unsigned long arg)
>   EXPORT_SYMBOL_GPL(dccp_ioctl);
>   
>   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_service_list *sl = NULL;
> @@ -417,9 +417,9 @@ static int dccp_setsockopt_service(struct sock *sk, const __be32 service,
>   			return -ENOMEM;
>   
>   		sl->dccpsl_nr = optlen / sizeof(u32) - 1;
> -		if (copy_from_user(sl->dccpsl_list,
> -				   optval + sizeof(service),
> -				   optlen - sizeof(service)) ||
> +		sockptr_advance(optval, sizeof(service));
> +		if (copy_from_sockptr(sl->dccpsl_list, optval,
> +				      optlen - sizeof(service)) ||
>   		    dccp_list_has_service(sl, DCCP_SERVICE_INVALID_VALUE)) {
>   			kfree(sl);
>   			return -EFAULT;
> @@ -473,7 +473,7 @@ static int dccp_setsockopt_cscov(struct sock *sk, int cscov, bool rx)
>   }
>   
>   static int dccp_setsockopt_ccid(struct sock *sk, int type,
> -				char __user *optval, unsigned int optlen)
> +				sockptr_t optval, unsigned int optlen)
>   {
>   	u8 *val;
>   	int rc = 0;
> @@ -481,7 +481,7 @@ static int dccp_setsockopt_ccid(struct sock *sk, int type,
>   	if (optlen < 1 || optlen > DCCP_FEAT_MAX_SP_VALS)
>   		return -EINVAL;
>   
> -	val = memdup_user(optval, optlen);
> +	val = memdup_sockptr(optval, optlen);
>   	if (IS_ERR(val))
>   		return PTR_ERR(val);
>   
> @@ -498,7 +498,7 @@ static int dccp_setsockopt_ccid(struct sock *sk, int type,
>   }
>   
>   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);
>   	int val, err = 0;
> @@ -520,7 +520,7 @@ static int do_dccp_setsockopt(struct sock *sk, int level, int optname,
>   	if (optlen < (int)sizeof(int))
>   		return -EINVAL;
>   
> -	if (get_user(val, (int __user *)optval))
> +	if (copy_from_sockptr(&val, optval, sizeof(int)))
>   		return -EFAULT;
>   
>   	if (optname == DCCP_SOCKOPT_SERVICE)
> @@ -563,8 +563,8 @@ static int do_dccp_setsockopt(struct sock *sk, int level, int optname,
>   	return err;
>   }
>   
> -int dccp_setsockopt(struct sock *sk, int level, int optname,
> -		    char __user *optval, unsigned int optlen)
> +int dccp_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
> +		    unsigned int optlen)
>   {
>   	if (level != SOL_DCCP)
>   		return inet_csk(sk)->icsk_af_ops->setsockopt(sk, level,
> diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
> index 7d51ab608fb3f1..3b53d766789d47 100644
> --- a/net/decnet/af_decnet.c
> +++ b/net/decnet/af_decnet.c
> @@ -150,7 +150,8 @@ static struct hlist_head dn_sk_hash[DN_SK_HASH_SIZE];
>   static struct hlist_head dn_wild_sk;
>   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 struct hlist_head *dn_find_list(struct sock *sk)
> @@ -1320,7 +1321,8 @@ static int dn_shutdown(struct socket *sock, int how)
>   	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;
>   	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 */
>   	if (err == -ENOPROTOOPT && optname != DSO_LINKINFO &&
>   	    optname != DSO_STREAM && optname != DSO_SEQPACKET)
> -		err = nf_setsockopt(sk, PF_DECnet, optname,
> -				    USER_SOCKPTR(optval), optlen);
> +		err = nf_setsockopt(sk, PF_DECnet, optname, optval, optlen);
>   #endif
>   
>   	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 dn_scp *scp = DN_SK(sk);
> @@ -1355,13 +1357,13 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char __us
>   	} u;
>   	int err;
>   
> -	if (optlen && !optval)
> +	if (optlen && sockptr_is_null(optval))
>   		return -EINVAL;
>   
>   	if (optlen > sizeof(u))
>   		return -EINVAL;
>   
> -	if (copy_from_user(&u, optval, optlen))
> +	if (copy_from_sockptr(&u, optval, optlen))
>   		return -EFAULT;
>   
>   	switch (optname) {
> diff --git a/net/ieee802154/socket.c b/net/ieee802154/socket.c
> index 94ae9662133e30..a45a0401adc50b 100644
> --- a/net/ieee802154/socket.c
> +++ b/net/ieee802154/socket.c
> @@ -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,
> -			  char __user *optval, unsigned int optlen)
> +			  sockptr_t optval, unsigned int optlen)
>   {
>   	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,
> -			    char __user *optval, unsigned int optlen)
> +			    sockptr_t optval, unsigned int optlen)
>   {
>   	struct dgram_sock *ro = dgram_sk(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))
>   		return -EINVAL;
>   
> -	if (get_user(val, (int __user *)optval))
> +	if (copy_from_sockptr(&val, optval, sizeof(int)))
>   		return -EFAULT;
>   

For the ieee802154 part:

Acked-by: Stefan Schmidt <stefan@...enfreihafen.org>

regards
Stefan Schmidt

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ