diff options
| author | Jakub Kicinski <kuba@kernel.org> | 2026-05-22 11:11:11 -0700 |
|---|---|---|
| committer | Jakub Kicinski <kuba@kernel.org> | 2026-05-22 11:11:12 -0700 |
| commit | 95fab46aea57d6d7b76b319341acbefe8a9293c8 (patch) | |
| tree | 208c365c3d8ec85c01ba1e00d2e8271eff45f887 | |
| parent | c227f8aaf22cf5acc3a55a4fef1dd2bf110caebe (diff) | |
| parent | c56dbb469fe2a9263de77941c71a547f2a2b0331 (diff) | |
Merge branch 'net-convert-atm-xdp-af_iucv-l2tp_ppp-rxrpc-tipc-to-getsockopt_iter'
Breno Leitao says:
====================
net: convert atm/xdp/af_iucv/l2tp_ppp/rxrpc/tipc to getsockopt_iter
This series continues the conversion of the remaining proto_ops getsockopt
callbacks to the new getsockopt_iter callback introduced in commit 67fab22a7adc
("net: add getsockopt_iter callback to proto_ops").
The new callback takes a sockopt_t — a type-safe wrapper around iov_iter
plus an optlen field — instead of raw __user pointers. This:
- Replaces (char __user *optval, int __user *optlen) with sockopt_t *opt
- Reads the input buffer size from opt->optlen instead of get_user()
- Writes the option value via copy_to_iter() instead of copy_to_user()
- Reports the returned length via opt->optlen instead of put_user(),
independently of the bytes copied through the iter
Each conversion is a behaviour-preserving and code-style-preserving refactor;
no big changes being introduced, even when the code looks weird.
====================
Link: https://patch.msgid.link/20260520-getsock_four-v3-0-b8c0b16b7780@debian.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
| -rw-r--r-- | net/atm/common.c | 18 | ||||
| -rw-r--r-- | net/atm/common.h | 2 | ||||
| -rw-r--r-- | net/atm/pvc.c | 6 | ||||
| -rw-r--r-- | net/atm/svc.c | 15 | ||||
| -rw-r--r-- | net/iucv/af_iucv.c | 14 | ||||
| -rw-r--r-- | net/l2tp/l2tp_ppp.c | 20 | ||||
| -rw-r--r-- | net/rxrpc/af_rxrpc.c | 16 | ||||
| -rw-r--r-- | net/tipc/socket.c | 33 | ||||
| -rw-r--r-- | net/xdp/xsk.c | 24 |
9 files changed, 72 insertions, 76 deletions
diff --git a/net/atm/common.c b/net/atm/common.c index fe77f51f6ce1..60132de4eebe 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -23,6 +23,7 @@ #include <net/sock.h> /* struct sock */ #include <linux/uaccess.h> #include <linux/poll.h> +#include <linux/uio.h> #include <linux/atomic.h> @@ -797,13 +798,13 @@ 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) + sockopt_t *opt) { struct atm_vcc *vcc; + int val; int len; - if (get_user(len, optlen)) - return -EFAULT; + len = opt->optlen; if (__SO_LEVEL_MATCH(optname, level) && len != __SO_SIZE(optname)) return -EINVAL; @@ -812,11 +813,13 @@ int vcc_getsockopt(struct socket *sock, int level, int optname, case SO_ATMQOS: if (!test_bit(ATM_VF_HASQOS, &vcc->flags)) return -EINVAL; - return copy_to_user(optval, &vcc->qos, sizeof(vcc->qos)) + return copy_to_iter(&vcc->qos, sizeof(vcc->qos), + &opt->iter_out) != sizeof(vcc->qos) ? -EFAULT : 0; case SO_SETCLP: - return put_user(vcc->atm_options & ATM_ATMOPT_CLP ? 1 : 0, - (unsigned long __user *)optval) ? -EFAULT : 0; + val = vcc->atm_options & ATM_ATMOPT_CLP ? 1 : 0; + return copy_to_iter(&val, sizeof(val), &opt->iter_out) != + sizeof(val) ? -EFAULT : 0; case SO_ATMPVC: { struct sockaddr_atmpvc pvc; @@ -828,7 +831,8 @@ int vcc_getsockopt(struct socket *sock, int level, int optname, pvc.sap_addr.itf = vcc->dev->number; pvc.sap_addr.vpi = vcc->vpi; pvc.sap_addr.vci = vcc->vci; - return copy_to_user(optval, &pvc, sizeof(pvc)) ? -EFAULT : 0; + return copy_to_iter(&pvc, sizeof(pvc), &opt->iter_out) != + sizeof(pvc) ? -EFAULT : 0; } default: return -EINVAL; diff --git a/net/atm/common.h b/net/atm/common.h index a1e56e8de698..ae4502abf028 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); + sockopt_t *opt); 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 8f5e76f5dd9e..8b2c3e515601 100644 --- a/net/atm/pvc.c +++ b/net/atm/pvc.c @@ -75,13 +75,13 @@ 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) + sockopt_t *opt) { struct sock *sk = sock->sk; int error; lock_sock(sk); - error = vcc_getsockopt(sock, level, optname, optval, optlen); + error = vcc_getsockopt(sock, level, optname, opt); release_sock(sk); return error; } @@ -122,7 +122,7 @@ static const struct proto_ops pvc_proto_ops = { .listen = sock_no_listen, .shutdown = pvc_shutdown, .setsockopt = pvc_setsockopt, - .getsockopt = pvc_getsockopt, + .getsockopt_iter = pvc_getsockopt, .sendmsg = vcc_sendmsg, .recvmsg = vcc_recvmsg, .mmap = sock_no_mmap, diff --git a/net/atm/svc.c b/net/atm/svc.c index 005964250ecd..7c5559f50a99 100644 --- a/net/atm/svc.c +++ b/net/atm/svc.c @@ -21,6 +21,7 @@ #include <linux/bitops.h> #include <net/sock.h> /* for sock_no_* */ #include <linux/uaccess.h> +#include <linux/uio.h> #include <linux/export.h> #include "resources.h" @@ -501,25 +502,23 @@ out: } static int svc_getsockopt(struct socket *sock, int level, int optname, - char __user *optval, int __user *optlen) + sockopt_t *opt) { struct sock *sk = sock->sk; int error = 0, len; lock_sock(sk); if (!__SO_LEVEL_MATCH(optname, level) || optname != SO_ATMSAP) { - error = vcc_getsockopt(sock, level, optname, optval, optlen); - goto out; - } - if (get_user(len, optlen)) { - error = -EFAULT; + error = vcc_getsockopt(sock, level, optname, opt); goto out; } + len = opt->optlen; if (len != sizeof(struct atm_sap)) { error = -EINVAL; goto out; } - if (copy_to_user(optval, &ATM_SD(sock)->sap, sizeof(struct atm_sap))) { + if (copy_to_iter(&ATM_SD(sock)->sap, sizeof(struct atm_sap), + &opt->iter_out) != sizeof(struct atm_sap)) { error = -EFAULT; goto out; } @@ -650,7 +649,7 @@ static const struct proto_ops svc_proto_ops = { .listen = svc_listen, .shutdown = svc_shutdown, .setsockopt = svc_setsockopt, - .getsockopt = svc_getsockopt, + .getsockopt_iter = svc_getsockopt, .sendmsg = vcc_sendmsg, .recvmsg = vcc_recvmsg, .mmap = sock_no_mmap, diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 72dfccd4e3d5..7a5ce93a83d9 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -26,6 +26,7 @@ #include <linux/init.h> #include <linux/poll.h> #include <linux/security.h> +#include <linux/uio.h> #include <net/sock.h> #include <asm/machine.h> #include <asm/ebcdic.h> @@ -1535,7 +1536,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) + sockopt_t *opt) { struct sock *sk = sock->sk; struct iucv_sock *iucv = iucv_sk(sk); @@ -1545,9 +1546,7 @@ static int iucv_sock_getsockopt(struct socket *sock, int level, int optname, if (level != SOL_IUCV) return -ENOPROTOOPT; - if (get_user(len, optlen)) - return -EFAULT; - + len = opt->optlen; if (len < 0) return -EINVAL; @@ -1574,9 +1573,8 @@ static int iucv_sock_getsockopt(struct socket *sock, int level, int optname, return -ENOPROTOOPT; } - if (put_user(len, optlen)) - return -EFAULT; - if (copy_to_user(optval, &val, len)) + opt->optlen = len; + if (copy_to_iter(&val, len, &opt->iter_out) != len) return -EFAULT; return 0; @@ -2228,7 +2226,7 @@ static const struct proto_ops iucv_sock_ops = { .socketpair = sock_no_socketpair, .shutdown = iucv_sock_shutdown, .setsockopt = iucv_sock_setsockopt, - .getsockopt = iucv_sock_getsockopt, + .getsockopt_iter = iucv_sock_getsockopt, }; static int iucv_sock_create(struct net *net, struct socket *sock, int protocol, diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index 99d6582f41de..46143e882af5 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c @@ -59,6 +59,7 @@ #include <linux/string.h> #include <linux/list.h> #include <linux/uaccess.h> +#include <linux/uio.h> #include <linux/kernel.h> #include <linux/spinlock.h> @@ -1317,7 +1318,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) + sockopt_t *opt) { struct sock *sk = sock->sk; struct l2tp_session *session; @@ -1328,9 +1329,7 @@ static int pppol2tp_getsockopt(struct socket *sock, int level, int optname, if (level != SOL_PPPOL2TP) return -EINVAL; - if (get_user(len, optlen)) - return -EFAULT; - + len = opt->optlen; if (len < 0) return -EINVAL; @@ -1358,14 +1357,9 @@ static int pppol2tp_getsockopt(struct socket *sock, int level, int optname, goto end_put_sess; } - err = -EFAULT; - if (put_user(len, optlen)) - goto end_put_sess; - - if (copy_to_user((void __user *)optval, &val, len)) - goto end_put_sess; - - err = 0; + opt->optlen = len; + if (copy_to_iter(&val, len, &opt->iter_out) != len) + err = -EFAULT; end_put_sess: l2tp_session_put(session); @@ -1634,7 +1628,7 @@ static const struct proto_ops pppol2tp_ops = { .listen = sock_no_listen, .shutdown = sock_no_shutdown, .setsockopt = pppol2tp_setsockopt, - .getsockopt = pppol2tp_getsockopt, + .getsockopt_iter = pppol2tp_getsockopt, .sendmsg = pppol2tp_sendmsg, .recvmsg = pppol2tp_recvmsg, .mmap = sock_no_mmap, diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index 32ec91fa938f..9ab0f22c881e 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c @@ -16,6 +16,7 @@ #include <linux/poll.h> #include <linux/proc_fs.h> #include <linux/key-type.h> +#include <linux/uio.h> #include <net/net_namespace.h> #include <net/sock.h> #include <net/af_rxrpc.h> @@ -743,23 +744,24 @@ error: * Get socket options. */ static int rxrpc_getsockopt(struct socket *sock, int level, int optname, - char __user *optval, int __user *_optlen) + sockopt_t *opt) { - int optlen; + int optlen, val; if (level != SOL_RXRPC) return -EOPNOTSUPP; - if (get_user(optlen, _optlen)) - return -EFAULT; + optlen = opt->optlen; switch (optname) { case RXRPC_SUPPORTED_CMSG: if (optlen < sizeof(int)) return -ETOOSMALL; - if (put_user(RXRPC__SUPPORTED - 1, (int __user *)optval) || - put_user(sizeof(int), _optlen)) + val = RXRPC__SUPPORTED - 1; + if (copy_to_iter(&val, sizeof(val), &opt->iter_out) != + sizeof(val)) return -EFAULT; + opt->optlen = sizeof(val); return 0; default: @@ -1009,7 +1011,7 @@ static const struct proto_ops rxrpc_rpc_ops = { .listen = rxrpc_listen, .shutdown = rxrpc_shutdown, .setsockopt = rxrpc_setsockopt, - .getsockopt = rxrpc_getsockopt, + .getsockopt_iter = rxrpc_getsockopt, .sendmsg = rxrpc_sendmsg, .recvmsg = rxrpc_recvmsg, .mmap = sock_no_mmap, diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 9329919fb07f..3a94278a44ac 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -37,6 +37,7 @@ #include <linux/rhashtable.h> #include <linux/sched/signal.h> +#include <linux/uio.h> #include <trace/events/sock.h> #include "core.h" @@ -3220,8 +3221,7 @@ static int tipc_setsockopt(struct socket *sock, int lvl, int opt, * @sock: socket structure * @lvl: option level * @opt: option identifier - * @ov: receptacle for option value - * @ol: receptacle for length of option value + * @sopt: socket option container (input buffer length, output value/length) * * For stream sockets only, returns 0 length result for all IPPROTO_TCP options * (to ease compatibility). @@ -3229,22 +3229,22 @@ 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) + sockopt_t *sopt) { struct sock *sk = sock->sk; struct tipc_sock *tsk = tipc_sk(sk); struct tipc_service_range seq; int len, scope; + int res = 0; u32 value; - int res; - if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM)) - return put_user(0, ol); + if (lvl == IPPROTO_TCP && sock->type == SOCK_STREAM) { + sopt->optlen = 0; + return 0; + } if (lvl != SOL_TIPC) return -ENOPROTOOPT; - res = get_user(len, ol); - if (res) - return res; + len = sopt->optlen; lock_sock(sk); @@ -3260,7 +3260,6 @@ static int tipc_getsockopt(struct socket *sock, int lvl, int opt, break; case TIPC_CONN_TIMEOUT: value = tsk->conn_timeout; - /* no need to set "res", since already 0 at this point */ break; case TIPC_NODE_RECVQ_DEPTH: value = 0; /* was tipc_queue_size, now obsolete */ @@ -3284,15 +3283,17 @@ static int tipc_getsockopt(struct socket *sock, int lvl, int opt, release_sock(sk); if (res) - return res; /* "get" failed */ + return res; if (len < sizeof(value)) return -EINVAL; - if (copy_to_user(ov, &value, sizeof(value))) + if (copy_to_iter(&value, sizeof(value), &sopt->iter_out) != + sizeof(value)) return -EFAULT; + sopt->optlen = sizeof(value); - return put_user(sizeof(value), ol); + return 0; } static int tipc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) @@ -3365,7 +3366,7 @@ static const struct proto_ops msg_ops = { .listen = sock_no_listen, .shutdown = tipc_shutdown, .setsockopt = tipc_setsockopt, - .getsockopt = tipc_getsockopt, + .getsockopt_iter = tipc_getsockopt, .sendmsg = tipc_sendmsg, .recvmsg = tipc_recvmsg, .mmap = sock_no_mmap, @@ -3385,7 +3386,7 @@ static const struct proto_ops packet_ops = { .listen = tipc_listen, .shutdown = tipc_shutdown, .setsockopt = tipc_setsockopt, - .getsockopt = tipc_getsockopt, + .getsockopt_iter = tipc_getsockopt, .sendmsg = tipc_send_packet, .recvmsg = tipc_recvmsg, .mmap = sock_no_mmap, @@ -3405,7 +3406,7 @@ static const struct proto_ops stream_ops = { .listen = tipc_listen, .shutdown = tipc_shutdown, .setsockopt = tipc_setsockopt, - .getsockopt = tipc_getsockopt, + .getsockopt_iter = tipc_getsockopt, .sendmsg = tipc_sendstream, .recvmsg = tipc_recvstream, .mmap = sock_no_mmap, diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c index 5e5786cd9af5..77f8de054a1b 100644 --- a/net/xdp/xsk.c +++ b/net/xdp/xsk.c @@ -22,6 +22,7 @@ #include <linux/net.h> #include <linux/netdevice.h> #include <linux/rculist.h> +#include <linux/uio.h> #include <linux/vmalloc.h> #include <net/netdev_queues.h> @@ -1729,7 +1730,7 @@ struct xdp_statistics_v1 { }; static int xsk_getsockopt(struct socket *sock, int level, int optname, - char __user *optval, int __user *optlen) + sockopt_t *opt) { struct sock *sk = sock->sk; struct xdp_sock *xs = xdp_sk(sk); @@ -1738,8 +1739,7 @@ static int xsk_getsockopt(struct socket *sock, int level, int optname, if (level != SOL_XDP) return -ENOPROTOOPT; - if (get_user(len, optlen)) - return -EFAULT; + len = opt->optlen; if (len < 0) return -EINVAL; @@ -1773,10 +1773,10 @@ static int xsk_getsockopt(struct socket *sock, int level, int optname, stats.tx_invalid_descs = xskq_nb_invalid_descs(xs->tx); mutex_unlock(&xs->mutex); - if (copy_to_user(optval, &stats, stats_size)) - return -EFAULT; - if (put_user(stats_size, optlen)) + if (copy_to_iter(&stats, stats_size, &opt->iter_out) != + stats_size) return -EFAULT; + opt->optlen = stats_size; return 0; } @@ -1825,10 +1825,9 @@ static int xsk_getsockopt(struct socket *sock, int level, int optname, to_copy = &off_v1; } - if (copy_to_user(optval, to_copy, len)) - return -EFAULT; - if (put_user(len, optlen)) + if (copy_to_iter(to_copy, len, &opt->iter_out) != len) return -EFAULT; + opt->optlen = len; return 0; } @@ -1845,10 +1844,9 @@ static int xsk_getsockopt(struct socket *sock, int level, int optname, mutex_unlock(&xs->mutex); len = sizeof(opts); - if (copy_to_user(optval, &opts, len)) - return -EFAULT; - if (put_user(len, optlen)) + if (copy_to_iter(&opts, len, &opt->iter_out) != len) return -EFAULT; + opt->optlen = len; return 0; } @@ -1949,7 +1947,7 @@ static const struct proto_ops xsk_proto_ops = { .listen = sock_no_listen, .shutdown = sock_no_shutdown, .setsockopt = xsk_setsockopt, - .getsockopt = xsk_getsockopt, + .getsockopt_iter = xsk_getsockopt, .sendmsg = xsk_sendmsg, .recvmsg = xsk_recvmsg, .mmap = xsk_mmap, |
