]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
Bluetooth: RFCOMM: convert to getsockopt_iter
authorBreno Leitao <leitao@debian.org>
Tue, 12 May 2026 11:12:19 +0000 (04:12 -0700)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Thu, 11 Jun 2026 18:24:38 +0000 (14:24 -0400)
Convert RFCOMM 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 RFCOMM_LM.

Signed-off-by: Breno Leitao <leitao@debian.org>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
net/bluetooth/rfcomm/sock.c

index 805ed5d28ed6687a632ee64b8b36864140d4ab2d..ed31d5f4fc76f0a19da476b1a0a383e35a5242fa 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/export.h>
 #include <linux/debugfs.h>
 #include <linux/sched/signal.h>
+#include <linux/uio.h>
 
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
@@ -740,7 +741,8 @@ 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,
+                                     sockopt_t *sopt)
 {
        struct sock *sk = sock->sk;
        struct sock *l2cap_sk;
@@ -752,8 +754,7 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u
 
        BT_DBG("sk %p", sk);
 
-       if (get_user(len, optlen))
-               return -EFAULT;
+       len = sopt->optlen;
 
        lock_sock(sk);
 
@@ -782,7 +783,8 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u
                if (rfcomm_pi(sk)->role_switch)
                        opt |= RFCOMM_LM_MASTER;
 
-               if (put_user(opt, (u32 __user *) optval))
+               if (copy_to_iter(&opt, sizeof(opt), &sopt->iter_out) !=
+                   sizeof(opt))
                        err = -EFAULT;
 
                break;
@@ -802,7 +804,7 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u
                memcpy(cinfo.dev_class, 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;
@@ -816,23 +818,24 @@ 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,
+                                 sockopt_t *sopt)
 {
        struct sock *sk = sock->sk;
        struct bt_security sec;
        int err = 0;
        size_t len;
+       u32 opt;
 
        BT_DBG("sk %p", sk);
 
        if (level == SOL_RFCOMM)
-               return rfcomm_sock_getsockopt_old(sock, optname, optval, optlen);
+               return rfcomm_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);
 
@@ -847,7 +850,7 @@ static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, c
                sec.key_size = 0;
 
                len = min(len, sizeof(sec));
-               if (copy_to_user(optval, (char *) &sec, len))
+               if (copy_to_iter(&sec, len, &sopt->iter_out) != len)
                        err = -EFAULT;
 
                break;
@@ -858,8 +861,9 @@ static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, c
                        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;
@@ -1039,7 +1043,7 @@ static const struct proto_ops rfcomm_sock_ops = {
        .recvmsg        = rfcomm_sock_recvmsg,
        .shutdown       = rfcomm_sock_shutdown,
        .setsockopt     = rfcomm_sock_setsockopt,
-       .getsockopt     = rfcomm_sock_getsockopt,
+       .getsockopt_iter = rfcomm_sock_getsockopt,
        .ioctl          = rfcomm_sock_ioctl,
        .gettstamp      = sock_gettstamp,
        .poll           = bt_sock_poll,