[PATCH net-next 5/7] Bluetooth: L2CAP: convert to getsockopt_iter

From: Breno Leitao

Date: Mon May 11 2026 - 06:51:01 EST


Convert L2CAP socket's getsockopt implementation to use the new
getsockopt_iter callback with sockopt_t.

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

The sockopt_t parameter is named sopt rather than opt to avoid
collision with the existing local u32 opt used by L2CAP_LM. The same
naming is reused for the new u32 helper in l2cap_sock_getsockopt(),
with mtu and mval helpers covering the u16 and u8 cases.

Signed-off-by: Breno Leitao <leitao@xxxxxxxxxx>
---
net/bluetooth/l2cap_sock.c | 61 ++++++++++++++++++++++++++++------------------
1 file changed, 37 insertions(+), 24 deletions(-)

diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index cf590a67d3641..dede550d60319 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -31,6 +31,7 @@
#include <linux/export.h>
#include <linux/filter.h>
#include <linux/sched/signal.h>
+#include <linux/uio.h>

#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
@@ -433,7 +434,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)
+ sockopt_t *sopt)
{
struct sock *sk = sock->sk;
struct l2cap_chan *chan = l2cap_pi(sk)->chan;
@@ -445,8 +446,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,

BT_DBG("sk %p", sk);

- if (get_user(len, optlen))
- return -EFAULT;
+ len = sopt->optlen;

lock_sock(sk);

@@ -488,7 +488,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
BT_DBG("mode 0x%2.2x", chan->mode);

len = min(len, sizeof(opts));
- if (copy_to_user(optval, (char *) &opts, len))
+ if (copy_to_iter(&opts, len, &sopt->iter_out) != len)
err = -EFAULT;

break;
@@ -520,7 +520,8 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags))
opt |= L2CAP_LM_RELIABLE;

- if (put_user(opt, (u32 __user *) optval))
+ if (copy_to_iter(&opt, sizeof(opt), &sopt->iter_out) !=
+ sizeof(opt))
err = -EFAULT;

break;
@@ -538,7 +539,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
memcpy(cinfo.dev_class, chan->conn->hcon->dev_class, 3);

len = min(len, sizeof(cinfo));
- if (copy_to_user(optval, (char *) &cinfo, len))
+ if (copy_to_iter(&cinfo, len, &sopt->iter_out) != len)
err = -EFAULT;

break;
@@ -553,25 +554,26 @@ 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)
+ sockopt_t *sopt)
{
struct sock *sk = sock->sk;
struct l2cap_chan *chan = l2cap_pi(sk)->chan;
struct bt_security sec;
struct bt_power pwr;
- u32 phys;
int len, mode, err = 0;
+ u32 opt;
+ u16 mtu;
+ u8 mval;

BT_DBG("sk %p", sk);

if (level == SOL_L2CAP)
- return l2cap_sock_getsockopt_old(sock, optname, optval, optlen);
+ return l2cap_sock_getsockopt_old(sock, optname, sopt);

if (level != SOL_BLUETOOTH)
return -ENOPROTOOPT;

- if (get_user(len, optlen))
- return -EFAULT;
+ len = sopt->optlen;

lock_sock(sk);

@@ -595,7 +597,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
}

len = min_t(unsigned int, len, sizeof(sec));
- if (copy_to_user(optval, (char *) &sec, len))
+ if (copy_to_iter(&sec, len, &sopt->iter_out) != len)
err = -EFAULT;

break;
@@ -606,15 +608,17 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
break;
}

- if (put_user(test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags),
- (u32 __user *) optval))
+ opt = test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
+ if (copy_to_iter(&opt, sizeof(opt), &sopt->iter_out) !=
+ sizeof(opt))
err = -EFAULT;

break;

case BT_FLUSHABLE:
- if (put_user(test_bit(FLAG_FLUSHABLE, &chan->flags),
- (u32 __user *) optval))
+ opt = test_bit(FLAG_FLUSHABLE, &chan->flags);
+ if (copy_to_iter(&opt, sizeof(opt), &sopt->iter_out) !=
+ sizeof(opt))
err = -EFAULT;

break;
@@ -629,13 +633,15 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
pwr.force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);

len = min_t(unsigned int, len, sizeof(pwr));
- if (copy_to_user(optval, (char *) &pwr, len))
+ if (copy_to_iter(&pwr, len, &sopt->iter_out) != len)
err = -EFAULT;

break;

case BT_CHANNEL_POLICY:
- if (put_user(chan->chan_policy, (u32 __user *) optval))
+ opt = chan->chan_policy;
+ if (copy_to_iter(&opt, sizeof(opt), &sopt->iter_out) !=
+ sizeof(opt))
err = -EFAULT;
break;

@@ -650,7 +656,9 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
break;
}

- if (put_user(chan->omtu, (u16 __user *) optval))
+ mtu = chan->omtu;
+ if (copy_to_iter(&mtu, sizeof(mtu), &sopt->iter_out) !=
+ sizeof(mtu))
err = -EFAULT;
break;

@@ -660,7 +668,9 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
break;
}

- if (put_user(chan->imtu, (u16 __user *) optval))
+ mtu = chan->imtu;
+ if (copy_to_iter(&mtu, sizeof(mtu), &sopt->iter_out) !=
+ sizeof(mtu))
err = -EFAULT;
break;

@@ -670,9 +680,10 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
break;
}

- phys = hci_conn_get_phy(chan->conn->hcon);
+ opt = hci_conn_get_phy(chan->conn->hcon);

- if (put_user(phys, (u32 __user *) optval))
+ if (copy_to_iter(&opt, sizeof(opt), &sopt->iter_out) !=
+ sizeof(opt))
err = -EFAULT;
break;

@@ -693,7 +704,9 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,
break;
}

- if (put_user(mode, (u8 __user *) optval))
+ mval = mode;
+ if (copy_to_iter(&mval, sizeof(mval), &sopt->iter_out) !=
+ sizeof(mval))
err = -EFAULT;
break;

@@ -2000,7 +2013,7 @@ static const struct proto_ops l2cap_sock_ops = {
.socketpair = sock_no_socketpair,
.shutdown = l2cap_sock_shutdown,
.setsockopt = l2cap_sock_setsockopt,
- .getsockopt = l2cap_sock_getsockopt
+ .getsockopt_iter = l2cap_sock_getsockopt
};

static const struct net_proto_family l2cap_sock_family_ops = {

--
2.53.0-Meta