Skip to content

Commit 3e643e4

Browse files
mmhalVudentz
authored andcommitted
Bluetooth: Improve setsockopt() handling of malformed user input
The bt_copy_from_sockptr() return value is being misinterpreted by most users: a non-zero result is mistakenly assumed to represent an error code, but actually indicates the number of bytes that could not be copied. Remove bt_copy_from_sockptr() and adapt callers to use copy_safe_from_sockptr(). For sco_sock_setsockopt() (case BT_CODEC) use copy_struct_from_sockptr() to scrub parts of uninitialized buffer. Opportunistically, rename `len` to `optlen` in hci_sock_setsockopt_old() and hci_sock_setsockopt(). Fixes: 51eda36 ("Bluetooth: SCO: Fix not validating setsockopt user input") Fixes: a97de7b ("Bluetooth: RFCOMM: Fix not validating setsockopt user input") Fixes: 4f39512 ("Bluetooth: L2CAP: Fix not validating setsockopt user input") Fixes: 9e8742c ("Bluetooth: ISO: Fix not validating setsockopt user input") Fixes: b218606 ("Bluetooth: hci_sock: Fix not validating setsockopt user input") Reviewed-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Reviewed-by: David Wei <dw@davidwei.uk> Signed-off-by: Michal Luczaj <mhal@rbox.co> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
1 parent 3dd002f commit 3e643e4

File tree

6 files changed

+33
-40
lines changed

6 files changed

+33
-40
lines changed

include/net/bluetooth/bluetooth.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -590,15 +590,6 @@ static inline struct sk_buff *bt_skb_sendmmsg(struct sock *sk,
590590
return skb;
591591
}
592592

593-
static inline int bt_copy_from_sockptr(void *dst, size_t dst_size,
594-
sockptr_t src, size_t src_size)
595-
{
596-
if (dst_size > src_size)
597-
return -EINVAL;
598-
599-
return copy_from_sockptr(dst, src, dst_size);
600-
}
601-
602593
int bt_to_errno(u16 code);
603594
__u8 bt_status(int err);
604595

net/bluetooth/hci_sock.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1926,7 +1926,7 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg,
19261926
}
19271927

19281928
static int hci_sock_setsockopt_old(struct socket *sock, int level, int optname,
1929-
sockptr_t optval, unsigned int len)
1929+
sockptr_t optval, unsigned int optlen)
19301930
{
19311931
struct hci_ufilter uf = { .opcode = 0 };
19321932
struct sock *sk = sock->sk;
@@ -1943,7 +1943,7 @@ static int hci_sock_setsockopt_old(struct socket *sock, int level, int optname,
19431943

19441944
switch (optname) {
19451945
case HCI_DATA_DIR:
1946-
err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, len);
1946+
err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
19471947
if (err)
19481948
break;
19491949

@@ -1954,7 +1954,7 @@ static int hci_sock_setsockopt_old(struct socket *sock, int level, int optname,
19541954
break;
19551955

19561956
case HCI_TIME_STAMP:
1957-
err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, len);
1957+
err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
19581958
if (err)
19591959
break;
19601960

@@ -1974,7 +1974,7 @@ static int hci_sock_setsockopt_old(struct socket *sock, int level, int optname,
19741974
uf.event_mask[1] = *((u32 *) f->event_mask + 1);
19751975
}
19761976

1977-
err = bt_copy_from_sockptr(&uf, sizeof(uf), optval, len);
1977+
err = copy_safe_from_sockptr(&uf, sizeof(uf), optval, optlen);
19781978
if (err)
19791979
break;
19801980

@@ -2005,7 +2005,7 @@ static int hci_sock_setsockopt_old(struct socket *sock, int level, int optname,
20052005
}
20062006

20072007
static int hci_sock_setsockopt(struct socket *sock, int level, int optname,
2008-
sockptr_t optval, unsigned int len)
2008+
sockptr_t optval, unsigned int optlen)
20092009
{
20102010
struct sock *sk = sock->sk;
20112011
int err = 0;
@@ -2015,7 +2015,7 @@ static int hci_sock_setsockopt(struct socket *sock, int level, int optname,
20152015

20162016
if (level == SOL_HCI)
20172017
return hci_sock_setsockopt_old(sock, level, optname, optval,
2018-
len);
2018+
optlen);
20192019

20202020
if (level != SOL_BLUETOOTH)
20212021
return -ENOPROTOOPT;
@@ -2035,7 +2035,7 @@ static int hci_sock_setsockopt(struct socket *sock, int level, int optname,
20352035
goto done;
20362036
}
20372037

2038-
err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, len);
2038+
err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
20392039
if (err)
20402040
break;
20412041

net/bluetooth/iso.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1566,7 +1566,7 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
15661566
break;
15671567
}
15681568

1569-
err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
1569+
err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
15701570
if (err)
15711571
break;
15721572

@@ -1577,7 +1577,7 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
15771577
break;
15781578

15791579
case BT_PKT_STATUS:
1580-
err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
1580+
err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
15811581
if (err)
15821582
break;
15831583

@@ -1596,7 +1596,7 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
15961596
break;
15971597
}
15981598

1599-
err = bt_copy_from_sockptr(&qos, sizeof(qos), optval, optlen);
1599+
err = copy_safe_from_sockptr(&qos, sizeof(qos), optval, optlen);
16001600
if (err)
16011601
break;
16021602

@@ -1617,8 +1617,8 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
16171617
break;
16181618
}
16191619

1620-
err = bt_copy_from_sockptr(iso_pi(sk)->base, optlen, optval,
1621-
optlen);
1620+
err = copy_safe_from_sockptr(iso_pi(sk)->base, optlen, optval,
1621+
optlen);
16221622
if (err)
16231623
break;
16241624

net/bluetooth/l2cap_sock.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -755,7 +755,8 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
755755
opts.max_tx = chan->max_tx;
756756
opts.txwin_size = chan->tx_win;
757757

758-
err = bt_copy_from_sockptr(&opts, sizeof(opts), optval, optlen);
758+
err = copy_safe_from_sockptr(&opts, sizeof(opts), optval,
759+
optlen);
759760
if (err)
760761
break;
761762

@@ -800,7 +801,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
800801
break;
801802

802803
case L2CAP_LM:
803-
err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
804+
err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
804805
if (err)
805806
break;
806807

@@ -909,7 +910,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
909910

910911
sec.level = BT_SECURITY_LOW;
911912

912-
err = bt_copy_from_sockptr(&sec, sizeof(sec), optval, optlen);
913+
err = copy_safe_from_sockptr(&sec, sizeof(sec), optval, optlen);
913914
if (err)
914915
break;
915916

@@ -956,7 +957,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
956957
break;
957958
}
958959

959-
err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
960+
err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
960961
if (err)
961962
break;
962963

@@ -970,7 +971,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
970971
break;
971972

972973
case BT_FLUSHABLE:
973-
err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
974+
err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
974975
if (err)
975976
break;
976977

@@ -1004,7 +1005,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
10041005

10051006
pwr.force_active = BT_POWER_FORCE_ACTIVE_ON;
10061007

1007-
err = bt_copy_from_sockptr(&pwr, sizeof(pwr), optval, optlen);
1008+
err = copy_safe_from_sockptr(&pwr, sizeof(pwr), optval, optlen);
10081009
if (err)
10091010
break;
10101011

@@ -1015,7 +1016,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
10151016
break;
10161017

10171018
case BT_CHANNEL_POLICY:
1018-
err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
1019+
err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
10191020
if (err)
10201021
break;
10211022

@@ -1046,7 +1047,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
10461047
break;
10471048
}
10481049

1049-
err = bt_copy_from_sockptr(&mtu, sizeof(mtu), optval, optlen);
1050+
err = copy_safe_from_sockptr(&mtu, sizeof(mtu), optval, optlen);
10501051
if (err)
10511052
break;
10521053

@@ -1076,7 +1077,8 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
10761077
break;
10771078
}
10781079

1079-
err = bt_copy_from_sockptr(&mode, sizeof(mode), optval, optlen);
1080+
err = copy_safe_from_sockptr(&mode, sizeof(mode), optval,
1081+
optlen);
10801082
if (err)
10811083
break;
10821084

net/bluetooth/rfcomm/sock.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -629,10 +629,9 @@ static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname,
629629

630630
switch (optname) {
631631
case RFCOMM_LM:
632-
if (bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen)) {
633-
err = -EFAULT;
632+
err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
633+
if (err)
634634
break;
635-
}
636635

637636
if (opt & RFCOMM_LM_FIPS) {
638637
err = -EINVAL;
@@ -685,7 +684,7 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname,
685684

686685
sec.level = BT_SECURITY_LOW;
687686

688-
err = bt_copy_from_sockptr(&sec, sizeof(sec), optval, optlen);
687+
err = copy_safe_from_sockptr(&sec, sizeof(sec), optval, optlen);
689688
if (err)
690689
break;
691690

@@ -703,7 +702,7 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname,
703702
break;
704703
}
705704

706-
err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
705+
err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
707706
if (err)
708707
break;
709708

net/bluetooth/sco.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -896,7 +896,7 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
896896
break;
897897
}
898898

899-
err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
899+
err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
900900
if (err)
901901
break;
902902

@@ -915,8 +915,8 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
915915

916916
voice.setting = sco_pi(sk)->setting;
917917

918-
err = bt_copy_from_sockptr(&voice, sizeof(voice), optval,
919-
optlen);
918+
err = copy_safe_from_sockptr(&voice, sizeof(voice), optval,
919+
optlen);
920920
if (err)
921921
break;
922922

@@ -941,7 +941,7 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
941941
break;
942942

943943
case BT_PKT_STATUS:
944-
err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
944+
err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
945945
if (err)
946946
break;
947947

@@ -984,7 +984,8 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
984984
break;
985985
}
986986

987-
err = bt_copy_from_sockptr(buffer, optlen, optval, optlen);
987+
err = copy_struct_from_sockptr(buffer, sizeof(buffer), optval,
988+
optlen);
988989
if (err) {
989990
hci_dev_put(hdev);
990991
break;

0 commit comments

Comments
 (0)