Commit fe3eb406 authored by Paolo Abeni's avatar Paolo Abeni

Merge tag 'for-net-2024-04-10' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth

Luiz Augusto von Dentz says:

====================
bluetooth pull request for net:

  - L2CAP: Don't double set the HCI_CONN_MGMT_CONNECTED bit
  - Fix memory leak in hci_req_sync_complete
  - hci_sync: Fix using the same interval and window for Coded PHY
  - Fix not validating setsockopt user input

* tag 'for-net-2024-04-10' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth:
  Bluetooth: l2cap: Don't double set the HCI_CONN_MGMT_CONNECTED bit
  Bluetooth: hci_sock: Fix not validating setsockopt user input
  Bluetooth: ISO: Fix not validating setsockopt user input
  Bluetooth: L2CAP: Fix not validating setsockopt user input
  Bluetooth: RFCOMM: Fix not validating setsockopt user input
  Bluetooth: SCO: Fix not validating setsockopt user input
  Bluetooth: Fix memory leak in hci_req_sync_complete()
  Bluetooth: hci_sync: Fix using the same interval and window for Coded PHY
  Bluetooth: ISO: Don't reject BT_ISO_QOS if parameters are unset
====================

Link: https://lore.kernel.org/r/20240410191610.4156653-1-luiz.dentz@gmail.comSigned-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents 47d8ac01 600b0bbe
...@@ -585,6 +585,15 @@ static inline struct sk_buff *bt_skb_sendmmsg(struct sock *sk, ...@@ -585,6 +585,15 @@ static inline struct sk_buff *bt_skb_sendmmsg(struct sock *sk,
return skb; return skb;
} }
static inline int bt_copy_from_sockptr(void *dst, size_t dst_size,
sockptr_t src, size_t src_size)
{
if (dst_size > src_size)
return -EINVAL;
return copy_from_sockptr(dst, src, dst_size);
}
int bt_to_errno(u16 code); int bt_to_errno(u16 code);
__u8 bt_status(int err); __u8 bt_status(int err);
......
...@@ -105,8 +105,10 @@ void hci_req_sync_complete(struct hci_dev *hdev, u8 result, u16 opcode, ...@@ -105,8 +105,10 @@ void hci_req_sync_complete(struct hci_dev *hdev, u8 result, u16 opcode,
if (hdev->req_status == HCI_REQ_PEND) { if (hdev->req_status == HCI_REQ_PEND) {
hdev->req_result = result; hdev->req_result = result;
hdev->req_status = HCI_REQ_DONE; hdev->req_status = HCI_REQ_DONE;
if (skb) if (skb) {
kfree_skb(hdev->req_skb);
hdev->req_skb = skb_get(skb); hdev->req_skb = skb_get(skb);
}
wake_up_interruptible(&hdev->req_wait_q); wake_up_interruptible(&hdev->req_wait_q);
} }
} }
......
...@@ -1946,10 +1946,9 @@ static int hci_sock_setsockopt_old(struct socket *sock, int level, int optname, ...@@ -1946,10 +1946,9 @@ static int hci_sock_setsockopt_old(struct socket *sock, int level, int optname,
switch (optname) { switch (optname) {
case HCI_DATA_DIR: case HCI_DATA_DIR:
if (copy_from_sockptr(&opt, optval, sizeof(opt))) { err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, len);
err = -EFAULT; if (err)
break; break;
}
if (opt) if (opt)
hci_pi(sk)->cmsg_mask |= HCI_CMSG_DIR; hci_pi(sk)->cmsg_mask |= HCI_CMSG_DIR;
...@@ -1958,10 +1957,9 @@ static int hci_sock_setsockopt_old(struct socket *sock, int level, int optname, ...@@ -1958,10 +1957,9 @@ static int hci_sock_setsockopt_old(struct socket *sock, int level, int optname,
break; break;
case HCI_TIME_STAMP: case HCI_TIME_STAMP:
if (copy_from_sockptr(&opt, optval, sizeof(opt))) { err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, len);
err = -EFAULT; if (err)
break; break;
}
if (opt) if (opt)
hci_pi(sk)->cmsg_mask |= HCI_CMSG_TSTAMP; hci_pi(sk)->cmsg_mask |= HCI_CMSG_TSTAMP;
...@@ -1979,11 +1977,9 @@ static int hci_sock_setsockopt_old(struct socket *sock, int level, int optname, ...@@ -1979,11 +1977,9 @@ static int hci_sock_setsockopt_old(struct socket *sock, int level, int optname,
uf.event_mask[1] = *((u32 *) f->event_mask + 1); uf.event_mask[1] = *((u32 *) f->event_mask + 1);
} }
len = min_t(unsigned int, len, sizeof(uf)); err = bt_copy_from_sockptr(&uf, sizeof(uf), optval, len);
if (copy_from_sockptr(&uf, optval, len)) { if (err)
err = -EFAULT;
break; break;
}
if (!capable(CAP_NET_RAW)) { if (!capable(CAP_NET_RAW)) {
uf.type_mask &= hci_sec_filter.type_mask; uf.type_mask &= hci_sec_filter.type_mask;
...@@ -2042,10 +2038,9 @@ static int hci_sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -2042,10 +2038,9 @@ static int hci_sock_setsockopt(struct socket *sock, int level, int optname,
goto done; goto done;
} }
if (copy_from_sockptr(&opt, optval, sizeof(opt))) { err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, len);
err = -EFAULT; if (err)
break; break;
}
hci_pi(sk)->mtu = opt; hci_pi(sk)->mtu = opt;
break; break;
......
...@@ -2814,8 +2814,8 @@ static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type, ...@@ -2814,8 +2814,8 @@ static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type,
if (qos->bcast.in.phy & BT_ISO_PHY_CODED) { if (qos->bcast.in.phy & BT_ISO_PHY_CODED) {
cp->scanning_phys |= LE_SCAN_PHY_CODED; cp->scanning_phys |= LE_SCAN_PHY_CODED;
hci_le_scan_phy_params(phy, type, hci_le_scan_phy_params(phy, type,
interval, interval * 3,
window); window * 3);
num_phy++; num_phy++;
phy++; phy++;
} }
...@@ -2835,7 +2835,7 @@ static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type, ...@@ -2835,7 +2835,7 @@ static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type,
if (scan_coded(hdev)) { if (scan_coded(hdev)) {
cp->scanning_phys |= LE_SCAN_PHY_CODED; cp->scanning_phys |= LE_SCAN_PHY_CODED;
hci_le_scan_phy_params(phy, type, interval, window); hci_le_scan_phy_params(phy, type, interval * 3, window * 3);
num_phy++; num_phy++;
phy++; phy++;
} }
......
...@@ -1451,8 +1451,8 @@ static bool check_ucast_qos(struct bt_iso_qos *qos) ...@@ -1451,8 +1451,8 @@ static bool check_ucast_qos(struct bt_iso_qos *qos)
static bool check_bcast_qos(struct bt_iso_qos *qos) static bool check_bcast_qos(struct bt_iso_qos *qos)
{ {
if (qos->bcast.sync_factor == 0x00) if (!qos->bcast.sync_factor)
return false; qos->bcast.sync_factor = 0x01;
if (qos->bcast.packing > 0x01) if (qos->bcast.packing > 0x01)
return false; return false;
...@@ -1475,6 +1475,9 @@ static bool check_bcast_qos(struct bt_iso_qos *qos) ...@@ -1475,6 +1475,9 @@ static bool check_bcast_qos(struct bt_iso_qos *qos)
if (qos->bcast.skip > 0x01f3) if (qos->bcast.skip > 0x01f3)
return false; return false;
if (!qos->bcast.sync_timeout)
qos->bcast.sync_timeout = BT_ISO_SYNC_TIMEOUT;
if (qos->bcast.sync_timeout < 0x000a || qos->bcast.sync_timeout > 0x4000) if (qos->bcast.sync_timeout < 0x000a || qos->bcast.sync_timeout > 0x4000)
return false; return false;
...@@ -1484,6 +1487,9 @@ static bool check_bcast_qos(struct bt_iso_qos *qos) ...@@ -1484,6 +1487,9 @@ static bool check_bcast_qos(struct bt_iso_qos *qos)
if (qos->bcast.mse > 0x1f) if (qos->bcast.mse > 0x1f)
return false; return false;
if (!qos->bcast.timeout)
qos->bcast.sync_timeout = BT_ISO_SYNC_TIMEOUT;
if (qos->bcast.timeout < 0x000a || qos->bcast.timeout > 0x4000) if (qos->bcast.timeout < 0x000a || qos->bcast.timeout > 0x4000)
return false; return false;
...@@ -1494,7 +1500,7 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -1494,7 +1500,7 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
sockptr_t optval, unsigned int optlen) sockptr_t optval, unsigned int optlen)
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
int len, err = 0; int err = 0;
struct bt_iso_qos qos = default_qos; struct bt_iso_qos qos = default_qos;
u32 opt; u32 opt;
...@@ -1509,10 +1515,9 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -1509,10 +1515,9 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
break; break;
} }
if (copy_from_sockptr(&opt, optval, sizeof(u32))) { err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
err = -EFAULT; if (err)
break; break;
}
if (opt) if (opt)
set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags); set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
...@@ -1521,10 +1526,9 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -1521,10 +1526,9 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
break; break;
case BT_PKT_STATUS: case BT_PKT_STATUS:
if (copy_from_sockptr(&opt, optval, sizeof(u32))) { err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
err = -EFAULT; if (err)
break; break;
}
if (opt) if (opt)
set_bit(BT_SK_PKT_STATUS, &bt_sk(sk)->flags); set_bit(BT_SK_PKT_STATUS, &bt_sk(sk)->flags);
...@@ -1539,17 +1543,9 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -1539,17 +1543,9 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
break; break;
} }
len = min_t(unsigned int, sizeof(qos), optlen); err = bt_copy_from_sockptr(&qos, sizeof(qos), optval, optlen);
if (err)
if (copy_from_sockptr(&qos, optval, len)) {
err = -EFAULT;
break;
}
if (len == sizeof(qos.ucast) && !check_ucast_qos(&qos)) {
err = -EINVAL;
break; break;
}
iso_pi(sk)->qos = qos; iso_pi(sk)->qos = qos;
iso_pi(sk)->qos_user_set = true; iso_pi(sk)->qos_user_set = true;
...@@ -1564,18 +1560,16 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -1564,18 +1560,16 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
} }
if (optlen > sizeof(iso_pi(sk)->base)) { if (optlen > sizeof(iso_pi(sk)->base)) {
err = -EOVERFLOW; err = -EINVAL;
break; break;
} }
len = min_t(unsigned int, sizeof(iso_pi(sk)->base), optlen); err = bt_copy_from_sockptr(iso_pi(sk)->base, optlen, optval,
optlen);
if (copy_from_sockptr(iso_pi(sk)->base, optval, len)) { if (err)
err = -EFAULT;
break; break;
}
iso_pi(sk)->base_len = len; iso_pi(sk)->base_len = optlen;
break; break;
......
...@@ -4054,8 +4054,7 @@ static int l2cap_connect_req(struct l2cap_conn *conn, ...@@ -4054,8 +4054,7 @@ static int l2cap_connect_req(struct l2cap_conn *conn,
return -EPROTO; return -EPROTO;
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (hci_dev_test_flag(hdev, HCI_MGMT) && if (hci_dev_test_flag(hdev, HCI_MGMT))
!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags))
mgmt_device_connected(hdev, hcon, NULL, 0); mgmt_device_connected(hdev, hcon, NULL, 0);
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
......
...@@ -727,7 +727,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, ...@@ -727,7 +727,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct l2cap_chan *chan = l2cap_pi(sk)->chan; struct l2cap_chan *chan = l2cap_pi(sk)->chan;
struct l2cap_options opts; struct l2cap_options opts;
int len, err = 0; int err = 0;
u32 opt; u32 opt;
BT_DBG("sk %p", sk); BT_DBG("sk %p", sk);
...@@ -754,11 +754,9 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, ...@@ -754,11 +754,9 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
opts.max_tx = chan->max_tx; opts.max_tx = chan->max_tx;
opts.txwin_size = chan->tx_win; opts.txwin_size = chan->tx_win;
len = min_t(unsigned int, sizeof(opts), optlen); err = bt_copy_from_sockptr(&opts, sizeof(opts), optval, optlen);
if (copy_from_sockptr(&opts, optval, len)) { if (err)
err = -EFAULT;
break; break;
}
if (opts.txwin_size > L2CAP_DEFAULT_EXT_WINDOW) { if (opts.txwin_size > L2CAP_DEFAULT_EXT_WINDOW) {
err = -EINVAL; err = -EINVAL;
...@@ -801,10 +799,9 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, ...@@ -801,10 +799,9 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
break; break;
case L2CAP_LM: case L2CAP_LM:
if (copy_from_sockptr(&opt, optval, sizeof(u32))) { err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
err = -EFAULT; if (err)
break; break;
}
if (opt & L2CAP_LM_FIPS) { if (opt & L2CAP_LM_FIPS) {
err = -EINVAL; err = -EINVAL;
...@@ -885,7 +882,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -885,7 +882,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
struct bt_security sec; struct bt_security sec;
struct bt_power pwr; struct bt_power pwr;
struct l2cap_conn *conn; struct l2cap_conn *conn;
int len, err = 0; int err = 0;
u32 opt; u32 opt;
u16 mtu; u16 mtu;
u8 mode; u8 mode;
...@@ -911,11 +908,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -911,11 +908,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
sec.level = BT_SECURITY_LOW; sec.level = BT_SECURITY_LOW;
len = min_t(unsigned int, sizeof(sec), optlen); err = bt_copy_from_sockptr(&sec, sizeof(sec), optval, optlen);
if (copy_from_sockptr(&sec, optval, len)) { if (err)
err = -EFAULT;
break; break;
}
if (sec.level < BT_SECURITY_LOW || if (sec.level < BT_SECURITY_LOW ||
sec.level > BT_SECURITY_FIPS) { sec.level > BT_SECURITY_FIPS) {
...@@ -960,10 +955,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -960,10 +955,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
break; break;
} }
if (copy_from_sockptr(&opt, optval, sizeof(u32))) { err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
err = -EFAULT; if (err)
break; break;
}
if (opt) { if (opt) {
set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags); set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
...@@ -975,10 +969,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -975,10 +969,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
break; break;
case BT_FLUSHABLE: case BT_FLUSHABLE:
if (copy_from_sockptr(&opt, optval, sizeof(u32))) { err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
err = -EFAULT; if (err)
break; break;
}
if (opt > BT_FLUSHABLE_ON) { if (opt > BT_FLUSHABLE_ON) {
err = -EINVAL; err = -EINVAL;
...@@ -1010,11 +1003,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -1010,11 +1003,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
pwr.force_active = BT_POWER_FORCE_ACTIVE_ON; pwr.force_active = BT_POWER_FORCE_ACTIVE_ON;
len = min_t(unsigned int, sizeof(pwr), optlen); err = bt_copy_from_sockptr(&pwr, sizeof(pwr), optval, optlen);
if (copy_from_sockptr(&pwr, optval, len)) { if (err)
err = -EFAULT;
break; break;
}
if (pwr.force_active) if (pwr.force_active)
set_bit(FLAG_FORCE_ACTIVE, &chan->flags); set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
...@@ -1023,10 +1014,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -1023,10 +1014,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
break; break;
case BT_CHANNEL_POLICY: case BT_CHANNEL_POLICY:
if (copy_from_sockptr(&opt, optval, sizeof(u32))) { err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
err = -EFAULT; if (err)
break; break;
}
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
break; break;
...@@ -1055,10 +1045,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -1055,10 +1045,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
break; break;
} }
if (copy_from_sockptr(&mtu, optval, sizeof(u16))) { err = bt_copy_from_sockptr(&mtu, sizeof(mtu), optval, optlen);
err = -EFAULT; if (err)
break; break;
}
if (chan->mode == L2CAP_MODE_EXT_FLOWCTL && if (chan->mode == L2CAP_MODE_EXT_FLOWCTL &&
sk->sk_state == BT_CONNECTED) sk->sk_state == BT_CONNECTED)
...@@ -1086,10 +1075,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -1086,10 +1075,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
break; break;
} }
if (copy_from_sockptr(&mode, optval, sizeof(u8))) { err = bt_copy_from_sockptr(&mode, sizeof(mode), optval, optlen);
err = -EFAULT; if (err)
break; break;
}
BT_DBG("mode %u", mode); BT_DBG("mode %u", mode);
......
...@@ -629,7 +629,7 @@ static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, ...@@ -629,7 +629,7 @@ static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname,
switch (optname) { switch (optname) {
case RFCOMM_LM: case RFCOMM_LM:
if (copy_from_sockptr(&opt, optval, sizeof(u32))) { if (bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen)) {
err = -EFAULT; err = -EFAULT;
break; break;
} }
...@@ -664,7 +664,6 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -664,7 +664,6 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname,
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct bt_security sec; struct bt_security sec;
int err = 0; int err = 0;
size_t len;
u32 opt; u32 opt;
BT_DBG("sk %p", sk); BT_DBG("sk %p", sk);
...@@ -686,11 +685,9 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -686,11 +685,9 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname,
sec.level = BT_SECURITY_LOW; sec.level = BT_SECURITY_LOW;
len = min_t(unsigned int, sizeof(sec), optlen); err = bt_copy_from_sockptr(&sec, sizeof(sec), optval, optlen);
if (copy_from_sockptr(&sec, optval, len)) { if (err)
err = -EFAULT;
break; break;
}
if (sec.level > BT_SECURITY_HIGH) { if (sec.level > BT_SECURITY_HIGH) {
err = -EINVAL; err = -EINVAL;
...@@ -706,10 +703,9 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -706,10 +703,9 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname,
break; break;
} }
if (copy_from_sockptr(&opt, optval, sizeof(u32))) { err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
err = -EFAULT; if (err)
break; break;
}
if (opt) if (opt)
set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags); set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
......
...@@ -824,7 +824,7 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -824,7 +824,7 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
sockptr_t optval, unsigned int optlen) sockptr_t optval, unsigned int optlen)
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
int len, err = 0; int err = 0;
struct bt_voice voice; struct bt_voice voice;
u32 opt; u32 opt;
struct bt_codecs *codecs; struct bt_codecs *codecs;
...@@ -843,10 +843,9 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -843,10 +843,9 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
break; break;
} }
if (copy_from_sockptr(&opt, optval, sizeof(u32))) { err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
err = -EFAULT; if (err)
break; break;
}
if (opt) if (opt)
set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags); set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
...@@ -863,11 +862,10 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -863,11 +862,10 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
voice.setting = sco_pi(sk)->setting; voice.setting = sco_pi(sk)->setting;
len = min_t(unsigned int, sizeof(voice), optlen); err = bt_copy_from_sockptr(&voice, sizeof(voice), optval,
if (copy_from_sockptr(&voice, optval, len)) { optlen);
err = -EFAULT; if (err)
break; break;
}
/* Explicitly check for these values */ /* Explicitly check for these values */
if (voice.setting != BT_VOICE_TRANSPARENT && if (voice.setting != BT_VOICE_TRANSPARENT &&
...@@ -890,10 +888,9 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -890,10 +888,9 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
break; break;
case BT_PKT_STATUS: case BT_PKT_STATUS:
if (copy_from_sockptr(&opt, optval, sizeof(u32))) { err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
err = -EFAULT; if (err)
break; break;
}
if (opt) if (opt)
set_bit(BT_SK_PKT_STATUS, &bt_sk(sk)->flags); set_bit(BT_SK_PKT_STATUS, &bt_sk(sk)->flags);
...@@ -934,9 +931,9 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, ...@@ -934,9 +931,9 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
break; break;
} }
if (copy_from_sockptr(buffer, optval, optlen)) { err = bt_copy_from_sockptr(buffer, optlen, optval, optlen);
if (err) {
hci_dev_put(hdev); hci_dev_put(hdev);
err = -EFAULT;
break; break;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment