[SRU][F][PATCH 4/5] Bluetooth: L2CAP: Fix not validating setsockopt user input
Koichiro Den
koichiro.den at canonical.com
Mon Oct 28 07:58:59 UTC 2024
From: Luiz Augusto von Dentz <luiz.von.dentz at intel.com>
[ Upstream commit 4f3951242ace5efc7131932e2e01e6ac6baed846 ]
Check user input length before copying data.
Fixes: 33575df7be67 ("Bluetooth: move l2cap_sock_setsockopt() to l2cap_sock.c")
Fixes: 3ee7b7cd8390 ("Bluetooth: Add BT_MODE socket option")
Signed-off-by: Eric Dumazet <edumazet at google.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz at intel.com>
Signed-off-by: Sasha Levin <sashal at kernel.org>
(backported from commit 9d42f373391211c7c8af66a3a316533a32b8a607 linux-6.1.y)
[koichiroden: Use bt_copy_from_user instead of bt_copy_from_sockptr,
which was introduced in the preceding backport commit
"Bluetooth: SCO: Fix not validating setsockopt user input".
Also, dropped changes on BT_MODE case due to missing commit:
3ee7b7cd8390 ("Bluetooth: Add BT_MODE socket option")]
CVE-2024-35965
Signed-off-by: Koichiro Den <koichiro.den at canonical.com>
---
net/bluetooth/l2cap_sock.c | 47 +++++++++++++++-----------------------
1 file changed, 18 insertions(+), 29 deletions(-)
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 633a3bcf1ab6..338b72bd8b83 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -658,7 +658,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
struct sock *sk = sock->sk;
struct l2cap_chan *chan = l2cap_pi(sk)->chan;
struct l2cap_options opts;
- int len, err = 0;
+ int err = 0;
u32 opt;
BT_DBG("sk %p", sk);
@@ -685,11 +685,9 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
opts.max_tx = chan->max_tx;
opts.txwin_size = chan->tx_win;
- len = min_t(unsigned int, sizeof(opts), optlen);
- if (copy_from_user((char *) &opts, optval, len)) {
- err = -EFAULT;
+ err = bt_copy_from_user(&opts, sizeof(opts), optval, optlen);
+ if (err)
break;
- }
if (opts.txwin_size > L2CAP_DEFAULT_EXT_WINDOW) {
err = -EINVAL;
@@ -729,10 +727,9 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
break;
case L2CAP_LM:
- if (get_user(opt, (u32 __user *) optval)) {
- err = -EFAULT;
+ err = bt_copy_from_user(&opt, sizeof(opt), optval, optlen);
+ if (err)
break;
- }
if (opt & L2CAP_LM_FIPS) {
err = -EINVAL;
@@ -774,7 +771,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
struct bt_security sec;
struct bt_power pwr;
struct l2cap_conn *conn;
- int len, err = 0;
+ int err = 0;
u32 opt;
u16 mtu;
@@ -799,11 +796,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
sec.level = BT_SECURITY_LOW;
- len = min_t(unsigned int, sizeof(sec), optlen);
- if (copy_from_user((char *) &sec, optval, len)) {
- err = -EFAULT;
+ err = bt_copy_from_user(&sec, sizeof(sec), optval, optlen);
+ if (err)
break;
- }
if (sec.level < BT_SECURITY_LOW ||
sec.level > BT_SECURITY_FIPS) {
@@ -848,10 +843,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
break;
}
- if (get_user(opt, (u32 __user *) optval)) {
- err = -EFAULT;
+ err = bt_copy_from_user(&opt, sizeof(opt), optval, optlen);
+ if (err)
break;
- }
if (opt) {
set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
@@ -863,10 +857,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
break;
case BT_FLUSHABLE:
- if (get_user(opt, (u32 __user *) optval)) {
- err = -EFAULT;
+ err = bt_copy_from_user(&opt, sizeof(opt), optval, optlen);
+ if (err)
break;
- }
if (opt > BT_FLUSHABLE_ON) {
err = -EINVAL;
@@ -898,11 +891,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
pwr.force_active = BT_POWER_FORCE_ACTIVE_ON;
- len = min_t(unsigned int, sizeof(pwr), optlen);
- if (copy_from_user((char *) &pwr, optval, len)) {
- err = -EFAULT;
+ err = bt_copy_from_user(&pwr, sizeof(pwr), optval, optlen);
+ if (err)
break;
- }
if (pwr.force_active)
set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
@@ -911,10 +902,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
break;
case BT_CHANNEL_POLICY:
- if (get_user(opt, (u32 __user *) optval)) {
- err = -EFAULT;
+ err = bt_copy_from_user(&opt, sizeof(opt), optval, optlen);
+ if (err)
break;
- }
if (opt > BT_CHANNEL_POLICY_AMP_PREFERRED) {
err = -EINVAL;
@@ -958,10 +948,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
break;
}
- if (get_user(mtu, (u16 __user *) optval)) {
- err = -EFAULT;
+ err = bt_copy_from_user(&mtu, sizeof(mtu), optval, optlen);
+ if (err)
break;
- }
chan->imtu = mtu;
break;
--
2.43.0
More information about the kernel-team
mailing list