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 --- 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 #include #include +#include #include #include @@ -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