Thread (28 messages) 28 messages, 5 authors, 2025-04-02
STALE423d

[RFC PATCH 2/4] net: pass 'optlen_t' to proto[ops].getsockopt() hooks

From: Stefan Metzmacher <metze@samba.org>
Date: 2025-03-31 20:12:25
Also in: bpf, io-uring, linux-bluetooth, linux-can, linux-hams, linux-rdma, linux-s390, linux-sctp, lkml, mptcp, virtualization
Subsystem: atm, bluetooth subsystem, can network layer, can-j1939 network layer, cxgb4 inline crypto driver, ieee 802.15.4 subsystem, llc (802.2), management component transport protocol (mctp), networking drivers, networking [general], networking [ipv4/ipv6], networking [mptcp], networking [sockets], networking [tcp], networking [tls], nfc subsystem, packet sockets, phonet protocol, ppp over l2tp, rds - reliable datagram sockets, rxrpc sockets (af_rxrpc), s390 iucv network layer, sctp protocol, shared memory communications (smc) sockets, the rest, tipc network layer, user datagram protocol (udp), vm sockets (af_vsock), x.25 stack, xdp sockets (af_xdp) · Maintainers: Chas Williams, Marcel Holtmann, Luiz Augusto von Dentz, Oliver Hartkopp, Marc Kleine-Budde, Robin van der Gracht, Oleksij Rempel, Ayush Sawal, Alexander Aring, Stefan Schmidt, Miquel Raynal, Jeremy Kerr, Matt Johnston, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, David Ahern, Ido Schimmel, Matthieu Baerts, Mat Martineau, Kuniyuki Iwashima, Willem de Bruijn, Neal Cardwell, John Fastabend, Sabrina Dubroca, David Heidelberg, Remi Denis-Courmont, James Chapman, Allison Henderson, David Howells, Marc Dionne, Alexandra Winter, Thorsten Winkler, Marcelo Ricardo Leitner, Xin Long, D. Wythe, Dust Li, Sidraya Jayagond, Wenjia Zhang, Linus Torvalds, Jon Maloy, Stefano Garzarella, Martin Schiller, Magnus Karlsson, Maciej Fijalkowski

The motivation for this is to remove the SOL_SOCKET limitation
from io_uring_cmd_getsockopt().

The reason for this limitation is that io_uring_cmd_getsockopt()
passes a kernel pointer.

The first idea would be to change the optval and optlen arguments
to the protocol specific hooks also to sockptr_t, as that
is already used for setsockopt() and also by do_sock_getsockopt()
sk_getsockopt() and BPF_CGROUP_RUN_PROG_GETSOCKOPT().

But as Linus don't like 'sockptr_t' I used a different approach.

This step only introduces 'optlen_t' as a trivial wrapper of
the 'int __user *', it makes sure that the optlen argument
is only ever used by get_optval(), put_optval.
For some corner cases OPTLEN_SOCKPTR().

We still expect a __user pointer, so this should be easy to
review and don't change the logic.

Link: https://lore.kernel.org/io-uring/86b1dce5-4bb4-4a0b-9cff-e72f488bf57d@samba.org/T/#t (local)
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Pavel Begunkov <asml.silence@gmail.com>
Cc: Breno Leitao <leitao@debian.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Karsten Keil <redacted>
Cc: Ayush Sawal <ayush.sawal@chelsio.com>
Cc: Andrew Lunn <andrew+netdev@lunn.ch>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Simon Horman <horms@kernel.org>
Cc: Kuniyuki Iwashima <redacted>
Cc: Willem de Bruijn <willemb@google.com>
Cc: David Ahern <dsahern@kernel.org>
Cc: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Cc: Xin Long <lucien.xin@gmail.com>
Cc: Neal Cardwell <ncardwell@google.com>
Cc: Joerg Reuter <redacted>
Cc: Marcel Holtmann <marcel@holtmann.org>
Cc: Johan Hedberg <redacted>
Cc: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Cc: Oliver Hartkopp <socketcan@hartkopp.net>
Cc: Marc Kleine-Budde <mkl@pengutronix.de>
Cc: Robin van der Gracht <robin@protonic.nl>
Cc: Oleksij Rempel <o.rempel@pengutronix.de>
Cc: kernel@pengutronix.de
Cc: Alexander Aring <alex.aring@gmail.com>
Cc: Stefan Schmidt <stefan@datenfreihafen.org>
Cc: Miquel Raynal <miquel.raynal@bootlin.com>
Cc: Alexandra Winter <wintera@linux.ibm.com>
Cc: Thorsten Winkler <twinkler@linux.ibm.com>
Cc: James Chapman <jchapman@katalix.com>
Cc: Jeremy Kerr <jk@codeconstruct.com.au>
Cc: Matt Johnston <matt@codeconstruct.com.au>
Cc: Matthieu Baerts <matttbe@kernel.org>
Cc: Mat Martineau <martineau@kernel.org>
Cc: Geliang Tang <geliang@kernel.org>
Cc: Krzysztof Kozlowski <krzk@kernel.org>
Cc: Remi Denis-Courmont <courmisch@gmail.com>
Cc: Allison Henderson <redacted>
Cc: David Howells <dhowells@redhat.com>
Cc: Marc Dionne <marc.dionne@auristor.com>
Cc: Wenjia Zhang <wenjia@linux.ibm.com>
Cc: Jan Karcher <redacted>
Cc: "D. Wythe" <alibuda@linux.alibaba.com>
Cc: Tony Lu <tonylu@linux.alibaba.com>
Cc: Wen Gu <guwen@linux.alibaba.com>
Cc: Jon Maloy <jmaloy@redhat.com>
Cc: Boris Pismenny <borisp@nvidia.com>
Cc: John Fastabend <john.fastabend@gmail.com>
Cc: Stefano Garzarella <sgarzare@redhat.com>
Cc: Martin Schiller <ms@dev.tdt.de>
Cc: "Björn Töpel" <bjorn@kernel.org>
Cc: Magnus Karlsson <magnus.karlsson@intel.com>
Cc: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Cc: Jonathan Lemon <redacted>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Jesper Dangaard Brouer <hawk@kernel.org>
CC: Stefan Metzmacher <metze@samba.org>
Cc: netdev@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-sctp@vger.kernel.org
Cc: linux-hams@vger.kernel.org
Cc: linux-bluetooth@vger.kernel.org
Cc: linux-can@vger.kernel.org
Cc: dccp@vger.kernel.org
Cc: linux-wpan@vger.kernel.org
Cc: linux-s390@vger.kernel.org
Cc: mptcp@lists.linux.dev
Cc: linux-rdma@vger.kernel.org
Cc: rds-devel@oss.oracle.com
Cc: linux-afs@lists.infradead.org
Cc: tipc-discussion@lists.sourceforge.net
Cc: virtualization@lists.linux.dev
Cc: linux-x25@vger.kernel.org
Cc: bpf@vger.kernel.org
Cc: isdn4linux@listserv.isdn4linux.de
Cc: io-uring@vger.kernel.org
Signed-off-by: Stefan Metzmacher <metze@samba.org>
---
 drivers/isdn/mISDN/socket.c                   |   2 +-
 .../chelsio/inline_crypto/chtls/chtls_main.c  |   4 +-
 include/linux/net.h                           |   2 +-
 include/linux/sockptr.h                       |  17 ++-
 include/net/inet_connection_sock.h            |   2 +-
 include/net/ip.h                              |   2 +-
 include/net/ipv6.h                            |   2 +-
 include/net/sctp/structs.h                    |   2 +-
 include/net/sock.h                            |   4 +-
 include/net/tcp.h                             |   2 +-
 include/net/udp.h                             |   2 +-
 net/atm/common.c                              |   2 +-
 net/atm/common.h                              |   2 +-
 net/atm/pvc.c                                 |   2 +-
 net/atm/svc.c                                 |   2 +-
 net/ax25/af_ax25.c                            |   2 +-
 net/bluetooth/hci_sock.c                      |   4 +-
 net/bluetooth/iso.c                           |   2 +-
 net/bluetooth/l2cap_sock.c                    |   4 +-
 net/bluetooth/rfcomm/sock.c                   |   4 +-
 net/bluetooth/sco.c                           |   4 +-
 net/can/isotp.c                               |   2 +-
 net/can/j1939/socket.c                        |   2 +-
 net/can/raw.c                                 |   2 +-
 net/core/sock.c                               |   2 +-
 net/dccp/ccid.c                               |   2 +-
 net/dccp/ccid.h                               |  10 +-
 net/dccp/ccids/ccid3.c                        |   4 +-
 net/dccp/dccp.h                               |   2 +-
 net/dccp/proto.c                              |   6 +-
 net/ieee802154/socket.c                       |   4 +-
 net/ipv4/ip_sockglue.c                        |   4 +-
 net/ipv4/raw.c                                |   6 +-
 net/ipv4/tcp.c                                |   4 +-
 net/ipv4/udp.c                                |   4 +-
 net/ipv4/udp_impl.h                           |   2 +-
 net/ipv6/ipv6_sockglue.c                      |   4 +-
 net/ipv6/raw.c                                |   6 +-
 net/ipv6/udp.c                                |   2 +-
 net/ipv6/udp_impl.h                           |   2 +-
 net/iucv/af_iucv.c                            |   2 +-
 net/kcm/kcmsock.c                             |   2 +-
 net/l2tp/l2tp_ppp.c                           |   2 +-
 net/llc/af_llc.c                              |   2 +-
 net/mctp/af_mctp.c                            |   2 +-
 net/mptcp/protocol.h                          |   2 +-
 net/mptcp/sockopt.c                           |  30 ++---
 net/netlink/af_netlink.c                      |   2 +-
 net/netrom/af_netrom.c                        |   2 +-
 net/nfc/llcp_sock.c                           |   2 +-
 net/packet/af_packet.c                        |   2 +-
 net/phonet/pep.c                              |   2 +-
 net/rds/af_rds.c                              |   2 +-
 net/rds/info.c                                |   2 +-
 net/rds/info.h                                |   2 +-
 net/rose/af_rose.c                            |   2 +-
 net/rxrpc/af_rxrpc.c                          |   2 +-
 net/sctp/socket.c                             | 112 +++++++++---------
 net/smc/af_smc.c                              |   4 +-
 net/smc/smc.h                                 |   2 +-
 net/socket.c                                  |   7 +-
 net/tipc/socket.c                             |   2 +-
 net/tls/tls_main.c                            |  10 +-
 net/vmw_vsock/af_vsock.c                      |   2 +-
 net/x25/af_x25.c                              |   2 +-
 net/xdp/xsk.c                                 |   2 +-
 66 files changed, 178 insertions(+), 166 deletions(-)
diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c
index b750cc0dfa4a..233426f24ab6 100644
--- a/drivers/isdn/mISDN/socket.c
+++ b/drivers/isdn/mISDN/socket.c
@@ -433,7 +433,7 @@ static int data_sock_setsockopt(struct socket *sock, int level, int optname,
 }
 
 static int data_sock_getsockopt(struct socket *sock, int level, int optname,
-				char __user *optval, int __user *optlen)
+				char __user *optval, optlen_t optlen)
 {
 	struct sock *sk = sock->sk;
 	int len, opt;
diff --git a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c
index daa1ebaef511..ac73ed4fc5d4 100644
--- a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c
+++ b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c
@@ -466,7 +466,7 @@ static int chtls_uld_rx_handler(void *handle, const __be64 *rsp,
 }
 
 static int do_chtls_getsockopt(struct sock *sk, char __user *optval,
-			       int __user *optlen)
+			       optlen_t optlen)
 {
 	struct tls_crypto_info crypto_info = { 0 };
 
@@ -477,7 +477,7 @@ static int do_chtls_getsockopt(struct sock *sk, char __user *optval,
 }
 
 static int chtls_getsockopt(struct sock *sk, int level, int optname,
-			    char __user *optval, int __user *optlen)
+			    char __user *optval, optlen_t optlen)
 {
 	struct tls_context *ctx = tls_get_ctx(sk);
 
diff --git a/include/linux/net.h b/include/linux/net.h
index 0ff950eecc6b..f8b2728f993c 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -193,7 +193,7 @@ struct proto_ops {
 				      int optname, sockptr_t optval,
 				      unsigned int optlen);
 	int		(*getsockopt)(struct socket *sock, int level,
-				      int optname, char __user *optval, int __user *optlen);
+				      int optname, char __user *optval, optlen_t optlen);
 	void		(*show_fdinfo)(struct seq_file *m, struct socket *sock);
 	int		(*sendmsg)   (struct socket *sock, struct msghdr *m,
 				      size_t total_len);
diff --git a/include/linux/sockptr.h b/include/linux/sockptr.h
index 28dbc3e27374..1baf66f26f4f 100644
--- a/include/linux/sockptr.h
+++ b/include/linux/sockptr.h
@@ -169,17 +169,21 @@ static inline int check_zeroed_sockptr(sockptr_t src, size_t offset,
 	return memchr_inv(src.kernel + offset, 0, size) == NULL;
 }
 
+typedef struct {
+	int __user *up;
+} optlen_t;
+
 #define __check_optlen_t(__optlen)				\
 ({								\
-	int __user *__ptr __maybe_unused = __optlen; 		\
-	BUILD_BUG_ON(sizeof(*(__ptr)) != sizeof(int));		\
+	optlen_t *__ptr __maybe_unused = &__optlen; \
+	BUILD_BUG_ON(sizeof(*((__ptr)->up)) != sizeof(int));	\
 })
 
 #define get_optlen(__val, __optlen)				\
 ({								\
 	long __err;						\
 	__check_optlen_t(__optlen);				\
-	__err = get_user(__val, __optlen);			\
+	__err = get_user(__val, __optlen.up);			\
 	__err;							\
 })
 
@@ -187,8 +191,13 @@ static inline int check_zeroed_sockptr(sockptr_t src, size_t offset,
 ({								\
 	long __err;						\
 	__check_optlen_t(__optlen);				\
-	__err = put_user(__val, __optlen);			\
+	__err = put_user(__val, __optlen.up);			\
 	__err;							\
 })
 
+static inline sockptr_t OPTLEN_SOCKPTR(optlen_t optlen)
+{
+	return (sockptr_t) { .user = optlen.up, };
+}
+
 #endif /* _LINUX_SOCKPTR_H */
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index 1735db332aab..3a3d03308611 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -47,7 +47,7 @@ struct inet_connection_sock_af_ops {
 	int	    (*setsockopt)(struct sock *sk, int level, int optname,
 				  sockptr_t optval, unsigned int optlen);
 	int	    (*getsockopt)(struct sock *sk, int level, int optname,
-				  char __user *optval, int __user *optlen);
+				  char __user *optval, optlen_t optlen);
 	void	    (*mtu_reduced)(struct sock *sk);
 };
 
diff --git a/include/net/ip.h b/include/net/ip.h
index 8a48ade24620..9f725642a42e 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -802,7 +802,7 @@ int ip_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
 int do_ip_getsockopt(struct sock *sk, int level, int optname,
 		     sockptr_t optval, sockptr_t optlen);
 int ip_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
-		  int __user *optlen);
+		  optlen_t optlen);
 int ip_ra_control(struct sock *sk, unsigned char on,
 		  void (*destructor)(struct sock *));
 
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 2ccdf85f34f1..99e655db1dde 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -1186,7 +1186,7 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
 int do_ipv6_getsockopt(struct sock *sk, int level, int optname,
 		       sockptr_t optval, sockptr_t optlen);
 int ipv6_getsockopt(struct sock *sk, int level, int optname,
-		    char __user *optval, int __user *optlen);
+		    char __user *optval, optlen_t optlen);
 
 int __ip6_datagram_connect(struct sock *sk, struct sockaddr *addr,
 			   int addr_len);
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 31248cfdfb23..15f9b9ece3ea 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -441,7 +441,7 @@ struct sctp_af {
 					 int level,
 					 int optname,
 					 char __user *optval,
-					 int __user *optlen);
+					 optlen_t optlen);
 	void		(*get_dst)	(struct sctp_transport *t,
 					 union sctp_addr *saddr,
 					 struct flowi *fl,
diff --git a/include/net/sock.h b/include/net/sock.h
index 8daf1b3b12c6..94c0e90d8901 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1248,7 +1248,7 @@ struct proto {
 					unsigned int optlen);
 	int			(*getsockopt)(struct sock *sk, int level,
 					int optname, char __user *optval,
-					int __user *option);
+					optlen_t optlen);
 	void			(*keepalive)(struct sock *sk, int valbool);
 #ifdef CONFIG_COMPAT
 	int			(*compat_ioctl)(struct sock *sk,
@@ -1856,7 +1856,7 @@ int sock_no_mmap(struct file *file, struct socket *sock,
  * uses the inet style.
  */
 int sock_common_getsockopt(struct socket *sock, int level, int optname,
-				  char __user *optval, int __user *optlen);
+				  char __user *optval, optlen_t optlen);
 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,
diff --git a/include/net/tcp.h b/include/net/tcp.h
index df04dc09c519..75e6bcd6eac4 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -449,7 +449,7 @@ __poll_t tcp_poll(struct file *file, struct socket *sock,
 int do_tcp_getsockopt(struct sock *sk, int level,
 		      int optname, sockptr_t optval, sockptr_t optlen);
 int tcp_getsockopt(struct sock *sk, int level, int optname,
-		   char __user *optval, int __user *optlen);
+		   char __user *optval, optlen_t optlen);
 bool tcp_bpf_bypass_getsockopt(int level, int optname);
 int do_tcp_setsockopt(struct sock *sk, int level, int optname,
 		      sockptr_t optval, unsigned int optlen);
diff --git a/include/net/udp.h b/include/net/udp.h
index 6e89520e100d..a846681ae497 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -418,7 +418,7 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,
 				       netdev_features_t features,
 				       bool is_ipv6);
 int udp_lib_getsockopt(struct sock *sk, int level, int optname,
-		       char __user *optval, int __user *optlen);
+		       char __user *optval, optlen_t optlen);
 int udp_lib_setsockopt(struct sock *sk, int level, int optname,
 		       sockptr_t optval, unsigned int optlen,
 		       int (*push_pending_frames)(struct sock *));
diff --git a/net/atm/common.c b/net/atm/common.c
index e95371abd705..55844a930ccf 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -787,7 +787,7 @@ int vcc_setsockopt(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, optlen_t optlen)
 {
 	struct atm_vcc *vcc;
 	int len;
diff --git a/net/atm/common.h b/net/atm/common.h
index a1e56e8de698..67a25f92a929 100644
--- a/net/atm/common.h
+++ b/net/atm/common.h
@@ -23,7 +23,7 @@ int vcc_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
 int vcc_setsockopt(struct socket *sock, int level, int optname,
 		   sockptr_t optval, unsigned int optlen);
 int vcc_getsockopt(struct socket *sock, int level, int optname,
-		   char __user *optval, int __user *optlen);
+		   char __user *optval, optlen_t optlen);
 void vcc_process_recv_queue(struct atm_vcc *vcc);
 
 int atmpvc_init(void);
diff --git a/net/atm/pvc.c b/net/atm/pvc.c
index 66d9a9bd5896..2f01f862d0fb 100644
--- a/net/atm/pvc.c
+++ b/net/atm/pvc.c
@@ -75,7 +75,7 @@ static int pvc_setsockopt(struct socket *sock, int level, int optname,
 }
 
 static int pvc_getsockopt(struct socket *sock, int level, int optname,
-			  char __user *optval, int __user *optlen)
+			  char __user *optval, optlen_t optlen)
 {
 	struct sock *sk = sock->sk;
 	int error;
diff --git a/net/atm/svc.c b/net/atm/svc.c
index a706c5f77d8e..600f7d381348 100644
--- a/net/atm/svc.c
+++ b/net/atm/svc.c
@@ -501,7 +501,7 @@ static int svc_setsockopt(struct socket *sock, int level, int optname,
 }
 
 static int svc_getsockopt(struct socket *sock, int level, int optname,
-			  char __user *optval, int __user *optlen)
+			  char __user *optval, optlen_t optlen)
 {
 	struct sock *sk = sock->sk;
 	int error = 0, len;
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index b184e2cb4b50..0e069f2ceb12 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -715,7 +715,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
 }
 
 static int ax25_getsockopt(struct socket *sock, int level, int optname,
-	char __user *optval, int __user *optlen)
+	char __user *optval, optlen_t optlen)
 {
 	struct sock *sk = sock->sk;
 	ax25_cb *ax25;
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 4b4e476e4e7c..90949b8dad2e 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -2053,7 +2053,7 @@ static int hci_sock_setsockopt(struct socket *sock, int level, int optname,
 }
 
 static int hci_sock_getsockopt_old(struct socket *sock, int level, int optname,
-				   char __user *optval, int __user *optlen)
+				   char __user *optval, optlen_t optlen)
 {
 	struct hci_ufilter uf;
 	struct sock *sk = sock->sk;
@@ -2119,7 +2119,7 @@ static int hci_sock_getsockopt_old(struct socket *sock, int level, int optname,
 }
 
 static int hci_sock_getsockopt(struct socket *sock, int level, int optname,
-			       char __user *optval, int __user *optlen)
+			       char __user *optval, optlen_t optlen)
 {
 	struct sock *sk = sock->sk;
 	int err = 0;
diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
index f6624b6e5485..72369c912161 100644
--- a/net/bluetooth/iso.c
+++ b/net/bluetooth/iso.c
@@ -1721,7 +1721,7 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
 }
 
 static int iso_sock_getsockopt(struct socket *sock, int level, int optname,
-			       char __user *optval, int __user *optlen)
+			       char __user *optval, optlen_t optlen)
 {
 	struct sock *sk = sock->sk;
 	int len, err = 0;
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 8ae25a918fd3..ac36d0ec08d3 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -433,7 +433,7 @@ static int l2cap_get_mode(struct l2cap_chan *chan)
 }
 
 static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
-				     char __user *optval, int __user *optlen)
+				     char __user *optval, optlen_t optlen)
 {
 	struct sock *sk = sock->sk;
 	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
@@ -553,7 +553,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
 }
 
 static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
-				 char __user *optval, int __user *optlen)
+				 char __user *optval, optlen_t optlen)
 {
 	struct sock *sk = sock->sk;
 	struct l2cap_chan *chan = l2cap_pi(sk)->chan;
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 785894b79dd8..10ec25dc038d 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -722,7 +722,7 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname,
 	return err;
 }
 
-static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
+static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, optlen_t optlen)
 {
 	struct sock *sk = sock->sk;
 	struct sock *l2cap_sk;
@@ -798,7 +798,7 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u
 	return err;
 }
 
-static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
+static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, optlen_t optlen)
 {
 	struct sock *sk = sock->sk;
 	struct bt_security sec;
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 25910eca759c..e95d924fe41d 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -1037,7 +1037,7 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
 }
 
 static int sco_sock_getsockopt_old(struct socket *sock, int optname,
-				   char __user *optval, int __user *optlen)
+				   char __user *optval, optlen_t optlen)
 {
 	struct sock *sk = sock->sk;
 	struct sco_options opts;
@@ -1099,7 +1099,7 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname,
 }
 
 static int sco_sock_getsockopt(struct socket *sock, int level, int optname,
-			       char __user *optval, int __user *optlen)
+			       char __user *optval, optlen_t optlen)
 {
 	struct sock *sk = sock->sk;
 	int len, err = 0;
diff --git a/net/can/isotp.c b/net/can/isotp.c
index aa9ab87d5e14..2a321400a9f8 100644
--- a/net/can/isotp.c
+++ b/net/can/isotp.c
@@ -1486,7 +1486,7 @@ static int isotp_setsockopt(struct socket *sock, int level, int optname,
 }
 
 static int isotp_getsockopt(struct socket *sock, int level, int optname,
-			    char __user *optval, int __user *optlen)
+			    char __user *optval, optlen_t optlen)
 {
 	struct sock *sk = sock->sk;
 	struct isotp_sock *so = isotp_sk(sk);
diff --git a/net/can/j1939/socket.c b/net/can/j1939/socket.c
index b2b538528c2e..606f8b3ac96f 100644
--- a/net/can/j1939/socket.c
+++ b/net/can/j1939/socket.c
@@ -754,7 +754,7 @@ static int j1939_sk_setsockopt(struct socket *sock, int level, int optname,
 }
 
 static int j1939_sk_getsockopt(struct socket *sock, int level, int optname,
-			       char __user *optval, int __user *optlen)
+			       char __user *optval, optlen_t optlen)
 {
 	struct sock *sk = sock->sk;
 	struct j1939_sock *jsk = j1939_sk(sk);
diff --git a/net/can/raw.c b/net/can/raw.c
index 8d1a1626d1a4..59c6d701db05 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -753,7 +753,7 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
 }
 
 static int raw_getsockopt(struct socket *sock, int level, int optname,
-			  char __user *optval, int __user *optlen)
+			  char __user *optval, optlen_t optlen)
 {
 	struct sock *sk = sock->sk;
 	struct raw_sock *ro = raw_sk(sk);
diff --git a/net/core/sock.c b/net/core/sock.c
index 323892066def..2cd7bd5b2a05 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -3854,7 +3854,7 @@ EXPORT_SYMBOL(sock_recv_errqueue);
  *	this means if you specify SO_ERROR (otherwise what is the point of it).
  */
 int sock_common_getsockopt(struct socket *sock, int level, int optname,
-			   char __user *optval, int __user *optlen)
+			   char __user *optval, optlen_t optlen)
 {
 	struct sock *sk = sock->sk;
 
diff --git a/net/dccp/ccid.c b/net/dccp/ccid.c
index 6f495ffb1d60..b5fad2a7e9a8 100644
--- a/net/dccp/ccid.c
+++ b/net/dccp/ccid.c
@@ -58,7 +58,7 @@ int ccid_get_builtin_ccids(u8 **ccid_array, u8 *array_len)
 }
 
 int ccid_getsockopt_builtin_ccids(struct sock *sk, int len,
-				  char __user *optval, int __user *optlen)
+				  char __user *optval, optlen_t optlen)
 {
 	u8 *ccid_array, array_len;
 	int err = 0;
diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h
index 105f3734dadb..2758d760af36 100644
--- a/net/dccp/ccid.h
+++ b/net/dccp/ccid.h
@@ -78,11 +78,11 @@ struct ccid_operations {
 	int		(*ccid_hc_rx_getsockopt)(struct sock *sk,
 						 const int optname, int len,
 						 u32 __user *optval,
-						 int __user *optlen);
+						 optlen_t optlen);
 	int		(*ccid_hc_tx_getsockopt)(struct sock *sk,
 						 const int optname, int len,
 						 u32 __user *optval,
-						 int __user *optlen);
+						 optlen_t optlen);
 };
 
 extern struct ccid_operations ccid2_ops;
@@ -106,7 +106,7 @@ static inline void *ccid_priv(const struct ccid *ccid)
 bool ccid_support_check(u8 const *ccid_array, u8 array_len);
 int ccid_get_builtin_ccids(u8 **ccid_array, u8 *array_len);
 int ccid_getsockopt_builtin_ccids(struct sock *sk, int len,
-				  char __user *, int __user *);
+				  char __user *, optlen_t );
 
 struct ccid *ccid_new(const u8 id, struct sock *sk, bool rx);
 
@@ -240,7 +240,7 @@ static inline void ccid_hc_tx_get_info(struct ccid *ccid, struct sock *sk,
 
 static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk,
 					const int optname, int len,
-					u32 __user *optval, int __user *optlen)
+					u32 __user *optval, optlen_t optlen)
 {
 	int rc = -ENOPROTOOPT;
 	if (ccid != NULL && ccid->ccid_ops->ccid_hc_rx_getsockopt != NULL)
@@ -251,7 +251,7 @@ static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk,
 
 static inline int ccid_hc_tx_getsockopt(struct ccid *ccid, struct sock *sk,
 					const int optname, int len,
-					u32 __user *optval, int __user *optlen)
+					u32 __user *optval, optlen_t optlen)
 {
 	int rc = -ENOPROTOOPT;
 	if (ccid != NULL && ccid->ccid_ops->ccid_hc_tx_getsockopt != NULL)
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 648aa5270f37..8e4f16ccba57 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -518,7 +518,7 @@ static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info)
 }
 
 static int ccid3_hc_tx_getsockopt(struct sock *sk, const int optname, int len,
-				  u32 __user *optval, int __user *optlen)
+				  u32 __user *optval, optlen_t optlen)
 {
 	const struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk);
 	struct tfrc_tx_info tfrc;
@@ -813,7 +813,7 @@ static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
 }
 
 static int ccid3_hc_rx_getsockopt(struct sock *sk, const int optname, int len,
-				  u32 __user *optval, int __user *optlen)
+				  u32 __user *optval, optlen_t optlen)
 {
 	const struct ccid3_hc_rx_sock *hc = ccid3_hc_rx_sk(sk);
 	struct tfrc_rx_info rx_info;
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index 1f748ed1279d..f6d99913e1ca 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -289,7 +289,7 @@ struct sk_buff *dccp_make_response(const struct sock *sk, struct dst_entry *dst,
 int dccp_connect(struct sock *sk);
 int dccp_disconnect(struct sock *sk, int flags);
 int dccp_getsockopt(struct sock *sk, int level, int optname,
-		    char __user *optval, int __user *optlen);
+		    char __user *optval, optlen_t optlen);
 int dccp_setsockopt(struct sock *sk, int level, int optname,
 		    sockptr_t optval, unsigned int optlen);
 int dccp_ioctl(struct sock *sk, int cmd, int *karg);
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 8d6461ef8b50..2255f359058d 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -586,7 +586,7 @@ EXPORT_SYMBOL_GPL(dccp_setsockopt);
 
 static int dccp_getsockopt_service(struct sock *sk, int len,
 				   __be32 __user *optval,
-				   int __user *optlen)
+				   optlen_t optlen)
 {
 	const struct dccp_sock *dp = dccp_sk(sk);
 	const struct dccp_service_list *sl;
@@ -613,7 +613,7 @@ static int dccp_getsockopt_service(struct sock *sk, int len,
 }
 
 static int do_dccp_getsockopt(struct sock *sk, int level, int optname,
-		    char __user *optval, int __user *optlen)
+		    char __user *optval, optlen_t optlen)
 {
 	struct dccp_sock *dp;
 	int val, len;
@@ -681,7 +681,7 @@ static int do_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, optlen_t optlen)
 {
 	if (level != SOL_DCCP)
 		return inet_csk(sk)->icsk_af_ops->getsockopt(sk, level,
diff --git a/net/ieee802154/socket.c b/net/ieee802154/socket.c
index cc1788853c08..7fb31054c0ad 100644
--- a/net/ieee802154/socket.c
+++ b/net/ieee802154/socket.c
@@ -380,7 +380,7 @@ static void ieee802154_raw_deliver(struct net_device *dev, struct sk_buff *skb)
 }
 
 static int raw_getsockopt(struct sock *sk, int level, int optname,
-			  char __user *optval, int __user *optlen)
+			  char __user *optval, optlen_t optlen)
 {
 	return -EOPNOTSUPP;
 }
@@ -832,7 +832,7 @@ static int ieee802154_dgram_deliver(struct net_device *dev, struct sk_buff *skb)
 }
 
 static int dgram_getsockopt(struct sock *sk, int level, int optname,
-			    char __user *optval, int __user *optlen)
+			    char __user *optval, optlen_t optlen)
 {
 	struct dgram_sock *ro = dgram_sk(sk);
 
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 4d372f76b317..6757c8d12778 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -1758,12 +1758,12 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
 }
 
 int ip_getsockopt(struct sock *sk, int level,
-		  int optname, char __user *optval, int __user *optlen)
+		  int optname, char __user *optval, optlen_t optlen)
 {
 	int err;
 
 	err = do_ip_getsockopt(sk, level, optname,
-			       USER_SOCKPTR(optval), USER_SOCKPTR(optlen));
+			       USER_SOCKPTR(optval), OPTLEN_SOCKPTR(optlen));
 
 #ifdef CONFIG_NETFILTER
 	/* we need to exclude all possible ENOPROTOOPTs except default case */
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 89d70acdacdc..de8c67c08c20 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -807,7 +807,7 @@ static int raw_seticmpfilter(struct sock *sk, sockptr_t optval, int optlen)
 	return 0;
 }
 
-static int raw_geticmpfilter(struct sock *sk, char __user *optval, int __user *optlen)
+static int raw_geticmpfilter(struct sock *sk, char __user *optval, optlen_t optlen)
 {
 	int len, ret = -EFAULT;
 
@@ -847,7 +847,7 @@ static int raw_setsockopt(struct sock *sk, int level, int optname,
 }
 
 static int do_raw_getsockopt(struct sock *sk, int optname,
-			     char __user *optval, int __user *optlen)
+			     char __user *optval, optlen_t optlen)
 {
 	if (optname == ICMP_FILTER) {
 		if (inet_sk(sk)->inet_num != IPPROTO_ICMP)
@@ -859,7 +859,7 @@ static int do_raw_getsockopt(struct sock *sk, int optname,
 }
 
 static int raw_getsockopt(struct sock *sk, int level, int optname,
-			  char __user *optval, int __user *optlen)
+			  char __user *optval, optlen_t optlen)
 {
 	if (level != SOL_RAW)
 		return ip_getsockopt(sk, level, optname, optval, optlen);
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index ea8de00f669d..89d7a5b0364e 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -4732,7 +4732,7 @@ bool tcp_bpf_bypass_getsockopt(int level, int optname)
 EXPORT_IPV6_MOD(tcp_bpf_bypass_getsockopt);
 
 int tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
-		   int __user *optlen)
+		   optlen_t optlen)
 {
 	struct inet_connection_sock *icsk = inet_csk(sk);
 
@@ -4741,7 +4741,7 @@ int tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
 		return READ_ONCE(icsk->icsk_af_ops)->getsockopt(sk, level, optname,
 								optval, optlen);
 	return do_tcp_getsockopt(sk, level, optname, USER_SOCKPTR(optval),
-				 USER_SOCKPTR(optlen));
+				 OPTLEN_SOCKPTR(optlen));
 }
 EXPORT_IPV6_MOD(tcp_getsockopt);
 
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 17c3fb1acb30..b27954698f5e 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -3053,7 +3053,7 @@ int udp_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
 }
 
 int udp_lib_getsockopt(struct sock *sk, int level, int optname,
-		       char __user *optval, int __user *optlen)
+		       char __user *optval, optlen_t optlen)
 {
 	struct udp_sock *up = udp_sk(sk);
 	int val, len;
@@ -3114,7 +3114,7 @@ int udp_lib_getsockopt(struct sock *sk, int level, int optname,
 EXPORT_IPV6_MOD(udp_lib_getsockopt);
 
 int udp_getsockopt(struct sock *sk, int level, int optname,
-		   char __user *optval, int __user *optlen)
+		   char __user *optval, optlen_t optlen)
 {
 	if (level == SOL_UDP  ||  level == SOL_UDPLITE)
 		return udp_lib_getsockopt(sk, level, optname, optval, optlen);
diff --git a/net/ipv4/udp_impl.h b/net/ipv4/udp_impl.h
index e1ff3a375996..67a01fd5154f 100644
--- a/net/ipv4/udp_impl.h
+++ b/net/ipv4/udp_impl.h
@@ -15,7 +15,7 @@ void udp_v4_rehash(struct sock *sk);
 int udp_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
 		   unsigned int optlen);
 int udp_getsockopt(struct sock *sk, int level, int optname,
-		   char __user *optval, int __user *optlen);
+		   char __user *optval, optlen_t optlen);
 
 int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags,
 		int *addr_len);
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 9b1843288035..253e420802ca 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -1470,7 +1470,7 @@ int do_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, optlen_t optlen)
 {
 	int err;
 
@@ -1481,7 +1481,7 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname,
 		return -ENOPROTOOPT;
 
 	err = do_ipv6_getsockopt(sk, level, optname,
-				 USER_SOCKPTR(optval), USER_SOCKPTR(optlen));
+				 USER_SOCKPTR(optval), OPTLEN_SOCKPTR(optlen));
 #ifdef CONFIG_NETFILTER
 	/* we need to exclude all possible ENOPROTOOPTs except default case */
 	if (err == -ENOPROTOOPT && optname != IPV6_2292PKTOPTIONS) {
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 90216d7e2af6..679ba4799c79 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -951,7 +951,7 @@ static int rawv6_seticmpfilter(struct sock *sk, int optname,
 }
 
 static int rawv6_geticmpfilter(struct sock *sk, int optname,
-			       char __user *optval, int __user *optlen)
+			       char __user *optval, optlen_t optlen)
 {
 	int len;
 
@@ -1050,7 +1050,7 @@ static int rawv6_setsockopt(struct sock *sk, int level, int optname,
 }
 
 static int do_rawv6_getsockopt(struct sock *sk, int level, int optname,
-			    char __user *optval, int __user *optlen)
+			    char __user *optval, optlen_t optlen)
 {
 	struct raw6_sock *rp = raw6_sk(sk);
 	int val, len;
@@ -1088,7 +1088,7 @@ static int do_rawv6_getsockopt(struct sock *sk, int level, int optname,
 }
 
 static int rawv6_getsockopt(struct sock *sk, int level, int optname,
-			  char __user *optval, int __user *optlen)
+			  char __user *optval, optlen_t optlen)
 {
 	switch (level) {
 	case SOL_RAW:
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 024458ef163c..861691ba88cd 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1843,7 +1843,7 @@ int udpv6_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
 }
 
 int udpv6_getsockopt(struct sock *sk, int level, int optname,
-		     char __user *optval, int __user *optlen)
+		     char __user *optval, optlen_t optlen)
 {
 	if (level == SOL_UDP  ||  level == SOL_UDPLITE)
 		return udp_lib_getsockopt(sk, level, optname, optval, optlen);
diff --git a/net/ipv6/udp_impl.h b/net/ipv6/udp_impl.h
index 0590f566379d..a23db3c3ca9a 100644
--- a/net/ipv6/udp_impl.h
+++ b/net/ipv6/udp_impl.h
@@ -17,7 +17,7 @@ int udp_v6_get_port(struct sock *sk, unsigned short snum);
 void udp_v6_rehash(struct sock *sk);
 
 int udpv6_getsockopt(struct sock *sk, int level, int optname,
-		     char __user *optval, int __user *optlen);
+		     char __user *optval, optlen_t optlen);
 int udpv6_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
 		     unsigned int optlen);
 int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len);
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
index ce0c68c9513c..00b6ba3f23ff 100644
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -1533,7 +1533,7 @@ static int iucv_sock_setsockopt(struct socket *sock, int level, int optname,
 }
 
 static int iucv_sock_getsockopt(struct socket *sock, int level, int optname,
-				char __user *optval, int __user *optlen)
+				char __user *optval, optlen_t optlen)
 {
 	struct sock *sk = sock->sk;
 	struct iucv_sock *iucv = iucv_sk(sk);
diff --git a/net/kcm/kcmsock.c b/net/kcm/kcmsock.c
index 68b6a8bd0cdb..ddc46864643e 100644
--- a/net/kcm/kcmsock.c
+++ b/net/kcm/kcmsock.c
@@ -1145,7 +1145,7 @@ static int kcm_setsockopt(struct socket *sock, int level, int optname,
 }
 
 static int kcm_getsockopt(struct socket *sock, int level, int optname,
-			  char __user *optval, int __user *optlen)
+			  char __user *optval, optlen_t optlen)
 {
 	struct kcm_sock *kcm = kcm_sk(sock->sk);
 	int val, len;
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
index aa3e34ef6b5c..c9effe687625 100644
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -1332,7 +1332,7 @@ static int pppol2tp_session_getsockopt(struct sock *sk,
  * or the special tunnel type.
  */
 static int pppol2tp_getsockopt(struct socket *sock, int level, int optname,
-			       char __user *optval, int __user *optlen)
+			       char __user *optval, optlen_t optlen)
 {
 	struct sock *sk = sock->sk;
 	struct l2tp_session *session;
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
index a8e5d6eb5ad1..08ac78fb2b5d 100644
--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -1170,7 +1170,7 @@ static int llc_ui_setsockopt(struct socket *sock, int level, int optname,
  *	Get connection specific socket information.
  */
 static int llc_ui_getsockopt(struct socket *sock, int level, int optname,
-			     char __user *optval, int __user *optlen)
+			     char __user *optval, optlen_t optlen)
 {
 	struct sock *sk = sock->sk;
 	struct llc_sock *llc = llc_sk(sk);
diff --git a/net/mctp/af_mctp.c b/net/mctp/af_mctp.c
index 2cff81d47b76..ec34e4dc0642 100644
--- a/net/mctp/af_mctp.c
+++ b/net/mctp/af_mctp.c
@@ -327,7 +327,7 @@ static int mctp_setsockopt(struct socket *sock, int level, int optname,
 }
 
 static int mctp_getsockopt(struct socket *sock, int level, int optname,
-			   char __user *optval, int __user *optlen)
+			   char __user *optval, optlen_t optlen)
 {
 	struct mctp_sock *msk = container_of(sock->sk, struct mctp_sock, sk);
 	int len, val;
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index d409586b5977..7187d7583e7c 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -862,7 +862,7 @@ bool mptcp_schedule_work(struct sock *sk);
 int mptcp_setsockopt(struct sock *sk, int level, int optname,
 		     sockptr_t optval, unsigned int optlen);
 int mptcp_getsockopt(struct sock *sk, int level, int optname,
-		     char __user *optval, int __user *option);
+		     char __user *optval, optlen_t option);
 
 u64 __mptcp_expand_seq(u64 old_seq, u64 cur_seq);
 static inline u64 mptcp_expand_seq(u64 old_seq, u64 cur_seq, bool use_64bit)
diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c
index 25b780598888..88480bbcfd39 100644
--- a/net/mptcp/sockopt.c
+++ b/net/mptcp/sockopt.c
@@ -906,7 +906,7 @@ int mptcp_setsockopt(struct sock *sk, int level, int optname,
 }
 
 static int mptcp_getsockopt_first_sf_only(struct mptcp_sock *msk, int level, int optname,
-					  char __user *optval, int __user *optlen)
+					  char __user *optval, optlen_t optlen)
 {
 	struct sock *sk = (struct sock *)msk;
 	struct sock *ssk;
@@ -991,7 +991,7 @@ void mptcp_diag_fill_info(struct mptcp_sock *msk, struct mptcp_info *info)
 }
 EXPORT_SYMBOL_GPL(mptcp_diag_fill_info);
 
-static int mptcp_getsockopt_info(struct mptcp_sock *msk, char __user *optval, int __user *optlen)
+static int mptcp_getsockopt_info(struct mptcp_sock *msk, char __user *optval, optlen_t optlen)
 {
 	struct mptcp_info m_info;
 	int len;
@@ -1019,7 +1019,7 @@ static int mptcp_getsockopt_info(struct mptcp_sock *msk, char __user *optval, in
 static int mptcp_put_subflow_data(struct mptcp_subflow_data *sfd,
 				  char __user *optval,
 				  u32 copied,
-				  int __user *optlen)
+				  optlen_t optlen)
 {
 	u32 copylen = min_t(u32, sfd->size_subflow_data, sizeof(*sfd));
 
@@ -1039,7 +1039,7 @@ static int mptcp_put_subflow_data(struct mptcp_subflow_data *sfd,
 
 static int mptcp_get_subflow_data(struct mptcp_subflow_data *sfd,
 				  char __user *optval,
-				  int __user *optlen)
+				  optlen_t optlen)
 {
 	int len, copylen;
 
@@ -1076,7 +1076,7 @@ static int mptcp_get_subflow_data(struct mptcp_subflow_data *sfd,
 }
 
 static int mptcp_getsockopt_tcpinfo(struct mptcp_sock *msk, char __user *optval,
-				    int __user *optlen)
+				    optlen_t optlen)
 {
 	struct mptcp_subflow_context *subflow;
 	struct sock *sk = (struct sock *)msk;
@@ -1168,7 +1168,7 @@ static void mptcp_get_sub_addrs(const struct sock *sk, struct mptcp_subflow_addr
 }
 
 static int mptcp_getsockopt_subflow_addrs(struct mptcp_sock *msk, char __user *optval,
-					  int __user *optlen)
+					  optlen_t optlen)
 {
 	struct mptcp_subflow_context *subflow;
 	struct sock *sk = (struct sock *)msk;
@@ -1222,7 +1222,7 @@ static int mptcp_getsockopt_subflow_addrs(struct mptcp_sock *msk, char __user *o
 
 static int mptcp_get_full_info(struct mptcp_full_info *mfi,
 			       char __user *optval,
-			       int __user *optlen)
+			       optlen_t optlen)
 {
 	int len;
 
@@ -1254,7 +1254,7 @@ static int mptcp_get_full_info(struct mptcp_full_info *mfi,
 static int mptcp_put_full_info(struct mptcp_full_info *mfi,
 			       char __user *optval,
 			       u32 copylen,
-			       int __user *optlen)
+			       optlen_t optlen)
 {
 	copylen += MIN_FULL_INFO_OPTLEN_SIZE;
 	if (put_optlen(copylen, optlen))
@@ -1266,7 +1266,7 @@ static int mptcp_put_full_info(struct mptcp_full_info *mfi,
 }
 
 static int mptcp_getsockopt_full_info(struct mptcp_sock *msk, char __user *optval,
-				      int __user *optlen)
+				      optlen_t optlen)
 {
 	unsigned int sfcount = 0, copylen = 0;
 	struct mptcp_subflow_context *subflow;
@@ -1340,7 +1340,7 @@ static int mptcp_getsockopt_full_info(struct mptcp_sock *msk, char __user *optva
 }
 
 static int mptcp_put_int_option(struct mptcp_sock *msk, char __user *optval,
-				int __user *optlen, int val)
+				optlen_t optlen, int val)
 {
 	int len;
 
@@ -1369,7 +1369,7 @@ static int mptcp_put_int_option(struct mptcp_sock *msk, char __user *optval,
 }
 
 static int mptcp_getsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
-				    char __user *optval, int __user *optlen)
+				    char __user *optval, optlen_t optlen)
 {
 	struct sock *sk = (void *)msk;
 
@@ -1412,7 +1412,7 @@ static int mptcp_getsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
 }
 
 static int mptcp_getsockopt_v4(struct mptcp_sock *msk, int optname,
-			       char __user *optval, int __user *optlen)
+			       char __user *optval, optlen_t optlen)
 {
 	struct sock *sk = (void *)msk;
 
@@ -1437,7 +1437,7 @@ static int mptcp_getsockopt_v4(struct mptcp_sock *msk, int optname,
 }
 
 static int mptcp_getsockopt_v6(struct mptcp_sock *msk, int optname,
-			       char __user *optval, int __user *optlen)
+			       char __user *optval, optlen_t optlen)
 {
 	struct sock *sk = (void *)msk;
 
@@ -1457,7 +1457,7 @@ static int mptcp_getsockopt_v6(struct mptcp_sock *msk, int optname,
 }
 
 static int mptcp_getsockopt_sol_mptcp(struct mptcp_sock *msk, int optname,
-				      char __user *optval, int __user *optlen)
+				      char __user *optval, optlen_t optlen)
 {
 	switch (optname) {
 	case MPTCP_INFO:
@@ -1474,7 +1474,7 @@ static int mptcp_getsockopt_sol_mptcp(struct mptcp_sock *msk, int optname,
 }
 
 int mptcp_getsockopt(struct sock *sk, int level, int optname,
-		     char __user *optval, int __user *option)
+		     char __user *optval, optlen_t option)
 {
 	struct mptcp_sock *msk = mptcp_sk(sk);
 	struct sock *ssk;
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 3cde0f15deed..ffb6ff92abc9 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1705,7 +1705,7 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname,
 }
 
 static int netlink_getsockopt(struct socket *sock, int level, int optname,
-			      char __user *optval, int __user *optlen)
+			      char __user *optval, optlen_t optlen)
 {
 	struct sock *sk = sock->sk;
 	struct netlink_sock *nlk = nlk_sk(sk);
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index 6039b5219460..21335e970f4c 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -346,7 +346,7 @@ static int nr_setsockopt(struct socket *sock, int level, int optname,
 }
 
 static int nr_getsockopt(struct socket *sock, int level, int optname,
-	char __user *optval, int __user *optlen)
+	char __user *optval, optlen_t optlen)
 {
 	struct sock *sk = sock->sk;
 	struct nr_sock *nr = nr_sk(sk);
diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c
index 5e588640c22f..a19bd39a0329 100644
--- a/net/nfc/llcp_sock.c
+++ b/net/nfc/llcp_sock.c
@@ -302,7 +302,7 @@ static int nfc_llcp_setsockopt(struct socket *sock, int level, int optname,
 }
 
 static int nfc_llcp_getsockopt(struct socket *sock, int level, int optname,
-			       char __user *optval, int __user *optlen)
+			       char __user *optval, optlen_t optlen)
 {
 	struct nfc_llcp_local *local;
 	struct sock *sk = sock->sk;
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index f35ab96fbcad..6afa989386e4 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -4103,7 +4103,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, sockptr_t optval,
 }
 
 static int packet_getsockopt(struct socket *sock, int level, int optname,
-			     char __user *optval, int __user *optlen)
+			     char __user *optval, optlen_t optlen)
 {
 	int len;
 	int val, lv = sizeof(val);
diff --git a/net/phonet/pep.c b/net/phonet/pep.c
index 78b269ddf28b..d66776ed765e 100644
--- a/net/phonet/pep.c
+++ b/net/phonet/pep.c
@@ -1063,7 +1063,7 @@ static int pep_setsockopt(struct sock *sk, int level, int optname,
 }
 
 static int pep_getsockopt(struct sock *sk, int level, int optname,
-				char __user *optval, int __user *optlen)
+				char __user *optval, optlen_t optlen)
 {
 	struct pep_sock *pn = pep_sk(sk);
 	int len, val;
diff --git a/net/rds/af_rds.c b/net/rds/af_rds.c
index 3395062245c5..12bc0352ba6e 100644
--- a/net/rds/af_rds.c
+++ b/net/rds/af_rds.c
@@ -481,7 +481,7 @@ static int rds_setsockopt(struct socket *sock, int level, int optname,
 }
 
 static int rds_getsockopt(struct socket *sock, int level, int optname,
-			  char __user *optval, int __user *optlen)
+			  char __user *optval, optlen_t optlen)
 {
 	struct rds_sock *rs = rds_sk_to_rs(sock->sk);
 	int ret = -ENOPROTOOPT, len;
diff --git a/net/rds/info.c b/net/rds/info.c
index 1990d068f6ee..b0d594026a48 100644
--- a/net/rds/info.c
+++ b/net/rds/info.c
@@ -156,7 +156,7 @@ EXPORT_SYMBOL_GPL(rds_info_copy);
  * in the snapshot.
  */
 int rds_info_getsockopt(struct socket *sock, int optname, char __user *optval,
-			int __user *optlen)
+			optlen_t optlen)
 {
 	struct rds_info_iterator iter;
 	struct rds_info_lengths lens;
diff --git a/net/rds/info.h b/net/rds/info.h
index a069b51c4679..aa25aaeb154f 100644
--- a/net/rds/info.h
+++ b/net/rds/info.h
@@ -22,7 +22,7 @@ typedef void (*rds_info_func)(struct socket *sock, unsigned int len,
 void rds_info_register_func(int optname, rds_info_func func);
 void rds_info_deregister_func(int optname, rds_info_func func);
 int rds_info_getsockopt(struct socket *sock, int optname, char __user *optval,
-			int __user *optlen);
+			optlen_t optlen);
 void rds_info_copy(struct rds_info_iterator *iter, void *data,
 		   unsigned long bytes);
 void rds_info_iter_unmap(struct rds_info_iterator *iter);
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index a1299e9dd3e6..481279525981 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -453,7 +453,7 @@ static int rose_setsockopt(struct socket *sock, int level, int optname,
 }
 
 static int rose_getsockopt(struct socket *sock, int level, int optname,
-	char __user *optval, int __user *optlen)
+	char __user *optval, optlen_t optlen)
 {
 	struct sock *sk = sock->sk;
 	struct rose_sock *rose = rose_sk(sk);
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c
index a88c635888fd..0373aa629885 100644
--- a/net/rxrpc/af_rxrpc.c
+++ b/net/rxrpc/af_rxrpc.c
@@ -756,7 +756,7 @@ static int rxrpc_setsockopt(struct socket *sock, int level, int optname,
  * Get socket options.
  */
 static int rxrpc_getsockopt(struct socket *sock, int level, int optname,
-			    char __user *optval, int __user *_optlen)
+			    char __user *optval, optlen_t _optlen)
 {
 	int optlen;
 
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 5120dc7728b7..2f2f6f0058b0 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -1386,7 +1386,7 @@ struct compat_sctp_getaddrs_old {
 
 static int sctp_getsockopt_connectx3(struct sock *sk, int len,
 				     char __user *optval,
-				     int __user *optlen)
+				     optlen_t optlen)
 {
 	struct sctp_getaddrs_old param;
 	sctp_assoc_t assoc_id = 0;
@@ -4557,7 +4557,7 @@ static int sctp_setsockopt_probe_interval(struct sock *sk,
  * The syntax is:
  *
  *   ret = getsockopt(int sd, int level, int optname, void __user *optval,
- *                    int __user *optlen);
+ *                    optlen_t optlen);
  *   ret = setsockopt(int sd, int level, int optname, const void __user *optval,
  *                    int optlen);
  *
@@ -5412,7 +5412,7 @@ EXPORT_SYMBOL_GPL(sctp_transport_traverse_process);
  */
 static int sctp_getsockopt_sctp_status(struct sock *sk, int len,
 				       char __user *optval,
-				       int __user *optlen)
+				       optlen_t optlen)
 {
 	struct sctp_status status;
 	struct sctp_association *asoc = NULL;
@@ -5492,7 +5492,7 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len,
  */
 static int sctp_getsockopt_peer_addr_info(struct sock *sk, int len,
 					  char __user *optval,
-					  int __user *optlen)
+					  optlen_t optlen)
 {
 	struct sctp_paddrinfo pinfo;
 	struct sctp_transport *transport;
@@ -5554,7 +5554,7 @@ static int sctp_getsockopt_peer_addr_info(struct sock *sk, int len,
  * instead a error will be indicated to the user.
  */
 static int sctp_getsockopt_disable_fragments(struct sock *sk, int len,
-					char __user *optval, int __user *optlen)
+					char __user *optval, optlen_t optlen)
 {
 	int val;
 
@@ -5576,7 +5576,7 @@ static int sctp_getsockopt_disable_fragments(struct sock *sk, int len,
  * ancillary data the user wishes to receive.
  */
 static int sctp_getsockopt_events(struct sock *sk, int len, char __user *optval,
-				  int __user *optlen)
+				  optlen_t optlen)
 {
 	struct sctp_event_subscribe subscribe;
 	__u8 *sn_type = (__u8 *)&subscribe;
@@ -5610,7 +5610,7 @@ static int sctp_getsockopt_events(struct sock *sk, int len, char __user *optval,
  * integer defining the number of seconds of idle time before an
  * association is closed.
  */
-static int sctp_getsockopt_autoclose(struct sock *sk, int len, char __user *optval, int __user *optlen)
+static int sctp_getsockopt_autoclose(struct sock *sk, int len, char __user *optval, optlen_t optlen)
 {
 	/* Applicable to UDP-style socket only */
 	if (sctp_style(sk, TCP))
@@ -5712,7 +5712,7 @@ static int sctp_getsockopt_peeloff_common(struct sock *sk, sctp_peeloff_arg_t *p
 	return retval;
 }
 
-static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user *optval, int __user *optlen)
+static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user *optval, optlen_t optlen)
 {
 	sctp_peeloff_arg_t peeloff;
 	struct file *newfile = NULL;
@@ -5746,7 +5746,7 @@ static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user *optval
 }
 
 static int sctp_getsockopt_peeloff_flags(struct sock *sk, int len,
-					 char __user *optval, int __user *optlen)
+					 char __user *optval, optlen_t optlen)
 {
 	sctp_peeloff_flags_arg_t peeloff;
 	struct file *newfile = NULL;
@@ -5913,7 +5913,7 @@ static int sctp_getsockopt_peeloff_flags(struct sock *sk, int len,
  *                     IPv4- or IPv6- layer setting.
  */
 static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len,
-					    char __user *optval, int __user *optlen)
+					    char __user *optval, optlen_t optlen)
 {
 	struct sctp_paddrparams  params;
 	struct sctp_transport   *trans = NULL;
@@ -6057,7 +6057,7 @@ static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len,
  */
 static int sctp_getsockopt_delayed_ack(struct sock *sk, int len,
 					    char __user *optval,
-					    int __user *optlen)
+					    optlen_t optlen)
 {
 	struct sctp_sack_info    params;
 	struct sctp_association *asoc = NULL;
@@ -6129,7 +6129,7 @@ static int sctp_getsockopt_delayed_ack(struct sock *sk, int len,
  * by the change).  With TCP-style sockets, this option is inherited by
  * sockets derived from a listener socket.
  */
-static int sctp_getsockopt_initmsg(struct sock *sk, int len, char __user *optval, int __user *optlen)
+static int sctp_getsockopt_initmsg(struct sock *sk, int len, char __user *optval, optlen_t optlen)
 {
 	if (len < sizeof(struct sctp_initmsg))
 		return -EINVAL;
@@ -6143,7 +6143,7 @@ static int sctp_getsockopt_initmsg(struct sock *sk, int len, char __user *optval
 
 
 static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
-				      char __user *optval, int __user *optlen)
+				      char __user *optval, optlen_t optlen)
 {
 	struct sctp_association *asoc;
 	int cnt = 0;
@@ -6239,7 +6239,7 @@ static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to,
 
 
 static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
-				       char __user *optval, int __user *optlen)
+				       char __user *optval, optlen_t optlen)
 {
 	struct sctp_bind_addr *bp;
 	struct sctp_association *asoc;
@@ -6347,7 +6347,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
  * association peer's addresses.
  */
 static int sctp_getsockopt_primary_addr(struct sock *sk, int len,
-					char __user *optval, int __user *optlen)
+					char __user *optval, optlen_t optlen)
 {
 	struct sctp_prim prim;
 	struct sctp_association *asoc;
@@ -6389,7 +6389,7 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len,
  * Indication parameter for all future INIT and INIT-ACK exchanges.
  */
 static int sctp_getsockopt_adaptation_layer(struct sock *sk, int len,
-				  char __user *optval, int __user *optlen)
+				  char __user *optval, optlen_t optlen)
 {
 	struct sctp_setadaptation adaptation;
 
@@ -6429,7 +6429,7 @@ static int sctp_getsockopt_adaptation_layer(struct sock *sk, int len,
  */
 static int sctp_getsockopt_default_send_param(struct sock *sk,
 					int len, char __user *optval,
-					int __user *optlen)
+					optlen_t optlen)
 {
 	struct sctp_sock *sp = sctp_sk(sk);
 	struct sctp_association *asoc;
@@ -6475,7 +6475,7 @@ static int sctp_getsockopt_default_send_param(struct sock *sk,
  */
 static int sctp_getsockopt_default_sndinfo(struct sock *sk, int len,
 					   char __user *optval,
-					   int __user *optlen)
+					   optlen_t optlen)
 {
 	struct sctp_sock *sp = sctp_sk(sk);
 	struct sctp_association *asoc;
@@ -6525,7 +6525,7 @@ static int sctp_getsockopt_default_sndinfo(struct sock *sk, int len,
  */
 
 static int sctp_getsockopt_nodelay(struct sock *sk, int len,
-				   char __user *optval, int __user *optlen)
+				   char __user *optval, optlen_t optlen)
 {
 	int val;
 
@@ -6555,7 +6555,7 @@ static int sctp_getsockopt_nodelay(struct sock *sk, int len,
  */
 static int sctp_getsockopt_rtoinfo(struct sock *sk, int len,
 				char __user *optval,
-				int __user *optlen) {
+				optlen_t optlen) {
 	struct sctp_rtoinfo rtoinfo;
 	struct sctp_association *asoc;
 
@@ -6609,7 +6609,7 @@ static int sctp_getsockopt_rtoinfo(struct sock *sk, int len,
  */
 static int sctp_getsockopt_associnfo(struct sock *sk, int len,
 				     char __user *optval,
-				     int __user *optlen)
+				     optlen_t optlen)
 {
 
 	struct sctp_assocparams assocparams;
@@ -6677,7 +6677,7 @@ static int sctp_getsockopt_associnfo(struct sock *sk, int len,
  * addresses on the socket.
  */
 static int sctp_getsockopt_mappedv4(struct sock *sk, int len,
-				    char __user *optval, int __user *optlen)
+				    char __user *optval, optlen_t optlen)
 {
 	int val;
 	struct sctp_sock *sp = sctp_sk(sk);
@@ -6700,7 +6700,7 @@ static int sctp_getsockopt_mappedv4(struct sock *sk, int len,
  * (chapter and verse is quoted at sctp_setsockopt_context())
  */
 static int sctp_getsockopt_context(struct sock *sk, int len,
-				   char __user *optval, int __user *optlen)
+				   char __user *optval, optlen_t optlen)
 {
 	struct sctp_assoc_value params;
 	struct sctp_association *asoc;
@@ -6757,7 +6757,7 @@ static int sctp_getsockopt_context(struct sock *sk, int len,
  * assoc_value:  This parameter specifies the maximum size in bytes.
  */
 static int sctp_getsockopt_maxseg(struct sock *sk, int len,
-				  char __user *optval, int __user *optlen)
+				  char __user *optval, optlen_t optlen)
 {
 	struct sctp_assoc_value params;
 	struct sctp_association *asoc;
@@ -6804,7 +6804,7 @@ static int sctp_getsockopt_maxseg(struct sock *sk, int len,
  * (chapter and verse is quoted at sctp_setsockopt_fragment_interleave())
  */
 static int sctp_getsockopt_fragment_interleave(struct sock *sk, int len,
-					       char __user *optval, int __user *optlen)
+					       char __user *optval, optlen_t optlen)
 {
 	int val;
 
@@ -6828,7 +6828,7 @@ static int sctp_getsockopt_fragment_interleave(struct sock *sk, int len,
  */
 static int sctp_getsockopt_partial_delivery_point(struct sock *sk, int len,
 						  char __user *optval,
-						  int __user *optlen)
+						  optlen_t optlen)
 {
 	u32 val;
 
@@ -6852,7 +6852,7 @@ static int sctp_getsockopt_partial_delivery_point(struct sock *sk, int len,
  */
 static int sctp_getsockopt_maxburst(struct sock *sk, int len,
 				    char __user *optval,
-				    int __user *optlen)
+				    optlen_t optlen)
 {
 	struct sctp_assoc_value params;
 	struct sctp_association *asoc;
@@ -6891,7 +6891,7 @@ static int sctp_getsockopt_maxburst(struct sock *sk, int len,
 }
 
 static int sctp_getsockopt_hmac_ident(struct sock *sk, int len,
-				    char __user *optval, int __user *optlen)
+				    char __user *optval, optlen_t optlen)
 {
 	struct sctp_endpoint *ep = sctp_sk(sk)->ep;
 	struct sctp_hmacalgo  __user *p = (void __user *)optval;
@@ -6927,7 +6927,7 @@ static int sctp_getsockopt_hmac_ident(struct sock *sk, int len,
 }
 
 static int sctp_getsockopt_active_key(struct sock *sk, int len,
-				    char __user *optval, int __user *optlen)
+				    char __user *optval, optlen_t optlen)
 {
 	struct sctp_endpoint *ep = sctp_sk(sk)->ep;
 	struct sctp_authkeyid val;
@@ -6963,7 +6963,7 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len,
 }
 
 static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len,
-				    char __user *optval, int __user *optlen)
+				    char __user *optval, optlen_t optlen)
 {
 	struct sctp_authchunks __user *p = (void __user *)optval;
 	struct sctp_authchunks val;
@@ -7007,7 +7007,7 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len,
 }
 
 static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len,
-				    char __user *optval, int __user *optlen)
+				    char __user *optval, optlen_t optlen)
 {
 	struct sctp_endpoint *ep = sctp_sk(sk)->ep;
 	struct sctp_authchunks __user *p = (void __user *)optval;
@@ -7063,7 +7063,7 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len,
  * to a one-to-many style socket.  The option value is an uint32_t.
  */
 static int sctp_getsockopt_assoc_number(struct sock *sk, int len,
-				    char __user *optval, int __user *optlen)
+				    char __user *optval, optlen_t optlen)
 {
 	struct sctp_sock *sp = sctp_sk(sk);
 	struct sctp_association *asoc;
@@ -7094,7 +7094,7 @@ static int sctp_getsockopt_assoc_number(struct sock *sk, int len,
  * See the corresponding setsockopt entry as description
  */
 static int sctp_getsockopt_auto_asconf(struct sock *sk, int len,
-				   char __user *optval, int __user *optlen)
+				   char __user *optval, optlen_t optlen)
 {
 	int val = 0;
 
@@ -7119,7 +7119,7 @@ static int sctp_getsockopt_auto_asconf(struct sock *sk, int len,
  * the SCTP associations handled by a one-to-many style socket.
  */
 static int sctp_getsockopt_assoc_ids(struct sock *sk, int len,
-				    char __user *optval, int __user *optlen)
+				    char __user *optval, optlen_t optlen)
 {
 	struct sctp_sock *sp = sctp_sk(sk);
 	struct sctp_association *asoc;
@@ -7170,7 +7170,7 @@ static int sctp_getsockopt_assoc_ids(struct sock *sk, int len,
  */
 static int sctp_getsockopt_paddr_thresholds(struct sock *sk,
 					    char __user *optval, int len,
-					    int __user *optlen, bool v2)
+					    optlen_t optlen, bool v2)
 {
 	struct sctp_paddrthlds_v2 val;
 	struct sctp_transport *trans;
@@ -7229,7 +7229,7 @@ static int sctp_getsockopt_paddr_thresholds(struct sock *sk,
  */
 static int sctp_getsockopt_assoc_stats(struct sock *sk, int len,
 				       char __user *optval,
-				       int __user *optlen)
+				       optlen_t optlen)
 {
 	struct sctp_assoc_stats sas;
 	struct sctp_association *asoc = NULL;
@@ -7287,7 +7287,7 @@ static int sctp_getsockopt_assoc_stats(struct sock *sk, int len,
 
 static int sctp_getsockopt_recvrcvinfo(struct sock *sk,	int len,
 				       char __user *optval,
-				       int __user *optlen)
+				       optlen_t optlen)
 {
 	int val = 0;
 
@@ -7307,7 +7307,7 @@ static int sctp_getsockopt_recvrcvinfo(struct sock *sk,	int len,
 
 static int sctp_getsockopt_recvnxtinfo(struct sock *sk,	int len,
 				       char __user *optval,
-				       int __user *optlen)
+				       optlen_t optlen)
 {
 	int val = 0;
 
@@ -7327,7 +7327,7 @@ static int sctp_getsockopt_recvnxtinfo(struct sock *sk,	int len,
 
 static int sctp_getsockopt_pr_supported(struct sock *sk, int len,
 					char __user *optval,
-					int __user *optlen)
+					optlen_t optlen)
 {
 	struct sctp_assoc_value params;
 	struct sctp_association *asoc;
@@ -7366,7 +7366,7 @@ static int sctp_getsockopt_pr_supported(struct sock *sk, int len,
 
 static int sctp_getsockopt_default_prinfo(struct sock *sk, int len,
 					  char __user *optval,
-					  int __user *optlen)
+					  optlen_t optlen)
 {
 	struct sctp_default_prinfo info;
 	struct sctp_association *asoc;
@@ -7412,7 +7412,7 @@ static int sctp_getsockopt_default_prinfo(struct sock *sk, int len,
 
 static int sctp_getsockopt_pr_assocstatus(struct sock *sk, int len,
 					  char __user *optval,
-					  int __user *optlen)
+					  optlen_t optlen)
 {
 	struct sctp_prstatus params;
 	struct sctp_association *asoc;
@@ -7471,7 +7471,7 @@ static int sctp_getsockopt_pr_assocstatus(struct sock *sk, int len,
 
 static int sctp_getsockopt_pr_streamstatus(struct sock *sk, int len,
 					   char __user *optval,
-					   int __user *optlen)
+					   optlen_t optlen)
 {
 	struct sctp_stream_out_ext *streamoute;
 	struct sctp_association *asoc;
@@ -7535,7 +7535,7 @@ static int sctp_getsockopt_pr_streamstatus(struct sock *sk, int len,
 
 static int sctp_getsockopt_reconfig_supported(struct sock *sk, int len,
 					      char __user *optval,
-					      int __user *optlen)
+					      optlen_t optlen)
 {
 	struct sctp_assoc_value params;
 	struct sctp_association *asoc;
@@ -7574,7 +7574,7 @@ static int sctp_getsockopt_reconfig_supported(struct sock *sk, int len,
 
 static int sctp_getsockopt_enable_strreset(struct sock *sk, int len,
 					   char __user *optval,
-					   int __user *optlen)
+					   optlen_t optlen)
 {
 	struct sctp_assoc_value params;
 	struct sctp_association *asoc;
@@ -7613,7 +7613,7 @@ static int sctp_getsockopt_enable_strreset(struct sock *sk, int len,
 
 static int sctp_getsockopt_scheduler(struct sock *sk, int len,
 				     char __user *optval,
-				     int __user *optlen)
+				     optlen_t optlen)
 {
 	struct sctp_assoc_value params;
 	struct sctp_association *asoc;
@@ -7652,7 +7652,7 @@ static int sctp_getsockopt_scheduler(struct sock *sk, int len,
 
 static int sctp_getsockopt_scheduler_value(struct sock *sk, int len,
 					   char __user *optval,
-					   int __user *optlen)
+					   optlen_t optlen)
 {
 	struct sctp_stream_value params;
 	struct sctp_association *asoc;
@@ -7694,7 +7694,7 @@ static int sctp_getsockopt_scheduler_value(struct sock *sk, int len,
 
 static int sctp_getsockopt_interleaving_supported(struct sock *sk, int len,
 						  char __user *optval,
-						  int __user *optlen)
+						  optlen_t optlen)
 {
 	struct sctp_assoc_value params;
 	struct sctp_association *asoc;
@@ -7733,7 +7733,7 @@ static int sctp_getsockopt_interleaving_supported(struct sock *sk, int len,
 
 static int sctp_getsockopt_reuse_port(struct sock *sk, int len,
 				      char __user *optval,
-				      int __user *optlen)
+				      optlen_t optlen)
 {
 	int val;
 
@@ -7752,7 +7752,7 @@ static int sctp_getsockopt_reuse_port(struct sock *sk, int len,
 }
 
 static int sctp_getsockopt_event(struct sock *sk, int len, char __user *optval,
-				 int __user *optlen)
+				 optlen_t optlen)
 {
 	struct sctp_association *asoc;
 	struct sctp_event param;
@@ -7788,7 +7788,7 @@ static int sctp_getsockopt_event(struct sock *sk, int len, char __user *optval,
 
 static int sctp_getsockopt_asconf_supported(struct sock *sk, int len,
 					    char __user *optval,
-					    int __user *optlen)
+					    optlen_t optlen)
 {
 	struct sctp_assoc_value params;
 	struct sctp_association *asoc;
@@ -7827,7 +7827,7 @@ static int sctp_getsockopt_asconf_supported(struct sock *sk, int len,
 
 static int sctp_getsockopt_auth_supported(struct sock *sk, int len,
 					  char __user *optval,
-					  int __user *optlen)
+					  optlen_t optlen)
 {
 	struct sctp_assoc_value params;
 	struct sctp_association *asoc;
@@ -7866,7 +7866,7 @@ static int sctp_getsockopt_auth_supported(struct sock *sk, int len,
 
 static int sctp_getsockopt_ecn_supported(struct sock *sk, int len,
 					 char __user *optval,
-					 int __user *optlen)
+					 optlen_t optlen)
 {
 	struct sctp_assoc_value params;
 	struct sctp_association *asoc;
@@ -7905,7 +7905,7 @@ static int sctp_getsockopt_ecn_supported(struct sock *sk, int len,
 
 static int sctp_getsockopt_pf_expose(struct sock *sk, int len,
 				     char __user *optval,
-				     int __user *optlen)
+				     optlen_t optlen)
 {
 	struct sctp_assoc_value params;
 	struct sctp_association *asoc;
@@ -7943,7 +7943,7 @@ static int sctp_getsockopt_pf_expose(struct sock *sk, int len,
 }
 
 static int sctp_getsockopt_encap_port(struct sock *sk, int len,
-				      char __user *optval, int __user *optlen)
+				      char __user *optval, optlen_t optlen)
 {
 	struct sctp_association *asoc;
 	struct sctp_udpencaps encap;
@@ -8003,7 +8003,7 @@ static int sctp_getsockopt_encap_port(struct sock *sk, int len,
 
 static int sctp_getsockopt_probe_interval(struct sock *sk, int len,
 					  char __user *optval,
-					  int __user *optlen)
+					  optlen_t optlen)
 {
 	struct sctp_probeinterval params;
 	struct sctp_association *asoc;
@@ -8062,7 +8062,7 @@ static int sctp_getsockopt_probe_interval(struct sock *sk, int len,
 }
 
 static int sctp_getsockopt(struct sock *sk, int level, int optname,
-			   char __user *optval, int __user *optlen)
+			   char __user *optval, optlen_t optlen)
 {
 	int retval = 0;
 	int len;
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
index 405c0bff7121..da20193e2925 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -2989,7 +2989,7 @@ int smc_shutdown(struct socket *sock, int how)
 }
 
 static int __smc_getsockopt(struct socket *sock, int level, int optname,
-			    char __user *optval, int __user *optlen)
+			    char __user *optval, optlen_t optlen)
 {
 	struct smc_sock *smc;
 	int val, len;
@@ -3141,7 +3141,7 @@ int smc_setsockopt(struct socket *sock, int level, int optname,
 }
 
 int smc_getsockopt(struct socket *sock, int level, int optname,
-		   char __user *optval, int __user *optlen)
+		   char __user *optval, optlen_t optlen)
 {
 	struct smc_sock *smc;
 	int rc;
diff --git a/net/smc/smc.h b/net/smc/smc.h
index 78ae10d06ed2..abcf01824fa8 100644
--- a/net/smc/smc.h
+++ b/net/smc/smc.h
@@ -59,7 +59,7 @@ int smc_shutdown(struct socket *sock, int how);
 int smc_setsockopt(struct socket *sock, int level, int optname,
 		   sockptr_t optval, unsigned int optlen);
 int smc_getsockopt(struct socket *sock, int level, int optname,
-		   char __user *optval, int __user *optlen);
+		   char __user *optval, optlen_t optlen);
 int smc_sendmsg(struct socket *sock, struct msghdr *msg, size_t len);
 int smc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
 		int flags);
diff --git a/net/socket.c b/net/socket.c
index 9a0e720f0859..fa2de12c10e6 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -2350,12 +2350,15 @@ int do_sock_getsockopt(struct socket *sock, bool compat, int level,
 	} else if (unlikely(!ops->getsockopt)) {
 		err = -EOPNOTSUPP;
 	} else {
-		if (WARN_ONCE(optval.is_kernel || optlen.is_kernel,
+		optlen_t _optlen = { .up = NULL, };
+
+		if (WARN_ONCE(optval.is_kernel,
 			      "Invalid argument type"))
 			return -EOPNOTSUPP;
 
+		_optlen.up = optlen.user;
 		err = ops->getsockopt(sock, level, optname, optval.user,
-				      optlen.user);
+				      _optlen);
 	}
 
 	if (!compat)
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 23822d9230e4..24db67f7f21a 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -3229,7 +3229,7 @@ static int tipc_setsockopt(struct socket *sock, int lvl, int opt,
  * Return: 0 on success, errno otherwise
  */
 static int tipc_getsockopt(struct socket *sock, int lvl, int opt,
-			   char __user *ov, int __user *ol)
+			   char __user *ov, optlen_t ol)
 {
 	struct sock *sk = sock->sk;
 	struct tipc_sock *tsk = tipc_sk(sk);
diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c
index f4e87b4295b4..1069c8ca5aad 100644
--- a/net/tls/tls_main.c
+++ b/net/tls/tls_main.c
@@ -436,7 +436,7 @@ static __poll_t tls_sk_poll(struct file *file, struct socket *sock,
 }
 
 static int do_tls_getsockopt_conf(struct sock *sk, char __user *optval,
-				  int __user *optlen, int tx)
+				  optlen_t optlen, int tx)
 {
 	int rc = 0;
 	const struct tls_cipher_desc *cipher_desc;
@@ -497,7 +497,7 @@ static int do_tls_getsockopt_conf(struct sock *sk, char __user *optval,
 }
 
 static int do_tls_getsockopt_tx_zc(struct sock *sk, char __user *optval,
-				   int __user *optlen)
+				   optlen_t optlen)
 {
 	struct tls_context *ctx = tls_get_ctx(sk);
 	unsigned int value;
@@ -517,7 +517,7 @@ static int do_tls_getsockopt_tx_zc(struct sock *sk, char __user *optval,
 }
 
 static int do_tls_getsockopt_no_pad(struct sock *sk, char __user *optval,
-				    int __user *optlen)
+				    optlen_t optlen)
 {
 	struct tls_context *ctx = tls_get_ctx(sk);
 	int value, len;
@@ -545,7 +545,7 @@ static int do_tls_getsockopt_no_pad(struct sock *sk, char __user *optval,
 }
 
 static int do_tls_getsockopt(struct sock *sk, int optname,
-			     char __user *optval, int __user *optlen)
+			     char __user *optval, optlen_t optlen)
 {
 	int rc = 0;
 
@@ -574,7 +574,7 @@ static int do_tls_getsockopt(struct sock *sk, int optname,
 }
 
 static int tls_getsockopt(struct sock *sk, int level, int optname,
-			  char __user *optval, int __user *optlen)
+			  char __user *optval, optlen_t optlen)
 {
 	struct tls_context *ctx = tls_get_ctx(sk);
 
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index c21a3bfcdd75..5f4ff266cf5e 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -1866,7 +1866,7 @@ static int vsock_connectible_setsockopt(struct socket *sock,
 static int vsock_connectible_getsockopt(struct socket *sock,
 					int level, int optname,
 					char __user *optval,
-					int __user *optlen)
+					optlen_t optlen)
 {
 	struct sock *sk = sock->sk;
 	struct vsock_sock *vsk = vsock_sk(sk);
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index 4eb65c05b3b9..863819103621 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -448,7 +448,7 @@ static int x25_setsockopt(struct socket *sock, int level, int optname,
 }
 
 static int x25_getsockopt(struct socket *sock, int level, int optname,
-			  char __user *optval, int __user *optlen)
+			  char __user *optval, optlen_t optlen)
 {
 	struct sock *sk = sock->sk;
 	int val, len, rc = -ENOPROTOOPT;
diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c
index 7cae6f4114b5..7b75b6217ba1 100644
--- a/net/xdp/xsk.c
+++ b/net/xdp/xsk.c
@@ -1461,7 +1461,7 @@ struct xdp_statistics_v1 {
 };
 
 static int xsk_getsockopt(struct socket *sock, int level, int optname,
-			  char __user *optval, int __user *optlen)
+			  char __user *optval, optlen_t optlen)
 {
 	struct sock *sk = sock->sk;
 	struct xdp_sock *xs = xdp_sk(sk);
-- 
2.34.1
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help