| From 84b7ddd1da7548f70f370167829509a08d6b2778 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Fri, 5 Apr 2024 15:56:50 -0400 |
| Subject: Bluetooth: ISO: Fix not validating setsockopt user input |
| |
| From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> |
| |
| [ Upstream commit 9e8742cdfc4b0e65266bb4a901a19462bda9285e ] |
| |
| Check user input length before copying data. |
| |
| Fixes: ccf74f2390d6 ("Bluetooth: Add BTPROTO_ISO socket type") |
| Fixes: 0731c5ab4d51 ("Bluetooth: ISO: Add support for BT_PKT_STATUS") |
| Fixes: f764a6c2c1e4 ("Bluetooth: ISO: Add broadcast support") |
| Signed-off-by: Eric Dumazet <edumazet@google.com> |
| Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| net/bluetooth/iso.c | 36 ++++++++++++------------------------ |
| 1 file changed, 12 insertions(+), 24 deletions(-) |
| |
| diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c |
| index 3681e3673654a..a8b05baa8e5a9 100644 |
| --- a/net/bluetooth/iso.c |
| +++ b/net/bluetooth/iso.c |
| @@ -1479,7 +1479,7 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname, |
| sockptr_t optval, unsigned int optlen) |
| { |
| struct sock *sk = sock->sk; |
| - int len, err = 0; |
| + int err = 0; |
| struct bt_iso_qos qos = default_qos; |
| u32 opt; |
| |
| @@ -1494,10 +1494,9 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname, |
| break; |
| } |
| |
| - if (copy_from_sockptr(&opt, optval, sizeof(u32))) { |
| - err = -EFAULT; |
| + err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen); |
| + if (err) |
| break; |
| - } |
| |
| if (opt) |
| set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags); |
| @@ -1506,10 +1505,9 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname, |
| break; |
| |
| case BT_PKT_STATUS: |
| - if (copy_from_sockptr(&opt, optval, sizeof(u32))) { |
| - err = -EFAULT; |
| + err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen); |
| + if (err) |
| break; |
| - } |
| |
| if (opt) |
| set_bit(BT_SK_PKT_STATUS, &bt_sk(sk)->flags); |
| @@ -1524,17 +1522,9 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname, |
| break; |
| } |
| |
| - len = min_t(unsigned int, sizeof(qos), optlen); |
| - |
| - if (copy_from_sockptr(&qos, optval, len)) { |
| - err = -EFAULT; |
| - break; |
| - } |
| - |
| - if (len == sizeof(qos.ucast) && !check_ucast_qos(&qos)) { |
| - err = -EINVAL; |
| + err = bt_copy_from_sockptr(&qos, sizeof(qos), optval, optlen); |
| + if (err) |
| break; |
| - } |
| |
| iso_pi(sk)->qos = qos; |
| iso_pi(sk)->qos_user_set = true; |
| @@ -1549,18 +1539,16 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname, |
| } |
| |
| if (optlen > sizeof(iso_pi(sk)->base)) { |
| - err = -EOVERFLOW; |
| + err = -EINVAL; |
| break; |
| } |
| |
| - len = min_t(unsigned int, sizeof(iso_pi(sk)->base), optlen); |
| - |
| - if (copy_from_sockptr(iso_pi(sk)->base, optval, len)) { |
| - err = -EFAULT; |
| + err = bt_copy_from_sockptr(iso_pi(sk)->base, optlen, optval, |
| + optlen); |
| + if (err) |
| break; |
| - } |
| |
| - iso_pi(sk)->base_len = len; |
| + iso_pi(sk)->base_len = optlen; |
| |
| break; |
| |
| -- |
| 2.43.0 |
| |