atm: convert to getsockopt_iter

Convert the ATM SVC and PVC sockets, along with the shared
vcc_getsockopt() helper, to use the new getsockopt_iter callback with
sockopt_t.

Key changes:
- Replace (char __user *optval, int __user *optlen) with sockopt_t *opt
- Use opt->optlen for buffer length (input)
- Use copy_to_iter() instead of put_user()/copy_to_user()

Acked-by: Stanislav Fomichev <sdf@fomichev.me>
Signed-off-by: Breno Leitao <leitao@debian.org>
Link: https://patch.msgid.link/20260520-getsock_four-v3-2-b8c0b16b7780@debian.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Breno Leitao
2026-05-20 09:53:47 -07:00
committed by Jakub Kicinski
parent 347fdd4df8
commit 4177767daf
4 changed files with 22 additions and 19 deletions

View File

@@ -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;

View File

@@ -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);

View File

@@ -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,

View File

@@ -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 @@ 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)
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,