]>
Commit | Line | Data |
---|---|---|
e1a39be2 SL |
1 | From 98af6b2539047fae9d30882da3ec133502604204 Mon Sep 17 00:00:00 2001 |
2 | From: Sasha Levin <sashal@kernel.org> | |
3 | Date: Fri, 5 Apr 2024 15:41:52 -0400 | |
4 | Subject: Bluetooth: SCO: Fix not validating setsockopt user input | |
5 | ||
6 | From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> | |
7 | ||
8 | [ Upstream commit 51eda36d33e43201e7a4fd35232e069b2c850b01 ] | |
9 | ||
10 | syzbot reported sco_sock_setsockopt() is copying data without | |
11 | checking user input length. | |
12 | ||
13 | BUG: KASAN: slab-out-of-bounds in copy_from_sockptr_offset | |
14 | include/linux/sockptr.h:49 [inline] | |
15 | BUG: KASAN: slab-out-of-bounds in copy_from_sockptr | |
16 | include/linux/sockptr.h:55 [inline] | |
17 | BUG: KASAN: slab-out-of-bounds in sco_sock_setsockopt+0xc0b/0xf90 | |
18 | net/bluetooth/sco.c:893 | |
19 | Read of size 4 at addr ffff88805f7b15a3 by task syz-executor.5/12578 | |
20 | ||
21 | Fixes: ad10b1a48754 ("Bluetooth: Add Bluetooth socket voice option") | |
22 | Fixes: b96e9c671b05 ("Bluetooth: Add BT_DEFER_SETUP option to sco socket") | |
23 | Fixes: 00398e1d5183 ("Bluetooth: Add support for BT_PKT_STATUS CMSG data for SCO connections") | |
24 | Fixes: f6873401a608 ("Bluetooth: Allow setting of codec for HFP offload use case") | |
25 | Reported-by: syzbot <syzkaller@googlegroups.com> | |
26 | Signed-off-by: Eric Dumazet <edumazet@google.com> | |
27 | Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> | |
28 | Signed-off-by: Sasha Levin <sashal@kernel.org> | |
29 | --- | |
30 | include/net/bluetooth/bluetooth.h | 9 +++++++++ | |
31 | net/bluetooth/sco.c | 23 ++++++++++------------- | |
32 | 2 files changed, 19 insertions(+), 13 deletions(-) | |
33 | ||
34 | diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h | |
35 | index bcc5a4cd2c17b..5aaf7d7f3c6fa 100644 | |
36 | --- a/include/net/bluetooth/bluetooth.h | |
37 | +++ b/include/net/bluetooth/bluetooth.h | |
38 | @@ -565,6 +565,15 @@ static inline struct sk_buff *bt_skb_sendmmsg(struct sock *sk, | |
39 | return skb; | |
40 | } | |
41 | ||
42 | +static inline int bt_copy_from_sockptr(void *dst, size_t dst_size, | |
43 | + sockptr_t src, size_t src_size) | |
44 | +{ | |
45 | + if (dst_size > src_size) | |
46 | + return -EINVAL; | |
47 | + | |
48 | + return copy_from_sockptr(dst, src, dst_size); | |
49 | +} | |
50 | + | |
51 | int bt_to_errno(u16 code); | |
52 | __u8 bt_status(int err); | |
53 | ||
54 | diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c | |
55 | index 6d4168cfeb563..2e9137c539a49 100644 | |
56 | --- a/net/bluetooth/sco.c | |
57 | +++ b/net/bluetooth/sco.c | |
58 | @@ -831,7 +831,7 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, | |
59 | sockptr_t optval, unsigned int optlen) | |
60 | { | |
61 | struct sock *sk = sock->sk; | |
62 | - int len, err = 0; | |
63 | + int err = 0; | |
64 | struct bt_voice voice; | |
65 | u32 opt; | |
66 | struct bt_codecs *codecs; | |
67 | @@ -850,10 +850,9 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, | |
68 | break; | |
69 | } | |
70 | ||
71 | - if (copy_from_sockptr(&opt, optval, sizeof(u32))) { | |
72 | - err = -EFAULT; | |
73 | + err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen); | |
74 | + if (err) | |
75 | break; | |
76 | - } | |
77 | ||
78 | if (opt) | |
79 | set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags); | |
80 | @@ -870,11 +869,10 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, | |
81 | ||
82 | voice.setting = sco_pi(sk)->setting; | |
83 | ||
84 | - len = min_t(unsigned int, sizeof(voice), optlen); | |
85 | - if (copy_from_sockptr(&voice, optval, len)) { | |
86 | - err = -EFAULT; | |
87 | + err = bt_copy_from_sockptr(&voice, sizeof(voice), optval, | |
88 | + optlen); | |
89 | + if (err) | |
90 | break; | |
91 | - } | |
92 | ||
93 | /* Explicitly check for these values */ | |
94 | if (voice.setting != BT_VOICE_TRANSPARENT && | |
95 | @@ -897,10 +895,9 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, | |
96 | break; | |
97 | ||
98 | case BT_PKT_STATUS: | |
99 | - if (copy_from_sockptr(&opt, optval, sizeof(u32))) { | |
100 | - err = -EFAULT; | |
101 | + err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen); | |
102 | + if (err) | |
103 | break; | |
104 | - } | |
105 | ||
106 | if (opt) | |
107 | sco_pi(sk)->cmsg_mask |= SCO_CMSG_PKT_STATUS; | |
108 | @@ -941,9 +938,9 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, | |
109 | break; | |
110 | } | |
111 | ||
112 | - if (copy_from_sockptr(buffer, optval, optlen)) { | |
113 | + err = bt_copy_from_sockptr(buffer, optlen, optval, optlen); | |
114 | + if (err) { | |
115 | hci_dev_put(hdev); | |
116 | - err = -EFAULT; | |
117 | break; | |
118 | } | |
119 | ||
120 | -- | |
121 | 2.43.0 | |
122 |