Bluetooth: Fix validating LE PSM values
LE PSM values have different ranges than those for BR/EDR. The valid ranges for fixed, SIG assigned values is 0x0001-0x007f and for dynamic PSM values 0x0080-0x00ff. We need to ensure that bind() and connect() calls conform to these ranges when operating on LE CoC sockets. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
This commit is contained in:
Родитель
e77af75592
Коммит
4946096d43
|
@ -1861,6 +1861,18 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
|
|||
return c1;
|
||||
}
|
||||
|
||||
static bool is_valid_psm(u16 psm, u8 dst_type)
|
||||
{
|
||||
if (!psm)
|
||||
return false;
|
||||
|
||||
if (bdaddr_type_is_le(dst_type))
|
||||
return (psm < 0x00ff);
|
||||
|
||||
/* PSM must be odd and lsb of upper byte must be 0 */
|
||||
return ((psm & 0x0101) == 0x0001);
|
||||
}
|
||||
|
||||
int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
|
||||
bdaddr_t *dst, u8 dst_type)
|
||||
{
|
||||
|
@ -1881,8 +1893,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
|
|||
|
||||
l2cap_chan_lock(chan);
|
||||
|
||||
/* PSM must be odd and lsb of upper byte must be 0 */
|
||||
if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid &&
|
||||
if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid &&
|
||||
chan->chan_type != L2CAP_CHAN_RAW) {
|
||||
err = -EINVAL;
|
||||
goto done;
|
||||
|
|
|
@ -53,6 +53,32 @@ bool l2cap_is_socket(struct socket *sock)
|
|||
}
|
||||
EXPORT_SYMBOL(l2cap_is_socket);
|
||||
|
||||
static int l2cap_validate_bredr_psm(u16 psm)
|
||||
{
|
||||
/* PSM must be odd and lsb of upper byte must be 0 */
|
||||
if ((psm & 0x0101) != 0x0001)
|
||||
return -EINVAL;
|
||||
|
||||
/* Restrict usage of well-known PSMs */
|
||||
if (psm < 0x1001 && !capable(CAP_NET_BIND_SERVICE))
|
||||
return -EACCES;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l2cap_validate_le_psm(u16 psm)
|
||||
{
|
||||
/* Valid LE_PSM ranges are defined only until 0x00ff */
|
||||
if (psm > 0x00ff)
|
||||
return -EINVAL;
|
||||
|
||||
/* Restrict fixed, SIG assigned PSM values to CAP_NET_BIND_SERVICE */
|
||||
if (psm <= 0x007f && !capable(CAP_NET_BIND_SERVICE))
|
||||
return -EACCES;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
|
||||
{
|
||||
struct sock *sk = sock->sk;
|
||||
|
@ -94,17 +120,13 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
|
|||
if (la.l2_psm) {
|
||||
__u16 psm = __le16_to_cpu(la.l2_psm);
|
||||
|
||||
/* PSM must be odd and lsb of upper byte must be 0 */
|
||||
if ((psm & 0x0101) != 0x0001) {
|
||||
err = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
if (la.l2_bdaddr_type == BDADDR_BREDR)
|
||||
err = l2cap_validate_bredr_psm(psm);
|
||||
else
|
||||
err = l2cap_validate_le_psm(psm);
|
||||
|
||||
/* Restrict usage of well-known PSMs */
|
||||
if (psm < 0x1001 && !capable(CAP_NET_BIND_SERVICE)) {
|
||||
err = -EACCES;
|
||||
if (err)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (la.l2_cid)
|
||||
|
|
Загрузка…
Ссылка в новой задаче